source: abuse/tags/pd/abuse/src/net/unix/tcpip.c @ 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.
  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1#include "tcpip.hpp"
2#include <ctype.h>
3
4tcpip_protocol tcpip;
5
6/*
7FILE *log_file=NULL;
8extern int net_start();
9void net_log(char *st, void *buf, long size)
10{
11   
12  if (!log_file)
13  {
14    if (net_start())
15      log_file=fopen("client.log","wb");
16    else
17      log_file=fopen("server.log","wb");
18  }
19
20
21    fprintf(log_file,"%s%d - ",st,size);
22    int i;
23    for (i=0;i<size;i++)
24      if (isprint(*((unsigned char *)buf+i)))
25        fprintf(log_file,"%c",*((unsigned char *)buf+i));
26      else fprintf(log_file,"~");
27
28    fprintf(log_file," : ");
29
30    for (i=0;i<size;i++)
31    fprintf(log_file,"%02x, ",*((unsigned char *)buf+i),*((unsigned char *)buf+i));
32    fprintf(log_file,"\n");
33    fflush(log_file);
34
35} */
36
37
38int unix_fd::read(void *buf, int size, net_address **addr)
39{
40  int tr=::read(fd,buf,size);
41  if (addr) *addr=NULL;
42  return tr;
43}
44
45int unix_fd::write(void *buf, int size, net_address *addr)
46{
47  if (addr) fprintf(stderr,"Cannot change address for this socket type\n");
48  return ::write(fd,buf,size);
49}
50
51
52net_address *tcpip_protocol::get_local_address()
53{
54  char my_name[100];                              // now check to see if this address is 'hostname'
55  gethostname(my_name,100);
56  struct hostent *l_hn=gethostbyname(my_name); 
57  ip_address *a=new ip_address();
58  memset(&a->addr,0,sizeof(a->addr));
59  memcpy(&a->addr.sin_addr,*l_hn->h_addr_list,4); 
60}
61
62net_address *tcpip_protocol::get_node_address(char *&server_name, int def_port, int force_port)
63{
64  char name[256],*np;
65  np=name;
66  while (*server_name && *server_name!=':' && *server_name!='/')
67    *(np++)=*(server_name)++;
68  *np=0;
69  if (*server_name==':')
70  {
71    server_name++;
72    char port[256],*p;
73    p=port;
74    while (*server_name && *server_name!='/')
75      *(p++)=*(server_name++);
76    *p=0;
77    int x;
78    if (!force_port)
79    {
80      if (sscanf(port,"%d",&x)==1) def_port=x;
81      else return 0;
82    }
83  }
84
85  if (*server_name=='/') server_name++;
86
87  hostent *hp=gethostbyname(name);
88  if (!hp)
89  {
90    fprintf(stderr,"unable to locate server named '%s'\n",name);
91    return 0;
92  }
93 
94
95  sockaddr_in host;
96  memset( (char*) &host,0, sizeof(host));
97  host.sin_family = AF_INET;
98  host.sin_port = htons(def_port);
99  host.sin_addr.s_addr = htonl(INADDR_ANY);
100  memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
101  return new ip_address(&host);
102}
103
104net_socket *tcpip_protocol::connect_to_server(net_address *addr, net_socket::socket_type sock_type)
105{
106  if (addr->protocol_type()!=net_address::IP)
107  {
108    fprintf(stderr,"Procotol type not supported in the executable\n");
109    return NULL;
110  }
111
112  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
113  if (socket_fd<0)
114  {
115    fprintf(stderr,"unable to create socket (too many open files?)\n");
116    return 0;
117  }
118
119  int zz;
120  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
121  {
122    fprintf(stderr,"could not set socket option reuseaddr");
123    return 0;
124  }
125
126   
127  if (connect(socket_fd, (struct sockaddr *) &((ip_address *)addr)->addr, sizeof( ((ip_address *)addr)->addr ))==-1)
128  {
129    fprintf(stderr,"unable to connect\n");
130    close(socket_fd);
131    return 0;
132  }
133
134  if (sock_type==net_socket::SOCKET_SECURE)
135    return new tcp_socket(socket_fd);
136  else
137    return new udp_socket(socket_fd);
138}
139
140
141net_socket *tcpip_protocol::create_listen_socket(int port, net_socket::socket_type sock_type, char *name)
142{
143  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
144  if (socket_fd<0)
145  {
146    fprintf(stderr,"unable to create socket (too many open files?)\n");
147    return 0;
148  }
149/*  int zz;
150  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
151  {
152    fprintf(stderr,"could not set socket option reuseaddr");
153    return 0;
154  } */
155
156
157  net_socket *s;
158  if (sock_type==net_socket::SOCKET_SECURE)
159    s=new tcp_socket(socket_fd);
160  else s=new udp_socket(socket_fd);
161  if (s->listen(port)==0)
162  {   
163    delete s;
164    return 0;
165  }
166
167  return s;
168}
169
170
171tcpip_protocol::tcpip_protocol()
172{
173  FD_ZERO(&master_set); 
174  FD_ZERO(&master_write_set); 
175  FD_ZERO(&read_set);
176  FD_ZERO(&exception_set);
177  FD_ZERO(&write_set);
178}
179
180
181int tcpip_protocol::select(int block)
182{
183  memcpy(&read_set,&master_set,sizeof(master_set));
184  memcpy(&exception_set,&master_set,sizeof(master_set));
185  memcpy(&write_set,&master_write_set,sizeof(master_set));
186  if (block)
187    return ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
188  else
189  {
190    timeval tv={0,0};
191    return ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,&tv);
192  }
193}
194
195
196
197net_socket *tcpip_protocol::start_notify(int port, void *data, int len)
198//{{{
199{
200        if (responder)
201        {
202                delete responder;
203                delete bcast;
204                responder = 0;
205        }
206       
207        int resp_len = strlen(notify_response);
208  notify_len = len + resp_len + 1;
209  strcpy(notify_data,notify_response);
210        notify_data[resp_len] = '.';
211  memcpy(notify_data+resp_len+1,data,len);
212 
213  // create notifier socket
214#ifdef TCPIP_DEBUG
215        fprintf(stderr,"Creating notifier on port %d\n",port);
216#endif
217  notifier = create_listen_socket(port, net_socket::SOCKET_FAST);
218 
219  if (notifier)
220  {
221    notifier->read_selectable();
222    notifier->write_unselectable();
223  }
224  else
225                fprintf(stderr,"Couldn't start notifier\n");
226 
227  return notifier;
228}
229//}}}///////////////////////////////////
230
231
232void tcpip_protocol::end_notify()
233//{{{
234{
235  if (notifier)
236    delete notifier;
237  notifier = 0;
238
239  notify_len = 0;
240}
241//}}}///////////////////////////////////
242
243int tcpip_protocol::handle_notification()
244//{{{
245{
246  if (!notifier)
247    return 0;
248   
249  if (notifier->ready_to_read())
250  {
251    char buf[513];
252    int len;
253    // got a notification request "broadcast"
254    ip_address *addr;
255
256#ifdef TCPIP_DEBUG
257                printf("Notifier: ");
258#endif
259
260    len = notifier->read(buf, 512, (net_address**)&addr);
261#ifdef TCPIP_DEBUG
262                if (len>0) {
263                        buf[len] = 0;
264                        printf("[%s] ",buf);
265                }
266#endif
267    if (addr && len>0)
268    {
269                        buf[len] = 0;
270      if  (strcmp(buf, notify_signature)==0) {
271                                char s[256];
272#ifdef TCPIP_DEBUG
273                                addr->store_string(s,256);
274                                printf("responding to %s",s);
275#endif
276        // send notification data to requester
277        notifier->write(notify_data,notify_len,addr);
278                        }
279       
280      delete addr;
281    }
282#ifdef TCPIP_DEBUG
283                printf("\n");
284#endif
285    return 1;
286  }
287  if (notifier->error())
288  {
289    fprintf(stderr,"Error on notification socket!\n");
290    return 1;
291  }
292
293  return 0;
294}
295//}}}///////////////////////////////////
296
297net_address *tcpip_protocol::find_address(int port, char *name)
298//{{{
299{
300  // name should be a 256 byte buffer
301        char s[256];
302
303        end_notify();
304
305  if (!responder) {
306//#ifdef TCPIP_DEBUG
307                fprintf(stderr,"Creating responder on port %d\n",port);
308//#endif
309    responder = create_listen_socket(port, net_socket::SOCKET_FAST);
310                responder->read_selectable();
311                responder->write_unselectable();
312    bcast = (ip_address *)get_local_address();
313    bcast->set_port(port);
314   
315//#ifdef TCPIP_DEBUG
316                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 255;
317                bcast->store_string(s,256);
318                fprintf(stderr,"Simulating broadcast to [%s]\n",s);
319//#endif
320
321                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 0;             
322        }
323
324  if (responder)
325  {
326    int i;
327   
328    for (i=0; i<5; i++)
329    {
330#ifdef TCPIP_DEBUG
331                        bcast->store_string(s,256);
332                        fprintf(stderr,"\r[%s]",s);
333#endif
334            int found = 0;
335           
336            for (p_request p = servers.begin(); !found && p!=servers.end(); ++p)
337                if ( *((*p)->addr) == *bcast )
338                        found = 1;
339            for (p_request q = returned.begin(); !found && q!=returned.end(); ++q)
340                if ( *((*q)->addr) == *bcast )
341                        found = 1;
342                       
343                        if (!found) {
344                                responder->write((void*)notify_signature,
345                                                                                                 strlen(notify_signature),bcast);
346                                select(0);
347                        }
348            *((unsigned char *)(&bcast->addr.sin_addr)+3) += 1;
349       
350            select(0);
351           
352            if (!servers.empty())
353                break;
354                }
355  }
356 
357  if (servers.empty())
358    return 0;
359
360  servers.move_next(servers.begin_prev(), returned.begin_prev());
361        ip_address *ret = (ip_address*)(*returned.begin())->addr->copy();
362        strcpy(name,(*returned.begin())->name);
363
364#ifdef TCPIP_DEBUG
365        ret->store_string(s,256);
366        fprintf(stderr,"Found [%s]\n",s);
367#endif
368
369  return ret;
370}
371//}}}///////////////////////////////////
372
373void tcpip_protocol::reset_find_list()
374//{{{
375{
376        p_request p;
377       
378        for (p=servers.begin(); p!=servers.end(); ++p)
379                delete (*p)->addr;
380        for (p=returned.begin(); p!=returned.end(); ++p)
381                delete (*p)->addr;
382               
383  servers.erase_all();
384  returned.erase_all();
385}
386//}}}///////////////////////////////////
Note: See TracBrowser for help on using the repository browser.