/** * \brief Unpack string8 from the buffer * \details This function check if it is possible to unpack string8 from the buffer, * because minimal length of string8 has to be 2, then data are copied to the * structure. * \param[in] *buffer The received buffer * \param[in] *buffer_size The remaining size of buffer, that could be processed * \param[out] **str The pointer at pointer of string. Informations from buffer are * copied to new allocated buffer. * \return This function return size of unpacked data in bytes. */ size_t vnp_raw_unpack_string8_to_str(const char *buffer, const size_t buffer_size, char **str) { char *string8; uint32 i, buffer_pos=0; uint8 length; /* Check if buffer_size is bigger then minimal length of string8 */ if(buffer_size < 2) { return buffer_size; } /* Unpack length of the command */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &length); /* Crop length of the string, when length of the string is * bigger then available buffer */ if( (size_t)(length + 1) > buffer_size ) { length = buffer_size - 1; } *str = string8 = (char*)malloc((length+1)*sizeof(char)); for(i=0; i<length; i++) { buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], (uint8*)&string8[i]); } string8[length] = '\0'; return buffer_pos; }
/** * \brief Get header of verse packet from received buffer * \param[in] *buffer The received buffer * \param[in] buffer_len The size of received buffer * \param[out] *vpacket The structure of packet, that will be filled with * information from the buffer. * \return This function returns relative buffer position of buffer proceeding. * When corrupted header detected, then it returns -1. */ int v_unpack_packet_header(const char *buffer, const unsigned short buffer_len, struct VPacket *vpacket) { unsigned short buffer_pos=0; unsigned char ver; if(buffer_len < VERSE_PACKET_HEADER_SIZE) return -1; /* Length of packet */ vpacket->len = buffer_len; /* Verse version */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &ver); vpacket->header.version = (ver >> 4) & 0x0F; /* Flags */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &vpacket->header.flags); /* Flow control window */ buffer_pos += vnp_raw_unpack_uint16(&buffer[buffer_pos], &vpacket->header.window); /* Payload ID */ buffer_pos += vnp_raw_unpack_uint32(&buffer[buffer_pos], &vpacket->header.payload_id); /* ACK NAK ID */ buffer_pos += vnp_raw_unpack_uint32(&buffer[buffer_pos], &vpacket->header.ack_nak_id); /* ANK ID */ buffer_pos += vnp_raw_unpack_uint32(&buffer[buffer_pos], &vpacket->header.ank_id); return buffer_pos; }
/** * \brief Unpack string8 from the buffer * \details This function check if it is possible to unpack string8 from the buffer, * because minimal length of string8 has to be 2, then data are copied to the * structure. * \param[in] *buffer The received buffer * \param[in] *buffer_size The remaining size of buffer, that could be processed * \param[out] *data The pointer at string8. Informations from buffer are * copied to this variable. * \return This function return size of unpacked data in bytes. */ size_t vnp_raw_unpack_string8_to_string8(const void *buffer, const size_t buffer_size, struct string8 *data) { uint32 i, size=0; /* Check if buffer_size is bigger then minimal length of string8 */ if(buffer_size < 2) { return buffer_size; } /* Unpack length of the command */ size += vnp_raw_unpack_uint8(((uint8 *)buffer) + size, &data->length); /* Crop length of the string, when length of the string is * bigger then available buffer */ if(data->length > buffer_size) { data->length = buffer_size; } for(i=0; i<data->length; i++) { size += vnp_raw_unpack_uint8(((uint8 *)buffer) + size, &data->str[i]); } /* Make real string terminated with '\0' character. */ data->str[data->length] = '\0'; return size; }
/** * \brief This function unpacks USER_AUTH_FAILURE command from the buffer */ int v_raw_unpack_user_auth_failure(const char *buffer, ssize_t buffer_size, struct User_Authentication_Failure *ua_fail) { unsigned short buffer_pos = 0; unsigned char length; int i; /* Check if buffer size is bigger then minimal size of user auth failure * command*/ if(buffer_size < 1+1) { v_print_log(VRS_PRINT_WARNING, "Buffer size: %d < minimal command length: %d\n.", buffer_size, 1+1); ua_fail->count = 0; return buffer_size; } /* Unpack command ID */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &ua_fail->id); /* Unpack length of the command */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &length); /* Security check: check if the length of the command is not bigger then * size of received buffer */ if(buffer_size < length) { v_print_log(VRS_PRINT_WARNING, "Buffer size: %d < command length: %d\n.", buffer_size, length); ua_fail->count = 0; return buffer_size; } /* Compute count of proposed user authentication methods */ ua_fail->count = length - 1 - 1; /* Save proposed methods to the array */ for(i=0; i<ua_fail->count && i < VRS_MAX_UA_METHOD_COUNT; i++) { buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &ua_fail->method[i]); } /* Update count of the proceeded method types */ ua_fail->count = i; /* Check if length and buffer_pos match */ if(buffer_pos!=length) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s: buffer_pos: %d != length: %d\n", __func__, buffer_pos, length); return length; } return buffer_pos; }
unsigned int v_unpack_c_curve_subscribe(const char *buf, size_t buffer_length) { unsigned int buffer_pos = 0; void (* func_c_curve_subscribe)(void *user_data, VNodeID node_id, VLayerID curve_id); VNodeID node_id; VLayerID curve_id; uint8 alias_bool; func_c_curve_subscribe = v_fs_get_user_func(129); if(buffer_length < 6) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &curve_id); if(buffer_length < buffer_pos + 1) return -1; buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &alias_bool); #if defined V_PRINT_RECEIVE_COMMANDS if(!alias_bool) printf("receive: verse_send_c_curve_unsubscribe(node_id = %u curve_id = %u ); callback = %p\n", node_id, curve_id, v_fs_get_alias_user_func(129)); else printf("receive: verse_send_c_curve_subscribe(node_id = %u curve_id = %u ); callback = %p\n", node_id, curve_id, v_fs_get_user_func(129)); #endif if(!alias_bool) { void (* alias_c_curve_unsubscribe)(void *user_data, VNodeID node_id, VLayerID curve_id); alias_c_curve_unsubscribe = v_fs_get_alias_user_func(129); if(alias_c_curve_unsubscribe != NULL) alias_c_curve_unsubscribe(v_fs_get_alias_user_data(129), node_id, curve_id); return buffer_pos; } if(func_c_curve_subscribe != NULL) func_c_curve_subscribe(v_fs_get_user_data(129), node_id, curve_id); return buffer_pos; }
unsigned int v_unpack_b_layer_subscribe(const char *buf, size_t buffer_length) { unsigned int buffer_pos = 0; void (* func_b_layer_subscribe)(void *user_data, VNodeID node_id, VLayerID layer_id, uint8 level); VNodeID node_id; VLayerID layer_id; uint8 level; func_b_layer_subscribe = v_fs_get_user_func(82); if(buffer_length < 6) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &layer_id); buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &level); #if defined V_PRINT_RECEIVE_COMMANDS if(level == 255) printf("receive: verse_send_b_layer_unsubscribe(node_id = %u layer_id = %u ); callback = %p\n", node_id, layer_id, v_fs_get_alias_user_func(82)); else printf("receive: verse_send_b_layer_subscribe(node_id = %u layer_id = %u level = %u ); callback = %p\n", node_id, layer_id, level, v_fs_get_user_func(82)); #endif if(level == 255) { void (* alias_b_layer_unsubscribe)(void *user_data, VNodeID node_id, VLayerID layer_id); alias_b_layer_unsubscribe = v_fs_get_alias_user_func(82); if(alias_b_layer_unsubscribe != NULL) alias_b_layer_unsubscribe(v_fs_get_alias_user_data(82), node_id, layer_id); return buffer_pos; } if(func_b_layer_subscribe != NULL) func_b_layer_subscribe(v_fs_get_user_data(82), node_id, layer_id, level); return buffer_pos; }
unsigned int v_unpack_b_tile_set(const char *buf, size_t buffer_length) { uint8 enum_temp; unsigned int buffer_pos = 0; void (* func_b_tile_set)(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile); VNodeID node_id; VLayerID layer_id; uint16 tile_x; uint16 tile_y; uint16 z; VNBLayerType type; const VNBTile *tile; func_b_tile_set = v_fs_get_user_func(83); if(buffer_length < 12) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &layer_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &tile_x); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &tile_y); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &z); buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &enum_temp); type = (VNBLayerType)enum_temp; #if defined V_PRINT_RECEIVE_COMMANDS printf("receive: verse_send_b_tile_set(node_id = %u layer_id = %u tile_x = %u tile_y = %u z = %u type = %u ); callback = %p\n", node_id, layer_id, tile_x, tile_y, z, type, v_fs_get_user_func(83)); #endif { VNBTile tile; switch(type) { case VN_B_LAYER_UINT1 : buffer_pos += vnp_raw_unpack_uint8_vector(&buf[buffer_pos], tile.vuint1, VN_B_TILE_SIZE * VN_B_TILE_SIZE / 8); break; case VN_B_LAYER_UINT8 : buffer_pos += vnp_raw_unpack_uint8_vector(&buf[buffer_pos], tile.vuint8, VN_B_TILE_SIZE * VN_B_TILE_SIZE); break; case VN_B_LAYER_UINT16 : buffer_pos += vnp_raw_unpack_uint16_vector(&buf[buffer_pos], tile.vuint16, VN_B_TILE_SIZE * VN_B_TILE_SIZE); break; case VN_B_LAYER_REAL32 : buffer_pos += vnp_raw_unpack_real32_vector(&buf[buffer_pos], tile.vreal32, VN_B_TILE_SIZE * VN_B_TILE_SIZE); break; case VN_B_LAYER_REAL64 : buffer_pos += vnp_raw_unpack_real64_vector(&buf[buffer_pos], tile.vreal64, VN_B_TILE_SIZE * VN_B_TILE_SIZE); break; } if(func_b_tile_set != NULL && type <= VN_B_LAYER_REAL64) func_b_tile_set(v_fs_get_user_data(83), node_id, layer_id, tile_x, tile_y, z, type, &tile); return buffer_pos; } if(func_b_tile_set != NULL) func_b_tile_set(v_fs_get_user_data(83), node_id, layer_id, tile_x, tile_y, z, (VNBLayerType)type, tile); return buffer_pos; }
/** * \brief Get header of verse message from received buffer * \param[in] *buffer The received buffer * \param[in] buffer_len The size of received buffer * \param[out] *vmessage The structure of message, that will be filled with * information from the buffer. * \return This function returns relative buffer position of buffer proceeding. * When corrupted header detected, then it returns -1. */ int v_unpack_message_header(const char *buffer, const unsigned short buffer_len, struct VMessage *vmessage) { unsigned short buffer_pos=0; unsigned char tmp; if(buffer_len < VERSE_MESSAGE_HEADER_SIZE) return -1; /* Unpack version of protocol */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &tmp); vmessage->header.version = (tmp >> 4) & 0x0F; /* Unpack zero byte for reservation */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &tmp); /* Unpack message length of message */ buffer_pos += vnp_raw_unpack_uint16(&buffer[buffer_pos], &vmessage->header.len); return buffer_pos; }
unsigned int v_unpack_b_layer_create(const char *buf, size_t buffer_length) { uint8 enum_temp; unsigned int buffer_pos = 0; void (* func_b_layer_create)(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type); VNodeID node_id; VLayerID layer_id; char name[16]; VNBLayerType type; func_b_layer_create = v_fs_get_user_func(81); if(buffer_length < 6) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &layer_id); buffer_pos += vnp_raw_unpack_string(&buf[buffer_pos], name, 16, buffer_length - buffer_pos); if(buffer_length < 1 + buffer_pos) return -1; buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &enum_temp); type = (VNBLayerType)enum_temp; #if defined V_PRINT_RECEIVE_COMMANDS if(name[0] == 0) printf("receive: verse_send_b_layer_destroy(node_id = %u layer_id = %u ); callback = %p\n", node_id, layer_id, v_fs_get_alias_user_func(81)); else printf("receive: verse_send_b_layer_create(node_id = %u layer_id = %u name = %s type = %u ); callback = %p\n", node_id, layer_id, name, type, v_fs_get_user_func(81)); #endif if(name[0] == 0) { void (* alias_b_layer_destroy)(void *user_data, VNodeID node_id, VLayerID layer_id); alias_b_layer_destroy = v_fs_get_alias_user_func(81); if(alias_b_layer_destroy != NULL) alias_b_layer_destroy(v_fs_get_alias_user_data(81), node_id, layer_id); return buffer_pos; } if(func_b_layer_create != NULL) func_b_layer_create(v_fs_get_user_data(81), node_id, layer_id, name, (VNBLayerType) type); return buffer_pos; }
unsigned int v_unpack_c_curve_create(const char *buf, size_t buffer_length) { unsigned int buffer_pos = 0; void (* func_c_curve_create)(void *user_data, VNodeID node_id, VLayerID curve_id, const char *name, uint8 dimensions); VNodeID node_id; VLayerID curve_id; char name[16]; uint8 dimensions; func_c_curve_create = v_fs_get_user_func(128); if(buffer_length < 6) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &curve_id); buffer_pos += vnp_raw_unpack_string(&buf[buffer_pos], name, 16, buffer_length - buffer_pos); if(buffer_length < 1 + buffer_pos) return -1; buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &dimensions); #if defined V_PRINT_RECEIVE_COMMANDS if(name[0] == 0) printf("receive: verse_send_c_curve_destroy(node_id = %u curve_id = %u ); callback = %p\n", node_id, curve_id, v_fs_get_alias_user_func(128)); else printf("receive: verse_send_c_curve_create(node_id = %u curve_id = %u name = %s dimensions = %u ); callback = %p\n", node_id, curve_id, name, dimensions, v_fs_get_user_func(128)); #endif if(name[0] == 0) { void (* alias_c_curve_destroy)(void *user_data, VNodeID node_id, VLayerID curve_id); alias_c_curve_destroy = v_fs_get_alias_user_func(128); if(alias_c_curve_destroy != NULL) alias_c_curve_destroy(v_fs_get_alias_user_data(128), node_id, curve_id); return buffer_pos; } if(func_c_curve_create != NULL) func_c_curve_create(v_fs_get_user_data(128), node_id, curve_id, name, dimensions); return buffer_pos; }
unsigned int v_unpack_c_key_set(const char *buf, size_t buffer_length) { unsigned int i, buffer_pos = 0; VNodeID node_id; VLayerID curve_id; uint32 key_id; uint8 dimensions; real64 pre_value[4], value[4], pos, post_value[4]; uint32 post_pos[4], pre_pos[4]; if(buffer_length < 11) return -1; buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &node_id); buffer_pos += vnp_raw_unpack_uint16(&buf[buffer_pos], &curve_id); buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &key_id); buffer_pos += vnp_raw_unpack_uint8(&buf[buffer_pos], &dimensions); if(dimensions != 0 && dimensions < 5) { void (* func_c_key_set)(void *user_data, VNodeID node_id, VLayerID curve_id, uint32 key_id, uint8 dimensions, real64 *pre_value, uint32 *pre_pos, real64 *value, real64 pos, real64 *post_value, uint32 *post_pos); for(i = 0; i < dimensions; i++) buffer_pos += vnp_raw_unpack_real64(&buf[buffer_pos], &pre_value[i]); for(i = 0; i < dimensions; i++) buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &pre_pos[i]); for(i = 0; i < dimensions; i++) buffer_pos += vnp_raw_unpack_real64(&buf[buffer_pos], &value[i]); buffer_pos += vnp_raw_unpack_real64(&buf[buffer_pos], &pos); for(i = 0; i < dimensions; i++) buffer_pos += vnp_raw_unpack_real64(&buf[buffer_pos], &post_value[i]); for(i = 0; i < dimensions; i++) buffer_pos += vnp_raw_unpack_uint32(&buf[buffer_pos], &post_pos[i]); #if defined V_PRINT_RECEIVE_COMMANDS switch(dimensions) { case 1: printf("receive: verse_send_c_key_set(node_id = %u curve_id = %u key_id = %u dimensions = %u pre_value = %f pre_pos = %u value = %f pos = %f, pre_value = %f pre_pos = %u ); callback = %p\n", node_id, curve_id, key_id, dimensions, pre_value[0], pre_pos[0], value[0], pos, pre_value[0], pre_pos[0], v_fs_get_user_func(130)); break; case 2: printf("receive: verse_send_c_key_set(node_id = %u curve_id = %u key_id = %u dimensions = %u pre_value = {%f, %f} pre_pos = {%u, %u} value = {%f, %f} pos = %f, pre_value = {%f, %f} pre_pos = {%u, %u}); callback = %p\n", node_id, curve_id, key_id, dimensions, pre_value[0], pre_value[1], pre_pos[0], pre_pos[1], value[0], value[1], pos, pre_value[0], pre_value[1], pre_pos[0], pre_pos[1], v_fs_get_user_func(130)); break; case 3: printf("receive: verse_send_c_key_set(node_id = %u curve_id = %u key_id = %u dimensions = %u pre_value = {%f, %f, %f} pre_pos = {%u, %u, %u} value = {%f, %f, %f} pos = %f, pre_value = {%f, %f, %f} pre_pos = {%u, %u, %u}); callback = %p\n", node_id, curve_id, key_id, dimensions, pre_value[0], pre_value[1], pre_value[2], pre_pos[0], pre_pos[1], pre_pos[2], value[0], value[1], value[2], pos, pre_value[0], pre_value[1], pre_value[2], pre_pos[0], pre_pos[1], pre_pos[2], v_fs_get_user_func(130)); break; case 4: printf("receive: verse_send_c_key_set(node_id = %u curve_id = %u key_id = %u dimensions = %u pre_value = {%f, %f, %f, %f} pre_pos = {%u, %u, %u, %u} value = {%f, %f, %f, %f} pos = %f, pre_value = {%f, %f, %f, %f} pre_pos = {%u, %u, %u, %u}); callback = %p\n", node_id, curve_id, key_id, dimensions, pre_value[0], pre_value[1], pre_value[2], pre_value[3], pre_pos[0], pre_pos[1], pre_pos[2], pre_pos[3], value[0], value[1], value[2], value[3], pos, pre_value[0], pre_value[1], pre_value[2], pre_value[3], pre_pos[0], pre_pos[1], pre_pos[2], pre_pos[3], v_fs_get_user_func(130)); break; } #endif func_c_key_set = v_fs_get_user_func(130); if(func_c_key_set != NULL) func_c_key_set(v_fs_get_user_data(130), node_id, curve_id, key_id, dimensions, pre_value, pre_pos, value, pos, post_value, post_pos); return buffer_pos; }else { void (* alias_c_key_destroy)(void *user_data, VNodeID node_id, VLayerID curve_id, uint32 key_id); alias_c_key_destroy = v_fs_get_alias_user_func(130); printf("receive: verse_send_c_key_destroy(node_id = %u curve_id = %u key_id = %u); callback = %p\n", node_id, curve_id, key_id, alias_c_key_destroy); if(alias_c_key_destroy != NULL) alias_c_key_destroy(v_fs_get_alias_user_data(130), node_id, curve_id, key_id); return buffer_pos; } }
/** * \brief Get system commands from received buffer and store them in VMessage * \param[in] *buffer The received buffer * \param[in] buffer_len The size of received buffer * \param[out] *vmessage The structure of message, that will be filled with * information from the buffer. * \return This function returns relative buffer position of buffer proceeding. */ int v_unpack_message_system_commands(const char *buffer, unsigned short buffer_len, struct VMessage *vmessage) { unsigned short not_used = 0, buffer_pos = 0; unsigned char length, cmd_id=CMD_RESERVED_ID; int i=0; if(buffer_len<1) { vmessage->sys_cmd[0].cmd.id = CMD_RESERVED_ID; return 0; /* Corrupted data was received ... buffer can not be proceeded further */ } else { while(buffer_pos<buffer_len && cmd_id<=MAX_SYS_CMD_ID) { /* System command IDs are in range 0-31 */ /* Unpack Command ID */ not_used += vnp_raw_unpack_uint8(&buffer[buffer_pos], &cmd_id); /* Is it still system command or is it node command */ if(cmd_id>MAX_SYS_CMD_ID) { vmessage->sys_cmd[i].cmd.id = CMD_RESERVED_ID; break; } else { vmessage->sys_cmd[i].cmd.id = cmd_id; vmessage->sys_cmd[i+1].cmd.id = CMD_RESERVED_ID; switch(cmd_id) { case CMD_USER_AUTH_REQUEST: buffer_pos += v_raw_unpack_user_auth_request(&buffer[buffer_pos], buffer_len - buffer_pos, &vmessage->sys_cmd[i].ua_req); break; case CMD_USER_AUTH_FAILURE: buffer_pos += v_raw_unpack_user_auth_failure(&buffer[buffer_pos], buffer_len - buffer_pos, &vmessage->sys_cmd[i].ua_fail); break; case CMD_USER_AUTH_SUCCESS: buffer_pos += v_raw_unpack_user_auth_success(&buffer[buffer_pos], buffer_len - buffer_pos, &vmessage->sys_cmd[i].ua_succ); break; case CMD_CHANGE_L_ID: case CMD_CONFIRM_L_ID: case CMD_CHANGE_R_ID: case CMD_CONFIRM_R_ID: buffer_pos += v_raw_unpack_negotiate_cmd(&buffer[buffer_pos], buffer_len - buffer_pos, &vmessage->sys_cmd[i].negotiate_cmd); break; default: /* Unknown system command. */ /* Unpack length of the command */ not_used = vnp_raw_unpack_uint8(&buffer[buffer_pos+1], &length); /* Warning print */ v_print_log(VRS_PRINT_WARNING, "Unknown system command ID: %d, Length: %d\n", cmd_id, length); /* Skip this command */ if(length < (buffer_len - buffer_pos)) buffer_pos += length; else buffer_pos = buffer_len; break; } i++; } } } return buffer_pos; }
/** * \brief Get system commands from received buffer and store them in VPacket * \param[in] *buffer The received buffer * \param[in] buffer_len The size of received buffer * \param[out] *vpacket The structure of packet, that will be filled with * information from the buffer. * \return This function returns relative buffer position of buffer proceeding. */ int v_unpack_packet_system_commands(const char *buffer, unsigned short buffer_len, struct VPacket *vpacket) { unsigned short not_used=0, buffer_pos=VERSE_PACKET_HEADER_SIZE; unsigned char length, cmd_id=CMD_RESERVED_ID; int i=0; if(buffer_len<VERSE_PACKET_HEADER_SIZE) { vpacket->sys_cmd[0].cmd.id = CMD_RESERVED_ID; return -1; /* Corrupted data was received ... buffer can not be proceeded further */ } else if(buffer_len==VERSE_PACKET_HEADER_SIZE) { vpacket->sys_cmd[0].cmd.id = CMD_RESERVED_ID; return VERSE_PACKET_HEADER_SIZE; } else { while(buffer_pos<buffer_len && cmd_id<=MAX_SYS_CMD_ID && /* System command IDs are in range 0-31 */ i < MAX_SYSTEM_COMMAND_COUNT-1 ) { /* Unpack Command ID */ not_used += vnp_raw_unpack_uint8(&buffer[buffer_pos], &cmd_id); /* Is it still system command or is it node command */ if(cmd_id>MAX_SYS_CMD_ID) { vpacket->sys_cmd[i].cmd.id = CMD_RESERVED_ID; break; } else { vpacket->sys_cmd[i].cmd.id = cmd_id; vpacket->sys_cmd[i+1].cmd.id = CMD_RESERVED_ID; switch(cmd_id) { case CMD_ACK_ID: buffer_pos += v_raw_unpack_ack_nak_cmd(&buffer[buffer_pos], &vpacket->sys_cmd[i].ack_cmd); break; case CMD_NAK_ID: buffer_pos += v_raw_unpack_ack_nak_cmd(&buffer[buffer_pos], &vpacket->sys_cmd[i].nak_cmd); break; case CMD_CHANGE_L_ID: case CMD_CONFIRM_L_ID: case CMD_CHANGE_R_ID: case CMD_CONFIRM_R_ID: buffer_pos += v_raw_unpack_negotiate_cmd(&buffer[buffer_pos], buffer_len - buffer_pos, &vpacket->sys_cmd[i].negotiate_cmd); break; default: /* This is unknown system command. Unpack length of * the command and skip this command. */ not_used = vnp_raw_unpack_uint8(&buffer[buffer_pos+1], &length); /* Warning print */ v_print_log(VRS_PRINT_WARNING, "Unknown system command ID: %d, Length: %d\n", cmd_id, length); /* Skip this command */ if(length < (buffer_len - buffer_pos)) buffer_pos += length; else buffer_pos = buffer_len; break; } } i++; } } return buffer_pos; }
/** * \brief This function unpack negotiate commands: Change_L/R and Confirm_L/R * from the buffer * * Unpack negotiate command (CHANGE_L, CONFIRM_L, CHANGE_R, CONFIRM_R). Buffer * size has to be at least 2 bytes long (this check has to be done before * calling this function) */ int v_raw_unpack_negotiate_cmd(const char *buffer, ssize_t buffer_size, struct Negotiate_Cmd *negotiate_cmd) { int str_len=0; unsigned short buffer_pos = 0, length, i; unsigned char length8 = 0, len8, lenlen; /* Unpack command ID */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &negotiate_cmd->id); /* Unpack Length of values */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &length8); /* Check if the length of the command is stored in the second byte of * command or is it stored in two bytes after second byte of the command */ if(length8==0xFF) { buffer_pos += vnp_raw_unpack_uint16(&buffer[buffer_pos], &length); lenlen = 3; } else { length = length8; lenlen = 1; } /* Security check: check if the length of the command is not bigger * then buffer_size. If this test failed, then return buffer_size and set * count of received values to the zero. */ if(buffer_size < length) { v_print_log(VRS_PRINT_WARNING, "Buffer size: %d < command length: %d.\n", buffer_size, length); negotiate_cmd->count = 0; return buffer_size; /* Security check: check if the length of the command is equal or bigger * then minimal length of the negotiate command: ID_len + Length_len + * Feature_len*/ } else if(length < (1+lenlen+1)) { v_print_log(VRS_PRINT_WARNING, "Command length: %d < (1+%d+1).\n", length, lenlen); negotiate_cmd->count = 0; return buffer_size; } /* Unpack Feature ID */ buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &negotiate_cmd->feature); /* Compute count of values in preference list. When unknown or unsupported * feature is detected, then processing of this command is stopped and it * returns the length of command. */ switch(negotiate_cmd->feature) { case FTR_RSV_ID: v_print_log(VRS_PRINT_WARNING, "Received RESERVED feature ID\n"); negotiate_cmd->count = 0; return length; /* This feature id should never be sent or received */ case FTR_FC_ID: case FTR_CC_ID: case FTR_RWIN_SCALE: case FTR_CMD_COMPRESS: negotiate_cmd->count = length - (1+lenlen+1); break; case FTR_HOST_URL: case FTR_TOKEN: case FTR_DED: case FTR_CLIENT_NAME: case FTR_CLIENT_VERSION: negotiate_cmd->count = 0; while(str_len < (length -(1+lenlen+1))) { vnp_raw_unpack_uint8(&buffer[buffer_pos+str_len], &len8); str_len += 1 + len8; negotiate_cmd->count++; } break; case FTR_FPS: negotiate_cmd->count = (length - (1+lenlen))/4; break; default: v_print_log(VRS_PRINT_WARNING, "Received UNKNOWN feature ID\n"); negotiate_cmd->count = 0; return length; } /* Unpack values (preference list) */ for(i=0; i<negotiate_cmd->count; i++) { switch(negotiate_cmd->feature) { case FTR_FC_ID: case FTR_CC_ID: case FTR_RWIN_SCALE: case FTR_CMD_COMPRESS: buffer_pos += vnp_raw_unpack_uint8(&buffer[buffer_pos], &negotiate_cmd->value[i].uint8); break; case FTR_HOST_URL: case FTR_TOKEN: case FTR_DED: case FTR_CLIENT_NAME: case FTR_CLIENT_VERSION: buffer_pos += vnp_raw_unpack_string8_(&buffer[buffer_pos], buffer_size-buffer_pos, &negotiate_cmd->value[i].string8); break; case FTR_FPS: buffer_pos += vnp_raw_unpack_real32(&buffer[buffer_pos], &negotiate_cmd->value[i].real32); break; default: break; } } /* Check if length and buffer_pos match */ if(buffer_pos!=length) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s: buffer_pos: %d != length: %d\n", __FUNCTION__, buffer_pos, length); return length; } return length; }