#include "EventManager.hpp" #include #include #include #include #include #include #include #include #include #include "events/types.hpp" #include "events/audio/AudioEvent.hpp" #include "events/info/InfoEvent.hpp" #include "events/pong/PongEvent.hpp" #include "events/search/SearchEvent.hpp" #include "packets/base/GenericPacket.hpp" #include "tasks/client/ClientTask.hpp" #include "tasks/server/ServerTask.hpp" #include "tasks/undefined/UndefinedTask.hpp" EventManager::EventManager() { // register the different events type this->eventRegistry = { {drp::event::EventType::PONG, std::make_shared()}, {drp::event::EventType::SEARCH, std::make_shared()}, {drp::event::EventType::INFO, std::make_shared()}, {drp::event::EventType::AUDIO, std::make_shared()}, }; // register the different tasks type this->taskRegistry = { {drp::task::TaskType::UNDEFINED, std::make_shared()}, {drp::task::TaskType::CLIENT, std::make_shared()}, {drp::task::TaskType::SERVER, std::make_shared()}, }; // hints for the communication addrinfo addressHints {}; addressHints.ai_family = AF_INET; // TODO: AF_INET6 addressHints.ai_socktype = SOCK_DGRAM; addressHints.ai_protocol = IPPROTO_UDP; // create the client socket this->context.socket = socket( addressHints.ai_family, addressHints.ai_socktype, addressHints.ai_protocol ); if (this->context.socket < 0) throw std::runtime_error("[Receiver] Could not create the socket: " + std::string(strerror(errno))); // get the information for the broadcast local-link address // TODO(Faraphel): ip / port as argument ? if(const int error = getaddrinfo( "0.0.0.0", // TODO: ff02::1 "5650", &addressHints, &context.broadcastAddressInfo ) != 0) throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error))); // define the time of the latest discovery this->context.latestPeerDiscovery = std::chrono::high_resolution_clock::now(); } void EventManager::loop() { // run an event receiver and sender this->senderThread = std::thread(&EventManager::loopSender, this); this->receiverThread = std::thread(&EventManager::loopReceiver, this); this->senderThread.join(); this->receiverThread.join(); freeaddrinfo(this->context.broadcastAddressInfo); } void EventManager::loopSender() { addrinfo* destinationInfo; addrinfo addressHints {}; addressHints.ai_family = AF_INET; // TODO: AF_INET6 addressHints.ai_socktype = SOCK_DGRAM; addressHints.ai_protocol = IPPROTO_UDP; // get the information for the broadcast local-link address // TODO(Faraphel): ip / port as argument ? if(const int error = getaddrinfo( "localhost", // TODO: ff02::1 "5650", &addressHints, &destinationInfo ) != 0) throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error))); while (true) { std::cout << "[Sender] Status: " + std::to_string(static_cast(this->context.me.status)) << std::endl; // get the corresponding task class std::shared_ptr task; try { task = this->taskRegistry.at(this->context.me.status); } catch (const std::out_of_range& exception) { std::cerr << "Unsupported status." << std::endl; continue; } // ask the task class to handle the task task->handle(this->context); } // free the address freeaddrinfo(destinationInfo); } void EventManager::loopReceiver() { // prepare space for the sender address sockaddr_storage fromAddress {}; socklen_t fromAddressLength = sizeof(fromAddress); drp::packet::GenericPacket packet {}; drp::packet::GenericPacketContent packetContent {}; addrinfo addressHints {}; addressHints.ai_family = AF_INET; // TODO: AF_INET6 addressHints.ai_socktype = SOCK_DGRAM; addressHints.ai_protocol = IPPROTO_UDP; // TODO(Faraphel): port as argument addrinfo* senderInfo; if(getaddrinfo( nullptr, // hostname "5650", // port &addressHints, &senderInfo ) != 0) throw std::runtime_error("[Receiver] Could not get the address: " + std::string(gai_strerror(errno))); // bind the socket to the address if (bind( this->context.socket, senderInfo->ai_addr, senderInfo->ai_addrlen ) < 0) throw std::runtime_error("[Receiver] Could not bind to the address: " + std::string(strerror(errno))); // free the sender address freeaddrinfo(senderInfo); // client loop while (true) { // receive new data const ssize_t size = recvfrom( this->context.socket, &packet, sizeof(packet), 0, reinterpret_cast(&fromAddress), &fromAddressLength ); if (size == -1) throw std::runtime_error("[Receiver] Could not receive the packet: " + std::string(strerror(errno))); // if the packet channel is neither 0 (all) nor the current one, ignore it if (packet.channel != 0 && packet.channel != this->context.me.channel) continue; // decrypt the packet packetContent = packet.getContent(); // get the corresponding event class std::shared_ptr event; try { event = this->eventRegistry.at(static_cast(packetContent.eventType)); } catch (const std::out_of_range& exception) { std::cerr << "Unsupported event type." << std::endl; continue; } // ask the event class to handle the event event->handle( this->context, packetContent, reinterpret_cast(&fromAddress), fromAddressLength ); } }