Support the monitor interface on Windows as well

This change required sacrificing both code cleanliness and the specific
error reports from perror(). Those could have been kept with a portable
wrapper, but that's too much work. We'll do it if unforseen errors
arise.
This commit is contained in:
dongresource 2020-12-04 17:22:54 +01:00
parent 85dcdd4cc5
commit 26024de866
3 changed files with 24 additions and 29 deletions

View File

@ -6,24 +6,26 @@
#include <cstdio> #include <cstdio>
#ifndef _WIN32
static int listener; static int listener;
static std::mutex sockLock; // guards socket list static std::mutex sockLock; // guards socket list
static std::list<int> sockets; static std::list<SOCKET> sockets;
static sockaddr_in address; static sockaddr_in address;
// runs during init // runs during init
void Monitor::init() { void Monitor::init() {
listener = socket(AF_INET, SOCK_STREAM, 0); listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0) { if (SOCKETERROR(listener)) {
perror("socket"); std::cout << "Failed to create monitor socket" << std::endl;
exit(1); exit(1);
} }
#ifdef _WIN32
const char opt = 1;
#else
int opt = 1; int opt = 1;
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { #endif
perror("setsockopt"); if (SOCKETERROR(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))) {
std::cout << "Failed to set SO_REUSEADDR on monitor socket" << std::endl;
exit(1); exit(1);
} }
@ -31,30 +33,35 @@ void Monitor::init() {
address.sin_addr.s_addr = INADDR_ANY; address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(settings::MONITORPORT); address.sin_port = htons(settings::MONITORPORT);
if (bind(listener, (struct sockaddr*)&address, sizeof(address)) < 0) { if (SOCKETERROR(bind(listener, (struct sockaddr*)&address, sizeof(address)))) {
perror("bind"); std::cout << "Failed to bind to monitor port" << std::endl;
exit(1); exit(1);
} }
if (listen(listener, SOMAXCONN) < 0) { if (SOCKETERROR(listen(listener, SOMAXCONN))) {
perror("listen"); std::cout << "Failed to listen on monitor port" << std::endl;
exit(1); exit(1);
} }
std::cout << "[INFO] Monitor listening on *:" << settings::MONITORPORT << std::endl; std::cout << "Monitor listening on *:" << settings::MONITORPORT << std::endl;
REGISTER_SHARD_TIMER(tick, settings::MONITORINTERVAL); REGISTER_SHARD_TIMER(tick, settings::MONITORINTERVAL);
} }
static bool transmit(std::list<int>::iterator& it, char *buff, int len) { static bool transmit(std::list<SOCKET>::iterator& it, char *buff, int len) {
int n = 0; int n = 0;
int sock = *it; int sock = *it;
while (n < len) { while (n < len) {
n += write(sock, buff+n, len-n); n += send(sock, buff+n, len-n, 0);
if (n < 0) { if (SOCKETERROR(n)) {
perror("send"); #ifdef _WIN32
shutdown(sock, SD_BOTH);
closesocket(sock);
#else
shutdown(sock, SHUT_RDWR);
close(sock); close(sock);
#endif
std::cout << "[INFO] Disconnected a monitor" << std::endl; std::cout << "[INFO] Disconnected a monitor" << std::endl;
@ -101,10 +108,8 @@ void Monitor::start(void *unused) {
for (;;) { for (;;) {
int sock = accept(listener, (struct sockaddr*)&address, &len); int sock = accept(listener, (struct sockaddr*)&address, &len);
if (sock < 0) { if (SOCKETERROR(sock))
perror("accept");
continue; continue;
}
std::cout << "[INFO] New monitor connection from " << inet_ntoa(address.sin_addr) << std::endl; std::cout << "[INFO] New monitor connection from " << inet_ntoa(address.sin_addr) << std::endl;
@ -115,5 +120,3 @@ void Monitor::start(void *unused) {
} }
} }
} }
#endif // _WIN32

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#ifndef _WIN32
#include "CNProtocol.hpp" #include "CNProtocol.hpp"
#include <list> #include <list>
@ -12,5 +10,3 @@ namespace Monitor {
void tick(CNServer *, time_t); void tick(CNServer *, time_t);
void start(void *); void start(void *);
}; };
#endif // _WIN32

View File

@ -104,9 +104,7 @@ int main() {
TransportManager::init(); TransportManager::init();
BuddyManager::init(); BuddyManager::init();
GroupManager::init(); GroupManager::init();
#ifndef _WIN32
Monitor::init(); Monitor::init();
#endif
Database::open(); Database::open();
switch (settings::EVENTMODE) { switch (settings::EVENTMODE) {
@ -125,9 +123,7 @@ int main() {
shardServer = new CNShardServer(settings::SHARDPORT); shardServer = new CNShardServer(settings::SHARDPORT);
shardThread = new std::thread(startShard, (CNShardServer*)shardServer); shardThread = new std::thread(startShard, (CNShardServer*)shardServer);
#ifndef _WIN32
monitorThread = new std::thread(Monitor::start, nullptr); monitorThread = new std::thread(Monitor::start, nullptr);
#endif
loginServer.start(); loginServer.start();