2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
28 #include <sys/param.h>
29 #include <sys/ioctl.h>
33 #include <sys/filio.h>
40 extern int gethostname (char *, int);
41 extern int close (int);
43 static int net_acceptsocket = -1; // socket for fielding new connections
44 static int net_controlsocket;
45 static int net_broadcastsocket = 0;
46 static struct qsockaddr broadcastaddr;
48 static unsigned long myAddr;
52 //=============================================================================
56 struct hostent *local;
57 char buff[MAXHOSTNAMELEN];
58 struct qsockaddr addr;
61 if (COM_CheckParm ("-noudp"))
64 // determine my name & address
65 gethostname(buff, MAXHOSTNAMELEN);
66 local = gethostbyname(buff);
68 myAddr = htonl(INADDR_LOOPBACK); // default to the loopback address
70 myAddr = *(int *)local->h_addr_list[0];
72 // if the quake hostname isn't set, set it to the machine name
73 if (strcmp(hostname.string, "UNNAMED") == 0)
76 Cvar_Set ("hostname", buff);
79 if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
80 Sys_Error("UDP_Init: Unable to open control socket\n");
82 ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
83 ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = htonl(INADDR_BROADCAST);
84 ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
86 UDP_GetSocketAddr (net_controlsocket, &addr);
87 strcpy(my_tcpip_address, UDP_AddrToString (&addr));
88 colon = strrchr (my_tcpip_address, ':');
92 Con_Printf("UDP Initialized\n");
93 tcpipAvailable = true;
95 return net_controlsocket;
98 //=============================================================================
100 void UDP_Shutdown (void)
103 UDP_CloseSocket (net_controlsocket);
106 //=============================================================================
108 void UDP_Listen (qboolean state)
113 if (net_acceptsocket != -1)
115 if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
116 Sys_Error ("UDP_Listen: Unable to open accept socket\n");
121 if (net_acceptsocket == -1)
123 UDP_CloseSocket (net_acceptsocket);
124 net_acceptsocket = -1;
127 //=============================================================================
129 int UDP_OpenSocket (int port)
132 struct sockaddr_in address;
133 qboolean _true = true;
135 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
138 if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
141 address.sin_family = AF_INET;
142 address.sin_addr.s_addr = INADDR_ANY;
143 address.sin_port = htons(port);
144 if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
154 //=============================================================================
156 int UDP_CloseSocket (int socket)
158 if (socket == net_broadcastsocket)
159 net_broadcastsocket = 0;
160 return close (socket);
164 //=============================================================================
169 this lets you type only as much of the net address as required, using
170 the local network components to fill in the rest
173 static int PartialIPAddress (const char *in, struct qsockaddr *hostaddr)
196 while (!( *b < '0' || *b > '9'))
198 num = num*10 + *b++ - '0';
202 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
204 if (num < 0 || num > 255)
207 addr = (addr<<8) + num;
215 hostaddr->sa_family = AF_INET;
216 ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
217 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
221 //=============================================================================
223 int UDP_Connect (int socket, struct qsockaddr *addr)
228 //=============================================================================
230 int UDP_CheckNewConnections (void)
232 unsigned long available;
233 struct sockaddr_in from;
237 if (net_acceptsocket == -1)
240 if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
241 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
243 return net_acceptsocket;
244 recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *) &from, &fromlen);
248 //=============================================================================
250 int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr)
252 return UDP_Read (net_acceptsocket, buf, len, addr);
255 //=============================================================================
257 int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr)
259 return UDP_Write (net_acceptsocket, buf, len, addr);
262 //=============================================================================
264 int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
266 int addrlen = sizeof (struct qsockaddr);
269 ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
270 if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
275 //=============================================================================
277 int UDP_MakeSocketBroadcastCapable (int socket)
281 // make this socket broadcast capable
282 if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
284 net_broadcastsocket = socket;
289 //=============================================================================
291 int UDP_Broadcast (int socket, qbyte *buf, int len)
295 if (socket != net_broadcastsocket)
297 if (net_broadcastsocket != 0)
298 Sys_Error("Attempted to use multiple broadcasts sockets\n");
299 ret = UDP_MakeSocketBroadcastCapable (socket);
302 Con_Printf("Unable to make socket broadcast capable\n");
307 return UDP_Write (socket, buf, len, &broadcastaddr);
310 //=============================================================================
312 int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr)
316 ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
317 if (ret == -1 && errno == EWOULDBLOCK)
322 //=============================================================================
324 char *UDP_AddrToString (const struct qsockaddr *addr)
326 static char buffer[22];
329 haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
330 sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
334 //=============================================================================
336 int UDP_StringToAddr (const char *string, struct qsockaddr *addr)
338 int ha1, ha2, ha3, ha4, hp;
341 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
342 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
344 addr->sa_family = AF_INET;
345 ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
346 ((struct sockaddr_in *)addr)->sin_port = htons(hp);
350 //=============================================================================
352 unsigned long inet_addr(const char *cp);
353 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
355 int addrlen = sizeof(struct qsockaddr);
358 memset(addr, 0, sizeof(struct qsockaddr));
359 getsockname(socket, (struct sockaddr *)addr, &addrlen);
360 a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
361 if (a == 0 || a == inet_addr("127.0.0.1"))
362 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
367 //=============================================================================
369 int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name)
371 struct hostent *hostentry;
373 hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
376 strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
380 strcpy (name, UDP_AddrToString (addr));
384 //=============================================================================
386 int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr)
388 struct hostent *hostentry;
390 if (name[0] >= '0' && name[0] <= '9')
391 return PartialIPAddress (name, addr);
393 hostentry = gethostbyname (name);
397 addr->sa_family = AF_INET;
398 ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
399 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
404 //=============================================================================
406 int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2)
408 if (addr1->sa_family != addr2->sa_family)
411 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
414 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
420 //=============================================================================
422 int UDP_GetSocketPort (struct qsockaddr *addr)
424 return ntohs(((struct sockaddr_in *)addr)->sin_port);
428 int UDP_SetSocketPort (struct qsockaddr *addr, int port)
430 ((struct sockaddr_in *)addr)->sin_port = htons(port);