1 /*
2 * net_mpath.c --
3 * MPATH TCP driver: the (Winsock) UDP driver for dosquake
4 * for use when run from within win95.
5 * from quake1 source with minor adaptations for uhexen2.
6 * $Id: net_mp.c,v 1.14 2009-04-28 14:00:34 sezero Exp $
7 *
8 * Copyright (C) 1996-1997 Id Software, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include <dpmi.h>
27 #include "quakedef.h"
28
29 /* these we get from djgpp: */
30 #define WSLIB_ntohl ntohl
31 #define WSLIB_ntohs ntohs
32 #define WSLIB_htonl htonl
33 #define WSLIB_htons htons
34 /* these we have implemented locally: */
35 #define WSLIB_inet_ntoa inet_ntoa
36 #define WSLIB_inet_addr inet_addr
37 #include "mpdosock.h"
38
39 #define sys_socket_t int /* messy... */
40
41 #include "net_defs.h"
42
43 short flat_selector;
44
45 int WSLIB_WSAGetLastError (void);
46 void WSLIB_sockets_flush (void);
47
48 #define MAXHOSTNAMELEN 256
49
50 static int net_acceptsocket = -1; // socket for fielding new connections
51 static int net_controlsocket;
52 static int net_broadcastsocket = 0;
53 //static qboolean ifbcastinit = false;
54 static struct sockaddr_in broadcastaddr;
55
56 static struct in_addr myAddr;
57
58 #include "net_mp.h"
59
60
61 //=============================================================================
62
MPATH_Init(void)63 int MPATH_Init (void)
64 {
65 struct hostent *local;
66 char buff[MAXHOSTNAMELEN];
67 struct qsockaddr addr;
68 char *colon;
69
70 if (COM_CheckParm ("-mpath") == 0)
71 return -1;
72
73 flat_selector = __dpmi_allocate_ldt_descriptors(1);
74 if (flat_selector == -1)
75 {
76 Con_Printf("MPATH_Init: Can't get flat selector\n");
77 return -1;
78 }
79 if (__dpmi_set_segment_base_address(flat_selector, 0) == -1)
80 {
81 Con_Printf("MPATH_Init: Can't seg flat base!\n");
82 return -1;
83 }
84 if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1)
85 {
86 Con_Printf("MPATH_Init: Can't set segment limit\n");
87 return -1;
88 }
89
90 // determine my name & address
91 myAddr.s_addr = WSLIB_htonl(INADDR_LOOPBACK);
92 if (WSLIB_gethostname(buff, MAXHOSTNAMELEN) != 0)
93 {
94 Con_Printf("MPATH_Init: WARNING: gethostname failed.\n");
95 }
96 else
97 {
98 buff[MAXHOSTNAMELEN - 1] = 0;
99 local = WSLIB_gethostbyname(buff);
100 if (local == NULL)
101 {
102 Con_Printf("MPATH_Init: WARNING: gethostbyname failed.\n");
103 }
104 else if (local->h_addrtype != AF_INET)
105 {
106 Con_Printf("MPATH_Init: address from gethostbyname not IPv4\n");
107 }
108 else
109 {
110 myAddr = *(struct in_addr *)local->h_addr_list[0];
111 }
112 }
113 Con_Printf("UDP, Local address: %s\n", WSLIB_inet_ntoa(myAddr));
114
115 if ((net_controlsocket = MPATH_OpenSocket(0)) == -1)
116 Sys_Error("MPATH_Init: Unable to open control socket\n");
117
118 broadcastaddr.sin_family = AF_INET;
119 broadcastaddr.sin_addr.s_addr = INADDR_BROADCAST;
120 broadcastaddr.sin_port = WSLIB_htons((unsigned short)net_hostport);
121
122 MPATH_GetSocketAddr (net_controlsocket, &addr);
123 strcpy(my_tcpip_address, MPATH_AddrToString (&addr));
124 colon = strrchr (my_tcpip_address, ':');
125 if (colon)
126 *colon = 0;
127
128 Con_Printf("MPath Initialized\n");
129 tcpipAvailable = true;
130
131 return net_controlsocket;
132 }
133
134 //=============================================================================
135
MPATH_Shutdown(void)136 void MPATH_Shutdown (void)
137 {
138 MPATH_Listen (false);
139 MPATH_CloseSocket (net_controlsocket);
140 }
141
142 //=============================================================================
143
MPATH_Listen(qboolean state)144 void MPATH_Listen (qboolean state)
145 {
146 // enable listening
147 if (state)
148 {
149 if (net_acceptsocket != -1)
150 return;
151 if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
152 Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
153 return;
154 }
155
156 // disable listening
157 if (net_acceptsocket == -1)
158 return;
159 MPATH_CloseSocket (net_acceptsocket);
160 net_acceptsocket = -1;
161 }
162
163 //=============================================================================
164
MPATH_OpenSocket(int port)165 int MPATH_OpenSocket (int port)
166 {
167 int newsocket;
168 struct sockaddr_in address;
169 u_long _true = 1;
170
171 if ((newsocket = WSLIB_socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
172 return -1;
173
174 if (WSLIB_ioctlsocket (newsocket, FIONBIO, &_true) == -1)
175 goto ErrorReturn;
176
177 memset(&address, 0, sizeof(struct sockaddr_in));
178 address.sin_family = AF_INET;
179 address.sin_addr.s_addr = INADDR_ANY;
180 address.sin_port = WSLIB_htons((unsigned short)port);
181 if ( WSLIB_bind (newsocket, (struct sockaddr *)&address, sizeof(address)) == -1)
182 goto ErrorReturn;
183
184 return newsocket;
185
186 ErrorReturn:
187 WSLIB_closesocket (newsocket);
188 return -1;
189 }
190
191 //=============================================================================
192
MPATH_CloseSocket(int socketid)193 int MPATH_CloseSocket (int socketid)
194 {
195 if (socketid == net_broadcastsocket)
196 net_broadcastsocket = 0;
197 return WSLIB_closesocket (socketid);
198 }
199
200 //=============================================================================
201
202 /*
203 ============
204 PartialIPAddress
205
206 this lets you type only as much of the net address as required, using
207 the local network components to fill in the rest
208 ============
209 */
PartialIPAddress(const char * in,struct qsockaddr * hostaddr)210 static int PartialIPAddress (const char *in, struct qsockaddr *hostaddr)
211 {
212 char buff[256];
213 char *b;
214 int addr, mask, num, port, run;
215
216 buff[0] = '.';
217 b = buff;
218 strcpy(buff+1, in);
219 if (buff[1] == '.')
220 b++;
221
222 addr = 0;
223 mask = -1;
224 while (*b == '.')
225 {
226 b++;
227 num = 0;
228 run = 0;
229 while (!( *b < '0' || *b > '9'))
230 {
231 num = num*10 + *b++ - '0';
232 if (++run > 3)
233 return -1;
234 }
235 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
236 return -1;
237 if (num < 0 || num > 255)
238 return -1;
239 mask <<= 8;
240 addr = (addr<<8) + num;
241 }
242
243 if (*b++ == ':')
244 port = atoi(b);
245 else
246 port = net_hostport;
247
248 hostaddr->qsa_family = AF_INET;
249 ((struct sockaddr_in *)hostaddr)->sin_port = WSLIB_htons((unsigned short)port);
250 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr.s_addr & WSLIB_htonl(mask)) | WSLIB_htonl(addr);
251
252 return 0;
253 }
254
255 //=============================================================================
256
MPATH_Connect(int socketid,struct qsockaddr * addr)257 int MPATH_Connect (int socketid, struct qsockaddr *addr)
258 {
259 return 0;
260 }
261
262 //=============================================================================
263
MPATH_CheckNewConnections(void)264 int MPATH_CheckNewConnections (void)
265 {
266 char buf[4];
267
268 if (net_acceptsocket == -1)
269 return -1;
270
271 if (WSLIB_recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) >= 0)
272 return net_acceptsocket;
273 return -1;
274 }
275
276 //=============================================================================
277
MPATH_Read(int socketid,byte * buf,int len,struct qsockaddr * addr)278 int MPATH_Read (int socketid, byte *buf, int len, struct qsockaddr *addr)
279 {
280 int addrlen = sizeof(struct qsockaddr);
281 int ret;
282
283 ret = WSLIB_recvfrom (socketid, (char *)buf, len, 0, (struct sockaddr *)addr, &addrlen);
284 if (ret == -1)
285 {
286 int err = WSLIB_WSAGetLastError();
287
288 if (err == WSAEWOULDBLOCK || err == WSAECONNREFUSED)
289 return 0;
290 }
291 return ret;
292 }
293
294 //=============================================================================
295
MPATH_MakeSocketBroadcastCapable(int socketid)296 int MPATH_MakeSocketBroadcastCapable (int socketid)
297 {
298 int i = 1;
299
300 // make this socket broadcast capable
301 if (WSLIB_setsockopt(socketid, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
302 return -1;
303 net_broadcastsocket = socketid;
304
305 return 0;
306 }
307
308 //=============================================================================
309
MPATH_Broadcast(int socketid,byte * buf,int len)310 int MPATH_Broadcast (int socketid, byte *buf, int len)
311 {
312 int ret;
313
314 if (socketid != net_broadcastsocket)
315 {
316 if (net_broadcastsocket != 0)
317 Sys_Error("Attempted to use multiple broadcasts sockets\n");
318 ret = MPATH_MakeSocketBroadcastCapable (socketid);
319 if (ret == -1)
320 {
321 Con_Printf("Unable to make socket broadcast capable\n");
322 return ret;
323 }
324 }
325
326 return MPATH_Write (socketid, buf, len, (struct qsockaddr *)&broadcastaddr);
327 }
328
329 //=============================================================================
330
MPATH_Write(int socketid,byte * buf,int len,struct qsockaddr * addr)331 int MPATH_Write (int socketid, byte *buf, int len, struct qsockaddr *addr)
332 {
333 int ret;
334
335 ret = WSLIB_sendto (socketid, (char *)buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
336 if (ret == -1)
337 {
338 if (WSLIB_WSAGetLastError() == WSAEWOULDBLOCK)
339 return 0;
340 }
341
342 WSLIB_sockets_flush();
343
344 return ret;
345 }
346
347 //=============================================================================
348
MPATH_AddrToString(struct qsockaddr * addr)349 const char *MPATH_AddrToString (struct qsockaddr *addr)
350 {
351 static char buffer[22];
352 int haddr;
353
354 haddr = WSLIB_ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
355 q_snprintf (buffer, sizeof(buffer), "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
356 (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff,
357 WSLIB_ntohs(((struct sockaddr_in *)addr)->sin_port));
358 return buffer;
359 }
360
361 //=============================================================================
362
MPATH_StringToAddr(const char * string,struct qsockaddr * addr)363 int MPATH_StringToAddr (const char *string, struct qsockaddr *addr)
364 {
365 int ha1, ha2, ha3, ha4, hp, ipaddr;
366
367 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
368 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
369
370 addr->qsa_family = AF_INET;
371 ((struct sockaddr_in *)addr)->sin_addr.s_addr = WSLIB_htonl(ipaddr);
372 ((struct sockaddr_in *)addr)->sin_port = WSLIB_htons((unsigned short)hp);
373 return 0;
374 }
375
376 //=============================================================================
377
MPATH_GetSocketAddr(int socketid,struct qsockaddr * addr)378 int MPATH_GetSocketAddr (int socketid, struct qsockaddr *addr)
379 {
380 int addrlen = sizeof(struct qsockaddr);
381 struct sockaddr_in *address = (struct sockaddr_in *)addr;
382 struct in_addr a;
383
384 memset(addr, 0, sizeof(struct qsockaddr));
385 WSLIB_getsockname(socketid, (struct sockaddr *)addr, &addrlen);
386 a = address->sin_addr;
387 if (a.s_addr == 0 || a.s_addr == WSLIB_htonl(INADDR_LOOPBACK))
388 address->sin_addr.s_addr = myAddr.s_addr;
389
390 return 0;
391 }
392
393 //=============================================================================
394
MPATH_GetNameFromAddr(struct qsockaddr * addr,char * name)395 int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
396 {
397 struct hostent *hostentry;
398
399 hostentry = WSLIB_gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
400 if (hostentry)
401 {
402 strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
403 return 0;
404 }
405
406 strcpy (name, MPATH_AddrToString (addr));
407 return 0;
408 }
409
410 //=============================================================================
411
MPATH_GetAddrFromName(const char * name,struct qsockaddr * addr)412 int MPATH_GetAddrFromName (const char *name, struct qsockaddr *addr)
413 {
414 struct hostent *hostentry;
415
416 if (name[0] >= '0' && name[0] <= '9')
417 return PartialIPAddress (name, addr);
418
419 hostentry = WSLIB_gethostbyname (name);
420 if (!hostentry)
421 return -1;
422
423 addr->qsa_family = AF_INET;
424 ((struct sockaddr_in *)addr)->sin_port = WSLIB_htons((unsigned short)net_hostport);
425 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(u_long *)hostentry->h_addr_list[0];
426
427 return 0;
428 }
429
430 //=============================================================================
431
MPATH_AddrCompare(struct qsockaddr * addr1,struct qsockaddr * addr2)432 int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
433 {
434 if (addr1->qsa_family != addr2->qsa_family)
435 return -1;
436
437 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
438 return -1;
439
440 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
441 return 1;
442
443 return 0;
444 }
445
446 //=============================================================================
447
MPATH_GetSocketPort(struct qsockaddr * addr)448 int MPATH_GetSocketPort (struct qsockaddr *addr)
449 {
450 return WSLIB_ntohs(((struct sockaddr_in *)addr)->sin_port);
451 }
452
453
MPATH_SetSocketPort(struct qsockaddr * addr,int port)454 int MPATH_SetSocketPort (struct qsockaddr *addr, int port)
455 {
456 ((struct sockaddr_in *)addr)->sin_port = WSLIB_htons((unsigned short)port);
457 return 0;
458 }
459
460 //=============================================================================
461
462