]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - net_dgrm.c
lightmap update checking is now handled very differently; each brush model has a...
[xonotic/darkplaces.git] / net_dgrm.c
index ac8cfa6c6db871664fc06a22a4e579526e106381..194739f71870e0a133a012d6546f92c5f5ba119a 100644 (file)
@@ -54,6 +54,7 @@ unsigned long inet_addr(const char *cp);
 
 #include "quakedef.h"
 #include "net_dgrm.h"
+#include "net_master.h"
 
 cvar_t cl_port = {CVAR_SAVE, "cl_port", "0"};
 
@@ -103,7 +104,7 @@ void NET_Ban_f (void)
 {
        char    addrStr [32];
        char    maskStr [32];
-       void    (*print) (char *fmt, ...);
+       void    (*print) (const char *fmt, ...);
 
        if (cmd_source == src_command)
        {
@@ -323,16 +324,13 @@ int       Datagram_GetMessage (qsocket_t *sock)
                        ReSendMessage (sock);
 
        while(1)
-       {       
+       {
                length = sfunc.Read (sock->socket, (qbyte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
 
-//     if ((rand() & 255) > 220)
-//             continue;
-
                if (length == 0)
                        break;
 
-               if (length == -1)
+               if ((int)length == -1)
                {
                        Con_Printf("Read error\n");
                        return -1;
@@ -489,20 +487,12 @@ void NET_Stats_f (void)
        {
                for (s = net_activeSockets; s; s = s->next)
                        PrintStats(s);
-               // LordHavoc: sockets are dynamically allocated now
-               //for (s = net_freeSockets; s; s = s->next)
-               //      PrintStats(s);
        }
        else
        {
                for (s = net_activeSockets; s; s = s->next)
                        if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
                                break;
-               // LordHavoc: sockets are dynamically allocated now
-               //if (s == NULL)
-               //      for (s = net_freeSockets; s; s = s->next)
-               //              if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
-               //                      break;
                if (s == NULL)
                        return;
                PrintStats(s);
@@ -529,13 +519,14 @@ static void Test_Poll(void)
        int             frags;
        int             connectTime;
        qbyte   playerNumber;
+       int             c;
 
        net_landriverlevel = testDriver;
 
        while (1)
        {
                len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
-               if (len < sizeof(int))
+               if (len < (int)sizeof(int))
                        break;
 
                net_message.cursize = len;
@@ -545,12 +536,13 @@ static void Test_Poll(void)
                MSG_ReadLong();
                if (control == -1)
                        break;
-               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+               if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                        break;
                if ((control & NETFLAG_LENGTH_MASK) != len)
                        break;
 
-               if (MSG_ReadByte() != CCREP_PLAYER_INFO)
+               c = MSG_ReadByte();
+               if (c != CCREP_PLAYER_INFO)
                        Sys_Error("Unexpected repsonse to Player Info request\n");
 
                playerNumber = MSG_ReadByte();
@@ -577,9 +569,8 @@ static void Test_Poll(void)
 
 static void Test_f (void)
 {
-       char    *host;
-       int             n;
-       int             max = MAX_SCOREBOARD;
+       const char *host;
+       int n, max = MAX_SCOREBOARD;
        struct qsockaddr sendaddr;
 
        if (testInProgress)
@@ -651,6 +642,7 @@ static void Test2_Poll(void)
        struct qsockaddr clientaddr;
        int             control;
        int             len;
+       int             c;
        char    name[256];
        char    value[256];
 
@@ -658,7 +650,7 @@ static void Test2_Poll(void)
        name[0] = 0;
 
        len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
-       if (len < sizeof(int))
+       if (len < (int)sizeof(int))
                goto Reschedule;
 
        net_message.cursize = len;
@@ -668,12 +660,13 @@ static void Test2_Poll(void)
        MSG_ReadLong();
        if (control == -1)
                goto Error;
-       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                goto Error;
        if ((control & NETFLAG_LENGTH_MASK) != len)
                goto Error;
 
-       if (MSG_ReadByte() != CCREP_RULE_INFO)
+       c = MSG_ReadByte();
+       if (c != CCREP_RULE_INFO)
                goto Error;
 
        strcpy(name, MSG_ReadString());
@@ -706,8 +699,8 @@ Done:
 
 static void Test2_f (void)
 {
-       char    *host;
-       int             n;
+       const char *host;
+       int n;
        struct qsockaddr sendaddr;
 
        if (test2InProgress)
@@ -839,6 +832,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        int                     command;
        int                     control;
        int                     ret;
+       int                     c;
 
        acceptsock = dfunc.CheckNewConnections();
        if (acceptsock == -1)
@@ -847,16 +841,26 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        SZ_Clear(&net_message);
 
        len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
-       if (len < sizeof(int))
+       if (len < (int)sizeof(int))
                return NULL;
        net_message.cursize = len;
 
        MSG_BeginReading ();
        control = BigLong(*((int *)net_message.data));
        MSG_ReadLong();
-       if (control == -1)
+
+       // Messages starting by 0xFFFFFFFF are master server messages
+       if ((unsigned int)control == 0xFFFFFFFF)
+       {
+               int responsesize = Master_HandleMessage();
+               if (responsesize > 0)
+               {
+                       dfunc.Write(acceptsock, net_message.data, responsesize, &clientaddr);
+                       SZ_Clear(&net_message);
+               }
                return NULL;
-       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+       }
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                return NULL;
        if ((control & NETFLAG_LENGTH_MASK) != len)
                return NULL;
@@ -867,6 +871,8 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                if (strcmp(MSG_ReadString(), "QUAKE") != 0)
                        return NULL;
 
+               Con_DPrintf("Datagram_CheckNewConnections: received CCREQ_SERVERINFO, replying.\n");
+
                SZ_Clear(&net_message);
                // save space for the header, filled in later
                MSG_WriteLong(&net_message, 0);
@@ -912,7 +918,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                MSG_WriteByte(&net_message, playerNumber);
                MSG_WriteString(&net_message, client->name);
                MSG_WriteLong(&net_message, client->colors);
-               MSG_WriteLong(&net_message, (int)client->edict->v.frags);
+               MSG_WriteLong(&net_message, (int)client->edict->v->frags);
                MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
                MSG_WriteString(&net_message, client->netconnection->address);
                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
@@ -929,23 +935,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
 
                // find the search start location
                prevCvarName = MSG_ReadString();
-               if (*prevCvarName)
-               {
-                       var = Cvar_FindVar (prevCvarName);
-                       if (!var)
-                               return NULL;
-                       var = var->next;
-               }
-               else
-                       var = cvar_vars;
-
-               // search for the next server cvar
-               while (var)
-               {
-                       if (var->flags & CVAR_NOTIFY)
-                               break;
-                       var = var->next;
-               }
+               var = Cvar_FindVarAfter(prevCvarName, CVAR_NOTIFY);
 
                // send the response
 
@@ -971,7 +961,8 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        if (strcmp(MSG_ReadString(), "QUAKE") != 0)
                return NULL;
 
-       if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
+       c = MSG_ReadByte();
+       if (c != NET_PROTOCOL_VERSION)
        {
                SZ_Clear(&net_message);
                // save space for the header, filled in later
@@ -1080,7 +1071,6 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        MSG_WriteByte(&net_message, CCREP_ACCEPT);
        dfunc.GetSocketAddr(newsock, &newaddr);
        MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
-//     MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        SZ_Clear(&net_message);
@@ -1100,16 +1090,95 @@ qsocket_t *Datagram_CheckNewConnections (void)
 }
 
 
+static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
+{
+       struct qsockaddr myaddr;
+       int control;
+       int c, n, i;
+
+       if (net_message.cursize < (int)sizeof(int))
+               return false;
+
+       // don't answer our own query
+       dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
+       //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0)
+       //      return false;
+
+       // is the cache full?
+       if (hostCacheCount == HOSTCACHESIZE)
+               return false;
+
+       MSG_BeginReading ();
+       control = BigLong(*((int *)net_message.data));
+       MSG_ReadLong();
+       if (control == -1)
+               return false;
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
+               return false;
+       if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize)
+               return false;
+
+       c = MSG_ReadByte();
+       if (c != CCREP_SERVER_INFO)
+               return false;
+
+       dfunc.GetAddrFromName(MSG_ReadString(), readaddr);
+       // search the cache for this server
+       for (n = 0; n < hostCacheCount; n++)
+               if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
+                       break;
+
+       // is it already there?
+       if (n < hostCacheCount)
+               return false;;
+
+       // add it
+       hostCacheCount++;
+       strcpy(hostcache[n].name, MSG_ReadString());
+       strcpy(hostcache[n].map, MSG_ReadString());
+       hostcache[n].users = MSG_ReadByte();
+       hostcache[n].maxusers = MSG_ReadByte();
+       c = MSG_ReadByte();
+       if (c != NET_PROTOCOL_VERSION)
+       {
+               strcpy(hostcache[n].cname, hostcache[n].name);
+               hostcache[n].cname[14] = 0;
+               strcpy(hostcache[n].name, "*");
+               strcat(hostcache[n].name, hostcache[n].cname);
+       }
+       memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
+       hostcache[n].driver = net_driverlevel;
+       hostcache[n].ldriver = net_landriverlevel;
+       strcpy(hostcache[n].cname, dfunc.AddrToString(readaddr));
+
+       // check for a name conflict
+       for (i = 0; i < hostCacheCount; i++)
+       {
+               if (i == n)
+                       continue;
+               if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
+               {
+                       i = strlen(hostcache[n].name);
+                       if (i < 15 && hostcache[n].name[i-1] > '8')
+                       {
+                               hostcache[n].name[i] = '0';
+                               hostcache[n].name[i+1] = 0;
+                       }
+                       else
+                               hostcache[n].name[i-1]++;
+                       i = -1;
+               }
+       }
+
+       return true;
+}
+
+
 static void _Datagram_SearchForHosts (qboolean xmit)
 {
        int             ret;
-       int             n;
-       int             i;
        struct qsockaddr readaddr;
-       struct qsockaddr myaddr;
-       int             control;
 
-       dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
        if (xmit)
        {
                SZ_Clear(&net_message);
@@ -1125,93 +1194,82 @@ static void _Datagram_SearchForHosts (qboolean xmit)
 
        while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
        {
-               if (ret < sizeof(int))
-                       continue;
                net_message.cursize = ret;
+               Datagram_HandleServerInfo (&readaddr);
+       }
+}
 
-               // don't answer our own query
-               if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
-                       continue;
-
-               // is the cache full?
+void Datagram_SearchForHosts (qboolean xmit)
+{
+       for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
+       {
                if (hostCacheCount == HOSTCACHESIZE)
-                       continue;
-
-               MSG_BeginReading ();
-               control = BigLong(*((int *)net_message.data));
-               MSG_ReadLong();
-               if (control == -1)
-                       continue;
-               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
-                       continue;
-               if ((control & NETFLAG_LENGTH_MASK) != ret)
-                       continue;
-
-               if (MSG_ReadByte() != CCREP_SERVER_INFO)
-                       continue;
+                       break;
+               if (net_landrivers[net_landriverlevel].initialized)
+                       _Datagram_SearchForHosts (xmit);
+       }
+}
 
-               dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
-               // search the cache for this server
-               for (n = 0; n < hostCacheCount; n++)
-                       if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
-                               break;
 
-               // is it already there?
-               if (n < hostCacheCount)
-                       continue;
+static qboolean _Datagram_SearchForInetHosts (const char *master)
+{
+       qboolean result = false;
+       struct qsockaddr masteraddr;
+       struct qsockaddr readaddr;
+       int ret;
 
-               // add it
-               hostCacheCount++;
-               strcpy(hostcache[n].name, MSG_ReadString());
-               strcpy(hostcache[n].map, MSG_ReadString());
-               hostcache[n].users = MSG_ReadByte();
-               hostcache[n].maxusers = MSG_ReadByte();
-               if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
+       if (master)
+       {
+               if (dfunc.GetAddrFromName(master, &masteraddr) != -1)
                {
-                       strcpy(hostcache[n].cname, hostcache[n].name);
-                       hostcache[n].cname[14] = 0;
-                       strcpy(hostcache[n].name, "*");
-                       strcat(hostcache[n].name, hostcache[n].cname);
+                       int portnum = 0;
+                       const char* port = strrchr (master, ':');
+                       if (port)
+                               portnum = atoi (port + 1);
+                       if (!portnum)
+                               portnum = MASTER_PORT;
+                       Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s\n", net_message.cursize, master);
+                       dfunc.SetSocketPort (&masteraddr, portnum);
+                       dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
                }
-               memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
-               hostcache[n].driver = net_driverlevel;
-               hostcache[n].ldriver = net_landriverlevel;
-               strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
+       }
 
-               // check for a name conflict
-               for (i = 0; i < hostCacheCount; i++)
-               {
-                       if (i == n)
-                               continue;
-                       if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
-                       {
-                               i = strlen(hostcache[n].name);
-                               if (i < 15 && hostcache[n].name[i-1] > '8')
-                               {
-                                       hostcache[n].name[i] = '0';
-                                       hostcache[n].name[i+1] = 0;
-                               }
-                               else
-                                       hostcache[n].name[i-1]++;
-                               i = -1;
-                       }
-               }
+       while ((ret = dfunc.Recv (net_message.data, net_message.maxsize, &readaddr)) > 0)
+       {
+               net_message.cursize = ret;
+               Con_DPrintf("Datagram_SearchForInetHosts: Recv received %d byte message\n", net_message.cursize);
+               Master_ParseServerList (&dfunc);
        }
+
+       while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
+       {
+               net_message.cursize = ret;
+               Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize);
+               if (Datagram_HandleServerInfo (&readaddr))
+                       result = true;
+       }
+
+       return result;
 }
 
-void Datagram_SearchForHosts (qboolean xmit)
+
+qboolean Datagram_SearchForInetHosts (const char *master)
 {
+       qboolean result = false;
        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        {
                if (hostCacheCount == HOSTCACHESIZE)
                        break;
                if (net_landrivers[net_landriverlevel].initialized)
-                       _Datagram_SearchForHosts (xmit);
+                       if (_Datagram_SearchForInetHosts (master))
+                               result = true;
        }
+
+       return result;
 }
 
 
-static qsocket_t *_Datagram_Connect (char *host)
+static qsocket_t *_Datagram_Connect (const char *host)
 {
        struct qsockaddr sendaddr;
        struct qsockaddr readaddr;
@@ -1265,17 +1323,15 @@ static qsocket_t *_Datagram_Connect (char *host)
                                // is it from the right place?
                                if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
                                {
-//#ifdef DEBUG
                                        Con_DPrintf("wrong reply address\n");
                                        Con_DPrintf("Expected: %s\n", StrAddr (&sendaddr));
                                        Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
                                        CL_UpdateScreen ();
-//#endif
                                        ret = 0;
                                        continue;
                                }
 
-                               if (ret < sizeof(int))
+                               if (ret < (int)sizeof(int))
                                {
                                        ret = 0;
                                        continue;
@@ -1291,7 +1347,7 @@ static qsocket_t *_Datagram_Connect (char *host)
                                        ret = 0;
                                        continue;
                                }
-                               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+                               if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                                {
                                        ret = 0;
                                        continue;
@@ -1378,7 +1434,7 @@ ErrorReturn2:
        return NULL;
 }
 
-qsocket_t *Datagram_Connect (char *host)
+qsocket_t *Datagram_Connect (const char *host)
 {
        qsocket_t *ret = NULL;
 
@@ -1388,3 +1444,30 @@ qsocket_t *Datagram_Connect (char *host)
                                break;
        return ret;
 }
+
+static void _Datagram_Heartbeat (const char *master)
+{
+       struct qsockaddr masteraddr;
+       int portnum;
+       const char* port;
+
+       if (dfunc.GetAddrFromName(master, &masteraddr) == -1)
+               return;
+
+       portnum = 0;
+       port = strrchr (master, ':');
+       if (port)
+               portnum = atoi (port + 1);
+       if (!portnum)
+               portnum = MASTER_PORT;
+       dfunc.SetSocketPort (&masteraddr, portnum);
+
+       dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
+}
+
+void Datagram_Heartbeat (const char *master)
+{
+       for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
+               if (net_landrivers[net_landriverlevel].initialized)
+                       _Datagram_Heartbeat (master);
+}