home *** CD-ROM | disk | FTP | other *** search
- #include "fileman.hpp"
- #include "netdrv.hpp"
- #include "gserver.hpp"
- #include "gclient.hpp"
- #include "undrv.hpp"
- #include "tcpip.hpp"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <string.h>
- #include <signal.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <bstring.h>
- #include <netdb.h>
-
- #define real2shm(type,ptr) (ptr==NULL ? NULL : ((type *)((char *)(ptr)-(char *)base)))
- #define shm2real(type,ptr) (ptr==NULL ? NULL : ((type *)((long)(ptr)+(long)(base))))
-
- net_driver *driver=NULL;
-
- #ifdef __sgi
- #define next_process() sginap(0)
- #else
- #define next_process() usleep(10)
- #endif
-
-
- #ifdef __sgi
- void die(...)
- #else
- void die(int why)
- #endif
- {
- fprintf(stderr,"dieing\n");
- if (driver) { delete driver; driver=NULL; }
- exit(0);
- }
-
-
- void mdie(char *reason)
- {
- fprintf(stderr,"net driver : %s\n",reason);
- if (driver) { driver->cleanup(); }
- exit(0);
- }
-
- void comm_failed() // general communication failure with engine
- {
- fprintf(stderr,"net driver : Error occured while trying to communicate with the engine\n");
- if (driver) { delete driver; driver=NULL; }
- exit(0);
- }
-
- int net_driver::add_joiner(int client_id, char *name)
- {
- join_array[client_id].next=base->join_list;
- base->join_list=real2shm(join_struct,&join_array[client_id]);
- join_array[client_id].client_id=client_id;
- strcpy(join_array[client_id].name,name);
- }
-
-
- void net_driver::cleanup()
- {
- base->input_state=INPUT_NET_DEAD;
- fprintf(stderr,"net driver : cleaning up\n");
- if (shm_seg_id!=-1)
- shmctl(shm_seg_id,IPC_RMID,NULL);
- if (shm_addr!=(void *)-1)
- {
- shmdt((char *)shm_addr);
- shm_addr=(void *)-1;
- }
-
- undrv_cleanup();
- unlink(DLOCK_NAME);
- }
-
- net_driver::~net_driver()
- {
- cleanup();
- }
-
- int net_driver::setup_shm()
- {
- shm_addr=(void *)-1; // shmat returns -1 on failure
- shm_seg_id=-1;
-
- driver=this;
- int catch_sigs[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,
- SIGIOT,SIGFPE,SIGKILL,SIGUSR1,SIGSEGV,
- SIGUSR2,SIGPIPE,SIGTERM,SIGCHLD,
- SIGCONT,SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU,-1};
-
- int i;
- for (i=0;catch_sigs[i]!=-1;i++) // catch all signals in case we get
- signal(catch_sigs[i],die); // interrupted before we remove shmid
-
-
- int alloc_size=sizeof(join_struct)*MAX_JOINERS+sizeof(base_memory_struct);
-
- shm_seg_id=shmget(IPC_PRIVATE,alloc_size,IPC_CREAT | 0777);
-
-
- if (shm_seg_id==-1) mdie("Unable to allocate shared memory");
-
-
- shm_addr=shmat(shm_seg_id,NULL,0); // attach as read/write
- if (shm_addr==(void *)-1)
- mdie("could not attach shm seg");
-
- base=(base_memory_struct *)shm_addr;
-
- base->join_list=real2shm(join_struct,NULL);
- base->mem_lock=0;
- base->calc_crcs=0;
- base->get_lsf=0;
- base->wait_reload=0;
- base->need_reload=0;
- base->input_state=INPUT_COLLECTING;
- base->current_tick=0;
- base->packet.packet_reset();
- join_array=(join_struct *) (base+1);
-
- // see if we can attach this memory with the abuse engine
- if (out->write(&shm_seg_id,sizeof(shm_seg_id))!=sizeof(shm_seg_id))
- comm_failed();
-
- // wait for engine to ack it has attached
- uchar ack=0;
- if (in->read(&ack,1)!=1 || ack!=1)
- comm_failed();
-
-
- if (shmctl(shm_seg_id,IPC_RMID,NULL)) // remove the shm id
- mdie("could not remove shm id");
-
- shm_seg_id=-1; // mark id as not allocated
- return 1;
-
- }
-
- int net_driver::connect_to_engine(int argc, char **argv)
- {
- if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
- { perror("Net driver : unable to make fifo in /tmp");
- return 0;
- }
- chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO); // just to be sure umask doesn't screw us
-
- if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
- { perror("Net driver : unable to make fifo in /tmp");
- return 0;
- }
- chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
-
- int driver_out_fd=open(DOUT_NAME,O_RDWR); // open the pipe
- if (driver_out_fd<0)
- { perror(DOUT_NAME);
- exit(1);
- }
-
- int driver_in_fd=open(DIN_NAME,O_RDWR);
- if (driver_in_fd<0)
- {
- close(driver_out_fd);
- perror(DIN_NAME);
- exit(1);
- }
-
- in=new unix_fd(driver_in_fd);
- in->read_selectable();
- out=new unix_fd(driver_out_fd);
-
- if (in->read(®,sizeof(reg))!=sizeof(reg))
- mdie("unable to registration from engine");
- }
-
- net_driver::net_driver(int argc, char **argv, int comm_port, int game_port, net_protocol *proto) :
- comm_port(comm_port), game_port(game_port), proto(proto)
- {
- debug=0;
- lsf_wait_list=NULL;
- crc_wait_list=NULL;
-
- base=NULL;
- in=out=NULL;
- game_face=new game_handler();
-
- connect_to_engine(argc,argv);
- setup_shm();
- int i;
- for (i=1;i<argc;i++) if (!strcmp(argv[i],"-debug")) debug=1;
- }
-
- int net_driver::become_server()
- {
- delete game_face;
- game_face=new game_server;
- return 1;
- }
-
- int net_driver::check_commands()
- {
- int ret=0;
- if (in->ready_to_read()) // commands from engine?
- {
- uchar cmd;
- if (in->read(&cmd,1)!=1) return 0;
-
- if (debug)
- {
- if (cmd<=EGCMD_DIE)
- {
- char *cmds[]={"open","close","read","write","seek","size","tell","setfs","crc_calced","process_lsf","request_lfs",
- "equest_entry","become_server","block","reload_start","reload_end","send_input","input_missing",
- "kill_slackers","die"};
- fprintf(stderr,"engine cmd : %s\n",cmds[cmd]);
- }
- }
-
- switch (cmd)
- {
- case EGCMD_DIE :
- {
- cmd=game_face->quit();
- if (!out->write(&cmd,1)) { mdie("could not write block ack1"); } // send something to unblock engine
- mdie("received die command");
- } break;
-
- case NFCMD_RELOAD_START :
- {
- cmd=game_face->start_reload();
- if (!out->write(&cmd,1)) { mdie("could not write start reload ack"); } // send something to unblock engine
- } break;
-
- case NFCMD_RELOAD_END :
- {
- cmd=game_face->end_reload();
- if (!out->write(&cmd,1)) { mdie("could not write end reload ack"); } // send something to unblock engine
- } break;
-
- case NFCMD_BLOCK :
- {
- if (!out->write(&cmd,1)) { mdie("could not write block ack1"); } // send something to unblock engine
- if (!in->read(&cmd,1)) { mdie("could not read block ack1"); } // send something to block ourself
- } break;
-
- case NFCMD_INPUT_MISSING : // try to fetch the input via a loss-less net protocol
- {
- game_face->input_missing();
- if (out->write(&cmd,1)!=1) { mdie("could not write block ack1"); } // send something to unblock engine
- } break;
- case NFCMD_KILL_SLACKERS :
- {
- if (!game_face->kill_slackers())
- {
- delete game_face;
- game_face=new game_handler();
- }
- if (out->write(&cmd,1)!=1) { mdie("could not write block ack1"); } // send something to unblock engine
- } break;
- case NFCMD_SEND_INPUT :
- {
- game_face->add_engine_input();
- if (out->write(&cmd,1)!=1) { mdie("could not write send ack1"); } // send something to unblock engine
- if (in->read(&cmd,1)!=1) { mdie("could not read send ack2"); } // read something to block ourselves for engine
- } break;
-
-
- case NFCMD_REQUEST_ENTRY :
- {
- uchar len;
- char name[256];
- if (in->read(&len,1)!=1) { mdie("could not read server name length"); }
- if (in->read(name,len)!=len) { mdie("could not read server name"); }
- ushort success=join_server(name);
- if (out->write(&success,2)!=2) mdie("cound not send lsf read failure");
- } break;
- case NFCMD_BECOME_SERVER :
- {
- cmd=become_server();
- if (out->write(&cmd,1)!=1) mdie("cound not send ok");
- } break;
- case NFCMD_REQUEST_LSF :
- {
- uchar len;
- char name[256];
- if (in->read(&len,1)!=1) { mdie("could not read lsf name length"); }
- if (in->read(name,len)!=len) { mdie("could not read lsf name"); }
- if (!get_lsf(name))
- {
- len=0;
- if (out->write(&len,1)!=1) mdie("cound not send lsf read failure");
- } else
- {
- len=strlen(name)+1;
- if (out->write(&len,1)!=1) mdie("cound not send lsf name len");
- if (out->write(name,len)!=len) mdie("cound not send lsf name");
- }
- } break;
-
- case NFCMD_PROCESS_LSF :
- {
- uchar len,name[256];
- if (in->read(&len,1)!=1) { mdie("could not read lsf name length"); }
- if (in->read(name,len)!=len) { mdie("could not read lsf name"); }
-
- while (lsf_wait_list)
- {
- lsf_waiter *c=lsf_wait_list;
- lsf_wait_list=lsf_wait_list->next;
- uchar status=1;
- c->sock->write(&len,1);
- c->sock->write(name,len);
- delete c;
- }
- } break;
-
- case NFCMD_CRCS_CALCED :
- {
- while (crc_wait_list)
- {
- crc_waiter *c=crc_wait_list;
- crc_wait_list=crc_wait_list->next;
- uchar status=1;
- c->sock->write(&status,1);
- delete c;
- }
- } break;
-
- case NFCMD_SET_FS :
- {
- uchar size;
- char sn[256];
- if (in->read(&size,1)!=1) mdie("could not read filename length");
- if (in->read(sn,size)!=size) mdie("could not read server name");
- fman->set_default_fs_name(sn);
-
- size=fetch_crcs(sn); // return success
- if (out->write(&size,1)!=1) mdie("could not send ok to engine");
- } break;
-
- case NFCMD_OPEN :
- {
- uchar size[2];
- char filename[300],mode[20],*fn;
- fn=filename;
- if (in->read(size,2)!=2 ||
- in->read(filename,size[0])!=size[0] ||
- in->read(mode,size[1])!=size[1])
- mdie("incomplete open command from engine");
-
- int fd=fman->rf_open_file(fn,mode);
- if (fd==-2)
- {
- uchar st[2];
- st[0]=NF_OPEN_LOCAL_FILE;
- st[1]=strlen(fn)+1;
- if (out->write(st,2)!=2) comm_failed();
- if (out->write(fn,st[1])!=st[1]) comm_failed();
- } else if (fd==-1)
- {
- uchar st=NF_OPEN_FAILED;
- if (out->write(&st,1)!=1) comm_failed();
- } else
- {
- uchar st=NF_OPEN_REMOTE_FILE;
- if (out->write(&st,1)!=1) comm_failed();
- if (out->write(&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
- }
- } break;
- case NFCMD_CLOSE :
- case NFCMD_SIZE :
- case NFCMD_TELL :
- case NFCMD_SEEK :
- case NFCMD_READ :
- {
- int fd;
- if (in->read(&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
-
- switch (cmd)
- {
- case NFCMD_CLOSE :
- {
- fman->rf_close(fd);
- uchar st=1;
- if (out->write(&st,1)!=1) comm_failed();
- } break;
- case NFCMD_SIZE :
- {
- long x=fman->rf_file_size(fd);
- if (out->write(&x,sizeof(x))!=sizeof(x)) comm_failed();
- } break;
- case NFCMD_TELL :
- {
- long offset=fman->rf_tell(fd);
- if (out->write(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
- } break;
- case NFCMD_SEEK :
- {
- long offset;
- if (in->read(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
- offset=fman->rf_seek(fd,offset);
- if (out->write(&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
- } break;
- case NFCMD_READ :
- {
- long size;
- if (in->read(&size,sizeof(size))!=sizeof(size)) comm_failed();
- fman->rf_read(fd,out,size);
- } break;
- }
- } break;
- default :
- { fprintf(stderr,"net driver : unknown net command %d\n",cmd); die(0); }
- }
- ret=1;
- }
-
- ret|=game_face->process_net();
- return ret;
- }
-
-
- int net_driver::join_server(char *server_name) // ask remote server for entry into game
- {
- char sn_start[256];
- strcpy(sn_start,server_name);
-
- net_socket *sock=connect_to_server(server_name,DEFAULT_COMM_PORT,0);
- if (!sock)
- {
- fprintf(stderr,"unable to connect\n");
- return 0;
- }
-
- uchar ctype=CLIENT_ABUSE;
- ushort port=lstl(game_port),cnum;
-
- uchar reg;
- if (sock->write(&ctype,1)!=1 || // send server out game port
- sock->read(®,1)!=1) // is remote engine registered?
- { delete sock; return 0; }
-
-
- // maker sure the two games are both registered or unregistered or sync problems
- // will occur.
-
- if (reg && !registered())
- {
- fprintf(stderr,
- "Sorry, this server is running REGISTERED ABUSE and you are not.\n"
- "Ask the server operator to run with -share option or better yet,\n"
- "Buy ABUSE, registered net games are more fun because you can fly,\n"
- "turn invisible and have more weapons to duke it out with\n");
- delete sock;
- return 0;
- }
-
- if (!reg && registered())
- {
- fprintf(stderr,
- "This is server is not running the registered version of abuse, and\n"
- "you are (thanks!). So that there are no conflict between the two games\n"
- "please start with the -share option when connecting to this server\n"
- "example : abuse -net somewhere.someplace.net -share\n");
- delete sock;
- return 0;
- }
-
- char uname[256];
- if (getlogin())
- strcpy(uname,getlogin());
- else strcpy(uname,"unknown");
- uchar len=strlen(uname)+1;
-
- if (sock->write(&len,1)!=1 ||
- sock->write(uname,len)!=len ||
- sock->write(&port,2)!=2 || // send server out game port
- sock->read(&port,2)!=2 || // read server's game port
- sock->read(&cnum,2)!=2 || cnum==0 // read player number (cannot be 0 because 0 is server)
- )
- { delete sock; return 0; }
-
- port=lstl(port);
- cnum=lstl(cnum);
-
- server_name=sn_start;
- net_socket *data_sock=connect_to_server(server_name,port,1,net_socket::SOCKET_FAST);
- if (!data_sock) { delete sock; return 0; }
-
- delete game_face;
- game_face=new game_client(sn_start,sock,data_sock);
- return cnum;
- }
-
-
- net_socket *net_driver::connect_to_server(char *&name, int port, int force_port,
- net_socket::socket_type sock_type)
- {
- char *oname=name;
- net_address *addr=proto->get_node_address(name, port, force_port);
- if (!addr)
- {
- if (debug) fprintf(stderr,"No IP address for name %s\n",oname);
- return NULL;
- }
-
- if (debug)
- fprintf(stderr,"connecting to server %s\n",oname);
- net_socket *sock=proto->connect_to_server(addr,sock_type);
- delete addr;
- return sock;
- }
-
-
- int net_driver::get_lsf(char *name) // contact remot host and ask for lisp startup file filename
- {
- char *name_start=name;
- net_socket *sock=connect_to_server(name);
- if (!sock) return 0;
-
- uchar ctype=CLIENT_LSF_WAITER;
- uchar len;
-
- if (sock->write(&ctype,1)!=1 ||
- sock->read(&len,1)!=1 || len==0 ||
- sock->read(name_start,len)!=len)
- {
- delete sock;
- return 0;
- }
-
- delete sock;
- return 1;
- }
-
-
-
- int net_driver::fetch_crcs(char *server)
- {
- net_socket *sock=connect_to_server(server);
- if (!sock) return 0;
- uchar cmd=CLIENT_CRC_WAITER;
- if (sock->write(&cmd,1)!=1 ||
- sock->read(&cmd,1)!=1)
- { delete sock; return 0; }
- delete sock;
- return cmd;
- }
-
-
- int net_driver::add_client(int type, net_socket *sock, net_address *from)
- {
- switch (type)
- {
- case CLIENT_CRC_WAITER :
- {
- if (debug)
- fprintf(stderr,"add crc waiter\n");
-
- crc_wait_list=new crc_waiter(sock,crc_wait_list);
- base->calc_crcs=1;
- return 1;
- } break;
- case CLIENT_LSF_WAITER :
- {
- if (debug)
- fprintf(stderr,"add lsf waiter\n");
- lsf_wait_list=new lsf_waiter(sock,lsf_wait_list);
- base->get_lsf=1;
- return 1;
- } break;
- default :
- {
- int ret=game_face->add_client(type,sock,from);
- if (!ret && debug)
- fprintf(stderr,"unknown client type %d\n",type);
- return ret;
- }
-
- }
- return 0;
- }
-