160 lines
2.8 KiB
C++
160 lines
2.8 KiB
C++
// 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<client *> 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()
|
|
{
|
|
}
|