home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / net / unix / netdrv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  15.4 KB  |  596 lines

  1. #include "fileman.hpp"
  2. #include "netdrv.hpp"
  3. #include "gserver.hpp"
  4. #include "gclient.hpp"
  5. #include "undrv.hpp"
  6. #include "tcpip.hpp"
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/stat.h>
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <string.h>
  17. #include <signal.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <sys/types.h>
  21. #include <sys/ipc.h>
  22. #include <sys/shm.h>
  23. #include <bstring.h>
  24. #include <netdb.h>
  25.  
  26. #define real2shm(type,ptr) (ptr==NULL ? NULL : ((type *)((char *)(ptr)-(char *)base)))
  27. #define shm2real(type,ptr) (ptr==NULL ? NULL : ((type *)((long)(ptr)+(long)(base))))
  28.  
  29. net_driver *driver=NULL;
  30.  
  31. #ifdef __sgi
  32. #define next_process() sginap(0)
  33. #else
  34. #define next_process() usleep(10)
  35. #endif
  36.  
  37.  
  38. #ifdef __sgi
  39. void die(...)
  40. #else
  41. void die(int why)
  42. #endif
  43.   fprintf(stderr,"dieing\n");
  44.   if (driver) { delete driver; driver=NULL; }
  45.   exit(0);
  46. }
  47.  
  48.  
  49. void mdie(char *reason)
  50. {
  51.   fprintf(stderr,"net driver : %s\n",reason);
  52.   if (driver) { driver->cleanup(); }
  53.   exit(0);
  54. }
  55.  
  56. void comm_failed()  // general communication failure with engine
  57. {
  58.   fprintf(stderr,"net driver : Error occured while trying to communicate with the engine\n");
  59.   if (driver) { delete driver; driver=NULL; }
  60.   exit(0);
  61. }
  62.  
  63. int net_driver::add_joiner(int client_id, char *name)
  64. {
  65.   join_array[client_id].next=base->join_list;
  66.   base->join_list=real2shm(join_struct,&join_array[client_id]);
  67.   join_array[client_id].client_id=client_id;
  68.   strcpy(join_array[client_id].name,name);
  69. }
  70.  
  71.  
  72. void net_driver::cleanup()
  73. {
  74.   base->input_state=INPUT_NET_DEAD;
  75.   fprintf(stderr,"net driver : cleaning up\n");
  76.   if (shm_seg_id!=-1)
  77.     shmctl(shm_seg_id,IPC_RMID,NULL);
  78.   if (shm_addr!=(void *)-1) 
  79.   {
  80.     shmdt((char *)shm_addr);
  81.     shm_addr=(void *)-1;
  82.   }
  83.  
  84.   undrv_cleanup();
  85.   unlink(DLOCK_NAME);
  86. }
  87.  
  88. net_driver::~net_driver()
  89. {
  90.   cleanup();
  91. }
  92.  
  93. int net_driver::setup_shm()
  94. {
  95.   shm_addr=(void *)-1;  // shmat returns -1 on failure
  96.   shm_seg_id=-1;
  97.  
  98.   driver=this;
  99.   int catch_sigs[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,
  100.             SIGIOT,SIGFPE,SIGKILL,SIGUSR1,SIGSEGV,
  101.             SIGUSR2,SIGPIPE,SIGTERM,SIGCHLD,
  102.             SIGCONT,SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU,-1};
  103.  
  104.   int i;
  105.   for (i=0;catch_sigs[i]!=-1;i++)     // catch all signals in case we get
  106.     signal(catch_sigs[i],die);            // interrupted before we remove shmid
  107.  
  108.  
  109.   int alloc_size=sizeof(join_struct)*MAX_JOINERS+sizeof(base_memory_struct);
  110.  
  111.   shm_seg_id=shmget(IPC_PRIVATE,alloc_size,IPC_CREAT | 0777);
  112.  
  113.  
  114.   if (shm_seg_id==-1) mdie("Unable to allocate shared memory");
  115.  
  116.  
  117.   shm_addr=shmat(shm_seg_id,NULL,0);  // attach as read/write
  118.   if (shm_addr==(void *)-1) 
  119.     mdie("could not attach shm seg");
  120.  
  121.   base=(base_memory_struct *)shm_addr;
  122.  
  123.   base->join_list=real2shm(join_struct,NULL);
  124.   base->mem_lock=0;
  125.   base->calc_crcs=0;
  126.   base->get_lsf=0;
  127.   base->wait_reload=0;
  128.   base->need_reload=0;
  129.   base->input_state=INPUT_COLLECTING;
  130.   base->current_tick=0;
  131.   base->packet.packet_reset();
  132.   join_array=(join_struct *) (base+1);
  133.  
  134.   // see if we can attach this memory with the abuse engine
  135.   if (out->write(&shm_seg_id,sizeof(shm_seg_id))!=sizeof(shm_seg_id))
  136.     comm_failed();
  137.  
  138.   // wait for engine to ack it has attached
  139.   uchar ack=0;
  140.   if (in->read(&ack,1)!=1 || ack!=1)
  141.     comm_failed();
  142.  
  143.   
  144.   if (shmctl(shm_seg_id,IPC_RMID,NULL))  // remove the shm id
  145.     mdie("could not remove shm id");
  146.  
  147.   shm_seg_id=-1;                      // mark id as not allocated
  148.   return 1;
  149.  
  150. }
  151.  
  152. int net_driver::connect_to_engine(int argc, char **argv)
  153. {
  154.   if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  155.   { perror("Net driver : unable to make fifo in /tmp");
  156.     return 0;
  157.   }
  158.   chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);   // just to be sure umask doesn't screw us
  159.  
  160.   if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  161.   { perror("Net driver : unable to make fifo in /tmp");
  162.     return 0;
  163.   }
  164.   chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  165.  
  166.   int driver_out_fd=open(DOUT_NAME,O_RDWR);  // open the pipe
  167.   if (driver_out_fd<0)
  168.   { perror(DOUT_NAME); 
  169.     exit(1);
  170.   }
  171.  
  172.   int driver_in_fd=open(DIN_NAME,O_RDWR);
  173.   if (driver_in_fd<0)
  174.   { 
  175.     close(driver_out_fd);
  176.     perror(DIN_NAME); 
  177.     exit(1);
  178.   }
  179.  
  180.   in=new unix_fd(driver_in_fd);
  181.   in->read_selectable();
  182.   out=new unix_fd(driver_out_fd);
  183.   
  184.   if (in->read(®,sizeof(reg))!=sizeof(reg)) 
  185.     mdie("unable to registration from engine");
  186. }
  187.  
  188. net_driver::net_driver(int argc, char **argv, int comm_port, int game_port, net_protocol *proto) : 
  189.   comm_port(comm_port), game_port(game_port), proto(proto)
  190. {
  191.   debug=0;
  192.   lsf_wait_list=NULL;
  193.   crc_wait_list=NULL;
  194.  
  195.   base=NULL;
  196.   in=out=NULL;
  197.   game_face=new game_handler();
  198.  
  199.   connect_to_engine(argc,argv);
  200.   setup_shm();
  201.   int i;
  202.   for (i=1;i<argc;i++) if (!strcmp(argv[i],"-debug")) debug=1;
  203. }
  204.  
  205. int net_driver::become_server()
  206. {
  207.   delete game_face;
  208.   game_face=new game_server;
  209.   return 1;
  210. }
  211.  
  212. int net_driver::check_commands()
  213. {
  214.   int ret=0;
  215.   if (in->ready_to_read())       // commands from engine?
  216.   {
  217.     uchar cmd;
  218.     if (in->read(&cmd,1)!=1) return 0;
  219.  
  220.     if (debug)
  221.     {
  222.       if (cmd<=EGCMD_DIE)
  223.       {
  224.     char *cmds[]={"open","close","read","write","seek","size","tell","setfs","crc_calced","process_lsf","request_lfs",
  225.              "equest_entry","become_server","block","reload_start","reload_end","send_input","input_missing",
  226.               "kill_slackers","die"};
  227.     fprintf(stderr,"engine cmd : %s\n",cmds[cmd]);
  228.       }
  229.     }
  230.  
  231.     switch (cmd)
  232.     {
  233.       case EGCMD_DIE :
  234.       {
  235.     cmd=game_face->quit();
  236.     if (!out->write(&cmd,1)) { mdie("could not write block ack1"); }  // send something to unblock engine
  237.     mdie("received die command");
  238.       } break;
  239.  
  240.       case NFCMD_RELOAD_START :
  241.       {      
  242.     cmd=game_face->start_reload();
  243.     if (!out->write(&cmd,1)) { mdie("could not write start reload ack"); }  // send something to unblock engine    
  244.       } break;
  245.  
  246.       case NFCMD_RELOAD_END :
  247.       {      
  248.     cmd=game_face->end_reload();
  249.     if (!out->write(&cmd,1)) { mdie("could not write end reload ack"); }  // send something to unblock engine    
  250.       } break;
  251.  
  252.       case NFCMD_BLOCK :
  253.       {      
  254.     if (!out->write(&cmd,1)) { mdie("could not write block ack1"); }  // send something to unblock engine
  255.     if (!in->read(&cmd,1)) { mdie("could not read block ack1"); }  // send something to block ourself
  256.       } break;
  257.  
  258.       case NFCMD_INPUT_MISSING :    // try to fetch the input via a loss-less net protocol
  259.       {
  260.     game_face->input_missing();
  261.     if (out->write(&cmd,1)!=1) { mdie("could not write block ack1"); }  // send something to unblock engine
  262.       } break;
  263.       case NFCMD_KILL_SLACKERS :
  264.       {
  265.     if (!game_face->kill_slackers())
  266.     {
  267.       delete game_face;
  268.       game_face=new game_handler();
  269.     }
  270.     if (out->write(&cmd,1)!=1) { mdie("could not write block ack1"); }  // send something to unblock engine
  271.       } break;
  272.       case NFCMD_SEND_INPUT :
  273.       {
  274.     game_face->add_engine_input();
  275.     if (out->write(&cmd,1)!=1) { mdie("could not write send ack1"); }  // send something to unblock engine
  276.     if (in->read(&cmd,1)!=1) { mdie("could not read send ack2"); }    // read something to block ourselves for engine
  277.       } break;
  278.  
  279.  
  280.       case NFCMD_REQUEST_ENTRY :
  281.       {
  282.     uchar len;
  283.     char name[256];
  284.     if (in->read(&len,1)!=1) { mdie("could not read server name length"); }
  285.     if (in->read(name,len)!=len) { mdie("could not read server name"); }
  286.     ushort success=join_server(name);
  287.     if (out->write(&success,2)!=2) mdie("cound not send lsf read failure");      
  288.       } break;
  289.       case NFCMD_BECOME_SERVER :
  290.       {
  291.     cmd=become_server();    
  292.     if (out->write(&cmd,1)!=1) mdie("cound not send ok");
  293.       } break;
  294.       case NFCMD_REQUEST_LSF :
  295.       {
  296.     uchar len;
  297.     char name[256];
  298.     if (in->read(&len,1)!=1) { mdie("could not read lsf name length"); }
  299.     if (in->read(name,len)!=len) { mdie("could not read lsf name"); }
  300.     if (!get_lsf(name))
  301.     {
  302.       len=0;
  303.       if (out->write(&len,1)!=1) mdie("cound not send lsf read failure");
  304.     } else
  305.     {
  306.       len=strlen(name)+1;
  307.       if (out->write(&len,1)!=1) mdie("cound not send lsf name len");
  308.       if (out->write(name,len)!=len) mdie("cound not send lsf name");
  309.     }     
  310.       } break;
  311.  
  312.       case NFCMD_PROCESS_LSF :
  313.       {
  314.     uchar len,name[256];
  315.     if (in->read(&len,1)!=1) { mdie("could not read lsf name length"); }
  316.     if (in->read(name,len)!=len) { mdie("could not read lsf name"); }
  317.  
  318.     while (lsf_wait_list)
  319.     {
  320.       lsf_waiter *c=lsf_wait_list;
  321.       lsf_wait_list=lsf_wait_list->next;
  322.       uchar status=1;
  323.       c->sock->write(&len,1);
  324.       c->sock->write(name,len);
  325.       delete c;
  326.     }
  327.       } break;
  328.  
  329.       case NFCMD_CRCS_CALCED : 
  330.       {
  331.     while (crc_wait_list)
  332.     {
  333.       crc_waiter *c=crc_wait_list;
  334.       crc_wait_list=crc_wait_list->next;
  335.       uchar status=1;
  336.       c->sock->write(&status,1);
  337.       delete c;
  338.     }
  339.       } break;
  340.  
  341.       case NFCMD_SET_FS :
  342.       {
  343.     uchar size;
  344.     char sn[256];
  345.     if (in->read(&size,1)!=1) mdie("could not read filename length");
  346.     if (in->read(sn,size)!=size) mdie("could not read server name");
  347.     fman->set_default_fs_name(sn);
  348.  
  349.     size=fetch_crcs(sn);  // return success
  350.     if (out->write(&size,1)!=1) mdie("could not send ok to engine");
  351.       } break;    
  352.  
  353.       case NFCMD_OPEN :
  354.       {
  355.     uchar size[2];
  356.     char filename[300],mode[20],*fn;
  357.     fn=filename;
  358.     if (in->read(size,2)!=2  ||
  359.         in->read(filename,size[0])!=size[0] ||
  360.         in->read(mode,size[1])!=size[1]) 
  361.       mdie("incomplete open command from engine");
  362.     
  363.     int fd=fman->rf_open_file(fn,mode);
  364.     if (fd==-2)
  365.     {
  366.       uchar st[2];
  367.       st[0]=NF_OPEN_LOCAL_FILE;
  368.       st[1]=strlen(fn)+1;
  369.       if (out->write(st,2)!=2) comm_failed();
  370.       if (out->write(fn,st[1])!=st[1]) comm_failed();
  371.     } else if (fd==-1)
  372.     {
  373.       uchar st=NF_OPEN_FAILED;
  374.       if (out->write(&st,1)!=1) comm_failed(); 
  375.     } else
  376.     {
  377.       uchar st=NF_OPEN_REMOTE_FILE;
  378.       if (out->write(&st,1)!=1) comm_failed();     
  379.       if (out->write(&fd,sizeof(fd))!=sizeof(fd)) comm_failed();     
  380.     }
  381.       } break;
  382.       case NFCMD_CLOSE :
  383.       case NFCMD_SIZE :
  384.       case NFCMD_TELL :
  385.       case NFCMD_SEEK :
  386.       case NFCMD_READ :
  387.       {
  388.     int fd;
  389.     if (in->read(&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
  390.  
  391.     switch (cmd)
  392.     {
  393.       case NFCMD_CLOSE : 
  394.       { 
  395.         fman->rf_close(fd);
  396.         uchar st=1;
  397.         if (out->write(&st,1)!=1) comm_failed();     
  398.       } break;
  399.       case NFCMD_SIZE  :
  400.       {
  401.         long x=fman->rf_file_size(fd);
  402.         if (out->write(&x,sizeof(x))!=sizeof(x)) comm_failed();           
  403.       } break;
  404.       case NFCMD_TELL :
  405.       {
  406.         long offset=fman->rf_tell(fd);
  407.         if (out->write(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();  
  408.       } break;
  409.       case NFCMD_SEEK :
  410.       {
  411.         long offset;
  412.         if (in->read(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
  413.         offset=fman->rf_seek(fd,offset);
  414.         if (out->write(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();  
  415.       } break;
  416.       case NFCMD_READ :
  417.       {
  418.         long size;
  419.         if (in->read(&size,sizeof(size))!=sizeof(size)) comm_failed();
  420.         fman->rf_read(fd,out,size);
  421.       } break;
  422.     }
  423.       } break;    
  424.       default :
  425.       { fprintf(stderr,"net driver : unknown net command %d\n",cmd); die(0); }
  426.     }   
  427.     ret=1;
  428.   }
  429.  
  430.   ret|=game_face->process_net();
  431.   return ret;
  432. }
  433.  
  434.  
  435. int net_driver::join_server(char *server_name)   // ask remote server for entry into game
  436. {
  437.   char sn_start[256];
  438.   strcpy(sn_start,server_name);
  439.  
  440.   net_socket *sock=connect_to_server(server_name,DEFAULT_COMM_PORT,0);
  441.   if (!sock)
  442.   { 
  443.     fprintf(stderr,"unable to connect\n");
  444.     return 0;
  445.   }
  446.  
  447.   uchar ctype=CLIENT_ABUSE;
  448.   ushort port=lstl(game_port),cnum;
  449.  
  450.   uchar reg;
  451.   if (sock->write(&ctype,1)!=1 ||   // send server out game port
  452.       sock->read(®,1)!=1)        // is remote engine registered?
  453.   { delete sock; return 0; }
  454.  
  455.  
  456.   // maker sure the two games are both registered or unregistered or sync problems
  457.   // will occur.
  458.  
  459.   if (reg && !registered())
  460.   {
  461.     fprintf(stderr,
  462.         "Sorry, this server is running REGISTERED ABUSE and you are not.\n"
  463.         "Ask the server operator to run with -share option or better yet,\n"
  464.         "Buy ABUSE, registered net games are more fun because you can fly,\n"
  465.         "turn invisible and have more weapons to duke it out with\n");
  466.     delete sock; 
  467.     return 0;
  468.   } 
  469.  
  470.   if (!reg && registered())
  471.   {
  472.     fprintf(stderr,
  473.         "This is server is not running the registered version of abuse, and\n"
  474.         "you are (thanks!).  So that there are no conflict between the two games\n"
  475.         "please start with the -share option when connecting to this server\n"
  476.         "example : abuse -net somewhere.someplace.net -share\n");
  477.     delete sock;
  478.     return 0;
  479.   }
  480.  
  481.   char uname[256];
  482.   if (getlogin())
  483.     strcpy(uname,getlogin());
  484.   else strcpy(uname,"unknown");
  485.   uchar len=strlen(uname)+1;
  486.  
  487.   if (sock->write(&len,1)!=1 ||
  488.       sock->write(uname,len)!=len || 
  489.       sock->write(&port,2)!=2  ||            // send server out game port
  490.       sock->read(&port,2)!=2   ||            // read server's game port
  491.       sock->read(&cnum,2)!=2   || cnum==0    // read player number (cannot be 0 because 0 is server)
  492.       )
  493.   { delete sock; return 0; }
  494.  
  495.   port=lstl(port);
  496.   cnum=lstl(cnum);
  497.  
  498.   server_name=sn_start;
  499.   net_socket *data_sock=connect_to_server(server_name,port,1,net_socket::SOCKET_FAST);
  500.   if (!data_sock)  { delete sock; return 0; }
  501.  
  502.   delete game_face;
  503.   game_face=new game_client(sn_start,sock,data_sock);
  504.   return cnum;
  505. }
  506.  
  507.  
  508. net_socket *net_driver::connect_to_server(char *&name, int port, int force_port, 
  509.                       net_socket::socket_type sock_type)
  510. {
  511.   char *oname=name;
  512.   net_address *addr=proto->get_node_address(name, port, force_port);
  513.   if (!addr) 
  514.   {
  515.     if (debug) fprintf(stderr,"No IP address for name %s\n",oname);
  516.     return NULL;
  517.   }
  518.  
  519.   if (debug)
  520.     fprintf(stderr,"connecting to server %s\n",oname);
  521.   net_socket *sock=proto->connect_to_server(addr,sock_type);
  522.   delete addr;
  523.   return sock;
  524. }
  525.  
  526.  
  527. int net_driver::get_lsf(char *name)  // contact remot host and ask for lisp startup file filename
  528. {
  529.   char *name_start=name;
  530.   net_socket *sock=connect_to_server(name);
  531.   if (!sock) return 0;
  532.  
  533.   uchar ctype=CLIENT_LSF_WAITER;
  534.   uchar len;
  535.  
  536.   if (sock->write(&ctype,1)!=1 ||
  537.       sock->read(&len,1)!=1 || len==0 ||
  538.       sock->read(name_start,len)!=len)
  539.   {
  540.     delete sock; 
  541.     return 0;
  542.   } 
  543.  
  544.   delete sock;
  545.   return 1;  
  546. }
  547.  
  548.  
  549.  
  550. int net_driver::fetch_crcs(char *server)
  551. {
  552.   net_socket *sock=connect_to_server(server);
  553.   if (!sock) return 0;
  554.   uchar cmd=CLIENT_CRC_WAITER;
  555.   if (sock->write(&cmd,1)!=1 ||
  556.       sock->read(&cmd,1)!=1)  
  557.   { delete sock; return 0; }
  558.   delete sock;
  559.   return cmd;  
  560. }
  561.  
  562.  
  563. int net_driver::add_client(int type, net_socket *sock, net_address *from)
  564. {
  565.   switch (type)
  566.   {
  567.     case CLIENT_CRC_WAITER :
  568.     {
  569.       if (debug)
  570.         fprintf(stderr,"add crc waiter\n");
  571.  
  572.       crc_wait_list=new crc_waiter(sock,crc_wait_list);
  573.       base->calc_crcs=1;      
  574.       return 1;
  575.     } break;
  576.     case CLIENT_LSF_WAITER :
  577.     {
  578.       if (debug)
  579.         fprintf(stderr,"add lsf waiter\n");
  580.       lsf_wait_list=new lsf_waiter(sock,lsf_wait_list);
  581.       base->get_lsf=1;
  582.       return 1;
  583.     } break;
  584.     default :
  585.     {
  586.       int ret=game_face->add_client(type,sock,from);
  587.       if (!ret && debug)
  588.         fprintf(stderr,"unknown client type %d\n",type);
  589.       return ret;
  590.     }
  591.         
  592.   } 
  593.   return 0;
  594. }
  595.