source: abuse/trunk/src/net/tcpip.hpp @ 97

Last change on this file since 97 was 97, checked in by Sam Hocevar, 14 years ago
  • Updated the Mac OS X port, thanks to Julian Mayer.
File size: 6.6 KB
Line 
1#include "sock.hpp"
2
3#include <stdlib.h>
4#include <fcntl.h>
5#include <sys/ioctl.h>
6#include <sys/stat.h>
7#include <sys/types.h>
8#include <signal.h>
9#include <sys/types.h>
10#include "isllist.hpp"
11
12#if (defined(__APPLE__) && !defined(__MACH__))
13#include "GUSI.h"
14#else
15#include <netdb.h>
16#include <netinet/in.h>
17#include <stdio.h>
18#include <string.h>
19#include <sys/time.h>
20#include <sys/ipc.h>
21#include <sys/shm.h>
22#include <sys/socket.h>
23#include <unistd.h>
24#ifdef HAVE_BSTRING_H
25#include <bstring.h>
26#else
27#include <sys/select.h>
28#endif
29#endif
30
31extern fd_set master_set,master_write_set,read_set,exception_set,write_set;
32
33class ip_address : public net_address
34{
35public:
36  sockaddr_in addr;
37
38  virtual protocol protocol_type() const { return net_address::IP; }
39  virtual int equal(const net_address *who) const
40  //{{{
41  {
42    if (who->protocol_type()==IP &&
43        !memcmp(&addr.sin_addr,& ((ip_address const *)who)->addr.sin_addr,sizeof(addr.sin_addr)))
44      return 1;
45    else return 0;
46  }
47        //}}}
48  virtual int set_port(int port)  { addr.sin_port=htons(port); return 1; }
49  ip_address(sockaddr_in *Addr) { memcpy(&addr,Addr,sizeof(addr)); }
50  virtual void print()
51  //{{{
52  {
53    unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr);
54    fprintf(stderr,"%d.%d.%d.%d",c[0],c[1],c[2],c[3]);
55  }
56        //}}}
57  int get_port() { return htons(addr.sin_port); }
58  net_address *copy()  { return new ip_address(&addr); }
59  ip_address() {} ;
60  void store_string(char *st, int st_length)
61  //{{{
62  {
63    char buf[100];
64    unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr);
65    sprintf(buf,"%d.%d.%d.%d:%d",c[0],c[1],c[2],c[3],htons(addr.sin_port));
66    strncpy(st,buf,st_length);
67    st[st_length-1]=0;   
68  }
69  //}}}
70} ;
71
72class tcpip_protocol : public net_protocol
73{
74protected:
75  // Request Data
76  struct RequestItem
77  {
78        ip_address *addr;
79        char name[256];   //name
80  };
81  typedef isllist<RequestItem *>::iterator p_request;
82  isllist<RequestItem*> servers,returned;
83
84  // Notification Data
85  net_socket *notifier;
86  char notify_data[512];
87  int notify_len;
88
89  net_socket *responder;
90  ip_address *bcast;
91
92  int handle_notification();
93  int handle_responder();
94public :
95  fd_set master_set,master_write_set,read_set,exception_set,write_set;
96
97  tcpip_protocol();
98  net_address *get_local_address();
99  net_address *get_node_address(char const *&server_name, int def_port, int force_port);
100  net_socket *connect_to_server(net_address *addr,
101        net_socket::socket_type sock_type=net_socket::SOCKET_SECURE);
102  net_socket *create_listen_socket(int port, net_socket::socket_type sock_type);
103  int installed() { return 1; }  // always part of unix
104  char const *name() { return "UNIX generic TCPIP"; }
105  void cleanup();
106  int select(int block);          // return # of sockets available for read & writing
107 
108  // Notification methods
109  virtual net_socket *start_notify(int port, void *data, int len);
110  virtual void end_notify();
111
112  // Find notifiers methods
113  virtual net_address *find_address(int port, char *name);   // name should be a 256 byte buffer
114  virtual void reset_find_list();
115  virtual ~tcpip_protocol() { cleanup(); }
116} ;
117
118extern tcpip_protocol tcpip;
119
120class unix_fd : public net_socket
121{
122  protected :
123  int fd;
124  public :
125  unix_fd(int fd) : fd(fd) { };
126  virtual int error()                             { return FD_ISSET(fd,&tcpip.exception_set); }
127  virtual int ready_to_read()                     { return FD_ISSET(fd,&tcpip.read_set); }
128  virtual int ready_to_write()                   
129  {
130    struct timeval tv={0,0};     // don't wait
131    fd_set write_check; 
132    FD_ZERO(&write_check); 
133    FD_SET(fd,&write_check);     
134    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
135    return FD_ISSET(fd,&write_check);
136  }
137  virtual int write(void const *buf, int size, net_address *addr=NULL);
138  virtual int read(void *buf, int size, net_address **addr);
139
140  virtual ~unix_fd()                            { read_unselectable();  write_unselectable(); close(fd); }
141  virtual void read_selectable()                   { FD_SET(fd,&tcpip.master_set); }
142  virtual void read_unselectable()                 { FD_CLR(fd,&tcpip.master_set); }
143  virtual void write_selectable()                  { FD_SET(fd,&tcpip.master_write_set); }
144  virtual void write_unselectable()                { FD_CLR(fd,&tcpip.master_write_set); }
145  int get_fd() { return fd; }
146 
147  void broadcastable();
148} ;
149
150class tcp_socket : public unix_fd
151{
152  int listening;
153  public :
154  tcp_socket(int fd) : unix_fd(fd) { listening=0; };
155  virtual int listen(int port)
156  {
157    sockaddr_in host;
158    memset( (char*) &host,0, sizeof(host));
159    host.sin_family = AF_INET;
160    host.sin_port = htons(port);
161    host.sin_addr.s_addr = htonl(INADDR_ANY);
162    if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
163    {
164      fprintf(stderr,"net driver : could not bind socket to port %d\n",port);
165      return 0;
166    }
167    if (::listen(fd,5)==-1)
168    {
169      fprintf(stderr,"net driver : could not listen to socket on port %d\n",port);   
170      return 0;
171    }
172    listening=1;
173    return 1;
174  }
175  virtual net_socket *accept(net_address *&addr)
176  {
177    if (listening)
178    {
179      struct sockaddr_in from;
180      socklen_t addr_len=sizeof(from);
181      int new_fd=::accept(fd,(sockaddr *)&from,&addr_len);
182      if (new_fd>=0)
183      {
184        addr=new ip_address(&from);
185        return new tcp_socket(new_fd);
186      }
187      else
188      { addr=NULL; return 0; }
189    }
190    return 0;
191  }
192} ;
193
194class udp_socket : public unix_fd
195{
196  public :
197  udp_socket(int fd) : unix_fd(fd) { };
198  virtual int read(void *buf, int size, net_address **addr)
199  {
200    int tr;
201    if (addr)
202    {
203      *addr=new ip_address;
204      socklen_t addr_size=sizeof(sockaddr_in);
205      tr=recvfrom(fd,buf,size,0, (sockaddr *) &((ip_address *)(*addr))->addr,&addr_size);
206    } else
207      tr=recv(fd,buf,size,0);
208    return tr;
209  }
210  virtual int write(void const *buf, int size, net_address *addr=NULL)
211  {
212    if (addr)
213      return sendto(fd,buf,size,0,(sockaddr *)(&((ip_address *)addr)->addr),sizeof(((ip_address *)addr)->addr));
214    else
215      return ::write(fd,(char*)buf,size);     
216  }
217  virtual int listen(int port)
218  {
219    sockaddr_in host;
220    memset( (char*) &host,0, sizeof(host));
221    host.sin_family = AF_INET;
222    host.sin_port = htons(port);
223    host.sin_addr.s_addr = htonl(INADDR_ANY);
224    if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
225    {
226      fprintf(stderr,"net driver : could not bind socket to port %d\n",port);
227      return 0;
228    }
229    return 1;
230  }
231
232} ;
233
Note: See TracBrowser for help on using the repository browser.