From 035d7caf2f9c74414cd3d6baeb20abd6fb4903aa Mon Sep 17 00:00:00 2001 From: ac-stef Date: Mon, 21 Mar 2016 20:52:13 +0100 Subject: [PATCH] thread-safe and fully buffered logging Uses own thread to actually write to logs, so the main thread can't be blocked by a slow logfile. Log entries are buffered in two ringbuffers, one for the main thread and one for all other threads. The main thread will copy the second buffer to the main buffer periodically. The main thread buffer is read from the log worker thread. Since two buffers are kept, there are now several functions to add a log entry: mlog() for main thread functions only: will never block tlog() other threads only: may block, until main thread copied some entries xlog() automatically determines, which thread it's been called from and then writes to the proper buffer (will block accordingly) To avoid improper usage, mlog and tlog verify, if they are used correctly. (Only for debug builds. An assert triggers, if necessary.) --- source/src/cube.h | 2 +- source/src/log.cpp | 156 +++++++++++++++++++++------ source/src/master.cpp | 7 +- source/src/protos.h | 5 +- source/src/server.cpp | 198 ++++++++++++++++++----------------- source/src/serveractions.h | 2 +- source/src/serverbrowser.cpp | 2 +- source/src/serverchecks.h | 8 +- source/src/serverfiles.h | 67 ++++++------ source/src/serverms.cpp | 18 ++-- source/src/tools.h | 10 +- 11 files changed, 285 insertions(+), 190 deletions(-) diff --git a/source/src/cube.h b/source/src/cube.h index 14988da6..ebfdf991 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -58,7 +58,7 @@ extern float waterlevel; #define AC_VERSION 1202 #define AC_MASTER_URI "ms.cubers.net" #define AC_MASTER_PORT 28760 -#define MAXCL 16 +#define MAXCLIENTSONMASTER 16 // FIXME #define CONFIGROTATEMAX 5 // keep 5 old versions of saved.cfg and init.cfg around #define DEFAULT_FOG 180 diff --git a/source/src/log.cpp b/source/src/log.cpp index 9fb5bb73..a399d964 100644 --- a/source/src/log.cpp +++ b/source/src/log.cpp @@ -32,8 +32,15 @@ static int facility = -1, consolethreshold = ACLOG_INFO; static bool timestamp = false, enabled = false; +enum { LOGTARGET_CONSOLE = 1, LOGTARGET_FILE = 2, LOGTARGET_SYSLOG = 4 }; + +static char loglevelenabled[ACLOG_NUM]; + bool initlogging(const char *identity, int facility_, int consolethres, int filethres, int syslogthres, bool logtimestamp, const char *logfilepath) { + static void *logworkerthread_id = NULL; + extern int logworkerthread(void *nop); + if(!logworkerthread_id) logworkerthread_id = sl_createthread(logworkerthread, NULL); // always start, if dedicated server facility = facility_; timestamp = logtimestamp; if(consolethres >= 0) consolethreshold = min(consolethres, (int)ACLOG_NUM); @@ -63,12 +70,14 @@ bool initlogging(const char *identity, int facility_, int consolethres, int file if(syslogthreshold < ACLOG_NUM) concatformatstring(msg, ", \"%s\", local%d", ident, facility); concatformatstring(msg, "), timestamp(%s)", timestamp ? "ENABLED" : "DISABLED"); enabled = consolethreshold < ACLOG_NUM || fp || syslogthreshold < ACLOG_NUM; + loopi(ACLOG_NUM) loglevelenabled[i] = (consolethreshold <= i ? LOGTARGET_CONSOLE : 0) | (fp && filethreshold <= i ? LOGTARGET_FILE : 0) | (syslogthreshold <= i ? LOGTARGET_SYSLOG : 0); if(enabled) printf("%s\n", msg); return enabled; } void exitlogging() { + loopi(ACLOG_NUM) loglevelenabled[i] = 0; if(fp) { fclose(fp); fp = NULL; } #ifdef AC_USE_SYSLOG if(enabled && syslogthreshold < ACLOG_NUM) closelog(); @@ -79,42 +88,129 @@ void exitlogging() bool logcheck(int level) { - return enabled && level >= 0 && level < ACLOG_NUM && (consolethreshold <= level || (fp && filethreshold <= level) || syslogthreshold <= level); + ASSERT(level >= 0 && level < ACLOG_NUM); + return loglevelenabled[level] != 0; } -bool logline(int level, const char *msg, ...) +struct logline_s { int level; time_t t; string msg; }; + +static ringbuf mainlog; // increase this number, if log overflows occur +static ringbuf threadlog; +static int mainlogoverflow = 0; +static sl_semaphore threadlogsem(1, NULL), threadlogfullsem(0, NULL), mainlogsem(0, NULL); + +int logworkerthread(void *nop) { - if(!enabled) return false; - if(level < 0 || level >= ACLOG_NUM) return false; - bool logtocon = consolethreshold <= level, logtofile = fp && filethreshold <= level, logtosyslog = syslogthreshold <= level; - if(!(logtocon || logtofile || logtosyslog)) return false; - defvformatstring(sf, msg, msg); - filtertext(sf, sf, FTXT__LOG); - const char *ts = timestamp ? timestring(true, "%b %d %H:%M:%S ") : "", *ld = levelprefix[level]; - char *p, *l = sf; - do - { // break into single lines first - if((p = strchr(l, '\n'))) *p = '\0'; - if(logtocon) printf("%s%s%s\n", ts, ld, l); - if(logtofile) fprintf(fp, "%s%s%s\n", ts, ld, l); - if(logtosyslog) + string tmp; + for(;;) + { + while(mainlog.empty()) mainlogsem.wait(); + logline_s *ll = mainlog.remove(); + int targets = loglevelenabled[ll->level]; + bool logtocon = (targets & LOGTARGET_CONSOLE) != 0, logtofile = fp && (targets & LOGTARGET_FILE) != 0, logtosyslog = (targets & LOGTARGET_SYSLOG) != 0; + const char *ts = timestamp ? timestring(ll->t, true, "%b %d %H:%M:%S ", tmp) : "", *ld = levelprefix[ll->level]; + char *p, *l = ll->msg; + do + { // break into single lines first + if((p = strchr(l, '\n'))) *p = '\0'; + if(logtocon) printf("%s%s%s\n", ts, ld, l); + if(logtofile) fprintf(fp, "%s%s%s\n", ts, ld, l); + if(logtosyslog) #ifdef AC_USE_SYSLOG - syslog(levels[level], "%s", l); + syslog(levels[ll->level], "%s", l); #else - { - defformatstring(text)("<%d>%s: %s", (16 + facility) * 8 + levels[level], ident, l); // no TIMESTAMP, no hostname: syslog will add this - ENetBuffer buf; - buf.data = text; - buf.dataLength = strlen(text); - enet_socket_send(logsock, &logdest, &buf, 1); + { + defformatstring(text)("<%d>%s: %s", (16 + facility) * 8 + levels[ll->level], ident, l); // no TIMESTAMP, no hostname: syslog will add this + ENetBuffer buf; + buf.data = text; + buf.dataLength = strlen(text); + enet_socket_send(logsock, &logdest, &buf, 1); + } +#endif + l = p + 1; } -#endif - l = p + 1; - } - while(p); + while(p); #ifdef _DEBUG - if(logtocon) fflush(stdout); - if(logtofile) fflush(fp); + if(logtocon) fflush(stdout); + if(logtofile) fflush(fp); #endif - return logtocon; + delete ll; + } + return 0; +} + +void mlog(int level, const char *msg, ...) // log line from main thread (never blocks) +{ + ASSERT(level >= 0 && level < ACLOG_NUM && ismainthread()); + if(!loglevelenabled[level]) return; + if(mainlog.full()) { mainlogoverflow++; return; } // do. not. block. + logline_s *ll = mainlog.stage(new logline_s); + vformatstring(ll->msg, msg, msg); + filtertext(ll->msg, ll->msg, FTXT__LOG); + ll->t = time(NULL); + ll->level = level; + mainlog.commit(); + if(mainlogsem.getvalue() < 1) mainlogsem.post(); +} + +void tlog(int level, const char *msg, ...) // log line from other-than-main thread (may block) +{ + ASSERT(level >= 0 && level < ACLOG_NUM && !ismainthread()); + if(!loglevelenabled[level]) return; + threadlogsem.wait(); // properly lock, so different threads can use this + while(threadlog.full()) threadlogfullsem.wait(); // wait for buffer to clear + logline_s *ll = threadlog.stage(new logline_s); + vformatstring(ll->msg, msg, msg); + filtertext(ll->msg, ll->msg, FTXT__LOG); + ll->t = time(NULL); + ll->level = level; + threadlog.commit(); + threadlogsem.post(); +} + +void xlog(int level, const char *msg, ...) // log line from any thread (more expensive: only use for functions, that are called from main and other threads) +{ + ASSERT(level >= 0 && level < ACLOG_NUM); + if(!loglevelenabled[level]) return; + bool ismain = ismainthread(); + if(ismain) + { + if(mainlog.full()) { mainlogoverflow++; return; } // do. not. block. + } + else + { + threadlogsem.wait(); // properly lock, so different threads can use this + while(threadlog.full()) threadlogfullsem.wait(); // wait for buffer to clear + } + logline_s *ll = ismain ? mainlog.stage(new logline_s) : threadlog.stage(new logline_s); + vformatstring(ll->msg, msg, msg); + filtertext(ll->msg, ll->msg, FTXT__LOG); + ll->t = time(NULL); + ll->level = level; + if(ismain) + { + mainlog.commit(); + if(mainlogsem.getvalue() < 1) mainlogsem.post(); + } + else + { + threadlog.commit(); + threadlogsem.post(); + } +} + +void poll_logbuffers() // just copy threadlog to mainlog and restart blocked threads, if necessary +{ + while(!mainlog.full() && !threadlog.empty()) + { + mainlog.stage(threadlog.remove()); + mainlog.commit(); + } + if(mainlogoverflow && !mainlog.full()) + { + mlog(ACLOG_ERROR, "main log ringbuffer overflow, %d entries lost", mainlogoverflow); + mainlogoverflow = 0; + } + if(!threadlog.full() && threadlogfullsem.getvalue() < 1) threadlogfullsem.post(); + if(!mainlog.empty() && mainlogsem.getvalue() < 1) mainlogsem.post(); } diff --git a/source/src/master.cpp b/source/src/master.cpp index cc35ceb6..5ed629c5 100644 --- a/source/src/master.cpp +++ b/source/src/master.cpp @@ -214,12 +214,7 @@ void output(client &c, const char *msg, int len = 0) void outputf(client &c, const char *fmt, ...) { - string msg; - va_list args; - va_start(args, fmt); - vformatstring(msg, fmt, args); - va_end(args); - + defvformatstring(msg, fmt, fmt); output(c, msg); } diff --git a/source/src/protos.h b/source/src/protos.h index 3dfd3706..0a20c48a 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -1124,7 +1124,10 @@ enum { ACLOG_DEBUG = 0, ACLOG_VERBOSE, ACLOG_INFO, ACLOG_WARNING, ACLOG_ERROR, A extern bool initlogging(const char *identity, int facility_, int consolethres, int filethres, int syslogthres, bool logtimestamp, const char *logfilepath); extern void exitlogging(); extern bool logcheck(int level); -extern bool logline(int level, const char *msg, ...) PRINTFARGS(2, 3); +extern void mlog(int level, const char *msg, ...) PRINTFARGS(2, 3); // log line from main thread (never blocks) +extern void tlog(int level, const char *msg, ...) PRINTFARGS(2, 3); // log line from other-than-main thread (may block) +extern void xlog(int level, const char *msg, ...) PRINTFARGS(2, 3); // log line from any thread (more expensive: only use for functions, that are called from main and other threads) +extern void poll_logbuffers(); // server config diff --git a/source/src/server.cpp b/source/src/server.cpp index 6c47d33b..45734ea8 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -126,7 +126,7 @@ void poll_serverthreads() // called once per mainloop-timeslice if(startnewservermapsepoch || readmapsthread_sem->getvalue()) fatal("thread management mishap"); // zero tolerance... // wake readmapsthread - logline(ACLOG_INFO,"waking readmapsthread"); + mlog(ACLOG_INFO,"waking readmapsthread"); startnewservermapsepoch = true; servclock = (int) (time(NULL) / (time_t) 60); readmapsthread_sem->post(); @@ -146,14 +146,14 @@ void poll_serverthreads() // called once per mainloop-timeslice { if(!strcmp(servermaps[i]->fname, fresh->fname)) // we don't check paths here - map filenames have to be unique { // found map of same name - logline(ACLOG_INFO,"marked servermap %s%s for deletion", servermaps[i]->fpath, servermaps[i]->fname); + mlog(ACLOG_INFO,"marked servermap %s%s for deletion", servermaps[i]->fpath, servermaps[i]->fname); servermapstodelete.add(servermaps.remove(i)); // mark old version for deletion } } if(fresh->isok) { servermaps.add(fresh); - logline(ACLOG_INFO,"added servermap %s%s", fresh->fpath, fresh->fname); + mlog(ACLOG_INFO,"added servermap %s%s", fresh->fpath, fresh->fname); maprot.initmap(fresh, NULL); servermaps.sort(servermapsortname); // keep list sorted at all times } @@ -231,6 +231,11 @@ void poll_serverthreads() // called once per mainloop-timeslice break; } } + + // update thread-safe data structures (vectors and hashtables can be read concurrently - but to be updated, they need to be locked) + poll_logbuffers(); + + } SERVPAR(gamepenalty_cutoff, 30, 60, 120, "gNumber of minutes to remember that a map+mode combination has been played"); @@ -808,13 +813,13 @@ const char *getDemoFilename(int gmode, int mplay, int mdrop, int tstamp, char *s strftime(cfspp, sizeof(string) - 1, DEMOTSFORMAT, timeinfo); break; } - default: logline(ACLOG_INFO, "bad formatstring: demonameformat @ %d", cc); cc-=1; break; // don't drop the bad char + default: mlog(ACLOG_INFO, "bad formatstring: demonameformat @ %d", cc); cc-=1; break; // don't drop the bad char } concatstring(dmofn, cfspp); } else { - logline(ACLOG_INFO, "trailing %%-sign in demonameformat"); + mlog(ACLOG_INFO, "trailing %%-sign in demonameformat"); } cc+=1; break; @@ -847,7 +852,7 @@ void enddemorecord() { delete demotmp; demotmp = NULL; - logline(ACLOG_INFO, "Demo discarded."); + mlog(ACLOG_INFO, "Demo discarded."); return; } @@ -865,7 +870,7 @@ void enddemorecord() if(mr) { concatformatstring(d.info, ", %d mr", mr); concatformatstring(d.file, "_%dmr", mr); } defformatstring(msg)("Demo \"%s\" recorded\nPress F10 to download it from the server..", d.info); sendservmsg(msg); - logline(ACLOG_INFO, "Demo \"%s\" recorded.", d.info); + mlog(ACLOG_INFO, "Demo \"%s\" recorded.", d.info); int mPLAY = sg->gamemillis >= sg->gamelimit ? sg->gamelimit/1000 : sg->gamemillis/1000; int mDROP = sg->gamemillis >= sg->gamelimit ? 0 : (sg->gamelimit - sg->gamemillis)/1000; @@ -890,11 +895,11 @@ void enddemorecord() { int wlen = (int) demo->write(d.data, d.len); delete demo; - logline(ACLOG_INFO, "demo written to file \"%s\" (%d bytes)", msg, wlen); + mlog(ACLOG_INFO, "demo written to file \"%s\" (%d bytes)", msg, wlen); } else { - logline(ACLOG_INFO, "failed to write demo to file \"%s\"", msg); + mlog(ACLOG_INFO, "failed to write demo to file \"%s\"", msg); } } } @@ -915,8 +920,8 @@ void setupdemorecord() return; } - sendservmsg("recording demo"); - logline(ACLOG_INFO, "Demo recording started."); + sendservmsg("recording demo"); // FIXME + mlog(ACLOG_INFO, "Demo recording started."); demorecord = f; recordpackets = false; @@ -1153,7 +1158,7 @@ bool flagdistance(sflaginfo &f, int cn) if(pdist) { c.farpickups++; - logline(ACLOG_INFO, "[%s] %s %s the %s flag at distance %.2f (%d)", + mlog(ACLOG_INFO, "[%s] %s %s the %s flag at distance %.2f (%d)", c.hostname, c.name, (pdist==2?"tried to touch":"touched"), team_string(&f == sg->sflaginfos + 1), dist, c.farpickups); if (pdist==2) return false; } @@ -1276,7 +1281,7 @@ void flagaction(int flag, int action, int actor) } if(abort) { - logline(ACLOG_DEBUG,"aborting flagaction(flag %d, action %d, actor %d), reason %d, resending flag states", flag, action, actor, abort); // FIXME: remove this logline after some time - it will only show a few bad ping effects + mlog(ACLOG_DEBUG,"aborting flagaction(flag %d, action %d, actor %d), reason %d, resending flag states", flag, action, actor, abort); sendflaginfo(); return; } @@ -1293,29 +1298,29 @@ void flagaction(int flag, int action, int actor) switch(message) { case FM_PICKUP: - logline(ACLOG_INFO,"[%s] %s %s the flag", c.hostname, c.name, action == FA_STEAL ? "stole" : "picked up"); + mlog(ACLOG_INFO,"[%s] %s %s the flag", c.hostname, c.name, action == FA_STEAL ? "stole" : "picked up"); break; case FM_DROP: case FM_LOST: - logline(ACLOG_INFO,"[%s] %s %s the flag", c.hostname, c.name, message == FM_LOST ? "lost" : "dropped"); + mlog(ACLOG_INFO,"[%s] %s %s the flag", c.hostname, c.name, message == FM_LOST ? "lost" : "dropped"); break; case FM_RETURN: - logline(ACLOG_INFO,"[%s] %s returned the flag", c.hostname, c.name); + mlog(ACLOG_INFO,"[%s] %s returned the flag", c.hostname, c.name); break; case FM_SCORE: if(m_htf) - logline(ACLOG_INFO, "[%s] %s hunted the flag for %s, new score %d", c.hostname, c.name, team_string(c.team), c.state.flagscore); + mlog(ACLOG_INFO, "[%s] %s hunted the flag for %s, new score %d", c.hostname, c.name, team_string(c.team), c.state.flagscore); else - logline(ACLOG_INFO, "[%s] %s scored with the flag for %s, new score %d", c.hostname, c.name, team_string(c.team), c.state.flagscore); + mlog(ACLOG_INFO, "[%s] %s scored with the flag for %s, new score %d", c.hostname, c.name, team_string(c.team), c.state.flagscore); break; case FM_KTFSCORE: - logline(ACLOG_INFO, "[%s] %s scored, carrying for %d seconds, new score %d", c.hostname, c.name, (sg->gamemillis - f.stolentime) / 1000, c.state.flagscore); + mlog(ACLOG_INFO, "[%s] %s scored, carrying for %d seconds, new score %d", c.hostname, c.name, (sg->gamemillis - f.stolentime) / 1000, c.state.flagscore); break; case FM_SCOREFAIL: - logline(ACLOG_INFO, "[%s] %s failed to score", c.hostname, c.name); + mlog(ACLOG_INFO, "[%s] %s failed to score", c.hostname, c.name); break; default: - logline(ACLOG_INFO, "flagaction %d, actor %d, flag %d, message %d", action, actor, flag, message); + mlog(ACLOG_INFO, "flagaction %d, actor %d, flag %d, message %d", action, actor, flag, message); break; } flagpoints (&c, message); @@ -1325,10 +1330,10 @@ void flagaction(int flag, int action, int actor) switch(message) { case FM_RESET: - logline(ACLOG_INFO,"the server reset the flag for team %s", team_string(flag)); + mlog(ACLOG_INFO,"the server reset the flag for team %s", team_string(flag)); break; default: - logline(ACLOG_INFO, "flagaction %d with invalid actor cn %d, flag %d, message %d", action, actor, flag, message); + mlog(ACLOG_INFO, "flagaction %d with invalid actor cn %d, flag %d, message %d", action, actor, flag, message); break; } } @@ -1402,7 +1407,7 @@ void htf_forceflag(int flag) f.actor_cn = cl->clientnum; sendflaginfo(flag); flagmessage(flag, FM_PICKUP, cl->clientnum); - logline(ACLOG_INFO,"[%s] %s got forced to pickup the flag", cl->hostname, cl->name); + mlog(ACLOG_INFO,"[%s] %s got forced to pickup the flag", cl->hostname, cl->name); } f.lastupdate = sg->gamemillis; } @@ -1665,13 +1670,13 @@ bool serverpickup(int i, int sender) // server side item pickup, acknowl const char *hn = sender >= 0 && clients[sender]->type == ST_TCPIP ? clients[sender]->hostname : NULL; if(!sg->sents.inrange(i)) { - if(hn && !m_coop) logline(ACLOG_INFO, "[%s] tried to pick up entity #%d - doesn't exist on this map", hn, i); + if(hn && !m_coop) mlog(ACLOG_INFO, "[%s] tried to pick up entity #%d - doesn't exist on this map", hn, i); return false; } server_entity &e = sg->sents[i]; if(!e.spawned) { - if(!e.legalpickup && hn && !m_demo) logline(ACLOG_INFO, "[%s] tried to pick up entity #%d (%s) - can't be picked up in this gamemode or at all", hn, i, entnames[e.type]); + if(!e.legalpickup && hn && !m_demo) mlog(ACLOG_INFO, "[%s] tried to pick up entity #%d (%s) - can't be picked up in this gamemode or at all", hn, i, entnames[e.type]); return false; } if(sender>=0) @@ -1686,7 +1691,7 @@ bool serverpickup(int i, int sender) // server side item pickup, acknowl if (pdist) { cl->farpickups++; - if (!m_demo) logline(ACLOG_INFO, "[%s] %s %s up entity #%d (%s), distance %.2f (%d)", + if (!m_demo) mlog(ACLOG_INFO, "[%s] %s %s up entity #%d (%s), distance %.2f (%d)", cl->hostname, cl->name, (pdist==2?"tried to pick":"picked"), i, entnames[e.type], dist, cl->farpickups); if (pdist==2) return false; } @@ -1757,7 +1762,7 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib, { // suicide actor->state.frags--; suic = true; - logline(ACLOG_INFO, "[%s] %s suicided", actor->hostname, actor->name); + mlog(ACLOG_INFO, "[%s] %s suicided", actor->hostname, actor->name); } sendf(-1, 1, "ri5", gib ? SV_GIBDIED : SV_DIED, target->clientnum, actor->clientnum, actor->state.frags, gun); if((suic || tk) && (m_htf || m_ktf) && targethasflag >= 0) @@ -1768,7 +1773,7 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib, target->position.setsize(0); ts.state = CS_DEAD; ts.lastdeath = sg->gamemillis; - if(!suic) logline(ACLOG_INFO, "[%s] %s %s%s %s", actor->hostname, actor->name, valid_weapon(gun) ? killmessages[gib ? 1 : 0][gun] : "smurfed", tk ? " their teammate" : "", target->name); + if(!suic) mlog(ACLOG_INFO, "[%s] %s %s%s %s", actor->hostname, actor->name, valid_weapon(gun) ? killmessages[gib ? 1 : 0][gun] : "smurfed", tk ? " their teammate" : "", target->name); if(m_flags && targethasflag >= 0) { if(m_ctf) @@ -2214,7 +2219,7 @@ void startgame(const char *newname, int newmode, int newtime, bool notify) if(notify) { sendservmsg("server description reset to default"); - logline(ACLOG_INFO, "server description reset to '%s'", sg->servdesc_current); + mlog(ACLOG_INFO, "server description reset to '%s'", sg->servdesc_current); } } @@ -2282,7 +2287,7 @@ void startgame(const char *newname, int newmode, int newtime, bool notify) if(sg->mastermode == MM_MATCH) concatformatstring(gsmsg, "teamsize %d, ", sg->matchteamsize); if(sm) concatformatstring(gsmsg, "(map rev %d/%d, %s, 'getmap' %sprepared)", sm->maprevision, sm->cgzlen, sm->getpathdesc(), sm->isdistributable() ? "" : "not "); else concatformatstring(gsmsg, "error: failed to preload map"); - logline(ACLOG_INFO, "\n%s", gsmsg); + mlog(ACLOG_INFO, "\n%s", gsmsg); if(m_arena) distributespawns(); if(notify) { @@ -2462,7 +2467,7 @@ bool svote(int sender, int vote, ENetPacket *msg) // true if the vote was placed sendpacket(-1, 1, msg, sender); clients[sender]->vote = vote; - logline(ACLOG_DEBUG,"[%s] client %s voted %s", clients[sender]->hostname, clients[sender]->name, vote == VOTE_NO ? "no" : "yes"); + mlog(ACLOG_DEBUG,"[%s] client %s voted %s", clients[sender]->hostname, clients[sender]->name, vote == VOTE_NO ? "no" : "yes"); curvote->evaluate(); return true; } @@ -2476,14 +2481,14 @@ void scallvotesuc(voteinfo *v) clients[v->owner]->lastvotecall = servmillis; clients[v->owner]->nvotes--; // successful votes do not count as abuse sendf(v->owner, 1, "ri", SV_CALLVOTESUC); - logline(ACLOG_INFO, "[%s] client %s called a vote: %s", clients[v->owner]->hostname, clients[v->owner]->name, v->action && *v->action->desc ? v->action->desc : "[unknown]"); + mlog(ACLOG_INFO, "[%s] client %s called a vote: %s", clients[v->owner]->hostname, clients[v->owner]->name, v->action && *v->action->desc ? v->action->desc : "[unknown]"); } void scallvoteerr(voteinfo *v, int error) { if(!valid_client(v->owner)) return; sendf(v->owner, 1, "ri2", SV_CALLVOTEERR, error); - logline(ACLOG_INFO, "[%s] client %s failed to call a vote: %s (%s)", clients[v->owner]->hostname, clients[v->owner]->name, v->action && *v->action->desc ? v->action->desc : "[unknown]", voteerrorstr(error)); + mlog(ACLOG_INFO, "[%s] client %s failed to call a vote: %s (%s)", clients[v->owner]->hostname, clients[v->owner]->name, v->action && *v->action->desc ? v->action->desc : "[unknown]", voteerrorstr(error)); } bool map_queued = false; @@ -2597,8 +2602,8 @@ void changeclientrole(int client, int role, char *pwd, bool force) clients[client]->role = role; sendserveropinfo(-1); if(pd.line > -1) - logline(ACLOG_INFO,"[%s] player %s used admin password in line %d", clients[client]->hostname, clients[client]->name[0] ? clients[client]->name : "[unnamed]", pd.line); - logline(ACLOG_INFO,"[%s] set role of player %s to %s", clients[client]->hostname, clients[client]->name[0] ? clients[client]->name : "[unnamed]", role == CR_ADMIN ? "admin" : "normal player"); // flowtron : connecting players haven't got a name yet (connectadmin) + mlog(ACLOG_INFO,"[%s] player %s used admin password in line %d", clients[client]->hostname, clients[client]->name[0] ? clients[client]->name : "[unnamed]", pd.line); + mlog(ACLOG_INFO,"[%s] set role of player %s to %s", clients[client]->hostname, clients[client]->name[0] ? clients[client]->name : "[unnamed]", role == CR_ADMIN ? "admin" : "normal player"); // flowtron : connecting players haven't got a name yet (connectadmin) if(role > CR_DEFAULT) sendiplist(client); } else if(pwd && pwd[0]) disconnect_client(client, DISC_SOPLOGINFAIL); // avoid brute-force @@ -2631,6 +2636,7 @@ void senddisconnectedscores(int cn) void disconnect_client(int n, int reason) { + ASSERT(ismainthread()); if(!clients.inrange(n) || clients[n]->type!=ST_TCPIP) return; sdropflag(n); client &c = *clients[n]; @@ -2646,8 +2652,8 @@ void disconnect_client(int n, int reason) } } int sp = (servmillis - c.connectmillis) / 1000; - if(reason>=0) logline(ACLOG_INFO, "[%s] disconnecting client %s (%s) cn %d, %d seconds played%s", c.hostname, c.name, disc_reason(reason), n, sp, scoresaved); - else logline(ACLOG_INFO, "[%s] disconnected client %s cn %d, %d seconds played%s", c.hostname, c.name, n, sp, scoresaved); + if(reason>=0) mlog(ACLOG_INFO, "[%s] disconnecting client %s (%s) cn %d, %d seconds played%s", c.hostname, c.name, disc_reason(reason), n, sp, scoresaved); + else mlog(ACLOG_INFO, "[%s] disconnected client %s cn %d, %d seconds played%s", c.hostname, c.name, n, sp, scoresaved); totalclients--; c.peer->data = (void *)-1; if(reason>=0) enet_peer_disconnect(c.peer, reason); @@ -2677,7 +2683,7 @@ void authsucceeded(uint id) client *cl = findauth(id); if(!cl) return; cl->authreq = 0; - logline(ACLOG_INFO, "player authenticated: %s", cl->name); + mlog(ACLOG_INFO, "player authenticated: %s", cl->name); defformatstring(auth4u)("player authenticated: %s", cl->name); sendf(-1, 1, "ris", SV_SERVMSG, auth4u); //setmaster(cl, true, "", ci->authname);//TODO? compare to sauerbraten @@ -3040,7 +3046,7 @@ void process(ENetPacket *packet, int sender, int chan) p.get((uchar*)sa->clientmsg, 64); } bool ipfail = servownip && servownip != curpeerip; - if(ipfail) logline(ACLOG_INFO, "[%s] client reported different server IP %s:%d (known own IP is %s)", cl->hostname, iptoa(curpeerip, tmp1), curpeerport, iptoa(servownip, tmp2)); + if(ipfail) mlog(ACLOG_INFO, "[%s] client reported different server IP %s:%d (known own IP is %s)", cl->hostname, iptoa(curpeerip, tmp1), curpeerport, iptoa(servownip, tmp2)); formatstring(text)("SERVINFOCHALLENGE<(%d) cn: %d c: %s (%s) s: %s:%d", cl->salt, sender, iptoa(cl->ip_censored, tmp1), cl->country, iptoa(servownip, tmp2), curpeerport); concatformatstring(text, " %s st: %d ct: %d (%d)>", bin2hex(tmp1, spk, 32), cl->connectclock, clientclock, clientsalt); sa->clientmsglen = (int)strlen(text); @@ -3086,16 +3092,16 @@ void process(ENetPacket *packet, int sender, int chan) if(matchreconnect && !banned) { // former player reconnecting to a server in match mode cl->isauthed = true; - logline(ACLOG_INFO, "[%s] %s logged in (reconnect to match)%s", cl->hostname, cl->name, tags); + mlog(ACLOG_INFO, "[%s] %s logged in (reconnect to match)%s", cl->hostname, cl->name, tags); } else if(wl == NWL_IPFAIL || wl == NWL_PWDFAIL) { // nickname matches whitelist, but IP is not in the required range or PWD doesn't match - logline(ACLOG_INFO, "[%s] '%s' matches nickname whitelist: wrong %s%s", cl->hostname, cl->name, wl == NWL_IPFAIL ? "IP" : "PWD", tags); + mlog(ACLOG_INFO, "[%s] '%s' matches nickname whitelist: wrong %s%s", cl->hostname, cl->name, wl == NWL_IPFAIL ? "IP" : "PWD", tags); disconnect_client(sender, DISC_BADNICK); } else if(bl > 0) { // nickname matches blacklist - logline(ACLOG_INFO, "[%s] '%s' matches nickname blacklist line %d%s", cl->hostname, cl->name, bl, tags); + mlog(ACLOG_INFO, "[%s] '%s' matches nickname blacklist line %d%s", cl->hostname, cl->name, bl, tags); disconnect_client(sender, DISC_BADNICK); } else if(passwords.check(cl->name, cl->pwd, cl->salt, &pd, (cl->type==ST_TCPIP ? cl->peer->address.host : 0)) && (!pd.denyadmin || (banned && !srvfull && !srvprivate)) && bantype != BAN_MASTER) // pass admins always through @@ -3114,14 +3120,14 @@ void process(ENetPacket *packet, int sender, int chan) break; } } - logline(ACLOG_INFO, "[%s] %s logged in using the admin password in line %d%s", cl->hostname, cl->name, pd.line, tags); + mlog(ACLOG_INFO, "[%s] %s logged in using the admin password in line %d%s", cl->hostname, cl->name, pd.line, tags); } else if(scl.serverpassword[0] && !(srvprivate || srvfull || banned)) { // server password required if(!strcmp(genpwdhash(cl->name, scl.serverpassword, cl->salt), cl->pwd)) { cl->isauthed = true; - logline(ACLOG_INFO, "[%s] %s client logged in (using serverpassword)%s", cl->hostname, cl->name, tags); + mlog(ACLOG_INFO, "[%s] %s client logged in (using serverpassword)%s", cl->hostname, cl->name, tags); } else disconnect_client(sender, DISC_WRONGPW); } @@ -3131,7 +3137,7 @@ void process(ENetPacket *packet, int sender, int chan) else { cl->isauthed = true; - logline(ACLOG_INFO, "[%s] %s logged in (default)%s", cl->hostname, cl->name, tags); + mlog(ACLOG_INFO, "[%s] %s logged in (default)%s", cl->hostname, cl->name, tags); } } if(!cl->isauthed) return; @@ -3161,7 +3167,7 @@ void process(ENetPacket *packet, int sender, int chan) } } - if(!cl) { logline(ACLOG_ERROR, " client in process()"); return; } // should never happen anyway + if(!cl) { mlog(ACLOG_ERROR, " client in process()"); return; } // should never happen anyway if(packet->flags&ENET_PACKET_FLAG_RELIABLE) reliablemessages = true; @@ -3213,12 +3219,12 @@ void process(ENetPacket *packet, int sender, int chan) bool canspeech = forbiddenlist.canspeech(text); if(!spamdetect(cl, text) && canspeech) // team chat { - logline(ACLOG_INFO, "[%s] %s%s says to team %s: '%s'", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", cl->name, team_string(cl->team), text); + mlog(ACLOG_INFO, "[%s] %s%s says to team %s: '%s'", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", cl->name, team_string(cl->team), text); sendteamtext(text, sender, type); } else { - logline(ACLOG_INFO, "[%s] %s%s says to team %s: '%s', %s", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", + mlog(ACLOG_INFO, "[%s] %s%s says to team %s: '%s', %s", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", cl->name, team_string(cl->team), text, canspeech ? "SPAM detected" : "Forbidden speech"); if (canspeech) { @@ -3248,19 +3254,19 @@ void process(ENetPacket *packet, int sender, int chan) { if(sg->mastermode != MM_MATCH || !sg->matchteamsize || team_isactive(cl->team) || (cl->team == TEAM_SPECT && cl->role == CR_ADMIN)) // common chat { - logline(ACLOG_INFO, "[%s] %s%s says: '%s'", cl->hostname, type == SV_TEXTME ? "(me) " : "", cl->name, text); + mlog(ACLOG_INFO, "[%s] %s%s says: '%s'", cl->hostname, type == SV_TEXTME ? "(me) " : "", cl->name, text); if(cl->type==ST_TCPIP) while(mid1messages.add(p.buf[mid1++]); QUEUE_STR(text); } else // spect chat { - logline(ACLOG_INFO, "[%s] %s%s says to team %s: '%s'", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", cl->name, team_string(cl->team), text); + mlog(ACLOG_INFO, "[%s] %s%s says to team %s: '%s'", cl->hostname, type == SV_TEAMTEXTME ? "(me) " : "", cl->name, team_string(cl->team), text); sendteamtext(text, sender, type == SV_TEXTME ? SV_TEAMTEXTME : SV_TEAMTEXT); } } else { - logline(ACLOG_INFO, "[%s] %s%s says: '%s', %s", cl->hostname, type == SV_TEXTME ? "(me) " : "", + mlog(ACLOG_INFO, "[%s] %s%s says: '%s', %s", cl->hostname, type == SV_TEXTME ? "(me) " : "", cl->name, text, canspeech ? "SPAM detected" : "Forbidden speech"); if (canspeech) { @@ -3293,12 +3299,12 @@ void process(ENetPacket *packet, int sender, int chan) if(!spamdetect(cl, text) && canspeech) { bool allowed = !(sg->mastermode == MM_MATCH && cl->team != target->team) && cl->role >= roleconf('t'); - logline(ACLOG_INFO, "[%s] %s says to %s: '%s' (%s)", cl->hostname, cl->name, target->name, text, allowed ? "allowed":"disallowed"); + mlog(ACLOG_INFO, "[%s] %s says to %s: '%s' (%s)", cl->hostname, cl->name, target->name, text, allowed ? "allowed":"disallowed"); if(allowed) sendf(target->clientnum, 1, "riis", SV_TEXTPRIVATE, cl->clientnum, text); } else { - logline(ACLOG_INFO, "[%s] %s says to %s: '%s', %s", cl->hostname, cl->name, target->name, text, canspeech ? "SPAM detected" : "Forbidden speech"); + mlog(ACLOG_INFO, "[%s] %s says to %s: '%s', %s", cl->hostname, cl->name, target->name, text, canspeech ? "SPAM detected" : "Forbidden speech"); if (canspeech) { sendservmsg("\f3Please do not spam; your message was not delivered.", sender); @@ -3344,7 +3350,7 @@ void process(ENetPacket *packet, int sender, int chan) int sp = canspawn(cl); sendf(sender, 1, "rii", SV_SPAWNDENY, sp); cl->spawnperm = sp; - if(cl->loggedwrongmap) logline(ACLOG_INFO, "[%s] %s is now on the right map: revision %d/%d", cl->hostname, cl->name, rev, gzs); + if(cl->loggedwrongmap) mlog(ACLOG_INFO, "[%s] %s is now on the right map: revision %d/%d", cl->hostname, cl->name, rev, gzs); bool spawn = false; if(team_isspect(cl->team)) { @@ -3364,7 +3370,7 @@ void process(ENetPacket *packet, int sender, int chan) else { forcedeath(cl); - logline(ACLOG_INFO, "[%s] %s is on the wrong map: revision %d/%d", cl->hostname, cl->name, rev, gzs); + mlog(ACLOG_INFO, "[%s] %s is on the wrong map: revision %d/%d", cl->hostname, cl->name, rev, gzs); cl->loggedwrongmap = true; sendf(sender, 1, "rii", SV_SPAWNDENY, SP_WRONGMAP); } @@ -3410,7 +3416,7 @@ void process(ENetPacket *packet, int sender, int chan) if(!text[0]) copystring(text, "unarmed"); QUEUE_STR(text); bool namechanged = strcmp(cl->name, text) != 0; - if(namechanged) logline(ACLOG_INFO,"[%s] %s changed name to %s", cl->hostname, cl->name, text); + if(namechanged) mlog(ACLOG_INFO,"[%s] %s changed name to %s", cl->hostname, cl->name, text); copystring(cl->name, text, MAXNAMELEN+1); if(namechanged) { @@ -3428,7 +3434,7 @@ void process(ENetPacket *packet, int sender, int chan) { case NWL_PWDFAIL: case NWL_IPFAIL: - logline(ACLOG_INFO, "[%s] '%s' matches nickname whitelist: wrong IP/PWD", cl->hostname, cl->name); + mlog(ACLOG_INFO, "[%s] '%s' matches nickname whitelist: wrong IP/PWD", cl->hostname, cl->name); disconnect_client(sender, DISC_BADNICK); break; @@ -3437,7 +3443,7 @@ void process(ENetPacket *packet, int sender, int chan) int l = nickblacklist.checkblacklist(cl->name); if(l >= 0) { - logline(ACLOG_INFO, "[%s] '%s' matches nickname blacklist line %d", cl->hostname, cl->name, l); + mlog(ACLOG_INFO, "[%s] '%s' matches nickname blacklist line %d", cl->hostname, cl->name, l); disconnect_client(sender, DISC_BADNICK); } break; @@ -3761,7 +3767,7 @@ void process(ENetPacket *packet, int sender, int chan) memcpy(sg->coop_mapdata, &p.buf[p.len], mapsize + cfgsizegz); } incoming_size += mapsize + cfgsize; - logline(ACLOG_INFO,"[%s] %s sent map %s, rev %d, %d + %d(%d) bytes written", + mlog(ACLOG_INFO,"[%s] %s sent map %s, rev %d, %d + %d(%d) bytes written", clients[sender]->hostname, clients[sender]->name, sentmap, revision, mapsize, cfgsize, cfgsizegz); defformatstring(msg)("%s (%d) up%sed map %s, rev %d", clients[sender]->name, sender, !sm ? "load": "dat", sentmap, revision); sendservmsg(msg); @@ -3774,7 +3780,7 @@ void process(ENetPacket *packet, int sender, int chan) } if (reject) { - logline(ACLOG_INFO,"[%s] %s sent map %s rev %d, rejected: %s", + mlog(ACLOG_INFO,"[%s] %s sent map %s rev %d, rejected: %s", clients[sender]->hostname, clients[sender]->name, sentmap, revision, reject); } p.len += mapsize + cfgsizegz; @@ -3821,11 +3827,11 @@ void process(ENetPacket *packet, int sender, int chan) remove(filename); defformatstring(msg)("map '%s' deleted", rmmap); sendservmsg(msg, sender); - logline(ACLOG_INFO,"[%s] deleted map %s", clients[sender]->hostname, rmmap); + mlog(ACLOG_INFO,"[%s] deleted map %s", clients[sender]->hostname, rmmap); } if (reject) { - logline(ACLOG_INFO,"[%s] deleting map %s failed: %s", clients[sender]->hostname, rmmap, reject); + mlog(ACLOG_INFO,"[%s] deleting map %s failed: %s", clients[sender]->hostname, rmmap, reject); defformatstring(msg)("\f3can't delete map '%s', %s", rmmap, reject); sendservmsg(msg, sender); } @@ -4008,7 +4014,7 @@ void process(ENetPacket *packet, int sender, int chan) getstring(text, p, n); if(valid_client(sender) && clients[sender]->role==CR_ADMIN) { - logline(ACLOG_INFO, "[%s] %s writes to log: %s", cl->hostname, cl->name, text); + mlog(ACLOG_INFO, "[%s] %s writes to log: %s", cl->hostname, cl->name, text); sendservmsg("your message has been logged", sender); } } @@ -4126,11 +4132,11 @@ void loggamestatus(const char *reason) int fragscore[2] = {0, 0}, flagscore[2] = {0, 0}, pnum[2] = {0, 0}; string text; formatstring(text)("%d minutes remaining", sg->minremain); - logline(ACLOG_INFO, ""); - logline(ACLOG_INFO, "Game status: %s on %s, %s, %s, %d clients%c %s", + mlog(ACLOG_INFO, ""); + mlog(ACLOG_INFO, "Game status: %s on %s, %s, %s, %d clients%c %s", modestr(gamemode), sg->smapname, reason ? reason : text, mmfullname(sg->mastermode), totalclients, sg->custom_servdesc ? ',' : '\0', sg->servdesc_current); if(!scl.loggamestatus) return; - logline(ACLOG_INFO, "cn name %s%s score frag death %sping role host", m_teammode ? "team " : "", m_flags ? "flag " : "", m_teammode ? "tk " : ""); + mlog(ACLOG_INFO, "cn name %s%s score frag death %sping role host", m_teammode ? "team " : "", m_flags ? "flag " : "", m_teammode ? "tk " : ""); loopv(clients) { client &c = *clients[i]; @@ -4141,7 +4147,7 @@ void loggamestatus(const char *reason) concatformatstring(text, "%6d ", c.state.points); // score concatformatstring(text, "%4d %5d", c.state.frags, c.state.deaths); // frag death if(m_teammode) concatformatstring(text, " %2d", c.state.teamkills); // tk - logline(ACLOG_INFO, "%s%5d %s %s", text, c.ping, c.role == CR_ADMIN ? "admin " : "normal", c.hostname); + mlog(ACLOG_INFO, "%s%5d %s %s", text, c.ping, c.role == CR_ADMIN ? "admin " : "normal", c.hostname); if(c.team != TEAM_SPECT) { int t = team_base(c.team); @@ -4160,7 +4166,7 @@ void loggamestatus(const char *reason) if(m_teammode) formatstring(text)("%-4s ", team_string(sc.team, true)); else text[0] = '\0'; if(m_flags) concatformatstring(text, "%4d ", sc.flagscore); - logline(ACLOG_INFO, " %-16s %s%4d %5d%s - disconnected", sc.name, text, sc.frags, sc.deaths, m_teammode ? " -" : ""); + mlog(ACLOG_INFO, " %-16s %s%4d %5d%s - disconnected", sc.name, text, sc.frags, sc.deaths, m_teammode ? " -" : ""); if(sc.team != TEAM_SPECT) { int t = team_base(sc.team); @@ -4173,9 +4179,9 @@ void loggamestatus(const char *reason) } if(m_teammode) { - loopi(2) logline(ACLOG_INFO, "Team %4s:%3d players,%5d frags%c%5d flags", team_string(i), pnum[i], fragscore[i], m_flags ? ',' : '\0', flagscore[i]); + loopi(2) mlog(ACLOG_INFO, "Team %4s:%3d players,%5d frags%c%5d flags", team_string(i), pnum[i], fragscore[i], m_flags ? ',' : '\0', flagscore[i]); } - logline(ACLOG_INFO, ""); + mlog(ACLOG_INFO, ""); } static unsigned char chokelog[MAXCLIENTS + 1] = { 0 }; @@ -4236,7 +4242,7 @@ void linequalitystats(int elapsed) chokelog[i] = (s << 4) + c; concatformatstring(msg, "%02X ", chokelog[i]); } - logline(ACLOG_DEBUG, "%s] +%d", msg, ncs); + mlog(ACLOG_DEBUG, "%s] +%d", msg, ncs); } } @@ -4342,7 +4348,7 @@ void serverslice(uint timeout) // main server update, called from cube main lo if(nonlocalclients || serverhost->totalSentData || serverhost->totalReceivedData) { if(nonlocalclients) loggamestatus(NULL); - logline(ACLOG_INFO, "Status at %s: %d remote clients, %.1f send, %.1f rec (K/sec);" + mlog(ACLOG_INFO, "Status at %s: %d remote clients, %.1f send, %.1f rec (K/sec);" " Ping: #%d|%d|%d; CSL: #%d|%d|%d (bytes)", timestring(true, "%d-%m-%Y %H:%M:%S"), nonlocalclients, serverhost->totalSentData/60.0f/1024, serverhost->totalReceivedData/60.0f/1024, mnum, msend, mrec, cnum, csend, crec); @@ -4382,7 +4388,7 @@ void serverslice(uint timeout) // main server update, called from cube main lo copystring(c.country, gi ? gi : "--", 3); filtercountrycode(c.country, c.country); entropy_add_byte(c.ip); - logline(ACLOG_INFO,"[%s] client connected (%s)", c.hostname, c.country); + mlog(ACLOG_INFO,"[%s] client connected (%s)", c.hostname, c.country); sendservinfo(c); totalclients++; break; @@ -4628,7 +4634,7 @@ void initserver(bool dedicated) restartlogging(); if(!logcheck(ACLOG_ERROR)) 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); + mlog(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(dedicated); @@ -4638,12 +4644,12 @@ void initserver(bool dedicated) serverparameters.init(scl.parfilepath); if(serverparameters.load()) serverparameters.read(); // do this early, so the parameters are properly set during initialisation ENetAddress address = { ENET_HOST_ANY, (enet_uint16)scl.serverport }; - if(scl.ip[0] && enet_address_set_host(&address, scl.ip)<0) logline(ACLOG_WARNING, "server ip not resolved!"); + if(scl.ip[0] && enet_address_set_host(&address, scl.ip)<0) mlog(ACLOG_WARNING, "server ip not resolved!"); serverhost = enet_host_create(&address, scl.maxclients+1, 3, 0, scl.uprate); if(!serverhost) fatal("could not create server host"); loopi(scl.maxclients) serverhost->peers[i].data = (void *)-1; - if(scl.ssk) logline(ACLOG_INFO,"server public key: %s", servpubkey); + if(scl.ssk) mlog(ACLOG_INFO,"server public key: %s", servpubkey); maprot.init(scl.maprotfile); passwords.init(scl.pwdfile, scl.adminpasswd); ipblacklist.init(scl.blfile); @@ -4652,19 +4658,19 @@ void initserver(bool dedicated) forbiddenlist.init(scl.forbidden); serverinfoinfo.init(scl.infopath, MAXTRANS / 2); serverinfomotd.init(scl.motdpath, MAXSTRLEN - 5); - logline(ACLOG_VERBOSE, "holding up to %d recorded demos in memory", scl.maxdemos); - if(scl.demopath[0]) logline(ACLOG_VERBOSE,"all recorded demos will be written to: \"%s\"", scl.demopath); - if(scl.voteperm[0]) logline(ACLOG_VERBOSE,"vote permission string: \"%s\"", scl.voteperm); - if(scl.mapperm[0]) logline(ACLOG_VERBOSE,"map permission string: \"%s\"", scl.mapperm); - logline(ACLOG_VERBOSE,"server description: \"%s\"", scl.servdesc_full); - if(scl.servdesc_pre[0] || scl.servdesc_suf[0]) logline(ACLOG_VERBOSE,"custom server description: \"%sCUSTOMPART%s\"", scl.servdesc_pre, scl.servdesc_suf); - logline(ACLOG_VERBOSE,"maxclients: %d, kick threshold: %d, ban threshold: %d", scl.maxclients, scl.kickthreshold, scl.banthreshold); - if(scl.master) logline(ACLOG_VERBOSE,"master server URL: \"%s\"", scl.master); - if(scl.serverpassword[0]) logline(ACLOG_VERBOSE,"server password: \"%s\"", hiddenpwd(scl.serverpassword)); + mlog(ACLOG_VERBOSE, "holding up to %d recorded demos in memory", scl.maxdemos); + if(scl.demopath[0]) mlog(ACLOG_VERBOSE,"all recorded demos will be written to: \"%s\"", scl.demopath); + if(scl.voteperm[0]) mlog(ACLOG_VERBOSE,"vote permission string: \"%s\"", scl.voteperm); + if(scl.mapperm[0]) mlog(ACLOG_VERBOSE,"map permission string: \"%s\"", scl.mapperm); + mlog(ACLOG_VERBOSE,"server description: \"%s\"", scl.servdesc_full); + if(scl.servdesc_pre[0] || scl.servdesc_suf[0]) mlog(ACLOG_VERBOSE,"custom server description: \"%sCUSTOMPART%s\"", scl.servdesc_pre, scl.servdesc_suf); + mlog(ACLOG_VERBOSE,"maxclients: %d, kick threshold: %d, ban threshold: %d", scl.maxclients, scl.kickthreshold, scl.banthreshold); + if(scl.master) mlog(ACLOG_VERBOSE,"master server URL: \"%s\"", scl.master); + if(scl.serverpassword[0]) mlog(ACLOG_VERBOSE,"server password: \"%s\"", hiddenpwd(scl.serverpassword)); #ifdef ACAC - logline(ACLOG_INFO, "anticheat: enabled"); + mlog(ACLOG_INFO, "anticheat: enabled"); #else - logline(ACLOG_INFO, "anticheat: disabled"); + mlog(ACLOG_INFO, "anticheat: disabled"); #endif } @@ -4676,17 +4682,15 @@ void initserver(bool dedicated) SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); #endif // kill -2 / Ctrl-C - see http://msdn.microsoft.com/en-us/library/xdkz3x12%28v=VS.100%29.aspx (or VS-2008?) for caveat (seems not to pertain to AC - 2011feb05:ft) - if (signal(SIGINT, quitproc) == SIG_ERR) logline(ACLOG_INFO, "Cannot handle SIGINT!"); + if (signal(SIGINT, quitproc) == SIG_ERR) mlog(ACLOG_INFO, "Cannot handle SIGINT!"); // kill -15 / probably process-manager on Win32 *shrug* - if (signal(SIGTERM, quitproc) == SIG_ERR) logline(ACLOG_INFO, "Cannot handle SIGTERM!"); + if (signal(SIGTERM, quitproc) == SIG_ERR) mlog(ACLOG_INFO, "Cannot handle SIGTERM!"); #ifndef WIN32 // kill -1 - if (signal(SIGHUP, quitproc) == SIG_ERR) logline(ACLOG_INFO, "Cannot handle SIGHUP!"); - // kill -9 is uncatchable - http://en.wikipedia.org/wiki/SIGKILL - //if (signal(SIGKILL, quitproc) == SIG_ERR) logline(ACLOG_INFO, "Cannot handle SIGKILL!"); + if (signal(SIGHUP, quitproc) == SIG_ERR) mlog(ACLOG_INFO, "Cannot handle SIGHUP!"); #endif - logline(ACLOG_INFO, "dedicated server started, waiting for clients..."); - logline(ACLOG_INFO, "Ctrl-C to exit"); // this will now actually call the atexit-hooks below - thanks to SIGINT hooked above - noticed and signal-code-docs found by SKB:2011feb05:ft: + mlog(ACLOG_INFO, "dedicated server started, waiting for clients..."); + mlog(ACLOG_INFO, "Ctrl-C to exit"); // this will now actually call the atexit-hooks below - thanks to SIGINT hooked above - noticed and signal-code-docs found by SKB:2011feb05:ft: atexit(enet_deinitialize); atexit(cleanupserver); enet_time_set(0); @@ -4710,8 +4714,8 @@ void fatal(const char *s, ...) { defvformatstring(msg,s,s); defformatstring(out)("AssaultCube fatal error: %s", msg); - if (logline(ACLOG_ERROR, "%s", out)); - else puts(out); + xlog(ACLOG_ERROR, "%s", out); + puts(out); cleanupserver(); exit(EXIT_FAILURE); } diff --git a/source/src/serveractions.h b/source/src/serveractions.h index dd5637d2..c8367b3b 100644 --- a/source/src/serveractions.h +++ b/source/src/serveractions.h @@ -95,7 +95,7 @@ struct mapaction : serveraction concatstring(msg, " missing"); } if(notify) sendservmsg(msg, caller); - logline(ACLOG_INFO, "%s", msg); + xlog(ACLOG_INFO, "%s", msg); } } loopv(scl.adminonlymaps) diff --git a/source/src/serverbrowser.cpp b/source/src/serverbrowser.cpp index 8e6ca75b..0562bee8 100644 --- a/source/src/serverbrowser.cpp +++ b/source/src/serverbrowser.cpp @@ -1042,7 +1042,7 @@ void refreshservers(void *menu, bool init) { serverinfo &si = *servers[i]; si.menuline_to = si.menuline_from = ((gmenu *)menu)->items.length(); - if( (!showallservers && si.lastpingmillis <= servermenumillis) || (si.maxclients>MAXCL && searchlan<2) ) continue; // no pong yet or forbidden + if((!showallservers && si.lastpingmillis <= servermenumillis) || (si.maxclients > MAXCLIENTSONMASTER && searchlan<2) ) continue; // no pong yet or forbidden int banned = ((si.pongflags >> PONGFLAG_BANNED) & 1) | ((si.pongflags >> (PONGFLAG_BLACKLIST - 1)) & 2); bool showthisone = !(banned && showonlygoodservers) && !(showonlyfavourites > 0 && si.favcat != showonlyfavourites - 1); bool serverfull = si.numplayers >= si.maxclients; diff --git a/source/src/serverchecks.h b/source/src/serverchecks.h index 15d3c9e8..2fcd2414 100644 --- a/source/src/serverchecks.h +++ b/source/src/serverchecks.h @@ -16,7 +16,7 @@ inline void checkclientpos(client *cl) if(sg->gamemillis > 10000 && (servmillis - cl->connectmillis) > 10000) cl->mapcollisions++; if(cl->mapcollisions && !(cl->mapcollisions % 25)) { - logline(ACLOG_INFO, "[%s] %s is colliding with the map", cl->hostname, cl->name); + xlog(ACLOG_INFO, "[%s] %s is colliding with the map", cl->hostname, cl->name); } } } @@ -40,7 +40,7 @@ enum { CTFLDEF, CTFLCOV, HTFLDEF, HTFLCOV, COVER, MEDALMESSAGENUM }; inline void print_medal_messages(client *c, int n) { if (n<0 || n>=MEDALMESSAGENUM) return; - logline(ACLOG_VERBOSE, "[%s] %s %s", c->hostname, c->name, medal_messages[n]); + xlog(ACLOG_VERBOSE, "[%s] %s %s", c->hostname, c->name, medal_messages[n]); } inline void addpt(client *c, int points, int n = -1) { @@ -448,7 +448,7 @@ void check_afk() */ ) { - logline(ACLOG_INFO, "[%s] %s %s", c.hostname, c.name, "is afk"); + xlog(ACLOG_INFO, "[%s] %s %s", c.hostname, c.name, "is afk"); defformatstring(msg)("%s is afk", c.name); sendservmsg(msg); disconnect_client(c.clientnum, DISC_AFK); @@ -464,7 +464,7 @@ void check_ffire(client *target, client *actor, int damage) if ( sg->mastermode != MM_OPEN ) return; actor->ffire += damage; if ( actor->ffire > 300 && actor->ffire * 600 > sg->gamemillis) { - logline(ACLOG_INFO, "[%s] %s %s", actor->hostname, actor->name, "kicked for excessive friendly fire"); + xlog(ACLOG_INFO, "[%s] %s %s", actor->hostname, actor->name, "kicked for excessive friendly fire"); defformatstring(msg)("%s %s", actor->name, "kicked for excessive friendly fire"); sendservmsg(msg); disconnect_client(actor->clientnum, DISC_FFKICK); diff --git a/source/src/serverfiles.h b/source/src/serverfiles.h index 71b7f4af..e77a64d6 100644 --- a/source/src/serverfiles.h +++ b/source/src/serverfiles.h @@ -653,7 +653,7 @@ bool serverconfigfile::load() buf = loadfile(filename, &filelen); if((readfailed = !buf)) { - logline(ACLOG_INFO,"could not read config file '%s'", filename); + xlog(ACLOG_INFO,"could not read config file '%s'", filename); return false; } entropy_add_block((const uchar *)buf, filelen); @@ -823,7 +823,7 @@ struct servermaprot : serverconfigfile { loopi(GMODE_NUM) base[i] = prebase[i]; loopv(preloaded) configsets.add(preloaded[i]); - logline(ACLOG_INFO,"read %d map rotation entries from '%s'", configsets.length(), filename); + mlog(ACLOG_INFO,"read %d map rotation entries from '%s'", configsets.length(), filename); } void initmap(servermap *m, stream *f) // set maprot parameters of a servermap @@ -974,7 +974,7 @@ struct serveripcclist : serverconfigfile iprangecc ir; int line = 0, errors = 0, concatd = 0; char *l, *r, *p = buf; - logline(ACLOG_VERBOSE,"reading ip list '%s'", filename); + mlog(ACLOG_VERBOSE,"reading ip list '%s'", filename); while(p < buf + filelen) { l = p + strspn(p, " "); p += strlen(p) + 1; line++; @@ -989,8 +989,7 @@ struct serveripcclist : serverconfigfile else ipranges.add(ir); } - else - logline(ACLOG_INFO," error in line %d, file %s: failed to parse '%s'", line, filename, r ? r : l), errors++; + else mlog(ACLOG_INFO," error in line %d, file %s: failed to parse '%s'", line, filename, r ? r : l), errors++; } ipranges.sort(cmpiprange); int orglength = ipranges.length(); @@ -1001,13 +1000,13 @@ struct serveripcclist : serverconfigfile if(ipranges[i].ur <= ipranges[i - 1].ur) { if(cmpcomment(ipranges[i], ipranges[i - 1])) - logline(ACLOG_INFO," error: IP list entry %s|%s deleted because of overlapping %s|%s", iprtoa(ipranges[i], b1), printcomment(ipranges[i]), iprtoa(ipranges[i - 1], b2), printcomment(ipranges[i - 1])); + mlog(ACLOG_INFO," error: IP list entry %s|%s deleted because of overlapping %s|%s", iprtoa(ipranges[i], b1), printcomment(ipranges[i]), iprtoa(ipranges[i - 1], b2), printcomment(ipranges[i - 1])); else { if(ipranges[i].lr == ipranges[i - 1].lr && ipranges[i].ur == ipranges[i - 1].ur) - logline(ACLOG_VERBOSE," IP list entry %s got dropped (double entry)", iprtoa(ipranges[i], b1)); + mlog(ACLOG_VERBOSE," IP list entry %s got dropped (double entry)", iprtoa(ipranges[i], b1)); else - logline(ACLOG_VERBOSE," IP list entry %s got dropped (already covered by %s)", iprtoa(ipranges[i], b1), iprtoa(ipranges[i - 1], b2)); + mlog(ACLOG_VERBOSE," IP list entry %s got dropped (already covered by %s)", iprtoa(ipranges[i], b1), iprtoa(ipranges[i - 1], b2)); } ipranges.remove(i--); continue; } @@ -1015,13 +1014,13 @@ struct serveripcclist : serverconfigfile { if(!cmpcomment(ipranges[i], ipranges[i - 1])) // same comment { - logline(ACLOG_VERBOSE," IP list entries %s and %s are joined due to overlap (both %s)", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2), printcomment(ipranges[i])); + mlog(ACLOG_VERBOSE," IP list entries %s and %s are joined due to overlap (both %s)", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2), printcomment(ipranges[i])); ipranges[i - 1].ur = ipranges[i].ur; ipranges.remove(i--); continue; } else { - logline(ACLOG_INFO," error: IP list entries %s|%s and %s|%s are overlapping - dropping %s|%s", iprtoa(ipranges[i - 1], b1), printcomment(ipranges[i - 1]), + mlog(ACLOG_INFO," error: IP list entries %s|%s and %s|%s are overlapping - dropping %s|%s", iprtoa(ipranges[i - 1], b1), printcomment(ipranges[i - 1]), iprtoa(ipranges[i], b2), printcomment(ipranges[i]), b2, printcomment(ipranges[i])); errors++; ipranges.remove(i--); continue; @@ -1029,13 +1028,13 @@ struct serveripcclist : serverconfigfile } if(ipranges[i].lr - 1 == ipranges[i - 1].ur && !cmpcomment(ipranges[i], ipranges[i - 1])) { - logline(ACLOG_VERBOSE," concatenating IP list entries %s and %s (both %s)", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2), printcomment(ipranges[i])); + mlog(ACLOG_VERBOSE," concatenating IP list entries %s and %s (both %s)", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2), printcomment(ipranges[i])); ipranges[i - 1].ur = ipranges[i].ur; ipranges.remove(i--); continue; } } - if(logcheck(ACLOG_VERBOSE)) loopv(ipranges) logline(ACLOG_VERBOSE," %s %s", iprtoa(ipranges[i], b1), printcomment(ipranges[i])); - logline(ACLOG_INFO,"read %d (%d) IP list entries from '%s', %d errors, %d concatenated", ipranges.length(), orglength, filename, errors, concatd); + if(logcheck(ACLOG_VERBOSE)) loopv(ipranges) mlog(ACLOG_VERBOSE," %s %s", iprtoa(ipranges[i], b1), printcomment(ipranges[i])); + mlog(ACLOG_INFO,"read %d (%d) IP list entries from '%s', %d errors, %d concatenated", ipranges.length(), orglength, filename, errors, concatd); } const char *check(enet_uint32 ip, bool lock = false) // ip: host byte order @@ -1067,7 +1066,7 @@ struct serveripblacklist : serverconfigfile iprange ir; int line = 0, errors = 0; char *l, *r, *p = buf; - logline(ACLOG_VERBOSE,"reading ip blacklist '%s'", filename); + mlog(ACLOG_VERBOSE,"reading ip blacklist '%s'", filename); while(p < buf + filelen) { l = p; p += strlen(p) + 1; line++; @@ -1079,7 +1078,7 @@ struct serveripblacklist : serverconfigfile if(l[strspn(l, " ")]) { for(int i = (int)strlen(l) - 1; i > 0 && l[i] == ' '; i--) l[i] = '\0'; - logline(ACLOG_INFO," error in line %d, file %s: ignored '%s'", line, filename, l); + mlog(ACLOG_INFO," error in line %d, file %s: ignored '%s'", line, filename, l); errors++; } } @@ -1092,20 +1091,20 @@ struct serveripblacklist : serverconfigfile if(ipranges[i].ur <= ipranges[i - 1].ur) { if(ipranges[i].lr == ipranges[i - 1].lr && ipranges[i].ur == ipranges[i - 1].ur) - logline(ACLOG_VERBOSE," blacklist entry %s got dropped (double entry)", iprtoa(ipranges[i], b1)); + mlog(ACLOG_VERBOSE," blacklist entry %s got dropped (double entry)", iprtoa(ipranges[i], b1)); else - logline(ACLOG_VERBOSE," blacklist entry %s got dropped (already covered by %s)", iprtoa(ipranges[i], b1), iprtoa(ipranges[i - 1], b2)); + mlog(ACLOG_VERBOSE," blacklist entry %s got dropped (already covered by %s)", iprtoa(ipranges[i], b1), iprtoa(ipranges[i - 1], b2)); ipranges.remove(i--); continue; } if(ipranges[i].lr <= ipranges[i - 1].ur) { - logline(ACLOG_VERBOSE," blacklist entries %s and %s are joined due to overlap", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2)); + mlog(ACLOG_VERBOSE," blacklist entries %s and %s are joined due to overlap", iprtoa(ipranges[i - 1], b1), iprtoa(ipranges[i], b2)); ipranges[i - 1].ur = ipranges[i].ur; ipranges.remove(i--); continue; } } - if(logcheck(ACLOG_VERBOSE)) loopv(ipranges) logline(ACLOG_VERBOSE," %s", iprtoa(ipranges[i], b1)); - logline(ACLOG_INFO,"read %d (%d) blacklist entries from '%s', %d errors", ipranges.length(), orglength, filename, errors); + if(logcheck(ACLOG_VERBOSE)) loopv(ipranges) mlog(ACLOG_VERBOSE," %s", iprtoa(ipranges[i], b1)); + mlog(ACLOG_INFO,"read %d (%d) blacklist entries from '%s', %d errors", ipranges.length(), orglength, filename, errors); } bool check(enet_uint32 ip) // ip: network byte order @@ -1147,7 +1146,7 @@ struct servernickblacklist : serverconfigfile iprchain iprc; blackline bl; char *b, *l, *s, *r, *p = buf; - logline(ACLOG_VERBOSE,"reading nickname blacklist '%s'", filename); + mlog(ACLOG_VERBOSE,"reading nickname blacklist '%s'", filename); while(p < buf + filelen) { l = p; p += strlen(p) + 1; @@ -1199,14 +1198,14 @@ struct servernickblacklist : serverconfigfile bl.line = line; blacklines.add(bl); } - else { logline(ACLOG_INFO," error in line %d, file %s: unknown keyword '%s'", line, filename, l); errors++; } - if(s && s[strspn(s, " ")]) { logline(ACLOG_INFO," error in line %d, file %s: ignored '%s'", line, filename, s); errors++; } + else { mlog(ACLOG_INFO," error in line %d, file %s: unknown keyword '%s'", line, filename, l); errors++; } + if(s && s[strspn(s, " ")]) { mlog(ACLOG_INFO," error in line %d, file %s: ignored '%s'", line, filename, s); errors++; } } line++; } if(logcheck(ACLOG_VERBOSE)) { - logline(ACLOG_VERBOSE," nickname whitelist (%d entries):", whitelist.numelems); + mlog(ACLOG_VERBOSE," nickname whitelist (%d entries):", whitelist.numelems); string text, b; enumeratekt(whitelist, const char *, key, int, idx, { @@ -1217,9 +1216,9 @@ struct servernickblacklist : serverconfigfile if(ic.pwd) concatformatstring(text, " pwd:\"%s\"", hiddenpwd(ic.pwd)); else concatformatstring(text, " %s", iprtoa(ic.ipr, b)); } - logline(ACLOG_VERBOSE, " accept %s%s", key, text); + mlog(ACLOG_VERBOSE, " accept %s%s", key, text); }); - logline(ACLOG_VERBOSE," nickname blacklist (%d entries):", blacklines.length()); + mlog(ACLOG_VERBOSE," nickname blacklist (%d entries):", blacklines.length()); loopv(blacklines) { text[0] = '\0'; @@ -1228,10 +1227,10 @@ struct servernickblacklist : serverconfigfile int k = blacklines[i].frag[j]; if(k >= 0) { concatstring(text, " "); concatstring(text, blfraglist[k]); } } - logline(ACLOG_VERBOSE, " %2d block%s%s", blacklines[i].line, blacklines[i].ignorecase ? "i" : "", text); + mlog(ACLOG_VERBOSE, " %2d block%s%s", blacklines[i].line, blacklines[i].ignorecase ? "i" : "", text); } } - logline(ACLOG_INFO,"read %d + %d entries from nickname blacklist file '%s', %d errors", whitelist.numelems, blacklines.length(), filename, errors); + mlog(ACLOG_INFO,"read %d + %d entries from nickname blacklist file '%s', %d errors", whitelist.numelems, blacklines.length(), filename, errors); } int checkwhitelist(const client &c) @@ -1361,7 +1360,7 @@ struct serverforbiddenlist : serverconfigfile void read() { char *l, *p = buf; - logline(ACLOG_VERBOSE,"reading forbidden list '%s'", filename); + mlog(ACLOG_VERBOSE,"reading forbidden list '%s'", filename); while(p < buf + filelen) { l = p; p += strlen(p) + 1; @@ -1424,7 +1423,7 @@ struct serverpasswords : serverconfigfile const char *sep = " "; int i, line = 1, par[ADMINPWD_MAXPAR]; char *b, *l, *p = buf; - logline(ACLOG_VERBOSE,"reading admin passwords '%s'", filename); + mlog(ACLOG_VERBOSE,"reading admin passwords '%s'", filename); while(p < buf + filelen) { l = p; p += strlen(p) + 1; @@ -1443,12 +1442,12 @@ struct serverpasswords : serverconfigfile c.line = line; c.denyadmin = par[0] > 0; adminpwds.add(c); - logline(ACLOG_VERBOSE,"line%4d: %s %d", c.line, hiddenpwd(c.pwd), c.denyadmin ? 1 : 0); + mlog(ACLOG_VERBOSE,"line%4d: %s %d", c.line, hiddenpwd(c.pwd), c.denyadmin ? 1 : 0); } } line++; } - logline(ACLOG_INFO,"read %d admin passwords from '%s'", adminpwds.length() - staticpasses, filename); + mlog(ACLOG_INFO,"read %d admin passwords from '%s'", adminpwds.length() - staticpasses, filename); } bool check(const char *name, const char *pwd, int salt, pwddetail *detail = NULL, enet_uint32 address = 0) @@ -1512,7 +1511,7 @@ struct serverinfofile : serverconfigfile // plaintext info file, used for serve { string s; char *l, *p = buf; - logline(ACLOG_VERBOSE,"reading info text file '%s'", filename); + mlog(ACLOG_VERBOSE,"reading info text file '%s'", filename); while(p < buf + filelen) { l = p; p += strlen(p) + 1; @@ -1522,7 +1521,7 @@ struct serverinfofile : serverconfigfile // plaintext info file, used for serve } if(msg.length() > maxlen) { - logline(ACLOG_VERBOSE,"info text file '%s' truncated: %d -> %d", filename, msg.length(), maxlen); + mlog(ACLOG_VERBOSE,"info text file '%s' truncated: %d -> %d", filename, msg.length(), maxlen); msg.shrink(maxlen); } } diff --git a/source/src/serverms.cpp b/source/src/serverms.cpp index 2487ea3f..203310de 100644 --- a/source/src/serverms.cpp +++ b/source/src/serverms.cpp @@ -46,11 +46,10 @@ void disconnectmaster() ENetSocket connectmaster() { 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) { - logline(ACLOG_INFO, "looking up %s:%d...", mastername, masterport); + xlog(ACLOG_INFO, "looking up %s:%d...", mastername, masterport); masteraddress.port = masterport; if(!resolverwait(mastername, &masteraddress)) return ENET_SOCKET_NULL; } @@ -62,7 +61,7 @@ ENetSocket connectmaster() } if(sock == ENET_SOCKET_NULL || connectwithtimeout(sock, mastername, masteraddress) < 0) { - logline(ACLOG_WARNING, sock==ENET_SOCKET_NULL ? "could not open socket" : "could not connect"); + xlog(ACLOG_WARNING, sock==ENET_SOCKET_NULL ? "could not open socket" : "could not connect"); return ENET_SOCKET_NULL; } @@ -105,10 +104,10 @@ void processmasterinput() while(args < end && isspace(*args)) args++; if(!strncmp(input, "failreg", cmdlen)) - logline(ACLOG_WARNING, "master server registration failed: %s", args); + xlog(ACLOG_WARNING, "master server registration failed: %s", args); else if(!strncmp(input, "succreg", cmdlen)) { - logline(ACLOG_INFO, "master server registration succeeded"); + xlog(ACLOG_INFO, "master server registration succeeded"); } else processmasterinput(input, cmdlen, args); @@ -330,7 +329,8 @@ void serverms(int mode, int numplayers, int minremain, char *smapname, int milli void servermsinit(bool listen) { if(scl.master && *scl.master) copystring(mastername, scl.master); - usemaster = !listen || (listen && scl.master && scl.ssk); // true: connect to master, false: LAN-only server + usemaster = !listen || (listen && scl.master && scl.ssk && scl.maxclients <= MAXCLIENTSONMASTER); // true: connect to master, false: LAN-only server + if(scl.maxclients > MAXCLIENTSONMASTER) mlog(ACLOG_WARNING, "maxclient exceeded: cannot register"); disconnectmaster(); if(listen) @@ -338,7 +338,7 @@ void servermsinit(bool listen) ENetAddress address = { ENET_HOST_ANY, (enet_uint16) CUBE_SERVINFO_PORT(scl.serverport) }; if(*scl.ip) { - if(enet_address_set_host(&address, scl.ip) < 0) logline(ACLOG_WARNING, "server ip \"%s\" not resolved", scl.ip); + if(enet_address_set_host(&address, scl.ip) < 0) mlog(ACLOG_WARNING, "server ip \"%s\" not resolved", scl.ip); else serveraddress.host = address.host; } @@ -358,8 +358,8 @@ void servermsinit(bool listen) enet_socket_destroy(lansock); lansock = ENET_SOCKET_NULL; } - if(lansock == ENET_SOCKET_NULL) logline(ACLOG_WARNING, "could not create LAN server info socket"); + if(lansock == ENET_SOCKET_NULL) mlog(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"); + if(!usemaster) mlog(ACLOG_INFO, "server is LAN-only - without connection to masterserver"); } diff --git a/source/src/tools.h b/source/src/tools.h index 56fdba08..f984a88f 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -117,7 +117,8 @@ inline int iabs(int n) { return labs(n); } #define MAXSTRLEN 260 typedef char string[MAXSTRLEN]; -inline void vformatstring(char *d, const char *fmt, va_list v, int len = MAXSTRLEN) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; } +#define vformatstring(d,last,fmt) { va_list ap; va_start(ap, last); vformatstring_(d, fmt, ap); va_end(ap); } +inline void vformatstring_(char *d, const char *fmt, va_list v, int len = MAXSTRLEN) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; } inline char *copystring(char *d, const char *s, size_t len = MAXSTRLEN) { strncpy(d, s, len); d[len-1] = 0; return d; } inline char *concatstring(char *d, const char *s, size_t len = MAXSTRLEN) { size_t used = strlen(d); return used < len ? copystring(d+used, s, len-used) : d; } extern char *concatformatstring(char *d, const char *s, ...) PRINTFARGS(2, 3); @@ -128,16 +129,13 @@ struct stringformatter stringformatter(char *buf): buf((char *)buf) {} void operator()(const char *fmt, ...) PRINTFARGS(2, 3) { - va_list v; - va_start(v, fmt); - vformatstring(buf, fmt, v); - va_end(v); + vformatstring(buf, fmt, fmt); } }; #define formatstring(d) stringformatter((char *)d) #define defformatstring(d) string d; formatstring(d) -#define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); } +#define defvformatstring(d,last,fmt) string d; vformatstring(d,last,fmt) #define loopv(v) for(int i = 0; i<(v).length(); i++) #define loopvj(v) for(int j = 0; j<(v).length(); j++)