home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / bios / ipx.c < prev    next >
Text File  |  1998-06-08  |  26KB  |  883 lines

  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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/bios/rcs/ipx.c $
  15.  * $Revision: 2.10 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/29 17:27:55 $
  18.  * 
  19.  * Routines for IPX communications.
  20.  * 
  21.  * $Log: ipx.c $
  22.  * Revision 2.10  1995/03/29  17:27:55  john
  23.  * Added code to not duplicate broadcasts.
  24.  * 
  25.  * Revision 2.9  1995/03/29  15:32:07  john
  26.  * NEatened.
  27.  * 
  28.  * Revision 2.8  1995/03/29  15:07:31  john
  29.  * Added network support.
  30.  * 
  31.  * Revision 2.7  1995/03/29  11:22:27  john
  32.  * Added broadcasting over a net.
  33.  * 
  34.  * Revision 2.6  1995/03/28  20:05:03  john
  35.  * Took away alternate server stuff.
  36.  * 
  37.  * Revision 2.5  1995/03/23  19:14:29  john
  38.  * Added better MAX_USERS message.
  39.  * 
  40.  * Revision 2.4  1995/03/23  19:00:02  john
  41.  * Added user list capabitly.
  42.  * 
  43.  * Revision 2.3  1995/03/23  12:27:05  john
  44.  * Move IPX into bios lib.
  45.  * 
  46.  * Revision 2.2  1995/03/22  19:08:15  john
  47.  * Added code to fix sending packets over router... now
  48.  * we just need to make broadcasts go over router!!
  49.  * 
  50.  * Revision 2.1  1995/03/21  08:40:16  john
  51.  * Ifdef'd out the NETWORK code.
  52.  * 
  53.  * Revision 2.0  1995/02/27  11:30:45  john
  54.  * New version 2.0, which has no anonymous unions, builds with
  55.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  56.  * 
  57.  * Revision 1.31  1995/02/16  17:35:03  john
  58.  * Added code to allow dynamic socket changing.
  59.  * 
  60.  * Revision 1.30  1995/02/01  21:03:45  john
  61.  * Lintified.
  62.  * 
  63.  * Revision 1.29  1995/01/22  14:31:05  john
  64.  * Added key.h
  65.  * 
  66.  * Revision 1.28  1995/01/22  14:29:26  john
  67.  * Added code to bypass broadcast messages.
  68.  * 
  69.  * Revision 1.27  1995/01/03  13:46:16  john
  70.  * Added code that should make ipx work over different servers,
  71.  * but ifdef'd it out with SHAREWARE in ipx.c.  I haven't tested
  72.  * this, and I hope it doesn't introduce net bugs.
  73.  * 
  74.  * Revision 1.26  1994/12/14  11:54:37  rob
  75.  * Reduce # of ipx packets.
  76.  * 
  77.  * Revision 1.25  1994/12/11  00:43:28  john
  78.  * Locked down DOS ipx buffers... probably not necessary, tho.
  79.  * 
  80.  * Revision 1.24  1994/12/08  15:49:58  rob
  81.  * Bumped up the # of ipx packets.
  82.  * 
  83.  * Revision 1.23  1994/12/04  15:23:54  rob
  84.  * Reduced packet # constants.
  85.  * 
  86.  * Revision 1.22  1994/11/27  23:12:39  matt
  87.  * Made changes for new mprintf calling convention
  88.  * 
  89.  * Revision 1.21  1994/11/19  15:15:19  mike
  90.  * remove unused code and data
  91.  * 
  92.  * Revision 1.20  1994/11/10  11:06:07  rob
  93.  * Raised number of ipx packets to 64 and buffers to 128 (for 8-way games)
  94.  * Removed (commented out) all the spx support stuff.
  95.  * 
  96.  * Revision 1.19  1994/11/07  17:50:12  rob
  97.  * Bumped up max_packets and ipx_num_packets to double their previous
  98.  * values.
  99.  * 
  100.  * Revision 1.18  1994/11/07  15:39:01  rob
  101.  * Removed temporary hacked ipx_send_object function.
  102.  * Replaced with a more general thing.
  103.  * 
  104.  * Revision 1.17  1994/11/05  16:08:40  rob
  105.  * Made a change necessary for object syncing on rejoin.
  106.  * 
  107.  * Revision 1.16  1994/11/01  15:57:12  rob
  108.  * Added support for SPX sockets for critical messages.
  109.  * 
  110.  * Revision 1.15  1994/10/31  19:21:01  rob
  111.  * Added a routine for sending objects via ipx.  Its a hack and shoukld
  112.  * be replaced by something more general time permitting.
  113.  * 
  114.  * Revision 1.14  1994/10/20  14:57:42  john
  115.  * Some test stuff.
  116.  * 
  117.  * Revision 1.13  1994/10/20  11:22:45  john
  118.  * Tweaked the number of waiting packets. Added code to print 
  119.  * total packets missed, and to limit the packet send rate to
  120.  * 10 packets per second unless firing.
  121.  * 
  122.  * Revision 1.12  1994/10/03  20:50:11  john
  123.  * Started adding sound pause functions.
  124.  * 
  125.  * Revision 1.11  1994/09/15  08:54:24  mike
  126.  * comment out a mprintf.
  127.  * 
  128.  * Revision 1.10  1994/09/12  19:38:20  john
  129.  * Made some stuff that prints to the DOS screen go to the
  130.  * mono instead, since it really is debugging info.
  131.  * 
  132.  * Revision 1.9  1994/09/07  13:32:03  john
  133.  * Made ipx_close explicitly close the socket we were using,
  134.  * because it seems that VLM's don't automatically close them
  135.  * like the older NETX stuff did (Going from Novell 3.11 driver
  136.  * to 3.12 anyway).
  137.  * 
  138.  * Revision 1.8  1994/09/06  19:29:20  john
  139.  * Added trial version of rejoin function.
  140.  * 
  141.  * Revision 1.7  1994/08/09  19:31:50  john
  142.  * Networking changes.
  143.  * 
  144.  * Revision 1.6  1994/08/05  16:11:41  john
  145.  * Psuedo working version of networking.
  146.  * 
  147.  * Revision 1.5  1994/08/04  19:17:21  john
  148.  * Inbetween version of network stuff.
  149.  * 
  150.  * Revision 1.4  1994/07/29  16:08:57  john
  151.  * *** empty log message ***
  152.  * 
  153.  * Revision 1.3  1994/07/25  12:33:31  john
  154.  * Network "pinging" in.
  155.  * 
  156.  * Revision 1.2  1994/07/20  15:58:28  john
  157.  * First installment of ipx stuff.
  158.  * 
  159.  * Revision 1.1  1994/07/19  15:42:00  john
  160.  * Initial revision
  161.  * 
  162.  * 
  163.  */
  164.  
  165.  
  166. #pragma off (unreferenced)
  167. static char rcsid[] = "$Id: ipx.c 2.10 1995/03/29 17:27:55 john Exp $";
  168. #pragma on (unreferenced)
  169.  
  170. #include <i86.h>
  171. #include <dos.h>
  172. #include <stdio.h>
  173. #include <string.h>
  174. #include <malloc.h>
  175. #include <stdlib.h>
  176. #include <conio.h>
  177. #include <assert.h>
  178.  
  179. #include "types.h"
  180. #include "timer.h"
  181. #include "ipx.h"
  182. #include "error.h"
  183. #include "dpmi.h"
  184. #include "key.h"
  185.  
  186. typedef unsigned char BYTE;
  187. typedef unsigned short WORD;
  188. typedef unsigned long DWORD;
  189.  
  190. typedef struct local_address {
  191.     ubyte address[6];
  192. } local_address;
  193.  
  194. typedef struct net_address {
  195.     BYTE                network_id[4];            
  196.     local_address    node_id;
  197.     WORD                socket_id;
  198. } net_address;
  199.  
  200. typedef struct ipx_header {
  201.     WORD            checksum;
  202.     WORD            length;
  203.     BYTE            transport_control;
  204.     BYTE            packet_type;
  205.     net_address    destination;
  206.     net_address    source;
  207. } ipx_header;
  208.  
  209. typedef struct ecb_header {
  210.     WORD            link[2];
  211.     WORD            esr_address[2];
  212.     BYTE            in_use;
  213.     BYTE            completion_code;
  214.     WORD            socket_id;
  215.     BYTE            ipx_reserved[14];        
  216.     WORD            connection_id;
  217.     local_address immediate_address;
  218.     WORD            fragment_count;
  219.     WORD            fragment_pointer[2];
  220.     WORD            fragment_size;
  221. } ecb_header;
  222.  
  223. typedef struct packet_data {
  224.     int            packetnum;
  225.     byte            data[IPX_MAX_DATA_SIZE];
  226. } packet_data;
  227.  
  228. typedef struct ipx_packet {
  229.     ecb_header    ecb;
  230.     ipx_header    ipx;
  231.     packet_data    pd;
  232. } ipx_packet;
  233.  
  234. typedef struct user_address {
  235.     ubyte network[4];
  236.     ubyte node[6];
  237.     ubyte address[6];
  238. } user_address;
  239.  
  240. #define MAX_USERS 64
  241. int Ipx_num_users = 0;
  242. user_address Ipx_users[MAX_USERS];
  243.  
  244. #define MAX_NETWORKS 64
  245. int Ipx_num_networks = 0;
  246. uint Ipx_networks[MAX_NETWORKS];
  247.  
  248. int ipx_packetnum = 0;
  249.  
  250. #define MAX_PACKETS 64
  251.  
  252. static packet_data packet_buffers[MAX_PACKETS];
  253. static short packet_free_list[MAX_PACKETS];
  254. static int num_packets = 0;
  255. static int largest_packet_index = 0;
  256. static short packet_size[MAX_PACKETS];
  257.  
  258. WORD ipx_socket=0;
  259. ubyte ipx_installed=0;
  260. WORD ipx_vector_segment;
  261. WORD ipx_vector_offset;
  262. ubyte ipx_socket_life = 0;     // 0=closed at prog termination, 0xff=closed when requested.
  263. DWORD ipx_network = 0;
  264. local_address ipx_my_node;
  265. WORD ipx_num_packets=32;        // 32 Ipx packets
  266. ipx_packet * packets;
  267. int neterrors = 0;
  268. ushort ipx_packets_selector;
  269.  
  270. ecb_header * last_ecb=NULL;
  271. int lastlen=0;
  272.  
  273. void free_packet( int id )
  274. {
  275.     packet_buffers[id].packetnum = -1;
  276.     packet_free_list[ --num_packets ] = id;
  277.     if (largest_packet_index==id)    
  278.         while ((--largest_packet_index>0) && (packet_buffers[largest_packet_index].packetnum == -1 ));
  279. }
  280.  
  281. int ipx_get_packet_data( ubyte * data )
  282. {
  283.     int i, n, best, best_id, size;
  284.  
  285.     for (i=1; i<ipx_num_packets; i++ )    {
  286.         if ( !packets[i].ecb.in_use )    {
  287.             got_new_packet( &packets[i].ecb );
  288.             packets[i].ecb.in_use = 0;
  289.             ipx_listen_for_packet(&packets[i].ecb);
  290.         }            
  291.     }
  292.  
  293.     best = -1;
  294.     n = 0;
  295.     best_id = -1;
  296.  
  297.     for (i=0; i<=largest_packet_index; i++ )    {
  298.         if ( packet_buffers[i].packetnum > -1 ) {
  299.             n++;
  300.             if ( best == -1 || (packet_buffers[i].packetnum<best) )    {
  301.                 best = packet_buffers[i].packetnum;
  302.                 best_id = i;
  303.             }
  304.         }            
  305.     }
  306.  
  307.     //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
  308.     //mprintf( (1, "<%d> ", neterrors ));
  309.  
  310.     if ( best_id < 0 ) return 0;
  311.  
  312.     size = packet_size[best_id];
  313.     memcpy( data, packet_buffers[best_id].data, size );
  314.     free_packet(best_id);
  315.  
  316.     return size;
  317. }
  318.  
  319. unsigned int swap_short( unsigned int short );
  320. #pragma aux swap_short parm [eax] = "xchg al,ah";
  321.  
  322. void got_new_packet( ecb_header * ecb )
  323. {
  324.     ipx_packet * p;
  325.     int id;
  326.     unsigned short datasize;
  327.  
  328.     datasize = 0;
  329.     last_ecb = ecb;
  330.     p = (ipx_packet *)ecb;
  331.  
  332.     if ( p->ecb.in_use ) { neterrors++; return; }
  333.     if    ( p->ecb.completion_code )    { neterrors++; return; }
  334.  
  335.     //    Error( "Recieve error %d for completion code", p->ecb.completion_code );
  336.     
  337.     if ( memcmp( &p->ipx.source.node_id, &ipx_my_node, 6 ) )    {
  338.         datasize=swap_short(p->ipx.length);
  339.         lastlen=datasize;
  340.         datasize -= sizeof(ipx_header);
  341.         // Find slot to put packet in...
  342.         if ( datasize > 0 && datasize <= sizeof(packet_data) )    {
  343.             if ( num_packets >= MAX_PACKETS ) {
  344.                 //printf( 1, "IPX: Packet buffer overrun!!!\n" );
  345.                 neterrors++;
  346.                 return;
  347.             }        
  348.             id = packet_free_list[ num_packets++ ];
  349.             if (id > largest_packet_index ) largest_packet_index = id;
  350.             packet_size[id] = datasize-sizeof(int);
  351.             packet_buffers[id].packetnum =  p->pd.packetnum;
  352.             if ( packet_buffers[id].packetnum < 0 ) { neterrors++; return; }
  353.             memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] );
  354.         } else {
  355.             neterrors++; return;
  356.         }
  357.     } 
  358.     // Repost the ecb
  359.     p->ecb.in_use = 0;
  360.     //ipx_listen_for_packet(&p->ecb);
  361. }
  362.  
  363. ubyte * ipx_get_my_local_address()
  364. {
  365.     return ipx_my_node.address;
  366. }
  367.  
  368. ubyte * ipx_get_my_server_address()
  369. {
  370.     return (ubyte *)&ipx_network;
  371. }
  372.  
  373. void ipx_listen_for_packet(ecb_header * ecb )    
  374. {
  375.     dpmi_real_regs rregs;
  376.     ecb->in_use = 0x1d;
  377.     memset(&rregs,0,sizeof(dpmi_real_regs));
  378.     rregs.ebx = 4;    // Listen For Packet function
  379.     rregs.esi = DPMI_real_offset(ecb);
  380.     rregs.es = DPMI_real_segment(ecb);
  381.     dpmi_real_int386x( 0x7A, &rregs );
  382. }
  383.  
  384. void ipx_cancel_listen_for_packet(ecb_header * ecb )    
  385. {
  386.     dpmi_real_regs rregs;
  387.     memset(&rregs,0,sizeof(dpmi_real_regs));
  388.     rregs.ebx = 6;    // IPX Cancel event
  389.     rregs.esi = DPMI_real_offset(ecb);
  390.     rregs.es = DPMI_real_segment(ecb);
  391.     dpmi_real_int386x( 0x7A, &rregs );
  392. }
  393.  
  394.  
  395. void ipx_send_packet(ecb_header * ecb )    
  396. {
  397.     dpmi_real_regs rregs;
  398.     memset(&rregs,0,sizeof(dpmi_real_regs));
  399.     rregs.ebx = 3;    // Send Packet function
  400.     rregs.esi = DPMI_real_offset(ecb);
  401.     rregs.es = DPMI_real_segment(ecb);
  402.     dpmi_real_int386x( 0x7A, &rregs );
  403. }
  404.  
  405. typedef struct {
  406.     ubyte     network[4];
  407.     ubyte        node[6];
  408.     ubyte        local_target[6];
  409. } net_xlat_info;
  410.  
  411. void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target )
  412. {
  413.     net_xlat_info * info;
  414.     dpmi_real_regs rregs;
  415.         
  416.     // Get dos memory for call...
  417.     info = (net_xlat_info *)dpmi_get_temp_low_buffer( sizeof(net_xlat_info) );    
  418.     assert( info != NULL );
  419.     memcpy( info->network, server, 4 );
  420.     memcpy( info->node, node, 6 );
  421.     
  422.     memset(&rregs,0,sizeof(dpmi_real_regs));
  423.  
  424.     rregs.ebx = 2;        // Get Local Target    
  425.     rregs.es = DPMI_real_segment(info);
  426.     rregs.esi = DPMI_real_offset(info->network);
  427.     rregs.edi = DPMI_real_offset(info->local_target);
  428.  
  429.     dpmi_real_int386x( 0x7A, &rregs );
  430.  
  431.     // Save the local target...
  432.     memcpy( local_target, info->local_target, 6 );
  433. }
  434.  
  435. void ipx_close()
  436. {
  437.     dpmi_real_regs rregs;
  438.     if ( ipx_installed )    {
  439.         // When using VLM's instead of NETX, the sockets don't
  440.         // seem to automatically get closed, so we must explicitly
  441.         // close them at program termination.
  442.         ipx_installed = 0;
  443.         memset(&rregs,0,sizeof(dpmi_real_regs));
  444.         rregs.edx = ipx_socket;
  445.         rregs.ebx = 1;    // Close socket
  446.         dpmi_real_int386x( 0x7A, &rregs );
  447.     }
  448. }
  449.  
  450.  
  451. //---------------------------------------------------------------
  452. // Initializes all IPX internals. 
  453. // If socket_number==0, then opens next available socket.
  454. // Returns:    0  if successful.
  455. //                -1 if socket already open.
  456. //                -2    if socket table full.
  457. //                -3 if IPX not installed.
  458. //                -4 if couldn't allocate low dos memory
  459. //                -5 if error with getting internetwork address
  460.  
  461. int ipx_init( int socket_number, int show_address )
  462. {
  463.     dpmi_real_regs rregs;
  464.     ubyte *ipx_real_buffer;
  465.     int i;
  466.  
  467.     atexit(ipx_close);
  468.  
  469.     ipx_packetnum = 0;
  470.  
  471.     // init packet buffers.
  472.     for (i=0; i<MAX_PACKETS; i++ )    {
  473.         packet_buffers[i].packetnum = -1;
  474.         packet_free_list[i] = i;
  475.     }
  476.     num_packets = 0;
  477.     largest_packet_index = 0;
  478.  
  479.     // Get the IPX vector
  480.     memset(&rregs,0,sizeof(dpmi_real_regs));
  481.     rregs.eax=0x00007a00;
  482.     dpmi_real_int386x( 0x2f, &rregs );
  483.  
  484.     if ( (rregs.eax & 0xFF) != 0xFF )    {
  485.         return 3;   
  486.     }
  487.     ipx_vector_offset = rregs.edi & 0xFFFF;
  488.     ipx_vector_segment = rregs.es;
  489.     //printf( "IPX entry point at %.4x:%.4x\n", ipx_vector_segment, ipx_vector_offset );
  490.  
  491.     // Open a socket for IPX
  492.  
  493.     memset(&rregs,0,sizeof(dpmi_real_regs));
  494.     swab( (char *)&socket_number,(char *)&ipx_socket, 2 );
  495.     rregs.edx = ipx_socket;
  496.     rregs.eax = ipx_socket_life;
  497.     rregs.ebx = 0;    // Open socket
  498.     dpmi_real_int386x( 0x7A, &rregs );
  499.     
  500.     ipx_socket = rregs.edx & 0xFFFF;
  501.     
  502.     if ( rregs.eax & 0xFF )    {
  503.         //mprintf( (1, "IPX error opening channel %d\n", socket_number-IPX_DEFAULT_SOCKET ));
  504.         return -2;
  505.     }
  506.     
  507.     ipx_installed = 1;
  508.  
  509.     // Find our internetwork address
  510.     ipx_real_buffer = dpmi_get_temp_low_buffer( 1024 );    // 1k block
  511.     if ( ipx_real_buffer == NULL )    {
  512.         //printf( "Error allocation realmode memory\n" );
  513.         return -4;
  514.     }
  515.  
  516.     memset(&rregs,0,sizeof(dpmi_real_regs));
  517.     rregs.ebx = 9;        // Get internetwork address
  518.     rregs.esi = DPMI_real_offset(ipx_real_buffer);
  519.     rregs.es = DPMI_real_segment(ipx_real_buffer);
  520.     dpmi_real_int386x( 0x7A, &rregs );
  521.  
  522.     if ( rregs.eax & 0xFF )    {
  523.         //printf( "Error getting internetwork address!\n" );
  524.         return -2;
  525.     }
  526.  
  527.     memcpy( &ipx_network, ipx_real_buffer, 4 );
  528.     memcpy( &ipx_my_node, &ipx_real_buffer[4], 6 );
  529.  
  530.     Ipx_num_networks = 0;
  531.     memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 );
  532.  
  533.     if ( show_address )    {
  534.         printf( "My IPX addresss is " );
  535.         printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
  536.         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] );
  537.         printf( "\n" );
  538.     }
  539.  
  540.     packets = dpmi_real_malloc( sizeof(ipx_packet)*ipx_num_packets, &ipx_packets_selector );
  541.     if ( packets == NULL )    {
  542.         //printf( "Couldn't allocate real memory for %d packets\n", ipx_num_packets );
  543.         return -4;
  544.     }
  545.     if (!dpmi_lock_region( packets, sizeof(ipx_packet)*ipx_num_packets ))    {
  546.         //printf( "Couldn't lock real memory for %d packets\n", ipx_num_packets );
  547.         return -4;
  548.     }
  549.     memset( packets, 0, sizeof(ipx_packet)*ipx_num_packets );
  550.  
  551.     for (i=1; i<ipx_num_packets; i++ )    {
  552.         packets[i].ecb.in_use = 0x1d;
  553.         //packets[i].ecb.in_use = 0;
  554.         packets[i].ecb.socket_id = ipx_socket;
  555.         packets[i].ecb.fragment_count = 1;
  556.         packets[i].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[i].ipx);
  557.         packets[i].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[i].ipx);
  558.         packets[i].ecb.fragment_size = sizeof(ipx_packet)-sizeof(ecb_header);            //-sizeof(ecb_header);
  559.  
  560.         ipx_listen_for_packet(&packets[i].ecb);
  561.     }
  562.  
  563.     packets[0].ecb.socket_id = ipx_socket;
  564.     packets[0].ecb.fragment_count = 1;
  565.     packets[0].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[0].ipx);
  566.     packets[0].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[0].ipx);
  567.     packets[0].ipx.packet_type = 4;        // IPX packet
  568.     packets[0].ipx.destination.socket_id = ipx_socket;
  569. //    memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 );
  570.     memset( packets[0].ipx.destination.network_id, 0, 4 );
  571.  
  572.     return 0;
  573. }
  574.  
  575. void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address )
  576. {
  577.     assert(ipx_installed);
  578.  
  579.     if ( datasize >= IPX_MAX_DATA_SIZE )    {
  580.         printf( "Data too big\n" );
  581.         exit(1);
  582.     }
  583.  
  584.     // Make sure no one is already sending something
  585.     while( packets[0].ecb.in_use )
  586.     {
  587.     }
  588.     
  589.     if (packets[0].ecb.completion_code)    {
  590.         printf( "Send error %d for completion code\n", packets[0].ecb.completion_code );
  591.         exit(1);
  592.     }
  593.  
  594.     // Fill in destination address
  595.     if ( memcmp( network, &ipx_network, 4 ) )
  596.         memcpy( packets[0].ipx.destination.network_id, network, 4 );
  597.     else
  598.         memset( packets[0].ipx.destination.network_id, 0, 4 );
  599.     memcpy( packets[0].ipx.destination.node_id.address, address, 6 );
  600.     memcpy( packets[0].ecb.immediate_address.address, immediate_address, 6 );
  601.     packets[0].pd.packetnum = ipx_packetnum++;
  602.  
  603.     // Fill in data to send
  604.     packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + datasize;
  605.  
  606.     assert( datasize > 1 );
  607.     assert( packets[0].ecb.fragment_size <= 576 );
  608.  
  609.     memcpy( packets[0].pd.data, data, datasize );
  610.  
  611.     // Send it
  612.     ipx_send_packet( &packets[0].ecb );
  613.  
  614. }
  615.  
  616. void ipx_send_broadcast_packet_data( ubyte * data, int datasize )    
  617. {
  618.     int i, j;
  619.     ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  620.     ubyte local_address[6];
  621.  
  622.     // Set to all networks besides mine
  623.     for (i=0; i<Ipx_num_networks; i++ )    {
  624.         if ( memcmp( &Ipx_networks[i], &ipx_network, 4 ) )    {
  625.             ipx_get_local_target( (ubyte *)&Ipx_networks[i], broadcast, local_address );
  626.             ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast, local_address );
  627.         } else {
  628.             ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast, broadcast );
  629.         }
  630.     }
  631.  
  632.     //OLDipx_send_packet_data( data, datasize, (ubyte *)&ipx_network, broadcast, broadcast );
  633.  
  634.     // Send directly to all users not on my network or in the network list.
  635.     for (i=0; i<Ipx_num_users; i++ )    {
  636.         if ( memcmp( Ipx_users[i].network, &ipx_network, 4 ) )    {
  637.             for (j=0; j<Ipx_num_networks; j++ )        {
  638.                 if (!memcmp( Ipx_users[i].network, &Ipx_networks[j], 4 ))
  639.                     goto SkipUser;
  640.             }
  641.             ipx_send_packet_data( data, datasize, Ipx_users[i].network, Ipx_users[i].node, Ipx_users[i].address );
  642. SkipUser:
  643.             j = 0;
  644.         }
  645.     }
  646. }
  647.  
  648. // Sends a non-localized packet... needs 4 byte server, 6 byte address
  649. void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address )
  650. {
  651.     ubyte local_address[6];
  652.  
  653.     if ( (*(uint *)server) != 0 )    {
  654.         ipx_get_local_target( server, address, local_address );
  655.         ipx_send_packet_data( data, datasize, server, address, local_address );
  656.     } else {
  657.         // Old method, no server info.
  658.         ipx_send_packet_data( data, datasize, server, address, address );
  659.     }
  660. }
  661.  
  662. int ipx_change_default_socket( ushort socket_number )
  663. {
  664.     int i;
  665.     WORD new_ipx_socket;
  666.     dpmi_real_regs rregs;
  667.  
  668.     if ( !ipx_installed ) return -3;
  669.  
  670.     // Open a new socket    
  671.     memset(&rregs,0,sizeof(dpmi_real_regs));
  672.     swab( (char *)&socket_number,(char *)&new_ipx_socket, 2 );
  673.     rregs.edx = new_ipx_socket;
  674.     rregs.eax = ipx_socket_life;
  675.     rregs.ebx = 0;    // Open socket
  676.     dpmi_real_int386x( 0x7A, &rregs );
  677.     
  678.     new_ipx_socket = rregs.edx & 0xFFFF;
  679.     
  680.     if ( rregs.eax & 0xFF )    {
  681.         //printf( (1, "IPX error opening channel %d\n", socket_number-IPX_DEFAULT_SOCKET ));
  682.         return -2;
  683.     }
  684.  
  685.     for (i=1; i<ipx_num_packets; i++ )    {
  686.         ipx_cancel_listen_for_packet(&packets[i].ecb);
  687.     }
  688.  
  689.     // Close existing socket...
  690.     memset(&rregs,0,sizeof(dpmi_real_regs));
  691.     rregs.edx = ipx_socket;
  692.     rregs.ebx = 1;    // Close socket
  693.     dpmi_real_int386x( 0x7A, &rregs );
  694.  
  695.     ipx_socket = new_ipx_socket;
  696.  
  697.     // Repost all listen requests on the new socket...    
  698.     for (i=1; i<ipx_num_packets; i++ )    {
  699.         packets[i].ecb.in_use = 0;
  700.         packets[i].ecb.socket_id = ipx_socket;
  701.         ipx_listen_for_packet(&packets[i].ecb);
  702.     }
  703.  
  704.     packets[0].ecb.socket_id = ipx_socket;
  705.     packets[0].ipx.destination.socket_id = ipx_socket;
  706.  
  707.     ipx_packetnum = 0;
  708.     // init packet buffers.
  709.     for (i=0; i<MAX_PACKETS; i++ )    {
  710.         packet_buffers[i].packetnum = -1;
  711.         packet_free_list[i] = i;
  712.     }
  713.     num_packets = 0;
  714.     largest_packet_index = 0;
  715.  
  716.     return 0;
  717. }
  718.  
  719. void ipx_read_user_file(char * filename)
  720. {
  721.     FILE * fp;
  722.     user_address tmp;
  723.     char temp_line[132], *p1;
  724.     int n, ln=0;
  725.  
  726.     if (!filename) return;
  727.  
  728.     Ipx_num_users = 0;
  729.  
  730.     fp = fopen( filename, "rt" );
  731.     if ( !fp ) return;
  732.  
  733.     printf( "Broadcast Users:\n" );
  734.  
  735.     while (fgets(temp_line, 132, fp)) {
  736.         ln++;
  737.         p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
  738.         p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
  739.         n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] );
  740.         if ( n != 10 ) continue;
  741.         if ( Ipx_num_users < MAX_USERS )    {
  742.             ubyte * ipx_real_buffer = (ubyte *)&tmp;
  743.             ipx_get_local_target( tmp.network, tmp.node, tmp.address );
  744.             Ipx_users[Ipx_num_users++] = tmp;
  745.             printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
  746.             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] );
  747.         } else {
  748.             printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
  749.             fclose(fp);
  750.             return;
  751.         }
  752.     }
  753.     fclose(fp);
  754. }
  755.  
  756.  
  757. void ipx_read_network_file(char * filename)
  758. {
  759.     FILE * fp;
  760.     user_address tmp;
  761.     char temp_line[132], *p1;
  762.     int i, n, ln=0;
  763.  
  764.     if (!filename) return;
  765.  
  766.     fp = fopen( filename, "rt" );
  767.     if ( !fp ) return;
  768.  
  769.     printf( "Using Networks:\n" );
  770.     for (i=0; i<Ipx_num_networks; i++ )        {
  771.         ubyte * n1 = (ubyte *)&Ipx_networks[i];
  772.         printf("* %02x%02x%02x%02x\n", n1[0], n1[1], n1[2], n1[3] );
  773.     }
  774.  
  775.     while (fgets(temp_line, 132, fp)) {
  776.         ln++;
  777.         p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
  778.         p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
  779.         n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] );
  780.         if ( n != 4 ) continue;
  781.         if ( Ipx_num_networks < MAX_NETWORKS  )    {
  782.             int j;
  783.             for (j=0; j<Ipx_num_networks; j++ )    
  784.                 if ( !memcmp( &Ipx_networks[j], tmp.network, 4 ) )
  785.                     break;
  786.             if ( j >= Ipx_num_networks )    {
  787.                 memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 );
  788.                 printf("  %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] );
  789.             }
  790.         } else {
  791.             printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS );
  792.             fclose(fp);
  793.             return;
  794.         }
  795.     }
  796.     fclose(fp);
  797.  
  798. }
  799.  
  800. //---typedef struct rip_entry {
  801. //---    uint         network;
  802. //---    ushort    nhops;
  803. //---    ushort    nticks;
  804. //---} rip_entry;
  805. //---
  806. //---typedef struct rip_packet {
  807. //---    ushort        operation;        //1=request, 2=response
  808. //---    rip_entry    rip[50];
  809. //---} rip_packet;
  810. //---
  811. //---
  812. //---void  ipx_find_all_servers()
  813. //---{
  814. //---    int i;
  815. //---    rip_packet * rp;
  816. //---    assert(ipx_installed);
  817. //---
  818. //---    ipx_change_default_socket( 0x0453 );
  819. //---    //    ipx_change_default_socket( 0x5304 );
  820. //---
  821. //---    // Make sure no one is already sending something
  822. //---    while( packets[0].ecb.in_use )
  823. //---    {
  824. //---    }
  825. //---    
  826. //---    if (packets[0].ecb.completion_code)    {
  827. //---        printf( "AAAA:Send error %d for completion code\n", packets[0].ecb.completion_code );
  828. //---        //exit(1);
  829. //---    }
  830. //---
  831. //---    rp = (rip_packet *)&packets[0].pd;
  832. //---
  833. //---    // Fill in destination address
  834. //---    {
  835. //---        char mzero1[] = {0,0,0,1};
  836. //---        char mzero[] = {0,0,0,0,0,1};
  837. //---        char immediate[6];
  838. //---        //memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 );
  839. //---        //memcpy( packets[0].ipx.destination.node_id.address, ipx_my_node.address, 6 );
  840. //---
  841. //---          memcpy( packets[0].ipx.destination.network_id, mzero1, 4 );
  842. //---        memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 );
  843. //---
  844. //---        memcpy( packets[0].ipx.destination.socket_id, &ipx_socket, 2 );
  845. //---        memcpy( packets[0].ipx.source.network_id, &ipx_network, 4 );
  846. //---        memcpy( packets[0].ipx.source.node_id.address, ipx_my_node.address, 6 );
  847. //---        memcpy( packets[0].ipx.source.socket_id, &ipx_socket, 2 );
  848. //---        //memcpy( packets[0].ecb.immediate_address.address, ipx_my_node.address, 6 );
  849. //---        //mzero1[3] = 1;
  850. //---        //memcpy( packets[0].ipx.destination.network_id, mzero1, 4 );
  851. //---        //mzero[5] = 1;
  852. //---        //memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 );
  853. //---        //ipx_get_local_target( mzero1, mzero, immediate );
  854. //---        //memcpy( packets[0].ecb.immediate_address.address, mzero, 6 );
  855. //---        //memcpy( packets[0].ecb.immediate_address.address, immediate, 6 );
  856. //---        //mzero[5] = 0;
  857. //---    }
  858. //---
  859. //---    packets[0].ipx.packet_type = 1;        // RIP packet
  860. //---
  861. //---    // Fill in data to send
  862. //---    packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(rip_packet);
  863. //---    assert( packets[0].ecb.fragment_size <= 576 );
  864. //---
  865. //---    rp->operation = 0;        // Request
  866. //---    for (i=0;i<50; i++)    {
  867. //---        rp->rip[i].network = 0xFFFFFFFF;
  868. //---        rp->rip[i].nhops = 0;
  869. //---        rp->rip[i].nticks = 0;
  870. //---    }
  871. //---
  872. //---    // Send it
  873. //---    ipx_send_packet( &packets[0].ecb );
  874. //---
  875. //---    for (i=0;i<50; i++)    {
  876. //---        if ( rp->rip[i].network != 0xFFFFFFFF )
  877. //---            printf( "Network = %8x, Hops=%d, Ticks=%d\n", rp->rip[i].network, rp->rip[i].nhops, rp->rip[i].nticks );
  878. //---    }
  879. //---}
  880. //---
  881. //---
  882. 
  883.