]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - netconn.c
independent volume control for the 8 entity channels
[xonotic/darkplaces.git] / netconn.c
index 54f81fad61817b9d229c3a931bc3ce4086ac7fc0..d114d7c2008a0a28c0cc60e716f5de1d80fe47fc 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -38,7 +38,7 @@ static cvar_t sv_masters [] =
        {CVAR_SAVE, "sv_master4", "", "user-chosen master server 4"},
        {0, "sv_masterextra1", "ghdigital.com", "default master server 1 (admin: LordHavoc)"}, // admin: LordHavoc
        {0, "sv_masterextra2", "dpmaster.deathmask.net", "default master server 2 (admin: Willis)"}, // admin: Willis
-       {0, "sv_masterextra3", "excalibur.nvg.ntnu.no", "default master server 3 (admin: tChr)"}, // admin: tChr
+       {0, "sv_masterextra3", "dpmaster.tchr.no", "default master server 3 (admin: tChr)"}, // admin: tChr
        {0, NULL, NULL, NULL}
 };
 
@@ -327,11 +327,11 @@ static void ServerList_ViewList_Insert( serverlist_entry_t *entry )
 
        // FIXME: change this to be more readable (...)
        // now check whether it passes through the masks
-       for( start = 0 ; serverlist_andmasks[start].active && start < SERVERLIST_ANDMASKCOUNT ; start++ )
+       for( start = 0 ; start < SERVERLIST_ANDMASKCOUNT && serverlist_andmasks[start].active; start++ )
                if( !_ServerList_Entry_Mask( &serverlist_andmasks[start], &entry->info ) )
                        return;
 
-       for( start = 0 ; serverlist_ormasks[start].active && start < SERVERLIST_ORMASKCOUNT ; start++ )
+       for( start = 0 ; start < SERVERLIST_ORMASKCOUNT && serverlist_ormasks[start].active ; start++ )
                if( _ServerList_Entry_Mask( &serverlist_ormasks[start], &entry->info ) )
                        break;
        if( start == SERVERLIST_ORMASKCOUNT || (start > 0 && !serverlist_ormasks[start].active) )
@@ -433,7 +433,7 @@ static void _ServerList_Test(void)
                serverlist_cache[serverlist_cachecount].info.ping = 1000 + 1024 - i;
                dpsnprintf( serverlist_cache[serverlist_cachecount].info.name, sizeof(serverlist_cache[serverlist_cachecount].info.name), "Black's ServerList Test %i", i );
                serverlist_cache[serverlist_cachecount].finished = true;
-               sprintf( serverlist_cache[serverlist_cachecount].line1, "%i %s", serverlist_cache[serverlist_cachecount].info.ping, serverlist_cache[serverlist_cachecount].info.name );
+               dpsnprintf( serverlist_cache[serverlist_cachecount].line1, sizeof(serverlist_cache[serverlist_cachecount].info.line1), "%i %s", serverlist_cache[serverlist_cachecount].info.ping, serverlist_cache[serverlist_cachecount].info.name );
                ServerList_ViewList_Insert( &serverlist_cache[serverlist_cachecount] );
                serverlist_cachecount++;
        }
@@ -567,18 +567,18 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
                        sendreliable = true;
                }
                // outgoing unreliable packet number, and outgoing reliable packet number (0 or 1)
-               *((int *)(sendbuffer + 0)) = LittleLong((unsigned int)conn->qw.outgoing_sequence | ((unsigned int)sendreliable<<31));
+               *((int *)(sendbuffer + 0)) = LittleLong((unsigned int)conn->outgoing_unreliable_sequence | ((unsigned int)sendreliable<<31));
                // last received unreliable packet number, and last received reliable packet number (0 or 1)
                *((int *)(sendbuffer + 4)) = LittleLong((unsigned int)conn->qw.incoming_sequence | ((unsigned int)conn->qw.incoming_reliable_sequence<<31));
                packetLen = 8;
-               conn->qw.outgoing_sequence++;
+               conn->outgoing_unreliable_sequence++;
                // client sends qport in every packet
                if (conn == cls.netcon)
                {
                        *((short *)(sendbuffer + 8)) = LittleShort(cls.qw_qport);
                        packetLen += 2;
                        // also update cls.qw_outgoing_sequence
-                       cls.qw_outgoing_sequence = conn->qw.outgoing_sequence;
+                       cls.qw_outgoing_sequence = conn->outgoing_unreliable_sequence;
                }
                if (packetLen + (sendreliable ? conn->sendMessageLength : 0) > 1400)
                {
@@ -594,7 +594,7 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
                        conn->outgoing_reliablesize[conn->outgoing_packetcounter] += conn->sendMessageLength;
                        memcpy(sendbuffer + packetLen, conn->sendMessage, conn->sendMessageLength);
                        packetLen += conn->sendMessageLength;
-                       conn->qw.last_reliable_sequence = conn->qw.outgoing_sequence;
+                       conn->qw.last_reliable_sequence = conn->outgoing_unreliable_sequence;
                }
 
                // add the unreliable message if possible
@@ -715,10 +715,10 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
 
                        header = (unsigned int *)sendbuffer;
                        header[0] = BigLong(packetLen | NETFLAG_UNRELIABLE);
-                       header[1] = BigLong(conn->nq.unreliableSendSequence);
+                       header[1] = BigLong(conn->outgoing_unreliable_sequence);
                        memcpy(sendbuffer + NET_HEADERSIZE, data->data, data->cursize);
 
-                       conn->nq.unreliableSendSequence++;
+                       conn->outgoing_unreliable_sequence++;
 
                        conn->outgoing_unreliablesize[conn->outgoing_packetcounter] += packetLen;
 
@@ -1208,7 +1208,6 @@ void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peer
        cls.signon = 0;                         // need all the signon messages before playing
        cls.protocol = initialprotocol;
        // reset move sequence numbering on this new connection
-       cls.movesequence = 1;
        cls.servermovesequence = 0;
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
                Cmd_ForwardStringToServer("new");
@@ -1976,38 +1975,61 @@ void NetConn_ClearConnectFlood(lhnetaddress_t *peeraddress)
        }
 }
 
-qboolean RCon_Authenticate(const char *password, const char *s, const char *endpos)
+// returns a string describing the user level, or NULL for auth failure
+const char *RCon_Authenticate(const char *password, const char *s, const char *endpos)
 {
        const char *text;
+       qboolean hasquotes;
 
        if(!strcmp(rcon_password.string, password))
-               return true;
+               return "rcon";
        
        if(strcmp(rcon_restricted_password.string, password))
-               return false;
+               return NULL;
 
        for(text = s; text != endpos; ++text)
                if(*text > 0 && (*text < ' ' || *text == ';'))
-                       return false; // block possible exploits against the parser/alias expansion
+                       return NULL; // block possible exploits against the parser/alias expansion
 
        while(s != endpos)
        {
                size_t l = strlen(s);
                if(l)
                {
-                       text = s;
-
-                       if (!COM_ParseToken_Console(&text))
-                               return false;
-
-                       // com_token now contains the command
-                       if(!strstr(va(" %s ", rcon_restricted_commands.string), va(" %s ", com_token)))
-                               return false;
+                       hasquotes = (strchr(s, '"') != NULL);
+                       // sorry, we can't allow these substrings in wildcard expressions,
+                       // as they can mess with the argument counts
+                       text = rcon_restricted_commands.string;
+                       while(COM_ParseToken_Console(&text))
+                       {
+                               // com_token now contains a pattern to check for...
+                               if(strchr(com_token, '*') || strchr(com_token, '?')) // wildcard expression, * can only match a SINGLE argument
+                               {
+                                       if(!hasquotes)
+                                               if(matchpattern_with_separator(s, com_token, true, " ", true)) // note how we excluded tab, newline etc. above
+                                                       goto match;
+                               }
+                               else if(strchr(com_token, ' ')) // multi-arg expression? must match in whole
+                               {
+                                       if(!strcmp(com_token, s))
+                                               goto match;
+                               }
+                               else // single-arg expression? must match the beginning of the command
+                               {
+                                       if(!strcmp(com_token, s))
+                                               goto match;
+                                       if(!memcmp(va("%s ", com_token), s, strlen(com_token) + 1))
+                                               goto match;
+                               }
+                       }
+                       // if we got here, nothing matched!
+                       return NULL;
                }
+match:
                s += l + 1;
        }
 
-       return true;
+       return "restricted rcon";
 }
 
 extern void SV_SendServerinfo (client_t *client);
@@ -2202,11 +2224,12 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        password[i] = 0;
                        if (password[0] > ' ')
                        {
-                               if (RCon_Authenticate(password, s, endpos))
+                               const char *userlevel = RCon_Authenticate(password, s, endpos);
+                               if(userlevel)
                                {
                                        // looks like a legitimate rcon command with the correct password
                                        char *s_ptr = s;
-                                       Con_Printf("server received rcon command from %s:\n", host_client ? host_client->name : addressstring2);
+                                       Con_Printf("server received %s command from %s: ", userlevel, host_client ? host_client->name : addressstring2);
                                        while(s_ptr != endpos)
                                        {
                                                size_t l = strlen(s_ptr);
@@ -2221,7 +2244,12 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                        {
                                                size_t l = strlen(s);
                                                if(l)
+                                               {
+                                                       client_t *host_client_save = host_client;
                                                        Cmd_ExecuteString(s, src_command);
+                                                       host_client = host_client_save;
+                                                       // in case it is a command that changes host_client (like restart)
+                                               }
                                                s += l + 1;
                                        }
                                        rcon_redirect_buffer[rcon_redirect_bufferpos] = 0;
@@ -2657,7 +2685,7 @@ static void Net_Heartbeat_f(void)
 void PrintStats(netconn_t *conn)
 {
        if ((cls.state == ca_connected && cls.protocol == PROTOCOL_QUAKEWORLD) || (sv.active && sv.protocol == PROTOCOL_QUAKEWORLD))
-               Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->qw.outgoing_sequence, conn->qw.incoming_sequence);
+               Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->outgoing_unreliable_sequence, conn->qw.incoming_sequence);
        else
                Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->nq.sendSequence, conn->nq.receiveSequence);
 }