home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / abuse / src / net / unix / gserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-10  |  11.3 KB  |  461 lines

  1. #include "system.h"
  2. #include "macs.hpp"
  3. #include "gserver.hpp"
  4. #include "netface.hpp"
  5. #include "timing.hpp"
  6. #include "netcfg.hpp"
  7. #include "id.hpp"
  8. #include "jwindow.hpp"
  9. #include "input.hpp"
  10.  
  11. extern base_memory_struct *base;
  12. extern net_socket *comm_sock,*game_sock;
  13. extern int registered;
  14.  
  15. extern net_protocol *prot;
  16. extern join_struct *join_array;
  17. extern window_manager *eh;
  18. extern char *symbol_str(char *name);
  19. extern void service_net_request();
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <sys/stat.h>
  26. #include <sys/types.h>
  27. #include <string.h>
  28. #include <signal.h>
  29.  
  30.  
  31. game_server::game_server()
  32. {
  33.   player_list=NULL;
  34.   waiting_server_input=1;
  35.   reload_state=0;
  36. }
  37.  
  38. int game_server::total_players()
  39. {
  40.   player_client *fl=player_list;
  41.   int total=1;
  42.   for (;fl;fl=fl->next) total++;
  43.   return total;
  44. }
  45.  
  46. void game_server::game_start_wait()
  47. {
  48.   int last_count=0;
  49.   jwindow *stat=NULL;
  50.   event ev;
  51.   int abort=0;
  52.   while (!abort && total_players()<main_net_cfg->min_players)
  53.   {
  54.     if (last_count!=total_players())
  55.     {
  56.       if (stat) eh->close_window(stat);
  57.       char msg[100];
  58.       sprintf(msg,symbol_str("min_wait"),main_net_cfg->min_players-total_players());
  59.       stat=eh->new_window(100,50,-1,-1,new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,msg,
  60.                        new button(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP+eh->font()->height()*2,
  61.                           ID_CANCEL,symbol_str("cancel_button"),NULL)  ));
  62.       eh->flush_screen();
  63.       last_count=total_players();
  64.     }
  65.  
  66.     if (eh->event_waiting())
  67.     {
  68.       do { eh->get_event(ev); }  while (ev.type==EV_MOUSE_MOVE && eh->event_waiting()); 
  69.       eh->flush_screen();
  70.       if (ev.type==EV_MESSAGE && ev.message.id==ID_CANCEL)
  71.         abort=1;
  72.     }
  73.     
  74.     service_net_request();
  75.   }
  76.   if (stat)
  77.   {
  78.     eh->close_window(stat);
  79.     eh->flush_screen();  
  80.   }
  81. }
  82.   
  83. game_server::player_client::~player_client()
  84. {
  85.   delete comm;
  86.   delete data_address;
  87. }
  88.  
  89. void game_server::check_collection_complete()
  90. {
  91.   player_client *c;
  92.   int got_all=waiting_server_input==0;
  93.   int add_deletes=0;
  94.   for (c=player_list;c && got_all;c=c->next)
  95.   {
  96.     if (c->delete_me())
  97.       add_deletes=1;
  98.     else if (c->has_joined() && c->wait_input())
  99.       got_all=0;
  100.   }
  101.  
  102.   if (add_deletes)
  103.   {
  104.     player_client *last=NULL;
  105.     for (c=player_list;c;)
  106.     {
  107.       if (c->delete_me())
  108.       {
  109.     base->packet.write_byte(SCMD_DELETE_CLIENT);
  110.     base->packet.write_byte(c->client_id);
  111.     if (c->wait_reload())
  112.     {
  113.       c->set_wait_reload(0);
  114.       check_reload_wait();
  115.     }
  116.  
  117.     if (last) last->next=c->next;
  118.     else player_list=c->next;
  119.     player_client *d=c;
  120.     c=c->next;
  121.     delete d;
  122.       } else 
  123.       {
  124.     last=c;
  125.     c=c->next;
  126.       }
  127.     }
  128.   }
  129.  
  130.   if (got_all)    // see if we have input from everyone, if so send it out
  131.   {   
  132.     base->packet.calc_checksum();
  133.  
  134.     for (c=player_list;c;c=c->next)      // setup for next time, wait for all the input
  135.     {
  136.       if (c->has_joined())
  137.       {
  138.     c->set_wait_input(1);      
  139.     game_sock->write(base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),c->data_address);
  140.  
  141.       }
  142.     }
  143.  
  144.     base->input_state=INPUT_PROCESSING; // tell engine to start processing
  145.     game_sock->read_unselectable();    // don't listen to this socket until we are prepared to read next tick's game data
  146.     waiting_server_input=1;
  147.   }  
  148. }
  149.  
  150. void game_server::add_engine_input()
  151. {
  152.   waiting_server_input=0;
  153.   base->input_state=INPUT_COLLECTING;
  154.   base->packet.set_tick_received(base->current_tick);
  155.   game_sock->read_selectable();    // we can listen for game data now that we have server input
  156.   check_collection_complete();
  157. }
  158.  
  159. void game_server::add_client_input(char *buf, int size, player_client *c)
  160. {
  161.   if (c->wait_input())  // don't add if we already have it
  162.   {
  163.     base->packet.add_to_packet(buf,size);
  164.     c->set_wait_input(0);
  165.     check_collection_complete();
  166.   }
  167. }
  168.  
  169. void game_server::check_reload_wait()
  170. {
  171.   player_client *d=player_list;
  172.   for (;d;d=d->next) 
  173.    if (d->wait_reload()) return ;    // we are still waiting for someone to reload the game 
  174.   base->wait_reload=0;
  175. }
  176.  
  177. int game_server::process_client_command(player_client *c)
  178. {
  179.   uchar cmd;
  180.   if (c->comm->read(&cmd,1)!=1) return 0;
  181.   switch (cmd)
  182.   {
  183.     case CLCMD_REQUEST_RESEND :
  184.     {
  185.       uchar tick;
  186.       if (c->comm->read(&tick,1)!=1) return 0;
  187.  
  188.       fprintf(stderr,"request for resend tick %d (game cur=%d, pack=%d, last=%d)\n",
  189.           tick,base->current_tick,base->packet.tick_received(),base->last_packet.tick_received());
  190.  
  191.       if (tick==base->last_packet.tick_received())
  192.       {
  193.     net_packet *pack=&base->last_packet;      
  194.     game_sock->write(pack->data,pack->packet_size()+pack->packet_prefix_size(),c->data_address); 
  195.       }
  196.       return 1;
  197.     } break;
  198.     case CLCMD_RELOAD_START :
  199.     {
  200.       if (reload_state)   // already in reload state, notify client ok to start reloading
  201.       {
  202.         if (c->comm->write(&cmd,1)!=1) 
  203.       c->set_delete_me(1);
  204.       } else c->set_need_reload_start_ok(1);
  205.       return 1;
  206.     } break;
  207.  
  208.     case CLCMD_RELOAD_END :
  209.     {
  210.       c->set_wait_reload(0);
  211.       return 1;
  212.     } break;
  213.     case CLCMD_UNJOIN :
  214.     {
  215.       c->comm->write(&cmd,1);        // don't care weither this works or not
  216.       c->set_delete_me(1);
  217.       if (base->input_state==INPUT_COLLECTING)
  218.         check_collection_complete();
  219.     } break;
  220.   }
  221.   return 0;
  222. }
  223.  
  224.  
  225. int game_server::process_net()
  226. {
  227.   int ret=0;
  228.   /**************************       Any game data waiting?       **************************/
  229.   if ((base->input_state==INPUT_COLLECTING ||
  230.        base->input_state==INPUT_RELOAD)
  231.        && game_sock->ready_to_read())
  232.   {
  233.     net_packet tmp;
  234.     net_packet *use=&tmp;
  235.     net_address *from;
  236.     int bytes_received=game_sock->read(use->data,PACKET_MAX_SIZE,&from);
  237.  
  238.     if (from && bytes_received)
  239.     {
  240.       // make sure we got a complete packet and the packet was not a previous game tick packet
  241.       if (bytes_received==use->packet_size()+use->packet_prefix_size())
  242.       {
  243.     unsigned short rec_crc=use->get_checksum();
  244.     if (rec_crc==use->calc_checksum())
  245.     {
  246.       player_client *f=player_list,*found=NULL;
  247.       for (;!found &&f;f=f->next)
  248.       if (f->has_joined() && from->equal(f->data_address))
  249.         found=f;
  250.       if (found)
  251.       {
  252.         if (base->current_tick==use->tick_received())          
  253.         {
  254.           if (prot->debug_level(net_protocol::DB_MINOR_EVENT))
  255.             fprintf(stderr,"(got data from %d)",found->client_id);
  256.  
  257. //          fprintf(stderr,"(got packet %d)\n",use->tick_received()); 
  258. //          { time_marker now,start; while (now.diff_time(&start)<5.0) now.get_time(); } 
  259.  
  260.           if (base->input_state!=INPUT_RELOAD)
  261.             add_client_input((char *)use->packet_data(),use->packet_size(),found);
  262.  
  263.         }
  264.         else if (use->tick_received()==base->last_packet.tick_received())
  265.         {
  266.           if (prot->debug_level(net_protocol::DB_IMPORTANT_EVENT))
  267.             fprintf(stderr,"(sending old %d)\n",use->tick_received());          
  268.  
  269.           // if they are sending stale data we need to send them the last packet so they can catchup
  270.           net_packet *pack=&base->last_packet;      
  271.           game_sock->write(pack->data,pack->packet_size()+pack->packet_prefix_size(),found->data_address); 
  272.  
  273.         } else if (prot->debug_level(net_protocol::DB_MAJOR_EVENT))
  274.           fprintf(stderr,"received stale packet (got %d, expected %d)\n",use->tick_received(),base->current_tick);
  275.  
  276.       } else
  277.       {
  278.         if (prot->debug_level(net_protocol::DB_MAJOR_EVENT))
  279.         {
  280.           fprintf(stderr,"received data from unknown client\n");
  281.           printf("from address "); from->print();
  282.           printf(" first addr "); player_list->data_address->print(); printf("\n");
  283.         }
  284.       }
  285.  
  286.     } else fprintf(stderr,"received packet with bad checksum\n");
  287.       } else fprintf(stderr,"received incomplete packet\n");
  288.     } else if (!from)
  289.       fprintf(stderr,"received data and no from\n");
  290.     else if (!bytes_received)
  291.       fprintf(stderr,"received 0 byte data\n");
  292.     ret=1;
  293.     if (from) delete from;
  294.  
  295.   }
  296.  
  297.  
  298.   /**************************       Any client with commands?       **************************/
  299.   player_client *c;
  300.   for (c=player_list;c;c=c->next)  
  301.     if (c->comm->error() || (c->comm->ready_to_read() && !process_client_command(c)))
  302.     {
  303.       c->set_delete_me(1);
  304.       check_collection_complete();
  305.     }
  306.     else ret=1;
  307.   
  308.   return 1;
  309. }
  310.  
  311.  
  312. int game_server::input_missing()
  313. {
  314.  
  315.   return 1;
  316. }
  317.  
  318.  
  319.  
  320. int game_server::end_reload(int disconnect)  // notify evryone you've reloaded the level (at server request)
  321. {  
  322.   player_client *c=player_list;
  323.   prot->select(0);
  324.  
  325.   for (;c;c=c->next) 
  326.     if (!c->delete_me() && c->wait_reload()) 
  327.     {
  328.       if (disconnect)
  329.         c->set_delete_me(1);
  330.       else return 0;
  331.     }
  332.  
  333.   for (c=player_list;c;c=c->next)   
  334.     c->set_has_joined(1);
  335.   reload_state=0;
  336.   
  337.   return 1;
  338. }
  339.  
  340. int game_server::start_reload()
  341. {
  342.   player_client *c=player_list;
  343.   reload_state=1;
  344.   prot->select(0);
  345.  
  346.   for (;c;c=c->next) 
  347.   {
  348.     if (!c->delete_me() && c->need_reload_start_ok())    // if the client is already waiting for reload state to start, send ok
  349.     {
  350.       uchar cmd=CLCMD_RELOAD_START;
  351.       if (c->comm->write(&cmd,1)!=1) { c->set_delete_me(1); }
  352.       c->set_need_reload_start_ok(0);
  353.     }
  354.     c->set_wait_reload(1);
  355.   }
  356.   return 1;
  357. }
  358.  
  359.  
  360. int game_server::isa_client(int client_id)
  361. {
  362.   player_client *c=player_list;
  363.   if (!client_id) return 1;
  364.   for (;c;c=c->next) if (c->client_id==client_id) return 1;
  365.   return 0;   
  366. }
  367.  
  368. int game_server::add_client(int type, net_socket *sock, net_address *from)
  369. {
  370.   if (type==CLIENT_ABUSE)
  371.   {
  372.  
  373.     if (total_players()>=main_net_cfg->max_players)
  374.     {
  375.       uchar too_many=2;
  376.       sock->write(&too_many,1);
  377.       return 0;
  378.     }
  379.  
  380.     uchar reg=registered ? 1 : 0;
  381.     if (sock->write(®,1)!=1)  
  382.       return 0;
  383.  
  384.  
  385.     ushort our_port=lstl(main_net_cfg->port+1),cport;
  386.     char name[256];
  387.     uchar len;
  388.     short nkills=lstl(main_net_cfg->kills);
  389.     
  390.     if (sock->read(&len,1)!=1 ||
  391.     sock->read(name,len)!=len ||
  392.     sock->read(&cport,2)!=2 ||
  393.         sock->write(&our_port,2)!=2 ||
  394.     sock->write(&nkills,2)!=2)
  395.       return 0;
  396.  
  397.     cport=lstl(cport);
  398.  
  399.     
  400.     int f=-1,i;
  401.     for (i=0;f==-1 && i<MAX_JOINERS;i++)
  402.       if (!isa_client(i))
  403.       {
  404.         f=i;
  405.  
  406.     join_struct *j=base->join_list;
  407.     for (;j;j=j->next)
  408.       if (j->client_id==i)
  409.         f=-1;
  410.       }
  411.  
  412.  
  413.     if (f==-1) return 0;    
  414.  
  415.  
  416.     from->set_port(cport);
  417.  
  418.     ushort client_id=lstl(f);
  419.     if (sock->write(&client_id,2)!=2) { return 0; }
  420.     client_id=f;
  421.  
  422.     join_array[client_id].next=base->join_list;
  423.     base->join_list=&join_array[client_id];
  424.     join_array[client_id].client_id=client_id;
  425.     strcpy(join_array[client_id].name,name);   
  426.     player_list=new player_client(f,sock,from,player_list);
  427.  
  428.     return 1;
  429.   } else return 0;
  430. }
  431.  
  432. int game_server::kill_slackers()
  433. {
  434.   player_client *c=player_list;
  435.   for (;c;c=c->next)
  436.     if (c->wait_input())
  437.       c->set_delete_me(1);
  438.   check_collection_complete();  
  439.   return 1;
  440. }
  441.  
  442. int game_server::quit()
  443. {
  444.   player_client *c=player_list;  
  445.   while (c)
  446.   {
  447.     player_client *d=c;
  448.     c=c->next;
  449.     delete c;
  450.   }
  451.   player_list=NULL;
  452.   return 1;
  453. }
  454.  
  455.  
  456. game_server::~game_server()
  457. {
  458.   quit();
  459. }
  460.  
  461.