improved StatList behavior

This commit is contained in:
study-faraphel 2024-11-08 00:14:39 +01:00
parent 1c5442c267
commit bea5704282
10 changed files with 63 additions and 90 deletions

View file

@ -23,8 +23,6 @@ add_executable(M2-PT-DRP
source/events/types.hpp source/events/types.hpp
source/packets/base/GenericPacket.cpp source/packets/base/GenericPacket.cpp
source/RemotePeer.hpp source/RemotePeer.hpp
source/utils/StatList.cpp
source/utils/StatList.hpp
source/events/base/BaseEvent.hpp source/events/base/BaseEvent.hpp
source/events/base/BaseEvent.hpp source/events/base/BaseEvent.hpp
source/events/audio/AudioPacketsComparator.cpp source/events/audio/AudioPacketsComparator.cpp
@ -46,7 +44,6 @@ add_executable(M2-PT-DRP
source/tasks/client/ClientTask.cpp source/tasks/client/ClientTask.cpp
source/tasks/client/ClientTask.hpp source/tasks/client/ClientTask.hpp
source/Context.hpp source/Context.hpp
source/utils/CacheMap.cpp
source/utils/CacheMap.hpp source/utils/CacheMap.hpp
source/packets/search/SearchPacketData.hpp source/packets/search/SearchPacketData.hpp
) )

12
Dockerfile Normal file
View file

@ -0,0 +1,12 @@
FROM alpine:latest
RUN apk add gcc g++ cmake ninja
RUN apk add mpg123-dev openssl-dev portaudio-dev
WORKDIR /app
COPY . /app
RUN cmake -S . -B build -G Ninja
RUN cmake --build build
CMD ["build/M2-PT-DRP"]

View file

@ -1,18 +1,18 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <map>
#include <netdb.h> #include <netdb.h>
#include "RemotePeer.hpp" #include "RemotePeer.hpp"
#include "utils/StatList.hpp"
struct Context { struct Context {
int socket = -1; int socket = -1;
addrinfo* broadcastAddressInfo = nullptr; addrinfo* broadcastAddressInfo = nullptr;
drp::util::StatList<std::shared_ptr<RemotePeer>> remotePeers {};
std::shared_ptr<RemotePeer> server = nullptr; std::shared_ptr<RemotePeer> server = nullptr;
Peer me; Peer me;
std::map<sockaddr, std::shared_ptr<RemotePeer>> remotePeers {};
std::chrono::high_resolution_clock::time_point latestPeerDiscovery;
}; };

View file

@ -56,13 +56,15 @@ EventManager::EventManager() {
// get the information for the broadcast local-link address // get the information for the broadcast local-link address
// TODO(Faraphel): ip / port as argument ? // TODO(Faraphel): ip / port as argument ?
if(const int error = getaddrinfo( if(const int error = getaddrinfo(
"localhost", // TODO: ff02::1 "0.0.0.0", // TODO: ff02::1
"5650", "5650",
&addressHints, &addressHints,
&context.broadcastAddressInfo &context.broadcastAddressInfo
) != 0) ) != 0)
throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error))); throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error)));
// define the time of the latest discovery
this->context.latestPeerDiscovery = std::chrono::high_resolution_clock::now();
} }
@ -96,8 +98,9 @@ void EventManager::loopSender() {
) != 0) ) != 0)
throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error))); throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error)));
while (true) { while (true) {
std::cout << "[Sender] Status: " + std::to_string(static_cast<int>(this->context.me.status)) << std::endl;
// get the corresponding task class // get the corresponding task class
std::shared_ptr<drp::task::BaseTask> task; std::shared_ptr<drp::task::BaseTask> task;
try { try {

View file

@ -13,20 +13,29 @@ void InfoEvent::handle(
sockaddr* fromAddress, sockaddr* fromAddress,
const socklen_t fromAddressLength const socklen_t fromAddressLength
) { ) {
const auto remotePeer = std::make_shared<RemotePeer>(); // check if the peer address is already in the map
std::shared_ptr<RemotePeer> remotePeer;
auto iterator = context.remotePeers.find(*fromAddress);
// TODO(Faraphel): first check if the peer is already in the list if (iterator == context.remotePeers.end()) {
// do not update the time of the list if yes ! // if not found, create a new peer
remotePeer = std::make_shared<RemotePeer>();
remotePeer->address = *fromAddress;
remotePeer->addressLength = fromAddressLength;
// update the latest discovery time
context.latestPeerDiscovery = std::chrono::high_resolution_clock::now();
} else {
// get the peer
remotePeer = iterator->second;
}
// save the remote peer information // save the remote peer information
remotePeer->address = *reinterpret_cast<sockaddr*>(&fromAddress);
remotePeer->addressLength = fromAddressLength;
std::memcpy(&remotePeer->information, &content, sizeof(Peer)); std::memcpy(&remotePeer->information, &content, sizeof(Peer));
// TODO(Faraphel): interpret the timestamp and calculate average ping // TODO(Faraphel): interpret the timestamp and calculate average ping
// save it in the peers list // save it in the peers list
context.remotePeers.push_back(remotePeer); context.remotePeers[remotePeer->address] = remotePeer;
} }

View file

@ -41,8 +41,10 @@ void event::SearchEvent::handle(
0, 0,
fromAddress, fromAddress,
fromAddressLength fromAddressLength
) == -1) ) == -1) {
std::cerr << "[Receiver] Could not send information: " << strerror(errno) << std::endl; std::cerr << "[Receiver] Could not send information: " << strerror(errno) << std::endl;
return;
}
std::cout << "[Receiver] Sent information." << std::endl; std::cout << "[Receiver] Sent information." << std::endl;
} }

View file

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <thread>
#include <sys/socket.h> #include <sys/socket.h>
#include "../../Context.hpp" #include "../../Context.hpp"
@ -23,10 +24,11 @@ void UndefinedTask::handle(Context& context) {
// check if no more peers have been found. // check if no more peers have been found.
if ( if (
std::chrono::high_resolution_clock::now() - context.remotePeers.getModificationTime() > std::chrono::high_resolution_clock::now() - context.latestPeerDiscovery >
std::chrono::milliseconds(5000) std::chrono::milliseconds(5000)
) { ) {
// verify if there are peers // verify if there are peers
// TODO(Faraphel): the map is never empty since there is a least the local client
if (context.remotePeers.empty()) { if (context.remotePeers.empty()) {
// if we are alone in the network // if we are alone in the network
@ -40,25 +42,38 @@ void UndefinedTask::handle(Context& context) {
return; return;
} }
// search for a server among the peers // look for a server among the peers
const auto& server = std::find_if( const auto& server = std::ranges::find_if(
context.remotePeers.begin(), context.remotePeers,
context.remotePeers.end(), [&](const auto& peer) { return peer.second->information.status == TaskType::SERVER; }
[&](const std::shared_ptr<Peer>& peer) { return peer->status == TaskType::SERVER; }
); );
if (server != context.remotePeers.end()) { if (server != context.remotePeers.end()) {
// if a server have been found, use it // if a server have been found, use it
context.server = *server; context.server = server->second;
context.me.status = TaskType::CLIENT; context.me.status = TaskType::CLIENT;
return; return;
} }
// TODO(Faraphel): check if we have the lowest average ping out of all the peers. If yes, become the server. // TODO(Faraphel): check if we have the lowest average ping out of all the peers. If yes, become the server.
// Others peers will connect to us on their next loop. // Others peers will connect to us on their next loop.
// TODO(Faraphel): use a unique ID instead ?
if (!context.me.serverEnabled) if (!context.me.serverEnabled)
return; return;
... // check we have the lowest latency out of all the peers
if (std::all_of(
context.remotePeers.begin(),
context.remotePeers.end(),
[&](const auto& peer) {
return peer.second->information.latencyAverage > context.me.latencyAverage;
}
)) {
// set ourselves as the server
context.server = nullptr;
context.me.status = TaskType::SERVER;
return;
}
} }
// prepare a search message // prepare a search message
@ -85,6 +100,8 @@ void UndefinedTask::handle(Context& context) {
context.broadcastAddressInfo->ai_addrlen context.broadcastAddressInfo->ai_addrlen
) == -1) ) == -1)
std::cerr << "[Sender] Could not send search event: " << strerror(errno) << std::endl; std::cerr << "[Sender] Could not send search event: " << strerror(errno) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
} }

View file

@ -1 +0,0 @@
#include "CacheMap.hpp"

View file

@ -1,36 +0,0 @@
#include "StatList.hpp"
namespace drp::util {
template<class T>
StatList<T>::StatList() {
this->updateModificationTime();
}
template<class T>
void StatList<T>::push_back(const T &value) {
std::list<T>::push_back(value);
this->updateModificationTime();
}
template<class T>
void StatList<T>::pop_back() {
std::list<T>::pop_back();
this->updateModificationTime();
}
template<class T>
std::chrono::time_point<std::chrono::high_resolution_clock> StatList<T>::getModificationTime() const {
return this->modificationTime;
}
template<class T>
void StatList<T>::updateModificationTime() {
this->modificationTime = std::chrono::high_resolution_clock::now();
}
}

View file

@ -1,30 +0,0 @@
#pragma once
#include <chrono>
#include <list>
namespace drp::util {
/**
* A simple list with additional stat data, such as the date of the latest modification
* @tparam Value the type of elements in the list
*/
template<class Value>
class StatList : public std::list<Value> {
public:
StatList();
void push_back(const Value& value);
void pop_back();
[[nodiscard]] std::chrono::time_point<std::chrono::high_resolution_clock> getModificationTime() const;
private:
void updateModificationTime();
std::chrono::time_point<std::chrono::high_resolution_clock> modificationTime;
};
}