source: abuse/trunk/src/net/engine.cpp @ 643

Last change on this file since 643 was 643, checked in by Sam Hocevar, 9 years ago

imlib: refactor Event and EventHandler?.

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