• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
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.
8 
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.
12 
13 See the GNU General Public License for more details.
14 
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.
18 
19 */
20 // net_wipx.c
21 
22 #include "quakedef.h"
23 #include "winquake.h"
24 #include <wsipx.h>
25 #include "net_wipx.h"
26 
27 extern cvar_t hostname;
28 
29 #define MAXHOSTNAMELEN		256
30 
31 static int net_acceptsocket = -1;		// socket for fielding new connections
32 static int net_controlsocket;
33 static struct qsockaddr broadcastaddr;
34 
35 extern qboolean winsock_initialized;
36 extern WSADATA		winsockdata;
37 
38 #define IPXSOCKETS 18
39 static int ipxsocket[IPXSOCKETS];
40 static int sequence[IPXSOCKETS];
41 
42 //=============================================================================
43 
WIPX_Init(void)44 int WIPX_Init (void)
45 {
46 	int		i;
47 	char	buff[MAXHOSTNAMELEN];
48 	struct qsockaddr addr;
49 	char	*p;
50 	int		r;
51 	WORD	wVersionRequested;
52 
53 	if (COM_CheckParm ("-noipx"))
54 		return -1;
55 
56 // make sure LoadLibrary has happened successfully
57 	if (!winsock_lib_initialized)
58 		return -1;
59 
60 	if (winsock_initialized == 0)
61 	{
62 		wVersionRequested = MAKEWORD(1, 1);
63 
64 		r = pWSAStartup (MAKEWORD(1, 1), &winsockdata);
65 
66 		if (r)
67 		{
68 			Con_Printf ("Winsock initialization failed.\n");
69 			return -1;
70 		}
71 	}
72 	winsock_initialized++;
73 
74 	for (i = 0; i < IPXSOCKETS; i++)
75 		ipxsocket[i] = 0;
76 
77 	// determine my name & address
78 	if (pgethostname(buff, MAXHOSTNAMELEN) == 0)
79 	{
80 		// if the quake hostname isn't set, set it to the machine name
81 		if (Q_strcmp(hostname.string, "UNNAMED") == 0)
82 		{
83 			// see if it's a text IP address (well, close enough)
84 			for (p = buff; *p; p++)
85 				if ((*p < '0' || *p > '9') && *p != '.')
86 					break;
87 
88 			// if it is a real name, strip off the domain; we only want the host
89 			if (*p)
90 			{
91 				for (i = 0; i < 15; i++)
92 					if (buff[i] == '.')
93 						break;
94 				buff[i] = 0;
95 			}
96 			Cvar_Set ("hostname", buff);
97 		}
98 	}
99 
100 	if ((net_controlsocket = WIPX_OpenSocket (0)) == -1)
101 	{
102 		Con_Printf("WIPX_Init: Unable to open control socket\n");
103 		if (--winsock_initialized == 0)
104 			pWSACleanup ();
105 		return -1;
106 	}
107 
108 	((struct sockaddr_ipx *)&broadcastaddr)->sa_family = AF_IPX;
109 	memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_netnum, 0, 4);
110 	memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_nodenum, 0xff, 6);
111 	((struct sockaddr_ipx *)&broadcastaddr)->sa_socket = htons((unsigned short)net_hostport);
112 
113 	WIPX_GetSocketAddr (net_controlsocket, &addr);
114 	Q_strcpy(my_ipx_address,  WIPX_AddrToString (&addr));
115 	p = Q_strrchr (my_ipx_address, ':');
116 	if (p)
117 		*p = 0;
118 
119 	Con_Printf("Winsock IPX Initialized\n");
120 	ipxAvailable = true;
121 
122 	return net_controlsocket;
123 }
124 
125 //=============================================================================
126 
WIPX_Shutdown(void)127 void WIPX_Shutdown (void)
128 {
129 	WIPX_Listen (false);
130 	WIPX_CloseSocket (net_controlsocket);
131 	if (--winsock_initialized == 0)
132 		pWSACleanup ();
133 }
134 
135 //=============================================================================
136 
WIPX_Listen(qboolean state)137 void WIPX_Listen (qboolean state)
138 {
139 	// enable listening
140 	if (state)
141 	{
142 		if (net_acceptsocket != -1)
143 			return;
144 		if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1)
145 			Sys_Error ("WIPX_Listen: Unable to open accept socket\n");
146 		return;
147 	}
148 
149 	// disable listening
150 	if (net_acceptsocket == -1)
151 		return;
152 	WIPX_CloseSocket (net_acceptsocket);
153 	net_acceptsocket = -1;
154 }
155 
156 //=============================================================================
157 
WIPX_OpenSocket(int port)158 int WIPX_OpenSocket (int port)
159 {
160 	int handle;
161 	int newsocket;
162 	struct sockaddr_ipx address;
163 	u_long _true = 1;
164 
165 	for (handle = 0; handle < IPXSOCKETS; handle++)
166 		if (ipxsocket[handle] == 0)
167 			break;
168 	if (handle == IPXSOCKETS)
169 		return -1;
170 
171 	if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET)
172 		return -1;
173 
174 	if (pioctlsocket (newsocket, FIONBIO, &_true) == -1)
175 		goto ErrorReturn;
176 
177 	if (psetsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) < 0)
178 		goto ErrorReturn;
179 
180 	address.sa_family = AF_IPX;
181 	memset(address.sa_netnum, 0, 4);
182 	memset(address.sa_nodenum, 0, 6);;
183 	address.sa_socket = htons((unsigned short)port);
184 	if( bind (newsocket, (void *)&address, sizeof(address)) == 0)
185 	{
186 		ipxsocket[handle] = newsocket;
187 		sequence[handle] = 0;
188 		return handle;
189 	}
190 
191 	Sys_Error ("Winsock IPX bind failed\n");
192 ErrorReturn:
193 	pclosesocket (newsocket);
194 	return -1;
195 }
196 
197 //=============================================================================
198 
WIPX_CloseSocket(int handle)199 int WIPX_CloseSocket (int handle)
200 {
201 	int socket = ipxsocket[handle];
202 	int ret;
203 
204 	ret =  pclosesocket (socket);
205 	ipxsocket[handle] = 0;
206 	return ret;
207 }
208 
209 
210 //=============================================================================
211 
WIPX_Connect(int handle,struct qsockaddr * addr)212 int WIPX_Connect (int handle, struct qsockaddr *addr)
213 {
214 	return 0;
215 }
216 
217 //=============================================================================
218 
WIPX_CheckNewConnections(void)219 int WIPX_CheckNewConnections (void)
220 {
221 	unsigned long	available;
222 
223 	if (net_acceptsocket == -1)
224 		return -1;
225 
226 	if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1)
227 		Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed\n");
228 	if (available)
229 		return net_acceptsocket;
230 	return -1;
231 }
232 
233 //=============================================================================
234 
235 static byte packetBuffer[NET_DATAGRAMSIZE + 4];
236 
WIPX_Read(int handle,byte * buf,int len,struct qsockaddr * addr)237 int WIPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
238 {
239 	int addrlen = sizeof (struct qsockaddr);
240 	int socket = ipxsocket[handle];
241 	int ret;
242 
243 	ret = precvfrom (socket, packetBuffer, len+4, 0, (struct sockaddr *)addr, &addrlen);
244 	if (ret == -1)
245 	{
246 		int errno = pWSAGetLastError();
247 
248 		if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
249 			return 0;
250 
251 	}
252 
253 	if (ret < 4)
254 		return 0;
255 
256 	// remove sequence number, it's only needed for DOS IPX
257 	ret -= 4;
258 	memcpy(buf, packetBuffer+4, ret);
259 
260 	return ret;
261 }
262 
263 //=============================================================================
264 
WIPX_Broadcast(int handle,byte * buf,int len)265 int WIPX_Broadcast (int handle, byte *buf, int len)
266 {
267 	return WIPX_Write (handle, buf, len, &broadcastaddr);
268 }
269 
270 //=============================================================================
271 
WIPX_Write(int handle,byte * buf,int len,struct qsockaddr * addr)272 int WIPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
273 {
274 	int socket = ipxsocket[handle];
275 	int ret;
276 
277 	// build packet with sequence number
278 	*(int *)(&packetBuffer[0]) = sequence[handle];
279 	sequence[handle]++;
280 	memcpy(&packetBuffer[4], buf, len);
281 	len += 4;
282 
283 	ret = psendto (socket, packetBuffer, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
284 	if (ret == -1)
285 		if (pWSAGetLastError() == WSAEWOULDBLOCK)
286 			return 0;
287 
288 	return ret;
289 }
290 
291 //=============================================================================
292 
WIPX_AddrToString(struct qsockaddr * addr)293 char *WIPX_AddrToString (struct qsockaddr *addr)
294 {
295 	static char buf[28];
296 
297 	sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
298 		((struct sockaddr_ipx *)addr)->sa_netnum[0] & 0xff,
299 		((struct sockaddr_ipx *)addr)->sa_netnum[1] & 0xff,
300 		((struct sockaddr_ipx *)addr)->sa_netnum[2] & 0xff,
301 		((struct sockaddr_ipx *)addr)->sa_netnum[3] & 0xff,
302 		((struct sockaddr_ipx *)addr)->sa_nodenum[0] & 0xff,
303 		((struct sockaddr_ipx *)addr)->sa_nodenum[1] & 0xff,
304 		((struct sockaddr_ipx *)addr)->sa_nodenum[2] & 0xff,
305 		((struct sockaddr_ipx *)addr)->sa_nodenum[3] & 0xff,
306 		((struct sockaddr_ipx *)addr)->sa_nodenum[4] & 0xff,
307 		((struct sockaddr_ipx *)addr)->sa_nodenum[5] & 0xff,
308 		ntohs(((struct sockaddr_ipx *)addr)->sa_socket)
309 		);
310 	return buf;
311 }
312 
313 //=============================================================================
314 
WIPX_StringToAddr(char * string,struct qsockaddr * addr)315 int WIPX_StringToAddr (char *string, struct qsockaddr *addr)
316 {
317 	int  val;
318 	char buf[3];
319 
320 	buf[2] = 0;
321 	Q_memset(addr, 0, sizeof(struct qsockaddr));
322 	addr->sa_family = AF_IPX;
323 
324 #define DO(src,dest)	\
325 	buf[0] = string[src];	\
326 	buf[1] = string[src + 1];	\
327 	if (sscanf (buf, "%x", &val) != 1)	\
328 		return -1;	\
329 	((struct sockaddr_ipx *)addr)->dest = val
330 
331 	DO(0, sa_netnum[0]);
332 	DO(2, sa_netnum[1]);
333 	DO(4, sa_netnum[2]);
334 	DO(6, sa_netnum[3]);
335 	DO(9, sa_nodenum[0]);
336 	DO(11, sa_nodenum[1]);
337 	DO(13, sa_nodenum[2]);
338 	DO(15, sa_nodenum[3]);
339 	DO(17, sa_nodenum[4]);
340 	DO(19, sa_nodenum[5]);
341 #undef DO
342 
343 	sscanf (&string[22], "%u", &val);
344 	((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)val);
345 
346 	return 0;
347 }
348 
349 //=============================================================================
350 
WIPX_GetSocketAddr(int handle,struct qsockaddr * addr)351 int WIPX_GetSocketAddr (int handle, struct qsockaddr *addr)
352 {
353 	int socket = ipxsocket[handle];
354 	int addrlen = sizeof(struct qsockaddr);
355 	unsigned int a;
356 
357 	Q_memset(addr, 0, sizeof(struct qsockaddr));
358 	if(pgetsockname(socket, (struct sockaddr *)addr, &addrlen) != 0)
359 	{
360 		int errno = pWSAGetLastError();
361 	}
362 
363 	return 0;
364 }
365 
366 //=============================================================================
367 
WIPX_GetNameFromAddr(struct qsockaddr * addr,char * name)368 int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
369 {
370 	Q_strcpy(name, WIPX_AddrToString(addr));
371 	return 0;
372 }
373 
374 //=============================================================================
375 
WIPX_GetAddrFromName(char * name,struct qsockaddr * addr)376 int WIPX_GetAddrFromName(char *name, struct qsockaddr *addr)
377 {
378 	int n;
379 	char buf[32];
380 
381 	n = Q_strlen(name);
382 
383 	if (n == 12)
384 	{
385 		sprintf(buf, "00000000:%s:%u", name, net_hostport);
386 		return WIPX_StringToAddr (buf, addr);
387 	}
388 	if (n == 21)
389 	{
390 		sprintf(buf, "%s:%u", name, net_hostport);
391 		return WIPX_StringToAddr (buf, addr);
392 	}
393 	if (n > 21 && n <= 27)
394 		return WIPX_StringToAddr (name, addr);
395 
396 	return -1;
397 }
398 
399 //=============================================================================
400 
WIPX_AddrCompare(struct qsockaddr * addr1,struct qsockaddr * addr2)401 int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
402 {
403 	if (addr1->sa_family != addr2->sa_family)
404 		return -1;
405 
406 	if (*((struct sockaddr_ipx *)addr1)->sa_netnum && *((struct sockaddr_ipx *)addr2)->sa_netnum)
407 		if (memcmp(((struct sockaddr_ipx *)addr1)->sa_netnum, ((struct sockaddr_ipx *)addr2)->sa_netnum, 4) != 0)
408 			return -1;
409 	if (memcmp(((struct sockaddr_ipx *)addr1)->sa_nodenum, ((struct sockaddr_ipx *)addr2)->sa_nodenum, 6) != 0)
410 		return -1;
411 
412 	if (((struct sockaddr_ipx *)addr1)->sa_socket != ((struct sockaddr_ipx *)addr2)->sa_socket)
413 		return 1;
414 
415 	return 0;
416 }
417 
418 //=============================================================================
419 
WIPX_GetSocketPort(struct qsockaddr * addr)420 int WIPX_GetSocketPort (struct qsockaddr *addr)
421 {
422 	return ntohs(((struct sockaddr_ipx *)addr)->sa_socket);
423 }
424 
425 
WIPX_SetSocketPort(struct qsockaddr * addr,int port)426 int WIPX_SetSocketPort (struct qsockaddr *addr, int port)
427 {
428 	((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)port);
429 	return 0;
430 }
431 
432 //=============================================================================
433