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

Last change on this file since 150 was 150, checked in by holiday, 14 years ago

Point tcpip debug logs at /tmp

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