diff --git a/implementation/endpoints/include/tp.hpp b/implementation/endpoints/include/tp.hpp index ee6b329b1..a62881673 100644 --- a/implementation/endpoints/include/tp.hpp +++ b/implementation/endpoints/include/tp.hpp @@ -30,6 +30,14 @@ typedef std::vector tp_split_messages_t; const std::uint8_t TP_FLAG = 0x20; +enum class tp_status_e : std::uint8_t { + TPS_ERROR = 0x00, + TPS_INCOMPLETE = 0x01, + TPS_COMPLETE = 0x02, + TPS_DUPLICATE = 0x04, + TPS_UNKNOWN = 0xff +}; + class tp { public: static inline length_t get_offset(tp_header_t _tp_header) { diff --git a/implementation/endpoints/include/tp_message.hpp b/implementation/endpoints/include/tp_message.hpp index 0f943b403..229b81331 100644 --- a/implementation/endpoints/include/tp_message.hpp +++ b/implementation/endpoints/include/tp_message.hpp @@ -13,6 +13,7 @@ #include #include "buffer.hpp" +#include "tp.hpp" #if defined(__QNX__) #include "../../utility/include/qnx_helper.hpp" @@ -25,8 +26,7 @@ class tp_message { tp_message(const byte_t* const _data, std::uint32_t _data_length, std::uint32_t _max_message_size); - bool add_segment(const byte_t* const _data, std::uint32_t _data_length); - + tp_status_e add_segment(const byte_t* const _data, std::uint32_t _data_length); message_buffer_t get_message(); std::chrono::steady_clock::time_point get_creation_time() const; diff --git a/implementation/endpoints/src/tp_message.cpp b/implementation/endpoints/src/tp_message.cpp index 7cb77b804..dda6cde0b 100644 --- a/implementation/endpoints/src/tp_message.cpp +++ b/implementation/endpoints/src/tp_message.cpp @@ -67,17 +67,16 @@ tp_message::tp_message(const byte_t* const _data, std::uint32_t _data_length, } } -bool tp_message::add_segment(const byte_t* const _data, - std::uint32_t _data_length) { +tp_status_e tp_message::add_segment(const byte_t* const _data, std::uint32_t _data_length) { if (_data_length < VSOMEIP_FULL_HEADER_SIZE + VSOMEIP_TP_HEADER_SIZE) { VSOMEIP_ERROR << __func__ << " received too short SOME/IP-TP message " << get_message_id(_data, _data_length); - return false; + return tp_status_e::TPS_ERROR; } - bool ret = false; + tp_status_e ret {tp_status_e::TPS_INCOMPLETE}; - const length_t its_segment_size = _data_length - VSOMEIP_FULL_HEADER_SIZE - - VSOMEIP_TP_HEADER_SIZE; + const length_t its_segment_size = + _data_length - VSOMEIP_FULL_HEADER_SIZE - VSOMEIP_TP_HEADER_SIZE; const tp_header_t its_tp_header = bithelper::read_uint32_be(&_data[VSOMEIP_TP_HEADER_POS_MIN]); if (check_lengths(_data, _data_length, its_segment_size, @@ -86,9 +85,7 @@ bool tp_message::add_segment(const byte_t* const _data, const auto emplace_res = segments_.emplace( segment_t(its_offset, its_offset + its_segment_size - 1)); if (!emplace_res.second) { - VSOMEIP_WARNING << __func__ << ":" << __LINE__ - << " received duplicate segment " << get_message_id(_data, _data_length) - << "TP offset: 0x" << std::hex << its_offset; + ret = tp_status_e::TPS_DUPLICATE; } else { const auto& seg_current = emplace_res.first; const auto& seg_next = std::next(seg_current); @@ -232,7 +229,9 @@ bool tp_message::add_segment(const byte_t* const _data, *(reinterpret_cast(&message_[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length); // all segments were received -> update return code field of message message_[VSOMEIP_RETURN_CODE_POS] = _data[VSOMEIP_RETURN_CODE_POS]; - ret = true; + ret = tp_status_e::TPS_COMPLETE; + } else { + ret = tp_status_e::TPS_ERROR; } } } @@ -256,10 +255,8 @@ std::string tp_message::get_message_id(const byte_t* const _data, std::uint32_t const service_t its_method = bithelper::read_uint16_be(&_data[VSOMEIP_METHOD_POS_MIN]); const service_t its_client = bithelper::read_uint16_be(&_data[VSOMEIP_CLIENT_POS_MIN]); const service_t its_session = bithelper::read_uint16_be(&_data[VSOMEIP_SESSION_POS_MIN]); - const interface_version_t its_interface_version = - _data[VSOMEIP_INTERFACE_VERSION_POS]; - const message_type_e its_msg_type = tp::tp_flag_unset( - _data[VSOMEIP_MESSAGE_TYPE_POS]); + const interface_version_t its_interface_version = _data[VSOMEIP_INTERFACE_VERSION_POS]; + const message_type_e its_msg_type = tp::tp_flag_unset(_data[VSOMEIP_MESSAGE_TYPE_POS]); ss << "(" << std::hex << std::setfill('0') @@ -273,7 +270,7 @@ std::string tp_message::get_message_id(const byte_t* const _data, std::uint32_t if (_data_length > VSOMEIP_TP_HEADER_POS_MAX) { const tp_header_t its_tp_header = bithelper::read_uint32_be(&_data[VSOMEIP_TP_HEADER_POS_MIN]); const length_t its_offset = tp::get_offset(its_tp_header); - ss << " TP offset: 0x" << std::hex << its_offset << " "; + ss << " TP offset: " << std::dec << its_offset << " "; } } return ss.str(); diff --git a/implementation/endpoints/src/tp_reassembler.cpp b/implementation/endpoints/src/tp_reassembler.cpp index f235957fc..a8f8c637e 100644 --- a/implementation/endpoints/src/tp_reassembler.cpp +++ b/implementation/endpoints/src/tp_reassembler.cpp @@ -62,8 +62,34 @@ std::pair tp_reassembler::process_tp_message( if (found_tp_msg != found_port->second.end()) { if (found_tp_msg->second.first == its_session) { // received additional segment for already known message - if (found_tp_msg->second.second.add_segment(_data, _data_size)) { - // message is complete + auto its_status = found_tp_msg->second.second.add_segment(_data, _data_size); + if (its_status == tp_status_e::TPS_DUPLICATE) { + const tp_header_t its_tp_header = bithelper::read_uint32_be(&_data[VSOMEIP_TP_HEADER_POS_MIN]); + const length_t its_offset = tp::get_offset(its_tp_header); + + if (its_offset == 0) { // new first segment + VSOMEIP_WARNING << __func__ << ": Received new start segment. Dropping received data for (" + << std::hex << std::setw(4) << std::setfill('0') << its_client << ") [" + << std::hex << std::setw(4) << std::setfill('0') << its_service << "." + << std::hex << std::setw(4) << std::setfill('0') << its_method << "." + << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_interface_version) << "." + << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_msg_type) << "] Old: 0x" + << std::hex << std::setw(4) << std::setfill('0') << found_tp_msg->second.first << ", new: 0x" + << std::hex << std::setw(4) << std::setfill('0') << its_session; + // new segment with same session id -> throw away current message data + found_tp_msg->second.second = tp_message(_data, _data_size, max_message_size_); + } else { + VSOMEIP_WARNING << __func__ << ": Received duplicate segment. Dropping it (" + << std::hex << std::setw(4) << std::setfill('0') << its_client << ") [" + << std::hex << std::setw(4) << std::setfill('0') << its_service << "." + << std::hex << std::setw(4) << std::setfill('0') << its_method << "." + << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_interface_version) << "." + << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_msg_type) << "] Old: 0x" + << std::hex << std::setw(4) << std::setfill('0') << found_tp_msg->second.first << ", new: 0x" + << std::hex << std::setw(4) << std::setfill('0') << its_session + << " TP offset:" << std::dec << its_offset; + } + } else if (its_status == tp_status_e::TPS_COMPLETE) { // message is complete ret.first = true; ret.second = found_tp_msg->second.second.get_message(); // cleanup tp_message as message was moved and cleanup map @@ -74,11 +100,12 @@ std::pair tp_reassembler::process_tp_message( tp_messages_.erase(found_ip); } } + } else { + // ignore } } else { - VSOMEIP_WARNING << __func__ << ": Received new segment " - "although old one is not finished yet. Dropping " - "old. (" + VSOMEIP_WARNING << __func__ << ": Received new message although old one is not " + "finished yet. Dropping old. (" << std::hex << std::setfill('0') << std::setw(4) << its_client << ") [" << std::setw(4) << its_service << "." @@ -87,7 +114,7 @@ std::pair tp_reassembler::process_tp_message( << std::setw(2) << std::uint32_t(its_msg_type) << "] Old: 0x" << std::setw(4) << found_tp_msg->second.first << ", new: 0x" << std::setw(4) << its_session; - // new segment with different session id -> throw away current + // new segment with different session id -> reset session and throw away current message data found_tp_msg->second.first = its_session; found_tp_msg->second.second = tp_message(_data, _data_size, max_message_size_); }