From 05142cbb1fd01f2dfbf1f768e2f133eae33f485a Mon Sep 17 00:00:00 2001 From: study-faraphel Date: Sun, 10 Nov 2024 19:26:21 +0100 Subject: [PATCH] fixed IPv6 mode not being able to receive response --- source/EventManager.cpp | 30 ++++++++++++++++++++---- source/events/info/InfoEvent.cpp | 3 +++ source/events/search/SearchEvent.cpp | 12 ++++++++-- source/tasks/undefined/UndefinedTask.cpp | 15 ++++++++++-- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/source/EventManager.cpp b/source/EventManager.cpp index 2c5066d..9d57779 100644 --- a/source/EventManager.cpp +++ b/source/EventManager.cpp @@ -44,7 +44,6 @@ EventManager::EventManager(const std::string& address, const std::string& port, // hints for the communication addrinfo addressHints {}; addressHints.ai_family = useIpv6 ? AF_INET6 : AF_INET; - // addressHints.ai_flags = AI_PASSIVE; addressHints.ai_socktype = SOCK_DGRAM; addressHints.ai_protocol = IPPROTO_UDP; @@ -58,21 +57,42 @@ EventManager::EventManager(const std::string& address, const std::string& port, if (this->context.socket < 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. + int socketLoopback = 1; + if (setsockopt( + context.socket, + 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 - // TODO(Faraphel): ip / port as argument ? if(const int error = getaddrinfo( address.c_str(), port.c_str(), &addressHints, &context.broadcastAddressInfo ) != 0) - throw std::runtime_error("Could not get the address: " + std::string(gai_strerror(error))); + throw std::runtime_error("Could not get the broadcast address: " + std::string(gai_strerror(error))); + + // get the information for the broadcast local-link address + addrinfo *anyAddressInfo; + if(const int error = getaddrinfo( + nullptr, + port.c_str(), + &addressHints, + &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( this->context.socket, - this->context.broadcastAddressInfo->ai_addr, - this->context.broadcastAddressInfo->ai_addrlen + anyAddressInfo->ai_addr, + anyAddressInfo->ai_addrlen ) < 0) throw std::runtime_error("Could not bind to the address: " + std::string(strerror(errno))); diff --git a/source/events/info/InfoEvent.cpp b/source/events/info/InfoEvent.cpp index 7d81183..f1a117e 100644 --- a/source/events/info/InfoEvent.cpp +++ b/source/events/info/InfoEvent.cpp @@ -1,6 +1,7 @@ #include "InfoEvent.hpp" #include +#include #include @@ -13,6 +14,8 @@ void InfoEvent::handle( const sockaddr_storage& fromAddress, const socklen_t fromAddressLength ) { + std::cout << "Received peer information." << std::endl; + // get the peer information Peer peer; std::memcpy(&peer, content.data.data(), sizeof(Peer)); diff --git a/source/events/search/SearchEvent.cpp b/source/events/search/SearchEvent.cpp index 359dbed..9006f5d 100644 --- a/source/events/search/SearchEvent.cpp +++ b/source/events/search/SearchEvent.cpp @@ -33,7 +33,7 @@ void event::SearchEvent::handle( // TODO(Faraphel): send back the timestamp too - // broadcast our information + // send back our information if (sendto( context.socket, &packet, @@ -46,7 +46,15 @@ void event::SearchEvent::handle( return; } - std::cout << "[Receiver] Sent information." << std::endl; + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + getnameinfo( + reinterpret_cast(&fromAddress), fromAddressLength, + hoststr, sizeof(hoststr), + portstr, sizeof(portstr), + NI_NUMERICHOST | NI_NUMERICSERV + ); + std::cout << "[Receiver] Sent back information to " << hoststr << ":" << portstr << std::endl; } diff --git a/source/tasks/undefined/UndefinedTask.cpp b/source/tasks/undefined/UndefinedTask.cpp index 5325b4d..dd4df41 100644 --- a/source/tasks/undefined/UndefinedTask.cpp +++ b/source/tasks/undefined/UndefinedTask.cpp @@ -19,6 +19,13 @@ namespace drp::task { void UndefinedTask::handle(Context& context) { + std::cout << "List of peers: " << std::endl; + for (const auto& peer : context.remotePeers) + std::cout << + "\tPeer(id=" << peer.second->information.id << ", " << + "status=" << std::to_string(static_cast(peer.second->information.status)) << ")" << + std::endl; + // search if a server is available among the peer. const auto& server = std::ranges::find_if( context.remotePeers, @@ -38,6 +45,8 @@ void UndefinedTask::handle(Context& context) { std::chrono::high_resolution_clock::now() - context.latestPeerDiscovery > std::chrono::milliseconds(5000) ) { + std::cout << "No more peers discovered." << std::endl; + // otherwise, become the server if we have the highest ID. // TODO(Faraphel): should use the machine with the lowest average ping if (context.me.serverEnabled) { @@ -54,7 +63,7 @@ void UndefinedTask::handle(Context& context) { // check if we are this peer if (context.me.id == serverCandidate->first) { - std::cout << "becoming server..." << std::endl; + std::cout << "Becoming server..." << std::endl; // set ourselves as the server context.server = serverCandidate->second; context.me.status = TaskType::SERVER; @@ -62,7 +71,7 @@ void UndefinedTask::handle(Context& context) { } } - // TODO(Faraphel): sleep 1s + std::this_thread::sleep_for(std::chrono::seconds(1)); } // prepare a search message @@ -79,6 +88,8 @@ void UndefinedTask::handle(Context& context) { std::memcpy(&packetContent.data, &packetData, sizeof(packetData)); packet.setContent(packetContent); + std::cout << "Looking for new peers." << std::endl; + // send the search message if (sendto( context.socket,