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.
28 int WSAGetLastError(void);
29 void sockets_flush(void);
31 extern cvar_t hostname
;
33 #define MAXHOSTNAMELEN 256
35 static int net_acceptsocket
= -1; // socket for fielding new connections
36 static int net_controlsocket
;
37 static int net_broadcastsocket
= 0;
38 //static qboolean ifbcastinit = false;
39 static struct qsockaddr broadcastaddr
;
41 static unsigned long myAddr
;
46 //=============================================================================
51 struct hostent
*local
= NULL
;
52 char buff
[MAXHOSTNAMELEN
];
53 struct qsockaddr addr
;
56 if (COM_CheckParm ("-mpath") == 0)
59 flat_selector
= __dpmi_allocate_ldt_descriptors(1);
60 if (flat_selector
== -1) {
61 Con_Printf("MPATH_Init: Can't get flat selector\n");
64 if (__dpmi_set_segment_base_address(flat_selector
, 0) == -1) {
65 Con_Printf("MPATH_Init: Can't seg flat base!\n");
68 if (__dpmi_set_segment_limit(flat_selector
, 0xffffffff) == -1) {
69 Con_Printf("MPATH_Init: Can't set segment limit\n");
72 // determine my name & address
73 if (gethostname(buff
, MAXHOSTNAMELEN
) == 0)
74 local
= gethostbyname(buff
);
77 myAddr
= *(int *)local
->h_addr_list
[0];
79 // if the quake hostname isn't set, set it to the machine name
80 if (Q_strcmp(hostname
.string
, "UNNAMED") == 0)
82 // see if it's a text IP address (well, close enough)
83 for (p
= buff
; *p
; p
++)
84 if ((*p
< '0' || *p
> '9') && *p
!= '.')
87 // if it is a real name, strip off the domain; we only want the host
90 for (i
= 0; i
< 15; i
++)
95 Cvar_Set ("hostname", buff
);
99 if ((net_controlsocket
= MPATH_OpenSocket (0)) == -1)
100 Sys_Error("MPATH_Init: Unable to open control socket\n");
102 ((struct sockaddr_in
*)&broadcastaddr
)->sin_family
= AF_INET
;
103 ((struct sockaddr_in
*)&broadcastaddr
)->sin_addr
.s_addr
= INADDR_BROADCAST
;
104 ((struct sockaddr_in
*)&broadcastaddr
)->sin_port
= htons(net_hostport
);
106 MPATH_GetSocketAddr (net_controlsocket
, &addr
);
107 Q_strcpy(my_tcpip_address
, MPATH_AddrToString (&addr
));
108 p
= Q_strrchr (my_tcpip_address
, ':');
112 Con_Printf("MPath Initialized\n");
113 tcpipAvailable
= true;
115 return net_controlsocket
;
118 //=============================================================================
120 void MPATH_Shutdown (void)
122 MPATH_Listen (false);
123 MPATH_CloseSocket (net_controlsocket
);
126 //=============================================================================
128 void MPATH_Listen (qboolean state
)
133 if (net_acceptsocket
!= -1)
135 if ((net_acceptsocket
= MPATH_OpenSocket (net_hostport
)) == -1)
136 Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
141 if (net_acceptsocket
== -1)
143 MPATH_CloseSocket (net_acceptsocket
);
144 net_acceptsocket
= -1;
147 //=============================================================================
149 int MPATH_OpenSocket (int port
)
152 struct sockaddr_in address
;
155 if ((newsocket
= socket (PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1)
158 if (ioctlsocket (newsocket
, FIONBIO
, &_true
) == -1)
161 address
.sin_family
= AF_INET
;
162 address
.sin_addr
.s_addr
= INADDR_ANY
;
163 address
.sin_port
= htons(port
);
164 if( bind (newsocket
, (void *)&address
, sizeof(address
)) == -1)
170 closesocket (newsocket
);
174 //=============================================================================
176 int MPATH_CloseSocket (int socket
)
178 if (socket
== net_broadcastsocket
)
179 net_broadcastsocket
= 0;
180 return closesocket (socket
);
184 //=============================================================================
189 this lets you type only as much of the net address as required, using
190 the local network components to fill in the rest
193 static int PartialIPAddress (char *in
, struct qsockaddr
*hostaddr
)
216 while (!( *b
< '0' || *b
> '9'))
218 num
= num
*10 + *b
++ - '0';
222 if ((*b
< '0' || *b
> '9') && *b
!= '.' && *b
!= ':' && *b
!= 0)
224 if (num
< 0 || num
> 255)
227 addr
= (addr
<<8) + num
;
235 hostaddr
->sa_family
= AF_INET
;
236 ((struct sockaddr_in
*)hostaddr
)->sin_port
= htons((short)port
);
237 ((struct sockaddr_in
*)hostaddr
)->sin_addr
.s_addr
= (myAddr
& htonl(mask
)) | htonl(addr
);
241 //=============================================================================
243 int MPATH_Connect (int socket
, struct qsockaddr
*addr
)
248 //=============================================================================
250 int MPATH_CheckNewConnections (void)
254 if (net_acceptsocket
== -1)
257 if (recvfrom (net_acceptsocket
, buf
, 4, MSG_PEEK
, NULL
, NULL
) > 0)
258 return net_acceptsocket
;
262 //=============================================================================
264 int MPATH_Read (int socket
, byte
*buf
, int len
, struct qsockaddr
*addr
)
266 int addrlen
= sizeof (struct qsockaddr
);
269 ret
= recvfrom (socket
, buf
, len
, 0, (struct sockaddr
*)addr
, &addrlen
);
272 int errno
= WSAGetLastError();
274 if (errno
== WSAEWOULDBLOCK
|| errno
== WSAECONNREFUSED
)
281 //=============================================================================
283 int MPATH_MakeSocketBroadcastCapable (int socket
)
287 // make this socket broadcast capable
288 if (setsockopt(socket
, SOL_SOCKET
, SO_BROADCAST
, (char *)&i
, sizeof(i
)) < 0)
290 net_broadcastsocket
= socket
;
295 //=============================================================================
297 int MPATH_Broadcast (int socket
, byte
*buf
, int len
)
301 if (socket
!= net_broadcastsocket
)
303 if (net_broadcastsocket
!= 0)
304 Sys_Error("Attempted to use multiple broadcasts sockets\n");
305 ret
= MPATH_MakeSocketBroadcastCapable (socket
);
308 Con_Printf("Unable to make socket broadcast capable\n");
313 return MPATH_Write (socket
, buf
, len
, &broadcastaddr
);
316 //=============================================================================
318 int MPATH_Write (int socket
, byte
*buf
, int len
, struct qsockaddr
*addr
)
322 ret
= sendto (socket
, buf
, len
, 0, (struct sockaddr
*)addr
, sizeof(struct qsockaddr
));
324 if (WSAGetLastError() == WSAEWOULDBLOCK
)
332 //=============================================================================
334 char *MPATH_AddrToString (struct qsockaddr
*addr
)
336 static char buffer
[22];
339 haddr
= ntohl(((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
);
340 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
));
344 //=============================================================================
346 int MPATH_StringToAddr (char *string
, struct qsockaddr
*addr
)
348 int ha1
, ha2
, ha3
, ha4
, hp
;
351 sscanf(string
, "%d.%d.%d.%d:%d", &ha1
, &ha2
, &ha3
, &ha4
, &hp
);
352 ipaddr
= (ha1
<< 24) | (ha2
<< 16) | (ha3
<< 8) | ha4
;
354 addr
->sa_family
= AF_INET
;
355 ((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
= htonl(ipaddr
);
356 ((struct sockaddr_in
*)addr
)->sin_port
= htons(hp
);
360 //=============================================================================
362 int MPATH_GetSocketAddr (int socket
, struct qsockaddr
*addr
)
364 int addrlen
= sizeof(struct qsockaddr
);
367 Q_memset(addr
, 0, sizeof(struct qsockaddr
));
368 getsockname(socket
, (struct sockaddr
*)addr
, &addrlen
);
369 a
= ((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
;
370 if (a
== 0 || a
== inet_addr("127.0.0.1"))
371 ((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
= myAddr
;
376 //=============================================================================
378 int MPATH_GetNameFromAddr (struct qsockaddr
*addr
, char *name
)
380 struct hostent
*hostentry
;
382 hostentry
= gethostbyaddr ((char *)&((struct sockaddr_in
*)addr
)->sin_addr
, sizeof(struct in_addr
), AF_INET
);
385 Q_strncpy (name
, (char *)hostentry
->h_name
, NET_NAMELEN
- 1);
389 Q_strcpy (name
, MPATH_AddrToString (addr
));
393 //=============================================================================
395 int MPATH_GetAddrFromName(char *name
, struct qsockaddr
*addr
)
397 struct hostent
*hostentry
;
399 if (name
[0] >= '0' && name
[0] <= '9')
400 return PartialIPAddress (name
, addr
);
402 hostentry
= gethostbyname (name
);
406 addr
->sa_family
= AF_INET
;
407 ((struct sockaddr_in
*)addr
)->sin_port
= htons(net_hostport
);
408 ((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
= *(int *)hostentry
->h_addr_list
[0];
413 //=============================================================================
415 int MPATH_AddrCompare (struct qsockaddr
*addr1
, struct qsockaddr
*addr2
)
417 if (addr1
->sa_family
!= addr2
->sa_family
)
420 if (((struct sockaddr_in
*)addr1
)->sin_addr
.s_addr
!= ((struct sockaddr_in
*)addr2
)->sin_addr
.s_addr
)
423 if (((struct sockaddr_in
*)addr1
)->sin_port
!= ((struct sockaddr_in
*)addr2
)->sin_port
)
429 //=============================================================================
431 int MPATH_GetSocketPort (struct qsockaddr
*addr
)
433 return ntohs(((struct sockaddr_in
*)addr
)->sin_port
);
437 int MPATH_SetSocketPort (struct qsockaddr
*addr
, int port
)
439 ((struct sockaddr_in
*)addr
)->sin_port
= htons(port
);
443 //=============================================================================