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/packets/base/GenericPacket.cpp
|
||||
source/RemotePeer.hpp
|
||||
source/utils/StatList.cpp
|
||||
source/utils/StatList.hpp
|
||||
source/events/base/BaseEvent.hpp
|
||||
source/events/base/BaseEvent.hpp
|
||||
source/events/audio/AudioPacketsComparator.cpp
|
||||
|
@ -46,7 +44,6 @@ add_executable(M2-PT-DRP
|
|||
source/tasks/client/ClientTask.cpp
|
||||
source/tasks/client/ClientTask.hpp
|
||||
source/Context.hpp
|
||||
source/utils/CacheMap.cpp
|
||||
source/utils/CacheMap.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
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "RemotePeer.hpp"
|
||||
#include "utils/StatList.hpp"
|
||||
|
||||
|
||||
struct Context {
|
||||
int socket = -1;
|
||||
addrinfo* broadcastAddressInfo = nullptr;
|
||||
|
||||
drp::util::StatList<std::shared_ptr<RemotePeer>> remotePeers {};
|
||||
std::shared_ptr<RemotePeer> server = nullptr;
|
||||
|
||||
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
|
||||
// TODO(Faraphel): ip / port as argument ?
|
||||
if(const int error = getaddrinfo(
|
||||
"localhost", // TODO: ff02::1
|
||||
"0.0.0.0", // TODO: ff02::1
|
||||
"5650",
|
||||
&addressHints,
|
||||
&context.broadcastAddressInfo
|
||||
) != 0)
|
||||
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)
|
||||
throw std::runtime_error("[Sender] Could not get the address: " + std::string(gai_strerror(error)));
|
||||
|
||||
|
||||
while (true) {
|
||||
std::cout << "[Sender] Status: " + std::to_string(static_cast<int>(this->context.me.status)) << std::endl;
|
||||
|
||||
// get the corresponding task class
|
||||
std::shared_ptr<drp::task::BaseTask> task;
|
||||
try {
|
||||
|
|
|
@ -13,20 +13,29 @@ void InfoEvent::handle(
|
|||
sockaddr* fromAddress,
|
||||
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
|
||||
// do not update the time of the list if yes !
|
||||
if (iterator == context.remotePeers.end()) {
|
||||
// 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
|
||||
remotePeer->address = *reinterpret_cast<sockaddr*>(&fromAddress);
|
||||
remotePeer->addressLength = fromAddressLength;
|
||||
std::memcpy(&remotePeer->information, &content, sizeof(Peer));
|
||||
|
||||
// TODO(Faraphel): interpret the timestamp and calculate average ping
|
||||
|
||||
// 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,
|
||||
fromAddress,
|
||||
fromAddressLength
|
||||
) == -1)
|
||||
) == -1) {
|
||||
std::cerr << "[Receiver] Could not send information: " << strerror(errno) << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "[Receiver] Sent information." << std::endl;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "../../Context.hpp"
|
||||
|
@ -23,10 +24,11 @@ void UndefinedTask::handle(Context& context) {
|
|||
|
||||
// check if no more peers have been found.
|
||||
if (
|
||||
std::chrono::high_resolution_clock::now() - context.remotePeers.getModificationTime() >
|
||||
std::chrono::high_resolution_clock::now() - context.latestPeerDiscovery >
|
||||
std::chrono::milliseconds(5000)
|
||||
) {
|
||||
// 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 we are alone in the network
|
||||
|
||||
|
@ -40,25 +42,38 @@ void UndefinedTask::handle(Context& context) {
|
|||
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; }
|
||||
// look for a server among the peers
|
||||
const auto& server = std::ranges::find_if(
|
||||
context.remotePeers,
|
||||
[&](const auto& peer) { return peer.second->information.status == TaskType::SERVER; }
|
||||
);
|
||||
|
||||
if (server != context.remotePeers.end()) {
|
||||
// if a server have been found, use it
|
||||
context.server = *server;
|
||||
context.server = server->second;
|
||||
context.me.status = TaskType::CLIENT;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
// TODO(Faraphel): use a unique ID instead ?
|
||||
if (!context.me.serverEnabled)
|
||||
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
|
||||
|
@ -85,6 +100,8 @@ void UndefinedTask::handle(Context& context) {
|
|||
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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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