]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - netconn.c
make IPv6 addresses actually work in server queries
[xonotic/darkplaces.git] / netconn.c
index 3f0796e54e9485027ae685c18c4f981cfc751412..f6e5a6f3d8124b2b8c4673318f78f32e5cf2c79a 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -32,7 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define DPMASTER_PORT 27950
 
 // note this defaults on for dedicated servers, off for listen servers
-cvar_t sv_public = {0, "sv_public", "0", "1: advertises this server on the master server (so that players can find it in the server browser); 0: allow direct queries only; -1: do not respond to direct queries; -2: do not allow anyone to connect"};
+cvar_t sv_public = {0, "sv_public", "0", "1: advertises this server on the master server (so that players can find it in the server browser); 0: allow direct queries only; -1: do not respond to direct queries; -2: do not allow anyone to connect; -3: already block at getchallenge level"};
+cvar_t sv_public_rejectreason = {0, "sv_public_rejectreason", "The server is closing.", "Rejection reason for connects when sv_public is -2"};
 static cvar_t sv_heartbeatperiod = {CVAR_SAVE, "sv_heartbeatperiod", "120", "how often to send heartbeat in seconds (only used if sv_public is 1)"};
 
 static cvar_t sv_masters [] =
@@ -1530,16 +1531,16 @@ static void NetConn_ClientParsePacket_ServerList_ParseDPList(lhnetaddress_t *sen
                                ifname = LHNETADDRESS_GetInterfaceName(senderaddress);
                                if (ifname != NULL)
                                {
-                                       dpsnprintf (ipstring, sizeof (ipstring), "[%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x%%%s]:%hu",
-                                                               data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
-                                                               data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16],
+                                       dpsnprintf (ipstring, sizeof (ipstring), "[%x:%x:%x:%x:%x:%x:%x:%x%%%s]:%hu",
+                                                               (data[1] << 8) | data[2], (data[3] << 8) | data[4], (data[5] << 8) | data[6], (data[7] << 8) | data[8],
+                                                               (data[9] << 8) | data[10], (data[11] << 8) | data[12], (data[13] << 8) | data[14], (data[15] << 8) | data[16],
                                                                ifname, port);
                                }
                                else
                                {
-                                       dpsnprintf (ipstring, sizeof (ipstring), "[%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x]:%hu",
-                                                               data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
-                                                               data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16],
+                                       dpsnprintf (ipstring, sizeof (ipstring), "[%x:%x:%x:%x:%x:%x:%x:%x]:%hu",
+                                                               (data[1] << 8) | data[2], (data[3] << 8) | data[4], (data[5] << 8) | data[6], (data[7] << 8) | data[8],
+                                                               (data[9] << 8) | data[10], (data[11] << 8) | data[12], (data[13] << 8) | data[14], (data[15] << 8) | data[16],
                                                                port);
                                }
                        }
@@ -1660,7 +1661,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        // update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
                        InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
                        // TODO: add userinfo stuff here instead of using NQ commands?
-                       NetConn_WriteString(mysocket, va("\377\377\377\377connect\\protocol\\darkplaces 3\\protocols\\%s\\challenge\\%s", protocolnames, string + 10), peeraddress);
+                       NetConn_WriteString(mysocket, va("\377\377\377\377connect\\protocol\\darkplaces 3\\protocols\\%s%s\\challenge\\%s", protocolnames, cls.connect_userinfo, string + 10), peeraddress);
                        return true;
                }
                if (length == 6 && !memcmp(string, "accept", 6) && cls.connect_trying)
@@ -1844,7 +1845,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        cls.qw_qport = qport.integer;
                        // update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
                        InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
-                       NetConn_WriteString(mysocket, va("\377\377\377\377connect %i %i %i \"%s\"\n", 28, cls.qw_qport, atoi(string + 1), cls.userinfo), peeraddress);
+                       NetConn_WriteString(mysocket, va("\377\377\377\377connect %i %i %i \"%s%s\"\n", 28, cls.qw_qport, atoi(string + 1), cls.userinfo, cls.connect_userinfo), peeraddress);
                        return true;
                }
                if (length >= 1 && string[0] == 'j' && cls.connect_trying)
@@ -2279,7 +2280,7 @@ static qboolean NetConn_BuildStatusResponse(const char* challenge, char* out_msg
                                        }
                                }
 
-                               if ((gamemode == GAME_NEXUIZ) && (teamplay.integer > 0))
+                               if ((gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC) && (teamplay.integer > 0))
                                {
                                        if(cl->frags == -666) // spectator
                                                strlcpy(teambuf, " 0", sizeof(teambuf));
@@ -2624,7 +2625,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        Com_HexDumpToConsole(data, length);
                }
 
-               if (length >= 12 && !memcmp(string, "getchallenge", 12) && (islocal || sv_public.integer > -2))
+               if (length >= 12 && !memcmp(string, "getchallenge", 12) && (islocal || sv_public.integer > -3))
                {
                        for (i = 0, best = 0, besttime = realtime;i < MAX_CHALLENGES;i++)
                        {
@@ -2647,7 +2648,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        NetConn_WriteString(mysocket, va("\377\377\377\377challenge %s", challenge[i].string), peeraddress);
                        return true;
                }
-               if (length > 8 && !memcmp(string, "connect\\", 8) && (islocal || sv_public.integer > -2))
+               if (length > 8 && !memcmp(string, "connect\\", 8))
                {
                        string += 7;
                        length -= 7;
@@ -2663,6 +2664,14 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        if (i == MAX_CHALLENGES)
                                return true;
 
+                       if(!(islocal || sv_public.integer > -2))
+                       {
+                               if (developer_extra.integer)
+                                       Con_Printf("Datagram_ParseConnectionless: sending \"reject %s\" to %s.\n", sv_public_rejectreason.string, addressstring2);
+                               NetConn_WriteString(mysocket, va("\377\377\377\377reject %s", sv_public_rejectreason.string), peeraddress);
+                               return true;
+                       }
+
                        // check engine protocol
                        if(!(s = SearchInfostring(string, "protocol")) || strcmp(s, "darkplaces 3"))
                        {
@@ -2863,8 +2872,20 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                case CCREQ_CONNECT:
                        if (developer_extra.integer)
                                Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2);
-                       if(!islocal && sv_public.integer <= -2)
+                       if(!(islocal || sv_public.integer > -2))
+                       {
+                               if (developer_extra.integer)
+                                       Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"%s\" to %s.\n", sv_public_rejectreason.string, addressstring2);
+                               SZ_Clear(&net_message);
+                               // save space for the header, filled in later
+                               MSG_WriteLong(&net_message, 0);
+                               MSG_WriteByte(&net_message, CCREP_REJECT);
+                               MSG_WriteString(&net_message, va("%s\n", sv_public_rejectreason.string));
+                               StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+                               NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
+                               SZ_Clear(&net_message);
                                break;
+                       }
 
                        protocolname = MSG_ReadString();
                        protocolnumber = MSG_ReadByte();
@@ -2964,7 +2985,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                case CCREQ_SERVER_INFO:
                        if (developer_extra.integer)
                                Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
-                       if(!islocal && sv_public.integer <= -1)
+                       if(!(islocal || sv_public.integer > -1))
                                break;
                        if (sv.active && !strcmp(MSG_ReadString(), "QUAKE"))
                        {
@@ -2995,7 +3016,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                case CCREQ_PLAYER_INFO:
                        if (developer_extra.integer)
                                Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2);
-                       if(!islocal && sv_public.integer <= -1)
+                       if(!(islocal || sv_public.integer > -1))
                                break;
                        if (sv.active)
                        {
@@ -3028,7 +3049,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                case CCREQ_RULE_INFO:
                        if (developer_extra.integer)
                                Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2);
-                       if(!islocal && sv_public.integer <= -1)
+                       if(!(islocal || sv_public.integer > -1))
                                break;
                        if (sv.active)
                        {
@@ -3368,6 +3389,7 @@ void NetConn_Init(void)
        Cvar_RegisterVariable(&net_address);
        Cvar_RegisterVariable(&net_address_ipv6);
        Cvar_RegisterVariable(&sv_public);
+       Cvar_RegisterVariable(&sv_public_rejectreason);
        Cvar_RegisterVariable(&sv_heartbeatperiod);
        for (i = 0;sv_masters[i].name;i++)
                Cvar_RegisterVariable(&sv_masters[i]);