summaryrefslogtreecommitdiff
path: root/src/engine/serverbrowser.cpp
diff options
context:
space:
mode:
authorxolatile2025-08-04 22:53:42 +0200
committerxolatile2025-08-04 22:53:42 +0200
commitd309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch)
tree999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/engine/serverbrowser.cpp
parent29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff)
downloadxolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz
xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst
Bunch of small changes...
Diffstat (limited to 'src/engine/serverbrowser.cpp')
-rw-r--r--src/engine/serverbrowser.cpp1160
1 files changed, 580 insertions, 580 deletions
diff --git a/src/engine/serverbrowser.cpp b/src/engine/serverbrowser.cpp
index ee36eea..85109bf 100644
--- a/src/engine/serverbrowser.cpp
+++ b/src/engine/serverbrowser.cpp
@@ -2,19 +2,19 @@
#include "engine.h"
-#define PROTOCOL_VERSION 260 // bump when protocol changes, dpulicate
+#define PROTOCOL_VERSION 260 // bump when protocol changes, dpulicate
struct resolverthread
{
- SDL_Thread *thread;
- const char *query;
- int starttime;
+ SDL_Thread *thread;
+ const char *query;
+ int starttime;
};
struct resolverresult
{
- const char *query;
- ENetAddress address;
+ const char *query;
+ ENetAddress address;
};
vector<resolverthread> resolverthreads;
@@ -28,234 +28,234 @@ SDL_cond *querycond, *resultcond;
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;
+ 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);
+ 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)
- {
+ SDL_LockMutex(resolvermutex);
+ if(rt.query)
+ {
#if SDL_VERSION_ATLEAST(2, 0, 2)
- SDL_DetachThread(rt.thread);
+ SDL_DetachThread(rt.thread);
#endif
- rt.thread = SDL_CreateThread(resolverloop, "resolver", &rt);
- }
- rt.query = NULL;
- rt.starttime = 0;
- SDL_UnlockMutex(resolvermutex);
+ 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);
+ 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();
+ if(resolverthreads.empty()) resolverinit();
- SDL_LockMutex(resolvermutex);
- resolverqueries.add(name);
- SDL_CondSignal(querycond);
- SDL_UnlockMutex(resolvermutex);
+ 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 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 && address->host != ENET_HOST_ANY;
+ 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 && address->host != ENET_HOST_ANY;
}
#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;
+ 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 };
+ enum { MAXATTEMPTS = 2 };
- int offset, attempts[MAXATTEMPTS];
+ int offset, attempts[MAXATTEMPTS];
- pingattempts() : offset(0) { clearattempts(); }
+ pingattempts() : offset(0) { clearattempts(); }
- void clearattempts() { memset(attempts, 0, sizeof(attempts)); }
+ void clearattempts() { memset(attempts, 0, sizeof(attempts)); }
- void setoffset() { offset = 1 + rnd(0xFFFFFF); }
+ void setoffset() { offset = 1 + rnd(0xFFFFFF); }
- int encodeping(int millis)
- {
- millis += offset;
- return millis ? millis : 1;
- }
+ int encodeping(int millis)
+ {
+ millis += offset;
+ return millis ? millis : 1;
+ }
- int decodeping(int val)
- {
- return val - offset;
- }
+ 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;
- }
+ 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;
- }
+ bool checkattempt(int val, bool del = true)
+ {
+ if(val) loopk(MAXATTEMPTS) if(attempts[k] == val)
+ {
+ if(del) attempts[k] = 0;
+ return true;
+ }
+ return false;
+ }
};
@@ -263,95 +263,95 @@ enum { UNRESOLVED = 0, RESOLVING, RESOLVED };
struct serverinfo : pingattempts
{
- enum
- {
- WAITING = INT_MAX,
-
- MAXPINGS = 3
- };
-
- string name, map, sdesc;
- int port, numplayers, resolved, ping, lastping, nextping;
- int pings[MAXPINGS];
- vector<int> attr;
- ENetAddress address;
- bool keep;
- const char *password;
-
- serverinfo()
- : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL)
- {
- name[0] = map[0] = sdesc[0] = '\0';
- clearpings();
- setoffset();
- }
-
- ~serverinfo()
- {
- DELETEA(password);
- }
-
- void clearpings()
- {
- ping = WAITING;
- loopk(MAXPINGS) pings[k] = WAITING;
- nextping = 0;
- lastping = -1;
- clearattempts();
- }
-
- void cleanup()
- {
- clearpings();
- attr.setsize(0);
- numplayers = 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();
- }
-
- static bool compare(serverinfo *a, serverinfo *b)
- {
- bool ac = (a->attr.length() != 0) && (a->attr[0]==PROTOCOL_VERSION);
- bool bc = (b->attr.length() != 0) && (b->attr[0]==PROTOCOL_VERSION);
- if(ac > bc) return true;
- if(bc > ac) 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->port < b->port) return true;
- if(a->port > b->port) return false;
- return false;
- }
+ enum
+ {
+ WAITING = INT_MAX,
+
+ MAXPINGS = 3
+ };
+
+ string name, map, sdesc;
+ int port, numplayers, resolved, ping, lastping, nextping;
+ int pings[MAXPINGS];
+ vector<int> attr;
+ ENetAddress address;
+ bool keep;
+ const char *password;
+
+ serverinfo()
+ : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL)
+ {
+ name[0] = map[0] = sdesc[0] = '\0';
+ clearpings();
+ setoffset();
+ }
+
+ ~serverinfo()
+ {
+ DELETEA(password);
+ }
+
+ void clearpings()
+ {
+ ping = WAITING;
+ loopk(MAXPINGS) pings[k] = WAITING;
+ nextping = 0;
+ lastping = -1;
+ clearattempts();
+ }
+
+ void cleanup()
+ {
+ clearpings();
+ attr.setsize(0);
+ numplayers = 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();
+ }
+
+ static bool compare(serverinfo *a, serverinfo *b)
+ {
+ bool ac = (a->attr.length() != 0) && (a->attr[0]==PROTOCOL_VERSION);
+ bool bc = (b->attr.length() != 0) && (b->attr[0]==PROTOCOL_VERSION);
+ if(ac > bc) return true;
+ if(bc > ac) 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->port < b->port) return true;
+ if(a->port > b->port) return false;
+ return false;
+ }
};
vector<serverinfo *> servers;
@@ -360,44 +360,44 @@ 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 = server::serverinfoport(port);
- if(ip!=ENET_HOST_ANY) si->resolved = RESOLVED;
+ serverinfo *si = new serverinfo;
+ si->address.host = ip;
+ si->address.port = server::serverinfoport(port);
+ if(ip!=ENET_HOST_ANY) si->resolved = RESOLVED;
- si->port = port;
- 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;
+ si->port = port;
+ 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);
+ servers.add(si);
- return 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->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;
+ if(port <= 0) port = server::serverport();
+ loopv(servers)
+ {
+ serverinfo *s = servers[i];
+ if(strcmp(s->name, name) || s->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);
@@ -409,134 +409,134 @@ pingattempts lanpings;
template<size_t N> static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a)
{
- ucharbuf p(ping, N);
- putint(p, a.addattempt(totalmillis));
- buf.data = ping;
- buf.dataLength = p.length();
+ ucharbuf p(ping, N);
+ 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;
+ 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;
- }
- }
- }
+ 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, server::serverport(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->numplayers = 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->sdesc, text, true, true);
- }
+ 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, server::serverport(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->numplayers = 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->sdesc, text, true, true);
+ }
}
void sortservers()
{
- servers.sort(serverinfo::compare);
+ servers.sort(serverinfo::compare);
}
COMMAND(sortservers, "");
@@ -545,173 +545,173 @@ 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();
+ 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();
}
serverinfo *selectedserver = NULL;
const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax)
{
- refreshservers();
- if(servers.empty())
- {
- if(header) execute(header);
- return NULL;
- }
- serverinfo *sc = NULL;
- for(int start = 0; start < servers.length();)
- {
- if(start > 0) cgui->tab();
- if(header) execute(header);
- int end = servers.length();
- cgui->pushlist();
- loopi(10)
- {
- if(!game::serverinfostartcolumn(cgui, i)) break;
- for(int j = start; j < end; j++)
- {
- if(!i && j+1 - start >= pagemin && (j+1 - start >= pagemax || cgui->shouldtab())) { end = j; break; }
- serverinfo &si = *servers[j];
- const char *sdesc = si.sdesc;
- if(si.address.host == ENET_HOST_ANY) sdesc = "[unknown host]";
- else if(si.ping == serverinfo::WAITING) sdesc = "[waiting for response]";
- if(game::serverinfoentry(cgui, i, si.name, si.port, sdesc, si.map, sdesc == si.sdesc ? si.ping : -1, si.attr, si.numplayers))
- sc = &si;
- }
- game::serverinfoendcolumn(cgui, i);
- }
- cgui->poplist();
- start = end;
- }
- if(selectedserver || !sc) return NULL;
- selectedserver = sc;
- return "connectselected";
+ refreshservers();
+ if(servers.empty())
+ {
+ if(header) execute(header);
+ return NULL;
+ }
+ serverinfo *sc = NULL;
+ for(int start = 0; start < servers.length();)
+ {
+ if(start > 0) cgui->tab();
+ if(header) execute(header);
+ int end = servers.length();
+ cgui->pushlist();
+ loopi(10)
+ {
+ if(!game::serverinfostartcolumn(cgui, i)) break;
+ for(int j = start; j < end; j++)
+ {
+ if(!i && j+1 - start >= pagemin && (j+1 - start >= pagemax || cgui->shouldtab())) { end = j; break; }
+ serverinfo &si = *servers[j];
+ const char *sdesc = si.sdesc;
+ if(si.address.host == ENET_HOST_ANY) sdesc = "[unknown host]";
+ else if(si.ping == serverinfo::WAITING) sdesc = "[waiting for response]";
+ if(game::serverinfoentry(cgui, i, si.name, si.port, sdesc, si.map, sdesc == si.sdesc ? si.ping : -1, si.attr, si.numplayers))
+ sc = &si;
+ }
+ game::serverinfoendcolumn(cgui, i);
+ }
+ cgui->poplist();
+ start = end;
+ }
+ if(selectedserver || !sc) return NULL;
+ selectedserver = sc;
+ return "connectselected";
}
void connectselected()
{
- if(!selectedserver) return;
- connectserv(selectedserver->name, selectedserver->port, selectedserver->password);
- selectedserver = NULL;
+ if(!selectedserver) return;
+ connectserv(selectedserver->name, selectedserver->port, selectedserver->password);
+ selectedserver = NULL;
}
COMMAND(connectselected, "");
void clearservers(bool full = false)
{
- resolverclear();
- if(full) servers.deletecontents();
- else loopvrev(servers) if(!servers[i]->keep) delete servers.remove(i);
- selectedserver = NULL;
+ resolverclear();
+ if(full) servers.deletecontents();
+ else loopvrev(servers) if(!servers[i]->keep) delete servers.remove(i);
+ selectedserver = NULL;
}
#define RETRIEVELIMIT 20000
void retrieveservers(vector<char> &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);
+ 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<char> data;
- retrieveservers(data);
- if(data.empty()) conoutf(CON_ERROR, "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;
+ vector<char> data;
+ retrieveservers(data);
+ if(data.empty()) conoutf(CON_ERROR, "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()
{
- selectedserver = NULL;
- if(autoupdateservers && !updatedservers) updatefrommaster();
+ selectedserver = NULL;
+ if(autoupdateservers && !updatedservers) updatefrommaster();
}
ICOMMAND(addserver, "sis", (const char *name, int *port, const char *password), addserver(name, *port, password[0] ? password : NULL));
@@ -722,32 +722,32 @@ COMMAND(initservers, "");
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->port, escapestring(s->password));
- else f->printf("keepserver %s %d\n", escapeid(s->name), s->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->port, escapestring(s->password));
- else f->printf("addserver %s %d\n", escapeid(s->name), s->port);
- }
- }
- delete f;
+ 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->port, escapestring(s->password));
+ else f->printf("keepserver %s %d\n", escapeid(s->name), s->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->port, escapestring(s->password));
+ else f->printf("addserver %s %d\n", escapeid(s->name), s->port);
+ }
+ }
+ delete f;
}