]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
try making srcon work better with many rcon comamnds queued
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Oct 2009 10:25:17 +0000 (10:25 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Oct 2009 10:25:17 +0000 (10:25 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9282 d7cf8633-e32d-0410-b094-e92efae38249

client.h
host_cmd.c
netconn.c

index acab743af8b32db34498a07040461a7558e9c5ad..38b6f2682c5a1953ffbe846413b0dd9518b7a810 100644 (file)
--- a/client.h
+++ b/client.h
@@ -581,10 +581,11 @@ typedef struct client_static_s
        // (kept outside client_state_t because it's used between levels)
        protocolversion_t protocol;
 
-#define MAX_RCONS 64
+#define MAX_RCONS 16
        int rcon_trying;
        lhnetaddress_t rcon_addresses[MAX_RCONS];
        char rcon_commands[MAX_RCONS][MAX_INPUTLINE];
+       double rcon_timeout[MAX_RCONS];
        int rcon_ringpos;
 
 // connection information
index 895bb2d2d586d2fe82c2691646283f5aa3cb1a09..5b45a09d7eef736571c9bd7361fb34ec1abb8c7b 100644 (file)
@@ -34,6 +34,7 @@ cvar_t sv_status_privacy = {CVAR_SAVE, "sv_status_privacy", "0", "do not show IP
 cvar_t sv_status_show_qcstatus = {CVAR_SAVE, "sv_status_show_qcstatus", "0", "show the 'qcstatus' field in status replies, not the 'frags' field. Turn this on if your mod uses this field, and the 'frags' field on the other hand has no meaningful value."};
 cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
 cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
+cvar_t rcon_secure_challengetimeout = {0, "rcon_secure_challengetimeout", "5", "challenge-based secure rcon: time out requests if no challenge came within this time interval"};
 cvar_t rcon_address = {0, "rcon_address", "", "server address to send rcon commands to (when not connected to a server)"};
 cvar_t team = {CVAR_USERINFO | CVAR_SAVE, "team", "none", "QW team (4 character limit, example: blue)"};
 cvar_t skin = {CVAR_USERINFO | CVAR_SAVE, "skin", "", "QW player skin name (example: base)"};
@@ -2441,12 +2442,25 @@ void Host_Rcon_f (void) // credit: taken from QuakeWorld
                // simply put together the rcon packet and send it
                if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer > 1)
                {
-                       if(!cls.rcon_commands[cls.rcon_ringpos][0])
-                               ++cls.rcon_trying;
+                       if(cls.rcon_commands[cls.rcon_ringpos][0])
+                       {
+                               char s[128];
+                               LHNETADDRESS_ToString(&cls.rcon_addresses[cls.rcon_ringpos], s, sizeof(s), true);
+                               Con_Printf("rcon to %s (for command %s) failed: too many buffered commands (possibly increase MAX_RCONS)\n", s, cls.rcon_commands[cls.rcon_ringpos]);
+                               cls.rcon_commands[cls.rcon_ringpos][0] = 0;
+                               --cls.rcon_trying;
+                       }
+                       for (i = 0;i < MAX_RCONS;i++)
+                               if(cls.rcon_commands[i][0])
+                                       if (!LHNETADDRESS_Compare(&to, &cls.rcon_addresses[i]))
+                                               break;
+                       ++cls.rcon_trying;
+                       if(i >= MAX_RCONS)
+                               NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", &to); // otherwise we'll request the challenge later
                        strlcpy(cls.rcon_commands[cls.rcon_ringpos], Cmd_Args(), sizeof(cls.rcon_commands[cls.rcon_ringpos]));
                        cls.rcon_addresses[cls.rcon_ringpos] = to;
                        cls.rcon_ringpos = (cls.rcon_ringpos) % 64;
-                       NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", &to);
+                       cls.rcon_timeout[i] = realtime + rcon_secure_challengetimeout.value;
                }
                else if(rcon_secure.integer)
                {
@@ -2843,6 +2857,7 @@ void Host_InitCommands (void)
        Cvar_RegisterVariable (&rcon_password);
        Cvar_RegisterVariable (&rcon_address);
        Cvar_RegisterVariable (&rcon_secure);
+       Cvar_RegisterVariable (&rcon_secure_challengetimeout);
        Cmd_AddCommand ("rcon", Host_Rcon_f, "sends a command to the server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's); note: if rcon_secure is set, client and server clocks must be synced e.g. via NTP");
        Cmd_AddCommand ("srcon", Host_Rcon_f, "sends a command to the server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's); this always works as if rcon_secure is set; note: client and server clocks must be synced e.g. via NTP");
        Cmd_AddCommand ("pqrcon", Host_PQRcon_f, "sends a command to a proquake server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's)");
index 1dfb0cc008baa2fab45f1d520fbd7cf991ac0ec5..a66e2f323da0925e79cbe75db4885b3f51dd4075 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -88,6 +88,7 @@ static cvar_t rcon_restricted_password = {CVAR_PRIVATE, "rcon_restricted_passwor
 static cvar_t rcon_restricted_commands = {0, "rcon_restricted_commands", "", "allowed commands for rcon when the restricted mode password was used"};
 static cvar_t rcon_secure_maxdiff = {0, "rcon_secure_maxdiff", "5", "maximum time difference between rcon request and server system clock (to protect against replay attack)"};
 extern cvar_t rcon_secure;
+extern cvar_t rcon_secure_challengetimeout;
 
 /* statistic counters */
 static int packetsSent = 0;
@@ -1022,6 +1023,8 @@ static int clientport2 = -1;
 static int hostport = -1;
 void NetConn_UpdateSockets(void)
 {
+       int i, j;
+
        if (cls.state != ca_dedicated)
        {
                if (clientport2 != cl_netport.integer)
@@ -1045,6 +1048,23 @@ void NetConn_UpdateSockets(void)
                if (sv.active)
                        Con_Print("Changing \"port\" will not take effect until \"map\" command is executed.\n");
        }
+
+       for (j = 0;j < MAX_RCONS;j++)
+       {
+               i = (cls.rcon_ringpos + j + 1) % MAX_RCONS;
+               if(cls.rcon_commands[i][0])
+               {
+                       if(realtime > cls.rcon_timeout[i])
+                       {
+                               char s[128];
+                               LHNETADDRESS_ToString(&cls.rcon_addresses[i], s, sizeof(s), true);
+                               Con_Printf("rcon to %s (for command %s) failed: challenge request timed out\n", s, cls.rcon_commands[i]);
+                               cls.rcon_commands[i][0] = 0;
+                               --cls.rcon_trying;
+                               break;
+                       }
+               }
+       }
 }
 
 static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int length, protocolversion_t protocol, double newtimeout)
@@ -1556,12 +1576,15 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
 
                if (length > 10 && !memcmp(string, "challenge ", 10) && cls.rcon_trying)
                {
-                       int i;
-                       for (i = 0;i < MAX_RCONS;i++)
+                       int i, j;
+                       for (j = 0;j < MAX_RCONS;j++)
+                       {
+                               i = (cls.rcon_ringpos + j + 1) % MAX_RCONS;
                                if(cls.rcon_commands[i][0])
                                        if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
                                                break;
-                       if (i < MAX_RCONS)
+                       }
+                       if (j < MAX_RCONS)
                        {
                                char buf[1500];
                                char argbuf[1500];
@@ -1574,6 +1597,21 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                        NetConn_Write(mysocket, buf, 46 + strlen(buf + 46), peeraddress);
                                        cls.rcon_commands[i][0] = 0;
                                        --cls.rcon_trying;
+
+                                       for (i = 0;i < MAX_RCONS;i++)
+                                               if(cls.rcon_commands[i][0])
+                                                       if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
+                                                               break;
+                                       if(i < MAX_RCONS)
+                                       {
+                                               NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", peeraddress);
+                                               // extend the timeout on other requests as we asked for a challenge
+                                               for (i = 0;i < MAX_RCONS;i++)
+                                                       if(cls.rcon_commands[i][0])
+                                                               if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
+                                                                       cls.rcon_timeout[i] = realtime + rcon_secure_challengetimeout.value;
+                                       }
+
                                        return true; // we used up the challenge, so we can't use this oen for connecting now anyway
                                }
                        }