source: abuse/tags/pd/abuse/src/net/unix/engine.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: 31.6 KB
RevLine 
[49]1#include "indian.hpp"
2#include "../inc/netface.hpp"      // net interface structures to the engine will use
3#include "netfile.hpp"
4#include "engine.hpp"
5
6// these are the names of the fifos to create in tmp
7// that communitcate with the engine
8
9#define DIN_NAME "/tmp/.abuse_ndrv_in"
10#define DOUT_NAME "/tmp/.abuse_ndrv_out"
11
12// the lock files is used in case a previous net driver is already running
13
14#define DLOCK_NAME "/tmp/.abuse_ndrv_lock"
15
16#ifdef __sgi
17#define next_process() sginap(0)
18#else
19#define next_process() usleep(10)
20#endif
21
22
23void net_watch();
24void setup_ports(int comm_port, int game_port);
25
26int no_security=0;
27int driver_out_fd,driver_in_fd;
28int shm_seg_id=-1;
29void *shm_addr=(void *)-1;  // shmat returns -1 on failure
30base_memory_struct *base;   // points to shm_addr
31int comm_fd=-1,             // listening socket for commincation port
32    game_fd=-1;
33char net_server[256];   // if -net option, fetch all files from "active server"
34int stand_alone=0;          // if we are running this stand-alone (not interfacing with the engine)
35
36fd_set master_set;
37fd_set master_write_set;    // set a socket here if you detect a write_full
38
39join_struct *join_array;      // points to an array of possible joining clients in shared memory
40int game_server_fd=-1,        // connection to server created by join_game()
41    game_server_data_fd=-1;
42
43int packet_port;              // port used to send 'lossy' game data
44
45void clean_up()      // on exit unattach all shared memory links
46
47  base->input_state=INPUT_NET_DEAD;
48  fprintf(stderr,"net driver : cleaning up\n");
49  if (shm_seg_id!=-1)
50    shmctl(shm_seg_id,IPC_RMID,NULL);
51
52  if (shm_addr!=(void *)-1)
53  {
54    shmdt((char *)shm_addr);
55    shm_addr=(void *)-1;
56  }
57
58  if (game_fd>0) close(game_fd);
59  if (comm_fd>0) close(comm_fd);
60
61  unlink(DIN_NAME);
62  unlink(DOUT_NAME);
63  unlink(DLOCK_NAME);
64}
65
66#ifdef __sgi
67void die(...)
68#else
69void die(int why)
70#endif
71{
72  fprintf(stderr,"dieing\n");
73  clean_up();
74  exit(0);
75}
76
77
78void mdie(char *reason)
79{
80  fprintf(stderr,"net driver : %s\n",reason);
81  die(0);
82}
83
84void comm_failed()  // general communication failure with engine
85{
86  fprintf(stderr,"net driver : Error occured while trying to communicate with the engine\n");
87  clean_up();
88  exit(0);
89}
90
91
92main(int argc, char **argv)
93{
94  int i;
95  strcpy(default_fs_name,"");          // initially no default file server
96  strcpy(net_server,"");
97
98  for (i=1;i<argc;i++)
99    if (!strcmp(argv[i],"-bastard"))   // this bypasses filename security features
100    {
101      fprintf(stderr,"Warning : Security measures bypassed (-bastard)\n");
102      no_security=1;
103    }
104
105
106  // make sure this program was run by the abuse engine
107  if (argc<2 || strcmp(argv[1],"runme"))   
108  {
109    stand_alone=1;
110    fprintf(stderr,"%s is normally run by abuse, running stand-alone file server\n"
111                   "Server will be killed by running abuse\n",argv[0]);
112  }
113
114
115  // see if we are already running, if so kill old driver
116  FILE *fp=fopen(DLOCK_NAME,"rb");
117  if (fp)
118  {
119    int pid;
120    if (fscanf(fp,"%d",&pid)==1)
121    {
122      struct stat st;
123      char proc_path[50];
124      sprintf(proc_path,"/proc/%d",pid);
125      if (!stat(proc_path,&st))
126      {
127        fprintf(stderr,"net driver : warning, %s already running, attempting to kill...\n",argv[0]);
128        if (kill(pid,SIGKILL))
129        {
130          fprintf(stderr,"net driver : unable to kill process %d, cannot run net-abuse\n",pid);
131          fclose(fp);
132          return 0;
133        }
134        fprintf(stderr,"killed process %d\n",pid);
135      }
136    }
137    fclose(fp);
138    unlink(DLOCK_NAME);   
139  }
140
141
142  unlink(DIN_NAME);    // remove any previous files if they exsists
143  unlink(DOUT_NAME);
144
145
146  if (!stand_alone)
147  {
148    if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
149    { perror("Net driver : unable to make fifo in /tmp");
150      return 0;
151    }
152    chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);   // just to be sure umask doesn't screw us
153
154    if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
155    { perror("Net driver : unable to make fifo in /tmp");
156      return 0;
157    }
158    chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
159
160    int i,no_fork=0;
161    for (i=1;i<argc;i++)
162    if (!strcmp(argv[i],"-no_fork"))    // use this to debug easier
163      no_fork=1;
164   
165    if (!no_fork)      // use this for debugging
166    {
167      int child_pid=fork();
168      if (child_pid)
169      {
170        FILE *fp=fopen(DLOCK_NAME,"wb");
171        if (!fp)
172        {
173          fprintf(stderr,"Unable to open %s for writing, killing child\n",DLOCK_NAME);
174          kill(child_pid,SIGKILL);
175          return 0;
176        }
177        fprintf(fp,"%d\n",child_pid);
178        fclose(fp);
179        printf("%d\n",child_pid);         // tell parent the sound driver's process number
180        return 0;                         // exit, child will continue
181      }
182    } 
183
184    driver_out_fd=open(DOUT_NAME,O_RDWR);  // open the pipe
185    if (driver_out_fd<0)
186    { perror(DOUT_NAME);
187      exit(1);
188    }
189
190    driver_in_fd=open(DIN_NAME,O_RDWR);
191    if (driver_in_fd<0)
192    { perror(DIN_NAME);
193      exit(1);
194    }
195  } else driver_in_fd=driver_out_fd=-1;
196
197
198
199  int catch_sigs[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,
200                    SIGIOT,SIGFPE,SIGKILL,SIGUSR1,SIGSEGV,
201                    SIGUSR2,SIGPIPE,SIGTERM,SIGCHLD,
202                    SIGCONT,SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU,-1};
203
204  for (i=0;catch_sigs[i]!=-1;i++)     // catch all signals in case we get
205    signal(catch_sigs[i],die);            // interrupted before we remove shmid
206
207
208/*  struct sigaction sa;
209  memset(&sa,0,sizeof(sa));
210  sa.sa_flags=SA_RESTART|SA_RESETHAND;
211  sa.sa_handler=send_sig;
212  sigaction(SIGUSR2,&sa,NULL); */
213
214
215  int alloc_size=sizeof(join_struct)*MAX_JOINERS+
216                 sizeof(base_memory_struct);
217
218  shm_seg_id=shmget(IPC_PRIVATE,alloc_size,IPC_CREAT | 0777);
219  if (shm_seg_id==-1)
220    mdie("Unable to allocate shared memory");
221
222
223  shm_addr=shmat(shm_seg_id,NULL,0);  // attach as read/write
224  if (shm_addr==(void *)-1)
225    mdie("could not attach shm seg");
226
227  base=(base_memory_struct *)shm_addr;
228
229  base->join_list=real2shm(join_struct,NULL);
230  base->mem_lock=0;
231  base->calc_crcs=0;
232  base->get_lsf=0;
233  base->wait_reload=0;
234  base->need_reload=0;
235  base->input_state=INPUT_COLLECTING;
236  base->current_tick=0;
237  base->packet.packet_reset();
238
239
240
241  if (!stand_alone)
242  {
243    // see if we can attach this memory with the abuse engine
244    if (write(driver_out_fd,&shm_seg_id,sizeof(shm_seg_id))!=sizeof(shm_seg_id))
245      comm_failed();
246
247    // wait for engine to ack it has attached
248    uchar ack=0;
249    if (read(driver_in_fd,&ack,1)!=1 || ack!=1)
250      comm_failed();
251  }
252
253 
254  if (shmctl(shm_seg_id,IPC_RMID,NULL))  // remove the shm id
255    mdie("could not remove shm id");
256
257  shm_seg_id=-1;                      // mark as not allocated
258
259
260  int comm_port=DEFAULT_COMM_PORT;
261  int game_port=-1;
262  for (i=1;i<argc-1;i++)
263    if (!strcmp(argv[i],"-port"))
264    {
265      comm_port=atoi(argv[i+1]);
266      if (game_port==-1)
267        game_port=comm_port+1;
268    }
269    else if (!strcmp(argv[i],"-game_port"))
270      game_port=atoi(argv[i+1]);
271    else if (!strcmp(argv[i],"-net"))
272    { strcpy(net_server,argv[i+1]); }
273
274  if (game_port==-1) game_port=DEFAULT_GAME_PORT+1;
275
276  setup_ports(comm_port,game_port);
277
278
279  net_watch();                        // now go into infinite block/read/process cycle
280
281  return 0;
282}
283
284client *first_client=NULL;
285
286
287void setup_ports(int comm_port, int game_port)
288{
289  sockaddr_in host;
290
291
292  game_fd=socket(AF_INET,SOCK_DGRAM,0);
293  if (game_fd==-1)
294    mdie("net driver : could not create a socket.  (too many open files?)");
295
296  int zz;
297  if (setsockopt(game_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
298    mdie("could not set socket option reuseaddr");
299
300//  if (fcntl(game_fd,F_SETFL,FNDELAY)==-1)
301//    mdie("cound not set udp socket to non-blocking");
302
303 
304  packet_port=game_port;   // save this port, so we can send it on joining a game
305  memset( (char*) &host,0, sizeof(host));
306  host.sin_family = AF_INET;
307  host.sin_port = lstl(game_port);
308  host.sin_addr.s_addr = lltl (INADDR_ANY);
309  if (bind(game_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
310  {
311    fprintf(stderr,"net driver : could not bind socket to port %d\n",game_port);
312    die(0);
313  }
314
315
316  // the comminication socket is a STREAM
317  comm_fd=socket(AF_INET,SOCK_STREAM,0);
318  if (comm_fd==-1)
319    mdie("net driver : could not create a socket.  (too many open files?)");
320
321
322  memset( (char*) &host,0, sizeof(host));
323  host.sin_family = AF_INET;
324  host.sin_port = lstl(comm_port);
325  host.sin_addr.s_addr = lltl (INADDR_ANY);
326  if (bind(comm_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
327  {
328    fprintf(stderr,"net driver : could not bind socket to port %d",comm_port);
329    die(0);
330  }
331
332  if (listen(comm_fd,5)==-1)
333  {
334    fprintf(stderr,"net driver : could not listen to socket on port %d\n",comm_port);   
335    die(0);
336  }
337
338
339
340
341}
342
343
344void delete_client(client *c)
345{
346  FD_CLR(c->socket_fd,&master_set);   // don't listen to this client anymore
347
348}
349
350
351inline int aquire_mem_lock()
352{
353  if (base->mem_lock==0 || base->mem_lock==1)
354  {
355    base->mem_lock=1;
356    if (base->mem_lock==1)
357      return 1;
358  }
359  return 0;
360}
361
362class crc_waiter
363{
364  public :
365  int socket_fd;
366  crc_waiter *next;
367  crc_waiter(int fd, crc_waiter *Next)
368  {
369    FD_SET(fd,&master_set);   // set in case socket dies
370    socket_fd=fd;
371    next=Next;
372  } ;
373  ~crc_waiter()
374  {
375    close(socket_fd);
376    FD_CLR(socket_fd,&master_set);
377  }   
378} *crc_wait_list=NULL;
379
380class lsf_waiter
381{
382  public :
383  int socket_fd;
384  lsf_waiter *next;
385  lsf_waiter(int fd, lsf_waiter *Next)
386  {
387    FD_SET(fd,&master_set);   // set in case socket dies
388    socket_fd=fd;
389    next=Next;
390  } ;
391  ~lsf_waiter()
392  {
393    close(socket_fd);
394    FD_CLR(socket_fd,&master_set);
395  }   
396} *lsf_wait_list=NULL;
397
398
399int connect_to_server(char *&server_name, int def_port, int stream_type, int force_port)
400{
401  char name[256],*np;
402  np=name;
403  while (*server_name && *server_name!=':' && *server_name!='/')
404    *(np++)=*(server_name)++;
405  *np=0;
406  if (*server_name==':')
407  {
408    server_name++;
409    char port[256],*p;
410    p=port;
411    while (*server_name && *server_name!='/')
412      *(p++)=*(server_name++);
413    *p=0;
414    int x;
415    if (!force_port)
416    {
417      if (sscanf(port,"%d",&x)==1) def_port=x;
418      else return -1;
419    }
420  }
421
422  if (*server_name=='/') server_name++;
423
424  if (local_address(name))    // returns 1 if server name is ourself
425  {
426    fprintf(stderr,"cannot connect to %s, is a local address\n");
427    return -1;
428  }
429 
430  int socket_fd=socket(AF_INET,stream_type,0);
431  if (socket_fd<0)
432  {
433    fprintf(stderr,"unable to create socket (too many open files?)\n");
434    return -1;
435  }
436
437 
438  hostent *hp=gethostbyname(name);
439  if (!hp)
440  {
441    fprintf(stderr,"unable to locate server named '%s'\n",name);
442    close(socket_fd);
443    return 0;
444  }
445 
446
447  sockaddr_in host;
448  memset( (char*) &host,0, sizeof(host));
449  host.sin_family = AF_INET;
450  host.sin_port = lstl(def_port);
451  host.sin_addr.s_addr = lltl (INADDR_ANY);
452  memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
453   
454  if (connect(socket_fd, (struct sockaddr *) &host, sizeof(host))==-1)
455  {
456    fprintf(stderr,"unable to connect\n");
457    close(socket_fd);
458    return -1;
459  }
460
461  return socket_fd;
462}
463
464int get_lsf(char *name)  // contact remot host and ask for lisp startup file filename
465{
466  char *name_start=name;
467  int fd=connect_to_server(name);
468  if (fd<0) return 0;
469  uchar ctype=CLIENT_LSF_WAITER;
470  if (write(fd,&ctype,1)!=1) { close(fd); return 0; }
471  uchar len;
472  if (read(fd,&len,1)!=1 || len==0) { close(fd); return 0; }
473  if (read(fd,name_start,len)!=len) { close(fd); return 0; }
474  close(fd);
475  return 1; 
476}
477
478int join_game(char *server_name)   // ask remote server for entry into game
479{
480  char sn_start[256];
481  strcpy(sn_start,server_name);
482
483  int fd=connect_to_server(server_name);
484  uchar ctype=CLIENT_ABUSE;
485  if (write(fd,&ctype,1)!=1) { close(fd); return 0; }
486
487  // send server out game port
488  ushort port=lstl(packet_port);
489  if (write(fd,&port,2)!=2) { close(fd); return 0; }
490
491  // read server's game port
492  if (read(fd,&port,2)!=2) { close(fd); return 0; }
493  port=lstl(port);
494
495  ushort cnum;
496  if (read(fd,&cnum,2)!=2 || cnum==0) { close(fd); return 0; }
497  cnum=lstl(cnum);
498
499 
500  game_server_fd=fd;
501
502  server_name=sn_start;
503  game_server_data_fd=connect_to_server(server_name,port,SOCK_DGRAM,1);
504  if (game_server_data_fd<0) mdie("could not udp-connect to server");
505  FD_SET(game_server_fd,&master_set);
506
507  return cnum;
508}
509
510void join_new_players()  // during this section we are giving mem_lock by engine
511{
512  client *c=first_client;
513
514  for (;c;c=c->next)     // tell all the clients to reload
515  {
516    if (!c->has_joined)
517    {
518      ushort cnum=lstl(c->client_id);
519      if (write(c->socket_fd,&cnum,2)!=2) { c->delete_me=1; }
520      c->wait_reload=1;
521      c->has_joined=1;
522    } else if (!c->delete_me)
523    {
524      uchar reload=CLCMD_RELOAD;
525      if (write(c->socket_fd,&reload,1)!=1) { c->delete_me=1; }
526      c->wait_reload=1;
527    }
528  }
529
530  base->join_list=NULL;  // all joiners have been added
531 
532}
533
534int waiting_server_input=1;
535
536void add_client_input(char *buf, int size, client *c)
537{
538  base->packet.add_to_packet(buf,size);
539
540  if (c)
541  {
542    c->wait_input=0;
543  }
544  else
545  {
546    FD_SET(game_fd,&master_set);   // we are ready to accept other client's game data, so add the udp socket to the select list
547    waiting_server_input=0;
548  }
549
550  int got_all=1; 
551  for (c=first_client;c;c=c->next)
552    if (c->wait_input)
553      got_all=0;
554
555  if (got_all && !waiting_server_input)
556  {   
557    base->packet.calc_checksum();
558
559    for (c=first_client;c;c=c->next)      // setup for next time, wait for all the input
560    {
561      c->wait_input=1;     
562      send(c->data_fd,base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),0);
563    }
564
565    base->input_state=INPUT_PROCESSING; // tell engine to start processing
566    FD_CLR(game_fd,&master_set);        // don't listen to this socket until we are prepared to read next tick's game data
567
568    waiting_server_input=1;
569  }
570}
571
572void get_input_from_server()
573{
574  int size=read(game_fd,base->packet.data,1024);
575  if (size<=0)
576  { mdie("read <= 0 bytes from server"); }
577  if (base->packet.packet_size()+base->packet.packet_prefix_size()==size &&     // did we read the whole packet?
578      base->packet.tick_received()==base->current_tick)    // if this was the correct tick packet, then tell server to go on
579    base->input_state=INPUT_PROCESSING;   
580}
581
582void process_engine_command()
583{
584  uchar cmd;
585  if (read(driver_in_fd,&cmd,1)!=1) { mdie("could not read command from engine"); }
586  switch (cmd)
587  {
588    case EGCMD_DIE :
589    {
590      if (!write(driver_out_fd,&cmd,1)) { mdie("could not write block ack1"); }  // send something to unblock engine
591      mdie("received die command");
592    } break;
593
594    case NFCMD_BLOCK :
595    {     
596      if (!write(driver_out_fd,&cmd,1)) { mdie("could not write block ack1"); }  // send something to unblock engine
597      if (!read(driver_in_fd,&cmd,1)) { mdie("could not read block ack1"); }  // send something to block ourself
598    } break;
599
600    case NFCMD_INPUT_MISSING :    // try to fetch the input via a loss-less net protocol
601    {
602      unsigned char pk[2]={CLCMD_REQUEST_RESEND,base->packet.tick_received()};
603
604      if (net_server[0])   // if we are connected to a server ask sever to resend
605      {
606        if (write(game_server_fd,pk,2)!=2) { mdie("attept to re-fetch input failed"); }
607        fprintf(stderr,"sending retry request to server (%d)\n",pk[1]);
608      } else
609      {
610        client *c=first_client;
611        for (;c;c=c->next)
612        {
613          if (!c->delete_me && c->wait_input)
614          {
615            fprintf(stderr,"sending retry request to client (%d)\n",pk[1]);
616            if (write(c->socket_fd,pk,2)!=2)
617              c->delete_me=1;
618          }
619          if (c->delete_me) fprintf(stderr,"delete this client!\n");
620        }
621      }
622      if (!write(driver_out_fd,&cmd,1)) { mdie("could not write block ack1"); }  // send something to unblock engine
623    } break;
624
625    case NFCMD_SEND_INPUT :
626    {
627      base->packet.set_tick_received(base->current_tick);
628      base->input_state=INPUT_COLLECTING; 
629      if (!net_server[0])
630      {
631        add_client_input(NULL,0,NULL);
632      }
633      else
634      {
635        base->packet.calc_checksum();
636        send(game_server_data_fd,base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),0);
637      }
638      if (!write(driver_out_fd,&cmd,1)) { mdie("could not write send ack1"); }  // send something to unblock engine
639      if (!read(driver_in_fd,&cmd,1)) { mdie("could not read send ack2"); }     // read something to block ourselves for engine
640    } break;
641
642    case NFCMD_RELOADED :
643    {
644      if (game_server_fd>0)
645      {
646        uchar ok=CLCMD_RELOADED;
647        if (!write(game_server_fd,&ok,1)) { mdie("could not send join_ok msg"); }       
648        next_process();
649      }
650    } break;
651
652    case NFCMD_PROCESS_ENTRIES :  // server is telling us the player has been added into the game
653    {
654      join_new_players();
655    } break;
656
657    case NFCMD_REQUEST_ENTRY :
658    {
659      uchar len;
660      char name[256];
661      if (read(driver_in_fd,&len,1)!=1) { mdie("could not read server name length"); }
662      if (read(driver_in_fd,name,len)!=len) { mdie("could not read server name"); }
663      strcpy(net_server,name);
664      ushort success=join_game(name);
665      if (write(driver_out_fd,&success,2)!=2) mdie("cound not send lsf read failure");     
666      next_process();
667    } break;
668
669    case NFCMD_REQUEST_LSF :
670    {
671      uchar len;
672      char name[256];
673      if (read(driver_in_fd,&len,1)!=1) { mdie("could not read lsf name length"); }
674      if (read(driver_in_fd,name,len)!=len) { mdie("could not read lsf name"); }
675      if (!get_lsf(name))
676      {
677        len=0;
678        if (write(driver_out_fd,&len,1)!=1) mdie("cound not send lsf read failure");
679      } else
680      {
681        len=strlen(name)+1;
682        if (write(driver_out_fd,&len,1)!=1) mdie("cound not send lsf name len");
683        if (write(driver_out_fd,name,len)!=len) mdie("cound not send lsf name");
684      }     
685      next_process();
686    } break;
687
688    case NFCMD_PROCESS_LSF :
689    {
690      uchar len,name[256];
691      if (read(driver_in_fd,&len,1)!=1) { mdie("could not read lsf name length"); }
692      if (read(driver_in_fd,name,len)!=len) { mdie("could not read lsf name"); }
693      while (lsf_wait_list)
694      {
695        lsf_waiter *c=lsf_wait_list;
696        lsf_wait_list=lsf_wait_list->next;
697        uchar status=1;
698        write(c->socket_fd,&len,1);
699        write(c->socket_fd,name,len);
700        delete c;
701      }
702      next_process();
703    } break;
704
705    case NFCMD_CRCS_CALCED :
706    {
707      while (crc_wait_list)
708      {
709        crc_waiter *c=crc_wait_list;
710        crc_wait_list=crc_wait_list->next;
711        uchar status=1;
712        write(c->socket_fd,&status,1);
713        delete c;
714      }
715      next_process();
716    } break;
717
718    case NFCMD_SET_FS :
719    {
720      uchar size;
721      char sn[256];
722      if (read(driver_in_fd,&size,1)!=1) mdie("could not read filename length");
723      if (read(driver_in_fd,sn,size)!=size) mdie("could not read server name");
724      strcpy(default_fs_name,sn);
725      size=fetch_crcs(sn);  // return success
726      if (write(driver_out_fd,&size,1)!=1) mdie("could not send ok to engine");
727      next_process();
728    } break;   
729
730    case NFCMD_OPEN :
731    {
732      uchar size[2];
733      char filename[300],mode[20],*fn;
734      fn=filename;
735      if (read(driver_in_fd,size,2)!=2) mdie("could not read fd on open");
736      if (read(driver_in_fd,filename,size[0])!=size[0]) mdie("incomplete filename");
737      if (read(driver_in_fd,mode,size[1])!=size[1]) mdie("incomplete mode string");
738     
739      int fd=open_file(fn,mode);
740      if (fd==-2)
741      {
742        uchar st[2];
743        st[0]=NF_OPEN_LOCAL_FILE;
744        st[1]=strlen(fn)+1;
745        if (write(driver_out_fd,st,2)!=2) comm_failed();
746        int size=write(driver_out_fd,fn,st[1]);
747        if (size!=st[1]) comm_failed();
748
749        if (size!=st[1]) comm_failed();
750      } else if (fd==-1)
751      {
752        uchar st=NF_OPEN_FAILED;
753        if (write(driver_out_fd,&st,1)!=1) comm_failed();
754      } else
755      {
756        uchar st=NF_OPEN_REMOTE_FILE;
757        if (write(driver_out_fd,&st,1)!=1) comm_failed();       
758        if (write(driver_out_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();     
759      }
760      next_process();
761    } break;
762    case NFCMD_CLOSE :
763    case NFCMD_SIZE :
764    case NFCMD_TELL :
765    case NFCMD_SEEK :
766    case NFCMD_READ :
767    {
768      int fd;
769      if (read(driver_in_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
770      remote_file *rf=find_rfile(fd);
771      if (!rf)
772        mdie("bad fd for engine command");
773
774      switch (cmd)
775      {
776        case NFCMD_CLOSE :
777        {
778          unlink_remote_file(rf);
779          delete rf;
780          uchar st=1;
781          if (write(driver_out_fd,&st,1)!=1) comm_failed();     
782        } break;
783        case NFCMD_SIZE  :
784        {
785          if (write(driver_out_fd,&rf->size,sizeof(rf->size))!=sizeof(rf->size)) comm_failed();                   
786        } break;
787        case NFCMD_TELL :
788        {
789          long offset=rf->unbuffered_tell();
790          if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed(); 
791        } break;
792        case NFCMD_SEEK :
793        {
794          long offset;
795          if (read(driver_in_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
796          offset=rf->unbuffered_seek(offset);
797          if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed(); 
798        } break;
799        case NFCMD_READ :
800        {
801          long size;
802          if (read(driver_in_fd,&size,sizeof(size))!=sizeof(size)) comm_failed();
803          rf->unbuffered_read(driver_out_fd,size);
804        } break;
805      }
806      next_process();
807    } break;   
808    default :
809    { fprintf(stderr,"net driver : unknown net command %d\n",cmd); die(0); }
810  }   
811}
812
813
814int process_client_command(client *c)
815{
816  uchar cmd;
817  if (read(c->socket_fd,&cmd,1)!=1) return 0;
818  switch (cmd)
819  {
820    case CLCMD_RELOADED :
821    {
822      c->wait_reload=0;
823      int done=1;
824      for (c=first_client;c;c=c->next)
825        if (c->wait_reload) done=0;
826      if (done) base->wait_reload=0;
827      return 1;
828    } break;
829    case CLCMD_REQUEST_RESEND :
830    {
831      uchar tick;
832      if (read(c->socket_fd,&tick,1)!=1) return 0;
833
834
835      fprintf(stderr,"request for resend tick %d (game cur=%d, pack=%d, last=%d)\n",
836              tick,base->current_tick,base->packet.tick_received(),base->last_packet.tick_received());
837
838      if (tick==base->last_packet.tick_received())
839      {
840        fprintf(stderr,"resending last game packet\n");
841        send(c->data_fd,base->last_packet.data,base->last_packet.packet_size()+base->last_packet.packet_prefix_size(),0);
842      }
843      else if (tick==base->packet.tick_received()) // asking for current tick, make sure it's collected
844      {
845        int got_all=!waiting_server_input;
846        client *cc=first_client;
847        for (;cc;cc=cc->next)
848          if (cc->wait_input) got_all=0;
849         
850        if (got_all)
851        {
852          fprintf(stderr,"resending current game packet\n");
853          send(c->data_fd,base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),0);
854        } else fprintf(stderr,"current game packet not complete yet\n");
855      }     
856      return 1;
857    } break;
858  }
859  return 0;
860}
861
862
863
864int isa_client(int client_id)    // sreach the list of active clients for this id and return 1 if found
865{
866  int i;
867  if (client_id==0) return 1;   // the server is always a client
868  client *c=first_client;
869  for (;c;c=c->next)
870    if (c->client_id==client_id) return 1;
871  return 0; 
872}
873
874int join_game_client(int client_id)
875{
876}
877
878int add_game_client(int fd, sockaddr *from)     // returns false if could not join client
879
880  ushort port;
881  if (read(fd,&port,2)!=2) { close(fd);  return 0; }
882  port=lstl(port);
883
884  ushort pport=lstl(packet_port);
885  if (write(fd,&pport,2)!=2) { close(fd);  return 0; } 
886
887
888  int f=-1,i;
889  for (i=0;f==-1 && i<MAX_JOINERS;i++)
890    if (!isa_client(i))
891      f=i;
892
893  if (f===-1) { close(fd); return 0; }
894
895  ushort client_id=lstl(f);
896  if (write(fd,&client_id,2)!=2) { close(fd);  return 0; }   
897
898
899  join_array[f].next=base->join_list;
900  base->join_list=real2shm(join_struct,&join_array[f]);
901  join_array[f].client_id=first_free_client;
902 
903  first_client=new client(fd,f,first_client);
904  memcpy(&first_client->data_address,from,sizeof(first_client->data_address));
905
906  // data port should be one above comminication port
907  first_client->data_address.sin_port = lstl(port);
908
909  first_client->data_fd=socket(AF_INET,SOCK_DGRAM,0);
910
911  if (first_client->data_fd==-1)
912  {
913    client *c=first_client;  first_client=first_client->next; delete c;
914    fprintf(stderr,"net driver : could not create a socket.  (too many open files?)");
915    return 0;
916  }
917 
918  if (connect(first_client->data_fd, (struct sockaddr *) &first_client->data_address,
919              sizeof(first_client->data_address))==-1)
920  {
921    client *c=first_client;  first_client=first_client->next; delete c;
922    fprintf(stderr,"unable to connect upd port\n");
923    return 0;
924  }
925
926
927  return 1;
928}
929
930
931void add_client()
932{
933  struct sockaddr from;
934  int addr_len=sizeof(from);
935  int new_fd=accept(comm_fd,&from,&addr_len);
936  if (new_fd>=0)
937  {
938    char client_type;
939    if (read(new_fd,&client_type,1)!=1) { close(new_fd); return ; }
940    switch (client_type)
941    {
942      case CLIENT_NFS : add_nfs_client(new_fd);    break;
943      case CLIENT_ABUSE : add_game_client(new_fd,&from); break;
944      case CLIENT_CRC_WAITER :
945      {
946        if (stand_alone)    // can't ask the engine if there is no engine
947        {
948          char status=0;
949          write(new_fd,&status,1);
950          close(new_fd);
951        } else
952        {
953          crc_wait_list=new crc_waiter(new_fd,crc_wait_list);
954          base->calc_crcs=1;
955        }
956      } break;
957      case CLIENT_LSF_WAITER :
958      {
959        if (stand_alone)    // can't ask the engine if there is no engine
960        {
961          char status=0;
962          write(new_fd,&status,1);
963          close(new_fd);
964        } else
965        {
966          lsf_wait_list=new lsf_waiter(new_fd,lsf_wait_list);
967          base->get_lsf=1;
968        }
969      } break;
970    }
971  }
972}
973
974void net_watch()
975{
976  int i;
977  join_array=(join_struct *) (base+1);
978
979  for (i=0;i<MAX_JOINERS;i++)
980    join_array[i].client_id=-1;
981
982
983  if (!stand_alone)
984  {
985    while (!aquire_mem_lock()) { next_process(); }
986    base->mem_lock=0;
987  }
988
989  fd_set read_set,exception_set,write_set;
990 
991  FD_ZERO(&master_set); 
992  FD_ZERO(&master_write_set); 
993  FD_SET(comm_fd,&master_set);     // new incoming connections & nfs data
994  if (net_server)
995    FD_SET(game_fd,&master_set);     // new incoming connections & nfs data
996
997  if (!stand_alone)
998  {
999    FD_SET(driver_in_fd,&master_set);  // request from engine
1000    FD_SET(driver_out_fd,&master_set); // check for error on messages to engine
1001  }
1002
1003  while (1)
1004  {
1005    memcpy(&read_set,&master_set,sizeof(master_set));
1006    memcpy(&exception_set,&master_set,sizeof(master_set));
1007    memcpy(&write_set,&master_write_set,sizeof(master_set));
1008
1009
1010    int tsel=select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
1011
1012    int check_rest=1;
1013    if (!stand_alone)
1014    {
1015      if (base->input_state==INPUT_COLLECTING)
1016      {
1017        // any game related data (udp) waiting to be read?
1018        if (FD_ISSET(game_fd,&read_set))
1019        {
1020          tsel--;
1021          check_rest=0;
1022          net_packet scratch,*use;
1023         
1024          if (net_server[0]==0)    // if we are the server, read into scratch, then "add" into base
1025            use=&scratch;
1026          else use=&base->packet;    // otherwise read directly into base because it is a complete packet from the server
1027
1028          sockaddr_in from_addr;
1029          int addr_size=sizeof(from_addr);
1030          int bytes_received=recvfrom(game_fd,use->data,1024,0, (sockaddr *)&from_addr,&addr_size);
1031
1032          // make sur we got a complete packet and the packet was not a previous game tick packet
1033          if (bytes_received==use->packet_size()+use->packet_prefix_size())
1034          {
1035            unsigned short rec_crc=use->get_checksum();
1036            use->calc_checksum();
1037            if (rec_crc==use->get_checksum())
1038            {
1039              if (base->current_tick==use->tick_received()) 
1040              {
1041                if (net_server[0])   // if we are a client, tell game to process input
1042                base->input_state=INPUT_PROCESSING;   // tell engine to start processing
1043                else
1044                {
1045
1046                  client *f=first_client,*found=NULL;
1047                  for (;!found &&f;f=f->next)
1048                  if (!memcmp(&from_addr.sin_addr,&f->data_address.sin_addr,sizeof(from_addr.sin_addr)))
1049                  found=f;
1050                 
1051                  if (!found)
1052                  fprintf(stderr,"received data from unknown client\n");
1053                  else
1054                  add_client_input((char *)use->packet_data(),use->packet_size(),found);
1055                }
1056              } else fprintf(stderr,"received stale packet (got %d, expected %d)\n",use->tick_received(),base->current_tick);
1057            } else fprintf(stderr,"received packet with bad checksum\n");
1058          } else fprintf(stderr,"received incomplete packet\n");
1059        }
1060        base->mem_lock=0;
1061      }
1062
1063      // see if we had any errors talking to the engine
1064      if (FD_ISSET(driver_in_fd,&exception_set) || FD_ISSET(driver_out_fd,&exception_set))
1065      {
1066        tsel--;
1067        check_rest=0;
1068        comm_failed();
1069      }
1070     
1071      // see if the engine has anything to say before getting to anyone else
1072      if (FD_ISSET(driver_in_fd,&read_set))
1073      {
1074        tsel--;
1075        process_engine_command();
1076        check_rest=0;
1077      }
1078    }
1079 
1080
1081    if (check_rest && aquire_mem_lock())  // we need to change shared memory, make sure server is not using it.
1082    {
1083      if (game_server_fd==-1)    // we are a server, check all client connections
1084      {
1085        client *c,*lastc=NULL;
1086
1087        for (c=first_client;c;)
1088        {
1089          int del=0;
1090          if (FD_ISSET(c->socket_fd,&exception_set))  // error?
1091          {
1092            tsel--;
1093            del=1;
1094          }
1095
1096          // waiting for engine to process command buffer, don't read anymore yet
1097          else if (FD_ISSET(c->socket_fd,&read_set))  // in comming commands data from client?
1098          {
1099            tsel--;
1100            if (process_client_command(c)==0)
1101            del=1;
1102
1103            if (del)
1104            {
1105              if (c->wait_reload)
1106              {
1107                int done=1;
1108                client *d=first_client;
1109                for (;d;d=d->next)                // see if this was the last client to wait on reloading
1110                if (d->wait_reload) done=0;
1111                if (done) base->wait_reload=0;
1112              }
1113
1114              if (lastc) lastc->next=c->next;
1115              else first_client=c->next;
1116              client *cd=c; c=c->next; delete cd;
1117            } else
1118            {
1119              lastc=c;
1120              c=c->next;
1121            }   
1122          } else c=c->next;
1123        }
1124      } else if (FD_ISSET(game_server_fd,&read_set))
1125      {
1126        uchar cmd;
1127        if (read(game_server_fd,&cmd,1)!=1) { mdie("unable to read command from server"); }
1128        switch (cmd)
1129        {
1130          case CLCMD_RELOAD :
1131          {
1132            base->need_reload=1;
1133          } break;
1134          case CLCMD_REQUEST_RESEND :
1135          {
1136            uchar tick;
1137            if (read(game_server_fd,&tick,1)!=1) { mdie("unable to read resend tick from server"); }
1138
1139            fprintf(stderr,"request for resend tick %d (game cur=%d, pack=%d, last=%d)\n",
1140              tick,base->current_tick,base->packet.tick_received(),base->last_packet.tick_received());
1141
1142            if (tick==base->packet.tick_received() && !waiting_server_input)    // asking for this tick?  make sure is collected
1143            {
1144              fprintf(stderr,"resending client packet to server\n");
1145              send(game_server_data_fd,base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),0);
1146            }
1147          } break;
1148        }
1149      }
1150
1151
1152
1153      if (FD_ISSET(comm_fd,&read_set))
1154      {
1155        tsel--;
1156        add_client();
1157      }
1158
1159      nfs_client *nc,*last=NULL;
1160      for (nc=first_nfs_client;nc;)      // check for nfs request
1161      {
1162
1163        int ok=1;
1164
1165        if (FD_ISSET(nc->socket_fd,&exception_set))
1166        {
1167          tsel--;
1168          ok=0;
1169          fprintf(stderr,"Killing nfs client, socket went bad\n");
1170        }
1171        else if (nc->size_to_read)
1172        {
1173          if (FD_ISSET(nc->socket_fd,&write_set))
1174          {
1175            tsel--;
1176            ok=nc->send_read();
1177          }
1178        }           
1179        else if (FD_ISSET(nc->socket_fd,&read_set))
1180        {
1181          tsel--;
1182          ok=process_nfs_command(nc);    // if we couldn't process the packeted, delete the connection
1183        }
1184           
1185        if (ok)
1186        {
1187          last=nc;
1188          nc=nc->next;
1189        } else
1190        {
1191          if (last) last->next=nc->next;
1192          else first_nfs_client=nc->next;
1193          nfs_client *c=nc;
1194          nc=nc->next;
1195          delete c;
1196        }
1197      }
1198
1199      // check for bad sockets for people waiting on crc's
1200      crc_waiter *crcw=crc_wait_list,*last_crcw=NULL;
1201      for (;crcw;)
1202      {
1203        if (FD_ISSET(crcw->socket_fd,&exception_set))
1204        {
1205          tsel--;
1206          if (last_crcw) { last_crcw->next=crcw->next; crc_waiter *cc=crcw; crcw=crcw->next; delete cc; }
1207          else { crc_wait_list=crcw->next; delete crcw; crcw=crc_wait_list; }
1208        } else crcw=crcw->next;
1209      }
1210      if (!crc_wait_list) base->calc_crcs=0;
1211
1212      // check for bad sockets for people waiting on crc's
1213      lsf_waiter *lsfw=lsf_wait_list,*last_lsfw=NULL;
1214      for (;lsfw;)
1215      {
1216        if (FD_ISSET(lsfw->socket_fd,&exception_set))
1217        {
1218          tsel--;
1219          if (last_lsfw) { last_lsfw->next=lsfw->next; lsf_waiter *cc=lsfw; lsfw=lsfw->next; delete cc; }
1220          else { lsf_wait_list=lsfw->next; delete lsfw; lsfw=lsf_wait_list; }
1221        } else lsfw=lsfw->next;
1222      }
1223      if (!lsf_wait_list) base->get_lsf=0;
1224
1225      base->mem_lock=0;
1226
1227    }   
1228    if (tsel)
1229    {
1230//      fprintf(stderr,"%d",tsel);
1231      next_process();
1232    }
1233
1234  }
1235}
1236
1237
1238
1239
1240
1241
Note: See TracBrowser for help on using the repository browser.