diff --git a/src/client/meson.build b/src/client/meson.build index da3e018..2441016 100644 --- a/src/client/meson.build +++ b/src/client/meson.build @@ -32,7 +32,6 @@ client_src = [ '../engine/rendertext.cc', '../engine/renderva.cc', '../engine/server.cc', - '../engine/serverbrowser.cc', '../engine/shader.cc', '../engine/stain.cc', '../engine/texture.cc', diff --git a/src/engine/client.cc b/src/engine/client.cc index 24e2135..02b6202 100644 --- a/src/engine/client.cc +++ b/src/engine/client.cc @@ -86,25 +86,10 @@ void connectserv(const char *servername, int serverport, const char *serverpassw ENetAddress address; address.port = serverport; - if(servername) - { - if(strcmp(servername, connectname)) setsvar("connectname", servername); - if(serverport != connectport) setvar("connectport", serverport); - addserver(servername, serverport, serverpassword && serverpassword[0] ? serverpassword : NULL); - conoutf("attempting to connect to %s:%d", servername, serverport); - if(!resolverwait(servername, &address)) - { - conoutf("\f3could not resolve server %s", servername); - return; - } - } - else - { - setsvar("connectname", ""); - setvar("connectport", 0); - conoutf("attempting to connect over LAN"); - address.host = ENET_HOST_BROADCAST; - } + setsvar("connectname", ""); + setvar("connectport", 0); + conoutf("attempting to connect over LAN"); + address.host = ENET_HOST_BROADCAST; if(!clienthost) { diff --git a/src/engine/engine.hh b/src/engine/engine.hh index 13b2cdd..897100a 100644 --- a/src/engine/engine.hh +++ b/src/engine/engine.hh @@ -533,17 +533,10 @@ extern void cleanupserver(); extern void serverslice(bool dedicated, uint timeout); extern void updatetime(); -extern ENetSocket connectmaster(bool wait); extern void localclienttoserver(int chan, ENetPacket *); extern void localconnect(); extern bool serveroption(char *opt); -// serverbrowser -extern bool resolverwait(const char *name, ENetAddress *address); -extern int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address); -extern void addserver(const char *name, int port = 0, const char *password = NULL, bool keep = false); -extern void writeservercfg(); - // client extern void localdisconnect(bool cleanup = true); extern void localservertoclient(int chan, ENetPacket *packet); diff --git a/src/engine/main.cc b/src/engine/main.cc index b986a6d..21402ee 100644 --- a/src/engine/main.cc +++ b/src/engine/main.cc @@ -32,7 +32,6 @@ extern void writeinitcfg(); void quit() // normal exit { writeinitcfg(); - writeservercfg(); abortconnect(); disconnect(); localdisconnect(); diff --git a/src/engine/master.cc b/src/engine/master.cc deleted file mode 100644 index 50bcc2d..0000000 --- a/src/engine/master.cc +++ /dev/null @@ -1,730 +0,0 @@ -#ifdef WIN32 -#define FD_SETSIZE 4096 -#else -#include -#undef __FD_SETSIZE -#define __FD_SETSIZE 4096 -#endif - -#include "cube.hh" -#include -#include - -#define INPUT_LIMIT 4096 -#define OUTPUT_LIMIT (64*1024) -#define CLIENT_TIME (3*60*1000) -#define AUTH_TIME (30*1000) -#define AUTH_LIMIT 100 -#define AUTH_THROTTLE 1000 -#define CLIENT_LIMIT 4096 -#define DUP_LIMIT 16 -#define PING_TIME 3000 -#define PING_RETRY 5 -#define KEEPALIVE_TIME (65*60*1000) -#define SERVER_LIMIT 4096 -#define SERVER_DUP_LIMIT 10 - -FILE *logfile = NULL; - -struct userinfo -{ - 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); -} -COMMAND(adduser, "ss"); - -void clearusers() -{ - enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); - users.clear(); -} -COMMAND(clearusers, ""); - -vector bans, servbans, gbans; - -void clearbans() -{ - 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); -} -ICOMMAND(ban, "s", (char *name), addban(bans, name)); -ICOMMAND(servban, "s", (char *name), addban(servbans, name)); -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; -} - -struct authreq -{ - enet_uint32 reqtime; - uint id; - void *answer; -}; - -struct gameserver -{ - ENetAddress address; - string ip; - int port, numpings; - enet_uint32 lastping, lastpong; -}; -vector gameservers; - -struct messagebuf -{ - vector &owner; - vector buf; - int refs; - - messagebuf(vector &owner) : owner(owner), refs(0) {} - - 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 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()); - } -}; -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) {} -}; -vector clients; - -ENetSocket serversocket = ENET_SOCKET_NULL; - -time_t starttime; -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); -} - -void conoutfv(int type, const char *fmt, va_list args) -{ - vfprintf(logfile, fmt, args); - fputc('\n', logfile); -} - -void conoutf(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - conoutfv(CON_INFO, fmt, args); - va_end(args); -} - -void conoutf(int type, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - conoutfv(type, fmt, args); - va_end(args); -} - -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); -} - -void output(client &c, const char *msg, int len = 0) -{ - if(!len) len = strlen(msg); - c.output.put(msg, len); -} - -void outputf(client &c, const char *fmt, ...) -{ - defvformatstring(msg, fmt, fmt); - - 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; -} - -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); -} - -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; -} - -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++; - } - } -} - -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; - 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; -} - -void servermessage(gameserver &s, const char *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; - } - } - } -} - -void bangameservers() -{ - 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[] = { 0xFF, 0xFF, 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; - } -} - -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); -} - -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()); -} - -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); -} - -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 || (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; } - } -} - -void banclients() -{ - loopvrev(clients) if(checkban(bans, clients[i]->address.host)) purgeclient(i); -} - -volatile int reloadcfg = 1; - -#ifndef WIN32 -void reloadsignal(int signum) -{ - reloadcfg = 1; -} -#endif - -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 = 41999; - 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); -#ifndef WIN32 - signal(SIGUSR1, reloadsignal); -#endif - setupserver(port, ip); - for(;;) - { - if(reloadcfg) - { - conoutf("reloading %s", cfgname); - execfile(cfgname); - bangameservers(); - banclients(); - gengbanlist(); - reloadcfg = 0; - } - - servtime = enet_time_get(); - checkclients(); - checkgameservers(); - } - - return EXIT_SUCCESS; -} - diff --git a/src/engine/server.cc b/src/engine/server.cc index 0a269bb..d6f2fee 100644 --- a/src/engine/server.cc +++ b/src/engine/server.cc @@ -352,172 +352,6 @@ void localclienttoserver(int chan, ENetPacket *packet) if(c) process(packet, c->num, chan); } -#ifdef STANDALONE -bool resolverwait(const char *name, ENetAddress *address) -{ - return enet_address_set_host(address, name) >= 0; -} - -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &remoteaddress) -{ - return enet_socket_connect(sock, &remoteaddress); -} -#endif - -ENetSocket mastersock = ENET_SOCKET_NULL; -ENetAddress masteraddress = { ENET_HOST_ANY, ENET_PORT_ANY }, serveraddress = { ENET_HOST_ANY, ENET_PORT_ANY }; -int lastupdatemaster = 0, lastconnectmaster = 0, masterconnecting = 0, masterconnected = 0; -vector masterout, masterin; -int masteroutpos = 0, masterinpos = 0; -VARN(updatemaster, allowupdatemaster, 0, 1, 1); - -void disconnectmaster() -{ - if(mastersock != ENET_SOCKET_NULL) - { - server::masterdisconnected(); - enet_socket_destroy(mastersock); - mastersock = ENET_SOCKET_NULL; - } - - masterout.setsize(0); - masterin.setsize(0); - masteroutpos = masterinpos = 0; - - masteraddress.host = ENET_HOST_ANY; - masteraddress.port = ENET_PORT_ANY; - - lastupdatemaster = masterconnecting = masterconnected = 0; -} - -SVARF(mastername, server::defaultmaster(), disconnectmaster()); -VARF(masterport, 1, server::masterport(), 0xFFFF, disconnectmaster()); - -ENetSocket connectmaster(bool wait) -{ - if(!mastername[0]) return ENET_SOCKET_NULL; - if(masteraddress.host == ENET_HOST_ANY) - { - if(isdedicatedserver()) logoutf("looking up %s...", mastername); - masteraddress.port = masterport; - if(!resolverwait(mastername, &masteraddress)) return ENET_SOCKET_NULL; - } - ENetSocket sock = enet_socket_create(ENET_SOCKET_TYPE_STREAM); - if(sock == ENET_SOCKET_NULL) - { - if(isdedicatedserver()) logoutf("could not open master server socket"); - return ENET_SOCKET_NULL; - } - if(wait || serveraddress.host == ENET_HOST_ANY || !enet_socket_bind(sock, &serveraddress)) - { - enet_socket_set_option(sock, ENET_SOCKOPT_NONBLOCK, 1); - if(wait) - { - if(!connectwithtimeout(sock, mastername, masteraddress)) return sock; - } - else if(!enet_socket_connect(sock, &masteraddress)) return sock; - } - enet_socket_destroy(sock); - if(isdedicatedserver()) logoutf("could not connect to master server"); - return ENET_SOCKET_NULL; -} - -bool requestmaster(const char *req) -{ - if(mastersock == ENET_SOCKET_NULL) - { - mastersock = connectmaster(false); - if(mastersock == ENET_SOCKET_NULL) return false; - lastconnectmaster = masterconnecting = totalmillis ? totalmillis : 1; - } - - if(masterout.length() >= 4096) return false; - - masterout.put(req, strlen(req)); - return true; -} - -bool requestmasterf(const char *fmt, ...) -{ - defvformatstring(req, fmt, fmt); - return requestmaster(req); -} - -void processmasterinput() -{ - if(masterinpos >= masterin.length()) return; - - char *input = &masterin[masterinpos], *end = (char *)memchr(input, '\n', masterin.length() - masterinpos); - while(end) - { - *end = '\0'; - - const char *args = input; - while(args < end && !iscubespace(*args)) args++; - int cmdlen = args - input; - while(args < end && iscubespace(*args)) args++; - - if(matchstring(input, cmdlen, "failreg")) - conoutf(CON_ERROR, "master server registration failed: %s", args); - else if(matchstring(input, cmdlen, "succreg")) - conoutf("master server registration succeeded"); - else server::processmasterinput(input, cmdlen, args); - - end++; - masterinpos = end - masterin.getbuf(); - input = end; - end = (char *)memchr(input, '\n', masterin.length() - masterinpos); - } - - if(masterinpos >= masterin.length()) - { - masterin.setsize(0); - masterinpos = 0; - } -} - -void flushmasteroutput() -{ - if(masterconnecting && totalmillis - masterconnecting >= 60000) - { - logoutf("could not connect to master server"); - disconnectmaster(); - } - if(masterout.empty() || !masterconnected) return; - - ENetBuffer buf; - buf.data = &masterout[masteroutpos]; - buf.dataLength = masterout.length() - masteroutpos; - int sent = enet_socket_send(mastersock, NULL, &buf, 1); - if(sent >= 0) - { - masteroutpos += sent; - if(masteroutpos >= masterout.length()) - { - masterout.setsize(0); - masteroutpos = 0; - } - } - else disconnectmaster(); -} - -void flushmasterinput() -{ - if(masterin.length() >= masterin.capacity()) - masterin.reserve(4096); - - ENetBuffer buf; - buf.data = masterin.getbuf() + masterin.length(); - buf.dataLength = masterin.capacity() - masterin.length(); - int recv = enet_socket_receive(mastersock, NULL, &buf, 1); - if(recv > 0) - { - masterin.advance(recv); - processmasterinput(); - } - else disconnectmaster(); -} - static ENetAddress serverinfoaddress; void sendserverinforeply(ucharbuf &p) @@ -536,12 +370,6 @@ void checkserversockets() // reply all server info requests ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENetSocket maxsock = ENET_SOCKET_NULL; - if(mastersock != ENET_SOCKET_NULL) - { - maxsock = maxsock == ENET_SOCKET_NULL ? mastersock : max(maxsock, mastersock); - ENET_SOCKETSET_ADD(readset, mastersock); - if(!masterconnected) ENET_SOCKETSET_ADD(writeset, mastersock); - } if(lansock != ENET_SOCKET_NULL) { maxsock = maxsock == ENET_SOCKET_NULL ? lansock : max(maxsock, lansock); @@ -561,29 +389,6 @@ void checkserversockets() // reply all server info requests p.len += len-2; server::serverinforeply(req, p); } - - if(mastersock != ENET_SOCKET_NULL) - { - if(!masterconnected) - { - if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock)) - { - int error = 0; - if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error) - { - logoutf("could not connect to master server"); - disconnectmaster(); - } - else - { - masterconnecting = 0; - masterconnected = totalmillis ? totalmillis : 1; - server::masterconnected(); - } - } - } - if(mastersock != ENET_SOCKET_NULL && ENET_SOCKETSET_CHECK(readset, mastersock)) flushmasterinput(); - } } static int serverinfointercept(ENetHost *host, ENetEvent *event) @@ -604,13 +409,6 @@ VARF(serverport, 0, server::serverport(), 0xFFFF, { if(!serverport) serverport = int curtime = 0, lastmillis = 0, elapsedtime = 0, totalmillis = 0; #endif -void updatemasterserver() -{ - if(!masterconnected && lastconnectmaster && totalmillis-lastconnectmaster <= 5*60*1000) return; - if(mastername[0] && allowupdatemaster) requestmasterf("regserv %d\n", serverport); - lastupdatemaster = totalmillis ? totalmillis : 1; -} - uint totalsecs = 0; void updatetime() @@ -650,12 +448,8 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f } server::serverupdate(); - flushmasteroutput(); checkserversockets(); - if(!lastupdatemaster || totalmillis-lastupdatemaster>60*60*1000) // send alive signal to masterserver every hour of uptime - updatemasterserver(); - if(totalmillis-laststatus>60*1000) // display bandwidth stats, useful for server ops { laststatus = totalmillis; @@ -1059,7 +853,6 @@ bool setuplistenserver(bool dedicated) if(*serverip) { if(enet_address_set_host(&address, serverip)<0) conoutf(CON_WARN, "WARNING: server ip not resolved"); - else serveraddress.host = address.host; } serverhost = enet_host_create(&address, min(maxclients + server::reserveclients(), MAXCLIENTS), server::numchannels(), 0, serveruprate); if(!serverhost) return servererror(dedicated, "could not create server host"); @@ -1095,7 +888,6 @@ void initserver(bool listen, bool dedicated) if(listen) { dedicatedserver = dedicated; - updatemasterserver(); if(dedicated) rundedicatedserver(); // never returns #ifndef STANDALONE else conoutf("listen server started"); @@ -1108,13 +900,7 @@ void startlistenserver(int *usemaster) { if(serverhost) { conoutf(CON_ERROR, "listen server is already running"); return; } - allowupdatemaster = *usemaster>0 ? 1 : 0; - if(!setuplistenserver(false)) return; - - updatemasterserver(); - - conoutf("listen server started for %d clients%s", maxclients, allowupdatemaster ? " and listed with master server" : ""); } COMMAND(startlistenserver, "i"); diff --git a/src/engine/serverbrowser.cc b/src/engine/serverbrowser.cc deleted file mode 100644 index 26b875b..0000000 --- a/src/engine/serverbrowser.cc +++ /dev/null @@ -1,753 +0,0 @@ -#include "engine.hh" - -struct resolverthread -{ - SDL_Thread *thread; - const char *query; - int starttime; -}; - -struct resolverresult -{ - const char *query; - ENetAddress address; -}; - -vector resolverthreads; -vector resolverqueries; -vector resolverresults; -SDL_mutex *resolvermutex; -SDL_cond *querycond, *resultcond; - -#define RESOLVERTHREADS 2 -#define RESOLVERLIMIT 3000 - -int resolverloop(void * data) -{ - resolverthread *rt = (resolverthread *)data; - SDL_LockMutex(resolvermutex); - SDL_Thread *thread = rt->thread; - SDL_UnlockMutex(resolvermutex); - if(!thread || SDL_GetThreadID(thread) != SDL_ThreadID()) - return 0; - while(thread == rt->thread) - { - SDL_LockMutex(resolvermutex); - while(resolverqueries.empty()) SDL_CondWait(querycond, resolvermutex); - rt->query = resolverqueries.pop(); - rt->starttime = totalmillis; - SDL_UnlockMutex(resolvermutex); - - ENetAddress address = { ENET_HOST_ANY, ENET_PORT_ANY }; - enet_address_set_host(&address, rt->query); - - SDL_LockMutex(resolvermutex); - if(rt->query && thread == rt->thread) - { - resolverresult &rr = resolverresults.add(); - rr.query = rt->query; - rr.address = address; - rt->query = NULL; - rt->starttime = 0; - SDL_CondSignal(resultcond); - } - SDL_UnlockMutex(resolvermutex); - } - return 0; -} - -void resolverinit() -{ - resolvermutex = SDL_CreateMutex(); - querycond = SDL_CreateCond(); - resultcond = SDL_CreateCond(); - - SDL_LockMutex(resolvermutex); - loopi(RESOLVERTHREADS) - { - resolverthread &rt = resolverthreads.add(); - rt.query = NULL; - rt.starttime = 0; - rt.thread = SDL_CreateThread(resolverloop, "resolver", &rt); - } - SDL_UnlockMutex(resolvermutex); -} - -void resolverstop(resolverthread &rt) -{ - SDL_LockMutex(resolvermutex); - if(rt.query) - { -#if SDL_VERSION_ATLEAST(2, 0, 2) - SDL_DetachThread(rt.thread); -#endif - rt.thread = SDL_CreateThread(resolverloop, "resolver", &rt); - } - rt.query = NULL; - rt.starttime = 0; - SDL_UnlockMutex(resolvermutex); -} - -void resolverclear() -{ - if(resolverthreads.empty()) return; - - SDL_LockMutex(resolvermutex); - resolverqueries.shrink(0); - resolverresults.shrink(0); - loopv(resolverthreads) - { - resolverthread &rt = resolverthreads[i]; - resolverstop(rt); - } - SDL_UnlockMutex(resolvermutex); -} - -void resolverquery(const char *name) -{ - if(resolverthreads.empty()) resolverinit(); - - SDL_LockMutex(resolvermutex); - resolverqueries.add(name); - SDL_CondSignal(querycond); - SDL_UnlockMutex(resolvermutex); -} - -bool resolvercheck(const char **name, ENetAddress *address) -{ - bool resolved = false; - SDL_LockMutex(resolvermutex); - if(!resolverresults.empty()) - { - resolverresult &rr = resolverresults.pop(); - *name = rr.query; - address->host = rr.address.host; - resolved = true; - } - else loopv(resolverthreads) - { - resolverthread &rt = resolverthreads[i]; - if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT) - { - resolverstop(rt); - *name = rt.query; - resolved = true; - } - } - SDL_UnlockMutex(resolvermutex); - return resolved; -} - -bool resolverwait(const char *name, ENetAddress *address) -{ - if(resolverthreads.empty()) resolverinit(); - - defformatstring(text, "resolving %s... (esc to abort)", name); - renderprogress(0, text); - - SDL_LockMutex(resolvermutex); - resolverqueries.add(name); - SDL_CondSignal(querycond); - int starttime = SDL_GetTicks(), timeout = 0; - bool resolved = false; - for(;;) - { - SDL_CondWaitTimeout(resultcond, resolvermutex, 250); - loopv(resolverresults) if(resolverresults[i].query == name) - { - address->host = resolverresults[i].address.host; - resolverresults.remove(i); - resolved = true; - break; - } - if(resolved) break; - - timeout = SDL_GetTicks() - starttime; - renderprogress(min(float(timeout)/RESOLVERLIMIT, 1.0f), text); - if(interceptkey(SDLK_ESCAPE)) timeout = RESOLVERLIMIT + 1; - if(timeout > RESOLVERLIMIT) break; - } - if(!resolved && timeout > RESOLVERLIMIT) - { - loopv(resolverthreads) - { - resolverthread &rt = resolverthreads[i]; - if(rt.query == name) { resolverstop(rt); break; } - } - } - SDL_UnlockMutex(resolvermutex); - return resolved; -} - -#define CONNLIMIT 20000 - -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address) -{ - defformatstring(text, "connecting to %s... (esc to abort)", hostname); - renderprogress(0, text); - - ENetSocketSet readset, writeset; - if(!enet_socket_connect(sock, &address)) for(int starttime = SDL_GetTicks(), timeout = 0; timeout <= CONNLIMIT;) - { - ENET_SOCKETSET_EMPTY(readset); - ENET_SOCKETSET_EMPTY(writeset); - ENET_SOCKETSET_ADD(readset, sock); - ENET_SOCKETSET_ADD(writeset, sock); - int result = enet_socketset_select(sock, &readset, &writeset, 250); - if(result < 0) break; - else if(result > 0) - { - if(ENET_SOCKETSET_CHECK(readset, sock) || ENET_SOCKETSET_CHECK(writeset, sock)) - { - int error = 0; - if(enet_socket_get_option(sock, ENET_SOCKOPT_ERROR, &error) < 0 || error) break; - return 0; - } - } - timeout = SDL_GetTicks() - starttime; - renderprogress(min(float(timeout)/CONNLIMIT, 1.0f), text); - if(interceptkey(SDLK_ESCAPE)) break; - } - - return -1; -} - -struct pingattempts -{ - enum { MAXATTEMPTS = 2 }; - - int offset, attempts[MAXATTEMPTS]; - - pingattempts() : offset(0) { clearattempts(); } - - void clearattempts() { memset(attempts, 0, sizeof(attempts)); } - - void setoffset() { offset = 1 + rnd(0xFFFFFF); } - - int encodeping(int millis) - { - millis += offset; - return millis ? millis : 1; - } - - int decodeping(int val) - { - return val - offset; - } - - int addattempt(int millis) - { - int val = encodeping(millis); - loopk(MAXATTEMPTS-1) attempts[k+1] = attempts[k]; - attempts[0] = val; - return val; - } - - bool checkattempt(int val, bool del = true) - { - if(val) loopk(MAXATTEMPTS) if(attempts[k] == val) - { - if(del) attempts[k] = 0; - return true; - } - return false; - } - -}; - -static int currentprotocol = server::protocolversion(); - -enum { UNRESOLVED = 0, RESOLVING, RESOLVED }; - -struct serverinfo : servinfo, pingattempts -{ - enum - { - WAITING = INT_MAX, - - MAXPINGS = 3 - }; - - int resolved, lastping, nextping; - int pings[MAXPINGS]; - ENetAddress address; - bool keep; - const char *password; - - serverinfo() - : resolved(UNRESOLVED), keep(false), password(NULL) - { - clearpings(); - setoffset(); - } - - ~serverinfo() - { - DELETEA(password); - } - - void clearpings() - { - ping = WAITING; - loopk(MAXPINGS) pings[k] = WAITING; - nextping = 0; - lastping = -1; - clearattempts(); - } - - void cleanup() - { - clearpings(); - protocol = -1; - numplayers = maxplayers = 0; - attr.setsize(0); - } - - void reset() - { - lastping = -1; - } - - void checkdecay(int decay) - { - if(lastping >= 0 && totalmillis - lastping >= decay) - cleanup(); - if(lastping < 0) lastping = totalmillis; - } - - void calcping() - { - int numpings = 0, totalpings = 0; - loopk(MAXPINGS) if(pings[k] != WAITING) { totalpings += pings[k]; numpings++; } - ping = numpings ? totalpings/numpings : WAITING; - } - - void addping(int rtt, int millis) - { - if(millis >= lastping) lastping = -1; - pings[nextping] = rtt; - nextping = (nextping+1)%MAXPINGS; - calcping(); - } - - const char *status() const - { - if(address.host == ENET_HOST_ANY) return "[unknown host]"; - if(ping == WAITING) return "[waiting for response]"; - if(protocol < currentprotocol) return "[older protocol]"; - if(protocol > currentprotocol) return "[newer protocol]"; - return NULL; - } - - bool valid() const { return !status(); } - - static bool compare(serverinfo *a, serverinfo *b) - { - if(a->protocol == currentprotocol) - { - if(b->protocol != currentprotocol) return true; - } - else if(b->protocol == currentprotocol) return false; - if(a->keep > b->keep) return true; - if(a->keep < b->keep) return false; - if(a->numplayers < b->numplayers) return false; - if(a->numplayers > b->numplayers) return true; - if(a->ping > b->ping) return false; - if(a->ping < b->ping) return true; - int cmp = strcmp(a->name, b->name); - if(cmp != 0) return cmp < 0; - if(a->address.port < b->address.port) return true; - if(a->address.port > b->address.port) return false; - return false; - } -}; - -vector servers; -ENetSocket pingsock = ENET_SOCKET_NULL; -int lastinfo = 0; - -static serverinfo *newserver(const char *name, int port, uint ip = ENET_HOST_ANY) -{ - serverinfo *si = new serverinfo; - si->address.host = ip; - si->address.port = port; - if(ip!=ENET_HOST_ANY) si->resolved = RESOLVED; - - if(name) copystring(si->name, name); - else if(ip==ENET_HOST_ANY || enet_address_get_host_ip(&si->address, si->name, sizeof(si->name)) < 0) - { - delete si; - return NULL; - - } - - servers.add(si); - - return si; -} - -void addserver(const char *name, int port, const char *password, bool keep) -{ - if(port <= 0) port = server::serverport(); - loopv(servers) - { - serverinfo *s = servers[i]; - if(strcmp(s->name, name) || s->address.port != port) continue; - if(password && (!s->password || strcmp(s->password, password))) - { - DELETEA(s->password); - s->password = newstring(password); - } - if(keep && !s->keep) s->keep = true; - return; - } - serverinfo *s = newserver(name, port); - if(!s) return; - if(password) s->password = newstring(password); - s->keep = keep; -} - -VARP(searchlan, 0, 0, 1); -VARMP(servpingrate, 1, 5, 60, 1000); -VARMP(servpingdecay, 1, 15, 60, 1000); -VARP(maxservpings, 0, 10, 1000); - -pingattempts lanpings; - -template static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a) -{ - ucharbuf p(ping, N); - p.put(0xFF); p.put(0xFF); - putint(p, a.addattempt(totalmillis)); - buf.data = ping; - buf.dataLength = p.length(); -} - -void pingservers() -{ - if(pingsock == ENET_SOCKET_NULL) - { - pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pingsock == ENET_SOCKET_NULL) - { - lastinfo = totalmillis; - return; - } - enet_socket_set_option(pingsock, ENET_SOCKOPT_NONBLOCK, 1); - enet_socket_set_option(pingsock, ENET_SOCKOPT_BROADCAST, 1); - - lanpings.setoffset(); - } - - ENetBuffer buf; - uchar ping[MAXTRANS]; - - static int lastping = 0; - if(lastping >= servers.length()) lastping = 0; - loopi(maxservpings ? min(servers.length(), maxservpings) : servers.length()) - { - serverinfo &si = *servers[lastping]; - if(++lastping >= servers.length()) lastping = 0; - if(si.address.host == ENET_HOST_ANY) continue; - buildping(buf, ping, si); - enet_socket_send(pingsock, &si.address, &buf, 1); - - si.checkdecay(servpingdecay); - } - if(searchlan) - { - ENetAddress address; - address.host = ENET_HOST_BROADCAST; - address.port = server::laninfoport(); - buildping(buf, ping, lanpings); - enet_socket_send(pingsock, &address, &buf, 1); - } - lastinfo = totalmillis; -} - -void checkresolver() -{ - int resolving = 0; - loopv(servers) - { - serverinfo &si = *servers[i]; - if(si.resolved == RESOLVED) continue; - if(si.address.host == ENET_HOST_ANY) - { - if(si.resolved == UNRESOLVED) { si.resolved = RESOLVING; resolverquery(si.name); } - resolving++; - } - } - if(!resolving) return; - - const char *name = NULL; - for(;;) - { - ENetAddress addr = { ENET_HOST_ANY, ENET_PORT_ANY }; - if(!resolvercheck(&name, &addr)) break; - loopv(servers) - { - serverinfo &si = *servers[i]; - if(name == si.name) - { - si.resolved = RESOLVED; - si.address.host = addr.host; - break; - } - } - } -} - -static int lastreset = 0; - -void checkpings() -{ - if(pingsock==ENET_SOCKET_NULL) return; - enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; - ENetBuffer buf; - ENetAddress addr; - uchar ping[MAXTRANS]; - char text[MAXTRANS]; - buf.data = ping; - buf.dataLength = sizeof(ping); - while(enet_socket_wait(pingsock, &events, 0) >= 0 && events) - { - int len = enet_socket_receive(pingsock, &addr, &buf, 1); - if(len <= 0) return; - ucharbuf p(ping, len); - int millis = getint(p); - serverinfo *si = NULL; - loopv(servers) if(addr.host == servers[i]->address.host && addr.port == servers[i]->address.port) { si = servers[i]; break; } - if(si) - { - if(!si->checkattempt(millis)) continue; - millis = si->decodeping(millis); - } - else if(!searchlan || !lanpings.checkattempt(millis, false)) continue; - else - { - si = newserver(NULL, addr.port, addr.host); - millis = lanpings.decodeping(millis); - } - int rtt = clamp(totalmillis - millis, 0, min(servpingdecay, totalmillis)); - if(millis >= lastreset && rtt < servpingdecay) si->addping(rtt, millis); - si->protocol = getint(p); - si->numplayers = getint(p); - si->maxplayers = getint(p); - int numattr = getint(p); - si->attr.setsize(0); - loopj(numattr) { int attr = getint(p); if(p.overread()) break; si->attr.add(attr); } - getstring(text, p); - filtertext(si->map, text, false); - getstring(text, p); - filtertext(si->desc, text, true, true); - } -} - -void sortservers() -{ - servers.sort(serverinfo::compare); -} -COMMAND(sortservers, ""); - -VARP(autosortservers, 0, 1, 1); -VARP(autoupdateservers, 0, 1, 1); - -void refreshservers() -{ - static int lastrefresh = 0; - if(lastrefresh==totalmillis) return; - if(totalmillis - lastrefresh > 1000) - { - loopv(servers) servers[i]->reset(); - lastreset = totalmillis; - } - lastrefresh = totalmillis; - - checkresolver(); - checkpings(); - if(totalmillis - lastinfo >= servpingrate/(maxservpings ? max(1, (servers.length() + maxservpings - 1) / maxservpings) : 1)) pingservers(); - if(autosortservers) sortservers(); -} - -ICOMMAND(numservers, "", (), intret(servers.length())) - -#define GETSERVERINFO_(idx, si, body) \ - if(servers.inrange(idx)) \ - { \ - serverinfo &si = *servers[idx]; \ - body; \ - } -#define GETSERVERINFO(idx, si, body) GETSERVERINFO_(idx, si, if(si.valid()) { body; }) - -ICOMMAND(servinfovalid, "i", (int *i), GETSERVERINFO_(*i, si, intret(si.valid() ? 1 : 0))); -ICOMMAND(servinfodesc, "i", (int *i), - GETSERVERINFO_(*i, si, - { - const char *status = si.status(); - result(status ? status : si.desc); - })); -ICOMMAND(servinfoname, "i", (int *i), GETSERVERINFO_(*i, si, result(si.name))); -ICOMMAND(servinfoport, "i", (int *i), GETSERVERINFO_(*i, si, intret(si.address.port))); -ICOMMAND(servinfohaspassword, "i", (int *i), GETSERVERINFO_(*i, si, intret(si.password && si.password[0] ? 1 : 0))); -ICOMMAND(servinfokeep, "i", (int *i), GETSERVERINFO_(*i, si, intret(si.keep ? 1 : 0))); -ICOMMAND(servinfomap, "i", (int *i), GETSERVERINFO(*i, si, result(si.map))); -ICOMMAND(servinfoping, "i", (int *i), GETSERVERINFO(*i, si, intret(si.ping))); -ICOMMAND(servinfonumplayers, "i", (int *i), GETSERVERINFO(*i, si, intret(si.numplayers))); -ICOMMAND(servinfomaxplayers, "i", (int *i), GETSERVERINFO(*i, si, intret(si.maxplayers))); -ICOMMAND(servinfoplayers, "i", (int *i), - GETSERVERINFO(*i, si, - { - if(si.maxplayers <= 0) intret(si.numplayers); - else result(tempformatstring(si.numplayers >= si.maxplayers ? "\f3%d/%d" : "%d/%d", si.numplayers, si.maxplayers)); - })); -ICOMMAND(servinfoattr, "ii", (int *i, int *n), GETSERVERINFO(*i, si, { if(si.attr.inrange(*n)) intret(si.attr[*n]); })); - -ICOMMAND(connectservinfo, "is", (int *i, char *pw), GETSERVERINFO_(*i, si, connectserv(si.name, si.address.port, pw[0] ? pw : si.password))); - -servinfo *getservinfo(int i) -{ - return servers.inrange(i) && servers[i]->valid() ? servers[i] : NULL; -} - -void clearservers(bool full = false) -{ - resolverclear(); - if(full) servers.deletecontents(); - else loopvrev(servers) if(!servers[i]->keep) delete servers.remove(i); -} - -#define RETRIEVELIMIT 20000 - -void retrieveservers(vector &data) -{ - ENetSocket sock = connectmaster(true); - if(sock == ENET_SOCKET_NULL) return; - - extern char *mastername; - defformatstring(text, "retrieving servers from %s... (esc to abort)", mastername); - renderprogress(0, text); - - int starttime = SDL_GetTicks(), timeout = 0; - const char *req = "list\n"; - int reqlen = strlen(req); - ENetBuffer buf; - while(reqlen > 0) - { - enet_uint32 events = ENET_SOCKET_WAIT_SEND; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { - buf.data = (void *)req; - buf.dataLength = reqlen; - int sent = enet_socket_send(sock, NULL, &buf, 1); - if(sent < 0) break; - req += sent; - reqlen -= sent; - if(reqlen <= 0) break; - } - timeout = SDL_GetTicks() - starttime; - renderprogress(min(float(timeout)/RETRIEVELIMIT, 1.0f), text); - if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; - if(timeout > RETRIEVELIMIT) break; - } - - if(reqlen <= 0) for(;;) - { - enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { - if(data.length() >= data.capacity()) data.reserve(4096); - buf.data = data.getbuf() + data.length(); - buf.dataLength = data.capacity() - data.length(); - int recv = enet_socket_receive(sock, NULL, &buf, 1); - if(recv <= 0) break; - data.advance(recv); - } - timeout = SDL_GetTicks() - starttime; - renderprogress(min(float(timeout)/RETRIEVELIMIT, 1.0f), text); - if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; - if(timeout > RETRIEVELIMIT) break; - } - - if(data.length()) data.add('\0'); - enet_socket_destroy(sock); -} - -bool updatedservers = false; - -void updatefrommaster() -{ - vector data; - retrieveservers(data); - if(data.empty()) conoutf("master server not replying"); - else - { - clearservers(); - char *line = data.getbuf(); - while(char *end = (char *)memchr(line, '\n', data.length() - (line - data.getbuf()))) - { - *end = '\0'; - - const char *args = line; - while(args < end && !iscubespace(*args)) args++; - int cmdlen = args - line; - while(args < end && iscubespace(*args)) args++; - - if(matchstring(line, cmdlen, "addserver")) - { - string ip; - int port; - if(sscanf(args, "%100s %d", ip, &port) == 2) addserver(ip, port); - } - else if(matchstring(line, cmdlen, "echo")) conoutf("\f1%s", args); - - line = end + 1; - } - } - refreshservers(); - updatedservers = true; -} - -void initservers() -{ - if(autoupdateservers && !updatedservers) updatefrommaster(); -} - -ICOMMAND(addserver, "sis", (const char *name, int *port, const char *password), addserver(name, *port, password[0] ? password : NULL)); -ICOMMAND(keepserver, "sis", (const char *name, int *port, const char *password), addserver(name, *port, password[0] ? password : NULL, true)); -ICOMMAND(clearservers, "i", (int *full), clearservers(*full!=0)); -COMMAND(updatefrommaster, ""); -COMMAND(initservers, ""); -COMMAND(refreshservers, ""); - -void writeservercfg() -{ - if(!game::savedservers()) return; - stream *f = openutf8file(path(game::savedservers(), true), "w"); - if(!f) return; - int kept = 0; - loopv(servers) - { - serverinfo *s = servers[i]; - if(s->keep) - { - if(!kept) f->printf("// servers that should never be cleared from the server list\n\n"); - if(s->password) f->printf("keepserver %s %d %s\n", escapeid(s->name), s->address.port, escapestring(s->password)); - else f->printf("keepserver %s %d\n", escapeid(s->name), s->address.port); - kept++; - } - } - if(kept) f->printf("\n"); - f->printf("// servers connected to are added here automatically\n\n"); - loopv(servers) - { - serverinfo *s = servers[i]; - if(!s->keep) - { - if(s->password) f->printf("addserver %s %d %s\n", escapeid(s->name), s->address.port, escapestring(s->password)); - else f->printf("addserver %s %d\n", escapeid(s->name), s->address.port); - } - } - delete f; -} - diff --git a/src/game/game.hh b/src/game/game.hh index 7ecf3d4..98486d0 100644 --- a/src/game/game.hh +++ b/src/game/game.hh @@ -135,7 +135,6 @@ static const int msgsizes[] = // size inclusive message token, 0 f #define TESSERACT_SERVER_PORT 42000 #define TESSERACT_LANINFO_PORT 41998 -#define TESSERACT_MASTER_PORT 41999 #define PROTOCOL_VERSION 2 // bump when protocol changes #define MAXNAMELEN 15 diff --git a/src/game/server.cc b/src/game/server.cc index c57ca62..2e1db9c 100644 --- a/src/game/server.cc +++ b/src/game/server.cc @@ -15,8 +15,6 @@ namespace game const char *gameident() { return "Tesseract"; } } -extern ENetAddress masteraddress; - namespace server { struct server_entity // server side version of "entity" type @@ -971,18 +969,6 @@ namespace server return ci && ci->connected; } - void masterconnected() - { - } - - void masterdisconnected() - { - } - - void processmasterinput(const char *cmd, int cmdlen, const char *args) - { - } - void receivefile(int sender, uchar *data, int len) { clientinfo *ci = getinfo(sender); @@ -1397,8 +1383,6 @@ namespace server int laninfoport() { return TESSERACT_LANINFO_PORT; } int serverport() { return TESSERACT_SERVER_PORT; } - const char *defaultmaster() { return "master.tesseract.gg"; } - int masterport() { return TESSERACT_MASTER_PORT; } int numchannels() { return 3; } void serverinforeply(ucharbuf &req, ucharbuf &p) diff --git a/src/master/meson.build b/src/master/meson.build deleted file mode 100644 index 61ae08f..0000000 --- a/src/master/meson.build +++ /dev/null @@ -1,21 +0,0 @@ -client_src = [ - '../shared/crypto.cc', - '../shared/stream.cc', - '../shared/tools.cc', - '../engine/command.cc', - '../engine/master.cc' -] - -threads_dep = dependency('threads') -zlib_dep = dependency('zlib') - -executable('native_master', - client_src, - dependencies: [ - threads_dep, libenet, zlib_dep - ], - include_directories: octacore_includes, - cpp_args: ['-DSTANDALONE'], - install: true, - install_dir: join_paths(meson.source_root(), 'bin_unix') -) diff --git a/src/meson.build b/src/meson.build index 35e5054..8639064 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,5 +7,4 @@ add_global_arguments('-fsigned-char', language: 'cpp') subdir('enet') subdir('client') -subdir('server') -subdir('master') +subdir('server') \ No newline at end of file diff --git a/src/shared/iengine.hh b/src/shared/iengine.hh index 7478ea7..a8a71b4 100644 --- a/src/shared/iengine.hh +++ b/src/shared/iengine.hh @@ -485,8 +485,6 @@ extern void kicknonlocalclients(int reason = DISC_NONE); extern bool hasnonlocalclients(); extern bool haslocalclients(); extern void sendserverinforeply(ucharbuf &p); -extern bool requestmaster(const char *req); -extern bool requestmasterf(const char *fmt, ...) PRINTFARGS(1, 2); extern bool isdedicatedserver(); // serverbrowser diff --git a/src/shared/igame.hh b/src/shared/igame.hh index 073bebd..22c9b00 100644 --- a/src/shared/igame.hh +++ b/src/shared/igame.hh @@ -112,11 +112,6 @@ namespace server extern int protocolversion(); extern int laninfoport(); extern int serverport(); - extern const char *defaultmaster(); - extern int masterport(); - extern void processmasterinput(const char *cmd, int cmdlen, const char *args); - extern void masterconnected(); - extern void masterdisconnected(); extern bool ispaused(); extern int scaletime(int t); }