Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

net_udp.c (9960B)


      1 // net_wins.c
      2 
      3 #include "../qcommon/qcommon.h"
      4 
      5 #include <unistd.h>
      6 #include <sys/socket.h>
      7 #include <netinet/in.h>
      8 #include <netdb.h>
      9 #include <sys/param.h>
     10 #include <sys/ioctl.h>
     11 #include <sys/uio.h>
     12 #include <errno.h>
     13 #include <sys/filio.h>
     14 
     15 #ifdef NeXT
     16 #include <libc.h>
     17 #endif
     18 
     19 netadr_t	net_local_adr;
     20 
     21 #define	LOOPBACK	0x7f000001
     22 
     23 #define	MAX_LOOPBACK	4
     24 
     25 typedef struct
     26 {
     27 	byte	data[MAX_MSGLEN];
     28 	int		datalen;
     29 } loopmsg_t;
     30 
     31 typedef struct
     32 {
     33 	loopmsg_t	msgs[MAX_LOOPBACK];
     34 	int			get, send;
     35 } loopback_t;
     36 
     37 loopback_t	loopbacks[2];
     38 int			ip_sockets[2];
     39 int			ipx_sockets[2];
     40 
     41 int NET_Socket (char *net_interface, int port);
     42 char *NET_ErrorString (void);
     43 
     44 //=============================================================================
     45 
     46 void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
     47 {
     48 	memset (s, 0, sizeof(*s));
     49 
     50 	if (a->type == NA_BROADCAST)
     51 	{
     52 		s->sin_family = AF_INET;
     53 
     54 		s->sin_port = a->port;
     55 		*(int *)&s->sin_addr = -1;
     56 	}
     57 	else if (a->type == NA_IP)
     58 	{
     59 		s->sin_family = AF_INET;
     60 
     61 		*(int *)&s->sin_addr = *(int *)&a->ip;
     62 		s->sin_port = a->port;
     63 	}
     64 }
     65 
     66 void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
     67 {
     68 	*(int *)&a->ip = *(int *)&s->sin_addr;
     69 	a->port = s->sin_port;
     70 	a->type = NA_IP;
     71 }
     72 
     73 
     74 qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
     75 {
     76 	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)
     77 		return true;
     78 	return false;
     79 }
     80 
     81 /*
     82 ===================
     83 NET_CompareBaseAdr
     84 
     85 Compares without the port
     86 ===================
     87 */
     88 qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b)
     89 {
     90 	if (a.type != b.type)
     91 		return false;
     92 
     93 	if (a.type == NA_LOOPBACK)
     94 		return true;
     95 
     96 	if (a.type == NA_IP)
     97 	{
     98 		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])
     99 			return true;
    100 		return false;
    101 	}
    102 
    103 	if (a.type == NA_IPX)
    104 	{
    105 		if ((memcmp(a.ipx, b.ipx, 10) == 0))
    106 			return true;
    107 		return false;
    108 	}
    109 }
    110 
    111 char	*NET_AdrToString (netadr_t a)
    112 {
    113 	static	char	s[64];
    114 	
    115 	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));
    116 
    117 	return s;
    118 }
    119 
    120 char	*NET_BaseAdrToString (netadr_t a)
    121 {
    122 	static	char	s[64];
    123 	
    124 	Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
    125 
    126 	return s;
    127 }
    128 
    129 /*
    130 =============
    131 NET_StringToAdr
    132 
    133 localhost
    134 idnewt
    135 idnewt:28000
    136 192.246.40.70
    137 192.246.40.70:28000
    138 =============
    139 */
    140 qboolean	NET_StringToSockaddr (char *s, struct sockaddr *sadr)
    141 {
    142 	struct hostent	*h;
    143 	char	*colon;
    144 	char	copy[128];
    145 	
    146 	memset (sadr, 0, sizeof(*sadr));
    147 	((struct sockaddr_in *)sadr)->sin_family = AF_INET;
    148 	
    149 	((struct sockaddr_in *)sadr)->sin_port = 0;
    150 
    151 	strcpy (copy, s);
    152 	// strip off a trailing :port if present
    153 	for (colon = copy ; *colon ; colon++)
    154 		if (*colon == ':')
    155 		{
    156 			*colon = 0;
    157 			((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));	
    158 		}
    159 	
    160 	if (copy[0] >= '0' && copy[0] <= '9')
    161 	{
    162 		*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
    163 	}
    164 	else
    165 	{
    166 		if (! (h = gethostbyname(copy)) )
    167 			return 0;
    168 		*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
    169 	}
    170 	
    171 	return true;
    172 }
    173 
    174 /*
    175 =============
    176 NET_StringToAdr
    177 
    178 localhost
    179 idnewt
    180 idnewt:28000
    181 192.246.40.70
    182 192.246.40.70:28000
    183 =============
    184 */
    185 qboolean	NET_StringToAdr (char *s, netadr_t *a)
    186 {
    187 	struct sockaddr_in sadr;
    188 	
    189 	if (!strcmp (s, "localhost"))
    190 	{
    191 		memset (a, 0, sizeof(*a));
    192 		a->type = NA_LOOPBACK;
    193 		return true;
    194 	}
    195 
    196 	if (!NET_StringToSockaddr (s, (struct sockaddr *)&sadr))
    197 		return false;
    198 	
    199 	SockadrToNetadr (&sadr, a);
    200 
    201 	return true;
    202 }
    203 
    204 
    205 qboolean	NET_IsLocalAddress (netadr_t adr)
    206 {
    207 	return NET_CompareAdr (adr, net_local_adr);
    208 }
    209 
    210 /*
    211 =============================================================================
    212 
    213 LOOPBACK BUFFERS FOR LOCAL PLAYER
    214 
    215 =============================================================================
    216 */
    217 
    218 qboolean	NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
    219 {
    220 	int		i;
    221 	loopback_t	*loop;
    222 
    223 	loop = &loopbacks[sock];
    224 
    225 	if (loop->send - loop->get > MAX_LOOPBACK)
    226 		loop->get = loop->send - MAX_LOOPBACK;
    227 
    228 	if (loop->get >= loop->send)
    229 		return false;
    230 
    231 	i = loop->get & (MAX_LOOPBACK-1);
    232 	loop->get++;
    233 
    234 	memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
    235 	net_message->cursize = loop->msgs[i].datalen;
    236 	*net_from = net_local_adr;
    237 	return true;
    238 
    239 }
    240 
    241 
    242 void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
    243 {
    244 	int		i;
    245 	loopback_t	*loop;
    246 
    247 	loop = &loopbacks[sock^1];
    248 
    249 	i = loop->send & (MAX_LOOPBACK-1);
    250 	loop->send++;
    251 
    252 	memcpy (loop->msgs[i].data, data, length);
    253 	loop->msgs[i].datalen = length;
    254 }
    255 
    256 //=============================================================================
    257 
    258 qboolean	NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
    259 {
    260 	int 	ret;
    261 	struct sockaddr_in	from;
    262 	int		fromlen;
    263 	int		net_socket;
    264 	int		protocol;
    265 	int		err;
    266 
    267 	if (NET_GetLoopPacket (sock, net_from, net_message))
    268 		return true;
    269 
    270 	for (protocol = 0 ; protocol < 2 ; protocol++)
    271 	{
    272 		if (protocol == 0)
    273 			net_socket = ip_sockets[sock];
    274 		else
    275 			net_socket = ipx_sockets[sock];
    276 
    277 		if (!net_socket)
    278 			continue;
    279 
    280 		fromlen = sizeof(from);
    281 		ret = recvfrom (net_socket, net_message->data, net_message->maxsize
    282 			, 0, (struct sockaddr *)&from, &fromlen);
    283 		if (ret == -1)
    284 		{
    285 			err = errno;
    286 
    287 			if (err == EWOULDBLOCK || err == ECONNREFUSED)
    288 				continue;
    289 			Com_Printf ("NET_GetPacket: %s", NET_ErrorString());
    290 			continue;
    291 		}
    292 
    293 		if (ret == net_message->maxsize)
    294 		{
    295 			Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
    296 			continue;
    297 		}
    298 
    299 		net_message->cursize = ret;
    300 		SockadrToNetadr (&from, net_from);
    301 		return true;
    302 	}
    303 
    304 	return false;
    305 }
    306 
    307 //=============================================================================
    308 
    309 void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
    310 {
    311 	int		ret;
    312 	struct sockaddr_in	addr;
    313 	int		net_socket;
    314 
    315 	if ( to.type == NA_LOOPBACK )
    316 	{
    317 		NET_SendLoopPacket (sock, length, data, to);
    318 		return;
    319 	}
    320 
    321 	if (to.type == NA_BROADCAST)
    322 	{
    323 		net_socket = ip_sockets[sock];
    324 		if (!net_socket)
    325 			return;
    326 	}
    327 	else if (to.type == NA_IP)
    328 	{
    329 		net_socket = ip_sockets[sock];
    330 		if (!net_socket)
    331 			return;
    332 	}
    333 	else if (to.type == NA_IPX)
    334 	{
    335 		net_socket = ipx_sockets[sock];
    336 		if (!net_socket)
    337 			return;
    338 	}
    339 	else if (to.type == NA_BROADCAST_IPX)
    340 	{
    341 		net_socket = ipx_sockets[sock];
    342 		if (!net_socket)
    343 			return;
    344 	}
    345 	else
    346 		Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
    347 
    348 	NetadrToSockadr (&to, &addr);
    349 
    350 	ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
    351 	if (ret == -1)
    352 	{
    353 		Com_Printf ("NET_SendPacket ERROR: %i\n", NET_ErrorString());
    354 	}
    355 }
    356 
    357 
    358 //=============================================================================
    359 
    360 
    361 
    362 
    363 /*
    364 ====================
    365 NET_OpenIP
    366 ====================
    367 */
    368 void NET_OpenIP (void)
    369 {
    370 	cvar_t	*port, *ip;
    371 
    372 	port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET);
    373 	ip = Cvar_Get ("ip", "localhost", CVAR_NOSET);
    374 
    375 	if (!ip_sockets[NS_SERVER])
    376 		ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value);
    377 	if (!ip_sockets[NS_CLIENT])
    378 		ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY);
    379 }
    380 
    381 /*
    382 ====================
    383 NET_OpenIPX
    384 ====================
    385 */
    386 void NET_OpenIPX (void)
    387 {
    388 }
    389 
    390 
    391 /*
    392 ====================
    393 NET_Config
    394 
    395 A single player game will only use the loopback code
    396 ====================
    397 */
    398 void	NET_Config (qboolean multiplayer)
    399 {
    400 	int		i;
    401 
    402 	if (!multiplayer)
    403 	{	// shut down any existing sockets
    404 		for (i=0 ; i<2 ; i++)
    405 		{
    406 			if (ip_sockets[i])
    407 			{
    408 				close (ip_sockets[i]);
    409 				ip_sockets[i] = 0;
    410 			}
    411 			if (ipx_sockets[i])
    412 			{
    413 				close (ipx_sockets[i]);
    414 				ipx_sockets[i] = 0;
    415 			}
    416 		}
    417 	}
    418 	else
    419 	{	// open sockets
    420 		NET_OpenIP ();
    421 		NET_OpenIPX ();
    422 	}
    423 }
    424 
    425 
    426 //===================================================================
    427 
    428 
    429 /*
    430 ====================
    431 NET_Init
    432 ====================
    433 */
    434 void NET_Init (void)
    435 {
    436 }
    437 
    438 
    439 /*
    440 ====================
    441 NET_Socket
    442 ====================
    443 */
    444 int NET_Socket (char *net_interface, int port)
    445 {
    446 	int newsocket;
    447 	struct sockaddr_in address;
    448 	qboolean _true = true;
    449 	int	i = 1;
    450 
    451 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    452 	{
    453 		Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString());
    454 		return 0;
    455 	}
    456 
    457 	// make it non-blocking
    458 	if (ioctl (newsocket, FIONBIO, &_true) == -1)
    459 	{
    460 		Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
    461 		return 0;
    462 	}
    463 
    464 	// make it broadcast capable
    465 	if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
    466 	{
    467 		Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
    468 		return 0;
    469 	}
    470 
    471 	if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
    472 		address.sin_addr.s_addr = INADDR_ANY;
    473 	else
    474 		NET_StringToSockaddr (net_interface, (struct sockaddr *)&address);
    475 
    476 	if (port == PORT_ANY)
    477 		address.sin_port = 0;
    478 	else
    479 		address.sin_port = htons((short)port);
    480 
    481 	address.sin_family = AF_INET;
    482 
    483 	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
    484 	{
    485 		Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
    486 		close (newsocket);
    487 		return 0;
    488 	}
    489 
    490 	return newsocket;
    491 }
    492 
    493 
    494 /*
    495 ====================
    496 NET_Shutdown
    497 ====================
    498 */
    499 void	NET_Shutdown (void)
    500 {
    501 	NET_Config (false);	// close sockets
    502 }
    503 
    504 
    505 /*
    506 ====================
    507 NET_ErrorString
    508 ====================
    509 */
    510 char *NET_ErrorString (void)
    511 {
    512 	int		code;
    513 
    514 	code = errno;
    515 	return strerror (code);
    516 }
    517 
    518 // sleeps msec or until net socket is ready
    519 void NET_Sleep(int msec)
    520 {
    521     struct timeval timeout;
    522 	fd_set	fdset;
    523 	extern cvar_t *dedicated;
    524 	extern qboolean stdin_active;
    525 
    526 	if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value))
    527 		return; // we're not a server, just run full speed
    528 
    529 	FD_ZERO(&fdset);
    530 	if (stdin_active)
    531 		FD_SET(0, &fdset); // stdin is processed too
    532 	FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
    533 	timeout.tv_sec = msec/1000;
    534 	timeout.tv_usec = (msec%1000)*1000;
    535 	select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout);
    536 }
    537