From d309df4ce4d8ad0ed995a8e1c4267412a7782021 Mon Sep 17 00:00:00 2001 From: xolatile Date: Mon, 4 Aug 2025 22:53:42 +0200 Subject: Bunch of small changes... --- src/engine/master.cpp | 1040 ++++++++++++++++++++++++------------------------- 1 file changed, 520 insertions(+), 520 deletions(-) (limited to 'src/engine/master.cpp') diff --git a/src/engine/master.cpp b/src/engine/master.cpp index 6eb6fe6..2bf1dba 100644 --- a/src/engine/master.cpp +++ b/src/engine/master.cpp @@ -24,24 +24,24 @@ FILE *logfile = NULL; struct userinfo { - char *name; - void *pubkey; + char *name; + void *pubkey; }; hashnameset users; void adduser(char *name, char *pubkey) { - name = newstring(name); - userinfo &u = users[name]; - u.name = name; - u.pubkey = parsepubkey(pubkey); + name = newstring(name); + userinfo &u = users[name]; + u.name = name; + u.pubkey = parsepubkey(pubkey); } COMMAND(adduser, "ss"); void clearusers() { - enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); - users.clear(); + enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); + users.clear(); } COMMAND(clearusers, ""); @@ -49,17 +49,17 @@ vector bans, servbans, gbans; void clearbans() { - bans.shrink(0); - servbans.shrink(0); - gbans.shrink(0); + bans.shrink(0); + servbans.shrink(0); + gbans.shrink(0); } COMMAND(clearbans, ""); void addban(vector &bans, const char *name) { - ipmask ban; - ban.parse(name); - bans.add(ban); + ipmask ban; + ban.parse(name); + bans.add(ban); } ICOMMAND(ban, "s", (char *name), addban(bans, name)); ICOMMAND(servban, "s", (char *name), addban(servbans, name)); @@ -67,73 +67,73 @@ ICOMMAND(gban, "s", (char *name), addban(gbans, name)); bool checkban(vector &bans, enet_uint32 host) { - loopv(bans) if(bans[i].check(host)) return true; - return false; + loopv(bans) if(bans[i].check(host)) return true; + return false; } struct authreq { - enet_uint32 reqtime; - uint id; - void *answer; + enet_uint32 reqtime; + uint id; + void *answer; }; struct gameserver { - ENetAddress address; - string ip; - int port, numpings; - enet_uint32 lastping, lastpong; + ENetAddress address; + string ip; + int port, numpings; + enet_uint32 lastping, lastpong; }; vector gameservers; struct messagebuf { - vector &owner; - vector buf; - int refs; + vector &owner; + vector buf; + int refs; - messagebuf(vector &owner) : owner(owner), refs(0) {} + messagebuf(vector &owner) : owner(owner), refs(0) {} - const char *getbuf() { return buf.getbuf(); } - int length() { return buf.length(); } - void purge(); + const char *getbuf() { return buf.getbuf(); } + int length() { return buf.length(); } + void purge(); - bool equals(const messagebuf &m) const - { - return buf.length() == m.buf.length() && !memcmp(buf.getbuf(), m.buf.getbuf(), buf.length()); - } + bool equals(const messagebuf &m) const + { + return buf.length() == m.buf.length() && !memcmp(buf.getbuf(), m.buf.getbuf(), buf.length()); + } - bool endswith(const messagebuf &m) const - { - return buf.length() >= m.buf.length() && !memcmp(&buf[buf.length() - m.buf.length()], m.buf.getbuf(), m.buf.length()); - } + bool endswith(const messagebuf &m) const + { + return buf.length() >= m.buf.length() && !memcmp(&buf[buf.length() - m.buf.length()], m.buf.getbuf(), m.buf.length()); + } - void concat(const messagebuf &m) - { - if(buf.length() && buf.last() == '\0') buf.pop(); - buf.put(m.buf.getbuf(), m.buf.length()); - } + void concat(const messagebuf &m) + { + if(buf.length() && buf.last() == '\0') buf.pop(); + buf.put(m.buf.getbuf(), m.buf.length()); + } }; vector gameserverlists, gbanlists; bool updateserverlist = true; struct client { - ENetAddress address; - ENetSocket socket; - char input[INPUT_LIMIT]; - messagebuf *message; - vector output; - int inputpos, outputpos; - enet_uint32 connecttime, lastinput; - int servport; - enet_uint32 lastauth; - vector authreqs; - bool shouldpurge; - bool registeredserver; - - client() : message(NULL), inputpos(0), outputpos(0), servport(-1), lastauth(0), shouldpurge(false), registeredserver(false) {} + ENetAddress address; + ENetSocket socket; + char input[INPUT_LIMIT]; + messagebuf *message; + vector output; + int inputpos, outputpos; + enet_uint32 connecttime, lastinput; + int servport; + enet_uint32 lastauth; + vector authreqs; + bool shouldpurge; + bool registeredserver; + + client() : message(NULL), inputpos(0), outputpos(0), servport(-1), lastauth(0), shouldpurge(false), registeredserver(false) {} }; vector clients; @@ -144,567 +144,567 @@ enet_uint32 servtime = 0; void fatal(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(logfile, fmt, args); - fputc('\n', logfile); - va_end(args); - exit(EXIT_FAILURE); + va_list args; + va_start(args, fmt); + vfprintf(logfile, fmt, args); + fputc('\n', logfile); + va_end(args); + exit(EXIT_FAILURE); } void conoutfv(int type, const char *fmt, va_list args) { - vfprintf(logfile, fmt, args); - fputc('\n', logfile); + vfprintf(logfile, fmt, args); + fputc('\n', logfile); } void purgeclient(int n) { - client &c = *clients[n]; - if(c.message) c.message->purge(); - enet_socket_destroy(c.socket); - delete clients[n]; - clients.remove(n); + client &c = *clients[n]; + if(c.message) c.message->purge(); + enet_socket_destroy(c.socket); + delete clients[n]; + clients.remove(n); } void output(client &c, const char *msg, int len = 0) { - if(!len) len = strlen(msg); - c.output.put(msg, len); + if(!len) len = strlen(msg); + c.output.put(msg, len); } void outputf(client &c, const char *fmt, ...) { - string msg; - va_list args; - va_start(args, fmt); - vformatstring(msg, fmt, args); - va_end(args); + string msg; + va_list args; + va_start(args, fmt); + vformatstring(msg, fmt, args); + va_end(args); - output(c, msg); + output(c, msg); } ENetSocket pingsocket = ENET_SOCKET_NULL; bool setuppingsocket(ENetAddress *address) { - if(pingsocket != ENET_SOCKET_NULL) return true; - pingsocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pingsocket == ENET_SOCKET_NULL) return false; - if(address && enet_socket_bind(pingsocket, address) < 0) return false; - enet_socket_set_option(pingsocket, ENET_SOCKOPT_NONBLOCK, 1); - return true; + if(pingsocket != ENET_SOCKET_NULL) return true; + pingsocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); + if(pingsocket == ENET_SOCKET_NULL) return false; + if(address && enet_socket_bind(pingsocket, address) < 0) return false; + enet_socket_set_option(pingsocket, ENET_SOCKOPT_NONBLOCK, 1); + return true; } void setupserver(int port, const char *ip = NULL) { - ENetAddress address; - address.host = ENET_HOST_ANY; - address.port = port; - - if(ip) - { - if(enet_address_set_host(&address, ip)<0) - fatal("failed to resolve server address: %s", ip); - } - serversocket = enet_socket_create(ENET_SOCKET_TYPE_STREAM); - if(serversocket==ENET_SOCKET_NULL || - enet_socket_set_option(serversocket, ENET_SOCKOPT_REUSEADDR, 1) < 0 || - enet_socket_bind(serversocket, &address) < 0 || - enet_socket_listen(serversocket, -1) < 0) - fatal("failed to create server socket"); - if(enet_socket_set_option(serversocket, ENET_SOCKOPT_NONBLOCK, 1)<0) - fatal("failed to make server socket non-blocking"); - if(!setuppingsocket(&address)) - fatal("failed to create ping socket"); - - enet_time_set(0); - - starttime = time(NULL); - char *ct = ctime(&starttime); - if(strchr(ct, '\n')) *strchr(ct, '\n') = '\0'; - conoutf("*** Starting master server on %s %d at %s ***", ip ? ip : "localhost", port, ct); + ENetAddress address; + address.host = ENET_HOST_ANY; + address.port = port; + + if(ip) + { + if(enet_address_set_host(&address, ip)<0) + fatal("failed to resolve server address: %s", ip); + } + serversocket = enet_socket_create(ENET_SOCKET_TYPE_STREAM); + if(serversocket==ENET_SOCKET_NULL || + enet_socket_set_option(serversocket, ENET_SOCKOPT_REUSEADDR, 1) < 0 || + enet_socket_bind(serversocket, &address) < 0 || + enet_socket_listen(serversocket, -1) < 0) + fatal("failed to create server socket"); + if(enet_socket_set_option(serversocket, ENET_SOCKOPT_NONBLOCK, 1)<0) + fatal("failed to make server socket non-blocking"); + if(!setuppingsocket(&address)) + fatal("failed to create ping socket"); + + enet_time_set(0); + + starttime = time(NULL); + char *ct = ctime(&starttime); + if(strchr(ct, '\n')) *strchr(ct, '\n') = '\0'; + conoutf("*** Starting master server on %s %d at %s ***", ip ? ip : "localhost", port, ct); } void genserverlist() { - if(!updateserverlist) return; - while(gameserverlists.length() && gameserverlists.last()->refs<=0) - delete gameserverlists.pop(); - messagebuf *l = new messagebuf(gameserverlists); - loopv(gameservers) - { - gameserver &s = *gameservers[i]; - if(!s.lastpong) continue; - defformatstring(cmd, "addserver %s %d\n", s.ip, s.port); - l->buf.put(cmd, strlen(cmd)); - } - l->buf.add('\0'); - gameserverlists.add(l); - updateserverlist = false; + if(!updateserverlist) return; + while(gameserverlists.length() && gameserverlists.last()->refs<=0) + delete gameserverlists.pop(); + messagebuf *l = new messagebuf(gameserverlists); + loopv(gameservers) + { + gameserver &s = *gameservers[i]; + if(!s.lastpong) continue; + defformatstring(cmd, "addserver %s %d\n", s.ip, s.port); + l->buf.put(cmd, strlen(cmd)); + } + l->buf.add('\0'); + gameserverlists.add(l); + updateserverlist = false; } void gengbanlist() { - messagebuf *l = new messagebuf(gbanlists); - const char *header = "cleargbans\n"; - l->buf.put(header, strlen(header)); - string cmd = "addgban "; - int cmdlen = strlen(cmd); - loopv(gbans) - { - ipmask &b = gbans[i]; - l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen])); - l->buf.add('\n'); - } - if(gbanlists.length() && gbanlists.last()->equals(*l)) - { - delete l; - return; - } - while(gbanlists.length() && gbanlists.last()->refs<=0) - delete gbanlists.pop(); - loopv(gbanlists) - { - messagebuf *m = gbanlists[i]; - if(m->refs > 0 && !m->endswith(*l)) m->concat(*l); - } - gbanlists.add(l); - loopv(clients) - { - client &c = *clients[i]; - if(c.servport >= 0 && !c.message) - { - c.message = l; - c.message->refs++; - } - } + messagebuf *l = new messagebuf(gbanlists); + const char *header = "cleargbans\n"; + l->buf.put(header, strlen(header)); + string cmd = "addgban "; + int cmdlen = strlen(cmd); + loopv(gbans) + { + ipmask &b = gbans[i]; + l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen])); + l->buf.add('\n'); + } + if(gbanlists.length() && gbanlists.last()->equals(*l)) + { + delete l; + return; + } + while(gbanlists.length() && gbanlists.last()->refs<=0) + delete gbanlists.pop(); + loopv(gbanlists) + { + messagebuf *m = gbanlists[i]; + if(m->refs > 0 && !m->endswith(*l)) m->concat(*l); + } + gbanlists.add(l); + loopv(clients) + { + client &c = *clients[i]; + if(c.servport >= 0 && !c.message) + { + c.message = l; + c.message->refs++; + } + } } void addgameserver(client &c) { - if(gameservers.length() >= SERVER_LIMIT) return; - int dups = 0; - loopv(gameservers) - { - gameserver &s = *gameservers[i]; - if(s.address.host != c.address.host) continue; - ++dups; - if(s.port == c.servport) - { - s.lastping = 0; - s.numpings = 0; - return; - } - } - if(dups >= SERVER_DUP_LIMIT) - { - outputf(c, "failreg too many servers on ip\n"); - return; - } - string hostname; - if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) - { - outputf(c, "failreg failed resolving ip\n"); - return; - } - gameserver &s = *gameservers.add(new gameserver); - s.address.host = c.address.host; - s.address.port = c.servport+1; - copystring(s.ip, hostname); - s.port = c.servport; - s.numpings = 0; - s.lastping = s.lastpong = 0; + if(gameservers.length() >= SERVER_LIMIT) return; + int dups = 0; + loopv(gameservers) + { + gameserver &s = *gameservers[i]; + if(s.address.host != c.address.host) continue; + ++dups; + if(s.port == c.servport) + { + s.lastping = 0; + s.numpings = 0; + return; + } + } + if(dups >= SERVER_DUP_LIMIT) + { + outputf(c, "failreg too many servers on ip\n"); + return; + } + string hostname; + if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) + { + outputf(c, "failreg failed resolving ip\n"); + return; + } + gameserver &s = *gameservers.add(new gameserver); + s.address.host = c.address.host; + s.address.port = c.servport+1; + copystring(s.ip, hostname); + s.port = c.servport; + s.numpings = 0; + s.lastping = s.lastpong = 0; } client *findclient(gameserver &s) { - loopv(clients) - { - client &c = *clients[i]; - if(s.address.host == c.address.host && s.port == c.servport) - return &c; - } - return NULL; + loopv(clients) + { + client &c = *clients[i]; + if(s.address.host == c.address.host && s.port == c.servport) + return &c; + } + return NULL; } void servermessage(gameserver &s, const char *msg) { - client *c = findclient(s); - if(c) outputf(*c, msg); + client *c = findclient(s); + if(c) outputf(*c, msg); } void checkserverpongs() { - ENetBuffer buf; - ENetAddress addr; - static uchar pong[MAXTRANS]; - for(;;) - { - buf.data = pong; - buf.dataLength = sizeof(pong); - int len = enet_socket_receive(pingsocket, &addr, &buf, 1); - if(len <= 0) break; - loopv(gameservers) - { - gameserver &s = *gameservers[i]; - if(s.address.host == addr.host && s.address.port == addr.port) - { - if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) - { - client *c = findclient(s); - if(c) - { - c->registeredserver = true; - outputf(*c, "succreg\n"); - if(!c->message && gbanlists.length()) - { - c->message = gbanlists.last(); - c->message->refs++; - } - } - } - if(!s.lastpong) updateserverlist = true; - s.lastpong = servtime ? servtime : 1; - break; - } - } - } + ENetBuffer buf; + ENetAddress addr; + static uchar pong[MAXTRANS]; + for(;;) + { + buf.data = pong; + buf.dataLength = sizeof(pong); + int len = enet_socket_receive(pingsocket, &addr, &buf, 1); + if(len <= 0) break; + loopv(gameservers) + { + gameserver &s = *gameservers[i]; + if(s.address.host == addr.host && s.address.port == addr.port) + { + if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) + { + client *c = findclient(s); + if(c) + { + c->registeredserver = true; + outputf(*c, "succreg\n"); + if(!c->message && gbanlists.length()) + { + c->message = gbanlists.last(); + c->message->refs++; + } + } + } + if(!s.lastpong) updateserverlist = true; + s.lastpong = servtime ? servtime : 1; + break; + } + } + } } void bangameservers() { - loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) - { - delete gameservers.remove(i); - updateserverlist = true; - } + loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) + { + delete gameservers.remove(i); + updateserverlist = true; + } } void checkgameservers() { - ENetBuffer buf; - loopv(gameservers) - { - gameserver &s = *gameservers[i]; - if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) - { - if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) - { - delete gameservers.remove(i--); - updateserverlist = true; - } - } - else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) - { - if(s.numpings >= PING_RETRY) - { - servermessage(s, "failreg failed pinging server\n"); - delete gameservers.remove(i--); - updateserverlist = true; - } - else - { - static const uchar ping[] = { 1 }; - buf.data = (void *)ping; - buf.dataLength = sizeof(ping); - s.numpings++; - s.lastping = servtime ? servtime : 1; - enet_socket_send(pingsocket, &s.address, &buf, 1); - } - } - } + ENetBuffer buf; + loopv(gameservers) + { + gameserver &s = *gameservers[i]; + if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) + { + if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) + { + delete gameservers.remove(i--); + updateserverlist = true; + } + } + else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) + { + if(s.numpings >= PING_RETRY) + { + servermessage(s, "failreg failed pinging server\n"); + delete gameservers.remove(i--); + updateserverlist = true; + } + else + { + static const uchar ping[] = { 1 }; + buf.data = (void *)ping; + buf.dataLength = sizeof(ping); + s.numpings++; + s.lastping = servtime ? servtime : 1; + enet_socket_send(pingsocket, &s.address, &buf, 1); + } + } + } } void messagebuf::purge() { - refs = max(refs - 1, 0); - if(refs<=0 && owner.last()!=this) - { - owner.removeobj(this); - delete this; - } + refs = max(refs - 1, 0); + if(refs<=0 && owner.last()!=this) + { + owner.removeobj(this); + delete this; + } } void purgeauths(client &c) { - int expired = 0; - loopv(c.authreqs) - { - if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) - { - outputf(c, "failauth %u\n", c.authreqs[i].id); - freechallenge(c.authreqs[i].answer); - expired = i + 1; - } - else break; - } - if(expired > 0) c.authreqs.remove(0, expired); + int expired = 0; + loopv(c.authreqs) + { + if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) + { + outputf(c, "failauth %u\n", c.authreqs[i].id); + freechallenge(c.authreqs[i].answer); + expired = i + 1; + } + else break; + } + if(expired > 0) c.authreqs.remove(0, expired); } void reqauth(client &c, uint id, char *name) { - if(ENET_TIME_DIFFERENCE(servtime, c.lastauth) < AUTH_THROTTLE) - return; - - c.lastauth = servtime; - - purgeauths(c); - - time_t t = time(NULL); - char *ct = ctime(&t); - if(ct) - { - char *newline = strchr(ct, '\n'); - if(newline) *newline = '\0'; - } - string ip; - if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); - conoutf("%s: attempting \"%s\" as %u from %s", ct ? ct : "-", name, id, ip); - - userinfo *u = users.access(name); - if(!u) - { - outputf(c, "failauth %u\n", id); - return; - } - - if(c.authreqs.length() >= AUTH_LIMIT) - { - outputf(c, "failauth %u\n", c.authreqs[0].id); - freechallenge(c.authreqs[0].answer); - c.authreqs.remove(0); - } - - authreq &a = c.authreqs.add(); - a.reqtime = servtime; - a.id = id; - uint seed[3] = { uint(starttime), servtime, randomMT() }; - static vector buf; - buf.setsize(0); - a.answer = genchallenge(u->pubkey, seed, sizeof(seed), buf); - - outputf(c, "chalauth %u %s\n", id, buf.getbuf()); + if(ENET_TIME_DIFFERENCE(servtime, c.lastauth) < AUTH_THROTTLE) + return; + + c.lastauth = servtime; + + purgeauths(c); + + time_t t = time(NULL); + char *ct = ctime(&t); + if(ct) + { + char *newline = strchr(ct, '\n'); + if(newline) *newline = '\0'; + } + string ip; + if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); + conoutf("%s: attempting \"%s\" as %u from %s", ct ? ct : "-", name, id, ip); + + userinfo *u = users.access(name); + if(!u) + { + outputf(c, "failauth %u\n", id); + return; + } + + if(c.authreqs.length() >= AUTH_LIMIT) + { + outputf(c, "failauth %u\n", c.authreqs[0].id); + freechallenge(c.authreqs[0].answer); + c.authreqs.remove(0); + } + + authreq &a = c.authreqs.add(); + a.reqtime = servtime; + a.id = id; + uint seed[3] = { uint(starttime), servtime, randomMT() }; + static vector buf; + buf.setsize(0); + a.answer = genchallenge(u->pubkey, seed, sizeof(seed), buf); + + outputf(c, "chalauth %u %s\n", id, buf.getbuf()); } void confauth(client &c, uint id, const char *val) { - purgeauths(c); - - loopv(c.authreqs) if(c.authreqs[i].id == id) - { - string ip; - if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); - if(checkchallenge(val, c.authreqs[i].answer)) - { - outputf(c, "succauth %u\n", id); - conoutf("succeeded %u from %s", id, ip); - } - else - { - outputf(c, "failauth %u\n", id); - conoutf("failed %u from %s", id, ip); - } - freechallenge(c.authreqs[i].answer); - c.authreqs.remove(i--); - return; - } - outputf(c, "failauth %u\n", id); + purgeauths(c); + + loopv(c.authreqs) if(c.authreqs[i].id == id) + { + string ip; + if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); + if(checkchallenge(val, c.authreqs[i].answer)) + { + outputf(c, "succauth %u\n", id); + conoutf("succeeded %u from %s", id, ip); + } + else + { + outputf(c, "failauth %u\n", id); + conoutf("failed %u from %s", id, ip); + } + freechallenge(c.authreqs[i].answer); + c.authreqs.remove(i--); + return; + } + outputf(c, "failauth %u\n", id); } bool checkclientinput(client &c) { - if(c.inputpos<0) return true; - char *end = (char *)memchr(c.input, '\n', c.inputpos); - while(end) - { - *end++ = '\0'; - c.lastinput = servtime; - - int port; - uint id; - string user, val; - if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) - { - genserverlist(); - if(gameserverlists.empty() || c.message) return false; - c.message = gameserverlists.last(); - c.message->refs++; - c.output.setsize(0); - c.outputpos = 0; - c.shouldpurge = true; - return true; - } - else if(sscanf(c.input, "regserv %d", &port) == 1) - { - if(checkban(servbans, c.address.host)) return false; - if(port < 0 || port > 0xFFFF-1 || (c.servport >= 0 && port != c.servport)) outputf(c, "failreg invalid port\n"); - else - { - c.servport = port; - addgameserver(c); - } - } - else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) - { - reqauth(c, id, user); - } - else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) - { - confauth(c, id, val); - } - c.inputpos = &c.input[c.inputpos] - end; - memmove(c.input, end, c.inputpos); - - end = (char *)memchr(c.input, '\n', c.inputpos); - } - return c.inputpos<(int)sizeof(c.input); + if(c.inputpos<0) return true; + char *end = (char *)memchr(c.input, '\n', c.inputpos); + while(end) + { + *end++ = '\0'; + c.lastinput = servtime; + + int port; + uint id; + string user, val; + if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) + { + genserverlist(); + if(gameserverlists.empty() || c.message) return false; + c.message = gameserverlists.last(); + c.message->refs++; + c.output.setsize(0); + c.outputpos = 0; + c.shouldpurge = true; + return true; + } + else if(sscanf(c.input, "regserv %d", &port) == 1) + { + if(checkban(servbans, c.address.host)) return false; + if(port < 0 || port > 0xFFFF-1 || (c.servport >= 0 && port != c.servport)) outputf(c, "failreg invalid port\n"); + else + { + c.servport = port; + addgameserver(c); + } + } + else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) + { + reqauth(c, id, user); + } + else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) + { + confauth(c, id, val); + } + c.inputpos = &c.input[c.inputpos] - end; + memmove(c.input, end, c.inputpos); + + end = (char *)memchr(c.input, '\n', c.inputpos); + } + return c.inputpos<(int)sizeof(c.input); } ENetSocketSet readset, writeset; void checkclients() { - ENetSocketSet readset, writeset; - ENetSocket maxsock = max(serversocket, pingsocket); - ENET_SOCKETSET_EMPTY(readset); - ENET_SOCKETSET_EMPTY(writeset); - ENET_SOCKETSET_ADD(readset, serversocket); - ENET_SOCKETSET_ADD(readset, pingsocket); - loopv(clients) - { - client &c = *clients[i]; - if(c.authreqs.length()) purgeauths(c); - if(c.message || c.output.length()) ENET_SOCKETSET_ADD(writeset, c.socket); - else ENET_SOCKETSET_ADD(readset, c.socket); - maxsock = max(maxsock, c.socket); - } - if(enet_socketset_select(maxsock, &readset, &writeset, 1000)<=0) return; - - if(ENET_SOCKETSET_CHECK(readset, pingsocket)) checkserverpongs(); - if(ENET_SOCKETSET_CHECK(readset, serversocket)) - { - ENetAddress address; - ENetSocket clientsocket = enet_socket_accept(serversocket, &address); - if(clients.length()>=CLIENT_LIMIT || checkban(bans, address.host)) enet_socket_destroy(clientsocket); - else if(clientsocket!=ENET_SOCKET_NULL) - { - int dups = 0, oldest = -1; - loopv(clients) if(clients[i]->address.host == address.host) - { - dups++; - if(oldest<0 || clients[i]->connecttime < clients[oldest]->connecttime) oldest = i; - } - if(dups >= DUP_LIMIT) purgeclient(oldest); - - client *c = new client; - c->address = address; - c->socket = clientsocket; - c->connecttime = servtime; - c->lastinput = servtime; - clients.add(c); - } - } - - loopv(clients) - { - client &c = *clients[i]; - if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) - { - const char *data = c.output.length() ? c.output.getbuf() : c.message->getbuf(); - int len = c.output.length() ? c.output.length() : c.message->length(); - ENetBuffer buf; - buf.data = (void *)&data[c.outputpos]; - buf.dataLength = len-c.outputpos; - int res = enet_socket_send(c.socket, NULL, &buf, 1); - if(res>=0) - { - c.outputpos += res; - if(c.outputpos>=len) - { - if(c.output.length()) c.output.setsize(0); - else - { - c.message->purge(); - c.message = NULL; - } - c.outputpos = 0; - if(!c.message && c.output.empty() && c.shouldpurge) - { - purgeclient(i--); - continue; - } - } - } - else { purgeclient(i--); continue; } - } - if(ENET_SOCKETSET_CHECK(readset, c.socket)) - { - ENetBuffer buf; - buf.data = &c.input[c.inputpos]; - buf.dataLength = sizeof(c.input) - c.inputpos; - int res = enet_socket_receive(c.socket, NULL, &buf, 1); - if(res>0) - { - c.inputpos += res; - c.input[min(c.inputpos, (int)sizeof(c.input)-1)] = '\0'; - if(!checkclientinput(c)) { purgeclient(i--); continue; } - } - else { purgeclient(i--); continue; } - } - if(c.output.length() > OUTPUT_LIMIT) { purgeclient(i--); continue; } - if(ENET_TIME_DIFFERENCE(servtime, c.lastinput) >= (c.registeredserver ? KEEPALIVE_TIME : CLIENT_TIME)) { purgeclient(i--); continue; } - } + ENetSocketSet readset, writeset; + ENetSocket maxsock = max(serversocket, pingsocket); + ENET_SOCKETSET_EMPTY(readset); + ENET_SOCKETSET_EMPTY(writeset); + ENET_SOCKETSET_ADD(readset, serversocket); + ENET_SOCKETSET_ADD(readset, pingsocket); + loopv(clients) + { + client &c = *clients[i]; + if(c.authreqs.length()) purgeauths(c); + if(c.message || c.output.length()) ENET_SOCKETSET_ADD(writeset, c.socket); + else ENET_SOCKETSET_ADD(readset, c.socket); + maxsock = max(maxsock, c.socket); + } + if(enet_socketset_select(maxsock, &readset, &writeset, 1000)<=0) return; + + if(ENET_SOCKETSET_CHECK(readset, pingsocket)) checkserverpongs(); + if(ENET_SOCKETSET_CHECK(readset, serversocket)) + { + ENetAddress address; + ENetSocket clientsocket = enet_socket_accept(serversocket, &address); + if(clients.length()>=CLIENT_LIMIT || checkban(bans, address.host)) enet_socket_destroy(clientsocket); + else if(clientsocket!=ENET_SOCKET_NULL) + { + int dups = 0, oldest = -1; + loopv(clients) if(clients[i]->address.host == address.host) + { + dups++; + if(oldest<0 || clients[i]->connecttime < clients[oldest]->connecttime) oldest = i; + } + if(dups >= DUP_LIMIT) purgeclient(oldest); + + client *c = new client; + c->address = address; + c->socket = clientsocket; + c->connecttime = servtime; + c->lastinput = servtime; + clients.add(c); + } + } + + loopv(clients) + { + client &c = *clients[i]; + if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) + { + const char *data = c.output.length() ? c.output.getbuf() : c.message->getbuf(); + int len = c.output.length() ? c.output.length() : c.message->length(); + ENetBuffer buf; + buf.data = (void *)&data[c.outputpos]; + buf.dataLength = len-c.outputpos; + int res = enet_socket_send(c.socket, NULL, &buf, 1); + if(res>=0) + { + c.outputpos += res; + if(c.outputpos>=len) + { + if(c.output.length()) c.output.setsize(0); + else + { + c.message->purge(); + c.message = NULL; + } + c.outputpos = 0; + if(!c.message && c.output.empty() && c.shouldpurge) + { + purgeclient(i--); + continue; + } + } + } + else { purgeclient(i--); continue; } + } + if(ENET_SOCKETSET_CHECK(readset, c.socket)) + { + ENetBuffer buf; + buf.data = &c.input[c.inputpos]; + buf.dataLength = sizeof(c.input) - c.inputpos; + int res = enet_socket_receive(c.socket, NULL, &buf, 1); + if(res>0) + { + c.inputpos += res; + c.input[min(c.inputpos, (int)sizeof(c.input)-1)] = '\0'; + if(!checkclientinput(c)) { purgeclient(i--); continue; } + } + else { purgeclient(i--); continue; } + } + if(c.output.length() > OUTPUT_LIMIT) { purgeclient(i--); continue; } + if(ENET_TIME_DIFFERENCE(servtime, c.lastinput) >= (c.registeredserver ? KEEPALIVE_TIME : CLIENT_TIME)) { purgeclient(i--); continue; } + } } void banclients() { - loopvrev(clients) if(checkban(bans, clients[i]->address.host)) purgeclient(i); + loopvrev(clients) if(checkban(bans, clients[i]->address.host)) purgeclient(i); } volatile int reloadcfg = 1; void reloadsignal(int signum) { - reloadcfg = 1; + reloadcfg = 1; } int main(int argc, char **argv) { - if(enet_initialize()<0) fatal("Unable to initialise network module"); - atexit(enet_deinitialize); - - const char *dir = "", *ip = NULL; - int port = 28787; - if(argc>=2) dir = argv[1]; - if(argc>=3) port = atoi(argv[2]); - if(argc>=4) ip = argv[3]; - defformatstring(logname, "%smaster.log", dir); - defformatstring(cfgname, "%smaster.cfg", dir); - path(logname); - path(cfgname); - logfile = fopen(logname, "a"); - if(!logfile) logfile = stdout; - setvbuf(logfile, NULL, _IOLBF, BUFSIZ); - signal(SIGUSR1, reloadsignal); - setupserver(port, ip); - for(;;) - { - if(reloadcfg) - { - conoutf("reloading master.cfg"); - execfile(cfgname); - bangameservers(); - banclients(); - gengbanlist(); - reloadcfg = 0; - } - - servtime = enet_time_get(); - checkclients(); - checkgameservers(); - } - - return EXIT_SUCCESS; + if(enet_initialize()<0) fatal("Unable to initialise network module"); + atexit(enet_deinitialize); + + const char *dir = "", *ip = NULL; + int port = 28787; + if(argc>=2) dir = argv[1]; + if(argc>=3) port = atoi(argv[2]); + if(argc>=4) ip = argv[3]; + defformatstring(logname, "%smaster.log", dir); + defformatstring(cfgname, "%smaster.cfg", dir); + path(logname); + path(cfgname); + logfile = fopen(logname, "a"); + if(!logfile) logfile = stdout; + setvbuf(logfile, NULL, _IOLBF, BUFSIZ); + signal(SIGUSR1, reloadsignal); + setupserver(port, ip); + for(;;) + { + if(reloadcfg) + { + conoutf("reloading master.cfg"); + execfile(cfgname); + bangameservers(); + banclients(); + gengbanlist(); + reloadcfg = 0; + } + + servtime = enet_time_get(); + checkclients(); + checkgameservers(); + } + + return EXIT_SUCCESS; } -- cgit v1.2.3