possible_end_play_signal playmp_controller::play_idle_loop() { LOG_NG << "playmp::play_human_turn...\n"; remove_blindfold(); while (!end_turn_) { turn_info_send send_safe(turn_data_); config cfg; if(network_reader_.read(cfg)) { turn_info::PROCESS_DATA_RESULT res; HANDLE_END_PLAY_SIGNAL( res = turn_data_.process_network_data(cfg, skip_replay_) ); if (res == turn_info::PROCESS_RESTART_TURN || res == turn_info::PROCESS_RESTART_TURN_TEMPORARY_LOCAL) { end_turn_struct ets = {static_cast<unsigned>(gui_->playing_side())}; return possible_end_play_signal(ets); //throw end_turn_exception(gui_->playing_side()); } } HANDLE_END_PLAY_SIGNAL ( play_slice() ); HANDLE_END_PLAY_SIGNAL ( check_end_level() ); if (!linger_) { SDL_Delay(1); } gui_->draw(); } return boost::none; }
/** * PUT function * Performs the sending half of a request */ void put(SOCKET s, SOCKADDR_IN sa, char * username, char* filename, int client_num, int server_num, FILE* logfile){ char window[FRAME_SIZE * WINDOW_SIZE]; // data retention window char buffer[FRAME_SIZE]; // send buffer int filesize; int size = 0, sent = 0; // Trace variables char tracebuf[128]; FILE* send_file; if((send_file = fopen(filename, "rb")) != NULL){ // open the file // Determines the file size fseek(send_file, 0L, SEEK_END); filesize = ftell(send_file); fseek(send_file, 0L, SEEK_SET); sprintf(tracebuf, "Filesize %d", filesize); write_log(logfile, username, tracebuf); strncpy(buffer, "SIZ", 3); memcpy(buffer + (3 * sizeof(char)), &filesize, sizeof(int)); // Add the size of the element to the buffer if(send_safe(s,sa,buffer,FRAME_SIZE,101) == 101){ cout << "Sent filesize, starting transfer..." << endl; memset(buffer, 0, sizeof(buffer)); int count = 0; int offset = 0; int frames_outstanding = 0; int next = 0; bool resend = false; int packet_id; int pid_max = WINDOW_SIZE + 1; // Start sending the file while (1){ // If the acks mismatch with the current send offset, has to be a resend if(next != offset && frames_outstanding > 0) resend = true; // Send as many frames as available for the given window size while((!feof(send_file) && frames_outstanding < WINDOW_SIZE) || resend){ if(next == offset) resend = false; if(!resend){ if(feof(send_file)) break; fread(buffer,1,FRAME_SIZE,send_file); // Read the next block of data memcpy(window + (offset * FRAME_SIZE), buffer, FRAME_SIZE); // Store the data in the local window send_packet(s,sa,buffer,FRAME_SIZE,offset); // Send the packet to peer offset = (offset + 1) % pid_max; // Update the offset frames_outstanding++; }else{ // Resend by copying the data from the window memcpy(buffer, window + (next * FRAME_SIZE), FRAME_SIZE); send_packet(s,sa,buffer,FRAME_SIZE,next); sprintf(tracebuf, "Resending packet %d", next); write_log(logfile, username, tracebuf); next = (next + 1) % pid_max; } } // Receive ACKs before continuing sending while(frames_outstanding > 0){ if((packet_id = recv_packet(s,sa,buffer,FRAME_SIZE,next)) < 0){ if(count < filesize) resend = true; //else frames_outstanding --; break; } // Receive acknowledgment from the client if(!strncmp(buffer,"NAK", 3)){ if(packet_id >= 0) next = packet_id; // Set the next packet id to send break; }else if(!strncmp(buffer,"ALL", 3)){ frames_outstanding = 0; break; } count += FRAME_SIZE; // Increment the counter sprintf(tracebuf, "Sent %d bytes", count); write_log(logfile, username, tracebuf); memset(buffer, 0, sizeof(buffer)); // Zero the buffer next = (next + 1) % pid_max; // Update the next frame tracker frames_outstanding --; // Another frame has been acked } if(feof(send_file) && frames_outstanding == 0) break; // Break when done reading the file and all frames are acked } cout << "File transfer completed" << endl; fclose(send_file); }else{ fclose(send_file); return put(s,sa,username,filename, client_num, server_num, logfile); } } }
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) { struct sockaddr_storage addr; uint8_t buf[STUN_MAX_MESSAGE_SIZE]; char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; struct iovec iov = { buf, sizeof (buf) }; StunMessage request; StunMessage response; StunValidationStatus validation; StunAgent *agent = NULL; struct msghdr mh = { .msg_name = (struct sockaddr *)&addr, .msg_namelen = sizeof (addr), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = ctlbuf, .msg_controllen = sizeof (ctlbuf) }; size_t len = recv_safe (sock, &mh); if (len == (size_t)-1) return -1; validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0); if (validation == STUN_VALIDATION_SUCCESS) { agent = newagent; } else { validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0); agent = oldagent; } /* Unknown attributes */ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) { stun_agent_build_unknown_attributes_error (agent, &response, buf, sizeof (buf), &request); goto send_buf; } /* Mal-formatted packets */ if (validation != STUN_VALIDATION_SUCCESS || stun_message_get_class (&request) != STUN_REQUEST) { return -1; } switch (stun_message_get_method (&request)) { case STUN_BINDING: stun_agent_init_response (agent, &response, buf, sizeof (buf), &request); if (stun_message_has_cookie (&request)) stun_message_append_xor_addr (&response, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); else stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); break; default: stun_agent_init_error (agent, &response, buf, sizeof (buf), &request, STUN_ERROR_BAD_REQUEST); } iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0); send_buf: len = send_safe (sock, &mh); return (len < iov.iov_len) ? -1 : 0; } static int run (int family, int protocol, unsigned port) { StunAgent oldagent; StunAgent newagent; int sock = listen_socket (family, SOCK_DGRAM, protocol, port); if (sock == -1) return -1; stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); for (;;) dgram_process (sock, &oldagent, &newagent); }
possible_end_play_signal playmp_controller::play_human_turn(){ LOG_NG << "playmp::play_human_turn...\n"; remove_blindfold(); int cur_ticks = SDL_GetTicks(); show_turn_dialog(); if (!preferences::disable_auto_moves()) { HANDLE_END_PLAY_SIGNAL(execute_gotos()); } if (!linger_ || is_host()) { end_turn_enable(true); } while(!end_turn_) { turn_info_send send_safe(turn_data_); config cfg; if(network_reader_.read(cfg)) { turn_info::PROCESS_DATA_RESULT res; HANDLE_END_PLAY_SIGNAL( res = turn_data_.process_network_data(cfg, skip_replay_) ); //PROCESS_RESTART_TURN_TEMPORARY_LOCAL should be impossible because that's means the currently active side (that's us) left. if (res == turn_info::PROCESS_RESTART_TURN || res == turn_info::PROCESS_RESTART_TURN_TEMPORARY_LOCAL) { // Clean undo stack if turn has to be restarted (losing control) if ( undo_stack_->can_undo() ) { font::floating_label flabel(_("Undoing moves not yet transmitted to the server.")); SDL_Color color = {255,255,255,255}; flabel.set_color(color); SDL_Rect rect = gui_->map_area(); flabel.set_position(rect.w/2, rect.h/2); flabel.set_lifetime(150); flabel.set_clip_rect(rect); font::add_floating_label(flabel); } while( undo_stack_->can_undo() ) undo_stack_->undo(); end_turn_struct ets = {static_cast<unsigned>(gui_->playing_side())}; return possible_end_play_signal(ets); //throw end_turn_exception(gui_->playing_side()); } else if(res == turn_info::PROCESS_END_LINGER) { if(!linger_) replay::process_error("Received unexpected next_scenario durign the game"); else { //we end the turn immidiately to prevent receiving data of the next scenario while we are not playing it. end_turn(); } } } HANDLE_END_PLAY_SIGNAL( play_slice() ); HANDLE_END_PLAY_SIGNAL( check_end_level() ); if (!linger_ && (current_team().countdown_time() > 0) && saved_game_.mp_settings().mp_countdown) { SDL_Delay(1); const int ticks = SDL_GetTicks(); int new_time = current_team().countdown_time()-std::max<int>(1,(ticks - cur_ticks)); if (new_time > 0 ){ current_team().set_countdown_time(new_time); cur_ticks = ticks; if(current_team().is_human() && !beep_warning_time_) { beep_warning_time_ = new_time - WARNTIME + ticks; } if(counting_down()) { think_about_countdown(ticks); } } else { // Clock time ended // If no turn bonus or action bonus -> defeat const int action_increment = saved_game_.mp_settings().mp_countdown_action_bonus; if ( (saved_game_.mp_settings().mp_countdown_turn_bonus == 0 ) && (action_increment == 0 || current_team().action_bonus_count() == 0)) { // Not possible to end level in MP with throw end_level_exception(DEFEAT); // because remote players only notice network disconnection // Current solution end remaining turns automatically current_team().set_countdown_time(10); } return possible_end_play_signal(end_turn_exception().to_struct()); //throw end_turn_exception(); } } gui_->draw(); } return boost::none; }