source: abuse/branches/pd/imlib/port/dos4gw/ipx.c @ 528

Last change on this file since 528 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1#include "ipx.hpp"
2#include "jnet.hpp"
3#include "macs.hpp"
4#include "dprint.hpp"
5#include "system.h"
6#include <i86.h>
7#include <sys/types.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <stdlib.h>
11#include <string.h>
12#include <dos.h>
13#include "jmalloc.hpp"
14#include "doscall.hpp"
15#include "timing.hpp"
16
17#define JC_SEG(x) (((long)x)>>4)
18#define JC_OFF(x) (((long)x)&0xf)
19
20static rminfo rm;
21
22class in_socket_dispatcher
23{
24 
25  ipx_in_socket **ins;
26  long *ports;            // ports which the in sockets are supposed to be on
27} ;
28
29
30int ipx_init()
31{
32  memset(&rm,0,sizeof(rm));
33  rm.eax=0x7a00;
34  RM_intr(0x2f,&rm);
35  return (rm.eax&0xff)==0xff;
36}
37
38void ipx_uninit() { ; }
39
40void close_ipx_socket(int fd)
41{
42  memset(&rm,0,sizeof(rm));
43  rm.ebx=1;
44  rm.edx=(ushort)bstl(fd);
45  RM_intr(0x7a,&rm);
46}
47
48
49void ipx_idle()
50{
51  memset(&rm,0,sizeof(rm));
52  rm.ebx=0xa;
53  RM_intr(0x7a,&rm);
54}
55
56uchar *ipx_get_local_address()                // same format as above (be sure to jfree this)
57{
58  uchar *addr=(uchar *)jmalloc(10,"IPX address");  // normal memory return
59  uchar *low_addr=(uchar *)alloc_low_memory(10);
60  memset(&rm,0,sizeof(rm));
61  rm.ebx=9;
62  rm.esi=JC_OFF(low_addr);
63  rm.es=JC_SEG(low_addr);
64  RM_intr(0x7a,&rm);
65
66  memcpy(addr,low_addr,10);
67  free_low_memory(low_addr);
68  return addr;
69}
70
71
72void ipx_listen(ECBStructure *ecb)
73{
74  memset(&rm,0,sizeof(rm));
75  rm.esi=JC_OFF(ecb);
76  rm.es=JC_SEG(ecb);
77
78  rm.ebx=4;
79  RM_intr(0x7a,&rm);
80
81  if (rm.eax&0xff)
82  {
83    current_sock_err=SOCK_LISTEN_FAIL;
84    sprintf(last_sock_err,"IPX : listen failed");
85  }
86}
87
88ipx_out_socket::ipx_out_socket(int port)
89{
90  remote_socket=-1;              // mark not connected
91  memset(&rm,0,sizeof(rm));
92  rm.ebx=0;                      // Open socket function
93  rm.eax=0;                      // close on program exit
94  rm.edx=(ushort)(bstl(port));
95  RM_intr(0x7a,&rm);
96  if (rm.eax&0xff)
97  {
98    current_sock_err=SOCK_CREATE_FAIL;
99    sprintf(last_sock_err,"Unable to open IPX socket\n");
100    return ;
101  }
102  local_socket=(ushort)bstl((rm.edx&0xffff));
103  printf("created socket %x\n",local_socket);
104
105
106  pk=(JC_ipx_packet *)alloc_low_memory(sizeof(JC_ipx_packet)*MAX_PACKETS);
107  if (!pk)
108  {
109    printf("unable to allocate low memory for packets\n");
110    exit(0);
111  }
112  memset(pk,0,sizeof(JC_ipx_packet)*MAX_PACKETS);
113
114
115  // setup an outgoing packet structure
116  pk[0].ecb.ECBSocket = (ushort)(bstl(local_socket));
117  pk[0].ecb.FragmentCount = 1;
118  pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx);
119  pk[0].ecb.fAddress[1] = JC_SEG(&pk[0].ipx);
120//  pk[0].ipx.PacketCheckSum=0xffff;
121 
122  uchar *my_addr=ipx_get_local_address();
123  memcpy(pk[0].ipx.sNetwork,my_addr,10);
124  pk[0].ipx.sSocket=(ushort)(bstl(local_socket));
125  jfree(my_addr);
126 
127  for (int i=1;i<MAX_PACKETS;i++)
128  {
129    // setup incoming packet structure
130    pk[i].ecb.InUseFlag = 0x1d;
131    pk[i].ecb.ECBSocket = (ushort)(bstl(local_socket));
132    pk[i].ecb.FragmentCount = 1;
133    pk[i].ecb.fAddress[0] = JC_OFF(&pk[i].ipx);
134    pk[i].ecb.fAddress[1] = JC_SEG(&pk[i].ipx);
135    pk[i].ecb.fSize = sizeof(JC_ipx_packet)-sizeof(ECBStructure);
136    ipx_listen(&pk[i].ecb);
137    printf("added listening ecb\n");
138  } 
139
140}
141
142int ipx_send_packet(void *packet)
143{
144  memset(&rm,0,sizeof(rm));
145  rm.ebx=3;                      // send packet function
146  rm.esi=JC_OFF(packet);
147  rm.es=JC_SEG(packet);
148  RM_intr(0x7a,&rm);
149  return 1;
150}
151
152
153int ipx_out_socket::try_connect(char *rhost, int port)
154{
155  uchar *addr=(uchar *)name_to_address(rhost,IPX_PROTOCOL);
156
157  printf("try connect to ");
158  uchar *me=addr;
159  for (int i=0;i<10;i++,me++)
160    printf("%02x:",*me);
161  printf("\n");
162
163  if (addr)
164  {
165    while (pk[0].ecb.InUseFlag)                       // make sure packet is not being used!
166      dprintf("Packet already in use (try connect)\n");
167
168    memcpy(&pk[0].ipx.dNetwork[0],addr,10);     // assume they are playing on the same network
169    memcpy(&pk[0].ecb.ImmediateAddress[0],addr+4,6);
170
171    memset(&pk[0].ipx.dNetwork[0],0,10);
172
173    memset(&pk[0].ipx.dNode[0],0xff,6);   
174    memset(&pk[0].ecb.ImmediateAddress[0],0xff,6);
175
176    pk[0].ipx.dSocket=(ushort)bstl(port);
177    pk[0].verify_stamp=0xcdc;
178    pk[0].ipx.PacketLength=(ushort)bstl(sizeof(IPXPacketStructure)+6);
179
180    pk[0].ecb.ECBSocket = bstl(port);
181    pk[0].ecb.FragmentCount = 1;
182    pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx);
183    pk[0].ecb.fAddress[1] = FP_SEG(&pk[0].ipx);
184    pk[0].ipx.PacketCheckSum=0xffff;
185
186//    for (int j=0 ; j<4 ; j++)
187//      pk[0].ipx.dNetwork[j] = localadr.network[j];
188    pk[0].ipx.dSocket = bstl(port);
189   
190
191    jfree(addr);
192    int found_reply=-1;
193    for (int tries=0;found_reply==-1 && tries<10;tries++)
194    {
195      ipx_send_packet(&pk[0].ecb);
196      printf("sent request packet\n");
197      ipx_idle();
198      milli_wait(500);           // wait 1/2 second for a response
199      for (int i=1;i<MAX_PACKETS;i++)
200      {
201        if (!pk[i].ecb.InUseFlag && pk[i].verify_stamp==0xcdc)
202        {
203          if (found_reply!=-1)    // we found two replies, this shouldn't happen
204          {
205            dprintf("Two replies found for connection request, what's going on?\n");
206            found_reply=-1;
207            tries=10;
208          }
209          found_reply=i;
210          printf("found reply on packet %d\n",i);
211        }
212      }
213    }
214
215
216    if (found_reply==-1)
217      return 0;
218    else
219    {
220      remote_socket=pk[found_reply].time_stamp;
221      local_time=remote_time=0;
222      pk[0].ipx.dSocket=(ushort)bstl(remote_socket);
223      return 1;
224    }
225  } else dprintf("Unable to get an IPX address for hostname '%s'\n",rhost);
226  return 0;
227}
228
229int ipx_out_socket::ready_to_read()
230{
231  if (remote_socket==-1)  return 1;  // not connected, return true so program doesn't block for a
232                                     // packet that will never come
233
234  for (int i=1;i<MAX_PACKETS;i++)
235  {
236    if (!pk[i].ecb.InUseFlag && pk[i].verify_stamp==0xcdc)
237      return 1;
238  }
239  return 0;
240}
241
242
243int ipx_out_socket::ready_to_write()            // true if send packet is clear
244{
245  return pk[0].ecb.InUseFlag==0;
246}
247
248
249
250int ipx_out_socket::send(packet &pak)
251{
252  if (remote_socket==-1) return 0;  // not connected, cannot send packet
253
254  ushort size=lstl(pak.wo-2);        // attach the packet size to the front of the packet
255  memcpy(pak.buf,&size,2);
256 
257
258  int bytes_to_write=size+2;
259  uchar *pk_off=pak.buf;
260  while (bytes_to_write)           // break the packet up into 512 byte segments and send till through
261  {
262    while (!ready_to_write()) ;       // wait till last packet finishes
263
264    int size_to_send=bytes_to_write>512 ? 512 : bytes_to_write;
265
266    memcpy(pk[0].buffer,pk_off,size_to_send);
267    pk[0].time_stamp=local_time;
268    local_time++;
269    pk[0].verify_stamp=0xcdc;
270    pk[0].ipx.PacketLength=(ushort)bstl(sizeof(IPXPacketStructure)+6+size_to_send);
271
272    ipx_send_packet(&pk[0]);
273   
274    pk_off+=size_to_send;
275    bytes_to_write-=size_to_send;
276  }
277
278  return 1;
279}
280
281
282int ipx_out_socket::get(packet &pak)
283{
284  pak.ro=pak.wo=2;
285  int start=-1;
286  time_marker then;
287  do
288  {
289    for (int i=1;start==-1 && i<MAX_PACKETS;i++)
290      if (!pk[i].ecb.InUseFlag && pk[i].time_stamp==remote_time && pk[i].verify_stamp==0xcdc)
291        start=i;
292    time_marker now;
293
294    if (now.diff_time(&then)>20)  // twenty second timeout
295      return 0;
296
297  } while (start==-1);     // wait until we get the packet we are looking for
298
299  remote_time++;
300
301  long data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6;
302
303  if (data_size<2)   // even enough space to read packet size?
304    return 0;
305 
306  ushort size;
307  memcpy(&size,pk[start].buffer,2);
308  data_size-=2;
309
310  size=lstl(size); 
311  pak.rend=size+2;
312  pak.make_bigger(pak.rend);
313
314  uchar *buf=pak.buf+2;
315  uchar *source=pk[start].buffer+2;
316
317  int bytes_left=size;
318  do
319  {
320    memcpy(buf,source,data_size);
321    buf+=data_size;
322    bytes_left-=data_size;
323    ipx_listen(&pk[start].ecb);    // this packet is done and available for listening again
324    pk[start].ecb.InUseFlag = 0x1d;
325
326    if (bytes_left)              // see if we need to get more packets
327    {
328      time_marker then;
329      do
330      {
331        for (int i=1;start==-1 && i<MAX_PACKETS;i++)
332          if (pk[i].time_stamp==remote_time && pk[i].verify_stamp==0xcdc)
333            start=i;
334        time_marker now;
335
336        if (now.diff_time(&then)>20)  // twenty second timeout
337          return 0;
338      } while (start==-1);     // wait until we get the packet we are looking for
339
340      remote_time++;
341      source=pk[start].buffer;
342      data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6;
343    }
344  } while (bytes_left>0);
345
346  return 1;
347}
348
349
350ipx_out_socket::~ipx_out_socket()
351{
352  close_ipx_socket(local_socket);
353  free_low_memory(pk);
354}
355
356ipx_in_socket::ipx_in_socket(int Port)
357{
358  port=Port;
359  listener=new ipx_out_socket(port);
360}
361
362out_socket *ipx_in_socket::check_for_connect()
363{
364  int start=-1;
365  ipx_idle();
366  for (int i=1;i<MAX_PACKETS;i++)
367  {
368    for (int i=1;start==-1 && i<MAX_PACKETS;i++)
369      if (!listener->pk[i].ecb.InUseFlag)
370      {
371        printf("found a connection\n");
372        if (listener->pk[i].verify_stamp==0xcdc)     
373          start=i;
374        else
375        {
376          listener->pk[i].ecb.InUseFlag=0x1d;
377          ipx_listen(&listener->pk[i].ecb);  // this packet is done and available for listening again
378
379          printf("bad stamp, getting packets from someone else!\n");
380        }
381      }
382  }
383
384  if (start!=-1)
385  {
386    ipx_out_socket *nsock=new ipx_out_socket(0);  // create a new socket and dynamicly allocate port
387    listener->pk[0].verify_stamp=0xcdc;
388    listener->pk[0].ipx.PacketLength=sizeof(IPXPacketStructure)+6;
389    listener->pk[0].time_stamp=nsock->local_socket;
390
391    uchar tmp_addr[10];
392    memcpy(tmp_addr,listener->pk[0].ipx.dNetwork,10);   
393    memcpy(listener->pk[0].ipx.dNetwork,
394           listener->pk[start].ipx.sNetwork,12);  // source <- dest
395    memcpy(listener->pk[start].ipx.sNetwork,tmp_addr,10);  // dest <- source
396
397    ipx_listen(&listener->pk[start].ecb);    // this packet is done and available for listening again
398    listener->pk[start].ecb.InUseFlag = 0x1d;
399   
400    ipx_send_packet(&listener->pk[0]);        // send new port info back to caller
401    return nsock;
402  }
403  return NULL;
404}
405
406
407
408ipx_in_socket::~ipx_in_socket()
409{
410  delete listener;
411}
412
413
414
415
416
Note: See TracBrowser for help on using the repository browser.