#include "system.h" #include "indian.hpp" #include #include #include #include #include #include #include #include #include #include "netface.hpp" #include "nfserver.hpp" #include "view.hpp" #include "objects.hpp" #include "level.hpp" #include "timing.hpp" #include "server2.hpp" #include "game.hpp" #include "jwindow.hpp" extern char lsf[256]; #define DIN_NAME "/tmp/.abuse_ndrv_out" // opposite of driver's in/out #define DOUT_NAME "/tmp/.abuse_ndrv_in" #define uchar unsigned char #define ushort unsigned short #define real2shm(type,ptr) (ptr==NULL ? NULL : ((type *)((char *)(ptr)-(char *)base))) #define shm2real(type,ptr) (ptr==NULL ? NULL : ((type *)((long)(ptr)+(long)(base)))) #ifdef __sgi #define next_process() sginap(0) #else #define next_process() usleep(1) #endif extern int crc_man_write_crc_file(char *filename); int net_installed=0,net_out_fd,net_in_fd; int net_child=-1; int local_client_number=0; void *shm_addr=(void *)-1; // shmat returns -1 on failure base_memory_struct *base; // points to shm_addr base_memory_struct local_base; net_address *net_server=NULL; extern int registered; int net_start() { return net_server!=NULL; } int kill_net() { if (net_installed) { char cmd=EGCMD_DIE; write(net_out_fd,&cmd,1); read(net_in_fd,&cmd,1); close(net_out_fd); close(net_in_fd); } if (net_child!=-1) { kill(net_child,SIGINT); net_child=-1; } net_installed=0; if (shm_addr!=(void *)-1) { shmdt((char *)shm_addr); shm_addr=(void *)-1; base=&local_base; } } void net_uninit() { kill_net(); } int net_init(int argc, char **argv) { int i,p1=-1,no_fork=0; base=&local_base; char *server_name=NULL; for (i=1;i #include int NF_set_file_server(char *name) { if (net_installed) { char cm[2]={NFCMD_SET_FS,strlen(name)+1}; if (write(net_out_fd,cm,2)!=2) { kill_net(); return 0; } if (write(net_out_fd,name,cm[1])!=cm[1]) { kill_net(); return 0; } if (read(net_in_fd,cm,1)!=1) { kill_net(); return 0; } // read the status of this command next_process(); return cm[0]; } else return 0; } int NF_open_file(char *filename, char *mode) { if (net_installed) { char cm[3]={NFCMD_OPEN,strlen(filename)+1,strlen(mode)+1}; if (write(net_out_fd,cm,3)!=3) { kill_net(); return -1; } if (write(net_out_fd,filename,cm[1])!=cm[1]) { kill_net(); return -1; } if (write(net_out_fd,mode,cm[2])!=cm[2]) { kill_net(); return -1; } uchar file_type; if (read(net_in_fd,&file_type,1)!=1) { kill_net(); return -1; } if (file_type==NF_OPEN_LOCAL_FILE) { uchar name_size; if (read(net_in_fd,&name_size,1)!=1) { kill_net(); return -1; } int size=read(net_in_fd,filename,name_size); if (size!=name_size) { kill_net(); return -1; } return -2; } else if (file_type==NF_OPEN_FAILED) return -1; int fd; if (read(net_in_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return -1; } return fd; } else return -2; // return open local } long NF_close(int fd) { if (net_installed) { char cm=NFCMD_CLOSE; if (write(net_out_fd,&cm,1)!=1) { kill_net(); return 0; } if (write(net_out_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return 0; } char stat; if (read(net_in_fd,&stat,sizeof(stat))!=sizeof(stat)) { kill_net(); return 0; } return stat; } else return 0; } long NF_read(int fd, void *buf, long size) { if (net_installed && size) { char cm=NFCMD_READ; if (write(net_out_fd,&cm,1)!=1) { kill_net(); return 0; } if (write(net_out_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return 0; } if (write(net_out_fd,&size,sizeof(size))!=sizeof(size)) { kill_net(); return 0; } long total_read=0; ushort t=0xffff; while (size && t>=READ_PACKET_SIZE-2) { if (read(net_in_fd,&t,sizeof(t))!=sizeof(t)) { kill_net(); return 0; } if (read(net_in_fd,buf,t)!=t) { kill_net(); return total_read; } total_read+=t; size-=t; buf=(void *)((char *)buf+t); } return total_read; } else return 0; } long NF_filelength(int fd) { if (net_installed) { char cm=NFCMD_SIZE; if (write(net_out_fd,&cm,1)!=1) { kill_net(); return 0; } if (write(net_out_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return 0; } long size; if (read(net_in_fd,&size,sizeof(size))!=sizeof(size)) { kill_net(); return 0; } return size; } else return 0; } long NF_tell(int fd) { if (net_installed) { char cm=NFCMD_TELL; if (write(net_out_fd,&cm,1)!=1) { kill_net(); return 0; } if (write(net_out_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return 0; } long offset; if (read(net_in_fd,&offset,sizeof(offset))!=sizeof(offset)) { kill_net(); return 0; } return offset; } else return 0; } long NF_seek(int fd, long offset) { if (net_installed) { char cm=NFCMD_SEEK; if (write(net_out_fd,&cm,1)!=1) { kill_net(); return 0; } if (write(net_out_fd,&fd,sizeof(fd))!=sizeof(fd)) { kill_net(); return 0; } if (write(net_out_fd,&offset,sizeof(offset))!=sizeof(offset)) { kill_net(); return 0; } long offset; if (read(net_in_fd,&offset,sizeof(offset))!=sizeof(offset)) { kill_net(); return 0; } return offset; } else return 0; } static int aquire_mem_lock() { if (base->mem_lock==0 || base->mem_lock==2) { base->mem_lock=2; if (base->mem_lock==2) return 1; } // next_process(); // probably just gonna loop until we get the lock so halt for next preocess return 0; } void service_net_request() { if (net_installed) { if (base->input_state==INPUT_NET_DEAD) kill_net(); else { if (aquire_mem_lock()) { if (base->calc_crcs) { crc_man_write_crc_file(NET_CRC_FILENAME); // return 0 on failure base->calc_crcs=0; base->mem_lock=0; uchar cmd=NFCMD_CRCS_CALCED; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } } else base->mem_lock=0; } if (aquire_mem_lock()) { if (base->get_lsf) { base->get_lsf=0; base->mem_lock=0; uchar c[2]={NFCMD_PROCESS_LSF,strlen(lsf)+1}; if (write(net_out_fd,&c,2)!=2) { kill_net(); return ; } if (write(net_out_fd,lsf,c[1])!=c[1]) { kill_net(); return ; } } else base->mem_lock=0; } } } } int get_remote_lsf(char *name, char *filename) // filename should be 256 bytes { if (net_installed) { uchar cm[2]={NFCMD_REQUEST_LSF,strlen(name)+1}; if (write(net_out_fd,cm,2)!=2) { kill_net(); return 0; } if (write(net_out_fd,name,cm[1])!=cm[1]) { kill_net(); return 0; } uchar size; if (read(net_in_fd,&size,1)!=1) { kill_net(); return 0; } if (size==0) return 0; if (read(net_in_fd,filename,size)!=size) { kill_net(); return 0; } return 1; } else return 0; } int request_server_entry() { if (net_installed) { if (!net_server) return 0; uchar cm[2]={NFCMD_REQUEST_ENTRY,strlen(net_server)+1}; if (write(net_out_fd,cm,2)!=2) { kill_net(); return 0; } if (write(net_out_fd,net_server,cm[1])!=cm[1]) { kill_net(); return 0; } ushort cnum; // client number if (read(net_in_fd,&cnum,2)!=2) { kill_net(); return 0; } if (cnum==0) return 0; local_client_number=cnum; return 1; } else return 0; } int reload_start() { if (net_installed) { uchar cmd=NFCMD_RELOAD_START; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return 0; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return 0; } return cmd; } else return 1; } int reload_end() { if (net_installed) { uchar cmd=NFCMD_RELOAD_END; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return 0; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return 0; } return cmd; } else return 1; } void net_reload() { if (net_installed) { if (net_server) { if (current_level) delete current_level; bFILE *fp; if (!reload_start()) return ; do { // make sure server saves the file fp=open_file(NET_STARTFILE,"rb"); if (fp->open_failure()) { delete fp; fp=NULL; } } while (!fp); spec_directory sd(fp); spec_entry *e=sd.find("Copyright 1995 Crack dot Com, All Rights reserved"); if (!e) { the_game->show_help("This level is missing copyright information, cannot load\n"); current_level=new level(100,100,"untitled"); the_game->need_refresh(); } else current_level=new level(&sd,fp,NET_STARTFILE); delete fp; base->current_tick=(current_level->tick_counter()&0xff); reload_end(); } else if (current_level) { join_struct *join_list=shm2real(join_struct,base->join_list); while (!aquire_mem_lock()) { next_process(); service_net_request(); } while (join_list) { view *f=player_list; for (;f && f->next;f=f->next); // find last player, add one for pn int i,st=0; for (i=0;iget_random_start(320,NULL); if (start) { o->x=start->x; o->y=start->y; } else { o->x=100; o->y=100; } f->next=new view(o,NULL,shm2real(join_struct,base->join_list)->client_id); strcpy(f->next->name,shm2real(join_struct,base->join_list)->name); o->set_controller(f->next); if (start) current_level->add_object_after(o,start); else current_level->add_object(o); view *v=f->next; v->cx1=5; v->cy1=5; v->cx2=319-5; v->cy2=199-5; join_list=shm2real(join_struct,join_list->next); } base->join_list=NULL; current_level->save(NET_STARTFILE,1); base->mem_lock=0; jwindow *j=eh->new_window(0,yres/2,-1,-1,new info_field(WINDOW_FRAME_LEFT, WINDOW_FRAME_TOP, 0,"Clients are re-syncing, please wait...",NULL)); eh->flush_screen(); if (!reload_start()) return ; // wait for all client to reload the level with the new players do { next_process(); } while (!reload_end()); eh->close_window(j); } } } int client_number() { return local_client_number; } void send_local_request() { if (net_installed) { if (base->join_list) base->packet.write_byte(SCMD_RELOAD); uchar cmd=NFCMD_SEND_INPUT; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return ; } if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } } else base->input_state=INPUT_PROCESSING; } void kill_slackers() { if (net_installed) { uchar cmd=NFCMD_KILL_SLACKERS; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return ; } } } int get_inputs_from_server(unsigned char *buf) { if (net_installed && base->input_state!=INPUT_PROCESSING) // if input is not here, wait on it { timeval start; gettimeofday(&start,NULL); int total_retry=0; jwindow *abort=NULL; linked_list input; while (base->input_state!=INPUT_PROCESSING) { if (!net_installed) { base->input_state=INPUT_PROCESSING; return 1; } server_check(); service_net_request(); timeval now; // if this is taking to long, the packet was probably lost, ask for it to be resent gettimeofday(&now,NULL); if ((((now.tv_sec-start.tv_sec)*100)+(now.tv_usec-start.tv_usec)/10000)>20) { // fprintf(stderr,"receive timeout %d\n",(((now.tv_sec-start.tv_sec)*100)+(now.tv_usec-start.tv_usec)/10000)); uchar cmd=NFCMD_INPUT_MISSING; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return 0; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return 0; } // block, so net driver can request input gettimeofday(&start,NULL); total_retry++; if (total_retry==10) // 2 seconds and nothing { abort=eh->new_window(0,yres/2,-1,eh->font()->height()*4, new info_field(WINDOW_FRAME_LEFT, WINDOW_FRAME_TOP, 0,"Waiting for data...", new button(WINDOW_FRAME_LEFT, WINDOW_FRAME_TOP+eh->font()->height()+5,ID_NET_DISCONNECT, "Disconnect slackers",NULL)),"Error"); eh->flush_screen(); } } if (abort) { if (eh->event_waiting()) { event ev; do { eh->get_event(ev); if (ev.type==EV_MESSAGE && ev.message.id==ID_NET_DISCONNECT) kill_slackers(); else if (ev.type!=EV_MOUSE_MOVE) // no need to save mouse move events (likely to be a lot) { event *e=new event; *e=ev; input.add_front(e); } } while (eh->event_waiting()); eh->flush_screen(); } } } if (abort) { eh->close_window(abort); while (input.first()) // push all the key events { event *ev=(event *)input.first(); input.unlink((linked_node *)ev); eh->push_event(ev); } } } // while (!aquire_mem_lock()) service_net_request(); memcpy(base->last_packet.data,base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size()); int size=base->packet.packet_size(); memcpy(buf,base->packet.packet_data(),size); base->packet.packet_reset(); base->mem_lock=0; return size; } void server_check() // read a byte from the net driver, causing the OS to give up the rest of our time-slice { if (net_installed) { if (base->input_state==INPUT_NET_DEAD) { close(net_out_fd); close(net_in_fd); net_installed=0; kill_net(); } else { uchar cmd=NFCMD_BLOCK; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } if (base->input_state==INPUT_NET_DEAD) { close(net_out_fd); close(net_in_fd); net_installed=0; kill_net(); } else { if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return ; } if (base->input_state==INPUT_NET_DEAD) { close(net_out_fd); close(net_in_fd); net_installed=0; kill_net(); } else if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return ; } } } } } int become_server() { if (net_installed) { uchar cmd=NFCMD_BECOME_SERVER; if (write(net_out_fd,&cmd,1)!=1) { kill_net(); return 0; } if (read(net_in_fd,&cmd,1)!=1) { kill_net(); return 0; } return 1; } return 0; } void read_new_views() { ; }