fix parsing of commandline switches for servers
also: * -Y now sets the private key for the server * -m without argument uses default masterserver URL * servers run LAN-only by default (set ms URL and private key to register with the master) * use generic locale "POSIX"
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
// -f // port, 1..65534, default 28763
|
||||
// -c // max client number, 1..16, default 6
|
||||
// -D // number of demos to keep in RAM, default 5
|
||||
// -Y // 32-byte private server key (you should maybe include that from another config file and remove it from the server after startup)
|
||||
// -m // masterserver URL (no parameter uses default URL), if not set, the server will be LAN-only
|
||||
|
||||
// the switches o, n, n1 and n2 support coloring and character escaping; 'o' also supports escaped newlines
|
||||
// the available colors are: 0: green, 1: blue, 2: yellow, 3: red, 4: gray, 5: white, 6: dark brown, 7: dark red
|
||||
@@ -95,5 +97,4 @@
|
||||
|
||||
// -u // uprate
|
||||
// -i // ip, only for machines with multiple network interfaces
|
||||
// -m // masterserver URL (exception: use "-m localhost", if you don't want AC to register at a masterserver at all)
|
||||
|
||||
|
||||
@@ -45,15 +45,12 @@ void setskin(playerent *pl, int skin, int team)
|
||||
pl->setskin(team, skin);
|
||||
}
|
||||
|
||||
extern char *global_name;
|
||||
|
||||
bool duplicatename(playerent *d, char *name = NULL)
|
||||
{
|
||||
if(!name) name = d->name;
|
||||
if(d!=player1 && !strcmp(name, player1->name) && !watchingdemo) return true;
|
||||
if(!strcmp(name, "you")) return true;
|
||||
loopv(players) if(players[i] && d!=players[i] && !strcmp(name, players[i]->name)) return true;
|
||||
global_name = player1->name; // this certainly is not the best place to put this
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -1012,6 +1012,7 @@ int main(int argc, char **argv)
|
||||
char *initscript = NULL;
|
||||
char *initdemo = NULL;
|
||||
|
||||
setlocale(LC_ALL, "POSIX");
|
||||
if(bootclientlog) cvecprintf(*bootclientlog, "######## start logging: %s\n", timestring(true));
|
||||
|
||||
const char *initmap = rndmapname();
|
||||
@@ -1134,8 +1135,8 @@ int main(int argc, char **argv)
|
||||
if(enet_initialize()<0) fatal("Unable to initialise network module");
|
||||
|
||||
if (!dedicated) initclient();
|
||||
//FIXME the server executed in this way does not catch the SIGTERM or ^C
|
||||
initserver(dedicated,argc,argv); // never returns if dedicated
|
||||
|
||||
initserver(dedicated); // never returns if dedicated
|
||||
|
||||
initlog("world (" STRINGIFY(AC_VERSION) ")");
|
||||
empty_world(7, true);
|
||||
@@ -1158,10 +1159,6 @@ int main(int argc, char **argv)
|
||||
int usedcolorbits = 0, useddepthbits = 0, usedfsaa = 0;
|
||||
setupscreen(usedcolorbits, useddepthbits, usedfsaa);
|
||||
|
||||
// no more TTF ATM.
|
||||
//initlog("font");
|
||||
//initfont();
|
||||
|
||||
initlog("video: misc");
|
||||
SDL_WM_SetCaption("AssaultCube", NULL);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#ifdef __GNUC__
|
||||
#include <new>
|
||||
|
||||
+22
-5
@@ -958,6 +958,9 @@ extern void tigerhash(uchar *hash, const uchar *msg, int len);
|
||||
extern void *tigerhash_init(uchar *hash);
|
||||
extern void tigerhash_add(uchar *hash, const void *msg, int len, void *state);
|
||||
extern void tigerhash_finish(uchar *hash, void *state);
|
||||
extern const char *bin2hex(char *d, const uchar *s, int len);
|
||||
extern int hex2bin(uchar *d, const char *s, int maxlen);
|
||||
extern void ed25519_pubkey_from_private(uchar *pubkey, const uchar *privkey);
|
||||
extern void loadcertdir(); // load all certs in "config/certs"
|
||||
#if 0
|
||||
// crypto // for AUTH
|
||||
@@ -1027,7 +1030,7 @@ extern const char *modestr(int n, bool acronyms = false);
|
||||
extern const char *voteerrorstr(int n);
|
||||
extern const char *mmfullname(int n);
|
||||
extern void fatal(const char *s, ...) PRINTFARGS(1, 2);
|
||||
extern void initserver(bool dedicated, int argc = 0, char **argv = NULL);
|
||||
extern void initserver(bool dedicated);
|
||||
extern void cleanupserver();
|
||||
extern void localconnect();
|
||||
extern void localdisconnect();
|
||||
@@ -1067,7 +1070,7 @@ extern int masterport;
|
||||
extern ENetSocket connectmaster();
|
||||
extern void serverms(int mode, int numplayers, int minremain, char *smapname, int millis, const ENetAddress &localaddr, int *mnum, int *msend, int *mrec, int *cnum, int *csend, int *crec, int protocol_version, const char *servdesccur, int _interm);
|
||||
extern const char *genpwdhash(const char *name, const char *pwd, int salt);
|
||||
extern void servermsinit(const char *master, const char *ip, int serverport, bool listen);
|
||||
extern void servermsinit(bool listen);
|
||||
extern bool serverpickup(int i, int sender);
|
||||
extern bool valid_client(int cn);
|
||||
extern void extinfo_cnbuf(ucharbuf &p, int cn);
|
||||
@@ -1127,7 +1130,8 @@ struct serverconfigfile
|
||||
struct servercommandline
|
||||
{
|
||||
int uprate, serverport, syslogfacility, filethres, syslogthres, maxdemos, maxclients, kickthreshold, banthreshold, verbose, incoming_limit, afk_limit, ban_time, demotimelocal;
|
||||
const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath, *motdpath, *forbidden, *demofilenameformat, *demotimestampformat;
|
||||
const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath, *motdpath, *forbidden, *demofilenameformat, *demotimestampformat, *service;
|
||||
uchar *ssk;
|
||||
bool logtimestamp, demo_interm, loggamestatus;
|
||||
string motd, servdesc_full, servdesc_pre, servdesc_suf, voteperm, mapperm;
|
||||
int clfilenesting;
|
||||
@@ -1137,7 +1141,8 @@ struct servercommandline
|
||||
maxclients(DEFAULTCLIENTS), kickthreshold(-5), banthreshold(-6), verbose(0), incoming_limit(10), afk_limit(45000), ban_time(20*60*1000), demotimelocal(0),
|
||||
ip(""), master(NULL), logident(""), serverpassword(""), adminpasswd(""), demopath(""),
|
||||
maprot("config/maprot.cfg"), pwdfile("config/serverpwd.cfg"), blfile("config/serverblacklist.cfg"), nbfile("config/nicknameblacklist.cfg"),
|
||||
infopath("config/serverinfo"), motdpath("config/motd"), forbidden("config/forbidden.cfg"),
|
||||
infopath("config/serverinfo"), motdpath("config/motd"), forbidden("config/forbidden.cfg"), service(NULL),
|
||||
ssk(NULL),
|
||||
logtimestamp(false), demo_interm(false), loggamestatus(true),
|
||||
clfilenesting(0)
|
||||
{
|
||||
@@ -1154,7 +1159,18 @@ struct servercommandline
|
||||
int ai = atoi(a);
|
||||
// client: dtwhzbsave
|
||||
switch(arg[1])
|
||||
{ // todo: gjlqEGHJQUYZ
|
||||
{ // todo: gjlqEGHJQU
|
||||
case 'Y': // private server key
|
||||
{
|
||||
uchar temp[64];
|
||||
if(hex2bin(temp, a, 32) == 32)
|
||||
{
|
||||
if(!ssk) ssk = new uchar[64];
|
||||
memcpy(ssk, temp, 32);
|
||||
ed25519_pubkey_from_private(ssk + 32, ssk);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-':
|
||||
if(!strncmp(arg, "--demofilenameformat=", 21))
|
||||
{
|
||||
@@ -1244,6 +1260,7 @@ struct servercommandline
|
||||
case 'P': concatstring(voteperm, a); break;
|
||||
case 'M': concatstring(mapperm, a); break;
|
||||
case 'Z': if(ai >= 0) incoming_limit = ai; break;
|
||||
case 'S': service = a; break;
|
||||
case 'V': verbose++; break;
|
||||
case 'C': if(*a && clfilenesting < 3)
|
||||
{
|
||||
|
||||
+24
-44
@@ -99,7 +99,6 @@ vector<demofile> demofiles;
|
||||
long int incoming_size = 0;
|
||||
|
||||
// cmod
|
||||
char *global_name;
|
||||
int totalclients = 0;
|
||||
int cn2boot;
|
||||
int servertime = 0, serverlagged = 0;
|
||||
@@ -4304,60 +4303,25 @@ void processmasterinput(const char *cmd, int cmdlen, const char *args)
|
||||
else if(sscanf(cmd, "addgban %s", val) == 1) addgban(val);
|
||||
}
|
||||
|
||||
string server_name = "unarmed server";
|
||||
|
||||
void quitproc(int param)
|
||||
{
|
||||
// this triggers any "atexit"-calls:
|
||||
exit(param == 2 ? EXIT_SUCCESS : EXIT_FAILURE); // 3 is the only reply on Win32 apparently, SIGINT == 2 == Ctrl-C
|
||||
}
|
||||
|
||||
void initserver(bool dedicated, int argc, char **argv)
|
||||
void initserver(bool dedicated)
|
||||
{
|
||||
const char *service = NULL;
|
||||
|
||||
for(int i = 1; i<argc; i++)
|
||||
{
|
||||
if(!scl.checkarg(argv[i]))
|
||||
{
|
||||
char *a = &argv[i][2];
|
||||
if(!scl.checkarg(argv[i]) && argv[i][0]=='-') switch(argv[i][1])
|
||||
{
|
||||
case '-': break;
|
||||
case 'S': service = a; break;
|
||||
default: break; /*printf("WARNING: unknown commandline option\n");*/ // less warnings - 2011feb05:ft: who disabled this - I think this should be on - more warnings == more clarity
|
||||
}
|
||||
else if (strncmp(argv[i], "assaultcube://", 13)) printf("WARNING: unknown commandline argument\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(service && !svcctrl)
|
||||
{
|
||||
#ifdef WIN32
|
||||
svcctrl = new winservice(service);
|
||||
#endif
|
||||
if(svcctrl)
|
||||
{
|
||||
svcctrl->argc = argc; svcctrl->argv = argv;
|
||||
svcctrl->start();
|
||||
}
|
||||
}
|
||||
|
||||
if ( strlen(scl.servdesc_full) ) global_name = scl.servdesc_full;
|
||||
else global_name = server_name;
|
||||
|
||||
sg->smapname[0] = '\0';
|
||||
|
||||
// start logging
|
||||
string identity;
|
||||
if(scl.logident[0]) filtertext(identity, scl.logident, FTXT__LOGIDENT);
|
||||
else formatstring(identity)("%s#%d", scl.ip[0] ? scl.ip : "local", scl.serverport);
|
||||
int conthres = scl.verbose > 1 ? ACLOG_DEBUG : (scl.verbose ? ACLOG_VERBOSE : ACLOG_INFO);
|
||||
if(dedicated && !initlogging(identity, scl.syslogfacility, conthres, scl.filethres, scl.syslogthres, scl.logtimestamp))
|
||||
printf("WARNING: logging not started!\n");
|
||||
if(dedicated && !initlogging(identity, scl.syslogfacility, conthres, scl.filethres, scl.syslogthres, scl.logtimestamp)) printf("WARNING: logging not started!\n");
|
||||
logline(ACLOG_INFO, "logging local AssaultCube server (version %d, protocol %d/%d) now..", AC_VERSION, SERVER_PROTOCOL_VERSION, EXT_VERSION);
|
||||
|
||||
copystring(sg->servdesc_current, scl.servdesc_full);
|
||||
servermsinit(scl.master ? scl.master : AC_MASTER_URI, scl.ip, CUBE_SERVINFO_PORT(scl.serverport), dedicated);
|
||||
servermsinit(dedicated);
|
||||
|
||||
if((isdedicated = dedicated))
|
||||
{
|
||||
@@ -4367,6 +4331,8 @@ void initserver(bool dedicated, int argc, char **argv)
|
||||
if(!serverhost) fatal("could not create server host");
|
||||
loopi(scl.maxclients) serverhost->peers[i].data = (void *)-1;
|
||||
|
||||
string pubkey;
|
||||
if(scl.ssk) logline(ACLOG_VERBOSE,"server public key: %s", bin2hex(pubkey, scl.ssk + 32, 32));
|
||||
maprot.init(scl.maprot);
|
||||
// maprot.next(false, true); // ensure minimum maprot length of '1'
|
||||
passwords.init(scl.pwdfile, scl.adminpasswd);
|
||||
@@ -4446,13 +4412,27 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for(int i = 1; i<argc; i++)
|
||||
setlocale(LC_ALL, "POSIX");
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strncmp(argv[i],"--wizard",8)) return wizardmain(argc, argv);
|
||||
if(!scl.checkarg(argv[i]))
|
||||
{
|
||||
if (!strncmp(argv[i],"--wizard",8)) return wizardmain(argc, argv);
|
||||
else printf("WARNING: unknown commandline argument \"%s\"\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(enet_initialize()<0) fatal("Unable to initialise network module");
|
||||
initserver(true, argc, argv);
|
||||
if(scl.service && !svcctrl)
|
||||
{
|
||||
#ifdef WIN32
|
||||
svcctrl = new winservice(scl.service, argc, argv);
|
||||
#endif
|
||||
if(svcctrl) svcctrl->start();
|
||||
}
|
||||
|
||||
if(enet_initialize() < 0) fatal("Unable to initialise network module");
|
||||
initserver(true);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
#if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
|
||||
|
||||
@@ -1306,7 +1306,6 @@ void clearservers()
|
||||
|
||||
#define RETRIEVELIMIT 5000
|
||||
|
||||
extern char *global_name;
|
||||
bool cllock = false, clfail = false;
|
||||
|
||||
int progress_callback_retrieveservers(void *data, float progress)
|
||||
@@ -1330,7 +1329,7 @@ void retrieveservers(vector<char> &data)
|
||||
if(h.set_host(mastername))
|
||||
{
|
||||
formatstring(progresstext)("retrieving servers from %s:%d... (esc to abort)", mastername, masterport);
|
||||
defformatstring(url)("/retrieve.do?action=list&name=%s&version=%d&build=%d", urlencode(global_name, true), AC_VERSION, getbuildtype()|(1<<16));
|
||||
defformatstring(url)("/retrieve.do?action=list&name=%s&version=%d&build=%d", urlencode(player1->name, true), AC_VERSION, getbuildtype()|(1<<16));
|
||||
h.outvec = (vector<uchar> *) &data; // ouch...
|
||||
show_out_of_renderloop_progress(0, progresstext);
|
||||
int got = h.get(url, RETRIEVELIMIT, RETRIEVELIMIT);
|
||||
@@ -1358,7 +1357,7 @@ void retrieveservers(vector<char> &data)
|
||||
defformatstring(text)("retrieving servers from %s:%d... (esc to abort)", mastername, masterport);
|
||||
show_out_of_renderloop_progress(0, text);
|
||||
int starttime = SDL_GetTicks(), timeout = 0;
|
||||
defformatstring(request)("list %s %d %d\n", global_name, AC_VERSION, getbuildtype());
|
||||
defformatstring(request)("list %s %d %d\n", player1->name, AC_VERSION, getbuildtype());
|
||||
const char *req = request;
|
||||
int reqlen = strlen(req);
|
||||
ENetBuffer buf;
|
||||
|
||||
@@ -19,11 +19,13 @@ struct winservice : servercontroller
|
||||
HANDLE stopevent;
|
||||
const char *name;
|
||||
|
||||
winservice(const char *name) : name(name)
|
||||
winservice(const char *name, int _argc, char **_argv) : name(name)
|
||||
{
|
||||
callbacks::svc = this;
|
||||
callbacks::svc = this;
|
||||
statushandle = 0;
|
||||
};
|
||||
argc = _argc;
|
||||
argv = _argv;
|
||||
}
|
||||
|
||||
~winservice()
|
||||
{
|
||||
@@ -109,25 +111,12 @@ struct winservice : servercontroller
|
||||
return main(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
struct callbacks
|
||||
{
|
||||
static winservice *svc;
|
||||
static int WINAPI main() { return svc->svcmain(); };
|
||||
static void WINAPI requesthandler(DWORD request) { svc->requesthandler(request); };
|
||||
};
|
||||
|
||||
/*void log(const char *msg, bool error)
|
||||
{
|
||||
HANDLE eventsrc = RegisterEventSource(NULL, "AC Server");
|
||||
if(eventsrc)
|
||||
{
|
||||
int eventid = ((error ? 0x11 : 0x1) << 10) & (0x1 << 9) & (FACILITY_NULL << 6) & 0x1; // TODO: create event definitions
|
||||
LPCTSTR msgs[1] = { msg };
|
||||
int r = ReportEvent(eventsrc, error ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, 0, 4, NULL, 1, 0, msgs, NULL);
|
||||
DeregisterEventSource(eventsrc);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
winservice *winservice::callbacks::svc = (winservice *)NULL;
|
||||
|
||||
+16
-12
@@ -16,6 +16,8 @@ int connectwithtimeout(ENetSocket sock, const char *hostname, ENetAddress &remot
|
||||
}
|
||||
#endif
|
||||
|
||||
extern struct servercommandline scl;
|
||||
bool usemaster = false;
|
||||
ENetSocket mastersock = ENET_SOCKET_NULL;
|
||||
ENetAddress masteraddress = { ENET_HOST_ANY, ENET_PORT_ANY }, serveraddress = { ENET_HOST_ANY, ENET_PORT_ANY };
|
||||
string mastername = AC_MASTER_URI;
|
||||
@@ -43,9 +45,8 @@ void disconnectmaster()
|
||||
|
||||
ENetSocket connectmaster()
|
||||
{
|
||||
if(!mastername[0]) return ENET_SOCKET_NULL;
|
||||
extern servercommandline scl;
|
||||
if(scl.maxclients>MAXCL) { logline(ACLOG_WARNING, "maxclient exceeded: cannot register"); return ENET_SOCKET_NULL; }
|
||||
if(!mastername[0] || !usemaster) return ENET_SOCKET_NULL;
|
||||
if(scl.maxclients > MAXCL) { logline(ACLOG_WARNING, "maxclient exceeded: cannot register"); return ENET_SOCKET_NULL; }
|
||||
|
||||
if(masteraddress.host == ENET_HOST_ANY)
|
||||
{
|
||||
@@ -160,7 +161,6 @@ void flushmasterinput()
|
||||
else disconnectmaster();
|
||||
}
|
||||
|
||||
extern char *global_name;
|
||||
extern int totalclients;
|
||||
|
||||
// send alive signal to masterserver after 40 minutes of uptime and if currently in intermission (so theoretically <= 1 hour)
|
||||
@@ -169,8 +169,9 @@ static inline void updatemasterserver(int millis, int port, int _interm)
|
||||
{
|
||||
if(!lastupdatemaster || ((millis-lastupdatemaster)>40*60*1000 && (_interm || !totalclients)))
|
||||
{
|
||||
char servername[30]; memset(servername,'\0',30); filtertext(servername, global_name, FTXT__GLOBALNAME, 20);
|
||||
if(mastername[0]) requestmasterf("regserv %d %s %d\n", port, servername[0] ? servername : "noname", AC_VERSION);
|
||||
string servdesc, pubkey;
|
||||
filtertext(servdesc, scl.servdesc_full[0] ? scl.servdesc_full : "noname", FTXT__GLOBALNAME, 20);
|
||||
if(mastername[0]) requestmasterf("regserv %d %s-%s %d\n", port, servdesc, scl.ssk ? bin2hex(pubkey, scl.ssk + 32, 32) : "nokey", AC_VERSION);
|
||||
lastupdatemaster = millis + 1;
|
||||
}
|
||||
}
|
||||
@@ -325,20 +326,21 @@ void serverms(int mode, int numplayers, int minremain, char *smapname, int milli
|
||||
if(mastersock != ENET_SOCKET_NULL && ENET_SOCKETSET_CHECK(sockset, mastersock)) flushmasterinput();
|
||||
}
|
||||
|
||||
// this function should be made better, because it is used just ONCE (no need of so much parameters)
|
||||
void servermsinit(const char *master, const char *ip, int infoport, bool listen)
|
||||
void servermsinit(bool listen)
|
||||
{
|
||||
copystring(mastername, master);
|
||||
if(scl.master && *scl.master) copystring(mastername, scl.master);
|
||||
usemaster = !listen || (listen && scl.master && scl.ssk); // true: connect to master, false: LAN-only server
|
||||
disconnectmaster();
|
||||
|
||||
if(listen)
|
||||
{
|
||||
ENetAddress address = { ENET_HOST_ANY, (enet_uint16)infoport };
|
||||
if(*ip)
|
||||
ENetAddress address = { ENET_HOST_ANY, (enet_uint16) CUBE_SERVINFO_PORT(scl.serverport) };
|
||||
if(*scl.ip)
|
||||
{
|
||||
if(enet_address_set_host(&address, ip)<0) logline(ACLOG_WARNING, "server ip not resolved");
|
||||
if(enet_address_set_host(&address, scl.ip) < 0) logline(ACLOG_WARNING, "server ip \"%s\" not resolved", scl.ip);
|
||||
else serveraddress.host = address.host;
|
||||
}
|
||||
|
||||
pongsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
|
||||
if(pongsock != ENET_SOCKET_NULL && enet_socket_bind(pongsock, &address) < 0)
|
||||
{
|
||||
@@ -347,6 +349,7 @@ void servermsinit(const char *master, const char *ip, int infoport, bool listen)
|
||||
}
|
||||
if(pongsock == ENET_SOCKET_NULL) fatal("could not create server info socket");
|
||||
else enet_socket_set_option(pongsock, ENET_SOCKOPT_NONBLOCK, 1);
|
||||
|
||||
address.port = CUBE_SERVINFO_PORT_LAN;
|
||||
lansock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
|
||||
if(lansock != ENET_SOCKET_NULL && (enet_socket_set_option(lansock, ENET_SOCKOPT_REUSEADDR, 1) < 0 || enet_socket_bind(lansock, &address) < 0))
|
||||
@@ -357,4 +360,5 @@ void servermsinit(const char *master, const char *ip, int infoport, bool listen)
|
||||
if(lansock == ENET_SOCKET_NULL) logline(ACLOG_WARNING, "could not create LAN server info socket");
|
||||
else enet_socket_set_option(lansock, ENET_SOCKOPT_NONBLOCK, 1);
|
||||
}
|
||||
if(!usemaster) logline(ACLOG_INFO, "server is LAN-only - without connection to masterserver");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user