diff --git a/source/src/client.cpp b/source/src/client.cpp index 57799dd0..9002a855 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -376,7 +376,7 @@ void gets2c() // get updates from the server break; case ENET_EVENT_TYPE_DISCONNECT: - extern char *disc_reasons[]; + extern char *disc_reason(int reason); if(event.data>=DISC_NUM) event.data = DISC_NONE; if(event.peer==connpeer) { @@ -385,7 +385,7 @@ void gets2c() // get updates from the server } else { - if(!discmillis || event.data) conoutf("\f3server network error, disconnecting (%s) ...", disc_reasons[event.data]); + if(!discmillis || event.data) conoutf("\f3server network error, disconnecting (%s) ...", disc_reason(event.data)); disconnect(); } return; diff --git a/source/src/main.cpp b/source/src/main.cpp index d785a865..673ea9c3 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -161,7 +161,7 @@ VARF(gamespeed, 10, 100, 1000, if(multiplayer()) gamespeed = 100); int main(int argc, char **argv) { bool dedicated = false; - int fs = SDL_FULLSCREEN, depth = 0, bpp = 0, fsaa = 0, vsync = -1, par = 0, uprate = 0, maxcl = DEFAULTCLIENTS, tkthreshold = -5; + int fs = SDL_FULLSCREEN, depth = 0, bpp = 0, fsaa = 0, vsync = -1, par = 0, uprate = 0, maxcl = DEFAULTCLIENTS, scthreshold = -5; char *sdesc = "", *ip = "", *master = NULL, *passwd = "", *maprot = NULL, *adminpwd = NULL, *srvmsg = NULL; #define initlog(s) puts("init: " s) @@ -189,7 +189,7 @@ int main(int argc, char **argv) case 'x' : adminpwd = a; break; case 'c': maxcl = atoi(a); break; case 'o': srvmsg = a; break; - case 'k': tkthreshold = atoi(a); break; + case 'k': scthreshold = atoi(a); break; default: conoutf("unknown commandline option"); } else conoutf("unknown commandline argument"); @@ -206,7 +206,7 @@ int main(int argc, char **argv) if(enet_initialize()<0) fatal("Unable to initialise network module"); initclient(); - initserver(dedicated, uprate, sdesc, ip, master, passwd, maxcl, maprot, adminpwd, srvmsg, tkthreshold); // never returns if dedicated + initserver(dedicated, uprate, sdesc, ip, master, passwd, maxcl, maprot, adminpwd, srvmsg, scthreshold); // never returns if dedicated initlog("world"); empty_world(7, true); diff --git a/source/src/protos.h b/source/src/protos.h index 32bc1b67..c8ed93c8 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -286,7 +286,7 @@ extern char *hudgunnames[]; extern void renderhudgun(); // server -extern void initserver(bool dedicated, int uprate, char *sdesc, char *ip, char *master, char *passwd, int maxcl, char *maprot, char *adminpwd, char *srvmsg, int tkthreshold); +extern void initserver(bool dedicated, int uprate, char *sdesc, char *ip, char *master, char *passwd, int maxcl, char *maprot, char *adminpwd, char *srvmsg, int scthreshold); extern void cleanupserver(); extern void localconnect(); extern void localdisconnect(); diff --git a/source/src/server.cpp b/source/src/server.cpp index 0315cc01..32f8eb2f 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -181,7 +181,7 @@ bool buildworldstate() } } -int maxclients = DEFAULTCLIENTS, teamkillthreshold; +int maxclients = DEFAULTCLIENTS, scorethreshold; string smapname; char *adminpasswd = NULL, *motd = NULL; @@ -443,7 +443,11 @@ void sendteamtext(char *text, int sender) if(packet->referenceCount==0) enet_packet_destroy(packet); } -char *disc_reasons[] = { "normal", "end of packet", "client num", "kicked by server operator", "banned by server operator", "tag type", "connection refused due to ban", "wrong password", "failed admin login", "server FULL - maxclients", "server mastermode is \"private\"", "auto kick - did your score drop below the threshold?" }; +char *disc_reason(int reason) +{ + static char *disc_reasons[] = { "normal", "end of packet", "client num", "kicked by server operator", "banned by server operator", "tag type", "connection refused due to ban", "wrong password", "failed admin login", "server FULL - maxclients", "server mastermode is \"private\"", "auto kick - did your score drop below the threshold?" }; + return reason >= 0 && reason < sizeof(disc_reasons)/sizeof(disc_reasons[0]) ? disc_reasons[reason] : "unknown"; +} void disconnect_client(int n, int reason = -1) { @@ -452,7 +456,7 @@ void disconnect_client(int n, int reason = -1) client &c = *clients[n]; clientscore *sc = findscore(c, true); if(sc) *sc = c.score; - if(reason>=0) printf("disconnecting client (%s) [%s]\n", c.hostname, disc_reasons[reason]); + if(reason>=0) printf("disconnecting client (%s) [%s]\n", c.hostname, disc_reason(reason)); else printf("disconnected client (%s)\n", c.hostname); c.peer->data = (void *)-1; if(reason>=0) enet_peer_disconnect(c.peer, reason); @@ -731,6 +735,13 @@ void serveropcmd(int sender, int cmd, int a) sendf(-1, 1, "riii", SV_SERVOPCMD, cmd, a); } +int numnonlocalclients() +{ + int nonlocalclients = 0; + loopv(clients) if(clients[i]->type==ST_TCPIP) nonlocalclients++; + return nonlocalclients; +} + // sending of maps between clients string copyname; @@ -784,23 +795,34 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1 if(cl && !cl->isauthed) { - if(!serverpassword[0] && mastermode==MM_OPEN) cl->isauthed = true; + int nonlocalclients = numnonlocalclients(); + int primaryreason = serverpassword[0] ? DISC_WRONGPW : (mastermode!=MM_OPEN ? DISC_MASTERMODE : (nonlocalclients>maxclients ? DISC_MAXCLIENTS : (isbanned(sender) ? DISC_MBAN : DISC_NONE))); + + if(primaryreason == DISC_NONE) cl->isauthed = true; else if(chan==0) return; - else if(chan!=1 || getint(p)!=SV_PWD) disconnect_client(sender, serverpassword[0] ? DISC_WRONGPW : DISC_MASTERMODE); + else if(chan!=1 || getint(p)!=SV_PWD) disconnect_client(sender, primaryreason); else { getstring(text, p); - if(adminpasswd[0] && !strcmp(text, adminpasswd)) // pass admins through + if(adminpasswd[0] && !strcmp(text, adminpasswd)) // pass admins always through { cl->isauthed = true; - cl->role = CR_ADMIN; + changeclientrole(sender, CR_ADMIN, NULL, true); + loopv(bans) if(bans[i].address.host == cl->peer->address.host) { bans.remove(i); break; } // remove admin bans + if(nonlocalclients>maxclients) for(int i = 0; i < nonlocalclients; i++) if(i != sender && clients[i]->type==ST_TCPIP) + { + disconnect_client(i, DISC_NONE); // disconnect someone else to fit maxclients again + break; + } } else if(serverpassword[0]) { if(!strcmp(text, serverpassword)) cl->isauthed = true; else disconnect_client(sender, DISC_WRONGPW); } - else disconnect_client(sender, DISC_MASTERMODE); + else if(mastermode==MM_PRIVATE) disconnect_client(sender, DISC_MASTERMODE); + else if(nonlocalclients>maxclients) disconnect_client(sender, DISC_MAXCLIENTS); + else disconnect_client(sender, DISC_MBAN); } if(!cl->isauthed) return; } @@ -963,7 +985,7 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1 case SV_FRAGS: cl->score.frags = getint(p); - if(cl->score.frags < teamkillthreshold) disconnect_client(sender, DISC_AUTOKICK); + if(cl->score.frags < scorethreshold) disconnect_client(sender, DISC_AUTOKICK); QUEUE_MSG; break; @@ -1087,12 +1109,6 @@ void resetserverifempty() autoteam = true; } -int refuseconnect(int i) -{ - if(valid_client(i) && isbanned(i)) return DISC_BANREFUSE; - return DISC_NONE; -} - void sendworldstate() { static enet_uint32 lastsend = 0; @@ -1125,8 +1141,7 @@ void serverslice(int seconds, unsigned int timeout) // main server update, cal lastsec = seconds; - int nonlocalclients = 0; - loopv(clients) if(clients[i]->type==ST_TCPIP) nonlocalclients++; + int nonlocalclients = numnonlocalclients(); if((smode>1 || (smode==0 && nonlocalclients)) && seconds>mapend-minremain*60) checkintermission(); if(interm && seconds>interm) @@ -1175,9 +1190,7 @@ void serverslice(int seconds, unsigned int timeout) // main server update, cal char hn[1024]; s_strcpy(c.hostname, (enet_address_get_host_ip(&c.peer->address, hn, sizeof(hn))==0) ? hn : "unknown"); printf("client connected (%s)\n", c.hostname); - int reason = DISC_MAXCLIENTS; - if(nonlocalclients 0 ? min(maxcl, MAXCLIENTS) : DEFAULTCLIENTS; @@ -1240,7 +1253,7 @@ void initserver(bool dedicated, int uprate, char *sdesc, char *ip, char *master, readscfg(path(maprot)); if(adminpwd && adminpwd[0]) adminpasswd = adminpwd; if(srvmsg && srvmsg[0]) motd = srvmsg; - teamkillthreshold = min(-1, tkthreshold); + scorethreshold = min(-1, scthreshold); } resetserverifempty(); @@ -1264,7 +1277,7 @@ void fatal(char *s, char *o) { cleanupserver(); printf("fatal: %s\n", s); exit(E int main(int argc, char **argv) { - int uprate = 0, maxcl = DEFAULTCLIENTS, tkthreshold = -5; + int uprate = 0, maxcl = DEFAULTCLIENTS, scthreshold = -5; char *sdesc = "", *ip = "", *master = NULL, *passwd = "", *maprot = "", *adminpasswd = NULL, *srvmsg = NULL; for(int i = 1; i