git-svn-id: http://bladebattles.com/kurok/SVN@11 20cd92bb-ff49-0410-b73e-96a06e42c3b9
[kurok.git] / net_dgrm.c
blobe5dbaaf326dd9ea1e601108f57841593d8f88d66
1 /*
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.
20 // net_dgrm.c
22 // This is enables a simple IP banning mechanism
23 #ifndef PSP
24 #define BAN_TEST
25 #endif
27 #ifdef BAN_TEST
28 #if defined(WIN32)
29 #include <windows.h>
30 #elif defined (NeXT)
31 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #else
34 #define AF_INET 2 /* internet */
35 struct in_addr
37 union
39 struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
40 struct { unsigned short s_w1,s_w2; } S_un_w;
41 unsigned long S_addr;
42 } S_un;
44 #define s_addr S_un.S_addr /* can be used for most tcp & ip code */
45 struct sockaddr_in
47 short sin_family;
48 unsigned short sin_port;
49 struct in_addr sin_addr;
50 char sin_zero[8];
52 char *inet_ntoa(struct in_addr in);
53 unsigned long inet_addr(const char *cp);
54 #endif
55 #endif // BAN_TEST
57 #include "quakedef.h"
58 #include "net_dgrm.h"
60 // these two macros are to make the code more readable
61 #define sfunc net_landrivers[sock->landriver]
62 #define dfunc net_landrivers[net_landriverlevel]
64 static int net_landriverlevel;
66 /* statistic counters */
67 int packetsSent = 0;
68 int packetsReSent = 0;
69 int packetsReceived = 0;
70 int receivedDuplicateCount = 0;
71 int shortPacketCount = 0;
72 int droppedDatagrams;
74 static int myDriverLevel;
76 struct
78 unsigned int length;
79 unsigned int sequence;
80 byte data[MAX_DATAGRAM];
81 } packetBuffer;
83 extern int m_return_state;
84 extern int m_state;
85 extern qboolean m_return_onerror;
86 extern char m_return_reason[32];
89 #ifdef DEBUG
90 char *StrAddr (struct qsockaddr *addr)
92 static char buf[34];
93 byte *p = (byte *)addr;
94 int n;
96 for (n = 0; n < 16; n++)
97 sprintf (buf + n * 2, "%02x", *p++);
98 return buf;
100 #endif
103 #ifdef BAN_TEST
104 unsigned long banAddr = 0x00000000;
105 unsigned long banMask = 0xffffffff;
107 void NET_Ban_f (void)
109 char addrStr [32];
110 char maskStr [32];
111 void (*print) (char *fmt, ...);
113 if (cmd_source == src_command)
115 if (!sv.active)
117 Cmd_ForwardToServer ();
118 return;
120 print = Con_Printf;
122 else
124 if (pr_global_struct->deathmatch && !host_client->privileged)
125 return;
126 print = SV_ClientPrintf;
129 switch (Cmd_Argc ())
131 case 1:
132 if (((struct in_addr *)&banAddr)->s_addr)
134 Q_strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr));
135 Q_strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask));
136 print("Banning %s [%s]\n", addrStr, maskStr);
138 else
139 print("Banning not active\n");
140 break;
142 case 2:
143 if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
144 banAddr = 0x00000000;
145 else
146 banAddr = inet_addr(Cmd_Argv(1));
147 banMask = 0xffffffff;
148 break;
150 case 3:
151 banAddr = inet_addr(Cmd_Argv(1));
152 banMask = inet_addr(Cmd_Argv(2));
153 break;
155 default:
156 print("BAN ip_address [mask]\n");
157 break;
160 #endif
163 int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
165 unsigned int packetLen;
166 unsigned int dataLen;
167 unsigned int eom;
169 #ifdef DEBUG
170 if (data->cursize == 0)
171 Sys_Error("Datagram_SendMessage: zero length message\n");
173 if (data->cursize > NET_MAXMESSAGE)
174 Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
176 if (sock->canSend == false)
177 Sys_Error("SendMessage: called with canSend == false\n");
178 #endif
180 Q_memcpy(sock->sendMessage, data->data, data->cursize);
181 sock->sendMessageLength = data->cursize;
183 if (data->cursize <= MAX_DATAGRAM)
185 dataLen = data->cursize;
186 eom = NETFLAG_EOM;
188 else
190 dataLen = MAX_DATAGRAM;
191 eom = 0;
193 packetLen = NET_HEADERSIZE + dataLen;
195 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
196 packetBuffer.sequence = BigLong(sock->sendSequence++);
197 Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
199 sock->canSend = false;
201 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
202 return -1;
204 sock->lastSendTime = net_time;
205 packetsSent++;
206 return 1;
210 int SendMessageNext (qsocket_t *sock)
212 unsigned int packetLen;
213 unsigned int dataLen;
214 unsigned int eom;
216 if (sock->sendMessageLength <= MAX_DATAGRAM)
218 dataLen = sock->sendMessageLength;
219 eom = NETFLAG_EOM;
221 else
223 dataLen = MAX_DATAGRAM;
224 eom = 0;
226 packetLen = NET_HEADERSIZE + dataLen;
228 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
229 packetBuffer.sequence = BigLong(sock->sendSequence++);
230 Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
232 sock->sendNext = false;
234 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
235 return -1;
237 sock->lastSendTime = net_time;
238 packetsSent++;
239 return 1;
243 int ReSendMessage (qsocket_t *sock)
245 unsigned int packetLen;
246 unsigned int dataLen;
247 unsigned int eom;
249 if (sock->sendMessageLength <= MAX_DATAGRAM)
251 dataLen = sock->sendMessageLength;
252 eom = NETFLAG_EOM;
254 else
256 dataLen = MAX_DATAGRAM;
257 eom = 0;
259 packetLen = NET_HEADERSIZE + dataLen;
261 packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
262 packetBuffer.sequence = BigLong(sock->sendSequence - 1);
263 Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
265 sock->sendNext = false;
267 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
268 return -1;
270 sock->lastSendTime = net_time;
271 packetsReSent++;
272 return 1;
276 qboolean Datagram_CanSendMessage (qsocket_t *sock)
278 if (sock->sendNext)
279 SendMessageNext (sock);
281 return sock->canSend;
285 qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
287 return true;
291 int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
293 int packetLen;
295 #ifdef DEBUG
296 if (data->cursize == 0)
297 Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
299 if (data->cursize > MAX_DATAGRAM)
300 Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
301 #endif
303 packetLen = NET_HEADERSIZE + data->cursize;
305 packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
306 packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
307 Q_memcpy (packetBuffer.data, data->data, data->cursize);
309 if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
310 return -1;
312 packetsSent++;
313 return 1;
317 int Datagram_GetMessage (qsocket_t *sock)
319 unsigned int length;
320 unsigned int flags;
321 int ret = 0;
322 struct qsockaddr readaddr;
323 unsigned int sequence;
324 unsigned int count;
326 #if 0
327 if (!sock->canSend)
328 if ((net_time - sock->lastSendTime) > 1.0)
329 ReSendMessage (sock);
330 #endif
332 while(1)
334 length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
336 // if ((rand() & 255) > 220)
337 // continue;
339 if (length == 0)
340 break;
342 if (length == -1)
344 Con_Printf("Read error\n");
345 return -1;
348 if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
350 #ifdef DEBUG
351 Con_DPrintf("Forged packet received\n");
352 Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
353 Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
354 #endif
355 continue;
358 if (length < NET_HEADERSIZE)
360 shortPacketCount++;
361 continue;
364 length = BigLong(packetBuffer.length);
365 flags = length & (~NETFLAG_LENGTH_MASK);
366 length &= NETFLAG_LENGTH_MASK;
368 if (flags & NETFLAG_CTL)
369 continue;
371 sequence = BigLong(packetBuffer.sequence);
372 packetsReceived++;
374 if (flags & NETFLAG_UNRELIABLE)
376 if (sequence < sock->unreliableReceiveSequence)
378 Con_DPrintf("Got a stale datagram\n");
379 ret = 0;
380 break;
382 if (sequence != sock->unreliableReceiveSequence)
384 count = sequence - sock->unreliableReceiveSequence;
385 droppedDatagrams += count;
386 Con_DPrintf("Dropped %u datagram(s)\n", count);
388 sock->unreliableReceiveSequence = sequence + 1;
390 length -= NET_HEADERSIZE;
392 SZ_Clear (&net_message);
393 SZ_Write (&net_message, packetBuffer.data, length);
395 ret = 2;
396 break;
399 if (flags & NETFLAG_ACK)
401 if (sequence != (sock->sendSequence - 1))
403 Con_DPrintf("Stale ACK received\n");
404 continue;
406 if (sequence == sock->ackSequence)
408 sock->ackSequence++;
409 if (sock->ackSequence != sock->sendSequence)
410 Con_DPrintf("ack sequencing error\n");
412 else
414 Con_DPrintf("Duplicate ACK received\n");
415 continue;
417 sock->sendMessageLength -= MAX_DATAGRAM;
418 if (sock->sendMessageLength > 0)
420 Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
421 sock->sendNext = true;
423 else
425 sock->sendMessageLength = 0;
426 sock->canSend = true;
428 continue;
431 if (flags & NETFLAG_DATA)
433 packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
434 packetBuffer.sequence = BigLong(sequence);
435 sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
437 if (sequence != sock->receiveSequence)
439 receivedDuplicateCount++;
440 continue;
442 sock->receiveSequence++;
444 length -= NET_HEADERSIZE;
446 if (flags & NETFLAG_EOM)
448 SZ_Clear(&net_message);
449 SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
450 SZ_Write(&net_message, packetBuffer.data, length);
451 sock->receiveMessageLength = 0;
453 ret = 1;
454 break;
457 Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
458 sock->receiveMessageLength += length;
459 continue;
463 if (sock->sendNext)
464 SendMessageNext (sock);
466 return ret;
470 void PrintStats(qsocket_t *s)
472 Con_Printf("canSend = %4u \n", s->canSend);
473 Con_Printf("sendSeq = %4u ", s->sendSequence);
474 Con_Printf("recvSeq = %4u \n", s->receiveSequence);
475 Con_Printf("\n");
478 void NET_Stats_f (void)
480 qsocket_t *s;
482 if (Cmd_Argc () == 1)
484 Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent);
485 Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived);
486 Con_Printf("reliable messages sent = %i\n", messagesSent);
487 Con_Printf("reliable messages received = %i\n", messagesReceived);
488 Con_Printf("packetsSent = %i\n", packetsSent);
489 Con_Printf("packetsReSent = %i\n", packetsReSent);
490 Con_Printf("packetsReceived = %i\n", packetsReceived);
491 Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount);
492 Con_Printf("shortPacketCount = %i\n", shortPacketCount);
493 Con_Printf("droppedDatagrams = %i\n", droppedDatagrams);
495 else if (Q_strcmp(Cmd_Argv(1), "*") == 0)
497 for (s = net_activeSockets; s; s = s->next)
498 PrintStats(s);
499 for (s = net_freeSockets; s; s = s->next)
500 PrintStats(s);
502 else
504 for (s = net_activeSockets; s; s = s->next)
505 if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
506 break;
507 if (s == NULL)
508 for (s = net_freeSockets; s; s = s->next)
509 if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
510 break;
511 if (s == NULL)
512 return;
513 PrintStats(s);
518 static qboolean testInProgress = false;
519 static int testPollCount;
520 static int testDriver;
521 static int testSocket;
523 static void Test_Poll(void);
524 PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll};
526 static void Test_Poll(void)
528 struct qsockaddr clientaddr;
529 int control;
530 int len;
531 char name[32];
532 char address[64];
533 int colors;
534 int frags;
535 int connectTime;
536 byte playerNumber;
538 net_landriverlevel = testDriver;
540 while (1)
542 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
543 if (len < sizeof(int))
544 break;
546 net_message.cursize = len;
548 MSG_BeginReading ();
549 control = BigLong(*((int *)net_message.data));
550 MSG_ReadLong();
551 if (control == -1)
552 break;
553 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
554 break;
555 if ((control & NETFLAG_LENGTH_MASK) != len)
556 break;
558 if (MSG_ReadByte() != CCREP_PLAYER_INFO)
559 Sys_Error("Unexpected repsonse to Player Info request\n");
561 playerNumber = MSG_ReadByte();
562 Q_strcpy(name, MSG_ReadString());
563 colors = MSG_ReadLong();
564 frags = MSG_ReadLong();
565 connectTime = MSG_ReadLong();
566 Q_strcpy(address, MSG_ReadString());
568 Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
571 testPollCount--;
572 if (testPollCount)
574 SchedulePollProcedure(&testPollProcedure, 0.1);
576 else
578 dfunc.CloseSocket(testSocket);
579 testInProgress = false;
583 static void Test_f (void)
585 char *host;
586 int n;
587 int max = MAX_SCOREBOARD;
588 struct qsockaddr sendaddr;
590 if (testInProgress)
591 return;
593 host = Cmd_Argv (1);
595 if (host && hostCacheCount)
597 for (n = 0; n < hostCacheCount; n++)
598 if (Q_strcasecmp (host, hostcache[n].name) == 0)
600 if (hostcache[n].driver != myDriverLevel)
601 continue;
602 net_landriverlevel = hostcache[n].ldriver;
603 max = hostcache[n].maxusers;
604 Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
605 break;
607 if (n < hostCacheCount)
608 goto JustDoIt;
611 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
613 if (!net_landrivers[net_landriverlevel].initialized)
614 continue;
616 // see if we can resolve the host name
617 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
618 break;
620 if (net_landriverlevel == net_numlandrivers)
621 return;
623 JustDoIt:
624 testSocket = dfunc.OpenSocket(0);
625 if (testSocket == -1)
626 return;
628 testInProgress = true;
629 testPollCount = 20;
630 testDriver = net_landriverlevel;
632 for (n = 0; n < max; n++)
634 SZ_Clear(&net_message);
635 // save space for the header, filled in later
636 MSG_WriteLong(&net_message, 0);
637 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
638 MSG_WriteByte(&net_message, n);
639 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
640 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
642 SZ_Clear(&net_message);
643 SchedulePollProcedure(&testPollProcedure, 0.1);
647 static qboolean test2InProgress = false;
648 static int test2Driver;
649 static int test2Socket;
651 static void Test2_Poll(void);
652 PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll};
654 static void Test2_Poll(void)
656 struct qsockaddr clientaddr;
657 int control;
658 int len;
659 char name[256];
660 char value[256];
662 net_landriverlevel = test2Driver;
663 name[0] = 0;
665 len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
666 if (len < sizeof(int))
667 goto Reschedule;
669 net_message.cursize = len;
671 MSG_BeginReading ();
672 control = BigLong(*((int *)net_message.data));
673 MSG_ReadLong();
674 if (control == -1)
675 goto Error;
676 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
677 goto Error;
678 if ((control & NETFLAG_LENGTH_MASK) != len)
679 goto Error;
681 if (MSG_ReadByte() != CCREP_RULE_INFO)
682 goto Error;
684 Q_strcpy(name, MSG_ReadString());
685 if (name[0] == 0)
686 goto Done;
687 Q_strcpy(value, MSG_ReadString());
689 Con_Printf("%-16.16s %-16.16s\n", name, value);
691 SZ_Clear(&net_message);
692 // save space for the header, filled in later
693 MSG_WriteLong(&net_message, 0);
694 MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
695 MSG_WriteString(&net_message, name);
696 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
697 dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
698 SZ_Clear(&net_message);
700 Reschedule:
701 SchedulePollProcedure(&test2PollProcedure, 0.05);
702 return;
704 Error:
705 Con_Printf("Unexpected repsonse to Rule Info request\n");
706 Done:
707 dfunc.CloseSocket(test2Socket);
708 test2InProgress = false;
709 return;
712 static void Test2_f (void)
714 char *host;
715 int n;
716 struct qsockaddr sendaddr;
718 if (test2InProgress)
719 return;
721 host = Cmd_Argv (1);
723 if (host && hostCacheCount)
725 for (n = 0; n < hostCacheCount; n++)
726 if (Q_strcasecmp (host, hostcache[n].name) == 0)
728 if (hostcache[n].driver != myDriverLevel)
729 continue;
730 net_landriverlevel = hostcache[n].ldriver;
731 Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
732 break;
734 if (n < hostCacheCount)
735 goto JustDoIt;
738 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
740 if (!net_landrivers[net_landriverlevel].initialized)
741 continue;
743 // see if we can resolve the host name
744 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
745 break;
747 if (net_landriverlevel == net_numlandrivers)
748 return;
750 JustDoIt:
751 test2Socket = dfunc.OpenSocket(0);
752 if (test2Socket == -1)
753 return;
755 test2InProgress = true;
756 test2Driver = net_landriverlevel;
758 SZ_Clear(&net_message);
759 // save space for the header, filled in later
760 MSG_WriteLong(&net_message, 0);
761 MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
762 MSG_WriteString(&net_message, "");
763 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
764 dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
765 SZ_Clear(&net_message);
766 SchedulePollProcedure(&test2PollProcedure, 0.05);
770 int Datagram_Init ()
772 int i;
773 int csock;
775 myDriverLevel = net_driverlevel;
776 if(!host_initialized)
777 Cmd_AddCommand ("net_stats", NET_Stats_f);
779 if (COM_CheckParm("-nolan"))
780 return -1;
782 i = net_driver_to_use;//for (i = 0; i < net_numlandrivers; i++)
784 csock = net_landrivers[i].Init ();
785 if (csock == -1) return 0;
786 //continue;
787 net_landrivers[i].initialized = true;
788 net_landrivers[i].controlSock = csock;
791 if(!host_initialized)
793 #ifdef BAN_TEST
794 Cmd_AddCommand ("ban", NET_Ban_f);
795 #endif
796 Cmd_AddCommand ("test", Test_f);
797 Cmd_AddCommand ("test2", Test2_f);
800 return 0;
804 void Datagram_Shutdown (void)
806 int i;
809 // shutdown the lan drivers
811 for (i = 0; i < net_numlandrivers; i++)
813 if (net_landrivers[i].initialized)
815 net_landrivers[i].Shutdown ();
816 net_landrivers[i].initialized = false;
822 void Datagram_Close (qsocket_t *sock)
824 sfunc.CloseSocket(sock->socket);
828 void Datagram_Listen (qboolean state)
830 int i;
832 for (i = 0; i < net_numlandrivers; i++)
833 if (net_landrivers[i].initialized)
834 net_landrivers[i].Listen (state);
838 static qsocket_t *_Datagram_CheckNewConnections (void)
840 struct qsockaddr clientaddr;
841 struct qsockaddr newaddr;
842 int newsock;
843 int acceptsock;
844 qsocket_t *sock;
845 qsocket_t *s;
846 int len;
847 int command;
848 int control;
849 int ret;
851 acceptsock = dfunc.CheckNewConnections();
852 if (acceptsock == -1)
853 return NULL;
855 SZ_Clear(&net_message);
857 len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
858 if (len < sizeof(int))
859 return NULL;
860 net_message.cursize = len;
862 MSG_BeginReading ();
863 control = BigLong(*((int *)net_message.data));
864 MSG_ReadLong();
865 if (control == -1)
866 return NULL;
867 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
868 return NULL;
869 if ((control & NETFLAG_LENGTH_MASK) != len)
870 return NULL;
872 command = MSG_ReadByte();
873 if (command == CCREQ_SERVER_INFO)
875 if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
876 return NULL;
878 SZ_Clear(&net_message);
879 // save space for the header, filled in later
880 MSG_WriteLong(&net_message, 0);
881 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
882 dfunc.GetSocketAddr(acceptsock, &newaddr);
883 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
884 MSG_WriteString(&net_message, hostname.string);
885 MSG_WriteString(&net_message, sv.name);
886 MSG_WriteByte(&net_message, net_activeconnections);
887 MSG_WriteByte(&net_message, svs.maxclients);
888 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
889 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
890 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
891 SZ_Clear(&net_message);
892 return NULL;
895 if (command == CCREQ_PLAYER_INFO)
897 int playerNumber;
898 int activeNumber;
899 int clientNumber;
900 client_t *client;
902 playerNumber = MSG_ReadByte();
903 activeNumber = -1;
904 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
906 if (client->active)
908 activeNumber++;
909 if (activeNumber == playerNumber)
910 break;
913 if (clientNumber == svs.maxclients)
914 return NULL;
916 SZ_Clear(&net_message);
917 // save space for the header, filled in later
918 MSG_WriteLong(&net_message, 0);
919 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
920 MSG_WriteByte(&net_message, playerNumber);
921 MSG_WriteString(&net_message, client->name);
922 MSG_WriteLong(&net_message, client->colors);
923 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
924 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
925 MSG_WriteString(&net_message, client->netconnection->address);
926 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
927 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
928 SZ_Clear(&net_message);
930 return NULL;
933 if (command == CCREQ_RULE_INFO)
935 char *prevCvarName;
936 cvar_t *var;
938 // find the search start location
939 prevCvarName = MSG_ReadString();
940 if (*prevCvarName)
942 var = Cvar_FindVar (prevCvarName);
943 if (!var)
944 return NULL;
945 var = var->next;
947 else
948 var = cvar_vars;
950 // search for the next server cvar
951 while (var)
953 if (var->server)
954 break;
955 var = var->next;
958 // send the response
960 SZ_Clear(&net_message);
961 // save space for the header, filled in later
962 MSG_WriteLong(&net_message, 0);
963 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
964 if (var)
966 MSG_WriteString(&net_message, var->name);
967 MSG_WriteString(&net_message, var->string);
969 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
970 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
971 SZ_Clear(&net_message);
973 return NULL;
976 if (command != CCREQ_CONNECT)
977 return NULL;
979 if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
980 return NULL;
982 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
984 SZ_Clear(&net_message);
985 // save space for the header, filled in later
986 MSG_WriteLong(&net_message, 0);
987 MSG_WriteByte(&net_message, CCREP_REJECT);
988 MSG_WriteString(&net_message, "Incompatible version.\n");
989 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
990 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
991 SZ_Clear(&net_message);
992 return NULL;
995 #ifdef BAN_TEST
996 // check for a ban
997 if (clientaddr.sa_family == AF_INET)
999 unsigned long testAddr;
1000 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
1001 if ((testAddr & banMask) == banAddr)
1003 SZ_Clear(&net_message);
1004 // save space for the header, filled in later
1005 MSG_WriteLong(&net_message, 0);
1006 MSG_WriteByte(&net_message, CCREP_REJECT);
1007 MSG_WriteString(&net_message, "You have been banned.\n");
1008 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1009 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1010 SZ_Clear(&net_message);
1011 return NULL;
1014 #endif
1016 // see if this guy is already connected
1017 for (s = net_activeSockets; s; s = s->next)
1019 if (s->driver != net_driverlevel)
1020 continue;
1021 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
1022 if (ret >= 0)
1024 // is this a duplicate connection reqeust?
1025 if (ret == 0 && net_time - s->connecttime < 2.0)
1027 // yes, so send a duplicate reply
1028 SZ_Clear(&net_message);
1029 // save space for the header, filled in later
1030 MSG_WriteLong(&net_message, 0);
1031 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1032 dfunc.GetSocketAddr(s->socket, &newaddr);
1033 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1034 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1035 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1036 SZ_Clear(&net_message);
1037 return NULL;
1039 // it's somebody coming back in from a crash/disconnect
1040 // so close the old qsocket and let their retry get them back in
1041 NET_Close(s);
1042 return NULL;
1046 // allocate a QSocket
1047 sock = NET_NewQSocket ();
1048 if (sock == NULL)
1050 // no room; try to let him know
1051 SZ_Clear(&net_message);
1052 // save space for the header, filled in later
1053 MSG_WriteLong(&net_message, 0);
1054 MSG_WriteByte(&net_message, CCREP_REJECT);
1055 MSG_WriteString(&net_message, "Server is full.\n");
1056 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1057 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1058 SZ_Clear(&net_message);
1059 return NULL;
1062 // allocate a network socket
1063 newsock = dfunc.OpenSocket(0);
1064 if (newsock == -1)
1066 NET_FreeQSocket(sock);
1067 return NULL;
1070 // connect to the client
1071 if (dfunc.Connect (newsock, &clientaddr) == -1)
1073 dfunc.CloseSocket(newsock);
1074 NET_FreeQSocket(sock);
1075 return NULL;
1078 // everything is allocated, just fill in the details
1079 sock->socket = newsock;
1080 sock->landriver = net_landriverlevel;
1081 sock->addr = clientaddr;
1082 Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));
1084 // send him back the info about the server connection he has been allocated
1085 SZ_Clear(&net_message);
1086 // save space for the header, filled in later
1087 MSG_WriteLong(&net_message, 0);
1088 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1089 dfunc.GetSocketAddr(newsock, &newaddr);
1090 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1091 // MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
1092 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1093 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1094 SZ_Clear(&net_message);
1096 return sock;
1099 qsocket_t *Datagram_CheckNewConnections (void)
1101 qsocket_t *ret = NULL;
1103 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1104 if (net_landrivers[net_landriverlevel].initialized)
1105 if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1106 break;
1107 return ret;
1111 static void _Datagram_SearchForHosts (qboolean xmit)
1113 int ret;
1114 int n;
1115 int i;
1116 struct qsockaddr readaddr;
1117 struct qsockaddr myaddr;
1118 int control;
1120 dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1121 if (xmit)
1123 SZ_Clear(&net_message);
1124 // save space for the header, filled in later
1125 MSG_WriteLong(&net_message, 0);
1126 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1127 MSG_WriteString(&net_message, "QUAKE");
1128 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1129 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1130 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1131 SZ_Clear(&net_message);
1134 while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1136 if (ret < sizeof(int))
1137 continue;
1138 net_message.cursize = ret;
1140 // don't answer our own query
1141 if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
1142 continue;
1144 // is the cache full?
1145 if (hostCacheCount == HOSTCACHESIZE)
1146 continue;
1148 MSG_BeginReading ();
1149 control = BigLong(*((int *)net_message.data));
1150 MSG_ReadLong();
1151 if (control == -1)
1152 continue;
1153 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
1154 continue;
1155 if ((control & NETFLAG_LENGTH_MASK) != ret)
1156 continue;
1158 if (MSG_ReadByte() != CCREP_SERVER_INFO)
1159 continue;
1161 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
1162 // search the cache for this server
1163 for (n = 0; n < hostCacheCount; n++)
1164 if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
1165 break;
1167 // is it already there?
1168 if (n < hostCacheCount)
1169 continue;
1171 // add it
1172 hostCacheCount++;
1173 Q_strcpy(hostcache[n].name, MSG_ReadString());
1174 Q_strcpy(hostcache[n].map, MSG_ReadString());
1175 hostcache[n].users = MSG_ReadByte();
1176 hostcache[n].maxusers = MSG_ReadByte();
1177 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
1179 Q_strcpy(hostcache[n].cname, hostcache[n].name);
1180 hostcache[n].cname[14] = 0;
1181 Q_strcpy(hostcache[n].name, "*");
1182 Q_strcat(hostcache[n].name, hostcache[n].cname);
1184 Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
1185 hostcache[n].driver = net_driverlevel;
1186 hostcache[n].ldriver = net_landriverlevel;
1187 Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
1189 // check for a name conflict
1190 for (i = 0; i < hostCacheCount; i++)
1192 if (i == n)
1193 continue;
1194 if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1196 i = Q_strlen(hostcache[n].name);
1197 if (i < 15 && hostcache[n].name[i-1] > '8')
1199 hostcache[n].name[i] = '0';
1200 hostcache[n].name[i+1] = 0;
1202 else
1203 hostcache[n].name[i-1]++;
1204 i = -1;
1210 void Datagram_SearchForHosts (qboolean xmit)
1212 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1214 if (hostCacheCount == HOSTCACHESIZE)
1215 break;
1216 if (net_landrivers[net_landriverlevel].initialized)
1217 _Datagram_SearchForHosts (xmit);
1222 static qsocket_t *_Datagram_Connect (char *host)
1224 struct qsockaddr sendaddr;
1225 struct qsockaddr readaddr;
1226 qsocket_t *sock;
1227 int newsock;
1228 int ret;
1229 int reps;
1230 double start_time;
1231 int control;
1232 char *reason;
1234 // see if we can resolve the host name
1235 if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1236 return NULL;
1238 newsock = dfunc.OpenSocket (0);
1239 if (newsock == -1)
1240 return NULL;
1242 sock = NET_NewQSocket ();
1243 if (sock == NULL)
1244 goto ErrorReturn2;
1245 sock->socket = newsock;
1246 sock->landriver = net_landriverlevel;
1248 // connect to the host
1249 if (dfunc.Connect (newsock, &sendaddr) == -1)
1250 goto ErrorReturn;
1252 // send the connection request
1253 Con_Printf("trying...\n"); SCR_UpdateScreen ();
1254 start_time = net_time;
1256 for (reps = 0; reps < 3; reps++)
1258 SZ_Clear(&net_message);
1259 // save space for the header, filled in later
1260 MSG_WriteLong(&net_message, 0);
1261 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1262 MSG_WriteString(&net_message, "QUAKE");
1263 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1264 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1265 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1266 SZ_Clear(&net_message);
1269 ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1270 // if we got something, validate it
1271 if (ret > 0)
1273 // is it from the right place?
1274 if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
1276 #ifdef DEBUG
1277 Con_Printf("wrong reply address\n");
1278 Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
1279 Con_Printf("Received: %s\n", StrAddr (&readaddr));
1280 SCR_UpdateScreen ();
1281 #endif
1282 ret = 0;
1283 continue;
1286 if (ret < sizeof(int))
1288 ret = 0;
1289 continue;
1292 net_message.cursize = ret;
1293 MSG_BeginReading ();
1295 control = BigLong(*((int *)net_message.data));
1296 MSG_ReadLong();
1297 if (control == -1)
1299 ret = 0;
1300 continue;
1302 if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL)
1304 ret = 0;
1305 continue;
1307 if ((control & NETFLAG_LENGTH_MASK) != ret)
1309 ret = 0;
1310 continue;
1313 sceKernelDelayThread(10);
1315 while (ret == 0 && (SetNetTime() - start_time) < 5.5);
1316 if (ret)
1317 break;
1318 Con_Printf("still trying...\n"); SCR_UpdateScreen ();
1319 start_time = SetNetTime();
1322 if (ret == 0)
1324 reason = "No Response";
1325 Con_Printf("%s\n", reason);
1326 Q_strcpy(m_return_reason, reason);
1327 goto ErrorReturn;
1330 if (ret == -1)
1332 reason = "Network Error";
1333 Con_Printf("%s\n", reason);
1334 Q_strcpy(m_return_reason, reason);
1335 goto ErrorReturn;
1338 ret = MSG_ReadByte();
1339 if (ret == CCREP_REJECT)
1341 reason = MSG_ReadString();
1342 Con_Printf(reason);
1343 Q_strncpy(m_return_reason, reason, 31);
1344 goto ErrorReturn;
1347 if (ret == CCREP_ACCEPT)
1349 Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1350 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1352 else
1354 reason = "Bad Response";
1355 Con_Printf("%s\n", reason);
1356 Q_strcpy(m_return_reason, reason);
1357 goto ErrorReturn;
1360 dfunc.GetNameFromAddr (&sendaddr, sock->address);
1362 Con_Printf ("Connection accepted\n");
1363 sock->lastMessageTime = SetNetTime();
1365 // switch the connection to the specified address
1366 if (dfunc.Connect (newsock, &sock->addr) == -1)
1368 reason = "Connect to Game failed";
1369 Con_Printf("%s\n", reason);
1370 Q_strcpy(m_return_reason, reason);
1371 goto ErrorReturn;
1374 m_return_onerror = false;
1375 return sock;
1377 ErrorReturn:
1378 NET_FreeQSocket(sock);
1379 ErrorReturn2:
1380 dfunc.CloseSocket(newsock);
1381 if (m_return_onerror)
1383 key_dest = key_menu;
1384 m_state = m_return_state;
1385 m_return_onerror = false;
1387 return NULL;
1390 qsocket_t *Datagram_Connect (char *host)
1392 qsocket_t *ret = NULL;
1394 for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1395 if (net_landrivers[net_landriverlevel].initialized)
1396 if ((ret = _Datagram_Connect (host)) != NULL)
1397 break;
1398 return ret;