Convert to ObjC++
FossilOrigin-Name: 7c2704b3d77d6e63d960e315bfb601fddbf6fce538b7c5db6da664e04fbce4c2
This commit is contained in:
parent
04fa50a332
commit
133382170f
34 changed files with 87 additions and 79 deletions
|
@ -1,330 +0,0 @@
|
|||
// serverbrowser.cpp: eihrul's concurrent resolver, and server browser window
|
||||
// management
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "cube.h"
|
||||
|
||||
struct resolverthread {
|
||||
SDL_Thread *thread;
|
||||
char *query;
|
||||
int starttime;
|
||||
};
|
||||
|
||||
struct resolverresult {
|
||||
char *query;
|
||||
ENetAddress address;
|
||||
};
|
||||
|
||||
vector<resolverthread> resolverthreads;
|
||||
vector<char *> resolverqueries;
|
||||
vector<resolverresult> resolverresults;
|
||||
SDL_mutex *resolvermutex;
|
||||
SDL_sem *resolversem;
|
||||
int resolverlimit = 1000;
|
||||
|
||||
int
|
||||
resolverloop(void *data)
|
||||
{
|
||||
resolverthread *rt = (resolverthread *)data;
|
||||
for (;;) {
|
||||
SDL_SemWait(resolversem);
|
||||
SDL_LockMutex(resolvermutex);
|
||||
if (resolverqueries.empty()) {
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
continue;
|
||||
}
|
||||
rt->query = resolverqueries.pop();
|
||||
rt->starttime = lastmillis;
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
ENetAddress address = {ENET_HOST_ANY, CUBE_SERVINFO_PORT};
|
||||
enet_address_set_host(&address, rt->query);
|
||||
SDL_LockMutex(resolvermutex);
|
||||
resolverresult &rr = resolverresults.add();
|
||||
rr.query = rt->query;
|
||||
rr.address = address;
|
||||
rt->query = NULL;
|
||||
rt->starttime = 0;
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
void
|
||||
resolverinit(int threads, int limit)
|
||||
{
|
||||
resolverlimit = limit;
|
||||
resolversem = SDL_CreateSemaphore(0);
|
||||
resolvermutex = SDL_CreateMutex();
|
||||
|
||||
while (threads > 0) {
|
||||
resolverthread &rt = resolverthreads.add();
|
||||
rt.query = NULL;
|
||||
rt.starttime = 0;
|
||||
rt.thread = SDL_CreateThread(resolverloop, &rt);
|
||||
--threads;
|
||||
};
|
||||
};
|
||||
|
||||
void
|
||||
resolverstop(resolverthread &rt, bool restart)
|
||||
{
|
||||
SDL_LockMutex(resolvermutex);
|
||||
SDL_KillThread(rt.thread);
|
||||
rt.query = NULL;
|
||||
rt.starttime = 0;
|
||||
rt.thread = NULL;
|
||||
if (restart)
|
||||
rt.thread = SDL_CreateThread(resolverloop, &rt);
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
};
|
||||
|
||||
void
|
||||
resolverclear()
|
||||
{
|
||||
SDL_LockMutex(resolvermutex);
|
||||
resolverqueries.setsize(0);
|
||||
resolverresults.setsize(0);
|
||||
while (SDL_SemTryWait(resolversem) == 0)
|
||||
;
|
||||
loopv(resolverthreads)
|
||||
{
|
||||
resolverthread &rt = resolverthreads[i];
|
||||
resolverstop(rt, true);
|
||||
};
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
};
|
||||
|
||||
void
|
||||
resolverquery(char *name)
|
||||
{
|
||||
SDL_LockMutex(resolvermutex);
|
||||
resolverqueries.add(name);
|
||||
SDL_SemPost(resolversem);
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
};
|
||||
|
||||
bool
|
||||
resolvercheck(char **name, ENetAddress *address)
|
||||
{
|
||||
SDL_LockMutex(resolvermutex);
|
||||
if (!resolverresults.empty()) {
|
||||
resolverresult &rr = resolverresults.pop();
|
||||
*name = rr.query;
|
||||
*address = rr.address;
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
return true;
|
||||
}
|
||||
loopv(resolverthreads)
|
||||
{
|
||||
resolverthread &rt = resolverthreads[i];
|
||||
if (rt.query) {
|
||||
if (lastmillis - rt.starttime > resolverlimit) {
|
||||
resolverstop(rt, true);
|
||||
*name = rt.query;
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
return true;
|
||||
};
|
||||
};
|
||||
};
|
||||
SDL_UnlockMutex(resolvermutex);
|
||||
return false;
|
||||
};
|
||||
|
||||
struct serverinfo {
|
||||
string name;
|
||||
string full;
|
||||
string map;
|
||||
string sdesc;
|
||||
int mode, numplayers, ping, protocol, minremain;
|
||||
ENetAddress address;
|
||||
};
|
||||
|
||||
vector<serverinfo> servers;
|
||||
ENetSocket pingsock = ENET_SOCKET_NULL;
|
||||
int lastinfo = 0;
|
||||
|
||||
char *
|
||||
getservername(int n)
|
||||
{
|
||||
return servers[n].name;
|
||||
};
|
||||
|
||||
void
|
||||
addserver(char *servername)
|
||||
{
|
||||
loopv(servers) if (strcmp(servers[i].name, servername) == 0) return;
|
||||
serverinfo &si = servers.insert(0, serverinfo());
|
||||
strcpy_s(si.name, servername);
|
||||
si.full[0] = 0;
|
||||
si.mode = 0;
|
||||
si.numplayers = 0;
|
||||
si.ping = 9999;
|
||||
si.protocol = 0;
|
||||
si.minremain = 0;
|
||||
si.map[0] = 0;
|
||||
si.sdesc[0] = 0;
|
||||
si.address.host = ENET_HOST_ANY;
|
||||
si.address.port = CUBE_SERVINFO_PORT;
|
||||
};
|
||||
|
||||
void
|
||||
pingservers()
|
||||
{
|
||||
ENetBuffer buf;
|
||||
uchar ping[MAXTRANS];
|
||||
uchar *p;
|
||||
loopv(servers)
|
||||
{
|
||||
serverinfo &si = servers[i];
|
||||
if (si.address.host == ENET_HOST_ANY)
|
||||
continue;
|
||||
p = ping;
|
||||
putint(p, lastmillis);
|
||||
buf.data = ping;
|
||||
buf.dataLength = p - ping;
|
||||
enet_socket_send(pingsock, &si.address, &buf, 1);
|
||||
};
|
||||
lastinfo = lastmillis;
|
||||
};
|
||||
|
||||
void
|
||||
checkresolver()
|
||||
{
|
||||
char *name = NULL;
|
||||
ENetAddress addr = {ENET_HOST_ANY, CUBE_SERVINFO_PORT};
|
||||
while (resolvercheck(&name, &addr)) {
|
||||
if (addr.host == ENET_HOST_ANY)
|
||||
continue;
|
||||
loopv(servers)
|
||||
{
|
||||
serverinfo &si = servers[i];
|
||||
if (name == si.name) {
|
||||
si.address = addr;
|
||||
addr.host = ENET_HOST_ANY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkpings()
|
||||
{
|
||||
enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE;
|
||||
ENetBuffer buf;
|
||||
ENetAddress addr;
|
||||
uchar ping[MAXTRANS], *p;
|
||||
char text[MAXTRANS];
|
||||
buf.data = ping;
|
||||
buf.dataLength = sizeof(ping);
|
||||
while (enet_socket_wait(pingsock, &events, 0) >= 0 && events) {
|
||||
if (enet_socket_receive(pingsock, &addr, &buf, 1) <= 0)
|
||||
return;
|
||||
loopv(servers)
|
||||
{
|
||||
serverinfo &si = servers[i];
|
||||
if (addr.host == si.address.host) {
|
||||
p = ping;
|
||||
si.ping = lastmillis - getint(p);
|
||||
si.protocol = getint(p);
|
||||
if (si.protocol != PROTOCOL_VERSION)
|
||||
si.ping = 9998;
|
||||
si.mode = getint(p);
|
||||
si.numplayers = getint(p);
|
||||
si.minremain = getint(p);
|
||||
sgetstr();
|
||||
strcpy_s(si.map, text);
|
||||
sgetstr();
|
||||
strcpy_s(si.sdesc, text);
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
int
|
||||
sicompare(const serverinfo *a, const serverinfo *b)
|
||||
{
|
||||
return a->ping > b->ping
|
||||
? 1
|
||||
: (a->ping < b->ping ? -1 : strcmp(a->name, b->name));
|
||||
};
|
||||
|
||||
void
|
||||
refreshservers()
|
||||
{
|
||||
checkresolver();
|
||||
checkpings();
|
||||
if (lastmillis - lastinfo >= 5000)
|
||||
pingservers();
|
||||
servers.sort((void *)sicompare);
|
||||
int maxmenu = 16;
|
||||
loopv(servers)
|
||||
{
|
||||
serverinfo &si = servers[i];
|
||||
if (si.address.host != ENET_HOST_ANY && si.ping != 9999) {
|
||||
if (si.protocol != PROTOCOL_VERSION)
|
||||
sprintf_s(si.full)(
|
||||
"%s [different cube protocol]", si.name);
|
||||
else
|
||||
sprintf_s(si.full)("%d\t%d\t%s, %s: %s %s",
|
||||
si.ping, si.numplayers,
|
||||
si.map[0] ? si.map : "[unknown]",
|
||||
modestr(si.mode), si.name, si.sdesc);
|
||||
} else {
|
||||
sprintf_s(si.full)(
|
||||
si.address.host != ENET_HOST_ANY
|
||||
? "%s [waiting for server response]"
|
||||
: "%s [unknown host]\t",
|
||||
si.name);
|
||||
}
|
||||
si.full[50] = 0; // cut off too long server descriptions
|
||||
menumanual(1, i, si.full);
|
||||
if (!--maxmenu)
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
void
|
||||
servermenu()
|
||||
{
|
||||
if (pingsock == ENET_SOCKET_NULL) {
|
||||
pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, NULL);
|
||||
resolverinit(1, 1000);
|
||||
};
|
||||
resolverclear();
|
||||
loopv(servers) resolverquery(servers[i].name);
|
||||
refreshservers();
|
||||
menuset(1);
|
||||
};
|
||||
|
||||
void
|
||||
updatefrommaster()
|
||||
{
|
||||
const int MAXUPD = 32000;
|
||||
uchar buf[MAXUPD];
|
||||
uchar *reply = retrieveservers(buf, MAXUPD);
|
||||
if (!*reply || strstr((char *)reply, "<html>") ||
|
||||
strstr((char *)reply, "<HTML>"))
|
||||
conoutf("master server not replying");
|
||||
else {
|
||||
servers.setsize(0);
|
||||
execute((char *)reply);
|
||||
};
|
||||
servermenu();
|
||||
};
|
||||
|
||||
COMMAND(addserver, ARG_1STR);
|
||||
COMMAND(servermenu, ARG_NONE);
|
||||
COMMAND(updatefrommaster, ARG_NONE);
|
||||
|
||||
void
|
||||
writeservercfg()
|
||||
{
|
||||
FILE *f = fopen("servers.cfg", "w");
|
||||
if (!f)
|
||||
return;
|
||||
fprintf(f, "// servers connected to are added here automatically\n\n");
|
||||
loopvrev(servers) fprintf(f, "addserver %s\n", servers[i].name);
|
||||
fclose(f);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue