90 lines
2.1 KiB
C++
90 lines
2.1 KiB
C++
#include "ydi_server.h"
|
|
#include <core/templates/vector.h>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <stop_token>
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <unordered_set>
|
|
#include <zmq.hpp>
|
|
#include <zmq_addon.hpp>
|
|
|
|
namespace ydi::server {
|
|
struct Service {
|
|
std::optional<zmq::context_t> context{ std::nullopt };
|
|
std::optional<zmq::socket_t> socket{ std::nullopt };
|
|
std::unordered_set<ClueID> revealedClues{};
|
|
std::recursive_mutex mtx{};
|
|
std::atomic<bool> stop_threads{ false };
|
|
std::optional<std::string> client{ std::nullopt };
|
|
};
|
|
|
|
std::optional<Service> service{ std::nullopt };
|
|
thread_local std::optional<std::thread> receiveThread{ std::nullopt };
|
|
thread_local std::optional<std::thread> pingThread{ std::nullopt };
|
|
|
|
void receive_thread_entry() {
|
|
using namespace std::chrono_literals;
|
|
zmq::multipart_t incoming{};
|
|
while (service->stop_threads) {
|
|
std::this_thread::sleep_for(20ms);
|
|
std::scoped_lock lock{ service->mtx };
|
|
if (incoming.recv(*service->socket)) {
|
|
}
|
|
}
|
|
}
|
|
|
|
void ping_thread_entry() {
|
|
using namespace std::chrono_literals;
|
|
{ std::scoped_lock lock{ service->mtx };
|
|
if (!service->client) {
|
|
return;
|
|
}
|
|
}
|
|
static zmq::multipart_t ping{ make_multipart(*service->client, std::string("PING")) };
|
|
while (!service->stop_threads) {
|
|
std::this_thread::sleep_for(1s);
|
|
std::scoped_lock lock{ service->mtx };
|
|
ping.send(*service->socket);
|
|
}
|
|
}
|
|
|
|
void open() {
|
|
service.emplace();
|
|
try {
|
|
service->context.emplace(1);
|
|
} catch (...) {
|
|
service.reset();
|
|
return;
|
|
}
|
|
try {
|
|
service->socket.emplace(*service->context, zmq::socket_type::router);
|
|
} catch (...) {
|
|
service->context->close();
|
|
service->context.reset();
|
|
service.reset();
|
|
return;
|
|
}
|
|
try {
|
|
service->socket->connect("tcp://*:6667");
|
|
} catch (...) {
|
|
service->socket->close();
|
|
service->socket.reset();
|
|
service->context->close();
|
|
service->context.reset();
|
|
service.reset();
|
|
}
|
|
receiveThread.emplace(receive_thread_entry);
|
|
}
|
|
|
|
void close() {
|
|
if (service) {
|
|
std::scoped_lock lock{ service->mtx };
|
|
service->socket->close();
|
|
service->socket.reset();
|
|
service->context->close();
|
|
service->context.reset();
|
|
service.reset();
|
|
}
|
|
}
|
|
}
|