// server.cpp: little more than enhanced multicaster // runs dedicated or as client coroutine #include "engine.hh" #define LOGSTRLEN 512 static FILE *logfile = NULL; void closelogfile() { if(logfile) { fclose(logfile); logfile = NULL; } } FILE *getlogfile() { #ifdef WIN32 return logfile; #else return logfile ? logfile : stdout; #endif } void setlogfile(const char *fname) { closelogfile(); if(fname && fname[0]) { fname = findfile(fname, "w"); if(fname) logfile = fopen(fname, "w"); } FILE *f = getlogfile(); if(f) setvbuf(f, NULL, _IOLBF, BUFSIZ); } void logoutf(const char *fmt, ...) { va_list args; va_start(args, fmt); logoutfv(fmt, args); va_end(args); } static void writelog(FILE *file, const char *buf) { static uchar ubuf[512]; size_t len = strlen(buf), carry = 0; while(carry < len) { size_t numu = encodeutf8(ubuf, sizeof(ubuf)-1, &((const uchar *)buf)[carry], len - carry, &carry); if(carry >= len) ubuf[numu++] = '\n'; fwrite(ubuf, 1, numu, file); } } static void writelogv(FILE *file, const char *fmt, va_list args) { static char buf[LOGSTRLEN]; vformatstring(buf, fmt, args, sizeof(buf)); writelog(file, buf); } #define DEFAULTCLIENTS 8 enum { ST_EMPTY, ST_LOCAL, ST_TCPIP }; struct client // server side version of "dynent" type { int type; int num; string hostname; void *info; }; vector clients; int laststatus = 0; int localclients = 0; bool hasnonlocalclients() { return false; } bool haslocalclients() { return localclients!=0; } client &addclient(int type) { client *c = NULL; loopv(clients) if(clients[i]->type==ST_EMPTY) { c = clients[i]; break; } if(!c) { c = new client; c->num = clients.length(); clients.add(c); } c->type = type; switch(type) { case ST_LOCAL: localclients++; break; } return *c; } void delclient(client *c) { if(!c) return; switch(c->type) { case ST_LOCAL: localclients--; break; case ST_EMPTY: return; } c->type = ST_EMPTY; } void cleanupserver() { } void updatetime() { } void localdisconnect(bool cleanup) { bool disconnected = false; loopv(clients) if(clients[i]->type==ST_LOCAL) { delclient(clients[i]); disconnected = true; } if(!disconnected) return; game::gamedisconnect(cleanup); mainmenu = 1; } void localconnect() { if(initing) return; client &c = addclient(ST_LOCAL); copystring(c.hostname, "local"); game::gameconnect(false); } void logoutfv(const char *fmt, va_list args) { FILE *f = getlogfile(); if(f) writelogv(f, fmt, args); } void initserver() { }