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

Last change on this file since 524 was 524, checked in by Sam Hocevar, 11 years ago

core: Get rid of mostly useless headers, move endianness handling to
common.h (and rewrite functions so that they do not need the SDL headers)
and move a few functions out of sdlport's video.cpp. These functions
were in the original video.cpp (which reappears) and shouldn't be part
of the SDL port.

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