source: abuse/tags/pd/macabuse/src/net/unix/tcpip.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: 5.5 KB
Line 
1#include "sock.hpp"
2
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <fcntl.h>
7#include <unistd.h>
8#include <sys/ioctl.h>
9#include <sys/stat.h>
10#include <sys/types.h>
11#include <sys/time.h>
12#include <string.h>
13#include <signal.h>
14#include <sys/socket.h>
15#include <netinet/in.h>
16#include <sys/types.h>
17#include <sys/ipc.h>
18#include <sys/shm.h>
19#include <bstring.h>
20#include <netdb.h>
21
22#ifdef __MAC__
23#define SLOW()
24#else
25#define SLOW() usleep(1000)
26#endif
27
28
29extern fd_set master_set,master_write_set,read_set,exception_set,write_set;
30
31
32class ip_address : public net_address
33{
34
35  public :
36  sockaddr_in addr;
37
38  virtual protocol protocol_type() const { return net_address::IP; }
39  virtual equal(const net_address *who) const
40  {
41    if (who->protocol_type()==IP &&
42        !memcmp(&addr.sin_addr,& ((ip_address *)who)->addr.sin_addr,sizeof(addr.sin_addr)))
43      return 1;
44    else return 0;
45  }
46  virtual int set_port(int port)  { addr.sin_port=htons(port); }
47  ip_address(sockaddr_in *Addr) { memcpy(&addr,Addr,sizeof(addr)); }
48  virtual void print()
49  {
50    unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr);
51    fprintf(stderr,"%d.%d.%d.%d",c[0],c[1],c[2],c[3]);
52  }
53  int get_port() { return htons(addr.sin_port); }
54  net_address *copy()  { return new ip_address(&addr); }
55  ip_address() {} ;
56  void store_string(char *st, int st_length)
57  {
58    char buf[100];
59    unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr);
60    sprintf(buf,"%d.%d.%d.%d:%d",c[0],c[1],c[2],c[3],htons(addr.sin_port));
61    strncpy(st,buf,st_length);
62    st[st_length-1]=0;   
63  }
64} ;
65
66class tcpip_protocol : public net_protocol
67{
68
69  public :
70  fd_set master_set,master_write_set,read_set,exception_set,write_set;
71
72  tcpip_protocol();
73  net_address *get_local_address();
74  net_address *get_node_address(char *&server_name, int def_port, int force_port);
75  net_socket *connect_to_server(net_address *addr,
76                                net_socket::socket_type sock_type=net_socket::SOCKET_SECURE);
77  net_socket *create_listen_socket(int &port, net_socket::socket_type sock_type);
78  int installed() { return 1; }  // always part of unix
79  char *name() { return "UNIX generic TCPIP"; }
80  void cleanup() { ; }
81  int select(int block);          // return # of sockets available for read & writing
82} ;
83
84extern tcpip_protocol tcpip;
85
86class unix_fd : public net_socket
87{
88  protected :
89  int fd;
90  public :
91  unix_fd(int fd) : fd(fd) {
92  };
93  virtual int error()                             { return FD_ISSET(fd,&tcpip.exception_set); }
94  virtual int ready_to_read()                     { return FD_ISSET(fd,&tcpip.read_set); }
95  virtual int ready_to_write()                   
96  {
97    struct timeval tv={0,0};     // don't wait
98    fd_set write_check; 
99    FD_ZERO(&write_check); 
100    FD_SET(fd,&write_check);     
101    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
102    return FD_ISSET(fd,&write_check);
103  }
104  virtual int write(void *buf, int size, net_address *addr=NULL);
105  virtual int read(void *buf, int size, net_address **addr);
106
107  virtual ~unix_fd()                            { read_unselectable();  write_unselectable(); close(fd);
108  }
109  virtual void read_selectable()                   { FD_SET(fd,&tcpip.master_set); }
110  virtual void read_unselectable()                 { FD_CLR(fd,&tcpip.master_set); }
111  virtual void write_selectable()                  { FD_SET(fd,&tcpip.master_write_set); }
112  virtual void write_unselectable()                { FD_CLR(fd,&tcpip.master_write_set); }
113  int get_fd() { return fd; }
114} ;
115
116class tcp_socket : public unix_fd
117{
118  int listening;
119  public :
120  tcp_socket(int fd) : unix_fd(fd) { listening=0; };
121  virtual int listen(int port)
122  {
123    sockaddr_in host;
124    memset( (char*) &host,0, sizeof(host));
125    host.sin_family = AF_INET;
126    host.sin_port = htons(port);
127    host.sin_addr.s_addr = htonl(INADDR_ANY);
128    if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
129    {
130      fprintf(stderr,"net driver : could not bind socket to port %d\n",port);
131      return 0;
132    }
133    if (::listen(fd,5)==-1)
134    {
135      fprintf(stderr,"net driver : could not listen to socket on port %d\n",port);   
136      return 0;
137    }
138    listening=1;
139    return 1;
140  }
141  virtual net_socket *accept(net_address *&addr)
142  {
143    if (listening)
144    {
145      struct sockaddr_in from;
146      int addr_len=sizeof(from);
147      int new_fd=::accept(fd,(sockaddr *)&from,&addr_len);
148      if (new_fd>=0)
149      {
150        addr=new ip_address(&from);
151        return new tcp_socket(new_fd);
152      }
153      else
154      { addr=NULL; return 0; }
155    }
156  }
157} ;
158
159class udp_socket : public unix_fd
160{
161  public :
162  udp_socket(int fd) : unix_fd(fd) { };
163  virtual int read(void *buf, int size, net_address **addr)
164  {
165    SLOW();
166    int tr;
167    if (addr)
168    {
169      *addr=new ip_address;
170      int addr_size=sizeof(ip_address::addr);
171      tr=recvfrom(fd,buf,size,0, (sockaddr *) &((ip_address *)(*addr))->addr,&addr_size);
172    } else
173      tr=recv(fd,buf,size,0);
174    return tr;
175  }
176  virtual int write(void *buf, int size, net_address *addr=NULL)
177  {
178    SLOW();
179    if (addr)
180      return sendto(fd,buf,size,0,(sockaddr *)(&((ip_address *)addr)->addr),
181                    sizeof(((ip_address *)addr)->addr));
182    else
183      return ::write(fd,buf,size);     
184  }
185  virtual int listen(int port)
186  {
187    sockaddr_in host;
188    memset( (char*) &host,0, sizeof(host));
189    host.sin_family = AF_INET;
190    host.sin_port = htons(port);
191    host.sin_addr.s_addr = htonl(INADDR_ANY);
192    if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
193    {
194      fprintf(stderr,"net driver : could not bind socket to port %d\n",port);
195      return 0;
196    }
197    return 1;
198  }
199
200} ;
201
Note: See TracBrowser for help on using the repository browser.