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 // net.c
22 
23 #ifdef SERVERONLY
24 #include "qwsvdef.h"
25 #else
26 #include "quakedef.h"
27 #include "server.h"
28 #endif
29 
30 #ifdef _WIN32
31 WSADATA		winsockdata;
32 #endif
33 
34 #ifndef SERVERONLY
35 netadr_t	net_local_cl_ipadr;
36 #endif
37 
38 #ifndef CLIENTONLY
39 netadr_t	net_local_sv_ipadr;
40 netadr_t	net_local_sv_tcpipadr;
41 
42 cvar_t		sv_local_addr = {"sv_local_addr", "", CVAR_ROM};
43 #endif
44 
45 netadr_t	net_from;
46 sizebuf_t	net_message;
47 
48 static byte	net_message_buffer[MSG_BUF_SIZE];
49 
50 // forward definition.
51 qbool NET_GetPacketEx (netsrc_t netsrc, qbool delay);
52 void NET_SendPacketEx (netsrc_t netsrc, int length, void *data, netadr_t to, qbool delay);
53 
54 //=============================================================================
55 //
56 // LOOPBACK defs.
57 //
58 
59 #define MAX_LOOPBACK 4 // must be a power of two
60 
61 typedef struct
62 {
63 	byte	data[MSG_BUF_SIZE];
64 	int		datalen;
65 } loopmsg_t;
66 
67 typedef struct
68 {
69 	loopmsg_t	msgs[MAX_LOOPBACK];
70 	unsigned int	get, send;
71 } loopback_t;
72 
73 loopback_t	loopbacks[2];
74 
75 //=============================================================================
76 //
77 // Delayed packets, CLIENT ONLY.
78 //
79 
80 #ifndef SERVERONLY
81 
82 static cl_delayed_packet_t cl_delayed_packets_input[CL_MAX_DELAYED_PACKETS]; // from server to our client.
83 static cl_delayed_packet_t cl_delayed_packets_output[CL_MAX_DELAYED_PACKETS]; // from our client to server.
84 
85 //
86 // Attempt to read packet from network and if succeed we put that packet in array/queue (so they are delayed).
87 // Packet will be unqued/extracted and used/parsed later, that depends of cl_delay_packet variable.
88 //
CL_QueInputPacket(void)89 void CL_QueInputPacket(void)
90 {
91 	int i;
92 
93 	// read packets.
94 	while (NET_GetPacketEx(NS_CLIENT, false))
95 	{
96 		// queue one packet.
97 		for (i = 0; i < CL_MAX_DELAYED_PACKETS; i++)
98 		{
99 			if (cl_delayed_packets_input[i].time)
100 				continue; // busy slot
101 
102 			// we found unused slot, copy packet, get it later, later depends of cl_delay_packet
103 			memmove(cl_delayed_packets_input[i].data, net_message.data, net_message.cursize);
104 			cl_delayed_packets_input[i].length = net_message.cursize;
105 			cl_delayed_packets_input[i].addr = net_from;
106 			cl_delayed_packets_input[i].time = Sys_DoubleTime() + 0.001 * bound(0, 0.5 * cl_delay_packet.value, CL_MAX_PACKET_DELAY);
107 			break; // queued OK.
108 		}
109 
110 		if (i >= CL_MAX_DELAYED_PACKETS)
111 		{
112 			Con_DPrintf("CL_QueInputPacket: cl_delayed_packets_input overflowed\n");
113 			break;
114 		}
115 	}
116 
117 	return;
118 }
119 
120 //
121 // Check if delayed output packets must be sent right now.
122 //
CL_UnqueOutputPacket(qbool sendall)123 void CL_UnqueOutputPacket(qbool sendall)
124 {
125 	int i;
126 	double time = Sys_DoubleTime();
127 
128 	for (i = 0; i < CL_MAX_DELAYED_PACKETS; i++)
129 	{
130 		if (!cl_delayed_packets_output[i].time)
131 			continue; // unused slot
132 		if (cl_delayed_packets_output[i].time > time && !sendall)
133 			continue; // we are not yet ready for send
134 
135 		// ok, send it
136 		NET_SendPacketEx(NS_CLIENT, cl_delayed_packets_output[i].length,
137 			cl_delayed_packets_output[i].data, cl_delayed_packets_output[i].addr, false);
138 
139 		cl_delayed_packets_output[i].time = 0; // mark as unused slot
140 
141 // perhaps there other packets should be sent
142 //		return;
143 	}
144 }
145 
146 //
147 // Get packet from input queue.
148 //
NET_GetDelayedPacket(netsrc_t netsrc,netadr_t * from,sizebuf_t * message)149 qbool NET_GetDelayedPacket (netsrc_t netsrc, netadr_t *from, sizebuf_t *message)
150 {
151 	int i;
152 	double time = Sys_DoubleTime();
153 
154 	for (i = 0; i < CL_MAX_DELAYED_PACKETS; i++)
155 	{
156 		if (!cl_delayed_packets_input[i].time)
157 			continue; // unused slot
158 		if (cl_delayed_packets_input[i].time > time)
159 			continue; // we are not yet ready to get this
160 
161 		// ok, we got something
162 		SZ_Clear(message);
163 		SZ_Write(message, cl_delayed_packets_input[i].data, cl_delayed_packets_input[i].length);
164 		*from = cl_delayed_packets_input[i].addr;
165 
166 		cl_delayed_packets_input[i].time = 0; // mark as free slot
167 
168 		return true;
169 	}
170 
171 	return false;
172 }
173 
174 //
175 // Put packet in output queue.
176 //
NET_SendDelayedPacket(netsrc_t netsrc,int length,void * data,netadr_t to)177 void NET_SendDelayedPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
178 {
179 	int i;
180 
181 	for (i = 0; i < CL_MAX_DELAYED_PACKETS; i++)
182 	{
183 		if (cl_delayed_packets_output[i].time)
184 			continue; // busy slot
185 		// we found unused slot, copy packet, send it later, later depends of cl_delay_packet
186 		memmove(cl_delayed_packets_output[i].data, data, length);
187 		cl_delayed_packets_output[i].length = length;
188 		cl_delayed_packets_output[i].addr = to;
189 		cl_delayed_packets_output[i].time = Sys_DoubleTime() + 0.001 * bound(0, 0.5 * cl_delay_packet.value, CL_MAX_PACKET_DELAY);
190 
191 		return;
192 	}
193 
194 	Con_DPrintf("NET_SendPacketEx: cl_delayed_packets_output overflowed\n");
195 	return;
196 }
197 
198 #endif
199 
200 //=============================================================================
201 //
202 // Geters.
203 //
204 
NET_UDPSVPort(void)205 int NET_UDPSVPort (void)
206 {
207 	return ntohs(net_local_sv_ipadr.port);
208 }
209 
NET_GetSocket(netsrc_t netsrc,qbool tcp)210 int NET_GetSocket(netsrc_t netsrc, qbool tcp)
211 {
212 	if (netsrc == NS_SERVER)
213 	{
214 #ifdef CLIENTONLY
215 		Sys_Error("NET_GetPacket: Bad netsrc");
216 		return INVALID_SOCKET;
217 #else
218 		return tcp ? svs.sockettcp : svs.socketip;
219 #endif
220 	}
221 	else
222 	{
223 #ifdef SERVERONLY
224 		Sys_Error("NET_GetPacket: Bad netsrc");
225 		return INVALID_SOCKET;
226 #else
227 		return tcp ? cls.sockettcp : cls.socketip;
228 #endif
229 	}
230 }
231 
232 //=============================================================================
233 //
234 // Converters.
235 //
236 
NetadrToSockadr(const netadr_t * a,struct sockaddr_storage * s)237 void NetadrToSockadr (const netadr_t *a, struct sockaddr_storage *s)
238 {
239 	memset (s, 0, sizeof(struct sockaddr_in));
240 	((struct sockaddr_in*)s)->sin_family = AF_INET;
241 
242 	((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&a->ip;
243 	((struct sockaddr_in*)s)->sin_port = a->port;
244 }
245 
SockadrToNetadr(const struct sockaddr_storage * s,netadr_t * a)246 void SockadrToNetadr (const struct sockaddr_storage *s, netadr_t *a)
247 {
248 	a->type = NA_IP;
249 	*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
250 	a->port = ((struct sockaddr_in *)s)->sin_port;
251 	return;
252 }
253 
254 //=============================================================================
255 //
256 // Comparators.
257 //
258 
NET_CompareBaseAdr(const netadr_t a,const netadr_t b)259 qbool NET_CompareBaseAdr (const netadr_t a, const netadr_t b)
260 {
261 #ifndef SERVERONLY
262 	if (a.type == NA_LOOPBACK && b.type == NA_LOOPBACK)
263 		return true;
264 #endif
265 
266 	// FIXME: Should we check a.type == b.type here ???
267 
268 	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
269 		return true;
270 	return false;
271 }
272 
NET_CompareAdr(const netadr_t a,const netadr_t b)273 qbool NET_CompareAdr (const netadr_t a, const netadr_t b)
274 {
275 #ifndef SERVERONLY
276 	if (a.type == NA_LOOPBACK && b.type == NA_LOOPBACK)
277 		return true;
278 #endif
279 
280 	// FIXME: Should we check a.type == b.type here ???
281 
282 	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
283 		return true;
284 	return false;
285 }
286 
287 //=============================================================================
288 //
289 // Printors.
290 //
291 
NET_AdrToString(const netadr_t a)292 char *NET_AdrToString (const netadr_t a)
293 {
294 	static char s[MAX_STRINGS][32]; // 22 should be OK too
295 	static int idx = 0;
296 
297 	idx %= MAX_STRINGS;
298 
299 #ifndef SERVERONLY
300 	if (a.type == NA_LOOPBACK)
301 	{
302 		snprintf (s[idx], sizeof(s[0]), "loopback");
303 	}
304 	else
305 #endif
306 	{
307 		snprintf (s[idx], sizeof(s[0]), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs (a.port));
308 	}
309 
310 	return s[idx++];
311 }
312 
NET_BaseAdrToString(const netadr_t a)313 char *NET_BaseAdrToString (const netadr_t a)
314 {
315 	static char s[MAX_STRINGS][32]; // 22 should be OK too
316 	static int idx = 0;
317 
318 	idx %= MAX_STRINGS;
319 
320 #ifndef SERVERONLY
321 	if (a.type == NA_LOOPBACK)
322 	{
323 		snprintf (s[idx], sizeof(s[0]), "loopback");
324 	}
325 	else
326 #endif
327 	{
328 		snprintf (s[idx], sizeof(s[0]), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
329 	}
330 
331 	return s[idx++];
332 }
333 
334 // !!! Not used outside of the net.c !!!
NET_StringToSockaddr(const char * s,struct sockaddr_storage * sadr)335 static qbool NET_StringToSockaddr (const char *s, struct sockaddr_storage *sadr)
336 {
337 	struct hostent	*h;
338 	char	*colon;
339 	char	copy[128];
340 
341 	if (!(*s))
342 		return false;
343 
344 	memset (sadr, 0, sizeof(*sadr));
345 
346 	((struct sockaddr_in *)sadr)->sin_family = AF_INET;
347 	((struct sockaddr_in *)sadr)->sin_port = 0;
348 
349 	// can't resolve IP by hostname if hostname was truncated
350 	if (strlcpy (copy, s, sizeof(copy)) >= sizeof(copy))
351 		return false;
352 
353 	// strip off a trailing :port if present
354 	for (colon = copy ; *colon ; colon++)
355 	{
356 		if (*colon == ':') {
357 			*colon = 0;
358 			((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
359 		}
360 	}
361 
362 	//this is the wrong way to test. a server name may start with a number.
363 	if (copy[0] >= '0' && copy[0] <= '9')
364 	{
365 		//this is the wrong way to test. a server name may start with a number.
366 		*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
367 	} else
368 	{
369 		if (!(h = gethostbyname(copy)))
370 			return false;
371 
372 		if (h->h_addrtype != AF_INET)
373 			return false;
374 
375 		*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
376 	}
377 
378 	return true;
379 }
380 
NET_StringToAdr(const char * s,netadr_t * a)381 qbool NET_StringToAdr (const char *s, netadr_t *a)
382 {
383 	struct sockaddr_storage sadr;
384 
385 #ifndef SERVERONLY
386 	if (!strcmp(s, "local"))
387 	{
388 		memset(a, 0, sizeof(*a));
389 		a->type = NA_LOOPBACK;
390 		return true;
391 	}
392 #endif
393 
394 	if (!NET_StringToSockaddr (s, &sadr))
395 		return false;
396 
397 	SockadrToNetadr (&sadr, a);
398 
399 	return true;
400 }
401 
402 /*
403 =============================================================================
404 LOOPBACK BUFFERS FOR LOCAL PLAYER
405 =============================================================================
406 */
407 
NET_GetLoopPacket(netsrc_t netsrc,netadr_t * from,sizebuf_t * message)408 qbool NET_GetLoopPacket (netsrc_t netsrc, netadr_t *from, sizebuf_t *message)
409 {
410 	int i;
411 	loopback_t *loop;
412 
413 	loop = &loopbacks[netsrc];
414 
415 	if (loop->send - loop->get > MAX_LOOPBACK)
416 		loop->get = loop->send - MAX_LOOPBACK;
417 
418 	if (loop->get >= loop->send)
419 		return false;
420 
421 	i = loop->get & (MAX_LOOPBACK-1);
422 	loop->get++;
423 
424 	if (message->maxsize < loop->msgs[i].datalen)
425 		Sys_Error("NET_SendLoopPacket: Loopback buffer was too big");
426 
427 	memcpy (message->data, loop->msgs[i].data, loop->msgs[i].datalen);
428 	message->cursize = loop->msgs[i].datalen;
429 	memset (from, 0, sizeof(*from));
430 	from->type = NA_LOOPBACK;
431 	return true;
432 }
433 
NET_SendLoopPacket(netsrc_t netsrc,int length,void * data,netadr_t to)434 void NET_SendLoopPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
435 {
436 	int i;
437 	loopback_t *loop;
438 
439 	loop = &loopbacks[netsrc ^ 1];
440 
441 	i = loop->send & (MAX_LOOPBACK - 1);
442 	loop->send++;
443 
444 	if (length > (int) sizeof(loop->msgs[i].data))
445 		Sys_Error ("NET_SendLoopPacket: length > %d", (int) sizeof(loop->msgs[i].data));
446 
447 	memcpy (loop->msgs[i].data, data, length);
448 	loop->msgs[i].datalen = length;
449 }
450 
NET_ClearLoopback(void)451 void NET_ClearLoopback (void)
452 {
453 	loopbacks[0].send = loopbacks[0].get = 0;
454 	loopbacks[1].send = loopbacks[1].get = 0;
455 }
456 
457 //=============================================================================
458 //
459 // SV TCP connection.
460 //
461 
462 // allocate, may link it in, if requested
sv_tcp_connection_new(int sock,netadr_t from,char * buf,int buf_len,qbool link)463 svtcpstream_t *sv_tcp_connection_new(int sock, netadr_t from, char *buf, int buf_len, qbool link)
464 {
465 	svtcpstream_t *st = NULL;
466 
467 	st = Q_malloc(sizeof(svtcpstream_t));
468 	st->waitingforprotocolconfirmation = true;
469 	st->socketnum = sock;
470 	st->remoteaddr = from;
471 	if (buf_len > 0 && buf_len < sizeof(st->inbuffer))
472 	{
473 		memmove(st->inbuffer, buf, buf_len);
474 		st->inlen = buf_len;
475 	}
476 	else
477 		st->drop = true; // yeah, funny
478 
479 	// link it in if requested
480 	if (link)
481 	{
482 		st->next = svs.tcpstreams;
483 		svs.tcpstreams = st;
484 	}
485 
486 	return st;
487 }
488 
489 // free data, may unlink it out if requested
sv_tcp_connection_free(svtcpstream_t * drop,qbool unlink)490 static void sv_tcp_connection_free(svtcpstream_t *drop, qbool unlink)
491 {
492 	if (!drop)
493 		return; // someone kidding us
494 
495 	// unlink if requested
496 	if (unlink)
497 	{
498 		if (svs.tcpstreams == drop)
499 		{
500 			svs.tcpstreams = svs.tcpstreams->next;
501 		}
502 		else
503 		{
504 			svtcpstream_t *st = NULL;
505 
506 			for (st = svs.tcpstreams; st; st = st->next)
507 			{
508 				if (st->next == drop)
509 				{
510 					st->next = st->next->next;
511 					break;
512 				}
513 			}
514 		}
515 	}
516 
517 	// well, think socket may be zero, but most of the time zero is stdin fd, so better not close it
518 	if (drop->socketnum && drop->socketnum != INVALID_SOCKET)
519 		closesocket(drop->socketnum);
520 
521 	Q_free(drop);
522 }
523 
sv_tcp_connection_count(void)524 int sv_tcp_connection_count(void)
525 {
526 	svtcpstream_t *st = NULL;
527 	int cnt = 0;
528 
529 	for (st = svs.tcpstreams; st; st = st->next)
530 		cnt++;
531 
532 	return cnt;
533 }
534 
535 //=============================================================================
536 
NET_GetUDPPacket(netsrc_t netsrc,netadr_t * from_adr,sizebuf_t * message)537 qbool NET_GetUDPPacket (netsrc_t netsrc, netadr_t *from_adr, sizebuf_t *message)
538 {
539 	int ret, err;
540 	struct sockaddr_storage from = {0};
541 	socklen_t fromlen;
542 	int socket = NET_GetSocket(netsrc, false);
543 
544 	if (socket == INVALID_SOCKET)
545 		return false;
546 
547 	fromlen = sizeof(from);
548 	ret = recvfrom (socket, (char *)message->data, message->maxsize, 0, (struct sockaddr *)&from, &fromlen);
549 	SockadrToNetadr (&from, from_adr);
550 
551 	if (ret == -1)
552 	{
553 		err = qerrno;
554 
555 		if (err == EWOULDBLOCK)
556 			return false; // common error, does not spam in logs.
557 
558 		if (err == EMSGSIZE)
559 		{
560 			Con_DPrintf ("Warning: Oversize packet from %s\n", NET_AdrToString (*from_adr));
561 			return false;
562 		}
563 
564 		if (err == ECONNABORTED || err == ECONNRESET)
565 		{
566 			Con_DPrintf ("Connection lost or aborted\n");
567 			return false;
568 		}
569 
570 		Con_Printf ("NET_GetPacket: recvfrom: (%i): %s\n", err, strerror(err));
571 		return false;
572 	}
573 
574 	if (ret >= message->maxsize)
575 	{
576 		Con_Printf ("Oversize packet from %s\n", NET_AdrToString (*from_adr));
577 		return false;
578 	}
579 
580 	message->cursize = ret;
581 
582 	return ret;
583 }
584 
585 #ifndef SERVERONLY
NET_GetTCPPacket_CL(netsrc_t netsrc,netadr_t * from,sizebuf_t * message)586 qbool NET_GetTCPPacket_CL (netsrc_t netsrc, netadr_t *from, sizebuf_t *message)
587 {
588 	int ret, err;
589 
590 	if (netsrc != NS_CLIENT || cls.sockettcp == INVALID_SOCKET)
591 		return false;
592 
593 	ret = recv(cls.sockettcp, (char *) cls.tcpinbuffer + cls.tcpinlen, sizeof(cls.tcpinbuffer) - cls.tcpinlen, 0);
594 
595 	// FIXME: should we check for ret == 0  for disconnect ???
596 
597 	if (ret == -1)
598 	{
599 		err = qerrno;
600 
601 		if (err == EWOULDBLOCK)
602 		{
603 			ret = 0; // hint for code below that it was not cricial error.
604 		}
605 		else if (err == ECONNABORTED || err == ECONNRESET)
606 		{
607 			Con_Printf ("Connection lost or aborted\n"); //server died/connection lost.
608 		}
609 		else
610 		{
611 			Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err));
612 		}
613 
614 		if (ret)
615 		{
616 			// error detected, close socket then.
617 			closesocket(cls.sockettcp);
618 			cls.sockettcp = INVALID_SOCKET;
619 			return false;
620 		}
621 	}
622 
623 	cls.tcpinlen += ret;
624 
625 	if (cls.tcpinlen < 2)
626 		return false;
627 
628 	message->cursize = BigShort(*(short*)cls.tcpinbuffer);
629 	if (message->cursize >= message->maxsize)
630 	{
631 		closesocket(cls.sockettcp);
632 		cls.sockettcp = INVALID_SOCKET;
633 		Con_Printf ("Warning: Oversize packet from %s\n", NET_AdrToString (cls.sockettcpdest));
634 		return false;
635 	}
636 
637 	if (message->cursize + 2 > cls.tcpinlen)
638 	{
639 		//not enough buffered to read a packet out of it.
640 		return false;
641 	}
642 
643 	memcpy(message->data, cls.tcpinbuffer + 2, message->cursize);
644 	memmove(cls.tcpinbuffer, cls.tcpinbuffer + message->cursize + 2, cls.tcpinlen - (message->cursize + 2));
645 	cls.tcpinlen -= message->cursize + 2;
646 
647 	*from = cls.sockettcpdest;
648 
649 	return true;
650 }
651 #endif
652 
653 #ifndef CLIENTONLY
NET_GetTCPPacket_SV(netsrc_t netsrc,netadr_t * from,sizebuf_t * message)654 qbool NET_GetTCPPacket_SV (netsrc_t netsrc, netadr_t *from, sizebuf_t *message)
655 {
656 	int ret;
657 	float timeval = Sys_DoubleTime();
658 	svtcpstream_t *st = NULL, *next = NULL;
659 
660 	if (netsrc != NS_SERVER)
661 		return false;
662 
663 	for (st = svs.tcpstreams; st; st = next)
664 	{
665 		next = st->next;
666 
667 		*from = st->remoteaddr;
668 
669 		if (st->socketnum == INVALID_SOCKET || st->drop)
670 		{
671 			sv_tcp_connection_free(st, true); // free and unlink
672 			continue;
673 		}
674 
675 		//due to the above checks about invalid sockets, the socket is always open for st below.
676 
677 		// check for client timeout
678 		if (st->timeouttime < timeval)
679 		{
680 			st->drop = true;
681 			continue;
682 		}
683 
684 		ret = recv(st->socketnum, st->inbuffer+st->inlen, sizeof(st->inbuffer)-st->inlen, 0);
685 		if (ret == 0)
686 		{
687 			// connection closed
688 			st->drop = true;
689 			continue;
690 		}
691 		else if (ret == -1)
692 		{
693 			int err = qerrno;
694 
695 			if (err == EWOULDBLOCK)
696 			{
697 				ret = 0; // it's OK
698 			}
699 			else
700 			{
701 				if (err == ECONNABORTED || err == ECONNRESET)
702 				{
703 					Con_DPrintf ("Connection lost or aborted\n"); //server died/connection lost.
704 				}
705 				else
706 				{
707 					Con_DPrintf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err));
708 				}
709 
710 				st->drop = true;
711 				continue;
712 			}
713 		}
714 		else
715 		{
716 			// update timeout
717 			st->timeouttime = Sys_DoubleTime() + 10;
718 		}
719 
720 		st->inlen += ret;
721 
722 		if (st->waitingforprotocolconfirmation)
723 		{
724 			// not enough data
725 			if (st->inlen < 6)
726 				continue;
727 
728 			if (strncmp(st->inbuffer, "qizmo\n", 6))
729 			{
730 				Con_Printf ("Unknown TCP client\n");
731 				st->drop = true;
732 				continue;
733 			}
734 
735 			// remove leading 6 bytes
736 			memmove(st->inbuffer, st->inbuffer+6, st->inlen - (6));
737 			st->inlen -= 6;
738 			// confirmed
739 			st->waitingforprotocolconfirmation = false;
740 		}
741 
742 		// need two bytes for packet len
743 		if (st->inlen < 2)
744 			continue;
745 
746 		message->cursize = BigShort(*(short*)st->inbuffer);
747 		if (message->cursize < 0)
748 		{
749 			message->cursize = 0;
750 			Con_Printf ("Warning: malformed message from %s\n", NET_AdrToString (*from));
751 			st->drop = true;
752 			continue;
753 		}
754 
755 		if (message->cursize >= message->maxsize)
756 		{
757 			Con_Printf ("Warning: Oversize packet from %s\n", NET_AdrToString (*from));
758 			st->drop = true;
759 			continue;
760 		}
761 
762 		if (message->cursize + 2 > st->inlen)
763 		{
764 			//not enough buffered to read a packet out of it.
765 			continue;
766 		}
767 
768 		memcpy(message->data, st->inbuffer + 2, message->cursize);
769 		memmove(st->inbuffer, st->inbuffer + message->cursize + 2, st->inlen - (message->cursize + 2));
770 		st->inlen -= message->cursize + 2;
771 
772 		return true; // we got packet!
773 	}
774 
775 	return false; // no packet received.
776 }
777 #endif
778 
NET_GetPacketEx(netsrc_t netsrc,qbool delay)779 qbool NET_GetPacketEx (netsrc_t netsrc, qbool delay)
780 {
781 #ifndef SERVERONLY
782 	if (delay)
783 		return NET_GetDelayedPacket(netsrc, &net_from, &net_message);
784 #endif
785 
786 #ifndef SERVERONLY
787 	if (NET_GetLoopPacket(netsrc, &net_from, &net_message))
788 		return true;
789 #endif
790 
791 	if (NET_GetUDPPacket(netsrc, &net_from, &net_message))
792 		return true;
793 
794 // TCPCONNECT -->
795 #ifndef SERVERONLY
796 	if (netsrc == NS_CLIENT && cls.sockettcp != INVALID_SOCKET && NET_GetTCPPacket_CL(netsrc, &net_from, &net_message))
797 		return true;
798 #endif
799 
800 #ifndef CLIENTONLY
801 	if (netsrc == NS_SERVER && svs.tcpstreams && NET_GetTCPPacket_SV(netsrc, &net_from, &net_message))
802 		return true;
803 #endif
804 // <--TCPCONNECT
805 
806 	return false;
807 }
808 
NET_GetPacket(netsrc_t netsrc)809 qbool NET_GetPacket (netsrc_t netsrc)
810 {
811 #ifdef SERVERONLY
812 	qbool delay = false;
813 #else
814 	qbool delay = (netsrc == NS_CLIENT && cl_delay_packet.integer);
815 #endif
816 
817 	return NET_GetPacketEx (netsrc, delay);
818 }
819 
820 //=============================================================================
821 
822 #ifndef SERVERONLY
NET_SendTCPPacket_CL(netsrc_t netsrc,int length,void * data,netadr_t to)823 qbool NET_SendTCPPacket_CL (netsrc_t netsrc, int length, void *data, netadr_t to)
824 {
825 	unsigned short slen;
826 
827 	if (netsrc != NS_CLIENT || cls.sockettcp == INVALID_SOCKET)
828 		return false;
829 
830 	if (!NET_CompareAdr(to, cls.sockettcpdest))
831 		return false;
832 
833 	// this goes to the server so send it via TCP.
834 	slen = BigShort((unsigned short)length);
835 	// FIXME: CHECK send() result, we use NON BLOCKIN MODE, FFS!
836 	send(cls.sockettcp, (char*)&slen, sizeof(slen), 0);
837 	send(cls.sockettcp, data, length, 0);
838 
839 	return true;
840 }
841 #endif
842 
843 #ifndef CLIENTONLY
NET_SendTCPPacket_SV(netsrc_t netsrc,int length,void * data,netadr_t to)844 qbool NET_SendTCPPacket_SV (netsrc_t netsrc, int length, void *data, netadr_t to)
845 {
846 	svtcpstream_t *st;
847 
848 	if (netsrc != NS_SERVER)
849 		return false;
850 
851 	for (st = svs.tcpstreams; st; st = st->next)
852 	{
853 		if (st->socketnum == INVALID_SOCKET)
854 			continue;
855 
856 		if (NET_CompareAdr(to, st->remoteaddr))
857 		{
858 			int sent;
859 			unsigned short slen = BigShort((unsigned short)length);
860 
861 			if (st->outlen + length + sizeof(slen) >= sizeof(st->outbuffer))
862 			{
863 				// not enough space, we overflowed
864 				break; // well, quake should resist to some packet lost.. so we just drop that packet.
865 			}
866 
867 			// put data in buffer
868 			memmove(st->outbuffer + st->outlen, (char*)&slen, sizeof(slen));
869 			st->outlen += sizeof(slen);
870 			memmove(st->outbuffer + st->outlen, data, length);
871 			st->outlen += length;
872 
873 			sent = send(st->socketnum, st->outbuffer, st->outlen, 0);
874 
875 			if (sent == 0)
876 			{
877 				// think it's OK
878 			}
879 			else if (sent > 0) //we put some data through
880 			{ //move up the buffer
881 				st->outlen -= sent;
882 				memmove(st->outbuffer, st->outbuffer + sent, st->outlen);
883 			}
884 			else
885 			{ //error of some kind. would block or something
886 				if (qerrno != EWOULDBLOCK && qerrno != EAGAIN)
887 				{
888 					st->drop = true; // something cricial, drop than
889 				}
890 			}
891 
892 			break;
893 		}
894 	}
895 
896 	// 'st' will be not zero, if we found 'to' in 'svs.tcpstreams'.
897 	// That does not mean we actualy send packet, since there case of overflow, but who cares,
898 	// all is matter that we found such 'to' and tried to send packet.
899 	return !!st;
900 }
901 #endif
902 
NET_SendUDPPacket(netsrc_t netsrc,int length,void * data,netadr_t to)903 qbool NET_SendUDPPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
904 {
905 	struct sockaddr_storage addr;
906 	int ret;
907 	int socket = NET_GetSocket(netsrc, false);
908 
909 	if (socket == INVALID_SOCKET)
910 		return false;
911 
912 	NetadrToSockadr (&to, &addr);
913 
914 	ret = sendto (socket, data, length, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
915 	if (ret == -1)
916 	{
917 		int err = qerrno;
918 
919 		if (err == EWOULDBLOCK || err == ECONNREFUSED || err == EADDRNOTAVAIL)
920 			; // nothing
921 		else
922 			Con_Printf ("NET_SendPacket: sendto: (%i): %s %i\n", err, strerror(err), socket);
923 	}
924 
925 	return true;
926 }
927 
NET_SendPacketEx(netsrc_t netsrc,int length,void * data,netadr_t to,qbool delay)928 void NET_SendPacketEx (netsrc_t netsrc, int length, void *data, netadr_t to, qbool delay)
929 {
930 #ifndef SERVERONLY
931 	if (delay)
932 	{
933 		NET_SendDelayedPacket (netsrc, length, data, to);
934 		return;
935 	}
936 #endif
937 
938 #ifndef SERVERONLY
939 	if (to.type == NA_LOOPBACK)
940 	{
941 		NET_SendLoopPacket (netsrc, length, data, to);
942 		return;
943 	}
944 #endif
945 
946 // TCPCONNECT -->
947 #ifndef SERVERONLY
948 	if (netsrc == NS_CLIENT && cls.sockettcp != INVALID_SOCKET && NET_SendTCPPacket_CL(netsrc, length, data, to))
949 		return;
950 #endif
951 
952 #ifndef CLIENTONLY
953 	if (netsrc == NS_SERVER && svs.tcpstreams && NET_SendTCPPacket_SV(netsrc, length, data, to))
954 		return;
955 #endif
956 // <--TCPCONNECT
957 
958 	NET_SendUDPPacket(netsrc, length, data, to);
959 }
960 
NET_SendPacket(netsrc_t netsrc,int length,void * data,netadr_t to)961 void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
962 {
963 #ifdef SERVERONLY
964 	qbool delay = false;
965 #else
966 	qbool delay = (netsrc == NS_CLIENT && cl_delay_packet.integer);
967 #endif
968 
969 	NET_SendPacketEx (netsrc, length, data, to, delay);
970 }
971 
972 //=============================================================================
973 
TCP_Set_KEEPALIVE(int sock)974 qbool TCP_Set_KEEPALIVE(int sock)
975 {
976 	int		iOptVal = 1;
977 
978 	if (sock == INVALID_SOCKET)
979 	{
980 		Con_Printf("TCP_Set_KEEPALIVE: invalid socket\n");
981 		return false;
982 	}
983 
984 	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&iOptVal, sizeof(iOptVal)) == SOCKET_ERROR)
985 	{
986 		Con_Printf ("TCP_Set_KEEPALIVE: setsockopt: (%i): %s\n", qerrno, strerror (qerrno));
987 		return false;
988 	}
989 
990 #if defined(__linux__)
991 
992 //	The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes,
993 //  if the socket option SO_KEEPALIVE has been set on this socket.
994 
995 	iOptVal = 60;
996 
997 	if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (void*)&iOptVal, sizeof(iOptVal)) == -1)
998 	{
999 		Con_Printf ("TCP_Set_KEEPALIVE: setsockopt TCP_KEEPIDLE: (%i): %s\n", qerrno, strerror(qerrno));
1000 		return false;
1001 	}
1002 
1003 //  The time (in seconds) between individual keepalive probes.
1004 	iOptVal = 30;
1005 
1006 	if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (void*)&iOptVal, sizeof(iOptVal)) == -1)
1007 	{
1008 		Con_Printf ("TCP_Set_KEEPALIVE: setsockopt TCP_KEEPINTVL: (%i): %s\n", qerrno, strerror(qerrno));
1009 		return false;
1010 	}
1011 
1012 //  The maximum number of keepalive probes TCP should send before dropping the connection.
1013 	iOptVal = 6;
1014 
1015 	if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, (void*)&iOptVal, sizeof(iOptVal)) == -1)
1016 	{
1017 		Con_Printf ("TCP_Set_KEEPALIVE: setsockopt TCP_KEEPCNT: (%i): %s\n", qerrno, strerror(qerrno));
1018 		return false;
1019 	}
1020 #else
1021 	// FIXME: windows, bsd etc...
1022 #endif
1023 
1024 	return true;
1025 }
1026 
TCP_OpenStream(netadr_t remoteaddr)1027 int TCP_OpenStream (netadr_t remoteaddr)
1028 {
1029 	unsigned long _true = true;
1030 	int newsocket;
1031 	int temp;
1032 	struct sockaddr_storage qs;
1033 
1034 	NetadrToSockadr(&remoteaddr, &qs);
1035 	temp = sizeof(struct sockaddr_in);
1036 
1037 	if ((newsocket = socket (((struct sockaddr_in*)&qs)->sin_family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
1038 	{
1039 		Con_Printf ("TCP_OpenStream: socket: (%i): %s\n", qerrno, strerror(qerrno));
1040 		return INVALID_SOCKET;
1041 	}
1042 
1043 	if (connect (newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET)
1044 	{
1045 		Con_Printf ("TCP_OpenStream: connect: (%i): %s\n", qerrno, strerror(qerrno));
1046 		closesocket(newsocket);
1047 		return INVALID_SOCKET;
1048 	}
1049 
1050 #ifndef _WIN32
1051 	if ((fcntl (newsocket, F_SETFL, O_NONBLOCK)) == -1)
1052 	{ // O'Rly?! @@@
1053 		Con_Printf ("TCP_OpenStream: fcntl: (%i): %s\n", qerrno, strerror(qerrno));
1054 		closesocket(newsocket);
1055 		return INVALID_SOCKET;
1056 	}
1057 #endif
1058 
1059 	if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
1060 	{ // make asynchronous
1061 		Con_Printf ("TCP_OpenStream: ioctl: (%i): %s\n", qerrno, strerror(qerrno));
1062 		closesocket(newsocket);
1063 		return INVALID_SOCKET;
1064 	}
1065 
1066 	return newsocket;
1067 }
1068 
TCP_OpenListenSocket(unsigned short int port)1069 int TCP_OpenListenSocket (unsigned short int port)
1070 {
1071 	int newsocket;
1072 	struct sockaddr_in address = {0};
1073 	unsigned long nonblocking = true;
1074 	int i;
1075 
1076 	if ((newsocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
1077 	{
1078 		Con_Printf ("TCP_OpenListenSocket: socket: (%i): %s\n", qerrno, strerror(qerrno));
1079 		return INVALID_SOCKET;
1080 	}
1081 
1082 	if (ioctlsocket (newsocket, FIONBIO, &nonblocking) == -1)
1083 	{ // make asynchronous
1084 		Con_Printf ("TCP_OpenListenSocket: ioctl: (%i): %s\n", qerrno, strerror(qerrno));
1085 		closesocket(newsocket);
1086 		return INVALID_SOCKET;
1087 	}
1088 
1089 #ifdef __APPLE__
1090 	address.sin_len = sizeof(address); // apple are special...
1091 #endif
1092 	address.sin_family = AF_INET;
1093 
1094 	// check for interface binding option
1095 	if ((i = COM_CheckParm("-ip")) != 0 && i < COM_Argc())
1096 	{
1097 		address.sin_addr.s_addr = inet_addr(COM_Argv(i+1));
1098 		Con_DPrintf ("Binding to IP Interface Address of %s\n", inet_ntoa(address.sin_addr));
1099 	}
1100 	else
1101 	{
1102 		address.sin_addr.s_addr = INADDR_ANY;
1103 	}
1104 
1105 	if (port == PORT_ANY)
1106 		address.sin_port = 0;
1107 	else
1108 		address.sin_port = htons(port);
1109 
1110 	if (bind (newsocket, (void *)&address, sizeof(address)) == -1)
1111 	{
1112 		Con_Printf ("TCP_OpenListenSocket: bind: (%i): %s\n", qerrno, strerror(qerrno));
1113 		closesocket(newsocket);
1114 		return INVALID_SOCKET;
1115 	}
1116 
1117 	if (listen (newsocket, 2) == INVALID_SOCKET)
1118 	{
1119 		Con_Printf ("TCP_OpenListenSocket: listen: (%i): %s\n", qerrno, strerror(qerrno));
1120 		closesocket(newsocket);
1121 		return INVALID_SOCKET;
1122 	}
1123 
1124 	if (!TCP_Set_KEEPALIVE(newsocket))
1125 	{
1126 		Con_Printf ("TCP_OpenListenSocket: TCP_Set_KEEPALIVE: failed\n");
1127 		closesocket(newsocket);
1128 		return INVALID_SOCKET;
1129 	}
1130 
1131 	return newsocket;
1132 }
1133 
UDP_OpenSocket(unsigned short int port)1134 int UDP_OpenSocket (unsigned short int port)
1135 {
1136 	int newsocket;
1137 	struct sockaddr_in address;
1138 	unsigned long _true = true;
1139 	int i;
1140 
1141 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
1142 	{
1143 		Con_Printf ("UDP_OpenSocket: socket: (%i): %s\n", qerrno, strerror(qerrno));
1144 		return INVALID_SOCKET;
1145 	}
1146 
1147 #ifndef _WIN32
1148 	if ((fcntl (newsocket, F_SETFL, O_NONBLOCK)) == -1)
1149 	{ // O'Rly?! @@@
1150 		Con_Printf ("UDP_OpenSocket: fcntl: (%i): %s\n", qerrno, strerror(qerrno));
1151 		closesocket(newsocket);
1152 		return INVALID_SOCKET;
1153 	}
1154 #endif
1155 
1156 	if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
1157 	{ // make asynchronous
1158 		Con_Printf ("UDP_OpenSocket: ioctl: (%i): %s\n", qerrno, strerror(qerrno));
1159 		closesocket(newsocket);
1160 		return INVALID_SOCKET;
1161 	}
1162 
1163 	address.sin_family = AF_INET;
1164 
1165 	// check for interface binding option
1166 	if ((i = COM_CheckParm("-ip")) != 0 && i < COM_Argc())
1167 	{
1168 		address.sin_addr.s_addr = inet_addr(COM_Argv(i+1));
1169 		Con_DPrintf ("Binding to IP Interface Address of %s\n", inet_ntoa(address.sin_addr));
1170 	}
1171 	else
1172 	{
1173 		address.sin_addr.s_addr = INADDR_ANY;
1174 	}
1175 
1176 	if (port == PORT_ANY)
1177 		address.sin_port = 0;
1178 	else
1179 		address.sin_port = htons(port);
1180 
1181 	if (bind (newsocket, (void *)&address, sizeof(address)) == -1)
1182 	{
1183 		Con_Printf ("UDP_OpenSocket: bind: (%i): %s\n", qerrno, strerror(qerrno));
1184 		closesocket(newsocket);
1185 		return INVALID_SOCKET;
1186 	}
1187 
1188 	return newsocket;
1189 }
1190 
NET_Sleep(int msec,qbool stdinissocket)1191 qbool NET_Sleep(int msec, qbool stdinissocket)
1192 {
1193 	struct timeval	timeout;
1194 	fd_set			fdset;
1195 	qbool			stdin_ready = false;
1196 	int				maxfd = 0;
1197 
1198 	FD_ZERO (&fdset);
1199 
1200 	if (stdinissocket)
1201 	{
1202 		FD_SET (0, &fdset); // stdin is processed too (tends to be socket 0)
1203 		maxfd = max(0, maxfd);
1204 	}
1205 
1206 	if (svs.socketip != INVALID_SOCKET)
1207 	{
1208 		FD_SET(svs.socketip, &fdset); // network socket
1209 		maxfd = max(svs.socketip, maxfd);
1210 	}
1211 
1212 	timeout.tv_sec = msec/1000;
1213 	timeout.tv_usec = (msec%1000)*1000;
1214 	switch (select(maxfd + 1, &fdset, NULL, NULL, &timeout))
1215 	{
1216 		case -1: break;
1217 		case  0: break;
1218 		default:
1219 
1220 		if (stdinissocket)
1221 			stdin_ready = FD_ISSET (0, &fdset);
1222 
1223 		break;
1224 	}
1225 
1226 	return stdin_ready;
1227 }
1228 
NET_GetLocalAddress(int socket,netadr_t * out)1229 void NET_GetLocalAddress (int socket, netadr_t *out)
1230 {
1231 	char buff[512];
1232 	struct sockaddr_storage address;
1233 	size_t namelen;
1234 	netadr_t adr = {0};
1235 	qbool notvalid = false;
1236 
1237 	strlcpy (buff, "localhost", sizeof (buff));
1238 	gethostname (buff, sizeof (buff));
1239 	buff[sizeof(buff) - 1] = 0;
1240 
1241 	if (!NET_StringToAdr (buff, &adr))	//urm
1242 		NET_StringToAdr ("127.0.0.1", &adr);
1243 
1244 	namelen = sizeof(address);
1245 	if (getsockname (socket, (struct sockaddr *)&address, (socklen_t *)&namelen) == -1)
1246 	{
1247 		notvalid = true;
1248 		NET_StringToSockaddr("0.0.0.0", (struct sockaddr_storage *)&address);
1249 //		Sys_Error ("NET_Init: getsockname:", strerror(qerrno));
1250 	}
1251 
1252 	SockadrToNetadr(&address, out);
1253 	if (!*(int*)out->ip)	//socket was set to auto
1254 		*(int *)out->ip = *(int *)adr.ip;	//change it to what the machine says it is, rather than the socket.
1255 
1256 #ifndef SERVERONLY
1257 	if (notvalid)
1258 		Com_Printf_State (PRINT_FAIL, "Couldn't detect local ip\n");
1259 	else
1260 		Com_Printf_State (PRINT_OK, "IP address %s\n", NET_AdrToString (*out));
1261 #endif
1262 }
1263 
NET_Init(void)1264 void NET_Init (void)
1265 {
1266 #ifdef _WIN32
1267 	WORD wVersionRequested;
1268 	int r;
1269 
1270 	wVersionRequested = MAKEWORD(1, 1);
1271 	r = WSAStartup (wVersionRequested, &winsockdata);
1272 	if (r)
1273 		Sys_Error ("Winsock initialization failed.");
1274 #endif
1275 
1276 	// init the message buffer
1277 	SZ_Init (&net_message, net_message_buffer, sizeof(net_message_buffer));
1278 
1279 	Con_DPrintf("UDP Initialized\n");
1280 
1281 #ifndef SERVERONLY
1282 	cls.socketip = INVALID_SOCKET;
1283 // TCPCONNECT -->
1284 	cls.sockettcp = INVALID_SOCKET;
1285 // <--TCPCONNECT
1286 #endif
1287 
1288 #ifndef CLIENTONLY
1289 
1290 	Cvar_Register (&sv_local_addr);
1291 
1292 	svs.socketip = INVALID_SOCKET;
1293 // TCPCONNECT -->
1294 	svs.sockettcp = INVALID_SOCKET;
1295 // <--TCPCONNECT
1296 #endif
1297 
1298 #ifdef SERVERONLY
1299 	// As client+server we init it in SV_SpawnServer().
1300 	// As serveronly we do it here.
1301 	NET_InitServer();
1302 #endif
1303 }
1304 
NET_Shutdown(void)1305 void NET_Shutdown (void)
1306 {
1307 #ifndef CLIENTONLY
1308 	NET_CloseServer();
1309 #endif
1310 
1311 #ifndef SERVERONLY
1312 	NET_CloseClient();
1313 #endif
1314 
1315 #ifdef _WIN32
1316 	WSACleanup ();
1317 #endif
1318 }
1319 
1320 #ifndef SERVERONLY
NET_InitClient(void)1321 void NET_InitClient(void)
1322 {
1323 	int port = PORT_CLIENT;
1324 	int p;
1325 
1326 	p = COM_CheckParm ("-clientport");
1327 	if (p && p < COM_Argc())
1328 	{
1329 		port = atoi(COM_Argv(p+1));
1330 	}
1331 
1332 	if (cls.socketip == INVALID_SOCKET)
1333 		cls.socketip = UDP_OpenSocket (port);
1334 
1335 	if (cls.socketip == INVALID_SOCKET)
1336 		cls.socketip = UDP_OpenSocket (PORT_ANY); // any dynamic port
1337 
1338 	if (cls.socketip == INVALID_SOCKET)
1339 		Sys_Error ("Couldn't allocate client socket");
1340 
1341 	// determine my name & address
1342 	NET_GetLocalAddress (cls.socketip, &net_local_cl_ipadr);
1343 
1344 	Com_Printf_State (PRINT_OK, "Client port Initialized\n");
1345 }
1346 
NET_CloseClient(void)1347 void NET_CloseClient (void)
1348 {
1349 	if (cls.socketip != INVALID_SOCKET)
1350 	{
1351 		closesocket(cls.socketip);
1352 		cls.socketip = INVALID_SOCKET;
1353 	}
1354 
1355 // TCPCONNECT -->
1356 	// FIXME: is it OK? Probably we should send disconnect?
1357 	if (cls.sockettcp != INVALID_SOCKET)
1358 	{
1359 		closesocket(cls.sockettcp);
1360 		cls.sockettcp = INVALID_SOCKET;
1361 	}
1362 // <--TCPCONNECT
1363 }
1364 
1365 #endif
1366 
1367 #ifndef CLIENTONLY
1368 
1369 //
1370 // Open server TCP port.
1371 // NOTE: Zero port will actually close already opened port.
1372 //
NET_InitServer_TCP(unsigned short int port)1373 void NET_InitServer_TCP(unsigned short int port)
1374 {
1375 	// close socket first.
1376 	if (svs.sockettcp != INVALID_SOCKET)
1377 	{
1378 		Con_Printf("Server TCP port closed\n");
1379 		closesocket(svs.sockettcp);
1380 		svs.sockettcp = INVALID_SOCKET;
1381 		net_local_sv_tcpipadr.type = NA_INVALID;
1382 	}
1383 
1384 	if (port)
1385 	{
1386 		svs.sockettcp = TCP_OpenListenSocket (port);
1387 
1388 		if (svs.sockettcp != INVALID_SOCKET)
1389 		{
1390 			// get local address.
1391 			NET_GetLocalAddress (svs.sockettcp, &net_local_sv_tcpipadr);
1392 			Con_Printf("Opening server TCP port %u\n", (unsigned int)port);
1393 		}
1394 		else
1395 		{
1396 			Con_Printf("Failed to open server TCP port %u\n", (unsigned int)port);
1397 		}
1398 	}
1399 }
1400 
NET_InitServer(void)1401 void NET_InitServer (void)
1402 {
1403 	int port = PORT_SERVER;
1404 	int p;
1405 
1406 	p = COM_CheckParm ("-port");
1407 	if (p && p < COM_Argc())
1408 	{
1409 		port = atoi(COM_Argv(p+1));
1410 	}
1411 
1412 	if (svs.socketip == INVALID_SOCKET)
1413 	{
1414 		svs.socketip = UDP_OpenSocket (port);
1415 	}
1416 
1417 	if (svs.socketip != INVALID_SOCKET)
1418 	{
1419 		NET_GetLocalAddress (svs.socketip, &net_local_sv_ipadr);
1420 		Cvar_SetROM (&sv_local_addr, NET_AdrToString (net_local_sv_ipadr));
1421 	}
1422 	else
1423 	{
1424 		// FIXME: is it right???
1425 		Cvar_SetROM (&sv_local_addr, "");
1426 	}
1427 
1428 // TCPCONNECT -->
1429 #if 0 // qqshka: TCP port shared with QTV now, so it opened outside here.
1430 	p = COM_CheckParm ("-tcpport");
1431 	if (p && p < COM_Argc())
1432 	{
1433 		NET_InitServer_TCP(atoi(COM_Argv(p+1)));
1434 	}
1435 #endif
1436 // <-- TCPCONNECT
1437 
1438 	if (svs.socketip == INVALID_SOCKET)
1439 	{
1440 #ifdef SERVERONLY
1441 		Sys_Error
1442 #else
1443 		Con_Printf
1444 #endif
1445  		("WARNING: Couldn't allocate server socket\n");
1446 	}
1447 }
1448 
NET_CloseServer(void)1449 void NET_CloseServer (void)
1450 {
1451 	if (svs.socketip != INVALID_SOCKET)
1452 	{
1453 		closesocket(svs.socketip);
1454 		svs.socketip = INVALID_SOCKET;
1455 	}
1456 
1457 	net_local_sv_ipadr.type = NA_LOOPBACK; // FIXME: why not NA_INVALID?
1458 
1459 // TCPCONNECT -->
1460 	NET_InitServer_TCP(0);
1461 // <--TCPCONNECT
1462 }
1463 #endif
1464 
1465