From: divverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Sun, 24 Aug 2008 19:50:08 +0000 (+0000)
Subject: rcon: use multiple reply packets to fit any size (where "any" means "as big as the... 
X-Git-Tag: xonotic-v0.1.0preview~2106
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a346c169ee4fe6934963a4e82417417c2c991b5d;p=xonotic%2Fdarkplaces.git

rcon: use multiple reply packets to fit any size (where "any" means "as big as the OS's socket buffer, about 32k on Linux)


git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8478 d7cf8633-e32d-0410-b094-e92efae38249
---

diff --git a/console.c b/console.c
index 14642f1b..07e65de3 100644
--- a/console.c
+++ b/console.c
@@ -106,7 +106,8 @@ int con_vislines;
 qboolean con_initialized;
 
 // used for server replies to rcon command
-qboolean rcon_redirect = false;
+lhnetsocket_t *rcon_redirect_sock = NULL;
+lhnetaddress_t *rcon_redirect_dest = NULL;
 int rcon_redirect_bufferpos = 0;
 char rcon_redirect_buffer[1400];
 
@@ -791,6 +792,35 @@ static char qfont_table[256] = {
 	'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
 };
 
+void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest)
+{
+	rcon_redirect_sock = sock;
+	rcon_redirect_dest = dest;
+	memcpy(rcon_redirect_buffer, "\377\377\377\377n", 5); // QW rcon print
+	rcon_redirect_bufferpos = 5;
+}
+
+void Con_Rcon_Redirect_Flush()
+{
+	rcon_redirect_buffer[rcon_redirect_bufferpos] = 0;
+	NetConn_WriteString(rcon_redirect_sock, rcon_redirect_buffer, rcon_redirect_dest);
+	memcpy(rcon_redirect_buffer, "\377\377\377\377n", 5); // QW rcon print
+	rcon_redirect_bufferpos = 5;
+}
+
+void Con_Rcon_Redirect_End()
+{
+	Con_Rcon_Redirect_Flush();
+	rcon_redirect_dest = NULL;
+	rcon_redirect_sock = NULL;
+}
+
+void Con_Rcon_Redirect_Abort()
+{
+	rcon_redirect_dest = NULL;
+	rcon_redirect_sock = NULL;
+}
+
 /*
 ================
 Con_Rcon_AddChar
@@ -807,8 +837,12 @@ void Con_Rcon_AddChar(char c)
 	// if this print is in response to an rcon command, add the character
 	// to the rcon redirect buffer
 
-	if (rcon_redirect && rcon_redirect_bufferpos < (int)sizeof(rcon_redirect_buffer) - 1)
+	if (rcon_redirect_dest)
+	{
 		rcon_redirect_buffer[rcon_redirect_bufferpos++] = c;
+		if(rcon_redirect_bufferpos >= (int)sizeof(rcon_redirect_buffer) - 1)
+			Con_Rcon_Redirect_Flush();
+	}
 	else if(*log_dest_udp.string) // don't duplicate rcon command responses here, these are sent another way
 	{
 		if(log_dest_buffer_pos == 0)
diff --git a/console.h b/console.h
index 4aa3e956..009b05bd 100644
--- a/console.h
+++ b/console.h
@@ -28,9 +28,9 @@ extern int con_totallines;
 extern int con_backscroll;
 extern qboolean con_initialized;
 
-extern qboolean rcon_redirect;
-extern int rcon_redirect_bufferpos;
-extern char rcon_redirect_buffer[1400];
+void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest);
+void Con_Rcon_Redirect_End();
+void Con_Rcon_Redirect_Abort();
 
 void Con_CheckResize (void);
 void Con_Init (void);
diff --git a/host.c b/host.c
index f4ee0b41..1e62ec9e 100644
--- a/host.c
+++ b/host.c
@@ -103,7 +103,8 @@ void Host_Error (const char *error, ...)
 	va_list argptr;
 
 	// turn off rcon redirect if it was active when the crash occurred
-	rcon_redirect = false;
+	// to prevent loops when it is a networking problem
+	Con_Rcon_Redirect_Abort();
 
 	va_start (argptr,error);
 	dpvsnprintf (hosterrorstring1,sizeof(hosterrorstring1),error,argptr);
diff --git a/netconn.c b/netconn.c
index 661455b9..43327ace 100755
--- a/netconn.c
+++ b/netconn.c
@@ -2383,8 +2383,9 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
 						s_ptr += l + 1;
 					}
 					Con_Printf("\n");
-					rcon_redirect = true;
-					rcon_redirect_bufferpos = 0;
+
+					if (!host_client || !host_client->netconnection || LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) != LHNETADDRESSTYPE_LOOP)
+						Con_Rcon_Redirect_Init(mysocket, peeraddress);
 					while(s != endpos)
 					{
 						size_t l = strlen(s);
@@ -2397,27 +2398,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
 						}
 						s += l + 1;
 					}
-					rcon_redirect_buffer[rcon_redirect_bufferpos] = 0;
-					rcon_redirect = false;
-					// print resulting text to client
-					// if client is playing, send a reliable reply instead of
-					// a command packet
-					if (host_client)
-					{
-						// if the netconnection is loop, then this is the
-						// local player on a listen mode server, and it would
-						// result in duplicate printing to the console
-						// (not that the local player should be using rcon
-						//  when they have the console)
-						if (host_client->netconnection && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) != LHNETADDRESSTYPE_LOOP)
-							SV_ClientPrintf("%s", rcon_redirect_buffer);
-					}
-					else
-					{
-						// qw print command
-						dpsnprintf(response, sizeof(response), "\377\377\377\377n%s", rcon_redirect_buffer);
-						NetConn_WriteString(mysocket, response, peeraddress);
-					}
+					Con_Rcon_Redirect_End();
 				}
 				else
 				{