source: abuse/tags/pd/macabuse/src/net/inc/ipx.hpp @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
File size: 12.2 KB
Line 
1#ifndef __IPX_SOCK_HPP_
2#define __IPX_SOCK_HPP_
3
4#include "sock.hpp"
5#include "macs.hpp"
6#include "timing.hpp"
7#include <string.h>
8
9#include <string.h>
10
11class ipx_net_address : public net_address
12{
13  public :
14  uchar addr[10];
15  ushort port;      // stored in intel-format
16  virtual protocol protocol_type() { return IPX; }
17  virtual int equal(net_address *who)   { return who->protocol_type()==protocol_type() &&
18                                                 memcmp(addr,((ipx_net_address *)who)->addr,10)==0; }
19  virtual int set_port(int Port);
20  virtual void print() { printf("network = %x.%x.%x.%x, node = %x.%x.%x.%x.%x.%x, port = %d\n",
21                         addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7],addr[8],addr[9],port); } 
22  ipx_net_address() { memset(addr,0,10); port=0; }
23  ipx_net_address(uchar *addr_data, ushort port) : port(port)
24  { memcpy(addr,addr_data,10); }
25  int get_port() { return port ; }
26  net_address *copy() { return new ipx_net_address(addr,port); }
27  void store_string(char *st, int st_length)
28  {
29    char buf[100];
30    sprintf(buf,"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x:%d",addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7],addr[8],addr[9],port);
31    strncpy(st,buf,st_length);
32    st[st_length-1]=0;
33  }
34} ;
35
36#pragma pack (1)
37
38
39class ipx_net_socket : public net_socket
40{
41  public :
42  uchar *backup;                   // when a partial read request happens
43  int backup_start,backup_end,backup_size;
44  int read_backup(void *&buf, int &size);
45  void add_backup(uchar *buf, int size);
46
47  ipx_net_socket *next;
48  int total_packets;
49
50  int ipx_packet_total() { return total_packets; }
51
52  enum {IPX_PACKET_SIZE=1024} ;      // this amount of data space reserved for each packet
53                                    // though the actaul packet sent may be smaller because of IPX limits
54
55
56  enum { ACK=1,            // acknowedge receipt of packet
57         FIN=2,            // connection has finished
58         CONNECT=4,        // asking to make a connection
59         WRITE_DATA=8,
60         WRITE_CONFIRM=16,
61         ALL_FLAGS=31 };
62
63  enum { SEND_RETRY_TIMEOUT=10,  // .1 seconds timeout before resending data packet
64         RETRY_TOTAL=2400        // give up after retring 2400 times, or 240 seconds =  4 minutes
65       } ;
66
67
68
69  struct ipx_packet
70  {
71    struct ECBStructure
72    {
73      ushort Link[2];
74      ushort ESRAddress[2];
75      uchar  InUseFlag;
76      uchar  CompletionCode;
77      ushort ECBSocket;
78      uchar  IPXWorkspace[4];
79      uchar  DriverWorkspace[12];
80      uchar  ImmediateAddress[6];
81      ushort FragmentCount;
82      ushort fAddress[2];
83      ushort fSize;
84
85      int data_waiting() { return InUseFlag; }
86      void set_data_size(int size);
87    } ecb;
88
89    struct IPXPacketStructure
90    {
91      ushort PacketCheckSum;
92      ushort PacketLength;
93      uchar  PacketTransportControl;
94      uchar  PacketType;
95
96      uchar  dAddr[10];
97      ushort dSocket;      // flipped intel-format
98
99      uchar  sAddr[10];
100      ushort sSocket;     // flipped intel-format
101
102    } ipx;
103
104
105    uchar data[IPX_PACKET_SIZE];
106
107    int packet_prefix_size()                 { return 6; }    // 2 size
108                                                              // 2 byte check sum
109                                                              // 1 byte packet order
110                                                              // 1 byte flags
111           
112
113    void set_packet_size(unsigned short x)   { *((unsigned short *)data)=lstl(x); }
114    unsigned short packet_size()             { unsigned short size=(*(unsigned short *)data); return lstl(size); }
115    unsigned char tick_received()            { return data[4]; } 
116    void set_tick_received(unsigned char x)  { data[4]=x; }
117    unsigned char *packet_data()             { return data+packet_prefix_size(); }
118    unsigned short get_checksum()            { unsigned short cs=*((unsigned short *)data+1); return lstl(cs); }
119    uchar get_flag(int flag)                 { return data[5]&flag; }
120    void set_flag(int flag, int x)           { if (x) data[5]|=flag; else data[5]&=~flag; }
121    unsigned short calc_checksum()
122    {
123      *((unsigned short *)data+1)=0;
124      int i,size=packet_prefix_size()+packet_size();
125      unsigned char c1=0x12,c2=0x34,*p=data;
126      for (i=0;i<size;i++,p++)
127      {
128        c1+=*p;
129        c2+=c1;
130      }
131      unsigned short cs=( (((unsigned short)c1)<<8) | c2);
132      *((unsigned short *)data+1)=lstl(cs);
133      return cs;
134    }
135
136
137    void reset()    { set_packet_size(0); set_flag(ALL_FLAGS,0); }     // 2 bytes for size, 1 byte for tick
138   
139    void add_to_packet(void *buf, int size);
140
141    void write_byte(unsigned char x) { add_to_packet(&x,1); }
142    void write_short(unsigned short x) { x=lstl(x); add_to_packet(&x,2); }
143    void write_long(unsigned long x) { x=lltl(x); add_to_packet(&x,4); }
144
145
146  } *pk;
147
148         
149
150  int fd,er;
151  void idle();   // call this if you are bored
152 
153  enum { INIT=0,
154         READ_CHECKING=1,
155         WRITE_CHECKING=2,
156         READ_SELECTED=4,
157         WRITE_SELECTED=8
158       } ;
159  uchar status;
160
161  void send_data(int data_size);
162  void send_ping_packet();
163  int listen_to_packet(int packet_num);
164  int open_socket(int port);
165
166  virtual int error()                                              { return er; }
167  virtual int ready_to_read();
168  virtual int ready_to_write() { if (fd>=0) return pk[0].ecb.InUseFlag; else return 1; }
169
170  virtual int write(void *buf, int size, net_address *addr=NULL) { return 0; }
171
172  virtual int read(void *buf, int size, net_address **addr=0) { if (addr) *addr=0; return 0; }
173  virtual int get_fd()    { return fd; }
174  virtual void read_selectable()     { status|=READ_CHECKING; }
175  virtual void read_unselectable()   { status&=~READ_CHECKING; }
176  virtual void write_selectable()    { status|=WRITE_CHECKING; }
177  virtual void write_unselectable()  { status&=~WRITE_CHECKING; }
178  virtual int listen(int port)       { return 0; }
179  virtual net_socket *accept(net_address *&from) { from=NULL; return NULL; }
180  virtual int from_port() { return -1; }
181
182  virtual void clear();
183
184  void set_socket_dest(uchar *addr, ushort port);
185  ipx_net_socket(int port, int total_read_packets, ipx_net_address *dest);
186  virtual void print() { fprintf(stderr,"ipx net socket");  }
187  virtual ~ipx_net_socket();
188} ;
189
190#pragma pack (0)
191
192
193class ipx_secure_listening_socket;
194
195class ipx_secure_socket : public ipx_net_socket
196
197  uchar packet_on,write_ack_needed,write_ack_checksum;
198  ushort parent_port;
199
200  enum { ESTABLISHED,
201         CLOSE_WAIT,        // waiting for user to close
202         CLOSING,           // waiting for remote response to close
203         TIME_WAIT,         // waiting till 'counter' expires to ensure remote socket has gotten close message
204       } state;
205
206  int counter,closed;
207 
208  public :
209  enum { SECURE_TOTAL_READ_PACKETS=2 } ;
210
211  virtual int ready_to_read();
212  virtual int ready_to_write() { return 1; }
213
214  virtual int write(void *buf, int size, net_address *addr=NULL);
215  virtual int read(void *buf, int size, net_address **addr=0);
216
217  void clear_packet(int i);
218  ipx_secure_socket(int parent_port, int port, ipx_net_address *dest) :
219    ipx_net_socket(port,SECURE_TOTAL_READ_PACKETS,dest),parent_port(parent_port)
220  { packet_on=1; write_ack_needed=0; closed=0; }
221  int from_port() { return parent_port; }
222  int verify_sync();
223  virtual void print() { fprintf(stderr,"ipx secure socket");  }
224  ~ipx_secure_socket();
225} ;
226
227
228// the closed_secure_ipx_packet is not to be seen by anyone other than the ipx_protocol
229// and it's is polled during calls to select()
230
231class closed_secure_ipx_socket
232{
233  public :
234  closed_secure_ipx_socket *next;
235
236  enum { CLOSING,                       // keep send close message, until receive ack, then goto TIME_WAIT
237         TIME_WAIT                      // after ack for close message, wait for TIME_WAIT_EXPIRE before closing
238       } state;
239
240  enum { CLOSE_MSG_RETRY_TIMEOUT=20,    // .2 seconds between each close() message retry
241         CLOSE_TOTAL_RETRY=10,          // 10 total retries for sending a close() message before giving up
242         TIME_WAIT_EXPIRE=1000          // 10 seconds before a socket expires and can be reused
243       } ;
244
245  time_marker start_counter;      // if CLOSING, then the clock() of the last close message sent
246                                  // if TIME_WAIT, then clock() of the entering this state
247
248  int close_send_count;           // number of times close socket msg has been sent (from CLOSING state)
249                                 
250  int fd;                          // the port this socket is using
251  uchar final_packet_number;
252  ipx_net_socket::ipx_packet *pk;  // pointer to low packet memory taken from a ipx_secure_socket
253  int poll();                      // called by select, return 0 when socket is expired
254  ~closed_secure_ipx_socket();
255  int tp;
256  closed_secure_ipx_socket(ipx_net_socket::ipx_packet *pk,
257                           int total_packets,
258                           int fd,
259                           unsigned char final_packet_number,
260                           closed_secure_ipx_socket *next);
261
262  void print() { fprintf(stderr,"closed secure socket, state=%d",(int)state);  }
263} ;
264
265
266// this class can only sit and listen, it will respond to 'ping' and 'connect' packets
267// this class will return 1 for ready_to_read and then create a ipx_secure_socket on accept()
268
269class ipx_secure_listening_socket : public ipx_net_socket
270{
271  enum { NAME_MAX=30 };
272  char name[NAME_MAX];
273  public :
274
275  virtual int ready_to_write() { return 1; }
276  virtual int ready_to_read();
277  virtual int write(void *buf, int size, net_address *addr=NULL) { return 0; }
278  virtual int read(void *buf, int size, net_address **addr=0) { if (addr) *addr=0; return 0; }
279
280  virtual net_socket *accept(net_address *&from);
281  ipx_secure_listening_socket(int port, ipx_net_address *dest, char *sock_name) : ipx_net_socket(port,2,dest)
282  { strncpy(name,sock_name,NAME_MAX-1); name[NAME_MAX-1]=0; }
283  ~ipx_secure_listening_socket();
284  virtual void print() { fprintf(stderr,"ipx secure listening socket");  }
285} ;
286
287class ipx_fast_socket : public ipx_net_socket
288{
289  public :
290  int write(void *buf, int size, net_address *addr=NULL);
291  int read(void *buf, int size, net_address **addr=0);
292  virtual int ready_to_read();
293  ipx_fast_socket(int port, ipx_net_address *dest) : ipx_net_socket(port,16,dest) { ; }
294  void clear() { ; }  // no need to clear these
295  virtual void print() { fprintf(stderr,"ipx fast socket");  }
296
297} ;
298
299class ipx_net_protocol : public net_protocol
300{
301  int Installed;
302  ushort max_pksz;
303  int max_packet_size() { return max_pksz; }
304
305  net_address *find_host(int port, int timeout);
306  ipx_net_socket *list;
307
308  class locator_node
309  {
310    public :
311    ipx_net_address *addr;
312    locator_node *next;
313    locator_node(ipx_net_address *addr, locator_node *next) : addr(addr), next(next) { ; }
314    ~locator_node() { delete addr; }
315  } *find_list;
316
317  ipx_net_socket *locator_socket;
318  time_marker last_ping;
319  enum { LOCATOR_PACKETS=16 } ;
320
321  public :
322  void *low_paragraph;
323
324  enum { CONNECT_PING_RETRY=10,     // retry connetc command every .1 seconds
325         CONNECT_RETRY_TOTAL=2400  // retry for 4 mins.
326       } ;
327         
328  closed_secure_ipx_socket *closed_list;
329
330  uchar local_addr[10];
331
332  virtual net_address *get_local_address();
333  virtual net_address *get_node_address(char *&server_name, int def_port, int force_port);
334  virtual net_socket *connect_to_server(net_address *addr,
335                                        net_socket::socket_type sock_type=net_socket::SOCKET_SECURE
336                                        ); 
337  virtual net_socket *create_listen_socket(int port, net_socket::socket_type sock_type, char *sock_name);
338
339  int select(int block);
340
341  int installed();
342
343  char *name()    { return "IPX driver"; }
344  void add_socket_to_list(ipx_net_socket *who);
345  void remove_socket_from_list(ipx_net_socket *who);
346
347  int max_packet_data_size() { int x=max_pksz-sizeof(ipx_net_socket::ipx_packet::IPXPacketStructure);  // max IPX will allow
348                               if (x>ipx_net_socket::IPX_PACKET_SIZE)                      // max space we have
349                                  return ipx_net_socket::IPX_PACKET_SIZE; else return x;
350                             }
351  void clear_sockets(ipx_net_socket *exclude);
352  ipx_net_socket *socket_origination(uchar *addr, ushort other_port);     // finds a socket connected to address, started from port 'port'
353  void add_closed(ipx_net_socket::ipx_packet *pk, int total_packets, int fd, int packet_on);
354  void cleanup();
355  int free_closed_socket();       // returns 1 if able to close 1 closed socket in FIN state
356  int socket_can_be_allocated(int num_packets);
357  ipx_net_protocol();
358  void show_socks();
359  ~ipx_net_protocol();
360
361  net_address *find_address(int port, char *name);
362  void reset_find_list();
363} ;
364
365extern ipx_net_protocol ipx_net;
366
367
368#endif
369
Note: See TracBrowser for help on using the repository browser.