• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, NULL};
55 PollProcedure	slistPollProcedure = {NULL, 0.0, Slist_Poll, NULL};
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 = CVAR2("net_messagetimeout","300");
67 cvar_t	hostname = CVAR2("hostname", "UNNAMED");
68 
69 qboolean	configRestored = false;
70 cvar_t	config_com_port = CVAR3("_config_com_port", "0x3f8", true);
71 cvar_t	config_com_irq = CVAR3("_config_com_irq", "4", true);
72 cvar_t	config_com_baud = CVAR3("_config_com_baud", "57600", true);
73 cvar_t	config_com_modem = CVAR3("_config_com_modem", "1", true);
74 cvar_t	config_modem_dialtype = CVAR3("_config_modem_dialtype", "T", true);
75 cvar_t	config_modem_clear = CVAR3("_config_modem_clear", "ATZ", true);
76 cvar_t	config_modem_init = CVAR3("_config_modem_init", "", true);
77 cvar_t	config_modem_hangup = CVAR3("_config_modem_hangup", "AT H", true);
78 
79 #ifdef IDGODS
80 cvar_t	idgods = CVAR2("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* /* arg */)
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* /* arg */)
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(const char * host)368 qsocket_t *NET_Connect (const 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 vcrConnect_t
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 vcrGetMessage_t
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 		if (net_time - sock->lastMessageTime > net_messagetimeout.value)
561 		{
562 			NET_Close(sock);
563 			return -1;
564 		}
565 	}
566 
567 
568 	if (ret > 0)
569 	{
570 		if (sock->driver)
571 		{
572 			sock->lastMessageTime = net_time;
573 			if (ret == 1)
574 				messagesReceived++;
575 			else if (ret == 2)
576 				unreliableMessagesReceived++;
577 		}
578 
579 		if (recording)
580 		{
581 			vcrGetMessage.time = host_time;
582 			vcrGetMessage.op = VCR_OP_GETMESSAGE;
583 			vcrGetMessage.session = (long)sock;
584 			vcrGetMessage.ret = ret;
585 			vcrGetMessage.len = net_message.cursize;
586 			Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
587 			Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
588 		}
589 	}
590 	else
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 			Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
599 		}
600 	}
601 
602 	return ret;
603 }
604 
605 
606 /*
607 ==================
608 NET_SendMessage
609 
610 Try to send a complete length+message unit over the reliable stream.
611 returns 0 if the message cannot be delivered reliably, but the connection
612 		is still considered valid
613 returns 1 if the message was sent properly
614 returns -1 if the connection died
615 ==================
616 */
617 struct vcrSendMessage_t
618 {
619 	double	time;
620 	int		op;
621 	long	session;
622 	int		r;
623 } vcrSendMessage;
624 
NET_SendMessage(qsocket_t * sock,sizebuf_t * data)625 int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
626 {
627 	int		r;
628 
629 	if (!sock)
630 		return -1;
631 
632 	if (sock->disconnected)
633 	{
634 		Con_Printf("NET_SendMessage: disconnected socket\n");
635 		return -1;
636 	}
637 
638 	SetNetTime();
639 	r = sfunc.QSendMessage(sock, data);
640 	if (r == 1 && sock->driver)
641 		messagesSent++;
642 
643 	if (recording)
644 	{
645 		vcrSendMessage.time = host_time;
646 		vcrSendMessage.op = VCR_OP_SENDMESSAGE;
647 		vcrSendMessage.session = (long)sock;
648 		vcrSendMessage.r = r;
649 		Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
650 	}
651 
652 	return r;
653 }
654 
655 
NET_SendUnreliableMessage(qsocket_t * sock,sizebuf_t * data)656 int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
657 {
658 	int		r;
659 
660 	if (!sock)
661 		return -1;
662 
663 	if (sock->disconnected)
664 	{
665 		Con_Printf("NET_SendMessage: disconnected socket\n");
666 		return -1;
667 	}
668 
669 	SetNetTime();
670 	r = sfunc.SendUnreliableMessage(sock, data);
671 	if (r == 1 && sock->driver)
672 		unreliableMessagesSent++;
673 
674 	if (recording)
675 	{
676 		vcrSendMessage.time = host_time;
677 		vcrSendMessage.op = VCR_OP_SENDMESSAGE;
678 		vcrSendMessage.session = (long)sock;
679 		vcrSendMessage.r = r;
680 		Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
681 	}
682 
683 	return r;
684 }
685 
686 
687 /*
688 ==================
689 NET_CanSendMessage
690 
691 Returns true or false if the given qsocket can currently accept a
692 message to be transmitted.
693 ==================
694 */
NET_CanSendMessage(qsocket_t * sock)695 qboolean NET_CanSendMessage (qsocket_t *sock)
696 {
697 	int		r;
698 
699 	if (!sock)
700 		return false;
701 
702 	if (sock->disconnected)
703 		return false;
704 
705 	SetNetTime();
706 
707 	r = sfunc.CanSendMessage(sock);
708 
709 	if (recording)
710 	{
711 		vcrSendMessage.time = host_time;
712 		vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
713 		vcrSendMessage.session = (long)sock;
714 		vcrSendMessage.r = r;
715 		Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
716 	}
717 
718 	return r;
719 }
720 
721 
NET_SendToAll(sizebuf_t * data,int blocktime)722 int NET_SendToAll(sizebuf_t *data, int blocktime)
723 {
724 	double		start;
725 	int			i;
726 	int			count = 0;
727 	qboolean	state1 [MAX_SCOREBOARD];
728 	qboolean	state2 [MAX_SCOREBOARD];
729 
730 	for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
731 	{
732 		if (!host_client->netconnection)
733 			continue;
734 		if (host_client->active)
735 		{
736 			if (host_client->netconnection->driver == 0)
737 			{
738 				NET_SendMessage(host_client->netconnection, data);
739 				state1[i] = true;
740 				state2[i] = true;
741 				continue;
742 			}
743 			count++;
744 			state1[i] = false;
745 			state2[i] = false;
746 		}
747 		else
748 		{
749 			state1[i] = true;
750 			state2[i] = true;
751 		}
752 	}
753 
754 	start = Sys_FloatTime();
755 	while (count)
756 	{
757 		count = 0;
758 		for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
759 		{
760 			if (! state1[i])
761 			{
762 				if (NET_CanSendMessage (host_client->netconnection))
763 				{
764 					state1[i] = true;
765 					NET_SendMessage(host_client->netconnection, data);
766 				}
767 				else
768 				{
769 					NET_GetMessage (host_client->netconnection);
770 				}
771 				count++;
772 				continue;
773 			}
774 
775 			if (! state2[i])
776 			{
777 				if (NET_CanSendMessage (host_client->netconnection))
778 				{
779 					state2[i] = true;
780 				}
781 				else
782 				{
783 					NET_GetMessage (host_client->netconnection);
784 				}
785 				count++;
786 				continue;
787 			}
788 		}
789 		if ((Sys_FloatTime() - start) > blocktime)
790 			break;
791 	}
792 	return count;
793 }
794 
795 
796 //=============================================================================
797 
798 /*
799 ====================
800 NET_Init
801 ====================
802 */
803 
NET_Init(void)804 void NET_Init (void)
805 {
806 	int			i;
807 	int			controlSocket;
808 	qsocket_t	*s;
809 
810 	if (COM_CheckParm("-playback"))
811 	{
812 		net_numdrivers = 1;
813 		net_drivers[0].Init = VCR_Init;
814 	}
815 
816 	if (COM_CheckParm("-record"))
817 		recording = true;
818 
819 	i = COM_CheckParm ("-port");
820 	if (!i)
821 		i = COM_CheckParm ("-udpport");
822 	if (!i)
823 		i = COM_CheckParm ("-ipxport");
824 
825 	if (i)
826 	{
827 		if (i < com_argc-1)
828 			DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
829 		else
830 			Sys_Error ("NET_Init: you must specify a number after -port");
831 	}
832 	net_hostport = DEFAULTnet_hostport;
833 
834 	if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
835 		listening = true;
836 	net_numsockets = svs.maxclientslimit;
837 	if (cls.state != ca_dedicated)
838 		net_numsockets++;
839 
840 	SetNetTime();
841 
842 	for (i = 0; i < net_numsockets; i++)
843 	{
844 		s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
845 		s->next = net_freeSockets;
846 		net_freeSockets = s;
847 		s->disconnected = true;
848 	}
849 
850 	// allocate space for network message buffer
851 	SZ_Alloc (&net_message, NET_MAXMESSAGE);
852 
853 	Cvar_RegisterVariable (&net_messagetimeout);
854 	Cvar_RegisterVariable (&hostname);
855 	Cvar_RegisterVariable (&config_com_port);
856 	Cvar_RegisterVariable (&config_com_irq);
857 	Cvar_RegisterVariable (&config_com_baud);
858 	Cvar_RegisterVariable (&config_com_modem);
859 	Cvar_RegisterVariable (&config_modem_dialtype);
860 	Cvar_RegisterVariable (&config_modem_clear);
861 	Cvar_RegisterVariable (&config_modem_init);
862 	Cvar_RegisterVariable (&config_modem_hangup);
863 #ifdef IDGODS
864 	Cvar_RegisterVariable (&idgods);
865 #endif
866 
867 	Cmd_AddCommand ("slist", NET_Slist_f);
868 	Cmd_AddCommand ("listen", NET_Listen_f);
869 	Cmd_AddCommand ("maxplayers", MaxPlayers_f);
870 	Cmd_AddCommand ("port", NET_Port_f);
871 
872 	// initialize all the drivers
873 	for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
874 		{
875 		controlSocket = net_drivers[net_driverlevel].Init();
876 		if (controlSocket == -1)
877 			continue;
878 		net_drivers[net_driverlevel].initialized = true;
879 		net_drivers[net_driverlevel].controlSock = controlSocket;
880 		if (listening)
881 			net_drivers[net_driverlevel].Listen (true);
882 		}
883 
884 	if (*my_ipx_address)
885 		Con_DPrintf("IPX address %s\n", my_ipx_address);
886 	if (*my_tcpip_address)
887 		Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
888 }
889 
890 /*
891 ====================
892 NET_Shutdown
893 ====================
894 */
895 
NET_Shutdown(void)896 void		NET_Shutdown (void)
897 {
898 	qsocket_t	*sock;
899 
900 	SetNetTime();
901 
902 	for (sock = net_activeSockets; sock; sock = sock->next)
903 		NET_Close(sock);
904 
905 //
906 // shutdown the drivers
907 //
908 	for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
909 	{
910 		if (net_drivers[net_driverlevel].initialized == true)
911 		{
912 			net_drivers[net_driverlevel].Shutdown ();
913 			net_drivers[net_driverlevel].initialized = false;
914 		}
915 	}
916 
917 	if (vcrFile != -1)
918 	{
919 		Con_Printf ("Closing vcrfile.\n");
920 		Sys_FileClose(vcrFile);
921 	}
922 }
923 
924 
925 static PollProcedure *pollProcedureList = NULL;
926 
NET_Poll(void)927 void NET_Poll(void)
928 {
929 	PollProcedure *pp;
930 	qboolean	useModem;
931 
932 	if (!configRestored)
933 	{
934 		if (serialAvailable)
935 		{
936 			if (config_com_modem.value == 1.0)
937 				useModem = true;
938 			else
939 				useModem = false;
940 			SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
941 			SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
942 		}
943 		configRestored = true;
944 	}
945 
946 	SetNetTime();
947 
948 	for (pp = pollProcedureList; pp; pp = pp->next)
949 	{
950 		if (pp->nextTime > net_time)
951 			break;
952 		pollProcedureList = pp->next;
953 		pp->procedure(pp->arg);
954 	}
955 }
956 
957 
SchedulePollProcedure(PollProcedure * proc,double timeOffset)958 void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
959 {
960 	PollProcedure *pp, *prev;
961 
962 	proc->nextTime = Sys_FloatTime() + timeOffset;
963 	for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
964 	{
965 		if (pp->nextTime >= proc->nextTime)
966 			break;
967 		prev = pp;
968 	}
969 
970 	if (prev == NULL)
971 	{
972 		proc->next = pollProcedureList;
973 		pollProcedureList = proc;
974 		return;
975 	}
976 
977 	proc->next = pp;
978 	prev->next = proc;
979 }
980 
981 
982 #ifdef IDGODS
983 #define IDNET	0xc0f62800
984 
IsID(struct qsockaddr * addr)985 qboolean IsID(struct qsockaddr *addr)
986 {
987 	if (idgods.value == 0.0)
988 		return false;
989 
990 	if (addr->sa_family != 2)
991 		return false;
992 
993 	if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
994 		return true;
995 	return false;
996 }
997 #endif
998