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