2020-12-02 09:00:11 +00:00
|
|
|
#include "CNShardServer.hpp"
|
|
|
|
#include "PlayerManager.hpp"
|
|
|
|
#include "CNStructs.hpp"
|
|
|
|
#include "Monitor.hpp"
|
2020-12-02 22:42:33 +00:00
|
|
|
#include "settings.hpp"
|
2020-12-02 09:00:11 +00:00
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
static int listener;
|
|
|
|
static std::mutex sockLock; // guards socket list
|
|
|
|
static std::list<int> sockets;
|
|
|
|
static sockaddr_in address;
|
|
|
|
|
|
|
|
// runs during init
|
|
|
|
void Monitor::init() {
|
|
|
|
listener = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (listener < 0) {
|
|
|
|
perror("socket");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int opt = 1;
|
|
|
|
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
|
|
|
perror("setsockopt");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
address.sin_family = AF_INET;
|
|
|
|
address.sin_addr.s_addr = INADDR_ANY;
|
2020-12-02 22:42:33 +00:00
|
|
|
address.sin_port = htons(settings::MONITORPORT);
|
2020-12-02 09:00:11 +00:00
|
|
|
|
|
|
|
if (bind(listener, (struct sockaddr*)&address, sizeof(address)) < 0) {
|
|
|
|
perror("bind");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listen(listener, SOMAXCONN) < 0) {
|
|
|
|
perror("listen");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2020-12-02 22:42:33 +00:00
|
|
|
std::cout << "[INFO] Monitor listening on *:" << settings::MONITORPORT << std::endl;
|
2020-12-02 09:00:11 +00:00
|
|
|
|
2020-12-02 22:42:33 +00:00
|
|
|
REGISTER_SHARD_TIMER(tick, settings::MONITORINTERVAL);
|
2020-12-02 09:00:11 +00:00
|
|
|
}
|
|
|
|
|
2020-12-02 10:40:34 +00:00
|
|
|
static bool transmit(std::list<int>::iterator& it, char *buff, int len) {
|
2020-12-02 09:00:11 +00:00
|
|
|
int n = 0;
|
|
|
|
int sock = *it;
|
|
|
|
|
|
|
|
while (n < len) {
|
2020-12-02 10:40:34 +00:00
|
|
|
n += write(sock, buff+n, len-n);
|
2020-12-02 09:00:11 +00:00
|
|
|
if (n < 0) {
|
|
|
|
perror("send");
|
|
|
|
close(sock);
|
2020-12-02 10:40:34 +00:00
|
|
|
|
|
|
|
std::cout << "[INFO] Disconnected a monitor" << std::endl;
|
|
|
|
|
2020-12-02 09:00:11 +00:00
|
|
|
it = sockets.erase(it);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// runs in shard thread
|
|
|
|
void Monitor::tick(CNServer *serv, time_t delta) {
|
|
|
|
std::lock_guard<std::mutex> lock(sockLock);
|
|
|
|
char buff[256];
|
|
|
|
|
|
|
|
auto it = sockets.begin();
|
|
|
|
while (it != sockets.end()) {
|
2020-12-02 10:40:34 +00:00
|
|
|
if (!transmit(it, (char*)"begin\n", 6))
|
2020-12-02 09:00:11 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
for (auto& pair : PlayerManager::players) {
|
2020-12-02 10:40:34 +00:00
|
|
|
int n = std::snprintf(buff, sizeof(buff), "player %d %d %s\n",
|
2020-12-02 09:00:11 +00:00
|
|
|
pair.second->x, pair.second->y,
|
|
|
|
PlayerManager::getPlayerName(pair.second, false).c_str());
|
|
|
|
|
2020-12-02 10:40:34 +00:00
|
|
|
if (!transmit(it, buff, n))
|
2020-12-02 09:00:11 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-12-02 10:40:34 +00:00
|
|
|
if (!transmit(it, (char*)"end\n", 4))
|
2020-12-02 09:00:11 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// runs in monitor thread
|
|
|
|
void Monitor::start(void *unused) {
|
|
|
|
socklen_t len = sizeof(address);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
int sock = accept(listener, (struct sockaddr*)&address, &len);
|
|
|
|
if (sock < 0) {
|
|
|
|
perror("accept");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "[INFO] New monitor connection from " << inet_ntoa(address.sin_addr) << std::endl;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(sockLock);
|
|
|
|
|
|
|
|
sockets.push_back(sock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|