From 7ae8a0ddf6af579f79f08e44773854202f886ad4 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 14 Feb 2023 15:37:11 -0800 Subject: [PATCH 01/16] WIP start adding entrypoint to fill out type version hash Signed-off-by: Emerson Knapp --- rmw_dds_common/include/rmw_dds_common/graph_cache.hpp | 11 ++++++++++- rmw_dds_common/src/graph_cache.cpp | 9 +++++++-- .../test/benchmark/benchmark_graph_cache.cpp | 1 + rmw_dds_common/test/test_graph_cache.cpp | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 30802e6..00d484a 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -24,6 +24,7 @@ #include #include "rcutils/logging_macros.h" +#include "rcutils/sha256.h" #include "rmw/names_and_types.h" #include "rmw/topic_endpoint_info.h" @@ -94,6 +95,7 @@ class GraphCache const rmw_gid_t & writer_gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); @@ -113,6 +115,7 @@ class GraphCache const rmw_gid_t & reader_gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); @@ -133,6 +136,7 @@ class GraphCache const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos, bool is_reader); @@ -543,6 +547,8 @@ struct EntityInfo std::string topic_name; /// Topic type. std::string topic_type; + /// Topic type hash. + uint8_t topic_type_hash[RCUTILS_SHA256_BLOCK_SIZE]; /// Participant gid. rmw_gid_t participant_gid; /// Quality of service of the topic. @@ -552,13 +558,16 @@ struct EntityInfo EntityInfo( const std::string & topic_name, const std::string & topic_type, + const uint8_t topic_type_hash_[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) : topic_name(topic_name), topic_type(topic_type), participant_gid(participant_gid), qos(qos) - {} + { + memcpy(topic_type_hash, topic_type_hash_, RCUTILS_SHA256_BLOCK_SIZE); + } }; } // namespace rmw_dds_common diff --git a/rmw_dds_common/src/graph_cache.cpp b/rmw_dds_common/src/graph_cache.cpp index 551bb1b..9b018ae 100644 --- a/rmw_dds_common/src/graph_cache.cpp +++ b/rmw_dds_common/src/graph_cache.cpp @@ -67,6 +67,7 @@ GraphCache::add_writer( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) { @@ -74,7 +75,7 @@ GraphCache::add_writer( auto pair = data_writers_.emplace( std::piecewise_construct, std::forward_as_tuple(gid), - std::forward_as_tuple(topic_name, type_name, participant_gid, qos)); + std::forward_as_tuple(topic_name, type_name, type_hash, participant_gid, qos)); GRAPH_CACHE_CALL_ON_CHANGE_CALLBACK_IF(this, pair.second); return pair.second; } @@ -84,6 +85,7 @@ GraphCache::add_reader( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) { @@ -91,7 +93,7 @@ GraphCache::add_reader( auto pair = data_readers_.emplace( std::piecewise_construct, std::forward_as_tuple(gid), - std::forward_as_tuple(topic_name, type_name, participant_gid, qos)); + std::forward_as_tuple(topic_name, type_name, type_hash, participant_gid, qos)); GRAPH_CACHE_CALL_ON_CHANGE_CALLBACK_IF(this, pair.second); return pair.second; } @@ -101,6 +103,7 @@ GraphCache::add_entity( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos, bool is_reader) @@ -110,6 +113,7 @@ GraphCache::add_entity( gid, topic_name, type_name, + type_hash, participant_gid, qos); } @@ -117,6 +121,7 @@ GraphCache::add_entity( gid, topic_name, type_name, + type_hash, participant_gid, qos); } diff --git a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp index 349bb7a..00dc372 100644 --- a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp +++ b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp @@ -120,6 +120,7 @@ add_entities( gid_from_string(elem.gid), elem.name, elem.type, + nullptr, gid_from_string(elem.participant_gid), rmw_qos_profile_default, elem.is_reader); diff --git a/rmw_dds_common/test/test_graph_cache.cpp b/rmw_dds_common/test/test_graph_cache.cpp index b4c4206..dad9700 100644 --- a/rmw_dds_common/test/test_graph_cache.cpp +++ b/rmw_dds_common/test/test_graph_cache.cpp @@ -303,6 +303,7 @@ add_entities( gid_from_string(elem.gid), elem.name, elem.type, + nullptr, gid_from_string(elem.participant_gid), rmw_qos_profile_default, elem.is_reader)); From 144c58d329fbdce1ff9b25c19fce2705bd794ec6 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 14 Feb 2023 16:34:34 -0800 Subject: [PATCH 02/16] Set the type hash on rmw_topic_endpoint_info Signed-off-by: Emerson Knapp --- rmw_dds_common/src/graph_cache.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rmw_dds_common/src/graph_cache.cpp b/rmw_dds_common/src/graph_cache.cpp index 9b018ae..9b18eda 100644 --- a/rmw_dds_common/src/graph_cache.cpp +++ b/rmw_dds_common/src/graph_cache.cpp @@ -575,6 +575,13 @@ __get_entities_info_by_topic( return ret; } + ret = rmw_topic_endpoint_info_set_topic_type_hash( + &endpoint_info, + entity_pair.second.topic_type_hash); + if (RMW_RET_OK != ret) { + return ret; + } + ret = rmw_topic_endpoint_info_set_endpoint_type( &endpoint_info, is_reader ? RMW_ENDPOINT_SUBSCRIPTION : RMW_ENDPOINT_PUBLISHER); From 57d5cd41b425cc2b67b4108fce833b56e7f9aa36 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Mon, 20 Feb 2023 11:49:18 -0800 Subject: [PATCH 03/16] WIP Type hash encoding helper functions Signed-off-by: Emerson Knapp --- .../include/rmw_dds_common/graph_cache.hpp | 5 ++ rmw_dds_common/include/rmw_dds_common/qos.hpp | 22 +++++++ rmw_dds_common/src/qos.cpp | 65 +++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 00d484a..a9af00c 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -566,6 +566,11 @@ struct EntityInfo participant_gid(participant_gid), qos(qos) { + RCUTILS_CHECK_FOR_NULL_WITH_MSG( + topic_type_hash_, + "Type hash cannot be null", + throw std::runtime_error("Type hash cannot be null.")); + RCUTILS_LOG_WARN("EntityInfo ctor, type hash %p", topic_type_hash_); memcpy(topic_type_hash, topic_type_hash_, RCUTILS_SHA256_BLOCK_SIZE); } }; diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index 3f0b128..bd9e693 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -16,6 +16,7 @@ #define RMW_DDS_COMMON__QOS_HPP_ #include +#include #include "rmw/qos_profiles.h" #include "rmw/topic_endpoint_info_array.h" @@ -224,6 +225,27 @@ RMW_DDS_COMMON_PUBLIC rmw_qos_profile_t qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_profile); +/// TODO(emersonknapp) +/** + * TODO(emersonknapp) + */ +RMW_DDS_COMMON_PUBLIC +rmw_ret_t +parse_type_hash_from_user_data_qos( + const uint8_t * user_data, + size_t user_data_size, + uint8_t out_type_hash[RCUTILS_SHA256_BLOCK_SIZE]); + +/// TODO(emersonknapp) +/** + * TODO(emersonknapp) + */ +RMW_DDS_COMMON_PUBLIC +rmw_ret_t +encode_type_hash_for_user_data_qos( + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + std::vector & out_data); + } // namespace rmw_dds_common #endif // RMW_DDS_COMMON__QOS_HPP_ diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index da1a8da..f9b28d7 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -16,7 +16,12 @@ #include #include +#include +#include +#include +#include "rcutils/error_handling.h" +#include "rcutils/logging_macros.h" #include "rcutils/snprintf.h" #include "rmw/error_handling.h" #include "rmw/get_topic_endpoint_info.h" @@ -664,4 +669,64 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro return result; } +rmw_ret_t +parse_type_hash_from_user_data_qos( + const uint8_t * user_data, + size_t user_data_size, + uint8_t out_type_hash[RCUTILS_SHA256_BLOCK_SIZE]) +{ + const std::string prefix = "type_hash="; + const std::string suffix = ";"; + const size_t expected_size = prefix.size() + RCUTILS_SHA256_BLOCK_SIZE + suffix.size(); + const uint8_t * hash_data = user_data + prefix.size(); + const uint8_t * suffix_data = hash_data + RCUTILS_SHA256_BLOCK_SIZE; + + if (user_data_size < expected_size) { + // Not the right size to be type hash user data + RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("NOT RIGHT SIZE %zu", user_data_size); + RCUTILS_LOG_ERROR("NOT RIGHT SIZE %zu", user_data_size); + return RMW_RET_ERROR; + } + if (memcmp(user_data, prefix.data(), prefix.size()) != 0) { + // Key is not "type_hash=" + RCUTILS_SET_ERROR_MSG("Wrong key!"); + RCUTILS_LOG_ERROR("WRONG KEY"); + return RMW_RET_ERROR; + } + if (memcmp(suffix_data, suffix.data(), suffix.size()) != 0) { + // No final semicolon + RCUTILS_SET_ERROR_MSG("No final ;"); + RCUTILS_LOG_ERROR("No final ;"); + return RMW_RET_ERROR; + } + memcpy(out_type_hash, hash_data, RCUTILS_SHA256_BLOCK_SIZE); + { + // Just debugging output TODO(emersonknapp) remove + std::stringstream ss; + ss << std::setw(2) << std::setfill('0'); + for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { + ss << std::hex << static_cast(out_type_hash[i]); + } + RCUTILS_LOG_ERROR(" --- %s", ss.str().c_str()); + } + return RMW_RET_OK; +} + +rmw_ret_t +encode_type_hash_for_user_data_qos( + const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + std::vector & out_data) +{ + static const std::string prefix = "type_hash="; + static const std::string suffix = ";"; + static const size_t data_size = prefix.size() + RCUTILS_SHA256_BLOCK_SIZE + suffix.size(); + assert(type_hash != nullptr); + out_data.clear(); + out_data.reserve(data_size); + out_data.insert(out_data.end(), prefix.begin(), prefix.end()); + out_data.insert(out_data.end(), type_hash, type_hash + RCUTILS_SHA256_BLOCK_SIZE); + out_data.insert(out_data.end(), suffix.begin(), suffix.end()); + return RMW_RET_OK; +} + } // namespace rmw_dds_common From 2e5c9679d2ee1a3dbce3839fee3b30688e69b0d2 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Mon, 20 Feb 2023 16:28:26 -0800 Subject: [PATCH 04/16] User data key-value encodings Signed-off-by: Emerson Knapp --- .../include/rmw_dds_common/graph_cache.hpp | 1 - rmw_dds_common/include/rmw_dds_common/qos.hpp | 7 +- rmw_dds_common/src/qos.cpp | 67 ++++++------------- 3 files changed, 23 insertions(+), 52 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index a9af00c..1c97bb1 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -570,7 +570,6 @@ struct EntityInfo topic_type_hash_, "Type hash cannot be null", throw std::runtime_error("Type hash cannot be null.")); - RCUTILS_LOG_WARN("EntityInfo ctor, type hash %p", topic_type_hash_); memcpy(topic_type_hash, topic_type_hash_, RCUTILS_SHA256_BLOCK_SIZE); } }; diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index bd9e693..0503c8f 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -16,6 +16,7 @@ #define RMW_DDS_COMMON__QOS_HPP_ #include +#include #include #include "rmw/qos_profiles.h" @@ -241,10 +242,8 @@ parse_type_hash_from_user_data_qos( * TODO(emersonknapp) */ RMW_DDS_COMMON_PUBLIC -rmw_ret_t -encode_type_hash_for_user_data_qos( - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], - std::vector & out_data); +std::string +encode_type_hash_for_user_data_qos(const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE]); } // namespace rmw_dds_common diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index f9b28d7..b3bc221 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -24,6 +24,7 @@ #include "rcutils/logging_macros.h" #include "rcutils/snprintf.h" #include "rmw/error_handling.h" +#include "rmw/impl/cpp/key_value.hpp" #include "rmw/get_topic_endpoint_info.h" #include "rmw/qos_profiles.h" #include "rmw/qos_string_conversions.h" @@ -675,58 +676,30 @@ parse_type_hash_from_user_data_qos( size_t user_data_size, uint8_t out_type_hash[RCUTILS_SHA256_BLOCK_SIZE]) { - const std::string prefix = "type_hash="; - const std::string suffix = ";"; - const size_t expected_size = prefix.size() + RCUTILS_SHA256_BLOCK_SIZE + suffix.size(); - const uint8_t * hash_data = user_data + prefix.size(); - const uint8_t * suffix_data = hash_data + RCUTILS_SHA256_BLOCK_SIZE; - - if (user_data_size < expected_size) { - // Not the right size to be type hash user data - RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("NOT RIGHT SIZE %zu", user_data_size); - RCUTILS_LOG_ERROR("NOT RIGHT SIZE %zu", user_data_size); - return RMW_RET_ERROR; - } - if (memcmp(user_data, prefix.data(), prefix.size()) != 0) { - // Key is not "type_hash=" - RCUTILS_SET_ERROR_MSG("Wrong key!"); - RCUTILS_LOG_ERROR("WRONG KEY"); - return RMW_RET_ERROR; - } - if (memcmp(suffix_data, suffix.data(), suffix.size()) != 0) { - // No final semicolon - RCUTILS_SET_ERROR_MSG("No final ;"); - RCUTILS_LOG_ERROR("No final ;"); - return RMW_RET_ERROR; - } - memcpy(out_type_hash, hash_data, RCUTILS_SHA256_BLOCK_SIZE); - { - // Just debugging output TODO(emersonknapp) remove - std::stringstream ss; - ss << std::setw(2) << std::setfill('0'); - for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { - ss << std::hex << static_cast(out_type_hash[i]); - } - RCUTILS_LOG_ERROR(" --- %s", ss.str().c_str()); + std::vector udvec(user_data, user_data + user_data_size); + auto key_value = rmw::impl::cpp::parse_key_value(udvec); + auto type_hash_value = key_value.at("typehash"); + + std::string type_hash_str(type_hash_value.begin(), type_hash_value.end()); + assert(type_hash_str.size() == RCUTILS_SHA256_BLOCK_SIZE * 2); + RCUTILS_LOG_ERROR(" - %s", type_hash_str.c_str()); + std::istringstream iss(type_hash_str); + for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { + iss >> std::hex >> out_type_hash[i]; } return RMW_RET_OK; } -rmw_ret_t -encode_type_hash_for_user_data_qos( - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], - std::vector & out_data) +std::string +encode_type_hash_for_user_data_qos(const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE]) { - static const std::string prefix = "type_hash="; - static const std::string suffix = ";"; - static const size_t data_size = prefix.size() + RCUTILS_SHA256_BLOCK_SIZE + suffix.size(); - assert(type_hash != nullptr); - out_data.clear(); - out_data.reserve(data_size); - out_data.insert(out_data.end(), prefix.begin(), prefix.end()); - out_data.insert(out_data.end(), type_hash, type_hash + RCUTILS_SHA256_BLOCK_SIZE); - out_data.insert(out_data.end(), suffix.begin(), suffix.end()); - return RMW_RET_OK; + std::ostringstream os; + os << "typehash="; + for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { + os << std::hex << std::setw(2) << std::setfill('0') << static_cast(type_hash[i]); + } + os << ";"; + return os.str(); } } // namespace rmw_dds_common From 638af67a2e3584012e5708cb8e82978d7c93e87b Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 21 Feb 2023 20:27:38 -0800 Subject: [PATCH 05/16] Type hash struct Signed-off-by: Emerson Knapp --- .../include/rmw_dds_common/graph_cache.hpp | 22 +++++++----------- rmw_dds_common/include/rmw_dds_common/qos.hpp | 7 +++--- rmw_dds_common/src/graph_cache.cpp | 8 +++---- rmw_dds_common/src/qos.cpp | 23 ++++++++++++------- .../test/benchmark/benchmark_graph_cache.cpp | 2 +- rmw_dds_common/test/test_graph_cache.cpp | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 1c97bb1..610b015 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -24,7 +24,6 @@ #include #include "rcutils/logging_macros.h" -#include "rcutils/sha256.h" #include "rmw/names_and_types.h" #include "rmw/topic_endpoint_info.h" @@ -95,7 +94,7 @@ class GraphCache const rmw_gid_t & writer_gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); @@ -115,7 +114,7 @@ class GraphCache const rmw_gid_t & reader_gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); @@ -136,7 +135,7 @@ class GraphCache const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos, bool is_reader); @@ -545,10 +544,10 @@ struct EntityInfo { /// Topic name. std::string topic_name; - /// Topic type. + /// Topic type name. std::string topic_type; /// Topic type hash. - uint8_t topic_type_hash[RCUTILS_SHA256_BLOCK_SIZE]; + rosidl_type_hash_t topic_type_hash; /// Participant gid. rmw_gid_t participant_gid; /// Quality of service of the topic. @@ -558,20 +557,15 @@ struct EntityInfo EntityInfo( const std::string & topic_name, const std::string & topic_type, - const uint8_t topic_type_hash_[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & topic_type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) : topic_name(topic_name), topic_type(topic_type), + topic_type_hash(topic_type_hash), participant_gid(participant_gid), qos(qos) - { - RCUTILS_CHECK_FOR_NULL_WITH_MSG( - topic_type_hash_, - "Type hash cannot be null", - throw std::runtime_error("Type hash cannot be null.")); - memcpy(topic_type_hash, topic_type_hash_, RCUTILS_SHA256_BLOCK_SIZE); - } + {} }; } // namespace rmw_dds_common diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index 0503c8f..c3d63ec 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -231,11 +231,10 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro * TODO(emersonknapp) */ RMW_DDS_COMMON_PUBLIC -rmw_ret_t +rosidl_type_hash_t parse_type_hash_from_user_data_qos( const uint8_t * user_data, - size_t user_data_size, - uint8_t out_type_hash[RCUTILS_SHA256_BLOCK_SIZE]); + size_t user_data_size); /// TODO(emersonknapp) /** @@ -243,7 +242,7 @@ parse_type_hash_from_user_data_qos( */ RMW_DDS_COMMON_PUBLIC std::string -encode_type_hash_for_user_data_qos(const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE]); +encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash); } // namespace rmw_dds_common diff --git a/rmw_dds_common/src/graph_cache.cpp b/rmw_dds_common/src/graph_cache.cpp index 9b18eda..8c2a46b 100644 --- a/rmw_dds_common/src/graph_cache.cpp +++ b/rmw_dds_common/src/graph_cache.cpp @@ -67,7 +67,7 @@ GraphCache::add_writer( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) { @@ -85,7 +85,7 @@ GraphCache::add_reader( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos) { @@ -103,7 +103,7 @@ GraphCache::add_entity( const rmw_gid_t & gid, const std::string & topic_name, const std::string & type_name, - const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE], + const rosidl_type_hash_t & type_hash, const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos, bool is_reader) @@ -577,7 +577,7 @@ __get_entities_info_by_topic( ret = rmw_topic_endpoint_info_set_topic_type_hash( &endpoint_info, - entity_pair.second.topic_type_hash); + &entity_pair.second.topic_type_hash); if (RMW_RET_OK != ret) { return ret; } diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index b3bc221..3c29aad 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -670,33 +670,40 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro return result; } -rmw_ret_t +rosidl_type_hash_t parse_type_hash_from_user_data_qos( const uint8_t * user_data, - size_t user_data_size, - uint8_t out_type_hash[RCUTILS_SHA256_BLOCK_SIZE]) + size_t user_data_size) { std::vector udvec(user_data, user_data + user_data_size); auto key_value = rmw::impl::cpp::parse_key_value(udvec); - auto type_hash_value = key_value.at("typehash"); + auto typehash_it = key_value.find("typehash"); + if (typehash_it == key_value.end()) { + return rosidl_get_zero_initialized_type_hash(); + } + auto type_hash_value = typehash_it->second; std::string type_hash_str(type_hash_value.begin(), type_hash_value.end()); assert(type_hash_str.size() == RCUTILS_SHA256_BLOCK_SIZE * 2); RCUTILS_LOG_ERROR(" - %s", type_hash_str.c_str()); + + rosidl_type_hash_t type_hash; + // TODO(emersonknapp) type_hash.version! std::istringstream iss(type_hash_str); for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { - iss >> std::hex >> out_type_hash[i]; + iss >> std::hex >> type_hash.value[i]; } - return RMW_RET_OK; + return type_hash; } std::string -encode_type_hash_for_user_data_qos(const uint8_t type_hash[RCUTILS_SHA256_BLOCK_SIZE]) +encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash) { std::ostringstream os; os << "typehash="; + // TODO(emersonknapp) version prefix for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { - os << std::hex << std::setw(2) << std::setfill('0') << static_cast(type_hash[i]); + os << std::hex << std::setw(2) << std::setfill('0') << static_cast(type_hash.value[i]); } os << ";"; return os.str(); diff --git a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp index 00dc372..cf6dff1 100644 --- a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp +++ b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp @@ -120,7 +120,7 @@ add_entities( gid_from_string(elem.gid), elem.name, elem.type, - nullptr, + rosidl_get_zero_initialized_type_hash(), gid_from_string(elem.participant_gid), rmw_qos_profile_default, elem.is_reader); diff --git a/rmw_dds_common/test/test_graph_cache.cpp b/rmw_dds_common/test/test_graph_cache.cpp index dad9700..c9927ad 100644 --- a/rmw_dds_common/test/test_graph_cache.cpp +++ b/rmw_dds_common/test/test_graph_cache.cpp @@ -303,7 +303,7 @@ add_entities( gid_from_string(elem.gid), elem.name, elem.type, - nullptr, + rosidl_get_zero_initialized_type_hash(), gid_from_string(elem.participant_gid), rmw_qos_profile_default, elem.is_reader)); From 512d7ee65b4bd63bbf55e5b9ff7fac6dd6c77ca1 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 21 Feb 2023 21:00:38 -0800 Subject: [PATCH 06/16] Linkage to rosidl_runtime_c dep Signed-off-by: Emerson Knapp --- rmw_dds_common/CMakeLists.txt | 9 ++++++--- rmw_dds_common/package.xml | 1 + rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/rmw_dds_common/CMakeLists.txt b/rmw_dds_common/CMakeLists.txt index b930cc3..6db5a2a 100644 --- a/rmw_dds_common/CMakeLists.txt +++ b/rmw_dds_common/CMakeLists.txt @@ -17,6 +17,7 @@ find_package(rcpputils REQUIRED) find_package(rcutils REQUIRED) find_package(rmw REQUIRED) find_package(rosidl_default_generators REQUIRED) +find_package(rosidl_runtime_c REQUIRED) ament_add_default_options() ament_export_dependencies(ament_cmake_core) @@ -44,7 +45,8 @@ target_link_libraries(${PROJECT_NAME}_library PUBLIC rcutils::rcutils rmw::rmw) target_link_libraries(${PROJECT_NAME}_library PRIVATE - rcpputils::rcpputils) + rcpputils::rcpputils + rosidl_runtime_c::rosidl_runtime_c) target_include_directories(${PROJECT_NAME}_library PUBLIC "$" @@ -95,7 +97,8 @@ if(BUILD_TESTING) ament_add_gmock(test_graph_cache test/test_graph_cache.cpp) if(TARGET test_graph_cache) - target_link_libraries(test_graph_cache ${PROJECT_NAME}_library osrf_testing_tools_cpp::memory_tools) + target_link_libraries(test_graph_cache + ${PROJECT_NAME}_library osrf_testing_tools_cpp::memory_tools rosidl_runtime_c::rosidl_runtime_c) target_compile_definitions(test_graph_cache PUBLIC RCUTILS_ENABLE_FAULT_INJECTION) endif() @@ -123,7 +126,7 @@ if(BUILD_TESTING) add_performance_test(benchmark_graph_cache test/benchmark/benchmark_graph_cache.cpp) if(TARGET benchmark_graph_cache) - target_link_libraries(benchmark_graph_cache ${PROJECT_NAME}_library) + target_link_libraries(benchmark_graph_cache ${PROJECT_NAME}_library rosidl_runtime_c::rosidl_runtime_c) endif() endif() diff --git a/rmw_dds_common/package.xml b/rmw_dds_common/package.xml index b0b57a7..8257e50 100644 --- a/rmw_dds_common/package.xml +++ b/rmw_dds_common/package.xml @@ -20,6 +20,7 @@ rcutils rcpputils rmw + rosidl_runtime_c rosidl_runtime_cpp ament_cmake_gmock diff --git a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp index cf6dff1..1fe8b55 100644 --- a/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp +++ b/rmw_dds_common/test/benchmark/benchmark_graph_cache.cpp @@ -24,6 +24,8 @@ #include "rmw_dds_common/gid_utils.hpp" #include "rmw_dds_common/graph_cache.hpp" +#include "rosidl_runtime_c/type_hash.h" + using performance_test_fixture::PerformanceTest; using rmw_dds_common::GraphCache; From e51c1f759c3501713279ccf712711f08bf9ac987 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 21 Feb 2023 21:36:28 -0800 Subject: [PATCH 07/16] Stop using sha256 consts Signed-off-by: Emerson Knapp --- rmw_dds_common/src/qos.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 3c29aad..60d5dbe 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -684,13 +684,13 @@ parse_type_hash_from_user_data_qos( auto type_hash_value = typehash_it->second; std::string type_hash_str(type_hash_value.begin(), type_hash_value.end()); - assert(type_hash_str.size() == RCUTILS_SHA256_BLOCK_SIZE * 2); + assert(type_hash_str.size() == ROSIDL_TYPE_HASH_SIZE * 2); RCUTILS_LOG_ERROR(" - %s", type_hash_str.c_str()); rosidl_type_hash_t type_hash; // TODO(emersonknapp) type_hash.version! std::istringstream iss(type_hash_str); - for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { + for (size_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { iss >> std::hex >> type_hash.value[i]; } return type_hash; @@ -699,10 +699,15 @@ parse_type_hash_from_user_data_qos( std::string encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash) { + if (type_hash.version == ROSIDL_TYPE_HASH_VERSION_UNSET) { + return ""; + } + std::ostringstream os; os << "typehash="; + // os << "RIHS" << type_hash.version << "_"; // TODO(emersonknapp) version prefix - for (size_t i = 0; i < RCUTILS_SHA256_BLOCK_SIZE; i++) { + for (size_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { os << std::hex << std::setw(2) << std::setfill('0') << static_cast(type_hash.value[i]); } os << ";"; From c37320527942a04368be448385a18a92858dd4b6 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 21 Feb 2023 23:28:19 -0800 Subject: [PATCH 08/16] Use rosidl_runtime_c type hash parser/encoder Signed-off-by: Emerson Knapp --- rmw_dds_common/src/qos.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 60d5dbe..c9698f0 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -676,23 +676,20 @@ parse_type_hash_from_user_data_qos( size_t user_data_size) { std::vector udvec(user_data, user_data + user_data_size); + rosidl_type_hash_t type_hash; + + auto key_value = rmw::impl::cpp::parse_key_value(udvec); auto typehash_it = key_value.find("typehash"); if (typehash_it == key_value.end()) { return rosidl_get_zero_initialized_type_hash(); } - auto type_hash_value = typehash_it->second; - - std::string type_hash_str(type_hash_value.begin(), type_hash_value.end()); - assert(type_hash_str.size() == ROSIDL_TYPE_HASH_SIZE * 2); - RCUTILS_LOG_ERROR(" - %s", type_hash_str.c_str()); - - rosidl_type_hash_t type_hash; - // TODO(emersonknapp) type_hash.version! - std::istringstream iss(type_hash_str); - for (size_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { - iss >> std::hex >> type_hash.value[i]; - } + std::string type_hash_str(typehash_it->second.begin(), typehash_it->second.end()); + rosidl_parse_type_hash_string( + type_hash_str.data(), + type_hash_str.size(), + &type_hash); + // RCUTILS_LOG_WARN("Hi am smashy"); return type_hash; } @@ -702,16 +699,12 @@ encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash) if (type_hash.version == ROSIDL_TYPE_HASH_VERSION_UNSET) { return ""; } - - std::ostringstream os; - os << "typehash="; - // os << "RIHS" << type_hash.version << "_"; - // TODO(emersonknapp) version prefix - for (size_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { - os << std::hex << std::setw(2) << std::setfill('0') << static_cast(type_hash.value[i]); + auto allocator = rcutils_get_default_allocator(); + char * type_hash_c_str = nullptr; + if (RCUTILS_RET_OK != rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str)) { + return ""; } - os << ";"; - return os.str(); + return "typehash=" + std::string(type_hash_c_str) + ";"; } } // namespace rmw_dds_common From 7564a5e8a76c369a875040ec35e1f78ed0b31c17 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Wed, 22 Feb 2023 17:27:27 -0800 Subject: [PATCH 09/16] Code cleanup Signed-off-by: Emerson Knapp --- rmw_dds_common/include/rmw_dds_common/qos.hpp | 11 +++++++---- rmw_dds_common/src/qos.cpp | 5 +---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index c3d63ec..954be81 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -226,9 +226,11 @@ RMW_DDS_COMMON_PUBLIC rmw_qos_profile_t qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_profile); -/// TODO(emersonknapp) +/// Parse the standard USER_DATA key=value;key=value; encoding, and find typehash /** - * TODO(emersonknapp) + * \param[in] user_data USER_DATA qos raw bytes + * \param[in] user_data_size Length of user_data + * \return Parsed type hash, may be zero-initialized unset value if data couldn't be parsed */ RMW_DDS_COMMON_PUBLIC rosidl_type_hash_t @@ -236,9 +238,10 @@ parse_type_hash_from_user_data_qos( const uint8_t * user_data, size_t user_data_size); -/// TODO(emersonknapp) +/// Encode a type hash as standardized USER_DATA key=value; substring /** - * TODO(emersonknapp) + * \param[in] type_hash Type hash value to encode + * \return A substring in key=value; format that can be appended to QoS USER_DATA */ RMW_DDS_COMMON_PUBLIC std::string diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index c9698f0..434687f 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -678,7 +678,6 @@ parse_type_hash_from_user_data_qos( std::vector udvec(user_data, user_data + user_data_size); rosidl_type_hash_t type_hash; - auto key_value = rmw::impl::cpp::parse_key_value(udvec); auto typehash_it = key_value.find("typehash"); if (typehash_it == key_value.end()) { @@ -686,10 +685,8 @@ parse_type_hash_from_user_data_qos( } std::string type_hash_str(typehash_it->second.begin(), typehash_it->second.end()); rosidl_parse_type_hash_string( - type_hash_str.data(), - type_hash_str.size(), + type_hash_str.c_str(), &type_hash); - // RCUTILS_LOG_WARN("Hi am smashy"); return type_hash; } From 73448e8d438bfbfbf6ae220e819331d8b3fd6ef3 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Sat, 11 Mar 2023 19:26:20 -0800 Subject: [PATCH 10/16] Add tests Signed-off-by: Emerson Knapp --- rmw_dds_common/include/rmw_dds_common/qos.hpp | 9 ++-- rmw_dds_common/src/qos.cpp | 2 +- rmw_dds_common/test/test_qos.cpp | 48 +++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index 954be81..925cd6e 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -226,19 +226,20 @@ RMW_DDS_COMMON_PUBLIC rmw_qos_profile_t qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_profile); -/// Parse the standard USER_DATA key=value;key=value; encoding, and find typehash +/// Parse USER_DATA key=value;key=value; encoding, find value of key "typehash" /** * \param[in] user_data USER_DATA qos raw bytes * \param[in] user_data_size Length of user_data - * \return Parsed type hash, may be zero-initialized unset value if data couldn't be parsed + * \return Parsed type hash + * \return zero-initialized value if data unparseable or key not found */ RMW_DDS_COMMON_PUBLIC rosidl_type_hash_t -parse_type_hash_from_user_data_qos( +parse_type_hash_from_user_data( const uint8_t * user_data, size_t user_data_size); -/// Encode a type hash as standardized USER_DATA key=value; substring +/// Encode type hash as "typehash=hash_string;" /** * \param[in] type_hash Type hash value to encode * \return A substring in key=value; format that can be appended to QoS USER_DATA diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 434687f..e05d7b1 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -671,7 +671,7 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro } rosidl_type_hash_t -parse_type_hash_from_user_data_qos( +parse_type_hash_from_user_data( const uint8_t * user_data, size_t user_data_size) { diff --git a/rmw_dds_common/test/test_qos.cpp b/rmw_dds_common/test/test_qos.cpp index c8aedbb..da761f8 100644 --- a/rmw_dds_common/test/test_qos.cpp +++ b/rmw_dds_common/test/test_qos.cpp @@ -1072,3 +1072,51 @@ TEST(test_qos, test_qos_profile_update_best_available_for_services) rmw_qos_profile_services_default.liveliness_lease_duration, output_profile.liveliness_lease_duration)); } + +TEST(test_qos, test_parse_type_hash_from_user_data) +{ + const auto zero_val = rosidl_get_zero_initialized_type_hash(); + + std::string bad_value = "something that isn't key equals value semicolon"; + rosidl_type_hash_t result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(bad_value.data()), bad_value.size()); + EXPECT_EQ(0, memcmp(&result_type_hash, &zero_val, sizeof(rosidl_type_hash_t))) + << "Malformed user_data should result in zero hash struct."; + + std::string no_key = "key1=value1;key2=value2;key3=value3;"; + result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(no_key.data()), no_key.size()); + EXPECT_EQ(0, memcmp(&result_type_hash, &zero_val, sizeof(rosidl_type_hash_t))) + << "No typehash key should result in zero hash struct."; + + rosidl_type_hash_t input_type_hash; + input_type_hash.version = 1; + for (uint8_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { + input_type_hash.value[i] = i; + } + char * type_hash_c_str; + auto allocator = rcutils_get_default_allocator(); + rmw_ret_t ret = rosidl_stringify_type_hash(&input_type_hash, allocator, &type_hash_c_str); + ASSERT_EQ(ret, RCUTILS_RET_OK); + std::string type_hash_string(type_hash_c_str); + allocator.deallocate(type_hash_c_str, &allocator.state); + std::string good_data = "foo=bar;typehash=" + type_hash_string + ";key=value;"; + result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(good_data.data()), good_data.size()); + EXPECT_EQ(0, memcmp(&result_type_hash, &input_type_hash, sizeof(rosidl_type_hash_t))); +} + +TEST(test_qos, test_encode_type_hash_for_user_data_qos) +{ + rosidl_type_hash_t test_hash = rosidl_get_zero_initialized_type_hash(); + EXPECT_EQ(rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash), ""); + + test_hash.version = 1; + for (uint8_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { + test_hash.value[i] = i; + } + std::string result = rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash); + EXPECT_EQ( + result, + "typehash=RIHS01_000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;"); +} From c5dbe7c978d63e5bc0f0ed79ffa658e7d10323c4 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Mon, 13 Mar 2023 00:47:41 -0700 Subject: [PATCH 11/16] Update docstrings Signed-off-by: Emerson Knapp --- rmw_dds_common/include/rmw_dds_common/graph_cache.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 610b015..2fd32dc 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -83,6 +83,7 @@ class GraphCache * \param writer_gid GUID of the data writer. * \param topic_name Name of the DDS topic for this data writer. * \param type_name Type name of the DDS topic for this data writer. + * \param type_hash Hash of the description of the topic type. * \param participant_gid GUID of the participant. * \param qos QoS profile of the data writer. * \return `true` if the cache was updated, `false` if the data writer @@ -103,6 +104,7 @@ class GraphCache * \param reader_gid GUID of the The data reader. * \param topic_name Name of the DDS topic for this data reader. * \param type_name Type name of the DDS topic for this data reader. + * \param type_hash Hash of the description of the topic type. * \param participant_gid GUID of the participant. * \param qos QoS profile of the data reader. * \return `true` if the cache was updated, `false` if the data reader @@ -123,6 +125,7 @@ class GraphCache * \param gid GUID of the entity. * \param topic_name Name of the DDS topic for this data reader. * \param type_name Type name of the DDS topic for this entity + * \param type_hash Hash of the description of the topic type. * \param participant_gid GUID of the participant. * \param qos QoS profile of the entity. * \param is_reader Whether the entity is a data reader or a writer. From ce7202599bf4910feb8891937a413d4b20419690 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Mon, 13 Mar 2023 20:04:30 -0700 Subject: [PATCH 12/16] Ticktock deprecate graphcache fns, change qos utility signatures to do more error handling Signed-off-by: Emerson Knapp --- .../include/rmw_dds_common/graph_cache.hpp | 49 ++++++++++++++++- rmw_dds_common/include/rmw_dds_common/qos.hpp | 26 +++++---- rmw_dds_common/src/graph_cache.cpp | 53 +++++++++++++++++++ rmw_dds_common/src/qos.cpp | 38 +++++++------ rmw_dds_common/test/test_qos.cpp | 31 +++++++---- 5 files changed, 159 insertions(+), 38 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 2fd32dc..724fc5e 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -78,7 +78,7 @@ class GraphCache * @{ */ - /// Add a data writer. + /// Add a data writer based on discovery. /** * \param writer_gid GUID of the data writer. * \param topic_name Name of the DDS topic for this data writer. @@ -99,6 +99,21 @@ class GraphCache const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); + /// Add a data writer based on discovery. + /** + * See add_reader with rosidl_type_hash_t, whose other parameters match these. + */ + RMW_DDS_COMMON_PUBLIC + RCUTILS_DEPRECATED_WITH_MSG( + "Migrate to using the version of this function taking a type hash.") + bool + add_writer( + const rmw_gid_t & writer_gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos); + /// Add a data reader based on discovery. /** * \param reader_gid GUID of the The data reader. @@ -120,6 +135,21 @@ class GraphCache const rmw_gid_t & participant_gid, const rmw_qos_profile_t & qos); + /// Add a data reader based on discovery. + /** + * See add_reader with rosidl_type_hash_t, whose other parameters match these. + */ + RMW_DDS_COMMON_PUBLIC + RCUTILS_DEPRECATED_WITH_MSG( + "Migrate to using the version of this function taking a type hash.") + bool + add_reader( + const rmw_gid_t & reader_gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos); + /// Add a data reader or writer. /** * \param gid GUID of the entity. @@ -143,6 +173,23 @@ class GraphCache const rmw_qos_profile_t & qos, bool is_reader); + /// Add a data reader or writer. + /** + * See add_entity with rosidl_type_hash_t, whose other parameters match these. + */ + RMW_DDS_COMMON_PUBLIC + RCUTILS_DEPRECATED_WITH_MSG( + "Migrate to using the version of this function taking a type hash.") + bool + add_entity( + const rmw_gid_t & gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos, + bool is_reader); + + /// Remove a data writer. /** * \param gid GUID of the data writer. diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index 925cd6e..9b0f093 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -17,7 +17,6 @@ #include #include -#include #include "rmw/qos_profiles.h" #include "rmw/topic_endpoint_info_array.h" @@ -226,27 +225,34 @@ RMW_DDS_COMMON_PUBLIC rmw_qos_profile_t qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_profile); -/// Parse USER_DATA key=value;key=value; encoding, find value of key "typehash" +/// Parse USER_DATA "key=value;key=value;"" encoding, finding value of key "typehash" /** * \param[in] user_data USER_DATA qos raw bytes * \param[in] user_data_size Length of user_data - * \return Parsed type hash - * \return zero-initialized value if data unparseable or key not found + * \param[out] type_hash_out Filled with type hash data if found, or to zero value if key not found + * \return RMW_RET_OK if key parsed successfully, or if key not found + * \return RMW_RET_ERROR if typehash key found, but value could not be parsed */ RMW_DDS_COMMON_PUBLIC -rosidl_type_hash_t +rmw_ret_t parse_type_hash_from_user_data( const uint8_t * user_data, - size_t user_data_size); + size_t user_data_size, + rosidl_type_hash_t & type_hash_out); -/// Encode type hash as "typehash=hash_string;" +/// Encode type hash as "typehash=hash_string;" for use in USER_DATA QoS /** * \param[in] type_hash Type hash value to encode - * \return A substring in key=value; format that can be appended to QoS USER_DATA + * \param[out] string_out On success, will be set to "typehash=stringified_type_hash;" + * If type_hash's version is 0, string_out will be set to empty + * \return RMW_RET_OK on success, including empty string for unset version + * \return RMW_RET_BAD_ALLOC if memory allocation fails */ RMW_DDS_COMMON_PUBLIC -std::string -encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash); +rmw_ret_t +encode_type_hash_for_user_data_qos( + const rosidl_type_hash_t & type_hash, + std::string & string_out); } // namespace rmw_dds_common diff --git a/rmw_dds_common/src/graph_cache.cpp b/rmw_dds_common/src/graph_cache.cpp index 8c2a46b..52f6b20 100644 --- a/rmw_dds_common/src/graph_cache.cpp +++ b/rmw_dds_common/src/graph_cache.cpp @@ -80,6 +80,23 @@ GraphCache::add_writer( return pair.second; } +bool +GraphCache::add_writer( + const rmw_gid_t & gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos) +{ + return this->add_writer( + gid, + topic_name, + type_name, + rosidl_get_zero_initialized_type_hash(), + participant_gid, + qos); +} + bool GraphCache::add_reader( const rmw_gid_t & gid, @@ -98,6 +115,23 @@ GraphCache::add_reader( return pair.second; } +bool +GraphCache::add_reader( + const rmw_gid_t & gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos) +{ + return this->add_reader( + gid, + topic_name, + type_name, + rosidl_get_zero_initialized_type_hash(), + participant_gid, + qos); +} + bool GraphCache::add_entity( const rmw_gid_t & gid, @@ -126,6 +160,25 @@ GraphCache::add_entity( qos); } +bool +GraphCache::add_entity( + const rmw_gid_t & gid, + const std::string & topic_name, + const std::string & type_name, + const rmw_gid_t & participant_gid, + const rmw_qos_profile_t & qos, + bool is_reader) +{ + return this->add_entity( + gid, + topic_name, + type_name, + rosidl_get_zero_initialized_type_hash(), + participant_gid, + qos, + is_reader); +} + bool GraphCache::remove_writer(const rmw_gid_t & gid) { diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index e05d7b1..57374aa 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include "rcutils/error_handling.h" #include "rcutils/logging_macros.h" @@ -670,38 +670,44 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro return result; } -rosidl_type_hash_t +rmw_ret_t parse_type_hash_from_user_data( const uint8_t * user_data, - size_t user_data_size) + size_t user_data_size, + rosidl_type_hash_t & type_hash_out) { std::vector udvec(user_data, user_data + user_data_size); - rosidl_type_hash_t type_hash; - auto key_value = rmw::impl::cpp::parse_key_value(udvec); auto typehash_it = key_value.find("typehash"); if (typehash_it == key_value.end()) { - return rosidl_get_zero_initialized_type_hash(); + type_hash_out = rosidl_get_zero_initialized_type_hash(); + return RMW_RET_OK; } std::string type_hash_str(typehash_it->second.begin(), typehash_it->second.end()); - rosidl_parse_type_hash_string( - type_hash_str.c_str(), - &type_hash); - return type_hash; + if (RMW_RET_OK != rosidl_parse_type_hash_string(type_hash_str.c_str(), &type_hash_out)) { + return RMW_RET_ERROR; + } + return RMW_RET_OK; } -std::string -encode_type_hash_for_user_data_qos(const rosidl_type_hash_t & type_hash) +rmw_ret_t +encode_type_hash_for_user_data_qos( + const rosidl_type_hash_t & type_hash, + std::string & string_out) { if (type_hash.version == ROSIDL_TYPE_HASH_VERSION_UNSET) { - return ""; + string_out.clear(); + return RMW_RET_OK; } auto allocator = rcutils_get_default_allocator(); char * type_hash_c_str = nullptr; - if (RCUTILS_RET_OK != rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str)) { - return ""; + rmw_ret_t stringify_ret = rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str); + if (RCUTILS_RET_OK != stringify_ret) { + return stringify_ret; } - return "typehash=" + std::string(type_hash_c_str) + ";"; + string_out = "typehash=" + std::string(type_hash_c_str) + ";"; + allocator.deallocate(type_hash_c_str, &allocator.state); + return RMW_RET_OK; } } // namespace rmw_dds_common diff --git a/rmw_dds_common/test/test_qos.cpp b/rmw_dds_common/test/test_qos.cpp index da761f8..28753c8 100644 --- a/rmw_dds_common/test/test_qos.cpp +++ b/rmw_dds_common/test/test_qos.cpp @@ -1078,14 +1078,17 @@ TEST(test_qos, test_parse_type_hash_from_user_data) const auto zero_val = rosidl_get_zero_initialized_type_hash(); std::string bad_value = "something that isn't key equals value semicolon"; - rosidl_type_hash_t result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( - reinterpret_cast(bad_value.data()), bad_value.size()); + rosidl_type_hash_t result_type_hash; + rmw_ret_t ret = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(bad_value.data()), bad_value.size(), result_type_hash); + EXPECT_EQ(ret, RMW_RET_OK); EXPECT_EQ(0, memcmp(&result_type_hash, &zero_val, sizeof(rosidl_type_hash_t))) - << "Malformed user_data should result in zero hash struct."; + << "Non-ros 2 user_data should result in zero hash struct."; std::string no_key = "key1=value1;key2=value2;key3=value3;"; - result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( - reinterpret_cast(no_key.data()), no_key.size()); + ret = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(no_key.data()), no_key.size(), result_type_hash); + EXPECT_EQ(ret, RMW_RET_OK); EXPECT_EQ(0, memcmp(&result_type_hash, &zero_val, sizeof(rosidl_type_hash_t))) << "No typehash key should result in zero hash struct."; @@ -1096,27 +1099,33 @@ TEST(test_qos, test_parse_type_hash_from_user_data) } char * type_hash_c_str; auto allocator = rcutils_get_default_allocator(); - rmw_ret_t ret = rosidl_stringify_type_hash(&input_type_hash, allocator, &type_hash_c_str); + ret = rosidl_stringify_type_hash(&input_type_hash, allocator, &type_hash_c_str); ASSERT_EQ(ret, RCUTILS_RET_OK); std::string type_hash_string(type_hash_c_str); allocator.deallocate(type_hash_c_str, &allocator.state); std::string good_data = "foo=bar;typehash=" + type_hash_string + ";key=value;"; - result_type_hash = rmw_dds_common::parse_type_hash_from_user_data( - reinterpret_cast(good_data.data()), good_data.size()); + ret = rmw_dds_common::parse_type_hash_from_user_data( + reinterpret_cast(good_data.data()), good_data.size(), result_type_hash); + EXPECT_EQ(ret, RMW_RET_OK); EXPECT_EQ(0, memcmp(&result_type_hash, &input_type_hash, sizeof(rosidl_type_hash_t))); } TEST(test_qos, test_encode_type_hash_for_user_data_qos) { rosidl_type_hash_t test_hash = rosidl_get_zero_initialized_type_hash(); - EXPECT_EQ(rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash), ""); + std::string hash_string; + rmw_ret_t ret = rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash, hash_string); + EXPECT_EQ(ret, RMW_RET_OK); + EXPECT_EQ(hash_string, ""); test_hash.version = 1; for (uint8_t i = 0; i < ROSIDL_TYPE_HASH_SIZE; i++) { test_hash.value[i] = i; } - std::string result = rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash); + hash_string.clear(); + ret = rmw_dds_common::encode_type_hash_for_user_data_qos(test_hash, hash_string); + EXPECT_EQ(ret, RMW_RET_OK); EXPECT_EQ( - result, + hash_string, "typehash=RIHS01_000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;"); } From 8dd475f4a9c4445afe1c1cc19dd92a19d69f62a6 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Mon, 13 Mar 2023 20:18:15 -0700 Subject: [PATCH 13/16] Minor code cleanup Signed-off-by: Emerson Knapp --- rmw_dds_common/include/rmw_dds_common/qos.hpp | 1 + rmw_dds_common/src/qos.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rmw_dds_common/include/rmw_dds_common/qos.hpp b/rmw_dds_common/include/rmw_dds_common/qos.hpp index 9b0f093..63e94f7 100644 --- a/rmw_dds_common/include/rmw_dds_common/qos.hpp +++ b/rmw_dds_common/include/rmw_dds_common/qos.hpp @@ -231,6 +231,7 @@ qos_profile_update_best_available_for_services(const rmw_qos_profile_t & qos_pro * \param[in] user_data_size Length of user_data * \param[out] type_hash_out Filled with type hash data if found, or to zero value if key not found * \return RMW_RET_OK if key parsed successfully, or if key not found + * \return RMW_RET_INVALID_ARGUMENT if user_data is null * \return RMW_RET_ERROR if typehash key found, but value could not be parsed */ RMW_DDS_COMMON_PUBLIC diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 57374aa..41ddaeb 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -16,12 +16,10 @@ #include #include -#include #include #include #include "rcutils/error_handling.h" -#include "rcutils/logging_macros.h" #include "rcutils/snprintf.h" #include "rmw/error_handling.h" #include "rmw/impl/cpp/key_value.hpp" @@ -676,6 +674,7 @@ parse_type_hash_from_user_data( size_t user_data_size, rosidl_type_hash_t & type_hash_out) { + RMW_CHECK_ARGUMENT_FOR_NULL(user_data, RMW_RET_INVALID_ARGUMENT); std::vector udvec(user_data, user_data + user_data_size); auto key_value = rmw::impl::cpp::parse_key_value(udvec); auto typehash_it = key_value.find("typehash"); From a237a684f637de8488c555a0e0cb54796f098e2d Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Tue, 14 Mar 2023 17:05:27 -0700 Subject: [PATCH 14/16] Proper return types for qos fns Signed-off-by: Emerson Knapp --- rmw_dds_common/src/qos.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 41ddaeb..5e571d3 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -683,7 +683,7 @@ parse_type_hash_from_user_data( return RMW_RET_OK; } std::string type_hash_str(typehash_it->second.begin(), typehash_it->second.end()); - if (RMW_RET_OK != rosidl_parse_type_hash_string(type_hash_str.c_str(), &type_hash_out)) { + if (RCUTILS_RET_OK != rosidl_parse_type_hash_string(type_hash_str.c_str(), &type_hash_out)) { return RMW_RET_ERROR; } return RMW_RET_OK; @@ -700,9 +700,11 @@ encode_type_hash_for_user_data_qos( } auto allocator = rcutils_get_default_allocator(); char * type_hash_c_str = nullptr; - rmw_ret_t stringify_ret = rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str); - if (RCUTILS_RET_OK != stringify_ret) { - return stringify_ret; + rcutils_ret_t stringify_ret = rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str); + if (RCUTILS_RET_BAD_ALLOC == stringify_ret) { + return RMW_RET_BAD_ALLOC; + } else if (RCUTILS_RET_OK != stringify_ret) { + return RMW_RET_ERROR; } string_out = "typehash=" + std::string(type_hash_c_str) + ";"; allocator.deallocate(type_hash_c_str, &allocator.state); From 643c508124e4f84a9b9a3702d9997e3202b733c1 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Thu, 23 Mar 2023 12:15:04 -0700 Subject: [PATCH 15/16] Use scope exit for deallocation Signed-off-by: Emerson Knapp --- rmw_dds_common/CMakeLists.txt | 2 +- rmw_dds_common/include/rmw_dds_common/graph_cache.hpp | 1 - rmw_dds_common/src/qos.cpp | 6 ++++-- rmw_dds_common/test/test_qos.cpp | 4 +++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/rmw_dds_common/CMakeLists.txt b/rmw_dds_common/CMakeLists.txt index 6db5a2a..a85bbeb 100644 --- a/rmw_dds_common/CMakeLists.txt +++ b/rmw_dds_common/CMakeLists.txt @@ -109,7 +109,7 @@ if(BUILD_TESTING) ament_add_gmock(test_qos test/test_qos.cpp) if(TARGET test_qos) - target_link_libraries(test_qos ${PROJECT_NAME}_library osrf_testing_tools_cpp::memory_tools) + target_link_libraries(test_qos ${PROJECT_NAME}_library osrf_testing_tools_cpp::memory_tools rcpputils::rcpputils) endif() ament_add_gmock(test_time_utils test/test_time_utils.cpp) diff --git a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp index 724fc5e..bc08ecf 100644 --- a/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp +++ b/rmw_dds_common/include/rmw_dds_common/graph_cache.hpp @@ -189,7 +189,6 @@ class GraphCache const rmw_qos_profile_t & qos, bool is_reader); - /// Remove a data writer. /** * \param gid GUID of the data writer. diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 5e571d3..935359c 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -19,6 +19,7 @@ #include #include +#include "rcpputils/scope_exit.hpp" #include "rcutils/error_handling.h" #include "rcutils/snprintf.h" #include "rmw/error_handling.h" @@ -703,11 +704,12 @@ encode_type_hash_for_user_data_qos( rcutils_ret_t stringify_ret = rosidl_stringify_type_hash(&type_hash, allocator, &type_hash_c_str); if (RCUTILS_RET_BAD_ALLOC == stringify_ret) { return RMW_RET_BAD_ALLOC; - } else if (RCUTILS_RET_OK != stringify_ret) { + } + RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); + if (RCUTILS_RET_OK != stringify_ret) { return RMW_RET_ERROR; } string_out = "typehash=" + std::string(type_hash_c_str) + ";"; - allocator.deallocate(type_hash_c_str, &allocator.state); return RMW_RET_OK; } diff --git a/rmw_dds_common/test/test_qos.cpp b/rmw_dds_common/test/test_qos.cpp index 28753c8..32fede0 100644 --- a/rmw_dds_common/test/test_qos.cpp +++ b/rmw_dds_common/test/test_qos.cpp @@ -17,6 +17,7 @@ #include #include "osrf_testing_tools_cpp/scope_exit.hpp" +#include "rcpputils/scope_exit.hpp" #include "rmw/error_handling.h" #include "rmw/qos_profiles.h" #include "rmw/types.h" @@ -1100,9 +1101,10 @@ TEST(test_qos, test_parse_type_hash_from_user_data) char * type_hash_c_str; auto allocator = rcutils_get_default_allocator(); ret = rosidl_stringify_type_hash(&input_type_hash, allocator, &type_hash_c_str); + ASSERT_NE(ret, RCUTILS_RET_BAD_ALLOC); + RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); ASSERT_EQ(ret, RCUTILS_RET_OK); std::string type_hash_string(type_hash_c_str); - allocator.deallocate(type_hash_c_str, &allocator.state); std::string good_data = "foo=bar;typehash=" + type_hash_string + ";key=value;"; ret = rmw_dds_common::parse_type_hash_from_user_data( reinterpret_cast(good_data.data()), good_data.size(), result_type_hash); From 5a2951c89fa620ec1a37378c4f7178d9c4aadd63 Mon Sep 17 00:00:00 2001 From: Emerson Knapp Date: Fri, 24 Mar 2023 10:02:46 -0700 Subject: [PATCH 16/16] Move scope exit to after all error code checking Signed-off-by: Emerson Knapp --- rmw_dds_common/src/qos.cpp | 2 +- rmw_dds_common/test/test_qos.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/rmw_dds_common/src/qos.cpp b/rmw_dds_common/src/qos.cpp index 935359c..7604cb1 100644 --- a/rmw_dds_common/src/qos.cpp +++ b/rmw_dds_common/src/qos.cpp @@ -705,10 +705,10 @@ encode_type_hash_for_user_data_qos( if (RCUTILS_RET_BAD_ALLOC == stringify_ret) { return RMW_RET_BAD_ALLOC; } - RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); if (RCUTILS_RET_OK != stringify_ret) { return RMW_RET_ERROR; } + RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); string_out = "typehash=" + std::string(type_hash_c_str) + ";"; return RMW_RET_OK; } diff --git a/rmw_dds_common/test/test_qos.cpp b/rmw_dds_common/test/test_qos.cpp index 32fede0..1074ce7 100644 --- a/rmw_dds_common/test/test_qos.cpp +++ b/rmw_dds_common/test/test_qos.cpp @@ -1101,9 +1101,8 @@ TEST(test_qos, test_parse_type_hash_from_user_data) char * type_hash_c_str; auto allocator = rcutils_get_default_allocator(); ret = rosidl_stringify_type_hash(&input_type_hash, allocator, &type_hash_c_str); - ASSERT_NE(ret, RCUTILS_RET_BAD_ALLOC); - RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); ASSERT_EQ(ret, RCUTILS_RET_OK); + RCPPUTILS_SCOPE_EXIT(allocator.deallocate(type_hash_c_str, &allocator.state)); std::string type_hash_string(type_hash_c_str); std::string good_data = "foo=bar;typehash=" + type_hash_string + ";key=value;"; ret = rmw_dds_common::parse_type_hash_from_user_data(