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);
67 myAddr = *(int *)local->h_addr_list[0];
69 // if the quake hostname isn't set, set it to the machine name
70 if (strcmp(hostname.string, "UNNAMED") == 0)
73 Cvar_Set ("hostname", buff);
76 if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
77 Sys_Error("UDP_Init: Unable to open control socket\n");
79 ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
80 ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
81 ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
83 UDP_GetSocketAddr (net_controlsocket, &addr);
84 strcpy(my_tcpip_address, UDP_AddrToString (&addr));
85 colon = strrchr (my_tcpip_address, ':');
89 Con_Printf("UDP Initialized\n");
90 tcpipAvailable = true;
92 return net_controlsocket;
95 //=============================================================================
97 void UDP_Shutdown (void)
100 UDP_CloseSocket (net_controlsocket);
103 //=============================================================================
105 void UDP_Listen (qboolean state)
110 if (net_acceptsocket != -1)
112 if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
113 Sys_Error ("UDP_Listen: Unable to open accept socket\n");
118 if (net_acceptsocket == -1)
120 UDP_CloseSocket (net_acceptsocket);
121 net_acceptsocket = -1;
124 //=============================================================================
126 int UDP_OpenSocket (int port)
129 struct sockaddr_in address;
130 qboolean _true = true;
132 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
135 if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
138 address.sin_family = AF_INET;
139 address.sin_addr.s_addr = INADDR_ANY;
140 address.sin_port = htons(port);
141 if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
151 //=============================================================================
153 int UDP_CloseSocket (int socket)
155 if (socket == net_broadcastsocket)
156 net_broadcastsocket = 0;
157 return close (socket);
161 //=============================================================================
166 this lets you type only as much of the net address as required, using
167 the local network components to fill in the rest
170 static int PartialIPAddress (const char *in, struct qsockaddr *hostaddr)
193 while (!( *b < '0' || *b > '9'))
195 num = num*10 + *b++ - '0';
199 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
201 if (num < 0 || num > 255)
204 addr = (addr<<8) + num;
212 hostaddr->sa_family = AF_INET;
213 ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
214 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
218 //=============================================================================
220 int UDP_Connect (int socket, struct qsockaddr *addr)
225 //=============================================================================
227 int UDP_CheckNewConnections (void)
229 unsigned long available;
230 struct sockaddr_in from;
234 if (net_acceptsocket == -1)
237 if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
238 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
240 return net_acceptsocket;
241 recvfrom (net_acceptsocket, buff, 0, 0, (struct sockaddr *) &from, &fromlen);
245 //=============================================================================
247 int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
249 int addrlen = sizeof (struct qsockaddr);
252 ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
253 if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
258 //=============================================================================
260 int UDP_MakeSocketBroadcastCapable (int socket)
264 // make this socket broadcast capable
265 if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
267 net_broadcastsocket = socket;
272 //=============================================================================
274 int UDP_Broadcast (int socket, qbyte *buf, int len)
278 if (socket != net_broadcastsocket)
280 if (net_broadcastsocket != 0)
281 Sys_Error("Attempted to use multiple broadcasts sockets\n");
282 ret = UDP_MakeSocketBroadcastCapable (socket);
285 Con_Printf("Unable to make socket broadcast capable\n");
290 return UDP_Write (socket, buf, len, &broadcastaddr);
293 //=============================================================================
295 int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr)
299 ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
300 if (ret == -1 && errno == EWOULDBLOCK)
305 //=============================================================================
307 char *UDP_AddrToString (struct qsockaddr *addr)
309 static char buffer[22];
312 haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
313 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));
317 //=============================================================================
319 int UDP_StringToAddr (const char *string, struct qsockaddr *addr)
321 int ha1, ha2, ha3, ha4, hp;
324 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
325 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
327 addr->sa_family = AF_INET;
328 ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
329 ((struct sockaddr_in *)addr)->sin_port = htons(hp);
333 //=============================================================================
335 unsigned long inet_addr(const char *cp);
336 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
338 int addrlen = sizeof(struct qsockaddr);
341 memset(addr, 0, sizeof(struct qsockaddr));
342 getsockname(socket, (struct sockaddr *)addr, &addrlen);
343 a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
344 if (a == 0 || a == inet_addr("127.0.0.1"))
345 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
350 //=============================================================================
352 int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
354 struct hostent *hostentry;
356 hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
359 strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
363 strcpy (name, UDP_AddrToString (addr));
367 //=============================================================================
369 int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr)
371 struct hostent *hostentry;
373 if (name[0] >= '0' && name[0] <= '9')
374 return PartialIPAddress (name, addr);
376 hostentry = gethostbyname (name);
380 addr->sa_family = AF_INET;
381 ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
382 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
387 //=============================================================================
389 int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
391 if (addr1->sa_family != addr2->sa_family)
394 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
397 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
403 //=============================================================================
405 int UDP_GetSocketPort (struct qsockaddr *addr)
407 return ntohs(((struct sockaddr_in *)addr)->sin_port);
411 int UDP_SetSocketPort (struct qsockaddr *addr, int port)
413 ((struct sockaddr_in *)addr)->sin_port = htons(port);