/** * \brief This function handles node commands, when payload packet was received. * * This function also detects packet loss of previous not received payload * packets. All node commands are unpacked from the buffer and added to incoming queue. * * \param[in] *C The verse context. * * \return This function returns RECEIVE_PACKET_DELAYED, when delayd packet * was received, otherwise it returns RECEIVE_PACKET_SUCCESS. */ static int handle_node_commands(struct vContext *C) { struct VSession *vsession = CTX_current_session(C); struct VDgramConn *vconn = CTX_current_dgram_conn(C); struct VPacket *r_packet = CTX_r_packet(C); struct Ack_Nak_Cmd ack_nak_cmd; /* Note: when ACK and NAK command are add to the AckNak history, * then this vector of commands is automatically compressed. */ /* Was any packet lost since last receiving of packet? */ if(r_packet->header.payload_id > vconn->last_r_pay+1) { v_print_log(VRS_PRINT_DEBUG_MSG, "Packet(s) lost: %d - %d\n", vconn->last_r_pay+1, r_packet->header.payload_id-1); /* Add NAK command to the list of ACK NAK commands */ ack_nak_cmd.id = CMD_NAK_ID; ack_nak_cmd.pay_id = vconn->last_r_pay+1; v_ack_nak_history_add_cmd(&vconn->ack_nak, &ack_nak_cmd); /* Was some delayed packet received? */ } else if(r_packet->header.payload_id < vconn->last_r_pay+1) { if(is_log_level(VRS_PRINT_WARNING)) v_print_log(VRS_PRINT_WARNING, "Received unordered packet: %d, expected: %d\n", r_packet->header.payload_id, vconn->last_r_pay+1); /* Drop this packet */ return RECEIVE_PACKET_UNORDERED; } /* ADD ACK command to the list of ACK NAK commands */ ack_nak_cmd.id = CMD_ACK_ID; ack_nak_cmd.pay_id = r_packet->header.payload_id; v_ack_nak_history_add_cmd(&vconn->ack_nak, &ack_nak_cmd); /* Check if there are really node commands */ if(r_packet->data!=NULL) { /* Unpack node commands and put them to the queue of incoming commands */ v_cmd_unpack((char*)r_packet->data, r_packet->data_size, vsession->in_queue); } return RECEIVE_PACKET_SUCCESS; }
int vc_OPEN_loop(struct vContext *C) { struct VDgramConn *dgram_conn = CTX_current_dgram_conn(C); struct VPacket *r_packet = CTX_r_packet(C); struct Ack_Nak_Cmd ack_cmd; int ret; /* OPEN state */ if(is_log_level(VRS_PRINT_DEBUG_MSG)) { printf("%c[%d;%dm", 27, 1, 31); v_print_log(VRS_PRINT_DEBUG_MSG, "Client state: OPEN\n"); printf("%c[%dm", 27, 0); } /* Add ACK command to the list of ACK NAK commands to be send to the peer */ ack_cmd.id = CMD_ACK_ID; ack_cmd.pay_id = r_packet->header.payload_id; v_ack_nak_history_add_cmd(&dgram_conn->ack_nak, &ack_cmd); /* Receiving of last packet in previous packet had to be successful, because * client is in this state now :-). */ ret = RECEIVE_PACKET_SUCCESS; while(dgram_conn->host_state == UDP_CLIENT_STATE_OPEN) { dgram_conn->state[UDP_CLIENT_STATE_OPEN].attempts++; /* Send payload data or keep-alive packet */ if( vc_OPEN_send_packet(C) == SEND_PACKET_ERROR ) { return STATE_EXIT_ERROR; } /* Try to receive packet and handle received packet */ ret = vc_receive_and_handle_packet(C, vc_OPEN_handle_packet); if(ret == RECEIVE_PACKET_SUCCESS) { continue; } else if(ret == RECEIVE_PACKET_TIMEOUT) { struct timeval tv; gettimeofday(&tv, NULL); /* When no valid packet received from server for defined time, then consider this * connection as dead and return error */ if((tv.tv_sec - dgram_conn->tv_pay_recv.tv_sec) >= VRS_TIMEOUT) { return STATE_EXIT_ERROR; } else { continue; } } else if(ret == RECEIVE_PACKET_CORRUPTED) { continue; } else if(ret == RECEIVE_PACKET_FAKED) { return STATE_EXIT_ERROR; } else if(ret == RECEIVE_PACKET_ERROR) { return STATE_EXIT_ERROR; } #ifdef WITH_OPENSSL if(dgram_conn->io_ctx.flags & SOCKET_SECURED) { /* Did server close DTLS connection? */ if((SSL_get_shutdown(dgram_conn->io_ctx.ssl) & SSL_RECEIVED_SHUTDOWN)) { return STATE_EXIT_ERROR; } } #endif } return STATE_EXIT_SUCCESS; }