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 // LordHavoc FIXME: get rid of this someday, just leave machines unnamed
73 // if the quake hostname isn't set, set it to the machine name
74 if (strcmp(hostname.string, "UNNAMED") == 0)
77 Cvar_Set ("hostname", buff);
80 if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
81 Sys_Error("UDP_Init: Unable to open control socket\n");
83 ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
84 ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = htonl(INADDR_BROADCAST);
85 ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
87 UDP_GetSocketAddr (net_controlsocket, &addr);
88 strcpy(my_tcpip_address, UDP_AddrToString (&addr));
89 colon = strrchr (my_tcpip_address, ':');
93 Con_Printf("UDP Initialized\n");
94 tcpipAvailable = true;
96 return net_controlsocket;
99 //=============================================================================
101 void UDP_Shutdown (void)
104 UDP_CloseSocket (net_controlsocket);
107 //=============================================================================
109 void UDP_Listen (qboolean state)
114 if (net_acceptsocket != -1)
116 if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
117 Sys_Error ("UDP_Listen: Unable to open accept socket\n");
122 if (net_acceptsocket == -1)
124 UDP_CloseSocket (net_acceptsocket);
125 net_acceptsocket = -1;
128 //=============================================================================
130 int UDP_OpenSocket (int port)
133 struct sockaddr_in address;
134 qboolean _true = true;
136 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
139 if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
142 address.sin_family = AF_INET;
143 address.sin_addr.s_addr = INADDR_ANY;
144 address.sin_port = htons(port);
145 if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
155 //=============================================================================
157 int UDP_CloseSocket (int socket)
159 if (socket == net_broadcastsocket)
160 net_broadcastsocket = 0;
161 return close (socket);
165 //=============================================================================
170 this lets you type only as much of the net address as required, using
171 the local network components to fill in the rest
174 // LordHavoc FIXME: this whole function is stupid
175 static int PartialIPAddress (const char *in, struct qsockaddr *hostaddr)
177 // LordHavoc FIXME: buff is stupid, it just ensures the address begins with a . for the parser
199 while (*b >= '0' && *b <= '9')
201 num = num*10 + *b++ - '0';
205 if (*b != '.' && *b != ':' && *b != 0)
208 addr = (addr<<8) + num;
216 hostaddr->sa_family = AF_INET;
217 ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
218 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
222 //=============================================================================
224 int UDP_Connect (int socket, struct qsockaddr *addr)
229 //=============================================================================
231 int UDP_CheckNewConnections (void)
233 unsigned long available;
234 struct sockaddr_in from;
238 if (net_acceptsocket == -1)
241 if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
242 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
244 return net_acceptsocket;
245 recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *) &from, &fromlen);
249 //=============================================================================
251 int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr)
253 return UDP_Read (net_acceptsocket, buf, len, addr);
256 //=============================================================================
258 int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr)
260 return UDP_Write (net_acceptsocket, buf, len, addr);
263 //=============================================================================
265 int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
267 int addrlen = sizeof (struct qsockaddr);
270 ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
271 if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
276 //=============================================================================
278 int UDP_MakeSocketBroadcastCapable (int socket)
282 // make this socket broadcast capable
283 if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
285 net_broadcastsocket = socket;
290 //=============================================================================
292 int UDP_Broadcast (int socket, qbyte *buf, int len)
296 if (socket != net_broadcastsocket)
298 if (net_broadcastsocket != 0)
299 Sys_Error("Attempted to use multiple broadcasts sockets\n");
300 ret = UDP_MakeSocketBroadcastCapable (socket);
303 Con_Printf("Unable to make socket broadcast capable\n");
308 return UDP_Write (socket, buf, len, &broadcastaddr);
311 //=============================================================================
313 int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr)
317 ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
318 if (ret == -1 && errno == EWOULDBLOCK)
323 //=============================================================================
325 char *UDP_AddrToString (const struct qsockaddr *addr)
327 static char buffer[22];
330 haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
331 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));
335 //=============================================================================
337 int UDP_StringToAddr (const char *string, struct qsockaddr *addr)
339 int ha1, ha2, ha3, ha4, hp;
342 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
343 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
345 addr->sa_family = AF_INET;
346 ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
347 ((struct sockaddr_in *)addr)->sin_port = htons(hp);
351 //=============================================================================
353 unsigned long inet_addr(const char *cp);
354 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
356 int addrlen = sizeof(struct qsockaddr);
359 memset(addr, 0, sizeof(struct qsockaddr));
360 getsockname(socket, (struct sockaddr *)addr, &addrlen);
361 a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
362 if (a == 0 || a == inet_addr("127.0.0.1"))
363 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
368 //=============================================================================
370 int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name)
372 struct hostent *hostentry;
374 hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
377 strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
381 strcpy (name, UDP_AddrToString (addr));
385 //=============================================================================
387 int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr)
389 struct hostent *hostentry;
391 if (name[0] >= '0' && name[0] <= '9')
392 return PartialIPAddress (name, addr);
394 hostentry = gethostbyname (name);
398 addr->sa_family = AF_INET;
399 ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
400 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
405 //=============================================================================
407 int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2)
409 if (addr1->sa_family != addr2->sa_family)
412 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
415 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
421 //=============================================================================
423 int UDP_GetSocketPort (struct qsockaddr *addr)
425 return ntohs(((struct sockaddr_in *)addr)->sin_port);
429 int UDP_SetSocketPort (struct qsockaddr *addr, int port)
431 ((struct sockaddr_in *)addr)->sin_port = htons(port);