From 92307063fc11a1d1af8413fc2de6c77d04fe2158 Mon Sep 17 00:00:00 2001 From: dongresource Date: Sun, 6 Dec 2020 01:44:37 +0100 Subject: [PATCH] Integrate the monitor's listener socket into the shard's poll() This removes the need for a separate monitor thread. --- src/CNProtocol.cpp | 6 +++++- src/CNProtocol.hpp | 1 + src/CNShardServer.cpp | 8 +++++++ src/CNShardServer.hpp | 1 + src/Monitor.cpp | 50 +++++++++++++++++++++++-------------------- src/Monitor.hpp | 4 ++-- src/main.cpp | 4 ---- 7 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/CNProtocol.cpp b/src/CNProtocol.cpp index fc61ac3..0c7b0ea 100644 --- a/src/CNProtocol.cpp +++ b/src/CNProtocol.cpp @@ -219,7 +219,7 @@ bool setSockNonblocking(SOCKET listener, SOCKET newSock) { unsigned long mode = 1; if (ioctlsocket(newSock, FIONBIO, &mode) != 0) { #else - if (fcntl(newSock, F_SETFL, (fcntl(listener, F_GETFL, 0) | O_NONBLOCK)) != 0) { + if (fcntl(newSock, F_SETFL, (fcntl(newSock, F_GETFL, 0) | O_NONBLOCK)) != 0) { #endif std::cerr << "[WARN] OpenFusion: fcntl failed on new connection" << std::endl; #ifdef _WIN32 @@ -351,6 +351,9 @@ void CNServer::start() { connections[newConnectionSocket] = tmp; newConnection(tmp); + } else if (checkExtraSockets(i)) { + // no-op. handled in checkExtraSockets(). + } else { // player sockets if (connections.find(fds[i].fd) == connections.end()) { @@ -419,6 +422,7 @@ void CNServer::printPacket(CNPacketData *data, int type) { std::cout << "OpenFusion: received " << Defines::p2str(type, data->type) << " (" << data->type << ")" << std::endl; } +bool CNServer::checkExtraSockets(int i) { return false; } // stubbed void CNServer::newConnection(CNSocket* cns) {} // stubbed void CNServer::killConnection(CNSocket* cns) {} // stubbed void CNServer::onStep() {} // stubbed diff --git a/src/CNProtocol.hpp b/src/CNProtocol.hpp index 4300c34..807cb85 100644 --- a/src/CNProtocol.hpp +++ b/src/CNProtocol.hpp @@ -223,6 +223,7 @@ public: void start(); void kill(); static void printPacket(CNPacketData *data, int type); + virtual bool checkExtraSockets(int i); virtual void newConnection(CNSocket* cns); virtual void killConnection(CNSocket* cns); virtual void onStep(); diff --git a/src/CNShardServer.cpp b/src/CNShardServer.cpp index 1bccf24..4f9a2a4 100644 --- a/src/CNShardServer.cpp +++ b/src/CNShardServer.cpp @@ -6,6 +6,7 @@ #include "CNShared.hpp" #include "settings.hpp" #include "Database.hpp" +#include "Monitor.hpp" #include "TableData.hpp" // for flush() #include @@ -21,6 +22,9 @@ CNShardServer::CNShardServer(uint16_t p) { REGISTER_SHARD_TIMER(keepAliveTimer, 4000); REGISTER_SHARD_TIMER(periodicSaveTimer, settings::DBSAVEINTERVAL*1000); init(); + + if (settings::MONITORENABLED) + fds.push_back({Monitor::init(), POLLIN}); } void CNShardServer::handlePacket(CNSocket* sock, CNPacketData* data) { @@ -62,6 +66,10 @@ void CNShardServer::periodicSaveTimer(CNServer* serv, time_t currTime) { std::cout << "[INFO] Done." << std::endl; } +bool CNShardServer::checkExtraSockets(int i) { + return Monitor::acceptConnection(fds[i].fd, fds[i].revents); +} + void CNShardServer::newConnection(CNSocket* cns) { cns->setActiveKey(SOCKETKEY_E); // by default they accept keys encrypted with the default key } diff --git a/src/CNShardServer.hpp b/src/CNShardServer.hpp index c4a5e2d..6e1d3f1 100644 --- a/src/CNShardServer.hpp +++ b/src/CNShardServer.hpp @@ -23,6 +23,7 @@ public: static void _killConnection(CNSocket *cns); + bool checkExtraSockets(int i); void newConnection(CNSocket* cns); void killConnection(CNSocket* cns); void kill(); diff --git a/src/Monitor.cpp b/src/Monitor.cpp index 7ec471a..941fc7a 100644 --- a/src/Monitor.cpp +++ b/src/Monitor.cpp @@ -6,16 +6,12 @@ #include -static int listener; +static SOCKET listener; static std::mutex sockLock; // guards socket list static std::list sockets; static sockaddr_in address; -// runs during init -void Monitor::init() { - if (!settings::MONITORENABLED) - return; - +SOCKET Monitor::init() { listener = socket(AF_INET, SOCK_STREAM, 0); if (SOCKETERROR(listener)) { std::cout << "Failed to create monitor socket" << std::endl; @@ -59,6 +55,8 @@ void Monitor::init() { std::cout << "Monitor listening on *:" << settings::MONITORPORT << std::endl; REGISTER_SHARD_TIMER(tick, settings::MONITORINTERVAL); + + return listener; } static bool transmit(std::list::iterator& it, char *buff, int len) { @@ -86,7 +84,6 @@ static bool transmit(std::list::iterator& it, char *buff, int len) { return true; } -// runs in shard thread void Monitor::tick(CNServer *serv, time_t delta) { std::lock_guard lock(sockLock); char buff[256]; @@ -115,26 +112,33 @@ void Monitor::tick(CNServer *serv, time_t delta) { } } -// runs in monitor thread -void Monitor::start(void *unused) { +bool Monitor::acceptConnection(SOCKET fd, uint16_t revents) { socklen_t len = sizeof(address); if (!settings::MONITORENABLED) - return; + return false; - for (;;) { - int sock = accept(listener, (struct sockaddr*)&address, &len); - if (SOCKETERROR(sock)) - continue; + if (fd != listener) + return false; - setSockNonblocking(listener, sock); - - std::cout << "[INFO] New monitor connection from " << inet_ntoa(address.sin_addr) << std::endl; - - { - std::lock_guard lock(sockLock); - - sockets.push_back(sock); - } + if (revents & ~POLLIN) { + std::cout << "[FATAL] Error on monitor listener?" << std::endl; + terminate(0); } + + int sock = accept(listener, (struct sockaddr*)&address, &len); + if (SOCKETERROR(sock)) + return true; + + setSockNonblocking(listener, sock); + + std::cout << "[INFO] New monitor connection from " << inet_ntoa(address.sin_addr) << std::endl; + + { + std::lock_guard lock(sockLock); + + sockets.push_back(sock); + } + + return true; } diff --git a/src/Monitor.hpp b/src/Monitor.hpp index c654b5a..c168b33 100644 --- a/src/Monitor.hpp +++ b/src/Monitor.hpp @@ -6,7 +6,7 @@ #include namespace Monitor { - void init(); + SOCKET init(); void tick(CNServer *, time_t); - void start(void *); + bool acceptConnection(SOCKET, uint16_t); }; diff --git a/src/main.cpp b/src/main.cpp index ee9220f..df7cd59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,8 +38,6 @@ CNShardServer *shardServer = nullptr; std::thread *shardThread = nullptr; -std::thread *monitorThread = nullptr; - void startShard(CNShardServer* server) { server->start(); } @@ -104,7 +102,6 @@ int main() { TransportManager::init(); BuddyManager::init(); GroupManager::init(); - Monitor::init(); Database::open(); switch (settings::EVENTMODE) { @@ -123,7 +120,6 @@ int main() { shardServer = new CNShardServer(settings::SHARDPORT); shardThread = new std::thread(startShard, (CNShardServer*)shardServer); - monitorThread = new std::thread(Monitor::start, nullptr); loginServer.start();