예제 #1
0
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);
        }
    }

}
예제 #3
0
파일: stund.c 프로젝트: zsx/ossbuild
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);
}
예제 #4
0
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;
}