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

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