1 /*
2 Copyright (C) 1997-2001 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 //
22 // net.c
23 //
24
25 #include "qcommon.h"
26 #include "net.h"
27
28 #define MAX_LOOPBACK 4
29
30 typedef struct {
31 byte data[MAX_PACKETLEN];
32 int datalen;
33 } loopmsg_t;
34
35 typedef struct {
36 loopmsg_t msgs[MAX_LOOPBACK];
37 int get;
38 int send;
39 } loopback_t;
40
41 static cvar_t *net_ip;
42 static cvar_t *net_port;
43 static cvar_t *net_clientport;
44 static cvar_t *net_dropsim;
45 static cvar_t *net_log_active;
46 static cvar_t *net_log_name;
47 static cvar_t *net_log_flush;
48 static cvar_t *net_ignore_icmp;
49
50 static loopback_t loopbacks[NS_COUNT];
51 static SOCKET sockets[NS_COUNT] = { INVALID_SOCKET, INVALID_SOCKET };
52
53 static fileHandle_t net_logFile;
54 static netflag_t net_active;
55
56 void NET_LogPacket( const netadr_t *address, qboolean send, const byte *data, int dataSize );
57
58 //=============================================================================
59
60 /*
61 ===================
62 NET_NetadrToSockadr
63 ===================
64 */
NET_NetadrToSockadr(const netadr_t * a,struct sockaddr * s)65 void NET_NetadrToSockadr( const netadr_t *a, struct sockaddr *s ) {
66 memset( s, 0, sizeof( *s ) );
67
68 switch( a->type ) {
69 case NA_BROADCAST:
70 ((struct sockaddr_in *)s)->sin_family = AF_INET;
71 ((struct sockaddr_in *)s)->sin_port = a->port;
72 ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
73 break;
74 case NA_IP:
75 ((struct sockaddr_in *)s)->sin_family = AF_INET;
76 ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
77 ((struct sockaddr_in *)s)->sin_port = a->port;
78 break;
79 default:
80 Com_Error( ERR_FATAL, "NetadrToSockadr: bad address type" );
81 break;
82 }
83 }
84
85 /*
86 ===================
87 NET_SockadrToNetadr
88 ===================
89 */
NET_SockadrToNetadr(const struct sockaddr * s,netadr_t * a)90 void NET_SockadrToNetadr( const struct sockaddr *s, netadr_t *a ) {
91 memset( a, 0, sizeof( *a ) );
92
93 a->type = NA_IP;
94 *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
95 a->port = ((struct sockaddr_in *)s)->sin_port;
96
97 }
98
99 /*
100 =============
101 NET_StringToSockaddr
102
103 localhost
104 idnewt
105 idnewt:28000
106 192.246.40.70
107 192.246.40.70:28000
108 =============
109 */
NET_StringToSockaddr(const char * s,struct sockaddr * sadr)110 qboolean NET_StringToSockaddr( const char *s, struct sockaddr *sadr ) {
111 struct hostent *h;
112 char *colon;
113 char copy[MAX_QPATH];
114
115 memset( sadr, 0, sizeof( *sadr ) );
116
117 ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
118 ((struct sockaddr_in *)sadr)->sin_port = 0;
119
120 Q_strncpyz( copy, s, sizeof( copy ) );
121 // strip off a trailing :port if present
122 for( colon = copy ; *colon ; colon++ )
123 if( *colon == ':' ) {
124 *colon = 0;
125 ((struct sockaddr_in *)sadr)->sin_port =
126 htons( (u_short)atoi( colon + 1 ) );
127 }
128
129 if( copy[0] >= '0' && copy[0] <= '9' ) {
130 *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr( copy );
131 } else {
132 if( !( h = gethostbyname( copy ) ) )
133 return qfalse;
134 *(int *)&((struct sockaddr_in *)sadr)->sin_addr =
135 *(int *)h->h_addr_list[0];
136 }
137
138
139 return qtrue;
140 }
141
142 /*
143 ===================
144 NET_IsEqualAdr
145 ===================
146 */
NET_IsEqualAdr(const netadr_t * a,const netadr_t * b)147 qboolean NET_IsEqualAdr( const netadr_t *a, const netadr_t *b ) {
148 if( a->type != b->type ) {
149 return qfalse;
150 }
151
152 switch( a->type ) {
153 case NA_LOOPBACK:
154 return qtrue;
155 case NA_IP:
156 case NA_BROADCAST:
157 if( *( uint32 * )a->ip == *( uint32 * )b->ip &&
158 a->port == b->port )
159 {
160 return qtrue;
161 }
162 return qfalse;
163 default:
164 Com_Error( ERR_FATAL, "NET_IsEqualAdr: bad address type: %i", a->type );
165 break;
166 }
167
168 return qfalse;
169 }
170
171 /*
172 ===================
173 NET_IsEqualBaseAdr
174
175 Compares without the port
176 ===================
177 */
NET_IsEqualBaseAdr(const netadr_t * a,const netadr_t * b)178 qboolean NET_IsEqualBaseAdr( const netadr_t *a, const netadr_t *b ) {
179 if( a->type != b->type ) {
180 return qfalse;
181 }
182
183 switch( a->type ) {
184 case NA_LOOPBACK:
185 return qtrue;
186 case NA_IP:
187 case NA_BROADCAST:
188 if( *( uint32 * )a->ip == *( uint32 * )b->ip ) {
189 return qtrue;
190 }
191 return qfalse;
192 default:
193 Com_Error( ERR_FATAL, "NET_IsEqualBaseAdr: bad address type: %i", a->type );
194 break;
195 }
196
197 return qfalse;
198 }
199
200 /*
201 ===================
202 NET_IsLANAddress
203 ===================
204 */
NET_IsLANAddress(const netadr_t * adr)205 qboolean NET_IsLANAddress( const netadr_t *adr ) {
206 switch( adr->type ) {
207 case NA_LOOPBACK:
208 return qtrue;
209 case NA_IP:
210 case NA_BROADCAST:
211 if( adr->ip[0] == 127 || adr->ip[0] == 10 ) {
212 return qtrue;
213 }
214 if( ( adr->ip[0] == 192 && adr->ip[1] == 168 ) ||
215 ( adr->ip[0] == 172 && adr->ip[1] == 16 ) )
216 {
217 return qtrue;
218 }
219 return qfalse;
220 default:
221 Com_Error( ERR_FATAL, "NET_IsLANAddress: bad address type: %i", adr->type );
222 break;
223 }
224
225 return qfalse;
226 }
227
228 /*
229 ===================
230 NET_AdrToString
231 ===================
232 */
NET_AdrToString(const netadr_t * a)233 char *NET_AdrToString( const netadr_t *a ) {
234 static char s[MAX_QPATH];
235
236 switch( a->type ) {
237 case NA_LOOPBACK:
238 Com_sprintf( s, sizeof( s ), "loopback" );
239 return s;
240 case NA_IP:
241 case NA_BROADCAST:
242 Com_sprintf( s, sizeof( s ), "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs( a->port ) );
243 return s;
244 default:
245 Com_Error( ERR_FATAL, "NET_AdrToString: bad address type: %i", a->type );
246 break;
247 }
248
249 return NULL;
250 }
251
252 /*
253 =============
254 NET_StringToAdr
255
256 localhost
257 idnewt
258 idnewt:28000
259 192.246.40.70
260 192.246.40.70:28000
261 =============
262 */
NET_StringToAdr(const char * s,netadr_t * a)263 qboolean NET_StringToAdr( const char *s, netadr_t *a ) {
264 struct sockaddr sadr;
265
266 if( !Q_stricmp( s, "localhost" ) ) {
267 memset( a, 0, sizeof( *a ) );
268 a->type = NA_LOOPBACK;
269 return qtrue;
270 }
271
272 if( !NET_StringToSockaddr( s, &sadr ) )
273 return qfalse;
274
275 NET_SockadrToNetadr( &sadr, a );
276
277 return qtrue;
278 }
279
280 /*
281 =============================================================================
282
283 LOOPBACK BUFFERS FOR LOCAL PLAYER
284
285 =============================================================================
286 */
287
288 /*
289 =============
290 NET_GetLoopPacket
291 =============
292 */
NET_GetLoopPacket(netsrc_t sock)293 qboolean NET_GetLoopPacket( netsrc_t sock ) {
294 loopback_t *loop;
295 loopmsg_t *loopmsg;
296
297 loop = &loopbacks[sock];
298
299 if( loop->send - loop->get > MAX_LOOPBACK - 1 ) {
300 loop->get = loop->send - MAX_LOOPBACK + 1;
301 }
302
303 if( loop->get >= loop->send ) {
304 return qfalse;
305 }
306
307 loopmsg = &loop->msgs[loop->get & (MAX_LOOPBACK-1)];
308 loop->get++;
309
310 memcpy( msg_read.data, loopmsg->data, loopmsg->datalen );
311 msg_read.cursize = loopmsg->datalen;
312
313 if( net_log_active->integer ) {
314 NET_LogPacket( &net_from, qfalse, loopmsg->data, loopmsg->datalen );
315 }
316
317 return qtrue;
318
319 }
320
321
322 //=============================================================================
323
NetLogFile_Close(void)324 static void NetLogFile_Close( void ) {
325 if( !net_logFile ) {
326 return;
327 }
328
329 Com_Printf( "Closing %s\n", FS_GetFileName( net_logFile ) );
330
331 FS_FCloseFile( net_logFile );
332 net_logFile = 0;
333 }
334
NetLogFile_Open(void)335 static void NetLogFile_Open( void ) {
336 uint32 mode;
337
338 mode = net_log_active->integer > 1 ? FS_MODE_APPEND : FS_MODE_WRITE;
339
340 if( net_log_flush->integer ) {
341 mode |= FS_FLUSH_SYNC;
342 }
343
344 FS_FOpenFile( net_log_name->string, &net_logFile, mode );
345
346 if( !net_logFile ) {
347 Com_WPrintf( "Couldn't open %s\n", net_log_name->string );
348 Cvar_SetInteger( "net_log_active", 0 );
349 return;
350 }
351
352 Com_Printf( "Logging network packets to %s\n", net_log_name->string );
353 }
354
NetLogFileActive_OnChange(cvar_t * self,void * arg)355 static void NetLogFileActive_OnChange( cvar_t *self, void *arg ) {
356 if( !self->integer ) {
357 NetLogFile_Close();
358 } else {
359 NetLogFile_Open();
360 }
361 }
362
NetLogFileParam_OnChange(cvar_t * self,void * arg)363 static void NetLogFileParam_OnChange( cvar_t *self, void *arg ) {
364 if( net_log_active->integer ) {
365 NetLogFile_Close();
366 NetLogFile_Open();
367 }
368 }
369
370 /*
371 =============
372 NET_LogPacket
373 =============
374 */
NET_LogPacket(const netadr_t * address,qboolean send,const byte * data,int dataSize)375 void NET_LogPacket( const netadr_t *address, qboolean send, const byte *data, int dataSize ) {
376 int numRows;
377 int i, j, c;
378
379 if( !net_logFile ) {
380 return;
381 }
382
383 FS_FPrintf( net_logFile, "%s : %s\n", send ? "send" : "recv", NET_AdrToString( address ) );
384
385 numRows = ( dataSize + 15 ) / 16;
386 for( i = 0; i < numRows; i++ ) {
387 FS_FPrintf( net_logFile, "%04x : ", i * 16 );
388 for( j = 0; j < 16; j++ ) {
389 if( i * 16 + j < dataSize ) {
390 FS_FPrintf( net_logFile, "%02x ", data[i * 16 + j] );
391 } else {
392 FS_FPrintf( net_logFile, " " );
393 }
394 }
395 FS_FPrintf( net_logFile, ": ", i );
396 for( j = 0; j < 16; j++ ) {
397 if( i * 16 + j < dataSize ) {
398 c = data[i * 16 + j];
399 FS_FPrintf( net_logFile, "%c", ( c < 32 || c > 127 ) ? '.' : c );
400 } else {
401 FS_FPrintf( net_logFile, " " );
402 }
403 }
404 FS_FPrintf( net_logFile, "\n" );
405 }
406
407 FS_FPrintf( net_logFile, "\n" );
408
409 }
410
411 /*
412 =============
413 NET_GetPacket
414
415 Fills current read buffer with packet contents
416 =============
417 */
NET_GetPacket(netsrc_t sock,netadr_t * fromAddress)418 int NET_GetPacket( netsrc_t sock, netadr_t *fromAddress ) {
419 byte buffer[MAX_PACKETLEN + 10];
420 int ret;
421 struct sockaddr from;
422 uint32 fromlen;
423 int err;
424
425 if( sock >= NS_COUNT ) {
426 Com_Error( ERR_FATAL, "NET_GetPacket: bad socket" );
427 }
428 if( sockets[sock] == INVALID_SOCKET ) {
429 return 0;
430 }
431
432 fromlen = sizeof( from );
433 ret = recvfrom( sockets[sock], buffer, sizeof( buffer ), 0,
434 ( struct sockaddr * )&from, &fromlen );
435
436 NET_SockadrToNetadr( &from, fromAddress );
437
438 if( ret == -1 ) {
439 #ifdef WIN32
440 err = WSAGetLastError();
441
442 switch( err ) {
443 case WSAEWOULDBLOCK:
444 // wouldblock is silent
445 break;
446 case WSAECONNRESET:
447 if( !net_ignore_icmp->integer ) {
448 return -1;
449 }
450 break;
451 case WSAEMSGSIZE:
452 Com_WPrintf( "NET_GetPacket: oversize packet from %s\n",
453 NET_AdrToString( fromAddress ) );
454 break;
455 default:
456 Com_EPrintf( "NET_GetPacket: %s from %s\n",
457 Sys_NetErrorString(), NET_AdrToString( fromAddress ) );
458 break;
459 }
460 #else
461 err = errno;
462
463 switch( err ) {
464 case EWOULDBLOCK:
465 // wouldblock is silent
466 break;
467 case ECONNREFUSED:
468 if( !net_ignore_icmp->integer ) {
469 return -1;
470 }
471 break;
472 default:
473 Com_EPrintf( "NET_GetPacket: %s from %s\n",
474 Sys_NetErrorString(), NET_AdrToString( fromAddress ) );
475 break;
476 }
477 #endif
478 return 0;
479 }
480
481 if( net_log_active->integer ) {
482 NET_LogPacket( fromAddress, qfalse, buffer, ret );
483 }
484
485 if( ret > msg_read.maxsize ) {
486 Com_WPrintf( "NET_GetPacket: oversize packet from %s\n",
487 NET_AdrToString( fromAddress ) );
488 return 0;
489 }
490
491 memcpy( msg_read.data, buffer, ret );
492 msg_read.cursize = ret;
493
494
495
496 return 1;
497
498 }
499
500 //=============================================================================
501
502 /*
503 =============
504 NET_SendPacket
505 =============
506 */
NET_SendPacket(netsrc_t sock,const netadr_t * to,int length,const byte * data)507 int NET_SendPacket( netsrc_t sock, const netadr_t *to, int length, const byte *data ) {
508 int ret;
509 struct sockaddr addr;
510 int err;
511
512 if( sock >= NS_COUNT ) {
513 Com_Error( ERR_FATAL, "NET_GetPacket: bad socket" );
514 }
515 if( length < 0 ) {
516 Com_Error( ERR_FATAL, "NET_SendPacket: bad length: %d\n", length );
517 }
518 if( length > MAX_PACKETLEN ) {
519 Com_WPrintf( "NET_SendPacket: oversize packet: %d\n", length );
520 return 0;
521 }
522
523 switch( to->type ) {
524 case NA_LOOPBACK: {
525 loopback_t *loop;
526 loopmsg_t *msg;
527
528 if( net_dropsim->integer > 0 && ( rand() % 100 ) < net_dropsim->integer ) {
529 return 0;
530 }
531
532 loop = &loopbacks[sock ^ 1];
533
534 msg = &loop->msgs[loop->send & ( MAX_LOOPBACK - 1 )];
535 loop->send++;
536
537 memcpy( msg->data, data, length );
538 msg->datalen = length;
539
540 if( net_log_active->integer ) {
541 NET_LogPacket( to, qtrue, data, length );
542 }
543 }
544 return 1;
545 case NA_IP:
546 case NA_BROADCAST:
547 break;
548 default:
549 Com_Error( ERR_FATAL, "NET_SendPacket: bad address type: %i", to->type );
550 break;
551 }
552
553 if( sockets[sock] == INVALID_SOCKET ) {
554 return 0;
555 }
556
557 NET_NetadrToSockadr( to, &addr );
558
559 ret = sendto( sockets[sock], data, length, 0, &addr, sizeof( addr ) );
560 if( net_log_active->integer ) {
561 NET_LogPacket( to, qtrue, data, length );
562 }
563
564 if( ret == SOCKET_ERROR ) {
565 #ifdef WIN32
566 err = WSAGetLastError();
567
568 switch( err ) {
569 case WSAEWOULDBLOCK:
570 case WSAEINTR:
571 // wouldblock is silent
572 break;
573 case WSAECONNRESET:
574 case WSAEHOSTUNREACH:
575 if( !net_ignore_icmp->integer ) {
576 return -1;
577 }
578 break;
579 case WSAEADDRNOTAVAIL:
580 // some PPP links do not allow broadcasts
581 if( to->type == NA_BROADCAST ) {
582 break;
583 }
584 // intentional fallthrough
585 default:
586 Com_EPrintf( "NET_SendPacket: %s to %s\n",
587 Sys_NetErrorString(), NET_AdrToString( to ) );
588 break;
589 }
590 #else
591 err = errno;
592
593 switch( err ) {
594 case EWOULDBLOCK:
595 // wouldblock is silent
596 break;
597 case ECONNRESET:
598 case EHOSTUNREACH:
599 case ENETUNREACH:
600 case ENETDOWN:
601 if( !net_ignore_icmp->integer ) {
602 return -1;
603 }
604 break;
605 default:
606 Com_EPrintf( "NET_SendPacket: %s (%d) to %s\n",
607 Sys_NetErrorString(), err, NET_AdrToString( to ) );
608 break;
609 }
610 #endif
611
612 return 0;
613
614 }
615
616 return 1;
617 }
618
619
620 //=============================================================================
621
622 /*
623 ====================
624 NET_OpenServerIP
625 ====================
626 */
NET_OpenServerIP(void)627 static void NET_OpenServerIP( void ) {
628 int port;
629
630 for( port = 0; port < PORT_MAX_SEARCH; port++ ) {
631 sockets[NS_SERVER] = Sys_IPSocket( net_ip->string, net_port->integer + port );
632 if( sockets[NS_SERVER] != INVALID_SOCKET ) {
633 if( port ) {
634 Cvar_SetInteger( "net_port", net_port->integer + port );
635 }
636 // set this for compatibility with game mods
637 Cvar_SetInteger( "port", net_port->integer + port );
638 return;
639 }
640 }
641
642 if( dedicated->integer ) {
643 Com_Error( ERR_FATAL, "Couldn't allocate dedicated server IP port" );
644 }
645
646 Com_Error( ERR_DROP, "Couldn't allocate server IP port" );
647
648 }
649
650 /*
651 ====================
652 NET_OpenClientIP
653 ====================
654 */
NET_OpenClientIP(void)655 static void NET_OpenClientIP( void ) {
656 sockets[NS_CLIENT] = Sys_IPSocket( net_ip->string, net_clientport->integer );
657 if( sockets[NS_CLIENT] != INVALID_SOCKET ) {
658 return;
659 }
660
661 if( net_clientport->integer != PORT_ANY ) {
662 sockets[NS_CLIENT] = Sys_IPSocket( net_ip->string, PORT_ANY );
663 if( sockets[NS_CLIENT] != INVALID_SOCKET ) {
664 Cvar_SetInteger( "net_clientport", PORT_ANY );
665 return;
666 }
667 }
668
669 Com_Error( ERR_DROP, "Couldn't allocate client IP port" );
670
671 }
672
673 /*
674 ====================
675 NET_Sleep
676
677 sleeps msec or until net socket is ready
678 ====================
679 */
NET_Sleep(int msec)680 void NET_Sleep( int msec ) {
681 struct timeval timeout;
682 fd_set fdset;
683 SOCKET i;
684
685 FD_ZERO( &fdset );
686 i = 0;
687 FD_SET( 0, &fdset ); // stdin
688 if( sockets[NS_SERVER] != INVALID_SOCKET ) {
689 FD_SET( sockets[NS_SERVER], &fdset ); // network socket
690 i = sockets[NS_SERVER];
691 }
692 timeout.tv_sec = msec / 1000;
693 timeout.tv_usec = ( msec % 1000 ) * 1000;
694 select( i + 1, &fdset, NULL, NULL, &timeout );
695 }
696
697 //===================================================================
698
699 /*
700 ====================
701 NET_DumpHostInfo
702 ====================
703 */
NET_DumpHostInfo(struct hostent * h)704 static void NET_DumpHostInfo( struct hostent *h ) {
705 byte **list;
706 int i;
707
708 Com_Printf( "Hostname: %s\n", h->h_name );
709
710 list = (byte **)h->h_aliases;
711 for( i=0 ; list[i] ; i++ ) {
712 Com_Printf( "Alias : %s\n", list[i] );
713 }
714
715 list = (byte **)h->h_addr_list;
716 for( i=0 ; list[i] ; i++ ) {
717 Com_Printf( "IP : %d.%d.%d.%d\n",
718 list[i][0] & 255,
719 list[i][1] & 255,
720 list[i][2] & 255,
721 list[i][3] & 255 );
722 }
723 }
724
725 /*
726 ====================
727 NET_ShowIP_f
728 ====================
729 */
NET_ShowIP_f(void)730 static void NET_ShowIP_f( void ) {
731 char buffer[256];
732 struct hostent *h;
733
734 if( gethostname( buffer, sizeof( buffer ) ) == SOCKET_ERROR ) {
735 Com_Printf( "Couldn't get machine hostname\n" );
736 return;
737 }
738
739 if( !( h = gethostbyname( buffer ) ) ) {
740 Com_Printf( "Couldn't get machine hostname\n" );
741 return;
742 }
743
744 NET_DumpHostInfo( h );
745 }
746
747 /*
748 ====================
749 NET_Dns_f
750 ====================
751 */
NET_Dns_f(void)752 static void NET_Dns_f( void ) {
753 char buffer[MAX_QPATH];
754 char *p;
755 struct hostent *h;
756 u_long address;
757
758 if( Cmd_Argc() != 2 ) {
759 Com_Printf( "Usage: %s <address>\n", Cmd_Argv( 0 ) );
760 return;
761 }
762
763 Cmd_ArgvBuffer( 1, buffer, sizeof( buffer ) );
764
765 if( ( p = strchr( buffer, ':' ) ) != NULL ) {
766 *p = 0;
767 }
768
769 if( ( address = inet_addr( buffer ) ) != INADDR_NONE ) {
770 h = gethostbyaddr( (const char *)&address, sizeof( address ), AF_INET );
771 } else {
772 h = gethostbyname( buffer );
773 }
774
775 if( !h ) {
776 Com_Printf( "Couldn't resolve %s\n", buffer );
777 return;
778 }
779
780 NET_DumpHostInfo( h );
781
782 }
783
784 /*
785 ====================
786 NET_Restart_f
787 ====================
788 */
NET_Restart_f(void)789 static void NET_Restart_f( void ) {
790 netflag_t flag = net_active;
791
792 NET_Config( NET_NONE );
793 NET_Config( flag );
794 }
795
796 /*
797 ====================
798 NET_Config
799 ====================
800 */
NET_Config(netflag_t flag)801 void NET_Config( netflag_t flag ) {
802 netsrc_t sock;
803
804 if( flag == net_active ) {
805 return;
806 }
807
808 if( flag == NET_NONE ) {
809 // shut down any existing sockets
810 for( sock = 0; sock < NS_COUNT; sock++ ) {
811 if( sockets[sock] != INVALID_SOCKET ) {
812 Sys_CloseSocket( sockets[sock] );
813 sockets[sock] = INVALID_SOCKET;
814 }
815 }
816 net_active = NET_NONE;
817 return;
818 }
819
820 if( flag & NET_CLIENT ) {
821 if( sockets[NS_CLIENT] == INVALID_SOCKET ) {
822 NET_OpenClientIP();
823 }
824 }
825
826 if( flag & NET_SERVER ) {
827 if( sockets[NS_SERVER] == INVALID_SOCKET ) {
828 NET_OpenServerIP();
829 }
830 }
831
832 net_active |= flag;
833 }
834
835 /*
836 ====================
837 NET_Init
838 ====================
839 */
NET_Init(void)840 void NET_Init( void ) {
841 if( !Sys_InitNetworking() ) {
842 return;
843 }
844
845 Cvar_Subsystem( CVAR_SYSTEM_NET );
846
847 net_ip = Cvar_Get( "net_ip", "localhost", 0 );
848 net_port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), 0 );
849 net_clientport = Cvar_Get( "net_clientport", va( "%i", PORT_ANY ), 0 );
850 net_dropsim = Cvar_Get( "net_dropsim", "0", 0 );
851 net_log_active = Cvar_Get( "net_log_active", "0", 0 );
852 net_log_active->changedFunc = NetLogFileActive_OnChange;
853 net_log_name = Cvar_Get( "net_log_name", "qnetwork.log", 0 );
854 net_log_name->changedFunc = NetLogFileParam_OnChange;
855 net_log_flush = Cvar_Get( "net_log_flush", "0", 0 );
856 net_log_flush->changedFunc = NetLogFileParam_OnChange;
857 net_ignore_icmp = Cvar_Get( "net_ignore_icmp", "0", 0 );
858
859 Cvar_Subsystem( CVAR_SYSTEM_GENERIC );
860
861 Cmd_AddCommand( "net_restart", NET_Restart_f );
862 Cmd_AddCommand( "showip", NET_ShowIP_f );
863 Cmd_AddCommand( "dns", NET_Dns_f );
864
865 NET_ShowIP_f();
866 }
867
868 /*
869 ====================
870 NET_Shutdown
871 ====================
872 */
NET_Shutdown(void)873 void NET_Shutdown( void ) {
874 if( net_logFile ) {
875 FS_FCloseFile( net_logFile );
876 net_logFile = 0;
877 }
878
879 NET_Config( NET_NONE );
880
881 Sys_ShutdownNetworking();
882
883 Cmd_RemoveCommand( "net_restart" );
884 Cmd_RemoveCommand( "showip" );
885 Cmd_RemoveCommand( "dns" );
886 }
887
888