Home | History | Annotate | Download | only in client
      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 
     24 #include <sys/types.h>
     25 #include <sys/socket.h>
     26 #include <netinet/in.h>
     27 #include <netdb.h>
     28 #include <sys/param.h>
     29 #include <sys/ioctl.h>
     30 #include <sys/uio.h>
     31 #include <arpa/inet.h>
     32 #include <errno.h>
     33 
     34 #if defined(sun)
     35 #include <unistd.h>
     36 #endif
     37 
     38 #ifdef sun
     39 #include <sys/filio.h>
     40 #endif
     41 
     42 #ifdef NeXT
     43 #include <libc.h>
     44 #endif
     45 
     46 netadr_t	net_local_adr;
     47 
     48 netadr_t	net_from;
     49 sizebuf_t	net_message;
     50 int			net_socket;			// non blocking, for receives
     51 int			net_send_socket;	// blocking, for sends
     52 
     53 #define	MAX_UDP_PACKET	8192
     54 byte		net_message_buffer[MAX_UDP_PACKET];
     55 
     56 // int gethostname (char *, int);
     57 int close (int);
     58 
     59 //=============================================================================
     60 
     61 void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
     62 {
     63 	memset (s, 0, sizeof(*s));
     64 	s->sin_family = AF_INET;
     65 
     66 	*(int *)&s->sin_addr = *(int *)&a->ip;
     67 	s->sin_port = a->port;
     68 }
     69 
     70 void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
     71 {
     72 	*(int *)&a->ip = *(int *)&s->sin_addr;
     73 	a->port = s->sin_port;
     74 }
     75 
     76 qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b)
     77 {
     78 	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])
     79 		return true;
     80 	return false;
     81 }
     82 
     83 
     84 qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
     85 {
     86 	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)
     87 		return true;
     88 	return false;
     89 }
     90 
     91 char	*NET_AdrToString (netadr_t a)
     92 {
     93 	static	char	s[64];
     94 
     95 	sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
     96 
     97 	return s;
     98 }
     99 
    100 char	*NET_BaseAdrToString (netadr_t a)
    101 {
    102 	static	char	s[64];
    103 
    104 	sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
    105 
    106 	return s;
    107 }
    108 
    109 /*
    110 =============
    111 NET_StringToAdr
    112 
    113 idnewt
    114 idnewt:28000
    115 192.246.40.70
    116 192.246.40.70:28000
    117 =============
    118 */
    119 qboolean	NET_StringToAdr (char *s, netadr_t *a)
    120 {
    121 	struct hostent	*h;
    122 	struct sockaddr_in sadr;
    123 	char	*colon;
    124 	char	copy[128];
    125 
    126 
    127 	memset (&sadr, 0, sizeof(sadr));
    128 	sadr.sin_family = AF_INET;
    129 
    130 	sadr.sin_port = 0;
    131 
    132 	strcpy (copy, s);
    133 	// strip off a trailing :port if present
    134 	for (colon = copy ; *colon ; colon++)
    135 		if (*colon == ':')
    136 		{
    137 			*colon = 0;
    138 			sadr.sin_port = htons(atoi(colon+1));
    139 		}
    140 
    141 	if (copy[0] >= '0' && copy[0] <= '9')
    142 	{
    143 		*(int *)&sadr.sin_addr = inet_addr(copy);
    144 	}
    145 	else
    146 	{
    147 		if (! (h = gethostbyname(copy)) )
    148 			return 0;
    149 		*(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
    150 	}
    151 
    152 	SockadrToNetadr (&sadr, a);
    153 
    154 	return true;
    155 }
    156 
    157 // Returns true if we can't bind the address locally--in other words,
    158 // the IP is NOT one of our interfaces.
    159 qboolean NET_IsClientLegal(netadr_t *adr)
    160 {
    161 	struct sockaddr_in sadr;
    162 	int newsocket;
    163 
    164 #if 0
    165 	if (adr->ip[0] == 127)
    166 		return false; // no local connections period
    167 
    168 	NetadrToSockadr (adr, &sadr);
    169 
    170 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    171 		Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
    172 
    173 	sadr.sin_port = 0;
    174 
    175 	if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1)
    176 	{
    177 		// It is not a local address
    178 		close(newsocket);
    179 		return true;
    180 	}
    181 	close(newsocket);
    182 	return false;
    183 #else
    184 	return true;
    185 #endif
    186 }
    187 
    188 
    189 //=============================================================================
    190 
    191 qboolean NET_GetPacket (void)
    192 {
    193 	int 	ret;
    194 	struct sockaddr_in	from;
    195 	socklen_t		fromlen;
    196 
    197 	fromlen = sizeof(from);
    198 	ret = recvfrom (net_socket, net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
    199 	if (ret == -1) {
    200 		if (errno == EWOULDBLOCK)
    201 			return false;
    202 		if (errno == ECONNREFUSED)
    203 			return false;
    204 		Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
    205 		return false;
    206 	}
    207 
    208 	net_message.cursize = ret;
    209 	SockadrToNetadr (&from, &net_from);
    210 
    211 	return ret;
    212 }
    213 
    214 //=============================================================================
    215 
    216 void NET_SendPacket (int length, void *data, netadr_t to)
    217 {
    218 	int ret;
    219 	struct sockaddr_in	addr;
    220 
    221 	NetadrToSockadr (&to, &addr);
    222 
    223 	ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
    224 	if (ret == -1) {
    225 		if (errno == EWOULDBLOCK)
    226 			return;
    227 		if (errno == ECONNREFUSED)
    228 			return;
    229 		Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
    230 	}
    231 }
    232 
    233 //=============================================================================
    234 
    235 int UDP_OpenSocket (int port)
    236 {
    237 	int newsocket;
    238 	struct sockaddr_in address;
    239 	qboolean _true = true;
    240 	int i;
    241 
    242 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    243 		Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
    244 	if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
    245 		Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
    246 	address.sin_family = AF_INET;
    247 //ZOID -- check for interface binding option
    248 	if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
    249 		address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
    250 		Con_Printf("Binding to IP Interface Address of %s\n",
    251 				inet_ntoa(address.sin_addr));
    252 	} else
    253 		address.sin_addr.s_addr = INADDR_ANY;
    254 	if (port == PORT_ANY)
    255 		address.sin_port = 0;
    256 	else
    257 		address.sin_port = htons((short)port);
    258 	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
    259 		Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
    260 
    261 	return newsocket;
    262 }
    263 
    264 void NET_GetLocalAddress (void)
    265 {
    266 	char	buff[MAXHOSTNAMELEN];
    267 	struct sockaddr_in	address;
    268 	socklen_t namelen;
    269 
    270 	gethostname(buff, MAXHOSTNAMELEN);
    271 	buff[MAXHOSTNAMELEN-1] = 0;
    272 
    273 	NET_StringToAdr (buff, &net_local_adr);
    274 
    275 	namelen = sizeof(address);
    276 	if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
    277 		Sys_Error ("NET_Init: getsockname:", strerror(errno));
    278 	net_local_adr.port = address.sin_port;
    279 
    280 	Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
    281 }
    282 
    283 /*
    284 ====================
    285 NET_Init
    286 ====================
    287 */
    288 void NET_Init (int port)
    289 {
    290 	//
    291 	// open the single socket to be used for all communications
    292 	//
    293 	net_socket = UDP_OpenSocket (port);
    294 
    295 	//
    296 	// init the message buffer
    297 	//
    298 	net_message.maxsize = sizeof(net_message_buffer);
    299 	net_message.data = net_message_buffer;
    300 
    301 	//
    302 	// determine my name & address
    303 	//
    304 	NET_GetLocalAddress ();
    305 
    306 	Con_Printf("UDP Initialized\n");
    307 }
    308 
    309 /*
    310 ====================
    311 NET_Shutdown
    312 ====================
    313 */
    314 void	NET_Shutdown (void)
    315 {
    316 	close (net_socket);
    317 }
    318 
    319