source: abuse/trunk/src/net/tcpip.cpp @ 48

Last change on this file since 48 was 40, checked in by Sam Hocevar, 14 years ago
  • Fix a few more warnings.
  • Remove -Wshadow from the warnings because it is too verbose for now.
  • Remove warning flags that have no meaning in C++.
File size: 14.3 KB
Line 
1#ifdef _AIX
2#include <strings.h>
3#endif
4
5#if (defined(__APPLE__) && !defined(__MACH__))
6#include "GUSI.h"
7#endif
8#include "tcpip.hpp"
9#include <ctype.h>
10
11extern tcpip_protocol tcpip;
12
13//#define TCPIP_DEBUG
14
15//{{{ net logging stuff
16/*
17FILE *log_file=NULL;
18extern int net_start();
19void net_log(char *st, void *buf, long size)
20{
21   
22  if (!log_file)
23  {
24    if (net_start())
25      log_file=fopen("client.log","wb");
26    else
27      log_file=fopen("server.log","wb");
28  }
29
30
31    fprintf(log_file,"%s%d - ",st,size);
32    int i;
33    for (i=0;i<size;i++)
34      if (isprint(*((unsigned char *)buf+i)))
35        fprintf(log_file,"%c",*((unsigned char *)buf+i));
36      else fprintf(log_file,"~");
37
38    fprintf(log_file," : ");
39
40    for (i=0;i<size;i++)
41    fprintf(log_file,"%02x, ",*((unsigned char *)buf+i),*((unsigned char *)buf+i));
42    fprintf(log_file,"\n");
43    fflush(log_file);
44
45} */
46//}}}
47
48////////////////////////////////////////////////////////////////////////
49//
50//  unix_fd methods
51//
52
53int unix_fd::read(void *buf, int size, net_address **addr)
54//{{{
55{
56  int tr=::read(fd,(char*)buf,size);
57  if (addr) *addr=NULL;
58  return tr;
59}
60//}}}///////////////////////////////////
61
62int unix_fd::write(void const *buf, int size, net_address *addr)
63//{{{
64{
65  if (addr) fprintf(stderr,"Cannot change address for this socket type\n");
66  return ::write(fd,(char*)buf,size);
67}
68//}}}///////////////////////////////////
69
70void unix_fd::broadcastable()
71//{{{
72{
73  int zz;
74  if (setsockopt(fd,SOL_SOCKET,SO_BROADCAST,(char *)&zz,sizeof(zz))<0)
75  {
76    fprintf(stderr,"could not set socket option broadcast");
77    return;
78  }
79}
80//}}}///////////////////////////////////
81
82////////////////////////////////////////////////////////////////////////
83//
84//  tcpip_protocol methods
85//
86
87net_address *tcpip_protocol::get_local_address()
88//{{{
89{
90#if 0
91        struct hostent *l_hn=gethostent();
92
93        ip_address *a=new ip_address();
94        memset(&a->addr,0,sizeof(a->addr));
95        memcpy(&a->addr.sin_addr,*l_hn->h_addr_list,4); 
96
97        return a; 
98#else
99  char my_name[100];                                            // check to see if this address is 'hostname'
100  gethostname(my_name,100);
101  //ip_address *ret = 0;
102 
103  if (my_name[0]<'0' || my_name[0]>'9')
104  {
105        struct hostent *l_hn=gethostbyname(my_name);
106       
107        if (l_hn)
108        {
109                ip_address *a=new ip_address();
110                memset(&a->addr,0,sizeof(a->addr));
111                memcpy(&a->addr.sin_addr,*l_hn->h_addr_list,4); 
112       
113                return a;
114          }
115          else
116          {
117                  printf("Enter ip address:");
118                  fgets(my_name, sizeof( my_name ), stdin );
119          }
120        } 
121
122  char tmp[4];
123  char const *np;
124  sockaddr_in host;
125 
126  np = my_name;
127  for (int i=0; i<4; i++)
128  {
129    int num = 0;
130    while (*np)
131    {
132      if (*np=='.')
133      {
134        np++;
135        break;
136      }
137      num = num*10 + *np - '0';
138      np++;
139    }
140    tmp[i] = num;
141  }
142 
143  memset( (char*) &host,0, sizeof(host));
144  host.sin_family = AF_INET;
145  host.sin_addr.s_addr = htonl(INADDR_ANY);
146  memcpy(&host.sin_addr,tmp,sizeof(in_addr));
147 
148        return new ip_address(&host);
149#endif
150}
151//}}}///////////////////////////////////
152
153net_address *tcpip_protocol::get_node_address(char const *&server_name,
154                                                                                                                                                                                        int def_port, int force_port)
155//{{{
156{
157    sockaddr_in host;
158
159    if (server_name[0]>='0' && server_name[0]<='9')
160    {
161        char tmp[4];
162        char const *np;
163         
164          np = server_name;
165          for (int i=0; i<4; i++)
166          {
167            int num = 0;
168            while (*np && *np!=':')
169            {
170              if (*np=='.')
171              {
172                np++;
173                break;
174              }
175              num = num*10 + *np - '0';
176              np++;
177            }
178            tmp[i] = num;
179            if (*np == ':' & !force_port)
180            {
181                int x;
182              if (sscanf(np+1,"%d",&x)==1)
183                def_port=x;
184                  }
185          }
186         
187          memset( (char*) &host,0, sizeof(host));
188          host.sin_family = AF_INET;
189          host.sin_port = htons(def_port);
190          host.sin_addr.s_addr = htonl(INADDR_ANY);
191          memcpy(&host.sin_addr,tmp,sizeof(in_addr));
192         
193          return new ip_address(&host);
194        }
195        else
196        {
197          char name[256], *np;
198
199          np=name;
200          while (*server_name && *server_name!=':' && *server_name!='/')
201            *(np++)=*(server_name)++;
202          *np=0;
203          if (*server_name==':')
204          {
205            server_name++;
206            char port[256],*p;
207            p=port;
208            while (*server_name && *server_name!='/')
209              *(p++)=*(server_name++);
210            *p=0;
211            int x;
212            if (!force_port)
213            {
214              if (sscanf(port,"%d",&x)==1) def_port=x;
215              else return 0;
216            }
217          }
218       
219          if (*server_name=='/') server_name++;
220       
221          hostent *hp=gethostbyname(name);
222          if (!hp)
223          {
224            fprintf(stderr,"unable to locate server named '%s'\n",name);
225            return 0;
226          }
227         
228          memset( (char*) &host,0, sizeof(host));
229          host.sin_family = AF_INET;
230          host.sin_port = htons(def_port);
231          host.sin_addr.s_addr = htonl(INADDR_ANY);
232          memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
233        }
234  return new ip_address(&host);
235}
236//}}}///////////////////////////////////
237
238net_socket *tcpip_protocol::connect_to_server(net_address *addr, net_socket::socket_type sock_type)
239//{{{
240{
241  if (addr->protocol_type()!=net_address::IP)
242  {
243    fprintf(stderr,"Procotol type not supported in the executable\n");
244    return NULL;
245  }
246
247  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
248  if (socket_fd<0)
249  {
250    fprintf(stderr,"unable to create socket (too many open files?)\n");
251    return 0;
252  }
253
254#if (defined(__APPLE__) && !defined(__MACH__))
255  int zz;
256  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
257  {
258    fprintf(stderr,"could not set socket option reuseaddr");
259    return 0;
260  }
261#endif
262   
263  if (connect(socket_fd, (struct sockaddr *) &((ip_address *)addr)->addr, sizeof( ((ip_address *)addr)->addr ))==-1)
264  {
265    fprintf(stderr,"unable to connect\n");
266    close(socket_fd);
267    return 0;
268  }
269
270  if (sock_type==net_socket::SOCKET_SECURE)
271    return new tcp_socket(socket_fd);
272  else
273    return new udp_socket(socket_fd);
274}
275//}}}///////////////////////////////////
276
277net_socket *tcpip_protocol::create_listen_socket(int port, net_socket::socket_type sock_type)
278//{{{
279{
280  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
281  if (socket_fd<0)
282  {
283    fprintf(stderr,"unable to create socket (too many open files?)\n");
284    return 0;
285  }
286
287#if (defined(__APPLE__) && !defined(__MACH__))
288  int zz;
289  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
290  {
291    fprintf(stderr,"could not set socket option reuseaddr");
292    return 0;
293  }
294#endif
295
296  net_socket *s;
297  if (sock_type==net_socket::SOCKET_SECURE)
298    s=new tcp_socket(socket_fd);
299  else s=new udp_socket(socket_fd);
300  if (s->listen(port)==0)
301  {   
302    delete s;
303    return 0;
304  }
305
306  return s;
307}
308//}}}///////////////////////////////////
309
310net_socket *tcpip_protocol::start_notify(int port, void *data, int len)
311//{{{
312{
313        if (responder)
314        {
315                delete responder;
316                delete bcast;
317                responder = 0;
318        }
319       
320        int resp_len = strlen(notify_response);
321  notify_len = len + resp_len + 1;
322  strcpy(notify_data,notify_response);
323        notify_data[resp_len] = '.';
324  memcpy(notify_data+resp_len+1,data,len);
325 
326  // create notifier socket
327#ifdef TCPIP_DEBUG
328        fprintf(stderr,"Creating notifier on port %d\n",port);
329#endif
330  notifier = create_listen_socket(port, net_socket::SOCKET_FAST);
331 
332  if (notifier)
333  {
334    notifier->read_selectable();
335    notifier->write_unselectable();
336  }
337  else
338                fprintf(stderr,"Couldn't start notifier\n");
339 
340  return notifier;
341}
342//}}}///////////////////////////////////
343
344void tcpip_protocol::end_notify()
345//{{{
346{
347  if (notifier)
348    delete notifier;
349  notifier = 0;
350
351  notify_len = 0;
352}
353//}}}///////////////////////////////////
354
355int tcpip_protocol::handle_notification()
356//{{{
357{
358  if (!notifier)
359    return 0;
360   
361  if (notifier->ready_to_read())
362  {
363    char buf[513];
364    int len;
365    // got a notification request "broadcast"
366    ip_address *addr;
367    net_address *tmp;
368
369#ifdef TCPIP_DEBUG
370                printf("Notifier: ");
371#endif
372
373    len = notifier->read(buf, 512, &tmp);
374    addr = (ip_address *)tmp;
375#ifdef TCPIP_DEBUG
376                if (len>0) {
377                        buf[len] = 0;
378                        printf("[%s] ",buf);
379                }
380#endif
381    if (addr && len>0)
382    {
383                        buf[len] = 0;
384      if  (strcmp(buf, notify_signature)==0) {
385#ifdef TCPIP_DEBUG
386                                char s[256];
387                                addr->store_string(s,256);
388                                printf("responding to %s",s);
389#endif
390        // send notification data to requester
391        notifier->write(notify_data,notify_len,addr);
392                        }
393       
394      delete addr;
395    }
396#ifdef TCPIP_DEBUG
397                printf("\n");
398#endif
399    return 1;
400  }
401  if (notifier->error())
402  {
403    fprintf(stderr,"Error on notification socket!\n");
404    return 1;
405  }
406
407  return 0;
408}
409//}}}///////////////////////////////////
410
411net_address *tcpip_protocol::find_address(int port, char *name)
412//{{{
413{
414  // name should be a 256 byte buffer
415        char s[256];
416
417        end_notify();
418
419  if (!responder) {
420//#ifdef TCPIP_DEBUG
421                fprintf(stderr,"Creating responder on port %d\n",port);
422//#endif
423    responder = create_listen_socket(port, net_socket::SOCKET_FAST);
424                responder->read_selectable();
425                responder->write_unselectable();
426    bcast = (ip_address *)get_local_address();
427    bcast->set_port(port);
428   
429//#ifdef TCPIP_DEBUG
430                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 255;
431                bcast->store_string(s,256);
432                fprintf(stderr,"Simulating broadcast to [%s]\n",s);
433//#endif
434
435                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 0;             
436        }
437
438  if (responder)
439  {
440    int i;
441   
442    for (i=0; i<5; i++)
443    {
444#ifdef TCPIP_DEBUG
445                        bcast->store_string(s,256);
446                        fprintf(stderr,"\r[%s]",s);
447#endif
448            int found = 0;
449           
450            for (p_request p = servers.begin(); !found && p!=servers.end(); ++p)
451                if ( *((*p)->addr) == *bcast )
452                        found = 1;
453            for (p_request q = returned.begin(); !found && q!=returned.end(); ++q)
454                if ( *((*q)->addr) == *bcast )
455                        found = 1;
456                       
457                        if (!found) {
458                                responder->write((void*)notify_signature,
459                                                                                                 strlen(notify_signature),bcast);
460                                select(0);
461                        }
462            *((unsigned char *)(&bcast->addr.sin_addr)+3) += 1;
463       
464            select(0);
465           
466            if (!servers.empty())
467                break;
468                }
469  }
470 
471  if (servers.empty())
472    return 0;
473
474  servers.move_next(servers.begin_prev(), returned.begin_prev());
475        ip_address *ret = (ip_address*)(*returned.begin())->addr->copy();
476        strcpy(name,(*returned.begin())->name);
477
478#ifdef TCPIP_DEBUG
479        ret->store_string(s,256);
480        fprintf(stderr,"Found [%s]\n",s);
481#endif
482
483  return ret;
484}
485//}}}///////////////////////////////////
486
487void tcpip_protocol::reset_find_list()
488//{{{
489{
490        p_request p;
491       
492        for (p=servers.begin(); p!=servers.end(); ++p)
493                delete (*p)->addr;
494        for (p=returned.begin(); p!=returned.end(); ++p)
495                delete (*p)->addr;
496               
497  servers.erase_all();
498  returned.erase_all();
499}
500//}}}///////////////////////////////////
501
502int tcpip_protocol::handle_responder()
503//{{{
504{
505  if (!responder)
506    return 0;
507   
508  if (responder->ready_to_read())
509  {
510    char buf[513];
511    int len;
512    // got a notification response
513    ip_address *addr;
514    net_address *tmp;
515
516#ifdef TCPIP_DEBUG
517                fprintf(stderr,"Responder: ");
518#endif
519
520    len = responder->read(buf, 512, &tmp);
521    addr = (ip_address *)tmp;
522
523#ifdef TCPIP_DEBUG
524                if (len>0) {
525                        buf[len] = 0;
526                        fprintf(stderr,"[%s] ",buf);
527                }
528#endif
529    if (addr && len>0)
530    {
531        buf[len] = 0;
532      buf[4] = 0;                                                                                               // ack! hard coded numbers for now
533      if (strcmp(buf,notify_response)==0)
534      {
535        int found=0;
536        for (p_request p = servers.begin(); !found && p!=servers.end(); ++p)
537                if ( *((*p)->addr) == *addr)
538                        found = 1;
539                    for (p_request q = returned.begin(); !found && q!=returned.end(); ++q)
540                        if ( *((*q)->addr) == *addr )
541                                found = 1;
542                       
543        if (!found)
544        {
545#ifdef TCPIP_DEBUG
546                                        char s[256];
547#endif
548                                        RequestItem *r = new RequestItem;
549                                        r->addr = addr;
550                                        strcpy(r->name,buf+5);                                  // ack hard coded numbers for now
551              servers.insert(r);
552#ifdef TCPIP_DEBUG
553                                        addr->store_string(s,256);
554                                        fprintf(stderr,"accepted %s",s);
555#endif
556                                }
557                        }
558      else {
559        delete addr;
560                        }
561    }
562#ifdef TCPIP_DEBUG
563    fprintf(stderr,"\n");
564#endif
565
566    return 1;
567  }
568  if (responder->error())
569  {
570    fprintf(stderr,"Error on responder socket!\n");
571    return 1;
572  }
573
574  return 0;
575}
576//}}}///////////////////////////////////
577
578tcpip_protocol::tcpip_protocol()
579//{{{
580  : notifier(0), notify_len(0), responder(0)
581{
582#if (defined(__APPLE__) && !defined(__MACH__))
583  GUSISetup(GUSIwithSIOUXSockets);
584  GUSISetup(GUSIwithPPCSockets);
585#endif 
586  FD_ZERO(&master_set); 
587  FD_ZERO(&master_write_set); 
588  FD_ZERO(&read_set);
589  FD_ZERO(&exception_set);
590  FD_ZERO(&write_set);
591}
592//}}}///////////////////////////////////
593
594int tcpip_protocol::select(int block)
595//{{{
596{
597  int ret;
598 
599  memcpy(&read_set,&master_set,sizeof(master_set));
600  memcpy(&exception_set,&master_set,sizeof(master_set));
601  memcpy(&write_set,&master_write_set,sizeof(master_set));
602  if (block)
603  {
604    ret = 0;
605    while (ret == 0) {
606      // get number of sockets ready from system call
607      ret = ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
608
609      // remove notifier & responder events from the count of sockets selected
610      if (handle_notification())
611        ret--;
612      if (handle_responder())
613        ret--;
614    }
615  }
616  else
617  {
618    timeval tv={0,0};
619    // get number of sockets ready from system call
620    ret = ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,&tv);
621
622    // remove notifier & responder events from the count of sockets selected
623    if (handle_notification())
624      ret--;
625    if (handle_responder())
626      ret--;
627  }
628  return ret;
629}
630//}}}///////////////////////////////////
631
632void tcpip_protocol::cleanup()
633//{{{
634{
635        if (notifier)
636                end_notify();
637               
638        reset_find_list();
639               
640        if (responder) {
641                delete responder;
642                delete bcast;
643                responder = 0;
644        }
645}
646//}}}///////////////////////////////////
647
648//{{{ Revision Log
649/*//////////////////////////////////////////////////////////////////////
650$Log$
651//////////////////////////////////////////////////////////////////////
652*/
653//}}}
654
655//{{{ Emacs Locals
656// Local Variables:
657// folded-file: t
658// End:
659//}}}
660
Note: See TracBrowser for help on using the repository browser.