source: abuse/tags/pd/abuse/src/net/dos4gw/ipx.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 12 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 37.4 KB
Line 
1
2#include "ipx.hpp"
3#include "doscall.hpp"
4#include "jmalloc.hpp"
5#include <ctype.h>
6#include <time.h>
7
8ipx_net_protocol ipx_net;
9
10#define JC_SEG(x) (((long)x)>>4)
11#define JC_OFF(x) (((long)x)&0xf)
12
13#define htons(x) (((x&0xff)<<8) | ((x>>8)&0xff))
14
15static rminfo rm;
16static uchar b_addr[6]={0xff,0xff,0xff,0xff,0xff,0xff};  // broadcast address
17
18closed_secure_ipx_socket::closed_secure_ipx_socket(ipx_net_socket::ipx_packet *pk,
19                                                   int total_packets,
20                                                   int fd,
21                                                   unsigned char final,
22                                                   closed_secure_ipx_socket *next) :
23                                                   pk(pk), fd(fd), next(next)
24{
25  tp=total_packets;
26  state=CLOSING;
27  final_packet_number=final;
28  close_send_count=0;
29  start_counter.get_time();
30}
31
32int ipx_net_address::set_port(int Port)
33{
34  port=Port;
35  return 1;
36}
37
38
39void ipx_idle()
40{
41  memset(&rm,0,sizeof(rm));
42  rm.ebx=0xa;
43  RM_intr(0x7a,&rm);
44}
45
46void show_ipx_address(uchar *addr, ushort sock)
47{
48  fprintf(stderr,"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x:%x",addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7],addr[8],addr[9],sock);
49
50
51static int ipx_listen_to_packet(ipx_net_socket::ipx_packet::ECBStructure *ecb)
52{
53  memset(&rm,0,sizeof(rm));
54  rm.esi=JC_OFF(ecb);
55  rm.es=JC_SEG(ecb);
56
57  rm.ebx=4;
58  RM_intr(0x7a,&rm);
59
60  if (rm.eax&0xff)
61    return 0;
62  else return 1; 
63}
64
65
66void ipx_send_data(int size, ipx_net_socket::ipx_packet *pk)
67{
68
69  if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
70  fprintf(stderr,"(send %d)",size);
71
72  memset(&rm,0,sizeof(rm));
73  rm.ebx=3;                      // send packet function
74  rm.esi=JC_OFF(&pk[0].ecb);
75  rm.es=JC_SEG(&pk[0].ecb);
76  pk[0].ecb.set_data_size(size+pk[0].packet_prefix_size());
77 
78  RM_intr(0x7a,&rm);
79
80}
81
82net_address *ipx_net_protocol::get_local_address()
83{
84  if (Installed)
85  {
86    ipx_net_address *a=new ipx_net_address;
87    uchar *low_addr=(uchar *)low_paragraph;
88
89    memset(&rm,0,sizeof(rm));
90    rm.ebx=9;
91    rm.esi=JC_OFF(low_addr);
92    rm.es=JC_SEG(low_addr);
93    RM_intr(0x7a,&rm);
94   
95    memcpy(a->addr,low_addr,10);
96    return a;
97  }
98  return NULL;
99}
100
101static int total_open_sockets=0;
102
103static void ipx_close_socket(int port)
104{
105  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
106    fprintf(stderr,"(close socket, port=%d)",port);
107
108  memset(&rm,0,sizeof(rm));
109  rm.ebx=1;                      // close socket function
110  rm.edx=htons(port);     
111  RM_intr(0x7a,&rm);
112  total_open_sockets--;
113}
114
115static int ipx_open_socket(int port)
116{
117  if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
118    fprintf(stderr,"(open socket, port=%d)",port);
119
120  do
121  {
122    memset(&rm,0,sizeof(rm));
123    rm.ebx=0;                      // Open socket function
124
125    rm.eax=0;                      // close on program exit
126    rm.edx=htons(port);     
127    RM_intr(0x7a,&rm);
128
129    //  fprintf(stderr,"******* open socket %d\n",htons((rm.edx&0xffff)));
130
131  } while ((rm.eax&0xff) && ipx_net.free_closed_socket());
132
133  if (rm.eax&0xff)
134  {
135    if (ipx_net.debug_level(net_protocol::DB_MAJOR_EVENT))
136      fprintf(stderr,"Unable to created ipx socket on port %d, socket table full\n",port);
137    return -1;
138  } 
139
140  total_open_sockets++;
141  return (ushort)htons((rm.edx&0xffff));
142}
143
144int ipx_net_socket::open_socket(int port)
145{
146  return ipx_open_socket(port);
147}
148
149void ipx_net_protocol::show_socks()
150{
151  ipx_net_socket *f=list;
152  for (;f;f=f->next) { fprintf(stderr,"("); f->print(); fprintf(stderr,")"); }
153
154  closed_secure_ipx_socket *c=closed_list;
155  for (;c;c=c->next) { fprintf(stderr,"("); c->print(); fprintf(stderr,")"); }
156}
157
158int ipx_net_protocol::socket_can_be_allocated(int num_packets)
159{
160  int fd=ipx_open_socket(0);
161  if (fd<0)
162  {
163    fprintf(stderr,"could not allocate a socket, total open=%d\n",total_open_sockets);
164    ipx_net.show_socks();
165    return 0;   
166  }
167  else
168  {
169    ipx_close_socket(fd);
170   
171    // now make sure enough low memory is available to allocate space for the packets   
172    void *mem;
173    do
174    {
175      mem=alloc_low_memory(sizeof(ipx_net_socket::ipx_packet)*num_packets);
176    } while (mem==0 && ipx_net.free_closed_socket());
177    if (!mem)
178    {
179      fprintf(stderr,"could not allocate memory for a socket, size=%d (t=%d), total open=%d, low avail=%d\n",
180              sizeof(ipx_net_socket::ipx_packet)*num_packets,num_packets,total_open_sockets,low_memory_available());
181      ipx_net.show_socks();
182      return 0;
183    }
184    free_low_memory(mem);    // we don't really need it
185     
186
187    return 1;
188  }
189}
190
191
192int ipx_net_protocol::free_closed_socket()   // returns 1 if able to close one socket from the closed (close pool) list
193{
194  closed_secure_ipx_socket *f=closed_list,*l=NULL;
195  for (;f;f=f->next)   // these sockets are just sitting listening for close pings
196  {
197    if (f->state==closed_secure_ipx_socket::TIME_WAIT)
198    {
199      if (l) l->next=f->next;
200      else closed_list=f->next;
201      delete f;
202      return 1;
203    }
204    l=f;
205  }
206
207
208  if (closed_list)  // gonna have to try to close a socket that's sending closed packets
209  {
210    closed_secure_ipx_socket *f=closed_list;
211    closed_list=closed_list->next;
212    delete f;
213    return 1;
214  }
215
216  return 0;
217}
218
219
220ipx_net_socket::~ipx_net_socket()
221{
222  if (backup) jfree(backup);
223  if (fd>=0) 
224    ipx_close_socket(fd);
225  ipx_net.remove_socket_from_list(this);
226  if (pk)
227    free_low_memory(pk);
228}
229
230closed_secure_ipx_socket::~closed_secure_ipx_socket()
231{
232  if (pk)
233    free_low_memory(pk);
234
235  if (fd>=0)
236    ipx_close_socket(fd);
237}
238
239
240void ipx_net_socket::ipx_packet::add_to_packet(void *buf, int size)
241{
242  if (size && size+packet_prefix_size()<=ipx_net.max_packet_data_size())
243  {
244    memcpy(data+packet_size()+packet_prefix_size(),buf,size);
245    set_packet_size(packet_size()+size);
246  }
247}
248
249int closed_secure_ipx_socket::poll()                      // called by select, return 0 when socket is expired
250{
251  int i;
252  for (i=1;i<tp;i++)
253  {
254    if (!pk[i].ecb.InUseFlag)
255    {
256      if (pk[i].get_flag(ipx_net_socket::FIN))           // other socket is finished?
257      {
258        if (pk[i].get_flag(ipx_net_socket::ACK))         // do they wnat an acknowedgement?
259        {
260          if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
261            fprintf(stderr,"(FIN->ACK)");
262          while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
263          pk[0].reset();
264          pk[0].set_flag(ipx_net_socket::FIN,1);         // tell other side we have closed as well
265          pk[0].set_tick_received(final_packet_number);
266          ipx_send_data(0,pk);
267        }
268
269        if (state==CLOSING)                              // if we were waiting for this then go to timeout state
270        {
271          if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
272            fprintf(stderr,"(CLOSING->TIME_WAIT)");
273          state=TIME_WAIT;
274          start_counter.get_time();
275        }
276      } else if (pk[i].get_flag(ipx_net_socket::WRITE_DATA) &&  // they want a acknowedgement of the last packet we read?
277                 pk[i].tick_received()==(uchar)(final_packet_number-1))
278      {
279        if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
280          fprintf(stderr,"(write ACK)");
281
282        while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
283        pk[0].reset();
284        pk[0].set_flag(ipx_net_socket::WRITE_CONFIRM,1);          // acknowedge the data
285        pk[0].set_tick_received((uchar)(final_packet_number-1));
286        ipx_send_data(0,pk);
287      }
288      ipx_listen_to_packet(&pk[i].ecb);                              // reset the packet for listening
289    }
290  }
291
292  time_marker now; 
293  if (state==CLOSING)
294  {
295    if (close_send_count==0 || now.diff_time(&start_counter)*10>CLOSE_MSG_RETRY_TIMEOUT)
296    {
297      if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
298        fprintf(stderr,"(send FIN|ACK)");
299      close_send_count++;
300      while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
301      pk[0].reset();
302      pk[0].set_flag(ipx_net_socket::FIN | ipx_net_socket::ACK,1);
303      pk[0].set_tick_received(final_packet_number);
304      ipx_send_data(0,pk);
305      start_counter.get_time();
306    }       
307  } else if (state==TIME_WAIT && now.diff_time(&start_counter)*10>TIME_WAIT_EXPIRE)
308    return 0;
309 
310  return 1;
311}
312
313ipx_net_socket::ipx_net_socket(int port, int total_read_packets, ipx_net_address *dest)
314
315  backup=NULL; backup_size=backup_end=backup_start=0;
316  pk=NULL;
317  er=0;
318  status=INIT;
319  fd=open_socket(port);
320  ipx_net.add_socket_to_list(this);
321  total_packets=total_read_packets+1;
322
323  if (fd>=0)
324  {
325    void *mem;
326    do
327    {
328      mem=alloc_low_memory(sizeof(ipx_net_socket::ipx_packet)*ipx_packet_total());
329    } while (mem==0 && ipx_net.free_closed_socket());
330    if (!mem)
331    {
332      fprintf(stderr,"unable to allocate low memory for packets, size = %d (t=%d), total open=%d, low_avail=%d\n",
333              sizeof(ipx_packet)*ipx_packet_total(),ipx_packet_total(),total_open_sockets,low_memory_available());
334      ipx_net.show_socks();
335      ipx_close_socket(fd);
336      fd=-1;
337      return ;
338    }
339
340    pk=(ipx_packet *)mem;
341    memset(pk,0,sizeof(ipx_packet)*ipx_packet_total());
342   
343
344    // setup an outgoing packet structure
345    pk[0].ecb.ECBSocket = htons(fd);
346    pk[0].ecb.FragmentCount = 1;
347    pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx);
348    pk[0].ecb.fAddress[1] = JC_SEG(&pk[0].ipx);
349
350
351    memcpy(pk[0].ipx.sAddr,ipx_net.local_addr,10);
352    pk[0].ipx.sSocket=htons(fd);
353
354    set_socket_dest(dest->addr,dest->port);
355
356    for (int i=1;i<ipx_packet_total();i++)
357    {
358      // setup incoming packet structure
359      pk[i].ecb.InUseFlag = 0x1d;
360      pk[i].ecb.ECBSocket = htons(fd);
361      pk[i].ecb.FragmentCount = 1;
362      pk[i].ecb.fAddress[0] = JC_OFF(&pk[i].ipx);
363      pk[i].ecb.fAddress[1] = JC_SEG(&pk[i].ipx);
364      pk[i].ecb.fSize = sizeof(pk[0].ipx)+sizeof(pk[0].data);
365
366      if (listen_to_packet(i)<0)
367        fprintf(stderr,"listen failed on packet %d\n",i);
368    }
369  }
370}
371
372
373void ipx_net_socket::send_ping_packet()
374{
375  while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
376  pk[0].reset();
377  send_data(0);   // send a 0 length data packet to remote host
378}
379
380ipx_net_socket *ipx_net_protocol::socket_origination(uchar *addr,         // their address
381                                                     ushort other_port)
382{
383  ipx_net_socket *p=list;
384  for (;p;p=p->next)
385  {
386    if (p->pk && p->from_port()!=-1)
387    {
388      int correct_machine=memcmp(p->pk[0].ipx.dAddr,addr,10)==0;
389      int correct_port=htons(p->pk[0].ipx.dSocket);
390      if (correct_machine && correct_port==other_port)
391        return p;
392    }
393  }
394  return NULL;
395}
396
397void ipx_net_socket::clear()
398{
399  if (pk && ready_to_read())
400  {
401    for (int i=1;i<ipx_packet_total();i++)
402      if (!pk[i].ecb.InUseFlag)
403        listen_to_packet(i);
404  }
405}
406
407void ipx_net_socket::set_socket_dest(uchar *addr, ushort port)
408{
409  uchar *low_addr=(uchar *)ipx_net.low_paragraph;
410
411  memcpy(pk[0].ipx.dAddr,addr,10);
412  pk[0].ipx.dSocket=htons(port);
413
414  int fail=1;       // if we can't get the local target, use a broadcast
415  if (low_addr)
416  {
417    memset(&rm,0,sizeof(rm));
418    rm.ebx=2;
419    memcpy(low_addr,addr,10);
420   
421    rm.es=JC_SEG(low_addr);
422    rm.esi=JC_OFF(low_addr);
423    rm.edi=rm.esi+10;
424    RM_intr(0x7a,&rm);
425   
426    if ((rm.eax&0xff)==0)  // was ipx able to get the local target?
427    {
428      memcpy(pk[0].ecb.ImmediateAddress,low_addr+10,6);
429      fail=0;
430    }
431
432  }
433  if (fail)
434    memset(pk[0].ecb.ImmediateAddress,0xff,6);
435}
436
437int ipx_secure_listening_socket::ready_to_read()
438{
439  // the following packets are checked for
440
441  //    locate  : dest address is (broadcast), send responce packet
442  //    connect : store remote address in connect_request and return True
443
444  for (int i=1;i<ipx_packet_total();i++)
445  {
446    if (!pk[i].ecb.InUseFlag)
447    {
448      if (memcmp(pk[i].ipx.sAddr,ipx_net.local_addr,10)!=0)
449      {
450        if (memcmp(pk[i].ipx.dAddr+4,b_addr,6)==0)                   // is this a 'locate' packet?
451        {
452          if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
453            fprintf(stderr,"(listen::rtr->locate responce)");
454          while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
455          pk[0].reset();
456          uchar nm_len=strlen(name)+1;
457          pk[0].add_to_packet(&nm_len,1);
458          pk[0].add_to_packet(name,nm_len);
459          pk[0].calc_checksum();
460         
461          set_socket_dest(pk[i].ipx.sAddr,htons(pk[i].ipx.sSocket));
462
463          send_data(strlen(name)+2);                                              // send response packet
464          listen_to_packet(i);
465        }
466        else if (pk[i].get_flag(CONNECT))
467        {
468          // is this address already allocated a socket?
469          ipx_net_socket *c=ipx_net.socket_origination(pk[i].ipx.sAddr,                // their address
470                                                       htons(pk[i].ipx.sSocket));      // their port
471
472          if (c)
473          {
474            if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
475              fprintf(stderr,"(listen::rtr->connect response, me=%d, other=%d)",
476                      htons(pk[i].ipx.dSocket),htons(pk[i].ipx.sSocket));
477
478            ((ipx_secure_socket *)c)->send_ping_packet();                                   // tell this socket to tell it's address
479            listen_to_packet(i);
480          }
481          else
482          {
483            if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
484              fprintf(stderr,"(listen::rtr->see real data)");
485
486            if (ipx_net.socket_can_be_allocated(ipx_secure_socket::SECURE_TOTAL_READ_PACKETS+1))
487              return 1;
488            else           
489              listen_to_packet(i);                                 
490          }
491        } else
492        {
493          if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
494            fprintf(stderr,"(listen::see unknown packet, flags=%d)",pk[i].get_flag(ALL_FLAGS));
495          listen_to_packet(i);
496        }
497      } else
498      {
499        if (ipx_net.debug_level(net_protocol::DB_MINOR_EVENT))
500          fprintf(stderr,"(listen::rtr->see self packet)");
501        listen_to_packet(i);
502      }
503    }
504  }
505  return 0;
506}
507
508
509net_socket *ipx_secure_listening_socket::accept(net_address *&from)
510{
511  // first check to make sure there is a pending connection
512  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
513    fprintf(stderr,"(accept)");
514
515  int i=1;
516  for (;i<ipx_packet_total();i++)
517  {
518    if (!pk[i].ecb.InUseFlag &&                     // active packet
519        memcmp(pk[i].ipx.dAddr+4,b_addr,6)!=0 &&    // not a 'ping' packet
520
521        !ipx_net.socket_origination(pk[i].ipx.sAddr,                // their address
522                                    htons(pk[i].ipx.sSocket)))      // their port
523                                                                    // no active connections with this address on this port
524    {
525      if (!ipx_net.socket_can_be_allocated(ipx_secure_socket::SECURE_TOTAL_READ_PACKETS+1))
526      {from=NULL; return NULL; }   // no more sockets, can't do anything..
527
528      from=new ipx_net_address(pk[i].ipx.sAddr,htons(pk[i].ipx.sSocket));
529      ipx_secure_socket *s=new ipx_secure_socket(htons(pk[i].ipx.sSocket),
530                                                 0,(ipx_net_address *)from);    // dynamically allocate port number
531      if (s->fd<0)
532      { delete s;
533        from=NULL;
534        return NULL;
535      }
536
537      s->send_ping_packet();                                                    // tell remote host which port we are on
538      listen_to_packet(i);
539      if (ipx_net.debug_level(net_protocol::DB_MAJOR_EVENT))
540      {
541        fprintf(stderr,"(accepting ");
542        if (from) from->print();
543        fprintf(stderr,")");
544      }
545
546      return s;
547    }
548  }
549  from=NULL;
550  return NULL;
551}
552
553ipx_secure_socket::~ipx_secure_socket()
554{
555  if (!closed)
556  {
557    if (ipx_net.debug_level(net_protocol::DB_MAJOR_EVENT))
558       fprintf(stderr,"(close secure %d)",fd);
559
560    ipx_net.add_closed(pk,2,fd,packet_on);
561    pk=NULL;
562    fd=-1;
563  }
564}
565
566ipx_secure_listening_socket::~ipx_secure_listening_socket()
567{
568;
569}
570
571void ipx_net_protocol::add_closed(ipx_net_socket::ipx_packet *pk, int total_packets, int fd, int packet_on)
572{
573  closed_list=new closed_secure_ipx_socket(pk,total_packets, fd,packet_on,closed_list);
574}
575
576
577net_address *ipx_net_protocol::find_host(int port, int timeout)
578{
579  ipx_net_address *dest=new ipx_net_address;
580  memcpy(dest->addr,local_addr,4);      // locate on the same net as us
581  memset(dest->addr+4,0xff,6);               // broadcast the packet and wait for a response
582  dest->port=port;
583
584  if (ipx_net.debug_level(DB_MAJOR_EVENT))
585    fprintf(stderr,"(find_host)");
586
587  int found=0;
588  {
589    int tp=ipx_secure_socket::SECURE_TOTAL_READ_PACKETS+1;
590    if (!ipx_net.socket_can_be_allocated(tp)) return NULL;   // no more sockets, can't do anything..
591
592    ipx_net_socket s(0,tp,dest);                  // allocate any abritray port, to use to send and recieve a response
593    if (s.fd<0) return NULL;
594    memset(s.pk[0].ecb.ImmediateAddress,0xff,6);  // broadcast the packet
595
596    while (s.pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
597    s.pk[0].reset();
598    do
599    {
600      fprintf(stderr,".");
601      s.send_data(0);
602     
603      timeout--;
604      time_marker start;
605
606
607      int old_time=timeout;
608     
609      do
610      {
611        time_marker now;
612        if (now.diff_time(&start)>0.1)
613        {
614          timeout--;
615          start.get_time();
616        }
617
618        int i=1;
619        for (;i<s.ipx_packet_total();i++)
620        {
621          if (!s.pk[i].ecb.InUseFlag)
622          {
623            if (ipx_net.debug_level(DB_MINOR_EVENT))
624              fprintf(stderr,"(find_host->see packet)");
625
626            if (memcmp(s.pk[i].ipx.sAddr,ipx_net.local_addr,10)!=0 &&     // from source address differs from ours?
627                htons(s.pk[i].ipx.sSocket)==port)                         // and from the port is the one we are pinging?
628            {
629              memcpy(dest->addr,s.pk[i].ipx.sAddr,10);
630              dest->port=htons(s.pk[i].ipx.sSocket);
631              found=1;
632            }
633
634            s.listen_to_packet(i);
635          }         
636        }
637      } while (timeout==old_time && found==0);
638    } while (timeout>0 && found==0);
639  }
640
641  if (found)
642    return dest;
643   
644  delete dest;
645  return NULL;
646}
647
648
649net_socket *ipx_net_protocol::connect_to_server(net_address *addr,
650                                                net_socket::socket_type sock_type)
651{
652  if (ipx_net.debug_level(DB_MAJOR_EVENT))
653  {
654    fprintf(stderr,"(connect to server "); addr->print(); fprintf(stderr,")");
655  }
656
657  if (addr->protocol_type()!=net_address::IPX)
658  {
659    fprintf(stderr,"cannot connect a non-ipx address on the ipx protocol\n");
660    return NULL;
661  }
662 
663  ipx_net_socket *s;
664
665
666  if (sock_type!=net_socket::SOCKET_FAST)    // fast socket are assumed to be connected
667  {
668    if (!ipx_net.socket_can_be_allocated(ipx_secure_socket::SECURE_TOTAL_READ_PACKETS+1)) return NULL;   // no more sockets, can't do anything..
669    s=new ipx_secure_socket(-1,0,(ipx_net_address *)addr);    // allocate a dynamic port
670    if (s->fd<0) { delete s; return NULL; }
671    s->pk[0].reset();
672    s->pk[0].set_flag(ipx_net_socket::CONNECT,1);
673
674
675    int retry=0;
676    time_marker start_clock;
677    do
678    {
679      time_marker now;
680      if (retry==0 || now.diff_time(&start_clock)*10>CONNECT_PING_RETRY)
681      {
682        retry++;
683        s->send_data(0);                   // send a packet to the server, packet has our port to respond to
684        start_clock.get_time();
685      }
686
687      for (int i=1;i<ipx_secure_socket::SECURE_TOTAL_READ_PACKETS+1;i++)    // check for a response
688      {
689        if (!s->pk[i].ecb.InUseFlag)                                           // incomming packet?
690        {
691          if (memcmp(s->pk[i].ipx.sAddr,((ipx_net_address *)addr)->addr,10)==0 &&    // from expected host?
692              htons(s->pk[i].ipx.sSocket)!=((ipx_net_address *)addr)->port)          // not from connection port?
693          {
694            if (ipx_net.debug_level(DB_MINOR_EVENT))
695              fprintf(stderr,"(got connect reply from port %d)",htons(s->pk[i].ipx.sSocket));
696            s->set_socket_dest(s->pk[i].ipx.sAddr,htons(s->pk[i].ipx.sSocket));
697            s->listen_to_packet(i);
698            return s;                                      // return the established connection
699          } else
700          {
701            if (ipx_net.debug_level(DB_IMPORTANT_EVENT))
702              fprintf(stderr,"(got connect reply from wrong addr/port)");
703          }
704
705          s->listen_to_packet(i);
706        }
707      }
708
709      ipx_net.clear_sockets(NULL);
710    } while (retry<CONNECT_RETRY_TOTAL);
711    delete s;
712    s=NULL;
713  } else
714  {
715    if (!ipx_net.socket_can_be_allocated(16+1)) return NULL;   // no more sockets, can't do anything..
716    s=new ipx_fast_socket(0,(ipx_net_address *)addr);
717    if (s->fd<0) { delete s; return NULL; }   
718  }
719
720  return s;
721}
722
723net_address *ipx_net_protocol::get_node_address(char *&server_name, int def_port, int force_port)
724{
725  char name[256],*np;
726  np=name;
727  while (*server_name && *server_name!=':' && *server_name!='/')
728    *(np++)=*(server_name)++;
729  *np=0;
730  if (*server_name==':')
731  {
732    server_name++;
733    char port[256],*p;
734    p=port;
735    while (*server_name && *server_name!='/')
736      *(p++)=*(server_name++);
737    *p=0;
738    int x;
739    if (!force_port)
740    {
741      if (sscanf(port,"%d",&x)==1) def_port=x;
742      else return 0;
743    }
744  }
745
746  if (*server_name=='/') server_name++;
747
748  if (name[0]==0 || stricmp(name,"any")==0)
749    return find_host(def_port,1000);       // timeout 1 second
750  else
751  {
752    int addr[10];
753    ipx_net_address *ret=new ipx_net_address;
754    ret->port=def_port;
755    int t=sscanf(name,"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x",
756                 addr,addr+1,addr+2,addr+3,addr+4,addr+5,addr+6,addr+7,addr+8,addr+9);
757    if (t==6)
758    {
759      memcpy(ret->addr,local_addr,4); // assume on same network
760      for (int i=0;i<6;i++) ret->addr[i+4]=addr[i];
761    } else if (t==10)
762    {
763      for (int i=0;i<10;i++)
764        ret->addr[i]=addr[i];     // convert int to uchar
765    } else                        // must be a bad address
766    {
767      delete ret;
768      ret=NULL;
769    }
770    return ret;
771  }
772
773  return NULL;  // stupid compilers
774}
775
776net_socket *ipx_net_protocol::create_listen_socket(int port, net_socket::socket_type sock_type, char *sock_name)
777{
778  if (!ipx_net.socket_can_be_allocated(3)) return NULL;   // no more sockets, can't do anything..
779
780  if (ipx_net.debug_level(DB_MAJOR_EVENT))
781    fprintf(stderr,"opening listening socket : port = %d, sock_type =%d\n",port,sock_type);
782
783  ipx_net_address a;
784  if (sock_type==net_socket::SOCKET_SECURE)
785    return new ipx_secure_listening_socket(port,&a,sock_name);
786  else return new ipx_fast_socket(port,&a);
787
788  return NULL;
789}
790
791int ipx_net_socket::listen_to_packet(int packet_num)
792{
793  if (ipx_listen_to_packet(&pk[packet_num].ecb))
794    return 1;
795  else
796  {
797    er=1;
798    return 0;
799  }
800}
801
802
803int ipx_net_socket::ready_to_read()     
804{
805  for (int i=1;i<ipx_packet_total();i++)
806  {
807    if (!pk[i].ecb.InUseFlag)
808    {
809      if (memcmp(pk[i].ipx.dAddr+4,b_addr,6)==0)                   // is this a 'locate' packet?
810      {
811/*      while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
812        memcpy(pk[0].ipx.dAddr,pk[i].ipx.sAddr,10);                // address to send back to
813        pk[0].ipx.dSocket=pk[i].ipx.sSocket;
814        pk[0].reset();
815        send_data(0); */                                             // send response packet
816        listen_to_packet(i);
817      } else if (memcmp(pk[i].ipx.sAddr,ipx_net.local_addr,10)==0) // if this packet was from us, reset listen and ignore
818          listen_to_packet(i);
819      else 
820        return 1;
821    }
822  }
823  return 0;
824}
825
826
827int ipx_fast_socket::ready_to_read()
828{
829  for (int i=1;i<ipx_packet_total();i++)
830  {
831    if (!pk[i].ecb.InUseFlag)
832    {
833      if (memcmp(pk[i].ipx.dAddr+4,b_addr,6)==0)                   // is this a 'locate' packet?
834      {
835/*      while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
836        memcpy(pk[0].ipx.dAddr,pk[i].ipx.sAddr,10);                // address to send back to
837        pk[0].ipx.dSocket=pk[i].ipx.sSocket;
838        pk[0].reset();
839        send_data(0); */                                              // send response packet
840        listen_to_packet(i);
841      } else if (memcmp(pk[i].ipx.sAddr,ipx_net.local_addr,10)==0) // if this packet was from us, reset listen and ignore
842          listen_to_packet(i);
843      else if (memcmp(pk[i].ipx.dAddr,ipx_net.local_addr,10)!=0)
844      {
845        if (ipx_net.debug_level(net_protocol::DB_MAJOR_EVENT))
846        {
847          fprintf(stderr,"see packet not addressed to us!\n");
848          show_ipx_address(pk[i].ipx.dAddr,pk[i].ipx.dSocket);
849          fprintf(stderr,",");
850          show_ipx_address(ipx_net.local_addr,pk[0].ipx.sSocket);
851          fprintf(stderr,"\n");
852        }
853
854       
855        listen_to_packet(i);
856      }
857      else 
858      {
859        return 1;
860      }
861    }
862  }
863  return 0;
864}
865
866
867
868int ipx_secure_socket::ready_to_read()     
869{
870  if (closed) return 1;
871
872  if (backup_start<backup_end) return 1;
873
874  for (int i=1;i<ipx_packet_total();i++)
875  {
876    if (!pk[i].ecb.InUseFlag)
877    {
878
879      if (memcmp(pk[i].ipx.dAddr+4,b_addr,6)==0)                   // is this a 'locate' packet?
880      {
881        listen_to_packet(i);
882      } else if (memcmp(pk[i].ipx.sAddr,ipx_net.local_addr,10)==0) // if this packet was from us, reset listen and ignore
883          listen_to_packet(i);
884      else if ( ((pk[i].tick_received()+1)&0xff)==packet_on && // old packet, send confirm crc anyway
885                 pk[i].get_flag(WRITE_DATA)                   &&
886                 pk[i].get_checksum()==pk[i].calc_checksum())
887      {
888        while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
889        pk[0].reset();
890        pk[0].set_flag(WRITE_CONFIRM,1);
891        pk[0].set_tick_received(pk[i].tick_received());
892        send_data(0);
893        listen_to_packet(i);   
894      } else if (pk[i].tick_received()==packet_on &&
895                 pk[i].get_flag(WRITE_DATA))
896        return 1;
897      else if (pk[i].tick_received()==packet_on &&
898               pk[i].get_flag(ipx_net_socket::FIN))
899      {
900
901        if (pk[i].get_flag(ipx_net_socket::ACK))
902        {
903          while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
904          pk[0].reset();
905          pk[0].set_flag(ipx_net_socket::WRITE_CONFIRM,1);          // acknowedge the data
906          pk[0].set_tick_received((uchar)(packet_on-1));
907          ipx_send_data(0,pk);
908        }
909        listen_to_packet(i);
910        closed=1;
911        ipx_net.add_closed(pk,2,fd,packet_on);
912        pk=NULL;
913        fd=-1;
914     
915      } else listen_to_packet(i);
916    }
917  }
918
919  return 0;
920}
921
922
923
924void ipx_net_socket::ipx_packet::ECBStructure::set_data_size(int size)
925{
926  fSize=sizeof(ipx_net_socket::ipx_packet::IPXPacketStructure)+size;
927}
928
929
930void paddr(uchar *addr)
931{
932  for (int i=0;i<10;i++) fprintf(stderr,"%x.",*(addr++));
933}
934
935virtual int ipx_secure_socket::write(void *buf, int size, net_address *addr)
936{
937  if (addr)
938  {
939    fprintf(stderr,"Cannot alter address for secure sockets\n");
940    return 0;
941  }
942
943  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
944    fprintf(stderr,"(FW %d,%d)",size,fd);
945
946  if (closed) { er=1; return 0; }
947
948  int ss=0,i;
949  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
950    fprintf(stderr,"(W %d,%d)",size,fd);
951
952  while (size && er==0)
953  {
954    while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
955    pk[0].reset();
956    int ws;
957
958    if (size<ipx_net.max_packet_data_size()-pk[0].packet_prefix_size())
959      ws=size;
960    else ws=ipx_net.max_packet_data_size()-pk[0].packet_prefix_size();
961
962    int verify=0,retry_total=0;
963    time_marker start_clock;
964    do
965    {
966      time_marker now;
967      if (retry_total==0 || (int)(now.diff_time(&start_clock)*100.0)>SEND_RETRY_TIMEOUT)
968      {
969        while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
970        pk[0].reset();
971        pk[0].add_to_packet(buf,ws);
972        pk[0].set_tick_received(packet_on);
973        pk[0].set_flag(WRITE_DATA,1);
974        pk[0].calc_checksum();
975
976        send_data(ws);
977
978        if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
979          fprintf(stderr,"w");
980
981        start_clock.get_time();
982        retry_total++;
983        if (retry_total>RETRY_TOTAL)
984          er=1;       
985      }
986
987   
988      for (i=1;i<ipx_packet_total();i++)    // wait till we get a packet back with the same packet_on
989        if (!pk[i].ecb.InUseFlag)
990        {
991          if (pk[i].tick_received()==packet_on && pk[i].get_flag(ipx_net_socket::WRITE_CONFIRM))
992          {
993            size-=ws;
994            ss+=ws;
995            buf=(void *)((uchar *)buf+ws);
996            packet_on++;
997            verify=1;
998            listen_to_packet(i);
999
1000          } else clear_packet(i);
1001         
1002        }
1003
1004      ipx_net.clear_sockets(this);
1005
1006    } while (verify==0 && er==0 && closed==0);
1007   
1008  }
1009
1010  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
1011    fprintf(stderr,"(~W)");
1012
1013  return ss;
1014}
1015
1016void ipx_net_socket::send_data(int data_size)
1017{
1018  ipx_send_data(data_size,pk);
1019}
1020
1021
1022void ipx_secure_socket::clear_packet(int i)
1023{
1024  if (pk[i].tick_received()==packet_on && pk[i].get_flag(ipx_net_socket::FIN)) // other socket is finished?
1025  {           
1026    if (pk[i].get_flag(ipx_net_socket::ACK))         // do they wnat an acknowedgement?
1027    {
1028      while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
1029      pk[0].reset();
1030      pk[0].set_flag(ipx_net_socket::FIN,1);         // tell other side we have closed as well
1031      pk[0].set_tick_received(packet_on);
1032      ipx_send_data(0,pk);
1033    }
1034   
1035    listen_to_packet(i);
1036
1037    closed=1;
1038    ipx_net.add_closed(pk,2,fd,packet_on);
1039    pk=NULL;
1040    fd=-1;
1041
1042  } else if ( ((pk[i].tick_received()+1)&0xff)==packet_on && pk[i].get_flag(WRITE_DATA))  // old packet, send confirm crc anyway
1043  {       
1044    while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet   
1045    pk[0].reset();
1046    pk[0].set_flag(WRITE_CONFIRM,1);
1047    pk[0].set_tick_received(pk[i].tick_received());
1048    send_data(0);
1049    listen_to_packet(i);
1050
1051  } else listen_to_packet(i);
1052
1053
1054}
1055
1056
1057int ipx_secure_socket::read(void *buf, int size, net_address **addr)
1058{
1059  if (closed) { er=1; return 0; }
1060
1061  if (addr) *addr=0;
1062  int rs=0;
1063
1064  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
1065    fprintf(stderr,"(R %d,%d)",size,fd);
1066
1067  rs+=read_backup(buf,size);
1068
1069  while (size && !er && !closed)
1070  {
1071    int got_packet=0;
1072    time_marker start_clock;
1073    do
1074    {
1075      for (int i=1;size && i<ipx_packet_total();i++)    // wait till we get a packet back with the same packet_on
1076      {
1077        if (!pk[i].ecb.InUseFlag)
1078        {
1079          if (pk[i].get_flag(WRITE_DATA) && pk[i].tick_received()==packet_on)
1080          {
1081            if (pk[i].get_checksum()==pk[i].calc_checksum())
1082            {
1083              int s=pk[i].packet_size();
1084              if (s)
1085              {
1086                if (s>size)
1087                {
1088                  memcpy(buf,pk[i].packet_data(),size); 
1089                  add_backup(pk[i].packet_data()+size,s-size);      // add the rest to a backup packet       
1090                  rs+=size;
1091                  size=0;
1092                } else
1093                {
1094                  memcpy(buf,pk[i].packet_data(),s);
1095                  buf=(void *)((uchar *)buf+s);
1096                  size-=s;
1097                  rs+=s;
1098                }
1099                while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
1100
1101                memcpy(pk[0].data,pk[i].data,pk[i].packet_prefix_size());   // copy packet prefix info into packet
1102                pk[0].set_flag(ALL_FLAGS,0);
1103                pk[0].set_flag(WRITE_CONFIRM,1);
1104
1105                send_data(0);
1106                packet_on++;
1107                got_packet=1;
1108              } else fprintf(stderr,"received 0 sized packet\n");
1109            } else fprintf(stderr,"bad checksum\n");
1110            listen_to_packet(i);
1111         
1112          } else clear_packet(i);
1113
1114        }
1115      }
1116
1117      time_marker now;
1118      if (now.diff_time(&start_clock)*10>RETRY_TOTAL*SEND_RETRY_TIMEOUT)  // if we don't get a packet after this long, report an error
1119        er=1;
1120      ipx_net.clear_sockets(this);
1121
1122    } while (!got_packet && !er && !closed);
1123
1124  }
1125
1126  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
1127    fprintf(stderr,"(~R)");
1128 
1129  return rs;
1130}
1131
1132
1133ipx_net_protocol::ipx_net_protocol()
1134{
1135  locator_socket=NULL;
1136  find_list=NULL;
1137  low_paragraph=NULL;
1138  memset(&rm,0,sizeof(rm));
1139  rm.eax=0x7a00;
1140  RM_intr(0x2f,&rm);
1141  list=NULL;
1142  closed_list=NULL;
1143
1144  if ((rm.eax&0xff)==0xff)      // drivers installed?
1145  {
1146    memset(&rm,0,sizeof(rm));   // get the maximum packet size
1147    rm.ebx=0xd;
1148    RM_intr(0x7a,&rm);   
1149    max_pksz=rm.eax&0xffff;
1150
1151    if (max_pksz<1024)
1152    {
1153      fprintf(stderr,"IPX : Maximum packet size is too small, needs to be at least 1024 (is %d)\n",max_pksz);
1154      Installed=0;
1155    } else
1156    {
1157      low_paragraph=alloc_low_memory(16);    // need this to store address when looking up immediate address
1158      if (!low_paragraph)
1159      {
1160        fprintf(stderr,"IPX : Unable to allocate 16 bytes of low memory!\n");
1161        Installed=0;
1162      } else
1163      {
1164        Installed=1;
1165        net_address *a=get_local_address();
1166        if (a)
1167        {
1168          memcpy(local_addr,((ipx_net_address *)a)->addr,10);
1169          delete a;
1170        } else Installed=0;
1171      }
1172
1173    }
1174  }
1175  else
1176  {
1177    Installed=0;
1178    max_pksz=0;
1179  }
1180
1181}
1182
1183
1184
1185void ipx_net_protocol::add_socket_to_list(ipx_net_socket *who)
1186{
1187  who->next=list;
1188  list=who;
1189}
1190
1191void ipx_net_protocol::remove_socket_from_list(ipx_net_socket *who)
1192{
1193  if (who==list)
1194    list=list->next;
1195  else if (list && list->next)
1196  {
1197    ipx_net_socket *last=(ipx_net_socket *)list;
1198    for (;last->next && last->next!=who;last=last->next);
1199    if (last->next==who)
1200      last->next=who->next;         
1201  }
1202}
1203
1204int ipx_net_protocol::select(int block)
1205{
1206  int t=0;
1207  do
1208  {
1209    ipx_net_socket *p=list;
1210    for (;p;p=p->next)
1211    {
1212      if ((p->status & ipx_net_socket::READ_CHECKING) && (p->ready_to_read()))
1213      {
1214        t++;
1215      }
1216      if ((p->status & ipx_net_socket::WRITE_CHECKING) && (p->ready_to_write()))
1217      {
1218        t++;
1219      }
1220      if (p->er) t++;
1221    }
1222
1223    closed_secure_ipx_socket *c=closed_list,*last=NULL,*q;
1224    for (;c;)
1225    {
1226      if (!c->poll())
1227      {
1228        if (last) last->next=c->next;
1229        else closed_list=c->next;
1230        q=c;
1231        c=c->next;
1232        delete q;
1233      } else
1234      {
1235        last=c;
1236        c=c->next;
1237      }
1238    }
1239   
1240
1241  } while (t==0 && block); 
1242
1243  return t;
1244}
1245
1246void ipx_net_protocol::cleanup()
1247{
1248  reset_find_list();
1249
1250  ipx_net_socket *first=list;
1251  list=NULL;
1252
1253  while (first)
1254  {
1255    ipx_net_socket *q=first;
1256    first=first->next;
1257    delete q;
1258  }
1259
1260  closed_secure_ipx_socket *c=closed_list;
1261  int need_wait=0;
1262  for (;c;c=c->next) 
1263    if (c->state==closed_secure_ipx_socket::CLOSING)
1264      need_wait=1;
1265
1266  time_marker now,start;
1267  while (need_wait)
1268  {
1269    if (now.diff_time(&start)>3.0) need_wait=0;  // wait a max of 3 seconds
1270    else
1271    {
1272      now.get_time();
1273      select(0);
1274
1275      need_wait=0;
1276      c=closed_list;
1277      for (;c;c=c->next) 
1278        if (c->state==closed_secure_ipx_socket::CLOSING)
1279           need_wait=1;
1280    }   
1281  }
1282  c=closed_list;
1283
1284  while (c)
1285  {
1286    closed_secure_ipx_socket *q=c;
1287    c=c->next;
1288    delete q;
1289  }
1290  closed_list=NULL;
1291}
1292
1293
1294int ipx_fast_socket::write(void *buf, int size, net_address *addr)
1295{
1296  while (pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the previous packet
1297
1298  if (size>ipx_net.max_packet_data_size())   // make sure this size will fit in IPX max allowable packet size
1299    size=ipx_net.max_packet_data_size();
1300
1301  pk[0].reset();
1302  pk[0].add_to_packet(buf,size);
1303
1304  if (addr)
1305    set_socket_dest( ((ipx_net_address *)addr)->addr,
1306                     ((ipx_net_address *)addr)->port);
1307
1308  send_data(size);
1309
1310  return size;
1311}
1312
1313int ipx_fast_socket::read(void *buf, int size, net_address **addr)
1314{
1315  if (ipx_net.debug_level(net_protocol::DB_IMPORTANT_EVENT))
1316    fprintf(stderr,"(FR %d,%d)",size,fd);
1317
1318  while (1)
1319  {
1320    int i;
1321    for (i=1;i<ipx_packet_total();i++)
1322      if (!pk[i].ecb.InUseFlag)
1323      {
1324        int s=pk[i].packet_size();     
1325        if (size<s) s=size;
1326        memcpy(buf,pk[i].packet_data(),s);
1327        if (addr) *addr=new ipx_net_address(pk[i].ipx.sAddr,htons(pk[i].ipx.sSocket));
1328        listen_to_packet(i);
1329        return s;
1330      }
1331    ipx_net.clear_sockets(this);
1332  }
1333  return 0;
1334}
1335
1336
1337
1338int ipx_net_socket::read_backup(void *&buf, int &size)    // read previously buffer data
1339{
1340  int s=backup_end-backup_start;
1341  if (s && size)
1342  {                                         
1343    if (size>=s)
1344    {
1345      memcpy(buf,backup+backup_start,s);
1346      buf=(void *)((uchar *)buf+s);
1347      backup_start=backup_end=0;
1348      size-=s;
1349      return s;
1350    } else
1351    {
1352      memcpy(buf,backup+backup_start,size);
1353      buf=(void *)((uchar *)+size);
1354      int ret=size;
1355      backup_start+=size;
1356      size=0;
1357      return ret;
1358    }
1359  } else return 0;
1360}
1361
1362
1363
1364void ipx_net_socket::add_backup(uchar *buf, int size)
1365{
1366  if (size)
1367  {
1368    if (backup_size-backup_end>=size)
1369    {
1370      memcpy(backup+backup_end,buf,size);
1371      backup_end+=size;
1372    } else
1373    {
1374      backup_size+=backup_end+size-backup_size;
1375      backup=(uchar *)jrealloc(backup,backup_size,"backup buffer");
1376      add_backup(buf,size);
1377    }
1378  }
1379}
1380
1381
1382void ipx_net_protocol::clear_sockets(ipx_net_socket *exclude)
1383{
1384  ipx_net_socket *p=list;
1385  for (;p;p=p->next)
1386    if (p!=exclude)
1387      p->clear();
1388
1389  closed_secure_ipx_socket *c=closed_list,*last=NULL,*q;
1390  for (;c;)
1391  {
1392    if (!c->poll())
1393    {
1394      if (last) last->next=c->next;
1395      else closed_list=c->next;
1396      q=c;
1397      c=c->next;
1398      delete q;
1399    } else
1400    {
1401      last=c;
1402      c=c->next;
1403    }
1404  }
1405
1406}
1407
1408ipx_net_protocol::~ipx_net_protocol()
1409{
1410  if (low_paragraph)
1411    free_low_memory(low_paragraph);
1412}
1413
1414
1415net_address *ipx_net_protocol::find_address(int port, char *name)
1416{
1417
1418  if (!locator_socket)
1419  {
1420    if (!ipx_net.socket_can_be_allocated(LOCATOR_PACKETS)) return NULL;   // no more sockets, can't do anything..
1421
1422    ipx_net_address *dest=new ipx_net_address;
1423    memcpy(dest->addr,local_addr,4);      // locate on the same net as us
1424    memset(dest->addr+4,0xff,6);               // broadcast the packet and wait for a response
1425    dest->port=port;
1426
1427
1428    locator_socket=new ipx_net_socket(0,LOCATOR_PACKETS,dest);  // allocate abritraty socket #
1429    delete dest;
1430
1431    if (locator_socket->fd<0) { delete locator_socket; locator_socket=NULL; return NULL; }
1432
1433
1434    memset(locator_socket->pk[0].ecb.ImmediateAddress,0xff,6);  // broadcast the packet
1435  } else locator_socket->pk[0].ipx.dSocket=htons(port);
1436
1437
1438  int i;
1439  for (i=1;i<LOCATOR_PACKETS;i++)
1440  {
1441    if  (!locator_socket->pk[i].ecb.InUseFlag)  // see something?
1442    {
1443      if (memcmp(locator_socket->pk[i].ipx.sAddr,ipx_net.local_addr,10)!=0 &&     // from source address differs from ours?
1444                htons(locator_socket->pk[i].ipx.sSocket)==port)                         // and from the port is the one we are pinging?
1445      {
1446        locator_node *p=find_list,*found=NULL;
1447        for (;p && !found;p=p->next)
1448          if (memcmp(p->addr->addr,locator_socket->pk[i].ipx.sAddr,10)==0 && p->addr->get_port()==htons(locator_socket->pk[i].ipx.sSocket))
1449            found=p;
1450
1451        if (!found)
1452        {
1453          uchar *c=locator_socket->pk[i].packet_data();
1454          int len=*(c++);
1455          memcpy(name,c,len);
1456
1457          find_list=new locator_node(new ipx_net_address(locator_socket->pk[i].ipx.sAddr,htons(locator_socket->pk[i].ipx.sSocket)),find_list);
1458          locator_socket->listen_to_packet(i);
1459          return find_list->addr->copy();
1460        }
1461      }
1462      locator_socket->listen_to_packet(i);
1463    }
1464  }
1465 
1466  time_marker now;
1467  if (now.diff_time(&last_ping)>0.3)
1468  {
1469    last_ping.get_time();
1470   
1471    while (locator_socket->pk[0].ecb.InUseFlag) ipx_idle();    // wait for ipx to clear the packet
1472    locator_socket->pk[0].reset();
1473    locator_socket->send_data(0);
1474  }
1475
1476  return NULL;
1477}
1478
1479
1480void ipx_net_protocol::reset_find_list()
1481{
1482  if (locator_socket) { delete locator_socket; locator_socket=NULL; }
1483
1484  while (find_list)
1485  {
1486    locator_node *q=find_list;
1487    find_list=find_list->next;
1488    delete q;   
1489  }
1490}
1491
1492int ipx_net_protocol::installed()
1493{
1494  if (!Installed) return 0;
1495  else if (low_memory_available()<150000)
1496    return 0;
1497  else return 1;
1498}
Note: See TracBrowser for help on using the repository browser.