int unix_out_socket::get(packet &pk) { pk.ro=pk.wo=2; ushort size=0; if (pk_buffer_last==pk_buffer_ro) fill_buffer(); if (pk_buffer_last-pk_buffer_ro<2) // make sure the two byte for the size are in the same packet { uchar two[2]; two[0]=pk_buffer[pk_buffer_ro]; fill_buffer(); if (pk_buffer_last-pk_buffer_ro<2) // if still not enough info, something is screwy { printf("Incomplete packet\n"); return 0; } two[1]=pk_buffer[pk_buffer_ro]; pk_buffer_ro++; size=lstl((*((ushort *)two))); } else { memcpy(&size,pk_buffer+pk_buffer_ro,2); pk_buffer_ro+=2; size=lstl(size); } pk.rend=size+2; pk.make_bigger(pk.rend); uchar *pk_off=pk.buf+2; int rs; while (size) { if (pk_buffer_last==pk_buffer_ro) fill_buffer(); if (pk_buffer_last-pk_buffer_ro>size) rs=size; else rs=pk_buffer_last-pk_buffer_ro; memcpy(pk_off,pk_buffer+pk_buffer_ro,rs); pk_buffer_ro+=rs; size-=rs; pk_off+=rs; } return 1; }
int server::client_do_packet(packet &pk) { int rp=pk.get_read_position(); int er=0; while (!pk.eop() && !er) { uint8_t cmd; if (pk.read(&cmd,1)!=1) er=1; else { view *f=NULL; int fail=0; if (cmd!=SCMD_ADD_VIEW && cmd!=SCMD_SYNC) { uint16_t player; if (pk.read((uint8_t *)&player,2)!=2) er=1; player=lstl(player); for (f=player_list; f && f->player_number!=player; f=f->next); if (!f) fail=1; } if (!fail) { if (!process_command(f,cmd,pk)) er=1; } else er=1; } } pk.set_read_position(rp); return !er; }
int unix_out_socket::send(packet &pk) { while (!ready_to_write()) ; ushort size=lstl(pk.wo-2); memcpy(pk.buf,&size,2); return write(fd,pk.buf,pk.wo)==pk.wo; }
void server::add_change_log(view *f, packet &pk, int number) { if (f->view_changed()) { uint8_t cmd=SCMD_VIEW_RESIZE; pk.write(&cmd,1); if (number) { uint16_t pn=lstl(f->player_number); pk.write((uint8_t *)&pn,2); dprintf("Server : %s resized view %d %d %d %d\n",f->name, f->suggest.cx1,f->suggest.cy1,f->suggest.cx2,f->suggest.cy2); f->resize_view(f->suggest.cx1,f->suggest.cy1,f->suggest.cx2,f->suggest.cy2); f->suggest.send_view=0; } else dprintf("sending resize to server\n"); uint32_t view_size[8]; view_size[0]=lltl(f->suggest.cx1); view_size[1]=lltl(f->suggest.cy1); view_size[2]=lltl(f->suggest.cx2); view_size[3]=lltl(f->suggest.cy2); view_size[4]=lltl(f->suggest.pan_x); view_size[5]=lltl(f->suggest.pan_y); view_size[6]=lltl(f->suggest.shift_down); view_size[7]=lltl(f->suggest.shift_right); pk.write((uint8_t *)view_size,8*4); } if (f->weapon_changed()) { uint8_t cmd=SCMD_WEAPON_CHANGE; pk.write(&cmd,1); if (number) { uint16_t pn=lstl(f->player_number); pk.write((uint8_t *)&pn,2); dprintf("Server : %s change weapon to %d\n",f->name,f->suggest.new_weapon); f->current_weapon=f->suggest.new_weapon; f->suggest.send_weapon_change=0; } else dprintf("sending resize to server\n"); uint32_t nw=lltl(f->suggest.new_weapon); pk.write((uint8_t *)&nw,4); } }
int file_manager::nfs_client::send_read() // return 0 if failure on socket, not failure to read { if (file_fd>=0 && sock) { // first make sure the socket isn't 'full' if (sock->ready_to_write()) { char buf[READ_PACKET_SIZE]; short read_total; short actual; do { read_total=size_to_read>(READ_PACKET_SIZE-2) ? (READ_PACKET_SIZE-2) : size_to_read; actual=read(file_fd,buf+2,read_total); ushort tmp = lstl(actual); memcpy(buf, &tmp, sizeof(tmp)); int write_amount=sock->write(buf,actual+2); if (write_amount!=actual+2) { fprintf(stderr,"write failed\n"); return 0; } size_to_read-=actual; if (!sock->ready_to_write()) { sock->read_unselectable(); sock->write_selectable(); return 1; // not ok to write anymore, try again latter } } while (size_to_read && actual==read_total); sock->read_selectable(); sock->write_unselectable(); size_to_read=0; return 1; } else { sock->read_unselectable(); sock->write_selectable(); return 1; } } return 0; }
int demo_manager::save_packet(void *packet, int packet_size) // returns non 0 if actually saved { if (state==RECORDING) { uint16_t ps=lstl(packet_size); if (record_file->write(&ps,2)!=2 || record_file->write(packet,packet_size)!=packet_size) { set_state(NORMAL); return 0; } return 1; } else return 0; }
int file_manager::remote_file::unbuffered_read(void *buffer, size_t count) { if (sock && count) { uint8_t cmd = NFCMD_READ; if (sock->write(&cmd, sizeof(cmd)) != sizeof(cmd)) { r_close("read : could not send command"); return 0; } int32_t rsize = lltl(count); if (sock->write(&rsize, sizeof(rsize)) != sizeof(rsize)) { r_close("read : could not send size"); return 0; } int32_t total_read = 0; char buf[READ_PACKET_SIZE]; ushort packet_size; do { if (sock->read(&packet_size, sizeof(packet_size)) != sizeof(packet_size)) { fprintf(stderr, "could not read packet size\n"); return 0; } packet_size = lstl(packet_size); ushort size_read = sock->read(buf, packet_size); if (size_read != packet_size) { if (sock->read(buf + 2 + size_read, packet_size - size_read) != packet_size - size_read) { fprintf(stderr, "incomplete packet\n"); return 0; } } memcpy(buffer, buf, packet_size); buffer = (void *) (((char *) buffer) + packet_size); total_read += packet_size; count -= packet_size; } while (packet_size == READ_PACKET_SIZE - 2 && count); return total_read; } return 0; }
void server::remove_player(view *f) { uint8_t cmd=SCMD_REMOVE_VIEW; next_out.write((uint8_t *)&cmd,1); uint16_t pn=lstl(f->player_number); next_out.write((uint8_t *)&pn,2); if (f==player_list) player_list=player_list->next; else { for (view *v=player_list; v && v->next!=f; v=v->next); v->next=f->next; } if (f->connect) delete f->connect; f->focus->set_controller(NULL); delete f; }
void server::distribute_changes() { char cmd; for (view *f=player_list; f; f=f->next) { cmd=SCMD_SET_INPUT; next_out.write((uint8_t *)&cmd,1); uint16_t pn=lstl(f->player_number); next_out.write((uint8_t *)&pn,2); signed char inp[5]; inp[0]=f->x_suggestion; inp[1]=f->y_suggestion; inp[2]=f->b1_suggestion; inp[3]=f->b2_suggestion; inp[4]=f->b3_suggestion; next_out.write((uint8_t *)inp,5); } if (sync_check) { cmd=SCMD_SYNC; uint32_t x=lltl(make_sync_uint32()); next_out.write((uint8_t *)&cmd,1); next_out.write((uint8_t *)&x,4); } for (f=player_list; f; ) { view *n=f->next; if (!f->local_player() && f->connect) if (!send_pkt(f->connect,next_out)) remove_player(f); f=n; } }
int demo_manager::get_packet(void *packet, int &packet_size) // returns non 0 if actually loaded { if (state==PLAYING) { uint16_t ps; if (record_file->read(&ps,2)!=2) { set_state(NORMAL); return 0; } ps=lstl(ps); if (record_file->read(packet,ps)!=ps) { set_state(NORMAL); return 0; } packet_size=ps; return 1; } return 0; }
int server::join_game(out_socket *os, char *name, char *server_name) { char *re="Error occurred while reading from server\n"; packet pk; if (!get_pkt(os,pk)) // read join status packet, 0 means we can't join { fputs(re,stderr); exit(0); } int32_t nfs_port; if (pk.read((uint8_t *)&nfs_port,4)!=4) { fputs(re,stderr); exit(0); } // connect_to_nfs_server(server_name,lltl(nfs_port)); pk.write((uint8_t *)name,strlen(name)+1); // send or name and see if it's ok to join in if (!send_pkt(os,pk)) { printf("Unable to write to server\n"); exit(0); } if (!get_pkt(os,pk)) // read join status packet, 0 means we can't join { fputs(re,stderr); exit(0); } uint8_t stat; if (pk.read((uint8_t *)&stat,1)!=1) { fputs(re,stderr); exit(0); } if (stat==0) { printf("Sorry, this server is refusing you (%s)\n",name); exit(0); } if (current_level) delete current_level; int32_t vs[4]={ lltl(320/2-155),lltl(200/2-95),lltl(320/2+155),lltl(200/2+70)}; pk.write((uint8_t *)vs,4*4); if (!send_pkt(os,pk)) { printf("Unable to write to server\n"); exit(0); } current_level=new level(os); if (current_level->load_failed()) { printf("Error occurred while downloading level\n"); exit(1); } if (!get_pkt(os,pk)) { printf("Unable to read views from server\n"); exit(0); } uint16_t tv; if (pk.read((uint8_t *)&tv,2)!=2) { fputs(re,stderr); exit(0); } tv=lstl(tv); view *last=NULL; for (int i=0; i<tv; i++) { if (!get_pkt(os,pk)) { fputs(re,stderr); exit(0); } view *v=add_view(pk); if (v) { printf("added view %d\n",v->player_number); if (last) last->next=v; else player_list=v; last=v; } else printf("no view created, why?\n"); } if (!get_pkt(os,pk)) { fputs(re,stderr); exit(0); } if (pk.read((uint8_t *)&rand_on,2)!=2) // read the current random seed used by the server. { fputs(re,stderr); exit(0); } rand_on=lstl(rand_on); uint16_t rtab[1024]; if (!pk.read((uint8_t *)rtab,1024*2)) { fputs(re,stderr); exit(0); } // read the rand table for (int j=0; j<1024*2; j++) if (((uint8_t *)rtab)[j]!=((uint8_t *)rtable)[j]) { printf("rtables differ on byte %d\n",j); exit(0); } if (last) { last->Drawable=1; last->connect=os; } start_running=1; is_server=0; return 1; }
void server::check_for_new_players() { if (is_server && has_net) { out_socket *nd=in->check_for_connect(); if (nd) { packet pk; // pk.write_uint32(file_server->get_port()); if (!send_pkt(nd,pk)) { printf("error writing to connection\n"); return ; } // while (!file_server->service_request()) milli_wait(1000); if (!get_pkt(nd,pk)) { printf("error reading from connection\n"); return ; } else { char name[100]; pk.get_string(name,100); printf("Joined by player %s\n",name); pk.reset(); uint8_t ok=1; pk.write((uint8_t *)&ok,1); // write ok to join send_pkt(nd,pk); /**************** Read suggested view size from client ****/ if (!get_pkt(nd,pk)) { printf("error reading view info from connection\n"); return ; } int32_t cx1,cy1,cx2,cy2; if (pk.read((uint8_t *)&cx1,4)!=4) return ; cx1=lltl(cx1); if (pk.read((uint8_t *)&cy1,4)!=4) return ; cy1=lltl(cy1); if (pk.read((uint8_t *)&cx2,4)!=4) return ; cx2=lltl(cx2); if (pk.read((uint8_t *)&cy2,4)!=4) return ; cy2=lltl(cy2); /**************** Create the player *******************/ for (view *f=player_list; f && f->next; f=f->next); // find last player, add one for pn int i,st=0; for (i=0; i<total_objects; i++) if (!strcmp(object_names[i],"START")) st=i; game_object *o=create(current_start_type,0,0); game_object *start=current_level->get_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,f->player_number+1); o->set_controller(f->next); current_level->add_object(o); view *v=f->next; v->cx1=cx1; v->cy1=cy1; v->cx2=cx2; v->cy2=cy2; v->connect=nd; strcpy(v->name,name); if (current_level->send(nd)) { uint8_t cmd=SCMD_ADD_VIEW; next_out.write((uint8_t *)&cmd,1); v->write_packet(next_out); /********** Send all of the views to the player **********/ pk.reset(); uint16_t tv=0; for (f=player_list; f; f=f->next) tv++; tv=lstl(tv); pk.write((uint8_t *)&tv,2); if (!send_pkt(nd,pk)) return ; for (f=player_list; f; f=f->next) { pk.reset(); f->write_packet(pk); if (!send_pkt(nd,pk)) return ; } pk.reset(); uint16_t r=lstl(rand_on); pk.write((uint8_t *)&r,2); // write current random seed pk.write((uint8_t *)rtable,1024*2); send_pkt(nd,pk); } } } } }
int server::process_command(view *f, uint8_t command, packet &pk) { switch (command) { case SCMD_QUIT : // delete player { dprintf("Player %d has quit\n",f->player_number); return 0; } break; case SCMD_VIEW_RESIZE : // change view area { uint32_t view_size[8]; if (pk.read((uint8_t *)view_size,8*4)!=8*4) return 0; else { f->resize_view(lltl(view_size[0]),lltl(view_size[1]),lltl(view_size[2]),lltl(view_size[3])); f->pan_x=lltl(view_size[4]); f->pan_y=lltl(view_size[5]); f->shift_down=lltl(view_size[6]); f->shift_right=lltl(view_size[7]); f->suggest.send_view=0; if (is_server) // if we are a server, tell everybody about this. { uint8_t cmd=SCMD_VIEW_RESIZE; next_out.write((uint8_t *)&cmd,1); uint16_t pn=lstl(f->player_number); next_out.write((uint8_t *)&pn,2); next_out.write((uint8_t *)view_size,8*4); } } } break; case SCMD_WEAPON_CHANGE : // change weapon { uint32_t new_weap; if (pk.read((uint8_t *)&new_weap,4)!=4) return 0; else { f->current_weapon=lltl(new_weap); f->suggest.send_weapon_change=0; if (is_server) // if we are a server, tell everybody about this. { uint8_t cmd=SCMD_WEAPON_CHANGE; next_out.write((uint8_t *)&cmd,1); uint16_t pn=lstl(f->player_number); next_out.write((uint8_t *)&pn,2); next_out.write((uint8_t *)&new_weap,4); } } } break; case SCMD_SET_INPUT : // set the input from this player { signed char inp[5]; if (pk.read((uint8_t *)inp,5)!=5) return 0; else f->set_input(inp[0],inp[1],inp[2],inp[3],inp[4]); } break; case SCMD_ADD_VIEW : { view *v=add_view(pk); if (v) { for (view *f=player_list; f && f->next; f=f->next); if (f) f->next=v; else player_list=f; } } break; case SCMD_SYNC : { uint32_t x; if (pk.read((uint8_t *)&x,4)!=4) return 0; else { uint32_t s=make_sync_uint32(); if (lltl(x)!=s) printf("Out of sync, %x!=%x\n",lltl(x),s); return 1; } } break; default : return 0; } return 1; }
int request_server_entry() { if (prot && main_net_cfg) { if (!net_server) return 0; if (game_sock) delete game_sock; dprintf("Joining game in progress, hang on....\n"); game_sock=prot->create_listen_socket(main_net_cfg->port+2,net_socket::SOCKET_FAST); // this is used for fast game packet transmission if (!game_sock) { if (comm_sock) delete comm_sock; comm_sock=NULL; prot=NULL; return 0; } game_sock->read_selectable(); net_socket *sock=prot->connect_to_server(net_server,net_socket::SOCKET_SECURE); if (!sock) { fprintf(stderr,"unable to connect to server\n"); return 0; } uint8_t ctype=CLIENT_ABUSE; uint16_t port=lstl(main_net_cfg->port+2),cnum; uint8_t reg; if (sock->write(&ctype,1)!=1 || // send server out game port sock->read(®,1)!=1) // is remote engine registered? { delete sock; return 0; } if (reg==2) // too many players { fprintf(stderr, "%s", symbol_str("max_players")); delete sock; return 0; } // make sure the server is registered or sync problems will occur if (!reg) { fprintf(stderr, "%s", symbol_str("server_not_reg")); delete sock; return 0; } const size_t unamesize = 256; char uname[unamesize]; strncpy(uname, get_login(), unamesize); uint8_t len=strlen(uname)+1; short nkills; 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(&nkills,2)!=2 || sock->read(&cnum,2)!=2 || cnum==0 // read player number (cannot be 0 because 0 is server) ) { delete sock; return 0; } nkills=lstl(nkills); port=lstl(port); cnum=lstl(cnum); main_net_cfg->kills=nkills; net_address *addr=net_server->copy(); addr->set_port(port); delete game_face; game_face=new game_client(sock,addr); delete addr; local_client_number=cnum; return cnum; } return 0; }
int request_server_entry() { if (prot && main_net_cfg) { if (!net_server) return 0; if (game_sock) delete game_sock; dprintf("Joining game in progress, hang on....\n"); int game_port = main_net_cfg->game_port; game_sock=prot->create_listen_socket(game_port,net_socket::SOCKET_FAST); // this is used for fast game packet transmission if (!game_sock) { if (comm_sock) delete comm_sock; comm_sock=NULL; prot=NULL; return 0; } game_sock->read_selectable(); main_net_cfg->game_port = game_port; net_socket *sock=prot->connect_to_server(net_server,net_socket::SOCKET_SECURE); if (!sock) { dprintf("unable to connect to server\n"); return 0; } uchar ctype=CLIENT_ABUSE; ushort port=lstl(game_port),cnum; uchar reg; if (sock->write(&ctype,1)!=1 || // send server our game port sock->read(®,1)!=1) // is remote engine registered? { delete sock; return 0; } if (reg==2) // too many players { dprintf(symbol_str("max_players")); delete sock; return 0; } // maker sure the two games are both registered or unregistered or sync problems // will occur. if (reg && !registered) { dprintf(symbol_str("net_not_reg")); delete sock; return 0; } if (!reg && registered) { dprintf(symbol_str("server_not_reg")); delete sock; return 0; } char uname[256]; if (get_login()) strcpy(uname,get_login()); else strcpy(uname,"unknown"); uchar len=strlen(uname)+1; short nkills; if (sock->write(&len,1)!=1 || sock->write(uname,len)!=len || sock->write(&port,2)!=2 || // send server our game port sock->read(&port,2)!=2 || // read server's game port sock->read(&nkills,2)!=2 || sock->read(&cnum,2)!=2 || cnum==0 // read player number (cannot be 0 because 0 is server) ) { delete sock; return 0; } nkills=lstl(nkills); port=lstl(port); cnum=lstl(cnum); main_net_cfg->kills=nkills; net_address *addr=net_server->copy(); addr->set_port(port); if (game_face) delete game_face; game_face=new game_client(sock,addr); delete addr; local_client_number=cnum; return cnum; } else return 0; }