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

87 lines
2.8 KiB
C++

#include "UndefinedTask.hpp"
#include "../types.hpp"
#include <chrono>
#include <cstring>
#include <iostream>
#include <sys/socket.h>
#include "../../Context.hpp"
#include "../../events/types.hpp"
#include "../../packets/base/GenericPacket.hpp"
namespace drp::task {
void UndefinedTask::handle(Context& context) {
// TODO(Faraphel): If .status is UNDEFINED, look for a server.
// if alone, become a server (if can emit).
// if everyone is UNKNOWN, elect a server (easiest to join / highest mac address, etc...)
// if a server is found, become a client.
// check if no more peers have been found.
if (
std::chrono::high_resolution_clock::now() - context.remotePeers.getModificationTime() >
std::chrono::milliseconds(5000)
) {
// verify if there are peers
if (context.remotePeers.empty()) {
// if we are alone in the network
// check if we are capable of being a server
if (!context.me.serverEnabled)
return;
// set ourselves as the server
context.server = nullptr;
context.me.status = TaskType::SERVER;
return;
}
// search for a server among the peers
const auto& server = std::find_if(
context.remotePeers.begin(),
context.remotePeers.end(),
[&](const std::shared_ptr<Peer>& peer) { return peer->status == TaskType::SERVER; }
);
if (server != context.remotePeers.end()) {
// if a server have been found, use it
context.server = *server;
context.me.status = TaskType::CLIENT;
return;
}
// TODO(Faraphel): elect a server among those capable of emitting.
}
// prepare a search message
packet::GenericPacket packet {};
packet::GenericPacketContent packetContent {};
packet.channel = 0;
packet.securityMode = static_cast<std::uint8_t>(packet::SecurityMode::PLAIN);
packetContent.eventType = static_cast<std::uint8_t>(event::EventType::SEARCH);
// TODO(Faraphel): generate a random broadcast code and put it in the packet.
// when sending the response to this message, include this broadcast code.
// it will allow us to determinate an estimation of the ping of the machine
// will help when electing a server.
// Bonus: when electing a server, define a random value in the constructor to send
// to every election, allowing for distinction of machines
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;
}
}