improved StatList behavior
This commit is contained in:
parent
1c5442c267
commit
bea5704282
10 changed files with 63 additions and 90 deletions
|
@ -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
12
Dockerfile
Normal 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"]
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "CacheMap.hpp"
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue