2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // This is enables a simple IP banning mechanism
29 #include <sys/socket.h>
30 #include <arpa/inet.h>
32 #define AF_INET 2 /* internet */
37 struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
38 struct { unsigned short s_w1,s_w2; } S_un_w;
42 #define s_addr S_un.S_addr /* can be used for most tcp & ip code */
46 unsigned short sin_port;
47 struct in_addr sin_addr;
50 char *inet_ntoa(struct in_addr in);
51 unsigned long inet_addr(const char *cp);
58 // these two macros are to make the code more readable
59 #define sfunc net_landrivers[sock->landriver]
60 #define dfunc net_landrivers[net_landriverlevel]
62 static int net_landriverlevel;
64 /* statistic counters */
66 int packetsReSent = 0;
67 int packetsReceived = 0;
68 int receivedDuplicateCount = 0;
69 int shortPacketCount = 0;
72 static int myDriverLevel;
77 unsigned int sequence;
78 byte data[MAX_DATAGRAM];
81 extern int m_return_state;
83 extern qboolean m_return_onerror;
84 extern char m_return_reason[32];
88 char *StrAddr (struct qsockaddr *addr)
91 byte *p = (byte *)addr;
94 for (n = 0; n < 16; n++)
95 sprintf (buf + n * 2, "%02x", *p++);
102 unsigned long banAddr = 0x00000000;
103 unsigned long banMask = 0xffffffff;
105 void NET_Ban_f (void)
109 void (*print) (char *fmt, ...);
111 if (cmd_source == src_command)
115 Cmd_ForwardToServer ();
122 if (pr_global_struct->deathmatch)
124 print = SV_ClientPrintf;
130 if (((struct in_addr *)&banAddr)->s_addr)
132 strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr));
133 strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask));
134 print("Banning %s [%s]\n", addrStr, maskStr);
137 print("Banning not active\n");
141 if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
142 banAddr = 0x00000000;
144 banAddr = inet_addr(Cmd_Argv(1));
145 banMask = 0xffffffff;
149 banAddr = inet_addr(Cmd_Argv(1));
150 banMask = inet_addr(Cmd_Argv(2));
154 print("BAN ip_address [mask]\n");
161 int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
163 unsigned int packetLen;
164 unsigned int dataLen;
168 if (data->cursize == 0)
169 Sys_Error("Datagram_SendMessage: zero length message\n");
171 if (data->cursize > NET_MAXMESSAGE)
172 Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
174 if (sock->canSend == false)
175 Sys_Error("SendMessage: called with canSend == false\n");
178 memcpy(sock->sendMessage, data->data, data->cursize);
179 sock->sendMessageLength = data->cursize;
181 if (data->cursize <= MAX_DATAGRAM)
183 dataLen = data->cursize;
188 dataLen = MAX_DATAGRAM;
191 packetLen = NET_HEADERSIZE + dataLen;
193 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
194 packetBuffer.sequence = BigLong(sock->sendSequence++);
195 memcpy (packetBuffer.data, sock->sendMessage, dataLen);
197 sock->canSend = false;
199 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
202 sock->lastSendTime = net_time;
208 int SendMessageNext (qsocket_t *sock)
210 unsigned int packetLen;
211 unsigned int dataLen;
214 if (sock->sendMessageLength <= MAX_DATAGRAM)
216 dataLen = sock->sendMessageLength;
221 dataLen = MAX_DATAGRAM;
224 packetLen = NET_HEADERSIZE + dataLen;
226 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
227 packetBuffer.sequence = BigLong(sock->sendSequence++);
228 memcpy (packetBuffer.data, sock->sendMessage, dataLen);
230 sock->sendNext = false;
232 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
235 sock->lastSendTime = net_time;
241 int ReSendMessage (qsocket_t *sock)
243 unsigned int packetLen;
244 unsigned int dataLen;
247 if (sock->sendMessageLength <= MAX_DATAGRAM)
249 dataLen = sock->sendMessageLength;
254 dataLen = MAX_DATAGRAM;
257 packetLen = NET_HEADERSIZE + dataLen;
259 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
260 packetBuffer.sequence = BigLong(sock->sendSequence - 1);
261 memcpy (packetBuffer.data, sock->sendMessage, dataLen);
263 sock->sendNext = false;
265 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
268 sock->lastSendTime = net_time;
274 qboolean Datagram_CanSendMessage (qsocket_t *sock)
277 SendMessageNext (sock);
279 return sock->canSend;
283 qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
289 int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
294 if (data->cursize == 0)
295 Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
297 if (data->cursize > MAX_DATAGRAM)
298 Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
301 packetLen = NET_HEADERSIZE + data->cursize;
303 packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
304 packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
305 memcpy (packetBuffer.data, data->data, data->cursize);
307 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
315 int Datagram_GetMessage (qsocket_t *sock)
320 struct qsockaddr readaddr;
321 unsigned int sequence;
325 if ((net_time - sock->lastSendTime) > 1.0)
326 ReSendMessage (sock);
330 length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
332 // if ((rand() & 255) > 220)
340 Con_Printf("Read error\n");
344 if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
347 Con_DPrintf("Forged packet received\n");
348 Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
349 Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
354 if (length < NET_HEADERSIZE)
360 length = BigLong(packetBuffer.length);
361 flags = length & (~NETFLAG_LENGTH_MASK);
362 length &= NETFLAG_LENGTH_MASK;
364 if (flags & NETFLAG_CTL)
367 sequence = BigLong(packetBuffer.sequence);
370 if (flags & NETFLAG_UNRELIABLE)
372 if (sequence < sock->unreliableReceiveSequence)
374 Con_DPrintf("Got a stale datagram\n");
378 if (sequence != sock->unreliableReceiveSequence)
380 count = sequence - sock->unreliableReceiveSequence;
381 droppedDatagrams += count;
382 Con_DPrintf("Dropped %u datagram(s)\n", count);
384 sock->unreliableReceiveSequence = sequence + 1;
386 length -= NET_HEADERSIZE;
388 SZ_Clear (&net_message);
389 SZ_Write (&net_message, packetBuffer.data, length);
395 if (flags & NETFLAG_ACK)
397 if (sequence != (sock->sendSequence - 1))
399 Con_DPrintf("Stale ACK received\n");
402 if (sequence == sock->ackSequence)
405 if (sock->ackSequence != sock->sendSequence)
406 Con_DPrintf("ack sequencing error\n");
410 Con_DPrintf("Duplicate ACK received\n");
413 sock->sendMessageLength -= MAX_DATAGRAM;
414 if (sock->sendMessageLength > 0)
416 memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
417 sock->sendNext = true;
421 sock->sendMessageLength = 0;
422 sock->canSend = true;
427 if (flags & NETFLAG_DATA)
429 packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
430 packetBuffer.sequence = BigLong(sequence);
431 sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
433 if (sequence != sock->receiveSequence)
435 receivedDuplicateCount++;
438 sock->receiveSequence++;
440 length -= NET_HEADERSIZE;
442 if (flags & NETFLAG_EOM)
444 SZ_Clear(&net_message);
445 SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
446 SZ_Write(&net_message, packetBuffer.data, length);
447 sock->receiveMessageLength = 0;
453 memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
454 sock->receiveMessageLength += length;
460 SendMessageNext (sock);
466 void PrintStats(qsocket_t *s)
468 Con_Printf("canSend = %4u \n", s->canSend);
469 Con_Printf("sendSeq = %4u ", s->sendSequence);
470 Con_Printf("recvSeq = %4u \n", s->receiveSequence);
474 void NET_Stats_f (void)
478 if (Cmd_Argc () == 1)
480 Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent);
481 Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived);
482 Con_Printf("reliable messages sent = %i\n", messagesSent);
483 Con_Printf("reliable messages received = %i\n", messagesReceived);
484 Con_Printf("packetsSent = %i\n", packetsSent);
485 Con_Printf("packetsReSent = %i\n", packetsReSent);
486 Con_Printf("packetsReceived = %i\n", packetsReceived);
487 Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount);
488 Con_Printf("shortPacketCount = %i\n", shortPacketCount);
489 Con_Printf("droppedDatagrams = %i\n", droppedDatagrams);
491 else if (strcmp(Cmd_Argv(1), "*") == 0)
493 for (s = net_activeSockets; s; s = s->next)
495 for (s = net_freeSockets; s; s = s->next)
500 for (s = net_activeSockets; s; s = s->next)
501 if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
504 for (s = net_freeSockets; s; s = s->next)
505 if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
514 static qboolean testInProgress = false;
515 static int testPollCount;
516 static int testDriver;
517 static int testSocket;
519 static void Test_Poll(void);
520 PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll};
522 static void Test_Poll(void)
524 struct qsockaddr clientaddr;
534 net_landriverlevel = testDriver;
538 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
539 if (len < sizeof(int))
542 net_message.cursize = len;
545 control = BigLong(*((int *)net_message.data));
549 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
551 if ((control & NETFLAG_LENGTH_MASK) != len)
554 if (MSG_ReadByte() != CCREP_PLAYER_INFO)
555 Sys_Error("Unexpected repsonse to Player Info request\n");
557 playerNumber = MSG_ReadByte();
558 strcpy(name, MSG_ReadString());
559 colors = MSG_ReadLong();
560 frags = MSG_ReadLong();
561 connectTime = MSG_ReadLong();
562 strcpy(address, MSG_ReadString());
564 Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
570 SchedulePollProcedure(&testPollProcedure, 0.1);
574 dfunc.CloseSocket(testSocket);
575 testInProgress = false;
579 static void Test_f (void)
583 int max = MAX_SCOREBOARD;
584 struct qsockaddr sendaddr;
591 if (host && hostCacheCount)
593 for (n = 0; n < hostCacheCount; n++)
594 if (Q_strcasecmp (host, hostcache[n].name) == 0)
596 if (hostcache[n].driver != myDriverLevel)
598 net_landriverlevel = hostcache[n].ldriver;
599 max = hostcache[n].maxusers;
600 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
603 if (n < hostCacheCount)
607 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
609 if (!net_landrivers[net_landriverlevel].initialized)
612 // see if we can resolve the host name
613 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
616 if (net_landriverlevel == net_numlandrivers)
620 testSocket = dfunc.OpenSocket(0);
621 if (testSocket == -1)
624 testInProgress = true;
626 testDriver = net_landriverlevel;
628 for (n = 0; n < max; n++)
630 SZ_Clear(&net_message);
631 // save space for the header, filled in later
632 MSG_WriteLong(&net_message, 0);
633 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
634 MSG_WriteByte(&net_message, n);
635 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
636 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
638 SZ_Clear(&net_message);
639 SchedulePollProcedure(&testPollProcedure, 0.1);
643 static qboolean test2InProgress = false;
644 static int test2Driver;
645 static int test2Socket;
647 static void Test2_Poll(void);
648 PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll};
650 static void Test2_Poll(void)
652 struct qsockaddr clientaddr;
658 net_landriverlevel = test2Driver;
661 len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
662 if (len < sizeof(int))
665 net_message.cursize = len;
668 control = BigLong(*((int *)net_message.data));
672 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
674 if ((control & NETFLAG_LENGTH_MASK) != len)
677 if (MSG_ReadByte() != CCREP_RULE_INFO)
680 strcpy(name, MSG_ReadString());
683 strcpy(value, MSG_ReadString());
685 Con_Printf("%-16.16s %-16.16s\n", name, value);
687 SZ_Clear(&net_message);
688 // save space for the header, filled in later
689 MSG_WriteLong(&net_message, 0);
690 MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
691 MSG_WriteString(&net_message, name);
692 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
693 dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
694 SZ_Clear(&net_message);
697 SchedulePollProcedure(&test2PollProcedure, 0.05);
701 Con_Printf("Unexpected repsonse to Rule Info request\n");
703 dfunc.CloseSocket(test2Socket);
704 test2InProgress = false;
708 static void Test2_f (void)
712 struct qsockaddr sendaddr;
719 if (host && hostCacheCount)
721 for (n = 0; n < hostCacheCount; n++)
722 if (Q_strcasecmp (host, hostcache[n].name) == 0)
724 if (hostcache[n].driver != myDriverLevel)
726 net_landriverlevel = hostcache[n].ldriver;
727 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
730 if (n < hostCacheCount)
734 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
736 if (!net_landrivers[net_landriverlevel].initialized)
739 // see if we can resolve the host name
740 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
743 if (net_landriverlevel == net_numlandrivers)
747 test2Socket = dfunc.OpenSocket(0);
748 if (test2Socket == -1)
751 test2InProgress = true;
752 test2Driver = net_landriverlevel;
754 SZ_Clear(&net_message);
755 // save space for the header, filled in later
756 MSG_WriteLong(&net_message, 0);
757 MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
758 MSG_WriteString(&net_message, "");
759 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
760 dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
761 SZ_Clear(&net_message);
762 SchedulePollProcedure(&test2PollProcedure, 0.05);
766 int Datagram_Init (void)
771 myDriverLevel = net_driverlevel;
772 Cmd_AddCommand ("net_stats", NET_Stats_f);
774 if (COM_CheckParm("-nolan"))
777 for (i = 0; i < net_numlandrivers; i++)
779 csock = net_landrivers[i].Init ();
782 net_landrivers[i].initialized = true;
783 net_landrivers[i].controlSock = csock;
787 Cmd_AddCommand ("ban", NET_Ban_f);
789 Cmd_AddCommand ("test", Test_f);
790 Cmd_AddCommand ("test2", Test2_f);
796 void Datagram_Shutdown (void)
801 // shutdown the lan drivers
803 for (i = 0; i < net_numlandrivers; i++)
805 if (net_landrivers[i].initialized)
807 net_landrivers[i].Shutdown ();
808 net_landrivers[i].initialized = false;
814 void Datagram_Close (qsocket_t *sock)
816 sfunc.CloseSocket(sock->socket);
820 void Datagram_Listen (qboolean state)
824 for (i = 0; i < net_numlandrivers; i++)
825 if (net_landrivers[i].initialized)
826 net_landrivers[i].Listen (state);
830 static qsocket_t *_Datagram_CheckNewConnections (void)
832 struct qsockaddr clientaddr;
833 struct qsockaddr newaddr;
843 acceptsock = dfunc.CheckNewConnections();
844 if (acceptsock == -1)
847 SZ_Clear(&net_message);
849 len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
850 if (len < sizeof(int))
852 net_message.cursize = len;
855 control = BigLong(*((int *)net_message.data));
859 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
861 if ((control & NETFLAG_LENGTH_MASK) != len)
864 command = MSG_ReadByte();
865 if (command == CCREQ_SERVER_INFO)
867 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
870 SZ_Clear(&net_message);
871 // save space for the header, filled in later
872 MSG_WriteLong(&net_message, 0);
873 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
874 dfunc.GetSocketAddr(acceptsock, &newaddr);
875 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
876 MSG_WriteString(&net_message, hostname.string);
877 MSG_WriteString(&net_message, sv.name);
878 MSG_WriteByte(&net_message, net_activeconnections);
879 MSG_WriteByte(&net_message, svs.maxclients);
880 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
881 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
882 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
883 SZ_Clear(&net_message);
887 if (command == CCREQ_PLAYER_INFO)
894 playerNumber = MSG_ReadByte();
896 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
901 if (activeNumber == playerNumber)
905 if (clientNumber == svs.maxclients)
908 SZ_Clear(&net_message);
909 // save space for the header, filled in later
910 MSG_WriteLong(&net_message, 0);
911 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
912 MSG_WriteByte(&net_message, playerNumber);
913 MSG_WriteString(&net_message, client->name);
914 MSG_WriteLong(&net_message, client->colors);
915 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
916 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
917 MSG_WriteString(&net_message, client->netconnection->address);
918 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
919 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
920 SZ_Clear(&net_message);
925 if (command == CCREQ_RULE_INFO)
930 // find the search start location
931 prevCvarName = MSG_ReadString();
934 var = Cvar_FindVar (prevCvarName);
942 // search for the next server cvar
952 SZ_Clear(&net_message);
953 // save space for the header, filled in later
954 MSG_WriteLong(&net_message, 0);
955 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
958 MSG_WriteString(&net_message, var->name);
959 MSG_WriteString(&net_message, var->string);
961 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
962 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
963 SZ_Clear(&net_message);
968 if (command != CCREQ_CONNECT)
971 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
974 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
976 SZ_Clear(&net_message);
977 // save space for the header, filled in later
978 MSG_WriteLong(&net_message, 0);
979 MSG_WriteByte(&net_message, CCREP_REJECT);
980 MSG_WriteString(&net_message, "Incompatible version.\n");
981 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
982 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
983 SZ_Clear(&net_message);
989 if (clientaddr.sa_family == AF_INET)
991 unsigned long testAddr;
992 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
993 if ((testAddr & banMask) == banAddr)
995 SZ_Clear(&net_message);
996 // save space for the header, filled in later
997 MSG_WriteLong(&net_message, 0);
998 MSG_WriteByte(&net_message, CCREP_REJECT);
999 MSG_WriteString(&net_message, "You have been banned.\n");
1000 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1001 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1002 SZ_Clear(&net_message);
1008 // see if this guy is already connected
1009 for (s = net_activeSockets; s; s = s->next)
1011 if (s->driver != net_driverlevel)
1013 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
1016 // is this a duplicate connection reqeust?
1017 if (ret == 0 && net_time - s->connecttime < 2.0)
1019 // yes, so send a duplicate reply
1020 SZ_Clear(&net_message);
1021 // save space for the header, filled in later
1022 MSG_WriteLong(&net_message, 0);
1023 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1024 dfunc.GetSocketAddr(s->socket, &newaddr);
1025 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1026 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1027 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1028 SZ_Clear(&net_message);
1031 // it's somebody coming back in from a crash/disconnect
1032 // so close the old qsocket and let their retry get them back in
1038 // allocate a QSocket
1039 sock = NET_NewQSocket ();
1042 // no room; try to let him know
1043 SZ_Clear(&net_message);
1044 // save space for the header, filled in later
1045 MSG_WriteLong(&net_message, 0);
1046 MSG_WriteByte(&net_message, CCREP_REJECT);
1047 MSG_WriteString(&net_message, "Server is full.\n");
1048 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1049 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1050 SZ_Clear(&net_message);
1054 // allocate a network socket
1055 newsock = dfunc.OpenSocket(0);
1058 NET_FreeQSocket(sock);
1062 // connect to the client
1063 if (dfunc.Connect (newsock, &clientaddr) == -1)
1065 dfunc.CloseSocket(newsock);
1066 NET_FreeQSocket(sock);
1070 // everything is allocated, just fill in the details
1071 sock->socket = newsock;
1072 sock->landriver = net_landriverlevel;
1073 sock->addr = clientaddr;
1074 strcpy(sock->address, dfunc.AddrToString(&clientaddr));
1076 // send him back the info about the server connection he has been allocated
1077 SZ_Clear(&net_message);
1078 // save space for the header, filled in later
1079 MSG_WriteLong(&net_message, 0);
1080 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1081 dfunc.GetSocketAddr(newsock, &newaddr);
1082 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1083 // MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
1084 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1085 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1086 SZ_Clear(&net_message);
1091 qsocket_t *Datagram_CheckNewConnections (void)
1093 qsocket_t *ret = NULL;
1095 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1096 if (net_landrivers[net_landriverlevel].initialized)
1097 if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1103 static void _Datagram_SearchForHosts (qboolean xmit)
1108 struct qsockaddr readaddr;
1109 struct qsockaddr myaddr;
1112 dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1115 SZ_Clear(&net_message);
1116 // save space for the header, filled in later
1117 MSG_WriteLong(&net_message, 0);
1118 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1119 MSG_WriteString(&net_message, "QUAKE");
1120 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1121 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1122 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1123 SZ_Clear(&net_message);
1126 while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1128 if (ret < sizeof(int))
1130 net_message.cursize = ret;
1132 // don't answer our own query
1133 if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
1136 // is the cache full?
1137 if (hostCacheCount == HOSTCACHESIZE)
1140 MSG_BeginReading ();
1141 control = BigLong(*((int *)net_message.data));
1145 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
1147 if ((control & NETFLAG_LENGTH_MASK) != ret)
1150 if (MSG_ReadByte() != CCREP_SERVER_INFO)
1153 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
1154 // search the cache for this server
1155 for (n = 0; n < hostCacheCount; n++)
1156 if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
1159 // is it already there?
1160 if (n < hostCacheCount)
1165 strcpy(hostcache[n].name, MSG_ReadString());
1166 strcpy(hostcache[n].map, MSG_ReadString());
1167 hostcache[n].users = MSG_ReadByte();
1168 hostcache[n].maxusers = MSG_ReadByte();
1169 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
1171 strcpy(hostcache[n].cname, hostcache[n].name);
1172 hostcache[n].cname[14] = 0;
1173 strcpy(hostcache[n].name, "*");
1174 strcat(hostcache[n].name, hostcache[n].cname);
1176 memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
1177 hostcache[n].driver = net_driverlevel;
1178 hostcache[n].ldriver = net_landriverlevel;
1179 strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
1181 // check for a name conflict
1182 for (i = 0; i < hostCacheCount; i++)
1186 if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1188 i = strlen(hostcache[n].name);
1189 if (i < 15 && hostcache[n].name[i-1] > '8')
1191 hostcache[n].name[i] = '0';
1192 hostcache[n].name[i+1] = 0;
1195 hostcache[n].name[i-1]++;
1202 void Datagram_SearchForHosts (qboolean xmit)
1204 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1206 if (hostCacheCount == HOSTCACHESIZE)
1208 if (net_landrivers[net_landriverlevel].initialized)
1209 _Datagram_SearchForHosts (xmit);
1214 static qsocket_t *_Datagram_Connect (char *host)
1216 struct qsockaddr sendaddr;
1217 struct qsockaddr readaddr;
1226 // see if we can resolve the host name
1227 if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1230 newsock = dfunc.OpenSocket (0);
1234 sock = NET_NewQSocket ();
1237 sock->socket = newsock;
1238 sock->landriver = net_landriverlevel;
1240 // connect to the host
1241 if (dfunc.Connect (newsock, &sendaddr) == -1)
1244 // send the connection request
1245 Con_Printf("trying...\n"); SCR_UpdateScreen ();
1246 start_time = net_time;
1248 for (reps = 0; reps < 3; reps++)
1250 SZ_Clear(&net_message);
1251 // save space for the header, filled in later
1252 MSG_WriteLong(&net_message, 0);
1253 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1254 MSG_WriteString(&net_message, "QUAKE");
1255 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1256 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1257 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1258 SZ_Clear(&net_message);
1261 ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1262 // if we got something, validate it
1265 // is it from the right place?
1266 if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
1269 Con_Printf("wrong reply address\n");
1270 Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
1271 Con_Printf("Received: %s\n", StrAddr (&readaddr));
1272 SCR_UpdateScreen ();
1278 if (ret < sizeof(int))
1284 net_message.cursize = ret;
1285 MSG_BeginReading ();
1287 control = BigLong(*((int *)net_message.data));
1294 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
1299 if ((control & NETFLAG_LENGTH_MASK) != ret)
1306 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
1309 Con_Printf("still trying...\n"); SCR_UpdateScreen ();
1310 start_time = SetNetTime();
1315 reason = "No Response";
1316 Con_Printf("%s\n", reason);
1317 strcpy(m_return_reason, reason);
1323 reason = "Network Error";
1324 Con_Printf("%s\n", reason);
1325 strcpy(m_return_reason, reason);
1329 ret = MSG_ReadByte();
1330 if (ret == CCREP_REJECT)
1332 reason = MSG_ReadString();
1334 strncpy(m_return_reason, reason, 31);
1338 if (ret == CCREP_ACCEPT)
1340 memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1341 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1345 reason = "Bad Response";
1346 Con_Printf("%s\n", reason);
1347 strcpy(m_return_reason, reason);
1351 dfunc.GetNameFromAddr (&sendaddr, sock->address);
1353 Con_Printf ("Connection accepted\n");
1354 sock->lastMessageTime = SetNetTime();
1356 // switch the connection to the specified address
1357 if (dfunc.Connect (newsock, &sock->addr) == -1)
1359 reason = "Connect to Game failed";
1360 Con_Printf("%s\n", reason);
1361 strcpy(m_return_reason, reason);
1365 m_return_onerror = false;
1369 NET_FreeQSocket(sock);
1371 dfunc.CloseSocket(newsock);
1372 if (m_return_onerror)
1374 key_dest = key_menu;
1375 m_state = m_return_state;
1376 m_return_onerror = false;
1381 qsocket_t *Datagram_Connect (char *host)
1383 qsocket_t *ret = NULL;
1385 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1386 if (net_landrivers[net_landriverlevel].initialized)
1387 if ((ret = _Datagram_Connect (host)) != NULL)