M2-PT-DRP/source/tasks/undefined/UndefinedTask.cpp

99 lines
3.3 KiB
C++

#include "UndefinedTask.hpp"
#include "../types.hpp"
#include <chrono>
#include <cstring>
#include <iostream>
#include <numeric>
#include <thread>
#include <bits/ranges_util.h>
#include <pstl/glue_numeric_defs.h>
#include <sys/socket.h>
#include "../../Context.hpp"
#include "../../events/types.hpp"
#include "../../packets/base/GenericPacket.hpp"
#include "../../packets/search/SearchPacketData.hpp"
namespace drp::task {
void UndefinedTask::handle(Context& context) {
// search if a server is available among the peer.
const auto& server = std::ranges::find_if(
context.remotePeers,
[&](const auto& peer) { return peer.second->information.status == TaskType::SERVER; }
);
// if a server have been found, use it
if (server != context.remotePeers.end()) {
// if a server have been found, use it
context.server = server->second;
context.me.status = TaskType::CLIENT;
return;
}
// wait that no more new peers are being discovered
if (
std::chrono::high_resolution_clock::now() - context.latestPeerDiscovery >
std::chrono::milliseconds(5000)
) {
// 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 auto serverCandidate = std::max_element(
context.remotePeers.begin(),
context.remotePeers.end(),
[&](auto& remotePeer1, auto& remotePeer2) {
return (
(remotePeer1.second->information.serverEnabled ? remotePeer1.first : 0) <
(remotePeer2.second->information.serverEnabled ? remotePeer2.first : 0)
);
}
);
// check if we are this peer
if (context.me.id == serverCandidate->first) {
std::cout << "becoming server..." << std::endl;
// set ourselves as the server
context.server = serverCandidate->second;
context.me.status = TaskType::SERVER;
return;
}
}
// TODO(Faraphel): sleep 1s
}
// prepare a search message
packet::GenericPacket packet {};
packet::GenericPacketContent packetContent {};
packet::SearchPacketData packetData {};
// broadcast message
packet.channel = 0;
packet.securityMode = static_cast<std::uint8_t>(packet::SecurityMode::PLAIN);
// search message with the time of the message being sent
packetContent.eventType = static_cast<std::uint8_t>(event::EventType::SEARCH);
packetData.timestamp = std::chrono::high_resolution_clock::now();
std::memcpy(&packetContent.data, &packetData, sizeof(packetData));
packet.setContent(packetContent);
// send the search message
if (sendto(
context.socket,
&packet,
sizeof(packet),
0,
context.broadcastAddressInfo->ai_addr,
context.broadcastAddressInfo->ai_addrlen
) == -1)
std::cerr << "[Sender] Could not send search event: " << strerror(errno) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}