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

Last change on this file was 651, checked in by Sam Hocevar, 8 years ago

build: add a --disable-network compilation flag and get rid of most of
the CELLOS_LV2 ifdefs.

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