X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=net_dgrm.c;h=194739f71870e0a133a012d6546f92c5f5ba119a;hp=b9ef1c19e6f160861823452ba3e59e5bce3e6233;hb=51b777708e8db285cd0d4f0911e92a90240d11f4;hpb=9f6e4476fe8049342ac61c87ab7286912c1ff97c diff --git a/net_dgrm.c b/net_dgrm.c index b9ef1c19..194739f7 100644 --- a/net_dgrm.c +++ b/net_dgrm.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -54,6 +54,9 @@ 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"}; // these two macros are to make the code more readable #define sfunc net_landrivers[sock->landriver] @@ -75,20 +78,15 @@ struct { unsigned int length; unsigned int sequence; - byte data[MAX_DATAGRAM]; + qbyte data[MAX_DATAGRAM]; } packetBuffer; -extern int m_return_state; -extern int m_state; -extern qboolean m_return_onerror; -extern char m_return_reason[32]; - //#ifdef DEBUG char *StrAddr (struct qsockaddr *addr) { static char buf[34]; - byte *p = (byte *)addr; + qbyte *p = (qbyte *)addr; int n; for (n = 0; n < 16; n++) @@ -106,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) { @@ -196,7 +194,7 @@ int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) sock->canSend = false; - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) return -1; sock->lastSendTime = net_time; @@ -229,7 +227,7 @@ int SendMessageNext (qsocket_t *sock) sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) return -1; sock->lastSendTime = net_time; @@ -262,7 +260,7 @@ int ReSendMessage (qsocket_t *sock) sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) return -1; sock->lastSendTime = net_time; @@ -304,7 +302,7 @@ int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) packetBuffer.sequence = BigLong(sock->unreliableSendSequence++); memcpy (packetBuffer.data, data->data, data->cursize); - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) return -1; packetsSent++; @@ -326,16 +324,13 @@ int Datagram_GetMessage (qsocket_t *sock) ReSendMessage (sock); while(1) - { - length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); - -// if ((rand() & 255) > 220) -// continue; + { + length = sfunc.Read (sock->socket, (qbyte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); if (length == 0) break; - if (length == -1) + if ((int)length == -1) { Con_Printf("Read error\n"); return -1; @@ -428,7 +423,7 @@ int Datagram_GetMessage (qsocket_t *sock) { packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK); packetBuffer.sequence = BigLong(sequence); - sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr); + sfunc.Write (sock->socket, (qbyte *)&packetBuffer, NET_HEADERSIZE, &readaddr); if (sequence != sock->receiveSequence) { @@ -492,18 +487,12 @@ void NET_Stats_f (void) { for (s = net_activeSockets; s; s = s->next) PrintStats(s); - 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; - 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,14 +518,15 @@ static void Test_Poll(void) int colors; int frags; int connectTime; - byte playerNumber; + 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; @@ -546,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(); @@ -578,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) @@ -652,6 +642,7 @@ static void Test2_Poll(void) struct qsockaddr clientaddr; int control; int len; + int c; char name[256]; char value[256]; @@ -659,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; @@ -669,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()); @@ -707,8 +699,8 @@ Done: static void Test2_f (void) { - char *host; - int n; + const char *host; + int n; struct qsockaddr sendaddr; if (test2InProgress) @@ -770,6 +762,7 @@ int Datagram_Init (void) myDriverLevel = net_driverlevel; Cmd_AddCommand ("net_stats", NET_Stats_f); + Cvar_RegisterVariable (&cl_port); if (COM_CheckParm("-nolan")) return -1; @@ -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); @@ -890,7 +896,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void) int activeNumber; int clientNumber; client_t *client; - + playerNumber = MSG_ReadByte(); activeNumber = -1; for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) @@ -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->server) - 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 @@ -1067,7 +1058,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void) return NULL; } - // everything is allocated, just fill in the details + // everything is allocated, just fill in the details sock->socket = newsock; sock->landriver = net_landriverlevel; sock->addr = clientaddr; @@ -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; @@ -1227,7 +1285,7 @@ static qsocket_t *_Datagram_Connect (char *host) if (dfunc.GetAddrFromName(host, &sendaddr) == -1) return NULL; - newsock = dfunc.OpenSocket (0); + newsock = dfunc.OpenSocket (cl_port.integer); if (newsock == -1) return NULL; @@ -1242,7 +1300,7 @@ static qsocket_t *_Datagram_Connect (char *host) goto ErrorReturn; // send the connection request - Con_Printf("trying...\n"); SCR_UpdateScreen (); + Con_Printf("trying...\n");CL_UpdateScreen();CL_UpdateScreen(); start_time = net_time; for (reps = 0; reps < 3; reps++) @@ -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)); - SCR_UpdateScreen (); -//#endif + CL_UpdateScreen (); 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; @@ -1306,7 +1362,7 @@ static qsocket_t *_Datagram_Connect (char *host) while (ret == 0 && (SetNetTime() - start_time) < 2.5); if (ret) break; - Con_Printf("still trying...\n"); SCR_UpdateScreen (); + Con_Printf("still trying...\n");CL_UpdateScreen();CL_UpdateScreen(); start_time = SetNetTime(); } @@ -1330,7 +1386,7 @@ static qsocket_t *_Datagram_Connect (char *host) if (ret == CCREP_REJECT) { reason = MSG_ReadString(); - Con_Printf(reason); + Con_Printf("%s", reason); strncpy(m_return_reason, reason, 31); goto ErrorReturn; } @@ -1350,7 +1406,7 @@ static qsocket_t *_Datagram_Connect (char *host) dfunc.GetNameFromAddr (&sendaddr, sock->address); - Con_Printf ("Connection accepted\n"); + Con_Printf ("Connection accepted to %s\n", sock->address); sock->lastMessageTime = SetNetTime(); // switch the connection to the specified address @@ -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); +}