1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 /* FIXME - just for the htons() call below */
22 #if defined(_WIN32)
23 #ifdef _XBOX
24 #include <xtl.h>
25 #else
26 #include <winsock2.h>
27 #endif
28 #elif defined(MSB_FIRST)
29 // Is already big-endian
30 #ifndef htons
31 #define htons(x) (x)
32 #define ntohs(x) (x)
33 #endif
34 #elif defined(VITA) || defined(_3DS)
35 #else
36 #include <arpa/inet.h>
37 #endif
38
39 #include "cmd.h"
40 #include "console.h"
41 #include "net.h"
42 #include "quakedef.h"
43 #include "server.h"
44 #include "sys.h"
45 #include "zone.h"
46
47
48 #ifdef MSB_FIRST
49
50 #ifndef htons
51 #define htons(A) (A)
52 #endif
53
54 #ifndef htonl
55 #define htonl(A) (A)
56 #endif
57
58 #ifndef ntohs
59 #define ntohs(A) (A)
60 #endif
61
62 #ifndef ntohl
63 #define ntohl(A) (A)
64 #endif
65
66 #else
67
68 #ifndef htons
69 #define htons(A) ((((uint16_t)(A) & 0xff00) >> 8) | \
70 (((uint16_t)(A) & 0x00ff) << 8))
71 #endif
72
73 #ifndef htonl
74 #define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
75 (((uint32_t)(A) & 0x00ff0000) >> 8) | \
76 (((uint32_t)(A) & 0x0000ff00) << 8) | \
77 (((uint32_t)(A) & 0x000000ff) << 24))
78 #endif
79
80 #ifndef ntohs
81 #define ntohs htons
82 #endif
83
84 #ifndef ntohl
85 #define ntohl htohl
86 #endif
87 #endif
88
89 qsocket_t *net_activeSockets = NULL;
90 qsocket_t *net_freeSockets = NULL;
91 static int net_numsockets = 0;
92
93 qboolean tcpipAvailable = false;
94
95 int net_hostport;
96 int DEFAULTnet_hostport = 26000;
97
98 char my_tcpip_address[NET_NAMELEN];
99
100 static qboolean listening = false;
101
102 qboolean slistInProgress = false;
103 qboolean slistSilent = false;
104 qboolean slistLocal = true;
105 #define IS_LOOP_DRIVER(p) ((p) == &net_drivers[0])
106
107 static double slistStartTime;
108 static int slistLastShown;
109
110 static void Slist_Send(void);
111 static void Slist_Poll(void);
112 static PollProcedure slistSendProcedure = { NULL, 0.0, Slist_Send };
113 static PollProcedure slistPollProcedure = { NULL, 0.0, Slist_Poll };
114
115 sizebuf_t net_message;
116 int net_activeconnections = 0;
117
118 int messagesSent = 0;
119 int messagesReceived = 0;
120 int unreliableMessagesSent = 0;
121 int unreliableMessagesReceived = 0;
122
123 cvar_t net_messagetimeout = { "net_messagetimeout", "300" };
124 cvar_t hostname = { "hostname", "UNNAMED" };
125
126 net_driver_t *net_driver;
127 double net_time;
128
129
130 const char *
NET_AdrToString(const netadr_t * a)131 NET_AdrToString(const netadr_t *a)
132 {
133 static char s[64];
134 const byte *b = a->ip.b;
135
136 sprintf(s, "%i.%i.%i.%i:%i", b[0], b[1], b[2], b[3], ntohs(a->port));
137
138 return s;
139 }
140
141
142 double
SetNetTime(void)143 SetNetTime(void)
144 {
145 net_time = Sys_DoubleTime();
146 return net_time;
147 }
148
149
150 /*
151 * ===================
152 * NET_NewQSocket
153 *
154 * Called by drivers when a new communications endpoint is required
155 * The sequence and buffer fields will be filled in properly
156 * ===================
157 */
158 qsocket_t *
NET_NewQSocket(void)159 NET_NewQSocket(void)
160 {
161 qsocket_t *sock;
162
163 if (!net_freeSockets)
164 return NULL;
165
166 if (net_activeconnections >= svs.maxclients)
167 return NULL;
168
169 /* get one from free list */
170 sock = net_freeSockets;
171 net_freeSockets = sock->next;
172
173 /* add it to active list */
174 sock->next = net_activeSockets;
175 net_activeSockets = sock;
176
177 sock->disconnected = false;
178 sock->connecttime = net_time;
179 strcpy(sock->address, "UNSET ADDRESS");
180 sock->driver = net_driver;
181 sock->socket = 0;
182 sock->driverdata = NULL;
183 sock->canSend = true;
184 sock->sendNext = false;
185 sock->lastMessageTime = net_time;
186 sock->ackSequence = 0;
187 sock->sendSequence = 0;
188 sock->unreliableSendSequence = 0;
189 sock->sendMessageLength = 0;
190 sock->receiveSequence = 0;
191 sock->unreliableReceiveSequence = 0;
192 sock->receiveMessageLength = 0;
193
194 return sock;
195 }
196
197
198 void
NET_FreeQSocket(qsocket_t * sock)199 NET_FreeQSocket(qsocket_t *sock)
200 {
201 qsocket_t *s;
202
203 /* remove it from active list */
204 if (sock == net_activeSockets)
205 net_activeSockets = net_activeSockets->next;
206 else {
207 for (s = net_activeSockets; s; s = s->next)
208 if (s->next == sock) {
209 s->next = sock->next;
210 break;
211 }
212 if (!s)
213 Sys_Error("%s: not active", __func__);
214 }
215
216 /* add it to free list */
217 sock->next = net_freeSockets;
218 net_freeSockets = sock;
219 sock->disconnected = true;
220 }
221
222
223 static void
NET_Listen_f(void)224 NET_Listen_f(void)
225 {
226 int i;
227
228 if (Cmd_Argc() != 2) {
229 Con_Printf("\"listen\" is \"%u\"\n", listening ? 1 : 0);
230 return;
231 }
232
233 listening = Q_atoi(Cmd_Argv(1)) ? true : false;
234
235 for (i = 0; i < net_numdrivers;i++) {
236 net_driver = &net_drivers[i];
237 if (net_driver->initialized == false)
238 continue;
239 net_driver->Listen(listening);
240 }
241 }
242
243
244 static void
MaxPlayers_f(void)245 MaxPlayers_f(void)
246 {
247 int n;
248
249 if (Cmd_Argc() != 2) {
250 Con_Printf("\"maxplayers\" is \"%u\"\n", svs.maxclients);
251 return;
252 }
253
254 if (sv.active) {
255 Con_Printf
256 ("maxplayers can not be changed while a server is running.\n");
257 return;
258 }
259
260 n = Q_atoi(Cmd_Argv(1));
261 if (n < 1)
262 n = 1;
263 if (n > svs.maxclientslimit) {
264 n = svs.maxclientslimit;
265 Con_Printf("\"maxplayers\" set to \"%u\"\n", n);
266 }
267
268 if ((n == 1) && listening)
269 Cbuf_AddText("listen 0\n");
270
271 if ((n > 1) && (!listening))
272 Cbuf_AddText("listen 1\n");
273
274 svs.maxclients = n;
275 if (n == 1) {
276 Cvar_Set("deathmatch", "0");
277 Cvar_Set("coop", "0");
278 } else {
279 if (coop.value)
280 Cvar_Set("deathmatch", "0");
281 else
282 Cvar_Set("deathmatch", "1");
283 }
284 }
285
286
287 static void
NET_Port_f(void)288 NET_Port_f(void)
289 {
290 int n;
291
292 if (Cmd_Argc() != 2) {
293 Con_Printf("\"port\" is \"%u\"\n", net_hostport);
294 return;
295 }
296
297 n = Q_atoi(Cmd_Argv(1));
298 if (n < 1 || n > 65534) {
299 Con_Printf("Bad value, must be between 1 and 65534\n");
300 return;
301 }
302
303 DEFAULTnet_hostport = n;
304 net_hostport = n;
305
306 if (listening) {
307 /* force a change to the new port */
308 Cbuf_AddText("listen 0\n");
309 Cbuf_AddText("listen 1\n");
310 }
311 }
312
313
314 static void
PrintSlistHeader(void)315 PrintSlistHeader(void)
316 {
317 Con_Printf("Server Map Users\n");
318 Con_Printf("--------------- --------------- -----\n");
319 slistLastShown = 0;
320 }
321
322
323 static void
PrintSlist(void)324 PrintSlist(void)
325 {
326 int n;
327
328 for (n = slistLastShown; n < hostCacheCount; n++) {
329 if (hostcache[n].maxusers)
330 Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name,
331 hostcache[n].map, hostcache[n].users,
332 hostcache[n].maxusers);
333 else
334 Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name,
335 hostcache[n].map);
336 }
337 slistLastShown = n;
338 }
339
340
341 static void
PrintSlistTrailer(void)342 PrintSlistTrailer(void)
343 {
344 if (hostCacheCount)
345 Con_Printf("== end list ==\n\n");
346 else
347 Con_Printf("No Quake servers found.\n\n");
348 }
349
350
351 void
NET_Slist_f(void)352 NET_Slist_f(void)
353 {
354 if (slistInProgress)
355 return;
356
357 if (!slistSilent) {
358 Con_Printf("Looking for Quake servers...\n");
359 PrintSlistHeader();
360 }
361
362 slistInProgress = true;
363 slistStartTime = Sys_DoubleTime();
364
365 SchedulePollProcedure(&slistSendProcedure, 0.0);
366 SchedulePollProcedure(&slistPollProcedure, 0.1);
367
368 hostCacheCount = 0;
369 }
370
371
372 static void
Slist_Send(void)373 Slist_Send(void)
374 {
375 int i;
376
377 for (i = 0; i < net_numdrivers; i++) {
378 net_driver = &net_drivers[i];
379
380 /* Only list the loop driver if slistLocal is true */
381 if (!slistLocal && IS_LOOP_DRIVER(net_driver))
382 continue;
383 if (net_driver->initialized == false)
384 continue;
385 net_driver->SearchForHosts(true);
386 }
387
388 if ((Sys_DoubleTime() - slistStartTime) < 0.5)
389 SchedulePollProcedure(&slistSendProcedure, 0.75);
390 }
391
392
393 static void
Slist_Poll(void)394 Slist_Poll(void)
395 {
396 int i;
397
398 for (i = 0; i < net_numdrivers; i++) {
399 net_driver = &net_drivers[i];
400
401 /* Only list the loop driver if slistLocal is true */
402 if (!slistLocal && IS_LOOP_DRIVER(net_driver))
403 continue;
404 if (net_driver->initialized == false)
405 continue;
406 net_driver->SearchForHosts(false);
407 }
408
409 if (!slistSilent)
410 PrintSlist();
411
412 if ((Sys_DoubleTime() - slistStartTime) < 1.5) {
413 SchedulePollProcedure(&slistPollProcedure, 0.1);
414 return;
415 }
416
417 if (!slistSilent)
418 PrintSlistTrailer();
419 slistInProgress = false;
420 slistSilent = false;
421 slistLocal = true;
422 }
423
424
425 /*
426 * ===================
427 * NET_Connect
428 * ===================
429 */
430 int hostCacheCount = 0;
431 hostcache_t hostcache[HOSTCACHESIZE];
432
433 qsocket_t *
NET_Connect(const char * host)434 NET_Connect(const char *host)
435 {
436 qsocket_t *ret;
437 int i, n;
438 int numdrivers = net_numdrivers;
439
440 printf("Attempting to connect to %s\n", host);
441
442 SetNetTime();
443
444 if (host && *host == 0)
445 host = NULL;
446
447 if (host) {
448 if (strcasecmp(host, "local") == 0) {
449 numdrivers = 1;
450 goto JustDoIt;
451 }
452
453 if (hostCacheCount) {
454 for (n = 0; n < hostCacheCount; n++)
455 if (strcasecmp(host, hostcache[n].name) == 0) {
456 host = hostcache[n].cname;
457 break;
458 }
459 if (n < hostCacheCount)
460 goto JustDoIt;
461 }
462 }
463
464 slistSilent = host ? true : false;
465 NET_Slist_f();
466
467 while (slistInProgress)
468 NET_Poll();
469
470 if (host == NULL) {
471 if (hostCacheCount != 1)
472 return NULL;
473 host = hostcache[0].cname;
474 Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
475 }
476
477 if (hostCacheCount)
478 for (n = 0; n < hostCacheCount; n++)
479 if (strcasecmp(host, hostcache[n].name) == 0) {
480 host = hostcache[n].cname;
481 break;
482 }
483
484 JustDoIt:
485 for (i = 0; i < numdrivers; i++) {
486 net_driver = &net_drivers[i];
487 if (net_driver->initialized == false)
488 continue;
489 ret = net_driver->Connect(host);
490 if (ret)
491 return ret;
492 }
493
494 if (host) {
495 Con_Printf("\n");
496 PrintSlistHeader();
497 PrintSlist();
498 PrintSlistTrailer();
499 }
500
501 return NULL;
502 }
503
504
505 /*
506 * ===================
507 * NET_CheckNewConnections
508 * ===================
509 */
510 qsocket_t *
NET_CheckNewConnections(void)511 NET_CheckNewConnections(void)
512 {
513 int i;
514 qsocket_t *ret = NULL;
515
516 SetNetTime();
517
518 for (i = 0; i < net_numdrivers; i++) {
519 net_driver = &net_drivers[i];
520 if (net_driver->initialized == false)
521 continue;
522 if (!IS_LOOP_DRIVER(net_driver) && listening == false)
523 continue;
524 ret = net_driver->CheckNewConnections();
525 if (ret)
526 break;
527 }
528
529 return ret;
530 }
531
532 /*
533 * ===================
534 * NET_Close
535 * ===================
536 */
537 void
NET_Close(qsocket_t * sock)538 NET_Close(qsocket_t *sock)
539 {
540 if (!sock)
541 return;
542
543 if (sock->disconnected)
544 return;
545
546 SetNetTime();
547
548 /* call the driver_Close function */
549 sock->driver->Close(sock);
550
551 NET_FreeQSocket(sock);
552 }
553
554
555 /*
556 * =================
557 * NET_GetMessage
558 *
559 * If there is a complete message, return it in net_message
560 *
561 * returns 0 if no data is waiting
562 * returns 1 if a message was received
563 * returns -1 if connection is invalid
564 * =================
565 */
566 int
NET_GetMessage(qsocket_t * sock)567 NET_GetMessage(qsocket_t *sock)
568 {
569 int ret;
570
571 if (!sock)
572 return -1;
573
574 if (sock->disconnected) {
575 Con_Printf("%s: disconnected socket\n", __func__);
576 return -1;
577 }
578
579 SetNetTime();
580
581 ret = sock->driver->QGetMessage(sock);
582
583 /* see if this connection has timed out (not for loop) */
584 if (ret == 0 && (!IS_LOOP_DRIVER(sock->driver))) {
585 if (net_time - sock->lastMessageTime > net_messagetimeout.value) {
586 NET_Close(sock);
587 return -1;
588 }
589 }
590
591 if (ret > 0) {
592 if (!IS_LOOP_DRIVER(sock->driver)) {
593 sock->lastMessageTime = net_time;
594 if (ret == 1)
595 messagesReceived++;
596 else if (ret == 2)
597 unreliableMessagesReceived++;
598 }
599 }
600
601 return ret;
602 }
603
604
605 /*
606 * ==================
607 * NET_SendMessage
608 *
609 * Try to send a complete length+message unit over the reliable stream.
610 * returns 0 : if the message cannot be delivered reliably, but the connection
611 * is still considered valid
612 * returns 1 : if the message was sent properly
613 * returns -1 : if the connection died
614 * ==================
615 */
616 int
NET_SendMessage(qsocket_t * sock,sizebuf_t * data)617 NET_SendMessage(qsocket_t *sock, sizebuf_t *data)
618 {
619 int r;
620
621 if (!sock)
622 return -1;
623
624 if (sock->disconnected) {
625 Con_Printf("%s: disconnected socket\n", __func__);
626 return -1;
627 }
628
629 SetNetTime();
630 r = sock->driver->QSendMessage(sock, data);
631 if (r == 1 && !IS_LOOP_DRIVER(sock->driver))
632 messagesSent++;
633
634 return r;
635 }
636
637
638 int
NET_SendUnreliableMessage(qsocket_t * sock,sizebuf_t * data)639 NET_SendUnreliableMessage(qsocket_t *sock, sizebuf_t *data)
640 {
641 int r;
642
643 if (!sock)
644 return -1;
645
646 if (sock->disconnected) {
647 Con_Printf("NET_SendMessage: disconnected socket\n");
648 return -1;
649 }
650
651 SetNetTime();
652 r = sock->driver->SendUnreliableMessage(sock, data);
653 if (r == 1 && !IS_LOOP_DRIVER(sock->driver))
654 unreliableMessagesSent++;
655
656 return r;
657 }
658
659
660 /*
661 * ==================
662 * NET_CanSendMessage
663 *
664 * Returns true or false if the given qsocket can currently accept a
665 * message to be transmitted.
666 * ==================
667 */
668 qboolean
NET_CanSendMessage(qsocket_t * sock)669 NET_CanSendMessage(qsocket_t *sock)
670 {
671 int r;
672
673 if (!sock)
674 return false;
675
676 if (sock->disconnected)
677 return false;
678
679 SetNetTime();
680
681 r = sock->driver->CanSendMessage(sock);
682
683 return r;
684 }
685
686
687 int
NET_SendToAll(sizebuf_t * data,double blocktime)688 NET_SendToAll(sizebuf_t *data, double blocktime)
689 {
690 double start;
691 int i;
692 int count = 0;
693 qboolean msg_init[MAX_SCOREBOARD]; /* data written */
694 qboolean msg_sent[MAX_SCOREBOARD]; /* send completed */
695
696 for (i = 0, host_client = svs.clients; i < svs.maxclients;
697 i++, host_client++) {
698 if (host_client->netconnection && host_client->active) {
699 /*
700 * Loopback driver guarantees delivery, skip checks
701 */
702 if (IS_LOOP_DRIVER(host_client->netconnection->driver)) {
703 NET_SendMessage(host_client->netconnection, data);
704 msg_init[i] = true;
705 msg_sent[i] = true;
706 continue;
707 }
708 count++;
709 msg_init[i] = false;
710 msg_sent[i] = false;
711 } else {
712 msg_init[i] = true;
713 msg_sent[i] = true;
714 }
715 }
716
717 start = Sys_DoubleTime();
718 while (count) {
719 count = 0;
720 for (i = 0, host_client = svs.clients; i < svs.maxclients;
721 i++, host_client++) {
722 if (!msg_init[i]) {
723 if (NET_CanSendMessage(host_client->netconnection)) {
724 msg_init[i] = true;
725 NET_SendMessage(host_client->netconnection, data);
726 } else {
727 NET_GetMessage(host_client->netconnection);
728 }
729 count++;
730 continue;
731 }
732
733 if (!msg_sent[i]) {
734 if (NET_CanSendMessage(host_client->netconnection)) {
735 msg_sent[i] = true;
736 } else {
737 NET_GetMessage(host_client->netconnection);
738 }
739 count++;
740 continue;
741 }
742 }
743 if ((Sys_DoubleTime() - start) > blocktime)
744 break;
745 }
746 return count;
747 }
748
749
750 /*
751 * ====================
752 * NET_Init
753 * ====================
754 */
755 void
NET_Init(void)756 NET_Init(void)
757 {
758 int i, num_inited;
759 int controlSocket;
760 qsocket_t *s;
761
762 i = COM_CheckParm("-port");
763 if (!i)
764 i = COM_CheckParm("-udpport");
765
766 if (i) {
767 if (i < com_argc - 1)
768 DEFAULTnet_hostport = Q_atoi(com_argv[i + 1]);
769 else
770 Sys_Error("%s: you must specify a number after -port", __func__);
771 }
772 net_hostport = DEFAULTnet_hostport;
773
774 if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
775 listening = true;
776 net_numsockets = svs.maxclientslimit;
777 if (cls.state != ca_dedicated)
778 net_numsockets++;
779
780 SetNetTime();
781
782 for (i = 0; i < net_numsockets; i++) {
783 s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
784 s->next = net_freeSockets;
785 net_freeSockets = s;
786 s->disconnected = true;
787 }
788
789 /* allocate space for network message buffer */
790 SZ_Alloc(&net_message, NET_MAXMESSAGE);
791
792 Cvar_RegisterVariable(&net_messagetimeout);
793 Cvar_RegisterVariable(&hostname);
794
795 Cmd_AddCommand("slist", NET_Slist_f);
796 Cmd_AddCommand("listen", NET_Listen_f);
797 Cmd_AddCommand("maxplayers", MaxPlayers_f);
798 Cmd_AddCommand("port", NET_Port_f);
799
800 /* initialize all the drivers */
801 num_inited = 0;
802 for (i = 0; i < net_numdrivers; i++) {
803 net_driver = &net_drivers[i];
804 controlSocket = net_driver->Init();
805 if (controlSocket == -1)
806 continue;
807 num_inited++;
808 net_driver->initialized = true;
809 net_driver->controlSock = controlSocket;
810 if (listening)
811 net_driver->Listen(true);
812 }
813
814 if (num_inited == 0 && cls.state == ca_dedicated)
815 Sys_Error("Network not available!");
816
817 if (*my_tcpip_address)
818 Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
819 }
820
821 /*
822 * ====================
823 * NET_Shutdown
824 * ====================
825 */
826 void
NET_Shutdown(void)827 NET_Shutdown(void)
828 {
829 int i;
830 qsocket_t *sock;
831
832 SetNetTime();
833
834 for (sock = net_activeSockets; sock; sock = sock->next)
835 NET_Close(sock);
836
837 /*
838 * shutdown the drivers
839 */
840 for (i = 0; i < net_numdrivers; i++) {
841 net_driver = &net_drivers[i];
842 if (net_driver->initialized == true) {
843 net_driver->Shutdown();
844 net_driver->initialized = false;
845 }
846 }
847 }
848
849
850 static PollProcedure *pollProcedureList = NULL;
851
852 void
NET_Poll(void)853 NET_Poll(void)
854 {
855 PollProcedure *pp;
856
857 SetNetTime();
858
859 /*
860 * FIXME - A procedure could schedule itself to the head of the list, but
861 * wouldn't be executed until next frame/tic; problem?
862 */
863 for (pp = pollProcedureList; pp; pp = pp->next) {
864 if (pp->nextTime > net_time)
865 break;
866 pollProcedureList = pp->next;
867 #ifdef _WIN32
868 //not sure what is going on here - params is void in NQ/net.h?
869 pp->procedure();
870 #else
871 pp->procedure(pp->arg);
872 #endif
873 }
874 }
875
876
877 void
SchedulePollProcedure(PollProcedure * proc,double timeOffset)878 SchedulePollProcedure(PollProcedure *proc, double timeOffset)
879 {
880 PollProcedure *pp, *prev;
881
882 proc->nextTime = Sys_DoubleTime() + timeOffset;
883 for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next) {
884 if (pp->nextTime >= proc->nextTime)
885 break;
886 prev = pp;
887 }
888
889 if (prev == NULL) {
890 proc->next = pollProcedureList;
891 pollProcedureList = proc;
892 return;
893 }
894
895 proc->next = pp;
896 prev->next = proc;
897 }
898