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