#include "Manager.hpp" #include #include #include #include #include #include #include #include #include #include "behavior/events/audio/AudioEvent.hpp" #include "behavior/tasks/server/ServerTask.hpp" #include "utils/crypto/aes/AesKey.hpp" #include "utils/crypto/rsa/RsaKeyPair.hpp" namespace drp::managers { Manager::Manager(const std::string& address, const std::string& port, const bool useIpv6) { std::cout << "Broadcast address: " << address << ":" << port << " (" << (useIpv6 ? "IPv6" : "IPv4") << ")" << std::endl; // hints for the communication addrinfo broadcastAddressHints {}; broadcastAddressHints.ai_family = useIpv6 ? AF_INET6 : AF_INET; broadcastAddressHints.ai_socktype = SOCK_DGRAM; broadcastAddressHints.ai_protocol = IPPROTO_UDP; // create the client socket const int sock = socket( broadcastAddressHints.ai_family, broadcastAddressHints.ai_socktype, broadcastAddressHints.ai_protocol ); if (sock < 0) throw std::runtime_error("Could not create the socket: " + std::string(strerror(errno))); // allow IPv6 multicast loopback so that we can receive our own messages. constexpr int socketLoopback = 1; if (setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &socketLoopback, sizeof(socketLoopback) ) < 0) { std::cerr << "Failed to set IPV6_MULTICAST_LOOP: " << strerror(errno) << std::endl; } // get the information for the broadcast local-link address addrinfo* broadcastAddressInfo = nullptr; if (const int error = getaddrinfo( address.c_str(), port.c_str(), &broadcastAddressHints, &broadcastAddressInfo ) != 0) throw std::runtime_error("Could not get the broadcast address: " + std::string(gai_strerror(error))); // hints for the bind address addrinfo anyAddressHints {}; anyAddressHints.ai_family = useIpv6 ? AF_INET6 : AF_INET; anyAddressHints.ai_flags = AI_PASSIVE; anyAddressHints.ai_socktype = SOCK_DGRAM; anyAddressHints.ai_protocol = IPPROTO_UDP; // get the information for the broadcast local-link address addrinfo *anyAddressInfo; if (const int error = getaddrinfo( nullptr, port.c_str(), &anyAddressHints, &anyAddressInfo ) != 0) throw std::runtime_error("Could not get the any address: " + std::string(gai_strerror(error))); // bind the socket to the address if (bind( sock, anyAddressInfo->ai_addr, anyAddressInfo->ai_addrlen ) < 0) throw std::runtime_error("Could not bind to the address: " + std::string(strerror(errno))); // create the context this->context = std::make_shared(sock, broadcastAddressInfo); // TODO(Faraphel): should only be enabled if it can really emit sound. this->context->me.serverEnabled = true; // create the sub-managers. this->sendManager = std::make_unique(context); this->receiveManager = std::make_unique(context); } Manager::~Manager() { freeaddrinfo(this->context->broadcastAddressInfo); } void Manager::loop() { // run an event receiver and sender std::thread senderThread(&SendManager::loop, this->sendManager.get()); std::thread receiverThread(&ReceiveManager::loop, this->receiveManager.get()); senderThread.join(); receiverThread.join(); } }