#include "UndefinedTask.hpp" #include "../types.hpp" #include #include #include #include #include #include #include #include "Context.hpp" #include "behavior/tasks/client/ClientTask.hpp" #include "behavior/tasks/server/ServerTask.hpp" #include "packets/base/Packet.hpp" #include "packets/base/SecurityMode.hpp" #include "packets/search/SearchPacketData.hpp" #include "utils/network/network.hpp" namespace drp::task { void UndefinedTask::use(Context &context) { context.me.status = TaskType::UNDEFINED; context.server = nullptr; context.remotePeers.clear(); } void UndefinedTask::handle(Context& context) { std::cout << "[Task - Undefined] List of peers: " << std::endl; for (const auto& remotePeer : context.remotePeers) std::cout << "\tPeer(id=" << remotePeer->information.id << ", " << "status=" << std::to_string(static_cast(remotePeer->information.status)) << ")" << std::endl; // search if a server is available among the peer. const auto& server = std::ranges::find_if( context.remotePeers, [&](const auto& peer) { return peer->information.status == TaskType::SERVER; } ); // if a server have been found, use it if (server != context.remotePeers.end()) { // go into client mode ClientTask::use(context, *server); return; } // wait that no more new peers are being discovered if ( 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) { // find the remote peer with the highest id that can be a server const std::shared_ptr serverCandidate = *std::ranges::max_element( context.remotePeers, [&](auto& remotePeer1, auto& remotePeer2) { return ( (remotePeer1->information.serverEnabled ? remotePeer1->information.id : 0) < (remotePeer2->information.serverEnabled ? remotePeer2->information.id : 0) ); } ); // check if we are this peer if (util::network::is_localhost(serverCandidate->address, serverCandidate->addressLength)) { std::cout << "[Task - Undefined] Becoming server..." << std::endl; // go into server mode ServerTask::use(context, serverCandidate); return; } } std::this_thread::sleep_for(std::chrono::seconds(1)); } // prepare a search message packet::base::Packet packet {}; packet::base::PacketContent packetContent {}; packet::search::SearchPacketData packetData {}; // broadcast message packet.channel = 0; // search message with the time of the message being sent packetData.timestamp = std::chrono::high_resolution_clock::now(); packetContent.eventType = event::EventType::SEARCH; packetContent.data = packetData.serialize(); packet.setContent(context, packet::base::SecurityMode::PLAIN, packetContent); std::cout << "[Task - Undefined] Looking for new peers." << std::endl; const auto serializedPacket = packet.serialize(); // send the search message if (sendto( context.socket, serializedPacket.data(), serializedPacket.size(), 0, context.broadcastAddressInfo->ai_addr, context.broadcastAddressInfo->ai_addrlen ) == -1) std::cerr << "[Task - Undefined] Could not send search event: " << strerror(errno) << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } }