Ejemplo n.º 1
0
/**
 * \brief This function send packets in OPEN and CLOSEREQ state.
 */
int send_packet_in_OPEN_CLOSEREQ_state(struct vContext *C)
{
	struct VDgramConn *vconn = CTX_current_dgram_conn(C);
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct VSession *vsession = CTX_current_session(C);
	struct VPacket *s_packet = CTX_s_packet(C);
	struct VSent_Packet *sent_packet = NULL;
	unsigned short buffer_pos = 0;
	struct timeval tv;
	int ret, keep_alive_packet = -1, full_packet = 0;
	int error_num;
	uint16 swin, prio_win, sent_size = 0;
	uint32 rwin;
	int cmd_rank = 0;

	/* Verse packet header */
	s_packet->header.version = 1;

	/* Clear header flags */
	s_packet->header.flags = 0;

	/* Check if it is necessary to send payload packet */
	ret = check_pay_flag(C);
	if(ret!=0) {
		s_packet->header.flags |= PAY_FLAG;
		if(ret==2) {
			keep_alive_packet = 1;
		}
	}

	/* When server is in CLOSEREQ state, then FIN flag should be set up */
	if(vconn->host_state == UDP_SERVER_STATE_CLOSEREQ) {
		s_packet->header.flags |= FIN_FLAG;
	}

	/* Check if it is necessary to send acknowledgment of received payload
	 * packet */
	ret = check_ack_nak_flag(C);
	if(ret==1) {
		s_packet->header.flags |= ACK_FLAG;

		/* Update last acknowledged Payload packet */
		vconn->last_acked_pay = vconn->last_r_pay;

		/* Add ACK and NAK commands from the list of ACK and NAK commands to the
		 * packet (only max count of ACK and NAK commands could be added to
		 * the packet) */
		for(cmd_rank = 0;
				cmd_rank < vconn->ack_nak.count &&
				cmd_rank < MAX_SYSTEM_COMMAND_COUNT;
				cmd_rank++)
		{
			s_packet->sys_cmd[cmd_rank].ack_cmd.id = vconn->ack_nak.cmds[cmd_rank].id;
			s_packet->sys_cmd[cmd_rank].ack_cmd.pay_id = vconn->ack_nak.cmds[cmd_rank].pay_id;
		}
		s_packet->sys_cmd[cmd_rank].cmd.id = CMD_RESERVED_ID;

	}

	/* If there is no need to send Payload or AckNak packet, then cancel
	 * sending of packet */
	if(! ((s_packet->header.flags & PAY_FLAG) ||
			(s_packet->header.flags & ACK_FLAG)) ) return SEND_PACKET_CANCELED;

	s_packet->header.flags |= ANK_FLAG;
	s_packet->header.ank_id = vconn->ank_id;

	/* Compute current windows for flow control and congestion control */
	set_host_rwin(C);
	set_host_cwin(C);

	/* Set window of flow control that will sent to receiver */
	rwin = vconn->rwin_host >> vconn->rwin_host_scale;
	s_packet->header.window = (unsigned short)(rwin > 0xFFFF) ? 0xFFFF : rwin;
	/*printf("\t---real window: %d---\n", s_packet->header.window);*/

	/* Compute how many data could be sent to not congest receiver */
	rwin = vconn->rwin_peer - vconn->sent_size;

	/* Select smallest window for sending (congestion control window or flow control window)*/
	swin = (vconn->cwin < rwin) ? vconn->cwin : rwin;

	/* Set up Payload ID, when there is need to send payload packet */
	if(s_packet->header.flags & PAY_FLAG)
		s_packet->header.payload_id = vconn->host_id + vconn->count_s_pay;
	else
		s_packet->header.payload_id  = 0;

	/* Set up AckNak ID, when there are some ACK or NAK command in the packet */
	if(s_packet->header.flags & ACK_FLAG)
		s_packet->header.ack_nak_id = vconn->count_s_ack;
	else
		s_packet->header.ack_nak_id = 0;

	/* When negotiated and used FPS is different, then pack negotiate command
	 * for FPS */
	if(vsession->fps_host != vsession->fps_peer) {
		cmd_rank += v_add_negotiate_cmd(s_packet->sys_cmd, cmd_rank,
				CMD_CHANGE_L_ID, FTR_FPS, &vsession->fps_host, NULL);
	} else {
		if(vsession->tmp_flags & SYS_CMD_NEGOTIATE_FPS) {
			cmd_rank += v_add_negotiate_cmd(s_packet->sys_cmd, cmd_rank,
					CMD_CONFIRM_L_ID, FTR_FPS, &vsession->fps_peer, NULL);
			/* Send confirmation only once for received system command */
			vsession->tmp_flags &= ~SYS_CMD_NEGOTIATE_FPS;
		}
	}

	v_print_send_packet(C);

	/* Fill buffer */
	buffer_pos += v_pack_packet_header(s_packet, &io_ctx->buf[buffer_pos]);
	buffer_pos += v_pack_dgram_system_commands(s_packet, &io_ctx->buf[buffer_pos]);

	/* When this is not pure keep alive packet */
	if(s_packet->header.flags & PAY_FLAG) {

		sent_packet = v_packet_history_add_packet(&vconn->packet_history, s_packet->header.payload_id);

		assert(sent_packet != NULL);

		if(keep_alive_packet != 1) {
			real32 prio_sum_high, prio_sum_low, r_prio;
			uint32 prio_count;
			int16 prio, max_prio, min_prio;
			uint16 tot_cmd_size;

			/* Print outgoing command with green color */
			if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
				printf("%c[%d;%dm", 27, 1, 32);
			}

			max_prio = v_out_queue_get_max_prio(vsession->out_queue);
			min_prio = v_out_queue_get_min_prio(vsession->out_queue);

			prio_sum_high = v_out_queue_get_prio_sum_high(vsession->out_queue);
			prio_sum_low = v_out_queue_get_prio_sum_low(vsession->out_queue);

			v_print_log(VRS_PRINT_DEBUG_MSG, "Packing prio queues, cmd count: %d\n", v_out_queue_get_count(vsession->out_queue));

			/* Go through all priorities and pick commands from priority queues */
			for(prio = max_prio; prio >= min_prio; prio--)
			{
				/* TODO: Add better check here */
				if(prio <= VRS_DEFAULT_PRIORITY && buffer_pos >= vconn->io_ctx.mtu) {
					break;
				}

				prio_count = v_out_queue_get_count_prio(vsession->out_queue, prio);

				if(prio_count > 0) {
					r_prio = v_out_queue_get_prio(vsession->out_queue, prio);

					/* Compute size of buffer that could be occupied by
					 * commands from this queue */
					if(prio >= VRS_DEFAULT_PRIORITY) {
						prio_win = ((swin - buffer_pos)*r_prio)/prio_sum_high;
					} else {
						prio_win = ((swin - buffer_pos)*r_prio)/prio_sum_low;
					}

					/* Debug print */
					v_print_log(VRS_PRINT_DEBUG_MSG, "Queue: %d, count: %d, r_prio: %6.3f, prio_win: %d\n",
							prio, prio_count, r_prio, prio_win);

					/* Get total size of commands that were stored in queue (sent_size) */
					tot_cmd_size = 0;
					/* Pack commands from queues with high priority to the buffer */
					buffer_pos = pack_prio_queue(C, sent_packet, buffer_pos, prio, prio_win, &tot_cmd_size);
					sent_size += tot_cmd_size;
				}
			}

			/* Use default color for output */
			if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
				printf("%c[%dm", 27, 0);
			}
		} else {
			if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
				printf("%c[%d;%dm", 27, 1, 32);
				v_print_log(VRS_PRINT_DEBUG_MSG, "Keep alive packet\n");
				printf("%c[%dm", 27, 0);
			}
		}
	}

	/* Update sent_size */
	vconn->sent_size += sent_size;

	io_ctx->buf_size = buffer_pos;

	/* Send buffer */
	ret = v_send_packet(io_ctx, &error_num);

	if(ret==SEND_PACKET_SUCCESS) {
		gettimeofday(&tv, NULL);

		/* Update time of sending last payload packet */
		if(s_packet->header.flags & PAY_FLAG) {
			vconn->tv_pay_send.tv_sec = tv.tv_sec;
			vconn->tv_pay_send.tv_usec = tv.tv_usec;
			/* Store time of sending packet in history of sent packets. It is
			 * used for computing RTT and SRTT */
			if(sent_packet != NULL) {
				sent_packet->tv.tv_sec = tv.tv_sec;
				sent_packet->tv.tv_usec = tv.tv_usec;
			}
		}

		/* Update time of sending last acknowledgment packet */
		if(s_packet->header.flags & ACK_FLAG) {
			vconn->tv_ack_send.tv_sec = tv.tv_sec;
			vconn->tv_ack_send.tv_usec = tv.tv_usec;
		}

		/* Update counter of sent packets */
		if(s_packet->header.flags & PAY_FLAG) vconn->count_s_pay++;
		if(s_packet->header.flags & ACK_FLAG) vconn->count_s_ack++;

		/* If the packet was sent full and there are some pending data to send
		 * then modify returned value*/
		if(full_packet == 1) {
			ret = SEND_PACKET_FULL;
		}
	} else {
		/* When packet wasn't sent, then remove this packet from history */
		if(sent_packet != NULL) {
			v_packet_history_rem_packet(C, s_packet->header.payload_id);
		}
	}

	/*v_print_packet_history(&vconn->packet_history);*/

	return ret;
}
Ejemplo n.º 2
0
END_TEST


/**
 * \brief Test of packing and unpacking negotiate command with string value.
 */
START_TEST ( test_pack_unpack_negotiate_cmd_long_string_value )
{
	union VSystemCommands send_sys_cmd[1], recv_sys_cmd[1];
	uint8 cmd_op_code = CMD_CHANGE_R_ID;
	uint8 ftr_op_code = FTR_CLIENT_NAME;
	char string[470] = "Lorem ipsum dolor sit amet, consectetuer adipiscing "
			"elit. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
			"laboris nisi ut aliquip ex ea commodo consequat. Nullam at arcu "
			"a est sollicitudin euismod. Fusce consectetuer risus a nunc. "
			"Cras pede libero, dapibus nec, pretium sit amet, tempor quis. "
			"Etiam dictum tincidunt diam. Nullam lectus justo, vulputate "
			"eget mollis sed, tempor sed magna. Vivamus porttitor turpis ac "
			"leo. Suspendisse sagittis ultrices augue.";
	char buffer[512];
	int ret, buffer_pos = 0, cmd_len;

	ret = v_add_negotiate_cmd(send_sys_cmd, 0, cmd_op_code, ftr_op_code, string, NULL);

	fail_unless( ret == 1,
			"Adding negotiate command failed");

	/* Pack negotiate command */
	buffer_pos += v_raw_pack_negotiate_cmd(buffer,
			&send_sys_cmd[0].negotiate_cmd);

	fail_unless( buffer_pos == 261,
			"Length of packed cmd: %d != %d",
			buffer_pos, 8);

	/* Unpack system command */
	cmd_len = v_raw_unpack_negotiate_cmd(buffer, buffer_pos,
			&recv_sys_cmd[0].negotiate_cmd);

	fail_unless( cmd_len == buffer_pos,
			"Length of packed and unpacked cmd: %d != %d",
			buffer_pos, cmd_len);
	fail_unless( recv_sys_cmd->negotiate_cmd.id == cmd_op_code,
			"Negotiate command OpCode: %d != %d",
			recv_sys_cmd->negotiate_cmd.id, cmd_op_code);
	fail_unless( recv_sys_cmd->negotiate_cmd.feature == ftr_op_code,
			"Negotiate command feature: %d != %d",
			recv_sys_cmd->negotiate_cmd.feature, ftr_op_code);
	fail_unless( recv_sys_cmd->negotiate_cmd.count == 1,
			"Negotiate command feature count: %d != %d",
			recv_sys_cmd->negotiate_cmd.count, 1);
	fail_unless( recv_sys_cmd->negotiate_cmd.value[0].string8.length == 255,
			"Negotiate command value (string length): %d != %d",
			recv_sys_cmd->negotiate_cmd.value[0].string8.length, 255);
	/* Make original string 255 bytes long */
	string[255] = '\0';
	fail_unless( strncmp((char*)recv_sys_cmd->negotiate_cmd.value[0].string8.str, string, 255) == 0,
			"Negotiate command value (string): %s != %s",
			recv_sys_cmd->negotiate_cmd.value[0].string8.str,
			string);

}
Ejemplo n.º 3
0
END_TEST


/**
 * \brief Test of packing and unpacking negotiate command with
 * two string values.
 */
START_TEST ( test_pack_unpack_negotiate_cmd_multiple_string_values )
{
	union VSystemCommands send_sys_cmd[1], recv_sys_cmd[1];
	uint8 cmd_op_code = CMD_CONFIRM_R_ID;
	uint8 ftr_op_code = FTR_CLIENT_NAME;
	char string_val0[5] = {'a', 'h', 'o', 'y', '\0'};
	char string_val1[4] = {'h', 'e', 'y', '\0'};
	char buffer[255];
	int ret, buffer_pos = 0, cmd_len;

	ret = v_add_negotiate_cmd(send_sys_cmd, 0, cmd_op_code, ftr_op_code,
			string_val0, string_val1, NULL);

	fail_unless( ret == 1,
			"Adding negotiate command failed");

	/* Pack negotiate command */
	buffer_pos += v_raw_pack_negotiate_cmd(buffer,
			&send_sys_cmd[0].negotiate_cmd);

	fail_unless( buffer_pos == 12,
			"Length of packed cmd: %d != %d",
			buffer_pos, 12);

	/* Unpack system command */
	cmd_len = v_raw_unpack_negotiate_cmd(buffer, buffer_pos,
			&recv_sys_cmd[0].negotiate_cmd);

	fail_unless( cmd_len == buffer_pos,
			"Length of packed and unpacked cmd: %d != %d",
			buffer_pos, cmd_len);
	fail_unless( recv_sys_cmd->negotiate_cmd.id == cmd_op_code,
			"Negotiate command OpCode: %d != %d",
			recv_sys_cmd->negotiate_cmd.id, cmd_op_code);
	fail_unless( recv_sys_cmd->negotiate_cmd.feature == ftr_op_code,
			"Negotiate command feature: %d != %d",
			recv_sys_cmd->negotiate_cmd.feature, ftr_op_code);
	fail_unless( recv_sys_cmd->negotiate_cmd.count == 2,
			"Negotiate command feature count: %d != %d",
			recv_sys_cmd->negotiate_cmd.count, 2);
	fail_unless( recv_sys_cmd->negotiate_cmd.value[0].string8.length == 4,
			"Negotiate command value (string length): %d != %d",
			recv_sys_cmd->negotiate_cmd.value[0].string8.length, 4);
	fail_unless( strcmp((char*)recv_sys_cmd->negotiate_cmd.value[0].string8.str, "ahoy") == 0,
			"Negotiate command value (string): %s != ahoy",
			recv_sys_cmd->negotiate_cmd.value[0].string8.str);
	fail_unless( recv_sys_cmd->negotiate_cmd.value[1].string8.length == 3,
			"Negotiate command value (string length): %d != %d",
			recv_sys_cmd->negotiate_cmd.value[1].string8.length, 3);
	fail_unless( strcmp((char*)recv_sys_cmd->negotiate_cmd.value[1].string8.str, "hey") == 0,
			"Negotiate command value (string): %s != hey",
			recv_sys_cmd->negotiate_cmd.value[1].string8.str);

}
Ejemplo n.º 4
0
END_TEST


/**
 * \brief Test simple adding negotiate command to the list of system commands
 */
START_TEST ( test_print_negotiate_cmds )
{
	union VSystemCommands sys_cmd[1];
	uint8 cmd_op_code;
	uint8 ftr_op_code;
	uint8 uint8_value = 1;
	real32 real32_value = 60.0f;
	char string[5] = {'a', 'h', 'o', 'y', '\0'};
	int ret;

	cmd_op_code = CMD_CHANGE_R_ID;
	ftr_op_code = FTR_FC_ID;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &uint8_value, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_CC_ID;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &uint8_value, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_R_ID;
	ftr_op_code = FTR_HOST_URL;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &string, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CHANGE_L_ID;
	ftr_op_code = FTR_TOKEN;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &string, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_DED;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &string, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_RWIN_SCALE;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &uint8_value, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_FPS;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &real32_value, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_CMD_COMPRESS;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &uint8_value, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_CLIENT_NAME;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &string, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);

	cmd_op_code = CMD_CONFIRM_L_ID;
	ftr_op_code = FTR_CLIENT_VERSION;
	ret = v_add_negotiate_cmd(sys_cmd, 0, cmd_op_code, ftr_op_code, &string, NULL);
	fail_unless( ret == 1,
			"Adding negotiate command failed");
	v_print_negotiate_cmd(VRS_PRINT_NONE, &sys_cmd->negotiate_cmd);
}