]> icculus.org git repositories - btb/d2x.git/blob - unused/win95/ipx.c
utilize hardware multitexturing support if possible (requires GL_NV_texture_env_combi...
[btb/d2x.git] / unused / win95 / ipx.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: ipx.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
17 #pragma on (unreferenced)
18
19 #define WIN32_LEAN_AND_MEAN
20 #include <windows.h>
21 #include <windowsx.h>
22 #include <winsock.h>
23 #include <wsipx.h>
24
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <malloc.h>
29 #include <stdlib.h>
30 #include <conio.h>
31
32
33 #include "pstypes.h"
34 #include "winapp.h"
35 #include "ipx.h"
36 #include "error.h"
37 #include "mono.h"
38
39
40
41 //      ---------------------------------------------------------------------------
42
43 #define NUM_IPX_PACKETS 32
44
45 #define MAX_USERS               64
46 #define MAX_SUBNETS     64
47 #define MAX_PACKETS     64
48
49
50 typedef struct tIpxNetworkID {
51         BYTE b[4];
52 } tIpxNetworkID;  
53
54 typedef struct tIpxAddrGeneric { 
55         BYTE b[6]; 
56 } tIpxAddrGeneric;
57
58 typedef struct tIpxNetAddr {
59         tIpxNetworkID net_id;
60         tIpxAddrGeneric node_addr;
61         WORD ipx_socket;
62 } tIpxNetAddr;
63
64 typedef struct tIpxUserAddr {
65         tIpxNetworkID net_id;
66         tIpxAddrGeneric node_addr;
67         tIpxAddrGeneric addr;
68 } tIpxUserAddr;
69
70 typedef struct tIpxPacket {
71         tIpxNetAddr saddr;
72         tIpxNetAddr daddr;
73         int in_use;
74         int datalen;
75         int packetnum;
76         ubyte data[IPX_MAX_DATA_SIZE];
77 } tIpxPacket;
78
79
80 typedef struct tPacket {
81         int free;
82         int size;
83         int packetnum;
84         ubyte data[IPX_MAX_DATA_SIZE];
85 } tPacket;
86
87
88
89 //      ---------------------------------------------------------------------------
90 //      Data
91 // ---------------------------------------------------------------------------
92
93 static ubyte                                    ipx_installed = 0;
94 static int                                              neterrors = 0;
95
96 static int                                              NumIPXUsers = 0;
97 static tIpxUserAddr                     IPXUsers[MAX_USERS];
98
99 static int                                              NumIPXSubnet = 0;
100 static tIpxNetworkID            IPXSubnetID[MAX_SUBNETS];
101
102 static tIpxPacket                               *IPXPackets = NULL;
103 static int                                              IPXPacketNum = 0;
104
105 static SOCKET                                   WinSocket = 0;
106 static WORD                                             IPXSocket = 0;
107 static tIpxNetworkID                    ThisIPXSubnet;
108 static tIpxAddrGeneric          ThisIPXNode;
109
110 static int                                              PacketListTail, PacketListCur;
111 static tPacket                                  *PacketList;
112
113
114
115 //      ---------------------------------------------------------------------------
116 //      Function Prototypes
117 //      ---------------------------------------------------------------------------
118
119 uint wipx_init();
120 uint wipx_open_socket(int sock_num, SOCKET *sock_id, WORD *ipx_socket);
121 uint wipx_close_socket(SOCKET sock_id);
122 uint wipx_get_socket_addr(SOCKET sock_id, tIpxNetworkID *net_addr, tIpxAddrGeneric *node_addr);
123 uint wipx_set_socket_mode_bool(SOCKET sock_id, int opt, BOOL toggle);
124 uint wipx_socket_listen(SOCKET sock_id, tIpxPacket *packet);
125 uint wipx_socket_send(SOCKET sock_id, tIpxPacket *packet);
126 uint wipx_close(); 
127 uint wipx_logerror(uint ipx_result, char *text);
128
129 void got_new_packet( tIpxPacket *packet );
130 void free_packet( int id );
131 void ipx_close();
132
133 ubyte *ipx_get_my_local_address() {
134         return (ubyte *)&ThisIPXNode;
135 }
136
137 ubyte *ipx_get_my_server_address() {
138   return (ubyte *)&ThisIPXSubnet;
139 }
140
141 void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target )
142 {
143         memset(local_target, 0, 6);
144 }
145
146
147
148 //      ---------------------------------------------------------------------------
149 //      Functions
150 //      ---------------------------------------------------------------------------     
151
152 //---------------------------------------------------------------
153 // Initializes all IPX internals. 
154 // If socket_number==0, then opens next available socket.
155 // Returns:     0  if successful.
156 //                              -1 if socket already open.
157 //                              -2      if socket table full.
158 //                              -3 if IPX not installed.
159 //                              -4 if couldn't allocate memory
160 //                              -5 if error with getting internetwork address
161
162 int ipx_init(int socket_number, int show_address)
163 {
164         int i;
165         uint ipx_result;
166
167         atexit(ipx_close);
168
169 //      Establish Winsock IPX Link.
170         ipx_result = wipx_init();
171         if (ipx_result) return -3;
172
173         ipx_result = wipx_open_socket(socket_number, &WinSocket, &IPXSocket);
174         if (ipx_result) {
175                 if (ipx_result == WSAEPROTONOSUPPORT) return -3;
176                 if (ipx_result == WSAENOBUFS) return -2;
177                 return -1;
178         }
179
180 //      Get this station's IPX address.
181         ipx_result = wipx_get_socket_addr(WinSocket, &ThisIPXSubnet, &ThisIPXNode);
182         if (ipx_result) return -5;
183         NumIPXSubnet = 0;
184         memcpy(&IPXSubnetID[NumIPXSubnet++], &ThisIPXSubnet, sizeof(tIpxNetworkID));    
185
186 //      Initialize packet buffers
187         PacketList = (tPacket *)GlobalAllocPtr(GPTR, MAX_PACKETS*sizeof(tPacket));
188         if (!PacketList) 
189                 return -4;                                                              // Memory will be freed in ipx_close
190
191         for (i = 0; i < MAX_PACKETS; i++) 
192         {
193                 PacketList[i].packetnum = -1;
194                 PacketList[i].free = i;
195         }
196
197         IPXPacketNum = 0;
198         PacketListCur = 0;
199         PacketListTail = 0;
200
201 //      Setup IPX packets for packet retrieval and sending
202         IPXPackets = (tIpxPacket *)GlobalAllocPtr(GPTR, sizeof(tIpxPacket)*NUM_IPX_PACKETS);
203         if (!IPXPackets) 
204                 return -4;                                                              // Memory will be freed in ipx_close
205
206         for (i = 1; i < NUM_IPX_PACKETS; i++)
207         {
208                 IPXPackets[i].in_use = 1;
209                 wipx_socket_listen(WinSocket, &IPXPackets[i]);
210         }
211
212         IPXPackets[0].daddr.ipx_socket = htons(IPXSocket);
213         memset( &IPXPackets[0].daddr.net_id, 0, sizeof(tIpxNetworkID));
214
215         ipx_installed = 1;
216
217         return 0;
218 }       
219
220
221 void ipx_close()
222 {
223         if (WinSocket) {
224                 wipx_close_socket(WinSocket);
225                 wipx_close();
226         }
227         if (IPXPackets) {
228                 GlobalFreePtr(IPXPackets);
229                 IPXPackets = NULL;
230         }
231         if (PacketList) {
232                 GlobalFreePtr(PacketList);
233                 PacketList = NULL;
234         }
235 }
236
237
238 //      ----------------------------------------------------------------------------
239 //      Listen/Retrieve Packet Functions
240 //      ----------------------------------------------------------------------------
241
242 int ipx_get_packet_data( ubyte * data )
243 {
244         int i, n, best, best_id, size;
245
246         for (i=1; i < NUM_IPX_PACKETS; i++ )    
247         {
248                 IPXPackets[i].in_use = 1;
249                 wipx_socket_listen(WinSocket, &IPXPackets[i]);
250                 if (!IPXPackets[i].in_use) 
251                         got_new_packet(&IPXPackets[i]);                         
252         }
253
254 //      Take oldest packet from list and get data.
255         best = -1;
256         n = 0;
257         best_id = -1;
258
259         for (i=0; i <= PacketListTail; i++ )    
260         {
261                 if ( PacketList[i].packetnum > -1 ) {
262                         n++;
263                         if ((best == -1) || (PacketList[i].packetnum < best) )  {
264                                 best = PacketList[i].packetnum;
265                                 best_id = i;
266                         }
267                 }                       
268         }
269
270         if ( best_id < 0 ) return 0;
271
272         size = PacketList[best_id].size;
273         memcpy( data, PacketList[best_id].data, size );
274
275         free_packet(best_id);                                                   
276
277         return size;
278 }
279
280
281 void got_new_packet( tIpxPacket *packet )
282 {
283         int id;
284         unsigned short datasize;
285
286         datasize = 0;
287
288         if (memcmp( &packet->saddr.node_addr, &ThisIPXNode, sizeof(tIpxAddrGeneric))) {
289         // Find slot to put packet in...
290                 datasize = packet->datalen;       
291
292                 if ( datasize > 0 && datasize <= sizeof(tPacket) )      {
293                         if ( PacketListCur >= MAX_PACKETS ) {
294                                 neterrors++;
295                                 return;
296                         }               
297                         id = PacketList[PacketListCur++].free;
298                         if (id > PacketListTail ) PacketListTail = id;
299                         PacketList[id].size = datasize - sizeof(int);
300                         PacketList[id].packetnum = packet->packetnum;
301                         if (PacketList[id].packetnum < 0) { neterrors++; return; } 
302                         memcpy( PacketList[id].data, packet->data, PacketList[id].size );
303                 } else {
304                         neterrors++; return;
305                 }
306         } 
307         // Repost the ecb
308         packet->in_use = 0;
309 }
310
311
312 void free_packet( int id )
313 {
314         PacketList[id].packetnum = -1;
315         PacketList[ --PacketListCur].free = id;
316         if (PacketListTail==id) 
317                 while ((--PacketListTail>0) && (PacketList[PacketListTail].packetnum == -1 ));
318 }
319
320
321
322 //      ----------------------------------------------------------------------------
323 //      Send IPX Packet Functions
324 //      ----------------------------------------------------------------------------
325
326 void ipx_send_packet_data( ubyte * data, 
327                                 int datasize, 
328                                 ubyte *network, 
329                                 ubyte *address, 
330                                 ubyte *immediate_address )
331 {
332         Assert(ipx_installed);
333
334         if ( datasize >= IPX_MAX_DATA_SIZE )    {
335                 Error("Illegal sized IPX packet being sent.");          
336         }
337
338 // Make sure no one is already sending something
339         IPXPackets[0].packetnum = IPXPacketNum;
340         IPXPacketNum++; 
341         memcpy( &IPXPackets[0].daddr.net_id, (tIpxNetworkID *)network, 4);
342         memcpy( &IPXPackets[0].daddr.node_addr, (tIpxAddrGeneric *)address, sizeof(tIpxAddrGeneric) );
343
344 // Fill in data to send
345         Assert(datasize > 1);
346         IPXPackets[0].datalen = sizeof(int) + datasize;
347         memcpy( IPXPackets[0].data, data, datasize );
348
349 // Send it
350         IPXPackets[0].daddr.ipx_socket = htons(IPXSocket);
351         wipx_socket_send( WinSocket, &IPXPackets[0]);
352 }
353
354
355 void ipx_send_broadcast_packet_data( ubyte * data, int datasize )       
356 {
357         int i, j;
358         ubyte broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
359         tIpxAddrGeneric local_address;
360
361         wipx_set_socket_mode_bool(WinSocket, SO_BROADCAST, TRUE);
362
363 // Set to all networks besides mine
364         for (i = 0; i < NumIPXSubnet; i++ )     
365         {
366                 if (memcmp(&IPXSubnetID[i], &ThisIPXSubnet, 4)) {
367                         ipx_get_local_target( (ubyte *)&IPXSubnetID[i], 
368                                                 broadcast, 
369                                                 (ubyte*)&local_address );
370                         ipx_send_packet_data( data, datasize, 
371                                                 (ubyte *)&IPXSubnetID[i], 
372                                                 broadcast, 
373                                                 (ubyte *)&local_address );
374                 } else {
375                         ipx_send_packet_data( data, datasize, 
376                                                 (ubyte *)&IPXSubnetID[i], 
377                                                 broadcast, 
378                                                 broadcast );
379                 }
380         }
381                                                          
382 // Send directly to all users not on my network or in the network list.
383         for (i = 0; i < NumIPXUsers; i++ )      
384         {
385                 if ( memcmp( &IPXUsers[i].net_id, &ThisIPXSubnet,4 ) )  {
386                         for (j=0; j < NumIPXSubnet; j++ )               {
387                                 if (!memcmp( &IPXUsers[i].net_id, &IPXSubnetID[j], 4 ))
388                                         goto SkipUser;
389                         }
390                         ipx_send_packet_data( data, datasize, 
391                                                 (ubyte*)&IPXUsers[i].net_id, 
392                                                 (ubyte*)&IPXUsers[i].node_addr, 
393                                                 (ubyte*)&IPXUsers[i].addr );
394 SkipUser:
395                         j = 0;
396                 }
397         }
398 }
399
400
401 //      Functions Sends a non-localized packet... needs 4 byte server, 
402 //      6 byte address
403
404 void ipx_send_internetwork_packet_data( ubyte * data, int datasize, 
405                                                 ubyte * server, 
406                                                 ubyte *address )
407 {
408         tIpxAddrGeneric local_address;
409
410         if ( (*(uint *)server) != 0 )   {
411                 ipx_get_local_target( server, address, (ubyte *)&local_address );
412                 ipx_send_packet_data( data, datasize, server, address, (ubyte *)&local_address );
413         } else {
414         // Old method, no server info.
415                 ipx_send_packet_data( data, datasize, server, address, address );
416         }
417 }
418
419
420
421 //      ---------------------------------------------------------------------------
422 // Read IPX User file stuff
423 //      ---------------------------------------------------------------------------
424
425 int ipx_change_default_socket( ushort socket_number )
426 {
427         int i;
428         int result;
429         SOCKET new_socket;
430         WORD new_ipx_socket;
431
432         if ( !ipx_installed ) return -3;
433
434 // Open a new socket    
435         result = wipx_open_socket(socket_number, &new_socket, &new_ipx_socket);
436         if (result) return -2;
437         
438
439 // Close existing socket...
440         wipx_close_socket(WinSocket);
441
442         IPXSocket = new_ipx_socket;
443         WinSocket = new_socket;
444
445 // Repost all listen requests on the new socket...      
446         for (i=1; i<NUM_IPX_PACKETS; i++ )      
447         {
448                 IPXPackets[i].in_use = 0;
449                 wipx_socket_listen(WinSocket, &IPXPackets[i]);
450         }
451
452         IPXPackets[0].daddr.ipx_socket = htons(IPXSocket);
453         IPXPacketNum = 0;
454
455 // init packet buffers.
456         for (i=0; i<MAX_PACKETS; i++ )  
457         {
458                 PacketList[i].packetnum = -1;
459                 PacketList[i].free = i;
460         }
461         PacketListCur = PacketListTail = 0;
462
463         return 0;
464 }
465
466
467 void ipx_read_user_file(char * filename)
468 {
469         FILE * fp;
470         tIpxUserAddr tmp;
471         char temp_line[132], *p1;
472         int n, ln=0;
473
474         if (!filename) return;
475
476         NumIPXUsers = 0;
477
478         fp = fopen( filename, "rt" );
479         if ( !fp ) return;
480
481         printf( "Broadcast Users:\n" );
482
483         while (fgets(temp_line, 132, fp)) {
484                 ln++;
485                 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
486                 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
487                 n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.net_id.b[0], 
488                                         &tmp.net_id.b[1], &tmp.net_id.b[2], &tmp.net_id.b[3],
489                                         &tmp.node_addr.b[0], &tmp.node_addr.b[1], &tmp.node_addr.b[2],
490                                         &tmp.node_addr.b[3], &tmp.node_addr.b[4], &tmp.node_addr.b[5] );
491                 if ( n != 10 ) continue;
492                 if ( NumIPXUsers < MAX_USERS )  {
493                         ipx_get_local_target( tmp.net_id.b, tmp.node_addr.b, tmp.addr.b );
494                         IPXUsers[NumIPXUsers++] = tmp;
495
496 //                      printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
497 //                      printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] );
498                 } else {
499                         printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
500                         fclose(fp);
501                         return;
502                 }
503         }
504         fclose(fp);
505 }
506
507
508 void ipx_read_network_file(char * filename)
509 {
510         FILE * fp;
511         tIpxUserAddr tmp;
512         char temp_line[132], *p1;
513         int i, n, ln=0;
514
515         if (!filename) return;
516
517         fp = fopen( filename, "rt" );
518         if ( !fp ) return;
519
520         printf( "Using Networks:\n" );
521         for (i=0; i<NumIPXSubnet; i++ )         {
522                 ubyte * n1 = (ubyte *)IPXSubnetID[i].b;
523                 printf("* %02x%02x%02x%02x\n", n1[0], n1[1], n1[2], n1[3] );
524         }
525
526         while (fgets(temp_line, 132, fp)) {
527                 ln++;
528                 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
529                 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
530                 n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.net_id.b[0], &tmp.net_id.b[1], &tmp.net_id.b[2], &tmp.net_id.b[3] );
531                 if ( n != 4 ) continue;
532                 if ( NumIPXSubnet < MAX_SUBNETS  )      {
533                         int j;
534                         for (j=0; j<NumIPXSubnet; j++ ) 
535                                 if ( !memcmp( &IPXSubnetID[j], &tmp.net_id, 4 ) )
536                                         break;
537                         if ( j >= NumIPXSubnet )        {
538                                 memcpy( &IPXSubnetID[NumIPXSubnet++], &tmp.net_id, 4 );
539 //                              printf("  %02x%02x%02x%02x\n", &tmp.net_id.b[0], &tmp.net_id.b[1], tmp.network[2], tmp.network[3] );
540                         }
541                 } else {
542                         printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_SUBNETS );
543                         fclose(fp);
544                         return;
545                 }
546         }
547         fclose(fp);
548
549 }
550
551
552
553 //      ----------------------------------------------------------------------------
554 //      Winsock API layer
555 //      ----------------------------------------------------------------------------
556
557 uint wipx_init()
558 {
559         WSADATA version_info;
560         WORD version_requested;
561         int result;
562         
563         version_requested = MAKEWORD(2,0);
564         
565         result = WSAStartup(version_requested, &version_info);
566         if (result) {
567                 wipx_logerror(result, "wpx_init");      
568                 return result;
569         }
570                 
571         if (LOBYTE(version_requested) < 1 && HIBYTE(version_requested) < 1) {
572                 logentry("Bad version of Winsock DLL %d.%d.\n", LOBYTE(version_requested), HIBYTE(version_requested));
573                 return 0xffffffff;
574         }
575
576         return 0;
577 }
578
579
580 uint wipx_open_socket(int sock_num, SOCKET *sock_id, WORD *ipx_socket)
581 {
582         LINGER ling;
583         SOCKET s;
584         SOCKADDR_IPX ipx_addr;
585         unsigned long ioctlval;
586
587         s = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
588         if (s == INVALID_SOCKET) {
589                 *sock_id = 0;
590                 *ipx_socket = 0;
591                 wipx_logerror(s, "wipx_open_socket::socket");
592                 return INVALID_SOCKET;
593         }
594
595 //      Set hard close for sockets
596         ling.l_onoff = 1;
597         ling.l_linger = 0;
598         setsockopt(s, SOL_SOCKET, SO_LINGER, (PSTR)&ling, sizeof(ling));
599         
600         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
601         ipx_addr.sa_socket = htons(sock_num);
602         ipx_addr.sa_family = AF_IPX;
603         if (bind(s, (SOCKADDR *)&ipx_addr, sizeof(SOCKADDR_IPX)) == SOCKET_ERROR) {
604                 closesocket(s);
605                 *ipx_socket = 0;
606                 *sock_id = 0;
607                 wipx_logerror(SOCKET_ERROR, "wipx_open_socket::bind");
608                 return SOCKET_ERROR;
609         }
610         
611         ioctlval = 1;                                                           // Set socket to non-blocking mode
612         if (ioctlsocket(s, FIONBIO, &ioctlval) == SOCKET_ERROR) {
613                 closesocket(s);
614                 *ipx_socket = 0;
615                 *sock_id = 0;
616                 wipx_logerror(SOCKET_ERROR, "wipx_open_socket::ioctlsocket");
617                 return SOCKET_ERROR;
618         }
619         
620         *sock_id = s;
621         *ipx_socket = sock_num;
622
623         return 0;
624 }
625
626
627 uint wipx_close_socket(SOCKET sock_id)
628 {
629         if (closesocket(sock_id) == SOCKET_ERROR) {
630                 wipx_logerror(SOCKET_ERROR, "wipx_close_socket");
631                 return SOCKET_ERROR;
632         }
633         else return 0;
634 }
635
636
637 uint wipx_get_socket_addr(SOCKET sock_id, tIpxNetworkID *net_addr, 
638                                 tIpxAddrGeneric *node_addr)
639 {
640         SOCKADDR_IPX    ipx_addr;
641         int                             len;
642
643 //      Use getsockname to get info
644         len = sizeof(SOCKADDR_IPX);
645         if (getsockname(sock_id, (SOCKADDR *)&ipx_addr, &len) == SOCKET_ERROR) {
646                 wipx_logerror(SOCKET_ERROR, "getsockname");
647                 return SOCKET_ERROR;
648         }
649         else {
650                 memcpy(net_addr, ipx_addr.sa_netnum, 4);
651                 memcpy(node_addr, ipx_addr.sa_nodenum, 6);
652                 return 0;
653         }
654 }
655
656
657 uint wipx_set_socket_mode_bool(SOCKET sock_id, int opt, BOOL toggle)
658 {
659         if (setsockopt(sock_id, SOL_SOCKET, opt, (LPSTR)&toggle,
660                                  sizeof(toggle)) == SOCKET_ERROR) {
661                 wipx_logerror(SOCKET_ERROR, "wipx_set_socket_mode_bool");
662                 return SOCKET_ERROR;
663         }
664         return 0;
665 }
666
667
668 uint wipx_socket_listen(SOCKET sock_id, tIpxPacket *packet)
669 {
670         unsigned long ioctlval = 0;
671         int bytes, length = sizeof(SOCKADDR_IPX);
672         SOCKADDR_IPX ipx_addr;
673         
674         if (ioctlsocket(sock_id, FIONREAD, &ioctlval) == SOCKET_ERROR)  {
675                 wipx_logerror(SOCKET_ERROR, "wipx_socket_listen::ioctlsocket");
676                 return SOCKET_ERROR;
677         }
678         else if (ioctlval) {
679                 ipx_addr.sa_socket = htons(IPXSocket);
680                 ipx_addr.sa_family = AF_IPX;
681                 bytes = recvfrom(sock_id, (char *)(&packet->packetnum),
682                                         sizeof(int) + IPX_MAX_DATA_SIZE,
683                                         0,
684                                         &ipx_addr,
685                                         &length);
686                 if (bytes == SOCKET_ERROR) {
687                         wipx_logerror(SOCKET_ERROR, "wipx_socket_listen::recvfrom");
688                         return SOCKET_ERROR;
689                 }
690                 packet->in_use = 0;
691                 packet->datalen = bytes;
692                 return 0;
693         }
694         else return 0;
695 }
696
697
698 uint wipx_socket_send(SOCKET sock_id, tIpxPacket *packet)
699 {
700         SOCKADDR_IPX ipx_addr;
701         int bytes = 0;
702
703         ipx_addr.sa_socket = htons(IPXSocket);
704         ipx_addr.sa_family = AF_IPX;
705         memcpy(ipx_addr.sa_nodenum, &packet->daddr.node_addr, 6);
706         memcpy(ipx_addr.sa_netnum, &packet->daddr.net_id, 4);
707         
708 /*      logentry("Sending packet to %2X%2X%2X%2X:%2X%2X%2X%2X%2X%2X\n",
709                                 packet->daddr.net_id.b[0],
710                                 packet->daddr.net_id.b[1],
711                                 packet->daddr.net_id.b[2],
712                                 packet->daddr.net_id.b[3],
713                                 packet->daddr.node_addr.b[0],
714                                 packet->daddr.node_addr.b[1],
715                                 packet->daddr.node_addr.b[2],
716                                 packet->daddr.node_addr.b[3],
717                                 packet->daddr.node_addr.b[4],
718                                 packet->daddr.node_addr.b[5]);
719 */
720
721         bytes = sendto(sock_id, (char *)(&packet->packetnum),
722                                 packet->datalen,
723                                 0,
724                                 &ipx_addr,
725                                 sizeof(SOCKADDR_IPX));          
726         packet->in_use = 1;
727         if (bytes == SOCKET_ERROR) {
728                 wipx_logerror(SOCKET_ERROR, "wipx_socket_send::sendto");
729                 return SOCKET_ERROR;
730         }
731         else return 0;
732 }
733
734
735 uint wipx_close()
736 {
737         return WSACleanup();
738 }
739
740  
741 uint wipx_logerror(uint ipx_result, char *text)
742 {
743         logentry("%s:: error %x.\n", text, ipx_result);
744         return ipx_result;
745 }       
746