source: abuse/trunk/src/net/include/ipx.hpp @ 17

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