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 // net_main.c
21
22 #include "quakedef.h"
23 #include "net_vcr.h"
24
25 qsocket_t *net_activeSockets = NULL;
26 qsocket_t *net_freeSockets = NULL;
27 int net_numsockets = 0;
28
29 qboolean serialAvailable = false;
30 qboolean ipxAvailable = false;
31 qboolean tcpipAvailable = false;
32
33 int net_hostport;
34 int DEFAULTnet_hostport = 26000;
35
36 char my_ipx_address[NET_NAMELEN];
37 char my_tcpip_address[NET_NAMELEN];
38
39 void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
40 void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
41 void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
42 void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
43
44 static qboolean listening = false;
45
46 qboolean slistInProgress = false;
47 qboolean slistSilent = false;
48 qboolean slistLocal = true;
49 static double slistStartTime;
50 static int slistLastShown;
51
52 static void Slist_Send(void);
53 static void Slist_Poll(void);
54 PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
55 PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
56
57
58 sizebuf_t net_message;
59 int net_activeconnections = 0;
60
61 int messagesSent = 0;
62 int messagesReceived = 0;
63 int unreliableMessagesSent = 0;
64 int unreliableMessagesReceived = 0;
65
66 cvar_t net_messagetimeout = {"net_messagetimeout","300"};
67 cvar_t hostname = {"hostname", "UNNAMED"};
68
69 qboolean configRestored = false;
70 cvar_t config_com_port = {"_config_com_port", "0x3f8", true};
71 cvar_t config_com_irq = {"_config_com_irq", "4", true};
72 cvar_t config_com_baud = {"_config_com_baud", "57600", true};
73 cvar_t config_com_modem = {"_config_com_modem", "1", true};
74 cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true};
75 cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true};
76 cvar_t config_modem_init = {"_config_modem_init", "", true};
77 cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true};
78
79 #ifdef IDGODS
80 cvar_t idgods = {"idgods", "0"};
81 #endif
82
83 int vcrFile = -1;
84 qboolean recording = false;
85
86 // these two macros are to make the code more readable
87 #define sfunc net_drivers[sock->driver]
88 #define dfunc net_drivers[net_driverlevel]
89
90 int net_driverlevel;
91
92
93 double net_time;
94
SetNetTime(void)95 double SetNetTime(void)
96 {
97 net_time = Sys_FloatTime();
98 return net_time;
99 }
100
101
102 /*
103 ===================
104 NET_NewQSocket
105
106 Called by drivers when a new communications endpoint is required
107 The sequence and buffer fields will be filled in properly
108 ===================
109 */
NET_NewQSocket(void)110 qsocket_t *NET_NewQSocket (void)
111 {
112 qsocket_t *sock;
113
114 if (net_freeSockets == NULL)
115 return NULL;
116
117 if (net_activeconnections >= svs.maxclients)
118 return NULL;
119
120 // get one from free list
121 sock = net_freeSockets;
122 net_freeSockets = sock->next;
123
124 // add it to active list
125 sock->next = net_activeSockets;
126 net_activeSockets = sock;
127
128 sock->disconnected = false;
129 sock->connecttime = net_time;
130 Q_strcpy (sock->address,"UNSET ADDRESS");
131 sock->driver = net_driverlevel;
132 sock->socket = 0;
133 sock->driverdata = NULL;
134 sock->canSend = true;
135 sock->sendNext = false;
136 sock->lastMessageTime = net_time;
137 sock->ackSequence = 0;
138 sock->sendSequence = 0;
139 sock->unreliableSendSequence = 0;
140 sock->sendMessageLength = 0;
141 sock->receiveSequence = 0;
142 sock->unreliableReceiveSequence = 0;
143 sock->receiveMessageLength = 0;
144
145 return sock;
146 }
147
148
NET_FreeQSocket(qsocket_t * sock)149 void NET_FreeQSocket(qsocket_t *sock)
150 {
151 qsocket_t *s;
152
153 // remove it from active list
154 if (sock == net_activeSockets)
155 net_activeSockets = net_activeSockets->next;
156 else
157 {
158 for (s = net_activeSockets; s; s = s->next)
159 if (s->next == sock)
160 {
161 s->next = sock->next;
162 break;
163 }
164 if (!s)
165 Sys_Error ("NET_FreeQSocket: not active\n");
166 }
167
168 // add it to free list
169 sock->next = net_freeSockets;
170 net_freeSockets = sock;
171 sock->disconnected = true;
172 }
173
174
NET_Listen_f(void)175 static void NET_Listen_f (void)
176 {
177 if (Cmd_Argc () != 2)
178 {
179 Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
180 return;
181 }
182
183 listening = Q_atoi(Cmd_Argv(1)) ? true : false;
184
185 for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
186 {
187 if (net_drivers[net_driverlevel].initialized == false)
188 continue;
189 dfunc.Listen (listening);
190 }
191 }
192
193
MaxPlayers_f(void)194 static void MaxPlayers_f (void)
195 {
196 int n;
197
198 if (Cmd_Argc () != 2)
199 {
200 Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
201 return;
202 }
203
204 if (sv.active)
205 {
206 Con_Printf ("maxplayers can not be changed while a server is running.\n");
207 return;
208 }
209
210 n = Q_atoi(Cmd_Argv(1));
211 if (n < 1)
212 n = 1;
213 if (n > svs.maxclientslimit)
214 {
215 n = svs.maxclientslimit;
216 Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
217 }
218
219 if ((n == 1) && listening)
220 Cbuf_AddText ("listen 0\n");
221
222 if ((n > 1) && (!listening))
223 Cbuf_AddText ("listen 1\n");
224
225 svs.maxclients = n;
226 if (n == 1)
227 Cvar_Set ("deathmatch", "0");
228 else
229 Cvar_Set ("deathmatch", "1");
230 }
231
232
NET_Port_f(void)233 static void NET_Port_f (void)
234 {
235 int n;
236
237 if (Cmd_Argc () != 2)
238 {
239 Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
240 return;
241 }
242
243 n = Q_atoi(Cmd_Argv(1));
244 if (n < 1 || n > 65534)
245 {
246 Con_Printf ("Bad value, must be between 1 and 65534\n");
247 return;
248 }
249
250 DEFAULTnet_hostport = n;
251 net_hostport = n;
252
253 if (listening)
254 {
255 // force a change to the new port
256 Cbuf_AddText ("listen 0\n");
257 Cbuf_AddText ("listen 1\n");
258 }
259 }
260
261
PrintSlistHeader(void)262 static void PrintSlistHeader(void)
263 {
264 Con_Printf("Server Map Users\n");
265 Con_Printf("--------------- --------------- -----\n");
266 slistLastShown = 0;
267 }
268
269
PrintSlist(void)270 static void PrintSlist(void)
271 {
272 int n;
273
274 for (n = slistLastShown; n < hostCacheCount; n++)
275 {
276 if (hostcache[n].maxusers)
277 Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
278 else
279 Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
280 }
281 slistLastShown = n;
282 }
283
284
PrintSlistTrailer(void)285 static void PrintSlistTrailer(void)
286 {
287 if (hostCacheCount)
288 Con_Printf("== end list ==\n\n");
289 else
290 Con_Printf("No Quake servers found.\n\n");
291 }
292
293
NET_Slist_f(void)294 void NET_Slist_f (void)
295 {
296 if (slistInProgress)
297 return;
298
299 if (! slistSilent)
300 {
301 Con_Printf("Looking for Quake servers...\n");
302 PrintSlistHeader();
303 }
304
305 slistInProgress = true;
306 slistStartTime = Sys_FloatTime();
307
308 SchedulePollProcedure(&slistSendProcedure, 0.0);
309 SchedulePollProcedure(&slistPollProcedure, 0.1);
310
311 hostCacheCount = 0;
312 }
313
314
Slist_Send(void)315 static void Slist_Send(void)
316 {
317 for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
318 {
319 if (!slistLocal && net_driverlevel == 0)
320 continue;
321 if (net_drivers[net_driverlevel].initialized == false)
322 continue;
323 dfunc.SearchForHosts (true);
324 }
325
326 if ((Sys_FloatTime() - slistStartTime) < 0.5)
327 SchedulePollProcedure(&slistSendProcedure, 0.75);
328 }
329
330
Slist_Poll(void)331 static void Slist_Poll(void)
332 {
333 for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
334 {
335 if (!slistLocal && net_driverlevel == 0)
336 continue;
337 if (net_drivers[net_driverlevel].initialized == false)
338 continue;
339 dfunc.SearchForHosts (false);
340 }
341
342 if (! slistSilent)
343 PrintSlist();
344
345 if ((Sys_FloatTime() - slistStartTime) < 1.5)
346 {
347 SchedulePollProcedure(&slistPollProcedure, 0.1);
348 return;
349 }
350
351 if (! slistSilent)
352 PrintSlistTrailer();
353 slistInProgress = false;
354 slistSilent = false;
355 slistLocal = true;
356 }
357
358
359 /*
360 ===================
361 NET_Connect
362 ===================
363 */
364
365 int hostCacheCount = 0;
366 hostcache_t hostcache[HOSTCACHESIZE];
367
NET_Connect(char * host)368 qsocket_t *NET_Connect (char *host)
369 {
370 qsocket_t *ret;
371 int n;
372 int numdrivers = net_numdrivers;
373
374 SetNetTime();
375
376 if (host && *host == 0)
377 host = NULL;
378
379 if (host)
380 {
381 if (Q_strcasecmp (host, "local") == 0)
382 {
383 numdrivers = 1;
384 goto JustDoIt;
385 }
386
387 if (hostCacheCount)
388 {
389 for (n = 0; n < hostCacheCount; n++)
390 if (Q_strcasecmp (host, hostcache[n].name) == 0)
391 {
392 host = hostcache[n].cname;
393 break;
394 }
395 if (n < hostCacheCount)
396 goto JustDoIt;
397 }
398 }
399
400 slistSilent = host ? true : false;
401 NET_Slist_f ();
402
403 while(slistInProgress)
404 NET_Poll();
405
406 if (host == NULL)
407 {
408 if (hostCacheCount != 1)
409 return NULL;
410 host = hostcache[0].cname;
411 Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
412 }
413
414 if (hostCacheCount)
415 for (n = 0; n < hostCacheCount; n++)
416 if (Q_strcasecmp (host, hostcache[n].name) == 0)
417 {
418 host = hostcache[n].cname;
419 break;
420 }
421
422 JustDoIt:
423 for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
424 {
425 if (net_drivers[net_driverlevel].initialized == false)
426 continue;
427 ret = dfunc.Connect (host);
428 if (ret)
429 return ret;
430 }
431
432 if (host)
433 {
434 Con_Printf("\n");
435 PrintSlistHeader();
436 PrintSlist();
437 PrintSlistTrailer();
438 }
439
440 return NULL;
441 }
442
443
444 /*
445 ===================
446 NET_CheckNewConnections
447 ===================
448 */
449
450 struct
451 {
452 double time;
453 int op;
454 long session;
455 } vcrConnect;
456
NET_CheckNewConnections(void)457 qsocket_t *NET_CheckNewConnections (void)
458 {
459 qsocket_t *ret;
460
461 SetNetTime();
462
463 for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
464 {
465 if (net_drivers[net_driverlevel].initialized == false)
466 continue;
467 if (net_driverlevel && listening == false)
468 continue;
469 ret = dfunc.CheckNewConnections ();
470 if (ret)
471 {
472 if (recording)
473 {
474 vcrConnect.time = host_time;
475 vcrConnect.op = VCR_OP_CONNECT;
476 vcrConnect.session = (long)ret;
477 Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
478 Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
479 }
480 return ret;
481 }
482 }
483
484 if (recording)
485 {
486 vcrConnect.time = host_time;
487 vcrConnect.op = VCR_OP_CONNECT;
488 vcrConnect.session = 0;
489 Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
490 }
491
492 return NULL;
493 }
494
495 /*
496 ===================
497 NET_Close
498 ===================
499 */
NET_Close(qsocket_t * sock)500 void NET_Close (qsocket_t *sock)
501 {
502 if (!sock)
503 return;
504
505 if (sock->disconnected)
506 return;
507
508 SetNetTime();
509
510 // call the driver_Close function
511 sfunc.Close (sock);
512
513 NET_FreeQSocket(sock);
514 }
515
516
517 /*
518 =================
519 NET_GetMessage
520
521 If there is a complete message, return it in net_message
522
523 returns 0 if no data is waiting
524 returns 1 if a message was received
525 returns -1 if connection is invalid
526 =================
527 */
528
529 struct
530 {
531 double time;
532 int op;
533 long session;
534 int ret;
535 int len;
536 } vcrGetMessage;
537
538 extern void PrintStats(qsocket_t *s);
539
NET_GetMessage(qsocket_t * sock)540 int NET_GetMessage (qsocket_t *sock)
541 {
542 int ret;
543
544 if (!sock)
545 return -1;
546
547 if (sock->disconnected)
548 {
549 Con_Printf("NET_GetMessage: disconnected socket\n");
550 return -1;
551 }
552
553 SetNetTime();
554
555 ret = sfunc.QGetMessage(sock);
556
557 // see if this connection has timed out
558 if (ret == 0 && sock->driver)
559 {
560 /*
561 RFC: Why doesn't this work!!! It's the same... or not??
562 Since when I compile it it evaluates the if body even if it's a smaller number...
563
564 if ((net_time - sock->lastMessageTime) > (double)net_messagetimeout.value)
565 {
566 Con_Printf("*** Connection timed out after %f s of inactivity (max is %f)\n",delta,net_messagetimeout.value);
567 //NET_Close(sock);
568 //return -1;
569 }
570 */
571 float delta = (net_time - sock->lastMessageTime);
572 if (delta > net_messagetimeout.value)
573 {
574 Con_Printf("*** Connection timed out after %f s of inactivity (max is %f)\n",delta,net_messagetimeout.value);
575 NET_Close(sock);
576 return -1;
577 }
578 }
579
580
581 if (ret > 0)
582 {
583 if (sock->driver)
584 {
585 sock->lastMessageTime = net_time;
586 if (ret == 1)
587 messagesReceived++;
588 else if (ret == 2)
589 unreliableMessagesReceived++;
590 }
591
592 if (recording)
593 {
594 vcrGetMessage.time = host_time;
595 vcrGetMessage.op = VCR_OP_GETMESSAGE;
596 vcrGetMessage.session = (long)sock;
597 vcrGetMessage.ret = ret;
598 vcrGetMessage.len = net_message.cursize;
599 Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
600 Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
601 }
602 }
603 else
604 {
605 if (recording)
606 {
607 vcrGetMessage.time = host_time;
608 vcrGetMessage.op = VCR_OP_GETMESSAGE;
609 vcrGetMessage.session = (long)sock;
610 vcrGetMessage.ret = ret;
611 Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
612 }
613 }
614
615 return ret;
616 }
617
618
619 /*
620 ==================
621 NET_SendMessage
622
623 Try to send a complete length+message unit over the reliable stream.
624 returns 0 if the message cannot be delivered reliably, but the connection
625 is still considered valid
626 returns 1 if the message was sent properly
627 returns -1 if the connection died
628 ==================
629 */
630 struct
631 {
632 double time;
633 int op;
634 long session;
635 int r;
636 } vcrSendMessage;
637
NET_SendMessage(qsocket_t * sock,sizebuf_t * data)638 int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
639 {
640 int r;
641
642 if (!sock)
643 return -1;
644
645 if (sock->disconnected)
646 {
647 Con_Printf("NET_SendMessage: disconnected socket\n");
648 return -1;
649 }
650
651 SetNetTime();
652 r = sfunc.QSendMessage(sock, data);
653 if (r == 1 && sock->driver)
654 messagesSent++;
655
656 if (recording)
657 {
658 vcrSendMessage.time = host_time;
659 vcrSendMessage.op = VCR_OP_SENDMESSAGE;
660 vcrSendMessage.session = (long)sock;
661 vcrSendMessage.r = r;
662 Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
663 }
664
665 return r;
666 }
667
668
NET_SendUnreliableMessage(qsocket_t * sock,sizebuf_t * data)669 int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
670 {
671 int r;
672
673 if (!sock)
674 return -1;
675
676 if (sock->disconnected)
677 {
678 Con_Printf("NET_SendMessage: disconnected socket\n");
679 return -1;
680 }
681
682 SetNetTime();
683 r = sfunc.SendUnreliableMessage(sock, data);
684 if (r == 1 && sock->driver)
685 unreliableMessagesSent++;
686
687 if (recording)
688 {
689 vcrSendMessage.time = host_time;
690 vcrSendMessage.op = VCR_OP_SENDMESSAGE;
691 vcrSendMessage.session = (long)sock;
692 vcrSendMessage.r = r;
693 Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
694 }
695
696 return r;
697 }
698
699
700 /*
701 ==================
702 NET_CanSendMessage
703
704 Returns true or false if the given qsocket can currently accept a
705 message to be transmitted.
706 ==================
707 */
NET_CanSendMessage(qsocket_t * sock)708 qboolean NET_CanSendMessage (qsocket_t *sock)
709 {
710 int r;
711
712 if (!sock)
713 return false;
714
715 if (sock->disconnected)
716 return false;
717
718 SetNetTime();
719
720 r = sfunc.CanSendMessage(sock);
721
722 if (recording)
723 {
724 vcrSendMessage.time = host_time;
725 vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
726 vcrSendMessage.session = (long)sock;
727 vcrSendMessage.r = r;
728 Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
729 }
730
731 return r;
732 }
733
734
NET_SendToAll(sizebuf_t * data,int blocktime)735 int NET_SendToAll(sizebuf_t *data, int blocktime)
736 {
737 double start;
738 int i;
739 int count = 0;
740 qboolean state1 [MAX_SCOREBOARD];
741 qboolean state2 [MAX_SCOREBOARD];
742
743 for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
744 {
745 if (!host_client->netconnection)
746 continue;
747 if (host_client->active)
748 {
749 if (host_client->netconnection->driver == 0)
750 {
751 NET_SendMessage(host_client->netconnection, data);
752 state1[i] = true;
753 state2[i] = true;
754 continue;
755 }
756 count++;
757 state1[i] = false;
758 state2[i] = false;
759 }
760 else
761 {
762 state1[i] = true;
763 state2[i] = true;
764 }
765 }
766
767 start = Sys_FloatTime();
768 while (count)
769 {
770 count = 0;
771 for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
772 {
773 if (! state1[i])
774 {
775 if (NET_CanSendMessage (host_client->netconnection))
776 {
777 state1[i] = true;
778 NET_SendMessage(host_client->netconnection, data);
779 }
780 else
781 {
782 NET_GetMessage (host_client->netconnection);
783 }
784 count++;
785 continue;
786 }
787
788 if (! state2[i])
789 {
790 if (NET_CanSendMessage (host_client->netconnection))
791 {
792 state2[i] = true;
793 }
794 else
795 {
796 NET_GetMessage (host_client->netconnection);
797 }
798 count++;
799 continue;
800 }
801 }
802 if ((Sys_FloatTime() - start) > blocktime)
803 break;
804 }
805 return count;
806 }
807
808
809 //=============================================================================
810
811 /*
812 ====================
813 NET_Init
814 ====================
815 */
816
NET_Init(void)817 void NET_Init (void)
818 {
819 int i;
820 int controlSocket;
821 qsocket_t *s;
822
823 if (COM_CheckParm("-playback"))
824 {
825 net_numdrivers = 1;
826 net_drivers[0].Init = VCR_Init;
827 }
828
829 if (COM_CheckParm("-record"))
830 recording = true;
831
832 i = COM_CheckParm ("-port");
833 if (!i)
834 i = COM_CheckParm ("-udpport");
835 if (!i)
836 i = COM_CheckParm ("-ipxport");
837
838 if (i)
839 {
840 if (i < com_argc-1)
841 DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
842 else
843 Sys_Error ("NET_Init: you must specify a number after -port");
844 }
845 net_hostport = DEFAULTnet_hostport;
846
847 if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
848 listening = true;
849 net_numsockets = svs.maxclientslimit;
850 if (cls.state != ca_dedicated)
851 net_numsockets++;
852
853 SetNetTime();
854
855 for (i = 0; i < net_numsockets; i++)
856 {
857 s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
858 s->next = net_freeSockets;
859 net_freeSockets = s;
860 s->disconnected = true;
861 }
862
863 // allocate space for network message buffer
864 SZ_Alloc (&net_message, NET_MAXMESSAGE);
865
866 Cvar_RegisterVariable (&net_messagetimeout);
867 Cvar_RegisterVariable (&hostname);
868 Cvar_RegisterVariable (&config_com_port);
869 Cvar_RegisterVariable (&config_com_irq);
870 Cvar_RegisterVariable (&config_com_baud);
871 Cvar_RegisterVariable (&config_com_modem);
872 Cvar_RegisterVariable (&config_modem_dialtype);
873 Cvar_RegisterVariable (&config_modem_clear);
874 Cvar_RegisterVariable (&config_modem_init);
875 Cvar_RegisterVariable (&config_modem_hangup);
876 #ifdef IDGODS
877 Cvar_RegisterVariable (&idgods);
878 #endif
879
880 Cmd_AddCommand ("slist", NET_Slist_f);
881 Cmd_AddCommand ("listen", NET_Listen_f);
882 Cmd_AddCommand ("maxplayers", MaxPlayers_f);
883 Cmd_AddCommand ("port", NET_Port_f);
884
885 // initialize all the drivers
886 for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
887 {
888 controlSocket = net_drivers[net_driverlevel].Init();
889 if (controlSocket == -1)
890 continue;
891 net_drivers[net_driverlevel].initialized = true;
892 net_drivers[net_driverlevel].controlSock = controlSocket;
893 if (listening)
894 net_drivers[net_driverlevel].Listen (true);
895 }
896
897 if (*my_ipx_address)
898 Con_DPrintf("IPX address %s\n", my_ipx_address);
899 if (*my_tcpip_address)
900 Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
901 }
902
903 /*
904 ====================
905 NET_Shutdown
906 ====================
907 */
908
NET_Shutdown(void)909 void NET_Shutdown (void)
910 {
911 qsocket_t *sock;
912
913 SetNetTime();
914
915 for (sock = net_activeSockets; sock; sock = sock->next)
916 NET_Close(sock);
917
918 //
919 // shutdown the drivers
920 //
921 for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
922 {
923 if (net_drivers[net_driverlevel].initialized == true)
924 {
925 net_drivers[net_driverlevel].Shutdown ();
926 net_drivers[net_driverlevel].initialized = false;
927 }
928 }
929
930 if (vcrFile != -1)
931 {
932 Con_Printf ("Closing vcrfile.\n");
933 Sys_FileClose(vcrFile);
934 }
935 }
936
937
938 static PollProcedure *pollProcedureList = NULL;
939
NET_Poll(void)940 void NET_Poll(void)
941 {
942 PollProcedure *pp;
943 qboolean useModem;
944
945 if (!configRestored)
946 {
947 if (serialAvailable)
948 {
949 if (config_com_modem.value == 1.0)
950 useModem = true;
951 else
952 useModem = false;
953 SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
954 SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
955 }
956 configRestored = true;
957 }
958
959 SetNetTime();
960
961 for (pp = pollProcedureList; pp; pp = pp->next)
962 {
963 if (pp->nextTime > net_time)
964 break;
965 pollProcedureList = pp->next;
966 pp->procedure(pp->arg);
967 }
968 }
969
970
SchedulePollProcedure(PollProcedure * proc,double timeOffset)971 void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
972 {
973 PollProcedure *pp, *prev;
974
975 proc->nextTime = Sys_FloatTime() + timeOffset;
976 for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
977 {
978 if (pp->nextTime >= proc->nextTime)
979 break;
980 prev = pp;
981 }
982
983 if (prev == NULL)
984 {
985 proc->next = pollProcedureList;
986 pollProcedureList = proc;
987 return;
988 }
989
990 proc->next = pp;
991 prev->next = proc;
992 }
993
994
995 #ifdef IDGODS
996 #define IDNET 0xc0f62800
997
IsID(struct qsockaddr * addr)998 qboolean IsID(struct qsockaddr *addr)
999 {
1000 if (idgods.value == 0.0)
1001 return false;
1002
1003 if (addr->sa_family != 2)
1004 return false;
1005
1006 if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
1007 return true;
1008 return false;
1009 }
1010 #endif
1011