Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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_ipx.c
21
 
22
#include 
23
#include 
24
#include 
25
 
26
#include "quakedef.h"
27
#include "dosisms.h"
28
#include "net_ipx.h"
29
 
30
#define	EIO		 		5	/* I/O error */
31
 
32
#define AF_NETWARE 		64
33
 
34
#define IPX_OPEN					0
35
#define IPX_CLOSE					1
36
#define IPX_GETROUTE				2
37
#define IPX_SEND					3
38
#define IPX_LISTEN					4
39
#define IPX_SCHEDULEEVENT			5
40
#define IPX_CANCEL					6
41
#define IPX_SCHEDULESPECIALEVENT	7
42
#define IPX_GETINTERVALMARKER		8
43
#define IPX_GETADDRESS				9
44
#define IPX_RELINQUISH				10
45
 
46
#define PTYPE_UNKNOWN				0
47
#define PTYPE_RIP					1
48
#define PTYPE_ECHO					2
49
#define PTYPE_ERROR					3
50
#define PTYPE_IPX					4
51
#define PTYPE_SPX					5
52
 
53
#pragma pack(1)
54
 
55
typedef struct
56
{
57
	byte	network[4];
58
	byte	node[6];
59
	short	socket;
60
} IPXaddr;
61
 
62
struct sockaddr_ipx
63
{
64
    short			sipx_family;
65
	IPXaddr			sipx_addr;
66
    char			sipx_zero[2];
67
};
68
#define sipx_port sipx_addr.socket
69
 
70
typedef struct
71
{
72
	short			checkSum;
73
	short			length;
74
	byte			transportControl;
75
	byte			type;
76
	IPXaddr			destination;
77
	IPXaddr			source;
78
} IPXheader;
79
 
80
typedef struct ECBStructure
81
{
82
	struct ECBStructure *link;
83
	unsigned short	ESR_off;
84
	unsigned short	ESR_seg;
85
	byte	inUse;
86
	byte	completionCode;
87
	short	socket;
88
	byte	IPXWorkspace[4];
89
	byte	driverWorkspace[12];
90
	byte	immediateAddress[6];
91
	short	fragCount;
92
	short	fragOff;
93
	short	fragSeg;
94
	short	fragSize;
95
} ECB;
96
 
97
#pragma pack()
98
 
99
typedef struct
100
{
101
	ECB			ecb;
102
	IPXheader	header;
103
	int			sequence;
104
	char		data[NET_DATAGRAMSIZE];
105
} ipx_lowmem_buffer_t;
106
 
107
#define LOWMEMSIZE		(100 * 1024)
108
#define LOWMEMSAVE		256
109
#define IPXBUFFERS		((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
110
#define IPXSOCKBUFFERS	5
111
#define IPXSOCKETS		(IPXBUFFERS / IPXSOCKBUFFERS)
112
 
113
// each socket's socketbuffer 0 is used for sending, the others for listening
114
 
115
typedef struct
116
{
117
	char				reserved[LOWMEMSAVE];
118
	ipx_lowmem_buffer_t	socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
119
} ipx_lowmem_area_t;
120
 
121
 
122
static int ipxsocket[IPXSOCKETS];
123
static ECB *readlist[IPXSOCKETS];
124
static int sequence[IPXSOCKETS];
125
static int handlesInUse;
126
static ipx_lowmem_area_t *lma;
127
static char *lowmem_buffer;
128
static int lowmem_bufseg;
129
static int lowmem_bufoff;
130
static unsigned short ipx_cs;
131
static unsigned short ipx_ip;
132
static int net_acceptsocket = -1;
133
static int net_controlsocket;
134
 
135
static void IPX_PollProcedure(void);
136
static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure};
137
 
138
//=============================================================================
139
 
140
static void IPX_GetLocalAddress(IPXaddr *addr)
141
{
142
	regs.x.cs = ipx_cs;
143
	regs.x.ip = ipx_ip;
144
	regs.x.bx = IPX_GETADDRESS;
145
	regs.x.es = lowmem_bufseg;
146
	regs.x.si = lowmem_bufoff;
147
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
148
	Q_memcpy(addr, lowmem_buffer, 10);
149
}
150
 
151
//=============================================================================
152
 
153
static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget)
154
{
155
	regs.x.cs = ipx_cs;
156
	regs.x.ip = ipx_ip;
157
	regs.x.bx = IPX_GETROUTE;
158
	regs.x.es = lowmem_bufseg;
159
	regs.x.si = lowmem_bufoff;
160
	regs.x.di = lowmem_bufoff + sizeof(IPXaddr);
161
	Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr));
162
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
163
	if (regs.h.al)
164
		return -1;
165
	Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6);
166
	return 0;
167
}
168
 
169
//=============================================================================
170
 
171
static void IPX_ListenForPacket(ECB *ecb)
172
{
173
	regs.x.cs = ipx_cs;
174
	regs.x.ip = ipx_ip;
175
	regs.x.bx = IPX_LISTEN;
176
	regs.x.es = ptr2real(ecb) >> 4;
177
	regs.x.si = ptr2real(ecb) & 0xf;
178
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
179
}
180
 
181
//=============================================================================
182
 
183
static void IPX_RelinquishControl(void)
184
{
185
	regs.x.cs = ipx_cs;
186
	regs.x.ip = ipx_ip;
187
	regs.x.bx = IPX_RELINQUISH;
188
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
189
}
190
 
191
 
192
void IPX_PollProcedure(void)
193
{
194
	IPX_RelinquishControl();
195
	SchedulePollProcedure(&pollProcedure, 0.01);
196
}
197
 
198
//=============================================================================
199
 
200
static void ProcessReadyList(int s)
201
{
202
	int n;
203
	ECB *ecb;
204
	ECB *prev;
205
 
206
	for (n = 1; n < IPXSOCKBUFFERS; n++)
207
	{
208
		if (lma->socketbuffer[s][n].ecb.inUse == 0)
209
		{
210
			for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link)
211
			{
212
				if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence)
213
					break;
214
				prev = ecb;
215
			}
216
			if (ecb)
217
				lma->socketbuffer[s][n].ecb.link = ecb;
218
			else
219
				lma->socketbuffer[s][n].ecb.link = NULL;
220
			if (prev)
221
				prev->link = &lma->socketbuffer[s][n].ecb;
222
			else
223
				readlist[s] = &lma->socketbuffer[s][n].ecb;
224
			lma->socketbuffer[s][n].ecb.inUse = 0xff;
225
		}
226
	}
227
}
228
 
229
//=============================================================================
230
 
231
int IPX_Init(void)
232
{
233
	int s;
234
	int n;
235
	struct qsockaddr addr;
236
	char *colon;
237
 
238
	if (COM_CheckParm ("-noipx"))
239
		return -1;
240
 
241
	// find the IPX far call entry point
242
	regs.x.ax = 0x7a00;
243
	__dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)®s);
244
	if (regs.h.al != 0xff)
245
	{
246
		Con_Printf("IPX not detected\n");
247
		return -1;
248
	}
249
	ipx_cs = regs.x.es;
250
	ipx_ip = regs.x.di;
251
 
252
	// grab a chunk of memory down in DOS land
253
	lowmem_buffer = dos_getmemory(LOWMEMSIZE);
254
	if (!lowmem_buffer)
255
	{
256
		Con_Printf("IPX_Init: Not enough low memory\n");
257
		return -1;
258
	}
259
	lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
260
	lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
261
 
262
	// init socket handles & buffers
263
	handlesInUse = 0;
264
	lma = (ipx_lowmem_area_t *)lowmem_buffer;
265
	for (s = 0; s < IPXSOCKETS; s++)
266
	{
267
		ipxsocket[s] = 0;
268
		for (n = 0; n < IPXSOCKBUFFERS; n++)
269
		{
270
			lma->socketbuffer[s][n].ecb.link = NULL;
271
			lma->socketbuffer[s][n].ecb.ESR_off = 0;
272
			lma->socketbuffer[s][n].ecb.ESR_seg = 0;
273
			lma->socketbuffer[s][n].ecb.socket = 0;
274
			lma->socketbuffer[s][n].ecb.inUse = 0xff;
275
			lma->socketbuffer[s][n].ecb.completionCode = 0;
276
			lma->socketbuffer[s][n].ecb.fragCount = 1;
277
			lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf;
278
			lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4;
279
			lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
280
		}
281
	}
282
 
283
	if ((net_controlsocket = IPX_OpenSocket (0)) == -1)
284
	{
285
		dos_freememory(lowmem_buffer);
286
		Con_DPrintf ("IPX_Init: Unable to open control socket\n");
287
		return -1;
288
	}
289
 
290
	SchedulePollProcedure(&pollProcedure, 0.01);
291
 
292
	IPX_GetSocketAddr (net_controlsocket, &addr);
293
	Q_strcpy(my_ipx_address,  IPX_AddrToString (&addr));
294
	colon = Q_strrchr (my_ipx_address, ':');
295
	if (colon)
296
		*colon = 0;
297
 
298
	Con_Printf("IPX initialized\n");
299
	ipxAvailable = true;
300
	return net_controlsocket;
301
}
302
 
303
//=============================================================================
304
 
305
void IPX_Shutdown(void)
306
{
307
	IPX_Listen (false);
308
	IPX_CloseSocket (net_controlsocket);
309
	dos_freememory(lowmem_buffer);
310
}
311
 
312
//=============================================================================
313
 
314
void IPX_Listen (qboolean state)
315
{
316
	// enable listening
317
	if (state)
318
	{
319
		if (net_acceptsocket != -1)
320
			return;
321
		if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
322
			Sys_Error ("IPX_Listen: Unable to open accept socket\n");
323
		return;
324
	}
325
 
326
	// disable listening
327
	if (net_acceptsocket == -1)
328
		return;
329
	IPX_CloseSocket (net_acceptsocket);
330
	net_acceptsocket = -1;
331
}
332
 
333
//=============================================================================
334
 
335
int IPX_OpenSocket(int port)
336
{
337
	int handle;
338
	int n;
339
	unsigned short socket;
340
 
341
	if (handlesInUse == IPXSOCKETS)
342
		return -1;
343
 
344
	// open the IPX socket
345
	regs.x.cs = ipx_cs;
346
	regs.x.ip = ipx_ip;
347
	regs.x.bx = IPX_OPEN;
348
	regs.h.al = 0;
349
	regs.x.dx = htons(port);
350
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
351
	if (regs.h.al == 0xfe)
352
	{
353
		Con_DPrintf("IPX_OpenSocket: all sockets in use\n");
354
		return -1;
355
	}
356
	if (regs.h.al == 0xff)
357
	{
358
		Con_DPrintf("IPX_OpenSocket: socket already open\n");
359
		return -1;
360
	}
361
	if (regs.h.al != 0)
362
	{
363
		Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al);
364
		return -1;
365
	}
366
	socket = regs.x.dx;
367
 
368
// grab a handle; fill in the ECBs, and get them listening
369
	for (handle = 0; handle < IPXSOCKETS; handle++)
370
	{
371
		if (ipxsocket[handle] == 0)
372
		{
373
			ipxsocket[handle] = socket;
374
			readlist[handle] = NULL;
375
			sequence[handle] = 0;
376
			for (n = 0; n < IPXSOCKBUFFERS; n ++)
377
			{
378
				lma->socketbuffer[handle][n].ecb.socket = socket;
379
				lma->socketbuffer[handle][n].ecb.inUse = 0;
380
				if (n)
381
					IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb);
382
			}
383
			handlesInUse++;
384
			return handle;
385
		}
386
	}
387
 
388
	// "this will NEVER happen"
389
	Sys_Error("IPX_OpenSocket: handle allocation failed\n");
390
	return -1;
391
}
392
 
393
//=============================================================================
394
 
395
int IPX_CloseSocket(int handle)
396
{
397
	// if there's a send in progress, give it one last chance
398
	if (lma->socketbuffer[handle][0].ecb.inUse != 0)
399
		IPX_RelinquishControl();
400
 
401
	// close the socket (all pending sends/received are cancelled)
402
	regs.x.cs = ipx_cs;
403
	regs.x.ip = ipx_ip;
404
	regs.x.bx = IPX_CLOSE;
405
	regs.x.dx = ipxsocket[handle];
406
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
407
 
408
	ipxsocket[handle] = 0;
409
	handlesInUse--;
410
 
411
	return 0;
412
}
413
 
414
//=============================================================================
415
 
416
int IPX_Connect (int handle, struct qsockaddr *addr)
417
{
418
	IPXaddr ipxaddr;
419
 
420
	Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
421
	if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
422
	{
423
		Con_Printf("Get Local Target failed\n");
424
		return -1;
425
	}
426
 
427
	return 0;
428
}
429
 
430
//=============================================================================
431
 
432
int IPX_CheckNewConnections (void)
433
{
434
	int n;
435
 
436
	if (net_acceptsocket == -1)
437
		return -1;
438
 
439
	for (n = 1; n < IPXSOCKBUFFERS; n ++)
440
		if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
441
			return net_acceptsocket;
442
	return -1;
443
}
444
 
445
//=============================================================================
446
 
447
int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
448
{
449
	ECB		*ecb;
450
	ipx_lowmem_buffer_t *rcvbuf;
451
	int		copylen;
452
 
453
	ProcessReadyList(handle);
454
tryagain:
455
	if (readlist[handle] == NULL)
456
		return 0;
457
	ecb = readlist[handle];
458
	readlist[handle] = ecb->link;
459
 
460
	if (ecb->completionCode != 0)
461
	{
462
		Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode);
463
		ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
464
		IPX_ListenForPacket(ecb);
465
		goto tryagain;
466
	}
467
 
468
	rcvbuf = (ipx_lowmem_buffer_t *)ecb;
469
 
470
	// copy the data up to the buffer
471
	copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader));
472
	if (len < copylen)
473
		Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen);
474
	Q_memcpy(buf, rcvbuf->data, copylen);
475
 
476
	// fill in the addr if they want it
477
	if (addr)
478
	{
479
		((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE;
480
		Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr));
481
		((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0;
482
		((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0;
483
	}
484
 
485
	// update the send ecb's immediate address
486
	Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6);
487
 
488
	// get this ecb listening again
489
	rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
490
	IPX_ListenForPacket(&rcvbuf->ecb);
491
	return copylen;
492
}
493
 
494
//=============================================================================
495
 
496
int IPX_Broadcast (int handle, byte *buf, int len)
497
{
498
	struct sockaddr_ipx addr;
499
	int ret;
500
 
501
	Q_memset(addr.sipx_addr.network, 0x00, 4);
502
	Q_memset(addr.sipx_addr.node, 0xff, 6);
503
	addr.sipx_port = htons(net_hostport);
504
	Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
505
	ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr);
506
	return ret;
507
}
508
 
509
//=============================================================================
510
 
511
int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
512
{
513
	// has the previous send completed?
514
	while (lma->socketbuffer[handle][0].ecb.inUse != 0)
515
		IPX_RelinquishControl();
516
 
517
	switch (lma->socketbuffer[handle][0].ecb.completionCode)
518
	{
519
		case 0x00: // success
520
		case 0xfc: // request cancelled
521
			break;
522
 
523
		case 0xfd: // malformed packet
524
		default:
525
			Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode);
526
			break;
527
 
528
		case 0xfe: // packet undeliverable
529
		case 0xff: // unable to send packet
530
			Con_Printf("IPX lost route, trying to re-establish\n");
531
 
532
			// look for a new route
533
			if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
534
				return -1;
535
 
536
			// re-send the one that failed
537
			regs.x.cs = ipx_cs;
538
			regs.x.ip = ipx_ip;
539
			regs.x.bx = IPX_SEND;
540
			regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
541
			regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
542
			__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
543
 
544
			// report that we did not send the current one
545
			return 0;
546
	}
547
 
548
	// ecb : length
549
	lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len;
550
 
551
	// ipx header : type
552
	lma->socketbuffer[handle][0].header.type = PTYPE_IPX;
553
 
554
	// ipx header : destination
555
	Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
556
 
557
	// sequence number
558
	lma->socketbuffer[handle][0].sequence = sequence[handle];
559
	sequence[handle]++;
560
 
561
	// copy down the data
562
	Q_memcpy(lma->socketbuffer[handle][0].data, buf, len);
563
 
564
	regs.x.cs = ipx_cs;
565
	regs.x.ip = ipx_ip;
566
	regs.x.bx = IPX_SEND;
567
	regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
568
	regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
569
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s);
570
 
571
	return len;
572
}
573
 
574
//=============================================================================
575
 
576
char *IPX_AddrToString (struct qsockaddr *addr)
577
{
578
	static char buf[28];
579
 
580
	sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
581
		((struct sockaddr_ipx *)addr)->sipx_addr.network[0],
582
		((struct sockaddr_ipx *)addr)->sipx_addr.network[1],
583
		((struct sockaddr_ipx *)addr)->sipx_addr.network[2],
584
		((struct sockaddr_ipx *)addr)->sipx_addr.network[3],
585
		((struct sockaddr_ipx *)addr)->sipx_addr.node[0],
586
		((struct sockaddr_ipx *)addr)->sipx_addr.node[1],
587
		((struct sockaddr_ipx *)addr)->sipx_addr.node[2],
588
		((struct sockaddr_ipx *)addr)->sipx_addr.node[3],
589
		((struct sockaddr_ipx *)addr)->sipx_addr.node[4],
590
		((struct sockaddr_ipx *)addr)->sipx_addr.node[5],
591
		ntohs(((struct sockaddr_ipx *)addr)->sipx_port)
592
		);
593
	return buf;
594
}
595
 
596
//=============================================================================
597
 
598
int IPX_StringToAddr (char *string, struct qsockaddr *addr)
599
{
600
	int  val;
601
	char buf[3];
602
 
603
	buf[2] = 0;
604
	Q_memset(addr, 0, sizeof(struct qsockaddr));
605
	addr->sa_family = AF_NETWARE;
606
 
607
#define DO(src,dest)	\
608
	buf[0] = string[src];	\
609
	buf[1] = string[src + 1];	\
610
	if (sscanf (buf, "%x", &val) != 1)	\
611
		return -1;	\
612
	((struct sockaddr_ipx *)addr)->sipx_addr.dest = val
613
 
614
	DO(0, network[0]);
615
	DO(2, network[1]);
616
	DO(4, network[2]);
617
	DO(6, network[3]);
618
	DO(9, node[0]);
619
	DO(11, node[1]);
620
	DO(13, node[2]);
621
	DO(15, node[3]);
622
	DO(17, node[4]);
623
	DO(19, node[5]);
624
#undef DO
625
 
626
	sscanf (&string[22], "%u", &val);
627
	((struct sockaddr_ipx *)addr)->sipx_port = htons(val);
628
 
629
	return 0;
630
}
631
 
632
//=============================================================================
633
 
634
int IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
635
{
636
	Q_memset(addr, 0, sizeof(struct qsockaddr));
637
	addr->sa_family = AF_NETWARE;
638
	IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr);
639
	((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle];
640
	return 0;
641
}
642
 
643
//=============================================================================
644
 
645
int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
646
{
647
	Q_strcpy(name, IPX_AddrToString(addr));
648
	return 0;
649
}
650
 
651
//=============================================================================
652
 
653
int IPX_GetAddrFromName (char *name, struct qsockaddr *addr)
654
{
655
	int n;
656
	char buf[32];
657
 
658
	n = Q_strlen(name);
659
 
660
	if (n == 12)
661
	{
662
		sprintf(buf, "00000000:%s:%u", name, net_hostport);
663
		return IPX_StringToAddr (buf, addr);
664
	}
665
	if (n == 21)
666
	{
667
		sprintf(buf, "%s:%u", name, net_hostport);
668
		return IPX_StringToAddr (buf, addr);
669
	}
670
	if (n > 21 && n <= 27)
671
		return IPX_StringToAddr (name, addr);
672
 
673
	return -1;
674
}
675
 
676
//=============================================================================
677
 
678
int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
679
{
680
	if (addr1->sa_family != addr2->sa_family)
681
		return -1;
682
 
683
	if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10))
684
		return -1;
685
 
686
	if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port)
687
		return 1;
688
 
689
	return 0;
690
}
691
 
692
//=============================================================================
693
 
694
int IPX_GetSocketPort (struct qsockaddr *addr)
695
{
696
	return ntohs(((struct sockaddr_ipx *)addr)->sipx_port);
697
}
698
 
699
 
700
int IPX_SetSocketPort (struct qsockaddr *addr, int port)
701
{
702
	((struct sockaddr_ipx *)addr)->sipx_port = htons(port);
703
	return 0;
704
}
705
 
706
//=============================================================================