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_Recv (qbyte *buf, int len, struct qsockaddr *addr)
249 return UDP_Read (net_acceptsocket, buf, len, addr);
252 //=============================================================================
254 int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr)
256 return UDP_Write (net_acceptsocket, buf, len, addr);
259 //=============================================================================
261 int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr)
263 int addrlen = sizeof (struct qsockaddr);
266 ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
267 if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
272 //=============================================================================
274 int UDP_MakeSocketBroadcastCapable (int socket)
278 // make this socket broadcast capable
279 if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
281 net_broadcastsocket = socket;
286 //=============================================================================
288 int UDP_Broadcast (int socket, qbyte *buf, int len)
292 if (socket != net_broadcastsocket)
294 if (net_broadcastsocket != 0)
295 Sys_Error("Attempted to use multiple broadcasts sockets\n");
296 ret = UDP_MakeSocketBroadcastCapable (socket);
299 Con_Printf("Unable to make socket broadcast capable\n");
304 return UDP_Write (socket, buf, len, &broadcastaddr);
307 //=============================================================================
309 int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr)
313 ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
314 if (ret == -1 && errno == EWOULDBLOCK)
319 //=============================================================================
321 char *UDP_AddrToString (const struct qsockaddr *addr)
323 static char buffer[22];
326 haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
327 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));
331 //=============================================================================
333 int UDP_StringToAddr (const char *string, struct qsockaddr *addr)
335 int ha1, ha2, ha3, ha4, hp;
338 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
339 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
341 addr->sa_family = AF_INET;
342 ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
343 ((struct sockaddr_in *)addr)->sin_port = htons(hp);
347 //=============================================================================
349 unsigned long inet_addr(const char *cp);
350 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
352 int addrlen = sizeof(struct qsockaddr);
355 memset(addr, 0, sizeof(struct qsockaddr));
356 getsockname(socket, (struct sockaddr *)addr, &addrlen);
357 a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
358 if (a == 0 || a == inet_addr("127.0.0.1"))
359 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
364 //=============================================================================
366 int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name)
368 struct hostent *hostentry;
370 hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
373 strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
377 strcpy (name, UDP_AddrToString (addr));
381 //=============================================================================
383 int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr)
385 struct hostent *hostentry;
387 if (name[0] >= '0' && name[0] <= '9')
388 return PartialIPAddress (name, addr);
390 hostentry = gethostbyname (name);
394 addr->sa_family = AF_INET;
395 ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
396 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
401 //=============================================================================
403 int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2)
405 if (addr1->sa_family != addr2->sa_family)
408 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
411 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
417 //=============================================================================
419 int UDP_GetSocketPort (struct qsockaddr *addr)
421 return ntohs(((struct sockaddr_in *)addr)->sin_port);
425 int UDP_SetSocketPort (struct qsockaddr *addr, int port)
427 ((struct sockaddr_in *)addr)->sin_port = htons(port);