improved messages and structure of the program

This commit is contained in:
study-faraphel 2024-11-11 13:39:13 +01:00
parent 454e86a982
commit 3c044249f4
31 changed files with 91 additions and 77 deletions

Binary file not shown.

View file

@ -7,15 +7,20 @@
#include "RemotePeer.hpp" #include "RemotePeer.hpp"
struct Context { /**
int socket = -1; * Information about the current state of our machine.
addrinfo* broadcastAddressInfo = nullptr; * Used everywhere to determinate how to behave.
std::shared_ptr<RemotePeer> server = nullptr; */
class Context {
public:
int socket = -1; /// current socket file descriptor, used to communicate
addrinfo* broadcastAddressInfo = nullptr; /// address used to broadcast messages
std::shared_ptr<RemotePeer> server = nullptr; /// peer currently used as the server
Peer me; Peer me; /// information about our own machine
std::map< std::map<
std::uint32_t, std::uint32_t,
std::shared_ptr<RemotePeer> std::shared_ptr<RemotePeer>
> remotePeers {}; > remotePeers {}; /// information about other machines
std::chrono::high_resolution_clock::time_point latestPeerDiscovery; std::chrono::high_resolution_clock::time_point latestPeerDiscovery; /// time of the latest discovered machine
}; };

View file

@ -1,4 +1,4 @@
#include "EventManager.hpp" #include "Manager.hpp"
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -11,20 +11,19 @@
#include <random> #include <random>
#include <sys/socket.h> #include <sys/socket.h>
#include "events/types.hpp" #include "behavior/events/types.hpp"
#include "events/audio/AudioEvent.hpp" #include "behavior/events/audio/AudioEvent.hpp"
#include "events/info/InfoEvent.hpp" #include "behavior/events/info/InfoEvent.hpp"
#include "events/pong/PongEvent.hpp" #include "behavior/events/pong/PongEvent.hpp"
#include "events/search/SearchEvent.hpp" #include "behavior/events/search/SearchEvent.hpp"
#include "packets/base/Packet.hpp" #include "packets/base/Packet.hpp"
#include "tasks/client/ClientTask.hpp" #include "behavior/tasks/client/ClientTask.hpp"
#include "tasks/server/ServerTask.hpp" #include "behavior/tasks/server/ServerTask.hpp"
#include "tasks/undefined/UndefinedTask.hpp" #include "behavior/tasks/undefined/UndefinedTask.hpp"
EventManager::EventManager(const std::string& address, const std::string& port, const bool useIpv6) { Manager::Manager(const std::string& address, const std::string& port, const bool useIpv6) {
std::cout << "address: " << address << " (" << (useIpv6 ? "IPv6" : "IPv4") << ")" << std::endl; std::cout << "Broadcast address: " << address << ":" << port << " (" << (useIpv6 ? "IPv6" : "IPv4") << ")" << std::endl;
std::cout << "port: " << port << std::endl;
// register the different events type // register the different events type
this->eventRegistry = { this->eventRegistry = {
@ -121,10 +120,10 @@ EventManager::EventManager(const std::string& address, const std::string& port,
} }
void EventManager::loop() { void Manager::loop() {
// run an event receiver and sender // run an event receiver and sender
this->senderThread = std::thread(&EventManager::loopSender, this); this->senderThread = std::thread(&Manager::loopSender, this);
this->receiverThread = std::thread(&EventManager::loopReceiver, this); this->receiverThread = std::thread(&Manager::loopReceiver, this);
this->senderThread.join(); this->senderThread.join();
this->receiverThread.join(); this->receiverThread.join();
@ -133,9 +132,9 @@ void EventManager::loop() {
} }
void EventManager::loopSender() { void Manager::loopSender() {
while (true) { while (true) {
std::cout << "[Sender] Status: " + std::to_string(static_cast<int>(this->context.me.status)) << std::endl; std::cout << "[Sender] Handling status: " + std::to_string(static_cast<int>(this->context.me.status)) << std::endl;
// get the corresponding task class // get the corresponding task class
std::shared_ptr<drp::task::BaseTask> task; std::shared_ptr<drp::task::BaseTask> task;
@ -152,7 +151,7 @@ void EventManager::loopSender() {
} }
void EventManager::loopReceiver() { void Manager::loopReceiver() {
// prepare space for the sender address // prepare space for the sender address
sockaddr_storage fromAddress {}; sockaddr_storage fromAddress {};
socklen_t fromAddressLength = sizeof(fromAddress); socklen_t fromAddressLength = sizeof(fromAddress);
@ -185,10 +184,12 @@ void EventManager::loopReceiver() {
try { try {
event = this->eventRegistry.at(static_cast<drp::event::EventType>(packetContent.eventType)); event = this->eventRegistry.at(static_cast<drp::event::EventType>(packetContent.eventType));
} catch (const std::out_of_range& exception) { } catch (const std::out_of_range& exception) {
std::cerr << "Unsupported event type." << std::endl; std::cerr << "[Receiver] Unsupported event type." << std::endl;
continue; continue;
} }
std::cout << "[Receiver] handling event: " << std::to_string(packetContent.eventType) << std::endl;
// ask the event class to handle the event // ask the event class to handle the event
event->handle( event->handle(
this->context, this->context,

View file

@ -5,15 +5,20 @@
#include <thread> #include <thread>
#include "Context.hpp" #include "Context.hpp"
#include "events/types.hpp" #include "behavior/events/types.hpp"
#include "events/base/BaseEvent.hpp" #include "behavior/events/base/BaseEvent.hpp"
#include "tasks/types.hpp" #include "behavior/tasks/types.hpp"
#include "tasks/base/BaseTask.hpp" #include "behavior/tasks/base/BaseTask.hpp"
class EventManager { /**
* The Manager.
* Manage how should the program behave depending on its current state, or the message it receive.
*/
// TODO(Faraphel): could be split in two part.
class Manager {
public: public:
EventManager(const std::string& address, const std::string& port, bool useIpv6 = false); Manager(const std::string& address, const std::string& port, bool useIpv6 = false);
void loop(); void loop();
void loopSender(); void loopSender();

View file

@ -3,7 +3,10 @@
#include <chrono> #include <chrono>
#include <sys/socket.h> #include <sys/socket.h>
#include "tasks/types.hpp" #include "behavior/tasks/types.hpp"
// TODO(Faraphel): should be split in multiple files.
/** /**

View file

@ -3,8 +3,8 @@
#include <iostream> #include <iostream>
#include <bits/unique_lock.h> #include <bits/unique_lock.h>
#include "../../packets/audio/AudioPacketData.hpp" #include "packets/audio/AudioPacketData.hpp"
#include "../../packets/base/PacketData.hpp" #include "packets/base/PacketData.hpp"
namespace drp::event { namespace drp::event {
@ -27,7 +27,7 @@ AudioEvent::~AudioEvent() {
Pa_StopStream(this->stream); Pa_StopStream(this->stream);
// close the audio stream // close the audio stream
if (const PaError error = Pa_CloseStream(this->stream)) if (const PaError error = Pa_CloseStream(this->stream))
std::cerr << "[Client] Could not close the stream: " << std::string(Pa_GetErrorText(error)) << std::endl; std::cerr << "[Event - Audio] Could not close the stream: " << std::string(Pa_GetErrorText(error)) << std::endl;
} }
@ -71,7 +71,7 @@ void AudioEvent::updateAudioStream(const int channels, const std::uint32_t sampl
nullptr, nullptr,
nullptr nullptr
) != paNoError) ) != paNoError)
throw std::runtime_error("[Client] Could not open the stream: " + std::string(Pa_GetErrorText(error))); throw std::runtime_error("[Event - Audio] Could not open the stream: " + std::string(Pa_GetErrorText(error)));
// update the new audio values // update the new audio values
this->streamChannels = channels; this->streamChannels = channels;
@ -101,7 +101,7 @@ void AudioEvent::loopPlay() {
std::this_thread::sleep_until(audioPacket.timePlay); std::this_thread::sleep_until(audioPacket.timePlay);
auto cTimePlay = std::chrono::high_resolution_clock::to_time_t(audioPacket.timePlay); auto cTimePlay = std::chrono::high_resolution_clock::to_time_t(audioPacket.timePlay);
std::cout << "[Client] Playing: " << std::ctime(&cTimePlay) << std::endl; std::cout << "[Event - Audio] Playing: " << std::ctime(&cTimePlay) << std::endl;
// immediately stop playing music // immediately stop playing music
// this avoids an offset created if this client's clock is too ahead of the others // this avoids an offset created if this client's clock is too ahead of the others
@ -110,7 +110,7 @@ void AudioEvent::loopPlay() {
// play the new audio data // play the new audio data
if (const int error = Pa_StartStream(this->stream) != paNoError) if (const int error = Pa_StartStream(this->stream) != paNoError)
throw std::runtime_error("[Client] Could not start the PortAudio stream: " + std::string(Pa_GetErrorText(error))); throw std::runtime_error("[Event - Audio] Could not start the PortAudio stream: " + std::string(Pa_GetErrorText(error)));
// write the new audio data into the audio buffer // write the new audio data into the audio buffer
const int error = Pa_WriteStream( const int error = Pa_WriteStream(
@ -125,10 +125,10 @@ void AudioEvent::loopPlay() {
// the output might be very slightly underflowed, // the output might be very slightly underflowed,
// causing a very small period where no noise will be played. // causing a very small period where no noise will be played.
case paOutputUnderflowed: case paOutputUnderflowed:
std::cerr << "[Client] Underflowed!" << std::endl; break;
default: default:
std::cerr << "[Client] Could not write to the audio stream: " << Pa_GetErrorText(error) << std::endl; std::cerr << "[Event - Audio] Could not write to the audio stream: " << Pa_GetErrorText(error) << std::endl;
} }
// remove the audio chunk // remove the audio chunk

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../../packets/audio/AudioPacketData.hpp" #include "packets/audio/AudioPacketData.hpp"
namespace drp::event { namespace drp::event {

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../../packets/base/Packet.hpp" #include "packets/base/Packet.hpp"
#include "../../Context.hpp" #include "Context.hpp"
namespace drp::event { namespace drp::event {

View file

@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
#include <sys/socket.h> #include <sys/socket.h>
#include "../../packets/info/InfoPacketData.hpp" #include "packets/info/InfoPacketData.hpp"
namespace drp::event { namespace drp::event {
@ -15,7 +15,7 @@ void InfoEvent::handle(
const sockaddr_storage& fromAddress, const sockaddr_storage& fromAddress,
const socklen_t fromAddressLength const socklen_t fromAddressLength
) { ) {
std::cout << "Received peer information." << std::endl; std::cout << "[Event - Info] Received peer information." << std::endl;
// get the peer information // get the peer information
const auto packetData = packet::info::InfoPacketData::fromGeneric(content); const auto packetData = packet::info::InfoPacketData::fromGeneric(content);

View file

@ -12,7 +12,7 @@ void PongEvent::handle(
const sockaddr_storage& fromAddress, const sockaddr_storage& fromAddress,
const socklen_t fromAddressLength const socklen_t fromAddressLength
) { ) {
std::cout << "[Receiver] Pong." << std::endl; std::cout << "[Event - Pong] Pong." << std::endl;
} }

View file

@ -6,8 +6,8 @@
#include <iostream> #include <iostream>
#include <ostream> #include <ostream>
#include "../../packets/base/SecurityMode.hpp" #include "packets/base/SecurityMode.hpp"
#include "../../packets/info/InfoPacketData.hpp" #include "packets/info/InfoPacketData.hpp"
namespace drp { namespace drp {
@ -42,11 +42,11 @@ void event::SearchEvent::handle(
reinterpret_cast<const sockaddr*>(&fromAddress), reinterpret_cast<const sockaddr*>(&fromAddress),
fromAddressLength fromAddressLength
) == -1) { ) == -1) {
std::cerr << "[Receiver] Could not send information: " << strerror(errno) << std::endl; std::cerr << "[Event - Search] Could not send information: " << strerror(errno) << std::endl;
return; return;
} }
std::cout << "[Receiver] Sent back information." << std::endl; std::cout << "[Event - Search] Sent back information." << std::endl;
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../../Context.hpp" #include "Context.hpp"
namespace drp::task { namespace drp::task {

View file

@ -22,7 +22,7 @@ void ClientTask::handle(Context& context) {
// TODO(Faraphel): only once ? // TODO(Faraphel): only once ?
FILE* chronyProcess = popen(("chronyc add server " + std::string(host) + " 2>&1").c_str(), "r"); FILE* chronyProcess = popen(("chronyc add server " + std::string(host) + " 2>&1").c_str(), "r");
if (pclose(chronyProcess) == -1) if (pclose(chronyProcess) == -1)
std::cerr << "Failed to connect to chrony server !" << std::endl; std::cerr << "[Task - Client] Failed to connect to chrony server !" << std::endl;
// TODO(Faraphel): check if the server is still reachable. // TODO(Faraphel): check if the server is still reachable.
// if connection lost, go back to undefined mode. // if connection lost, go back to undefined mode.

View file

@ -10,10 +10,10 @@
#include <thread> #include <thread>
#include <sys/socket.h> #include <sys/socket.h>
#include "../../packets/audio/AudioPacketData.hpp" #include "packets/audio/AudioPacketData.hpp"
#include "../../packets/base/Packet.hpp" #include "packets/base/Packet.hpp"
#include "../../packets/base/SecurityMode.hpp" #include "packets/base/SecurityMode.hpp"
#include "../../utils/audio.hpp" #include "utils/audio.hpp"
namespace drp::task { namespace drp::task {
@ -28,7 +28,7 @@ ServerTask::ServerTask() {
int error; int error;
this->mpgHandle = mpg123_new(nullptr, &error); this->mpgHandle = mpg123_new(nullptr, &error);
if (this->mpgHandle == nullptr) if (this->mpgHandle == nullptr)
throw std::runtime_error("[Server] Could not create a mpg123 handle."); throw std::runtime_error("[Task - Server] Could not create a mpg123 handle.");
// open the mp3 file // open the mp3 file
// TODO(Faraphel): mp3 file as argument // TODO(Faraphel): mp3 file as argument
@ -36,7 +36,7 @@ ServerTask::ServerTask() {
this->mpgHandle, this->mpgHandle,
"./assets/Queen - Another One Bites the Dust.mp3" "./assets/Queen - Another One Bites the Dust.mp3"
) != MPG123_OK) ) != MPG123_OK)
throw std::runtime_error("[Server] Could not open file."); throw std::runtime_error("[Task - Server] Could not open file.");
// get the format of the file // get the format of the file
if (mpg123_getformat( if (mpg123_getformat(
@ -45,7 +45,7 @@ ServerTask::ServerTask() {
&this->channels, &this->channels,
&this->encoding &this->encoding
) != MPG123_OK) ) != MPG123_OK)
throw std::runtime_error("[Server] Could not get the format of the file."); throw std::runtime_error("[Task - Server] Could not get the format of the file.");
} }
ServerTask::~ServerTask() { ServerTask::~ServerTask() {
@ -79,7 +79,7 @@ void ServerTask::handle(Context& context) {
std::size(audioPacket.content), std::size(audioPacket.content),
&done &done
) != MPG123_OK) { ) != MPG123_OK) {
std::cerr << "[Server] Could not read audio data from file." << std::endl; std::cerr << "[Task - Server] Could not read audio data from file." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
return; return;
} }
@ -109,12 +109,12 @@ void ServerTask::handle(Context& context) {
context.broadcastAddressInfo->ai_addr, context.broadcastAddressInfo->ai_addr,
context.broadcastAddressInfo->ai_addrlen context.broadcastAddressInfo->ai_addrlen
) == -1) { ) == -1) {
std::cerr << "[Server] Could not send audio packet: " << strerror(errno) << std::endl; std::cerr << "[Task - Server] Could not send audio packet: " << strerror(errno) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
return; return;
} }
std::cout << "[Server] Sent: " << done << " bytes" << std::endl; std::cout << "[Task - Server] Sent: " << done << " bytes" << std::endl;
// wait for the duration of the audio chunk // wait for the duration of the audio chunk
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<std::uint64_t>( std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<std::uint64_t>(

View file

@ -9,17 +9,17 @@
#include <algorithm> #include <algorithm>
#include <sys/socket.h> #include <sys/socket.h>
#include "../../Context.hpp" #include "Context.hpp"
#include "../../packets/base/Packet.hpp" #include "packets/base/Packet.hpp"
#include "../../packets/base/SecurityMode.hpp" #include "packets/base/SecurityMode.hpp"
#include "../../packets/search/SearchPacketData.hpp" #include "packets/search/SearchPacketData.hpp"
namespace drp::task { namespace drp::task {
void UndefinedTask::handle(Context& context) { void UndefinedTask::handle(Context& context) {
std::cout << "List of peers: " << std::endl; std::cout << "[Task - Undefined] List of peers: " << std::endl;
for (const auto& peer : context.remotePeers) for (const auto& peer : context.remotePeers)
std::cout << std::cout <<
"\tPeer(id=" << peer.second->information.id << ", " << "\tPeer(id=" << peer.second->information.id << ", " <<
@ -63,7 +63,7 @@ void UndefinedTask::handle(Context& context) {
// check if we are this peer // check if we are this peer
if (context.me.id == serverCandidate->first) { if (context.me.id == serverCandidate->first) {
std::cout << "Becoming server..." << std::endl; std::cout << "[Task - Undefined] Becoming server..." << std::endl;
// set ourselves as the server // set ourselves as the server
context.server = serverCandidate->second; context.server = serverCandidate->second;
context.me.status = TaskType::SERVER; context.me.status = TaskType::SERVER;
@ -87,7 +87,7 @@ void UndefinedTask::handle(Context& context) {
packet.setContent(packetData.toGeneric()); packet.setContent(packetData.toGeneric());
std::cout << "Looking for new peers." << std::endl; std::cout << "[Task - Undefined] Looking for new peers." << std::endl;
// send the search message // send the search message
if (sendto( if (sendto(
@ -98,7 +98,7 @@ void UndefinedTask::handle(Context& context) {
context.broadcastAddressInfo->ai_addr, context.broadcastAddressInfo->ai_addr,
context.broadcastAddressInfo->ai_addrlen context.broadcastAddressInfo->ai_addrlen
) == -1) ) == -1)
std::cerr << "[Sender] Could not send search event: " << strerror(errno) << std::endl; std::cerr << "[Task - Undefined] Could not send search event: " << strerror(errno) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
} }

View file

@ -2,7 +2,7 @@
#include <portaudio.h> #include <portaudio.h>
#include <stdexcept> #include <stdexcept>
#include "argparse/argparse.hpp" #include "argparse/argparse.hpp"
#include "EventManager.hpp" #include "Manager.hpp"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
@ -26,7 +26,7 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
auto eventManager = EventManager( auto eventManager = Manager(
parser.get<std::string>("--host"), parser.get<std::string>("--host"),
parser.get<std::string>("--port"), parser.get<std::string>("--port"),
parser.get<bool>("-6") parser.get<bool>("-6")

View file

@ -3,7 +3,7 @@
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include "../../events/types.hpp" #include "behavior/events/types.hpp"
#include "../base/PacketData.hpp" #include "../base/PacketData.hpp"

View file

@ -3,7 +3,7 @@
#include <cstring> #include <cstring>
#include "PacketContent.hpp" #include "PacketContent.hpp"
#include "../../events/types.hpp" #include "behavior/events/types.hpp"
namespace drp::packet::base { namespace drp::packet::base {

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../../RemotePeer.hpp" #include "RemotePeer.hpp"
#include "../../events/types.hpp" #include "behavior/events/types.hpp"
#include "../base/PacketData.hpp" #include "../base/PacketData.hpp"