From b57538d7e2f1d563a9cf94ff1932fdfc2828183b Mon Sep 17 00:00:00 2001 From: "Minju, Lee" Date: Sun, 22 Jun 2025 08:59:38 +0900 Subject: [PATCH 1/3] Add rmw_get_service_endpoint_info and update graph cache entity to support service type hash Signed-off-by: Minju, Lee --- rmw_fastrtps_cpp/CMakeLists.txt | 1 + rmw_fastrtps_cpp/src/rmw_client.cpp | 5 +- .../src/rmw_get_service_endpoint_info.cpp | 46 ++++ rmw_fastrtps_cpp/src/rmw_service.cpp | 5 +- rmw_fastrtps_dynamic_cpp/CMakeLists.txt | 1 + rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp | 5 +- .../src/rmw_get_service_endpoint_info.cpp | 46 ++++ rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp | 5 +- rmw_fastrtps_shared_cpp/CMakeLists.txt | 1 + .../custom_participant_info.hpp | 11 +- .../include/rmw_fastrtps_shared_cpp/qos.hpp | 6 +- .../rmw_fastrtps_shared_cpp/rmw_common.hpp | 21 ++ rmw_fastrtps_shared_cpp/src/qos.cpp | 21 +- .../src/rmw_get_service_endpoint_info.cpp | 256 ++++++++++++++++++ 14 files changed, 413 insertions(+), 17 deletions(-) create mode 100644 rmw_fastrtps_cpp/src/rmw_get_service_endpoint_info.cpp create mode 100644 rmw_fastrtps_dynamic_cpp/src/rmw_get_service_endpoint_info.cpp create mode 100644 rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp diff --git a/rmw_fastrtps_cpp/CMakeLists.txt b/rmw_fastrtps_cpp/CMakeLists.txt index c29a7c013c..4793ed63eb 100644 --- a/rmw_fastrtps_cpp/CMakeLists.txt +++ b/rmw_fastrtps_cpp/CMakeLists.txt @@ -68,6 +68,7 @@ add_library(rmw_fastrtps_cpp src/rmw_get_gid_for_publisher.cpp src/rmw_get_implementation_identifier.cpp src/rmw_get_serialization_format.cpp + src/rmw_get_service_endpoint_info.cpp src/rmw_get_topic_endpoint_info.cpp src/rmw_guard_condition.cpp src/rmw_init.cpp diff --git a/rmw_fastrtps_cpp/src/rmw_client.cpp b/rmw_fastrtps_cpp/src/rmw_client.cpp index 4f052b73d6..c1350b71bc 100644 --- a/rmw_fastrtps_cpp/src/rmw_client.cpp +++ b/rmw_fastrtps_cpp/src/rmw_client.cpp @@ -319,10 +319,11 @@ rmw_create_client( reader_qos.data_sharing().off(); } + const rosidl_type_hash_t * ser_type_hash = type_supports->get_type_hash_func(type_supports); if (!get_datareader_qos( adapted_qos_policies, *type_supports->response_typesupport->get_type_hash_func(type_supports->response_typesupport), - reader_qos)) + reader_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_client() failed setting response DataReader QoS"); return nullptr; @@ -389,7 +390,7 @@ rmw_create_client( if (!get_datawriter_qos( adapted_qos_policies, *type_supports->request_typesupport->get_type_hash_func(type_supports->request_typesupport), - writer_qos)) + writer_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_client() failed setting request DataWriter QoS"); return nullptr; diff --git a/rmw_fastrtps_cpp/src/rmw_get_service_endpoint_info.cpp b/rmw_fastrtps_cpp/src/rmw_get_service_endpoint_info.cpp new file mode 100644 index 0000000000..2e36f0ba89 --- /dev/null +++ b/rmw_fastrtps_cpp/src/rmw_get_service_endpoint_info.cpp @@ -0,0 +1,46 @@ +// Copyright 2025 Minju Lee (이민주). All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rmw/get_service_endpoint_info.h" +#include "rmw/service_endpoint_info_array.h" +#include "rmw/types.h" +#include "rmw_fastrtps_cpp/identifier.hpp" +#include "rmw_fastrtps_shared_cpp/rmw_common.hpp" + +extern "C" +{ +rmw_ret_t +rmw_get_clients_info_by_service( + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * clients_info) +{ + return rmw_fastrtps_shared_cpp::__rmw_get_clients_info_by_service( + eprosima_fastrtps_identifier, node, allocator, service_name, no_mangle, clients_info); +} + +rmw_ret_t +rmw_get_servers_info_by_service( + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * servers_info) +{ + return rmw_fastrtps_shared_cpp::__rmw_get_servers_info_by_service( + eprosima_fastrtps_identifier, node, allocator, service_name, no_mangle, servers_info); +} +} // extern "C" diff --git a/rmw_fastrtps_cpp/src/rmw_service.cpp b/rmw_fastrtps_cpp/src/rmw_service.cpp index 0dc457abdf..a116173db1 100644 --- a/rmw_fastrtps_cpp/src/rmw_service.cpp +++ b/rmw_fastrtps_cpp/src/rmw_service.cpp @@ -315,10 +315,11 @@ rmw_create_service( reader_qos.data_sharing().off(); } + const rosidl_type_hash_t * ser_type_hash = type_supports->get_type_hash_func(type_supports); if (!get_datareader_qos( adapted_qos_policies, *type_supports->request_typesupport->get_type_hash_func(type_supports->request_typesupport), - reader_qos)) + reader_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_service() failed setting request DataReader QoS"); return nullptr; @@ -389,7 +390,7 @@ rmw_create_service( if (!get_datawriter_qos( adapted_qos_policies, *type_supports->response_typesupport->get_type_hash_func(type_supports->response_typesupport), - writer_qos)) + writer_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_service() failed setting response DataWriter QoS"); return nullptr; diff --git a/rmw_fastrtps_dynamic_cpp/CMakeLists.txt b/rmw_fastrtps_dynamic_cpp/CMakeLists.txt index 6bb2129cfb..ca37227ab4 100644 --- a/rmw_fastrtps_dynamic_cpp/CMakeLists.txt +++ b/rmw_fastrtps_dynamic_cpp/CMakeLists.txt @@ -66,6 +66,7 @@ add_library(rmw_fastrtps_dynamic_cpp src/rmw_get_gid_for_publisher.cpp src/rmw_get_implementation_identifier.cpp src/rmw_get_serialization_format.cpp + src/rmw_get_service_endpoint_info.cpp src/rmw_get_topic_endpoint_info.cpp src/rmw_guard_condition.cpp src/rmw_init.cpp diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp index 483c03cd42..ff04e63cec 100644 --- a/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp @@ -348,10 +348,11 @@ rmw_create_client( reader_qos.data_sharing().off(); } + const rosidl_type_hash_t * ser_type_hash = type_supports->get_type_hash_func(type_supports); if (!get_datareader_qos( adapted_qos_policies, *type_supports->response_typesupport->get_type_hash_func(type_supports->response_typesupport), - reader_qos)) + reader_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_client() failed setting response DataReader QoS"); return nullptr; @@ -418,7 +419,7 @@ rmw_create_client( if (!get_datawriter_qos( adapted_qos_policies, *type_supports->request_typesupport->get_type_hash_func(type_supports->request_typesupport), - writer_qos)) + writer_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_client() failed setting request DataWriter QoS"); return nullptr; diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_get_service_endpoint_info.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_get_service_endpoint_info.cpp new file mode 100644 index 0000000000..a962c69b2c --- /dev/null +++ b/rmw_fastrtps_dynamic_cpp/src/rmw_get_service_endpoint_info.cpp @@ -0,0 +1,46 @@ +// Copyright 2025 Minju Lee (이민주). All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rmw/get_service_endpoint_info.h" +#include "rmw/service_endpoint_info_array.h" +#include "rmw/types.h" +#include "rmw_fastrtps_dynamic_cpp/identifier.hpp" +#include "rmw_fastrtps_shared_cpp/rmw_common.hpp" + +extern "C" +{ +rmw_ret_t +rmw_get_clients_info_by_service( + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * clients_info) +{ + return rmw_fastrtps_shared_cpp::__rmw_get_clients_info_by_service( + eprosima_fastrtps_identifier, node, allocator, service_name, no_mangle, clients_info); +} + +rmw_ret_t +rmw_get_servers_info_by_service( + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * servers_info) +{ + return rmw_fastrtps_shared_cpp::__rmw_get_servers_info_by_service( + eprosima_fastrtps_identifier, node, allocator, service_name, no_mangle, servers_info); +} +} // extern "C" diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp index 3c6201b182..b4a6143d23 100644 --- a/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp @@ -344,10 +344,11 @@ rmw_create_service( reader_qos.data_sharing().off(); } + const rosidl_type_hash_t * ser_type_hash = type_supports->get_type_hash_func(type_supports); if (!get_datareader_qos( adapted_qos_policies, *type_supports->request_typesupport->get_type_hash_func(type_supports->request_typesupport), - reader_qos)) + reader_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_service() failed setting request DataReader QoS"); return nullptr; @@ -418,7 +419,7 @@ rmw_create_service( if (!get_datawriter_qos( adapted_qos_policies, *type_supports->response_typesupport->get_type_hash_func(type_supports->response_typesupport), - writer_qos)) + writer_qos, ser_type_hash)) { RMW_SET_ERROR_MSG("create_service() failed setting response DataWriter QoS"); return nullptr; diff --git a/rmw_fastrtps_shared_cpp/CMakeLists.txt b/rmw_fastrtps_shared_cpp/CMakeLists.txt index a8032cd40c..2475015ec2 100644 --- a/rmw_fastrtps_shared_cpp/CMakeLists.txt +++ b/rmw_fastrtps_shared_cpp/CMakeLists.txt @@ -71,6 +71,7 @@ add_library(rmw_fastrtps_shared_cpp src/rmw_get_endpoint_network_flow.cpp src/rmw_get_gid_for_client.cpp src/rmw_get_gid_for_publisher.cpp + src/rmw_get_service_endpoint_info.cpp src/rmw_get_topic_endpoint_info.cpp src/rmw_guard_condition.cpp src/rmw_init.cpp diff --git a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_participant_info.hpp b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_participant_info.hpp index 8b4ee92b94..308a178807 100644 --- a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_participant_info.hpp +++ b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_participant_info.hpp @@ -243,7 +243,13 @@ class ParticipantListener : public eprosima::fastdds::dds::DomainParticipantList // We've handled the error, so clear it out. rmw_reset_error(); } - + rosidl_type_hash_t ser_type_hash; + rosidl_type_hash_t * ser_type_hash_ptr = nullptr; + if (RMW_RET_OK == rmw_dds_common::parse_sertype_hash_from_user_data( + userDataValue.data(), userDataValue.size(), ser_type_hash)) + { + ser_type_hash_ptr = &ser_type_hash; + } context->graph_cache.add_entity( rmw_fastrtps_shared_cpp::create_rmw_gid( identifier_, @@ -255,7 +261,8 @@ class ParticipantListener : public eprosima::fastdds::dds::DomainParticipantList identifier_, proxyData.participant_guid), qos_profile, - is_reader); + is_reader, + ser_type_hash_ptr); } else { context->graph_cache.remove_entity( rmw_fastrtps_shared_cpp::create_rmw_gid( diff --git a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/qos.hpp b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/qos.hpp index aa1c0f4841..9a3c8f2455 100644 --- a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/qos.hpp +++ b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/qos.hpp @@ -36,14 +36,16 @@ bool get_datareader_qos( const rmw_qos_profile_t & qos_policies, const rosidl_type_hash_t & type_hash, - eprosima::fastdds::dds::DataReaderQos & reader_qos); + eprosima::fastdds::dds::DataReaderQos & reader_qos, + const rosidl_type_hash_t * ser_type_hash = nullptr); RMW_FASTRTPS_SHARED_CPP_PUBLIC bool get_datawriter_qos( const rmw_qos_profile_t & qos_policies, const rosidl_type_hash_t & type_hash, - eprosima::fastdds::dds::DataWriterQos & writer_qos); + eprosima::fastdds::dds::DataWriterQos & writer_qos, + const rosidl_type_hash_t * ser_type_hash = nullptr); RMW_FASTRTPS_SHARED_CPP_PUBLIC bool diff --git a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/rmw_common.hpp b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/rmw_common.hpp index 98ebf7d3d9..fa4be7c799 100644 --- a/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/rmw_common.hpp +++ b/rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/rmw_common.hpp @@ -24,6 +24,7 @@ #include "rmw/event.h" #include "rmw/features.h" #include "rmw/rmw.h" +#include "rmw/service_endpoint_info_array.h" #include "rmw/topic_endpoint_info_array.h" #include "rmw/types.h" #include "rmw/names_and_types.h" @@ -523,6 +524,26 @@ __rmw_get_subscriptions_info_by_topic( bool no_mangle, rmw_topic_endpoint_info_array_t * subscriptions_info); +RMW_FASTRTPS_SHARED_CPP_PUBLIC +rmw_ret_t +__rmw_get_clients_info_by_service( + const char * identifier, + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * clients_info); + +RMW_FASTRTPS_SHARED_CPP_PUBLIC +rmw_ret_t +__rmw_get_servers_info_by_service( + const char * identifier, + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * servers_info); + RMW_FASTRTPS_SHARED_CPP_PUBLIC rmw_ret_t __rmw_qos_profile_check_compatible( diff --git a/rmw_fastrtps_shared_cpp/src/qos.cpp b/rmw_fastrtps_shared_cpp/src/qos.cpp index c11bead552..88862922fa 100644 --- a/rmw_fastrtps_shared_cpp/src/qos.cpp +++ b/rmw_fastrtps_shared_cpp/src/qos.cpp @@ -154,7 +154,8 @@ bool fill_data_entity_qos_from_profile( const rmw_qos_profile_t & qos_policies, const rosidl_type_hash_t & type_hash, - DDSEntityQos & entity_qos) + DDSEntityQos & entity_qos, + const rosidl_type_hash_t * ser_type_hash = nullptr) { if (!fill_entity_qos_from_profile(qos_policies, entity_qos)) { return false; @@ -169,6 +170,14 @@ fill_data_entity_qos_from_profile( // code won't overwrite it. rmw_reset_error(); } + if (ser_type_hash) { + std::string typehash_str; + if (RMW_RET_OK == + rmw_dds_common::encode_sertype_hash_for_user_data_qos(*ser_type_hash, typehash_str)) + { + user_data_str += typehash_str; + } + } std::vector user_data(user_data_str.begin(), user_data_str.end()); entity_qos.user_data().resize(user_data.size()); entity_qos.user_data().setValue(user_data); @@ -179,9 +188,10 @@ bool get_datareader_qos( const rmw_qos_profile_t & qos_policies, const rosidl_type_hash_t & type_hash, - eprosima::fastdds::dds::DataReaderQos & datareader_qos) + eprosima::fastdds::dds::DataReaderQos & datareader_qos, + const rosidl_type_hash_t * ser_type_hash) { - if (fill_data_entity_qos_from_profile(qos_policies, type_hash, datareader_qos)) { + if (fill_data_entity_qos_from_profile(qos_policies, type_hash, datareader_qos, ser_type_hash)) { // The type support in the RMW implementation is always XCDR1. constexpr auto rep = eprosima::fastdds::dds::XCDR_DATA_REPRESENTATION; datareader_qos.representation().clear(); @@ -196,9 +206,10 @@ bool get_datawriter_qos( const rmw_qos_profile_t & qos_policies, const rosidl_type_hash_t & type_hash, - eprosima::fastdds::dds::DataWriterQos & datawriter_qos) + eprosima::fastdds::dds::DataWriterQos & datawriter_qos, + const rosidl_type_hash_t * ser_type_hash) { - if (fill_data_entity_qos_from_profile(qos_policies, type_hash, datawriter_qos)) { + if (fill_data_entity_qos_from_profile(qos_policies, type_hash, datawriter_qos, ser_type_hash)) { // The type support in the RMW implementation is always XCDR1. constexpr auto rep = eprosima::fastdds::dds::XCDR_DATA_REPRESENTATION; datawriter_qos.representation().clear(); diff --git a/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp b/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp new file mode 100644 index 0000000000..5326b78c05 --- /dev/null +++ b/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp @@ -0,0 +1,256 @@ +// Copyright 2025 Minju Lee (이민주). All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "rmw/impl/cpp/macros.hpp" +#include "rmw/rmw.h" +#include "rmw/types.h" +#include "rmw/topic_endpoint_info_array.h" +#include "rmw/topic_endpoint_info.h" +#include "rmw/service_endpoint_info_array.h" +#include "rmw/service_endpoint_info.h" + +#include "rmw_fastrtps_shared_cpp/custom_participant_info.hpp" +#include "rmw_fastrtps_shared_cpp/names.hpp" +#include "rmw_fastrtps_shared_cpp/rmw_common.hpp" +#include "rmw_fastrtps_shared_cpp/rmw_context_impl.hpp" + +#include "rmw_dds_common/graph_cache.hpp" + +#include "demangle.hpp" + +namespace rmw_fastrtps_shared_cpp +{ + +static rmw_ret_t __validate_arguments( + const char * identifier, + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * topic_name, + rmw_service_endpoint_info_array_t * participants_info) +{ + RMW_CHECK_ARGUMENT_FOR_NULL(node, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_TYPE_IDENTIFIERS_MATCH( + node, + node->implementation_identifier, + identifier, + return RMW_RET_INCORRECT_RMW_IMPLEMENTATION); + RCUTILS_CHECK_ALLOCATOR_WITH_MSG( + allocator, "allocator argument is invalid", return RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(topic_name, RMW_RET_INVALID_ARGUMENT); + if (RMW_RET_OK != rmw_service_endpoint_info_array_check_zero(participants_info)) { + return RMW_RET_INVALID_ARGUMENT; + } + return RMW_RET_OK; +} + + +rmw_ret_t +__rmw_get_clients_info_by_service( + const char * identifier, + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * clients_info) +{ + rmw_ret_t ret = __validate_arguments( + identifier, + node, + allocator, + service_name, + clients_info); + if (ret != RMW_RET_OK) { + return ret; + } + if (no_mangle) { + // Services in DDS require mangled topic names + // because they internally use separate readers and writers. + // Therefore, this function cannot support the 'no_mangle' option. + // If user need to query raw topic information without mangling, + // use`rmw_get_publishers_info_by_topic` or `rmw_get_subscriptions_info_by_topic` instead. + RMW_SET_ERROR_MSG( + "'no_mangle' is not supported for services" + " because they rely on internally mangled topic names.\n" + "Use 'rmw_get_publishers_info_by_topic' or 'rmw_get_subscriptions_info_by_topic'" + " instead to access unmangled topic information."); + return RMW_RET_INVALID_ARGUMENT; + } + auto common_context = static_cast(node->context->impl->common); + std::string mangled_rq_topic_name = \ + _mangle_topic_name(ros_service_requester_prefix, service_name, "Request").to_string(); + std::string mangled_rp_topic_name = \ + _mangle_topic_name(ros_service_response_prefix, service_name, "Reply").to_string(); + DemangleFunction demangle_type = _demangle_service_type_only; + + rmw_topic_endpoint_info_array_t subscriptions_info = + rmw_get_zero_initialized_topic_endpoint_info_array(); + std::unique_ptr< + rmw_topic_endpoint_info_array_t, + std::function> + subscriptions_info_delete( + &subscriptions_info, + [allocator](rmw_topic_endpoint_info_array_t * p) { + rmw_ret_t ret = rmw_topic_endpoint_info_array_fini( + p, + allocator + ); + if (RMW_RET_OK != ret) { + RMW_SET_ERROR_MSG("Failed to destroy subscriptions_info when function ended."); + } + } + ); + ret = common_context->graph_cache.get_readers_info_by_topic( + mangled_rp_topic_name, + demangle_type, + allocator, + &subscriptions_info); + if(RMW_RET_OK != ret) { + return ret; + } + + rmw_topic_endpoint_info_array_t publishers_info = + rmw_get_zero_initialized_topic_endpoint_info_array(); + std::unique_ptr< + rmw_topic_endpoint_info_array_t, + std::function> + publishers_info_delete( + &publishers_info, + [allocator](rmw_topic_endpoint_info_array_t * p) { + rmw_ret_t ret = rmw_topic_endpoint_info_array_fini( + p, + allocator + ); + if (RMW_RET_OK != ret) { + RMW_SET_ERROR_MSG("Failed to destroy publishers_info when function ended."); + } + } + ); + ret = common_context->graph_cache.get_writers_info_by_topic( + mangled_rq_topic_name, + demangle_type, + allocator, + &publishers_info); + if(RMW_RET_OK != ret) { + return ret; + } + + return common_context->graph_cache.get_clients_info_by_service( + &subscriptions_info, + &publishers_info, + allocator, + clients_info); +} + +rmw_ret_t +__rmw_get_servers_info_by_service( + const char * identifier, + const rmw_node_t * node, + rcutils_allocator_t * allocator, + const char * service_name, + bool no_mangle, + rmw_service_endpoint_info_array_t * servers_info) +{ + rmw_ret_t ret = __validate_arguments( + identifier, + node, + allocator, + service_name, + servers_info); + if (ret != RMW_RET_OK) { + return ret; + } + if (no_mangle) { + // Services in DDS require mangled topic names + // because they internally use separate readers and writers. + // Therefore, this function cannot support the 'no_mangle' option. + // If user need to query raw topic information without mangling, + // use`rmw_get_publishers_info_by_topic` or `rmw_get_subscriptions_info_by_topic` instead. + RMW_SET_ERROR_MSG( + "'no_mangle' is not supported for services" + " because they rely on internally mangled topic names.\n" + "Use 'rmw_get_publishers_info_by_topic' or 'rmw_get_subscriptions_info_by_topic'" + " instead to access unmangled topic information."); + return RMW_RET_INVALID_ARGUMENT; + } + auto common_context = static_cast(node->context->impl->common); + std::string mangled_rq_topic_name = \ + _mangle_topic_name(ros_service_requester_prefix, service_name, "Request").to_string(); + std::string mangled_rp_topic_name = \ + _mangle_topic_name(ros_service_response_prefix, service_name, "Reply").to_string(); + DemangleFunction demangle_type = _demangle_service_type_only; + + rmw_topic_endpoint_info_array_t subscriptions_info = + rmw_get_zero_initialized_topic_endpoint_info_array(); + std::unique_ptr< + rmw_topic_endpoint_info_array_t, + std::function> + subscriptions_info_delete( + &subscriptions_info, + [allocator](rmw_topic_endpoint_info_array_t * p) { + rmw_ret_t ret = rmw_topic_endpoint_info_array_fini( + p, + allocator + ); + if (RMW_RET_OK != ret) { + RMW_SET_ERROR_MSG("Failed to destroy subscriptions_info when function failed."); + } + } + ); + ret = common_context->graph_cache.get_readers_info_by_topic( + mangled_rq_topic_name, + demangle_type, + allocator, + &subscriptions_info); + if(RMW_RET_OK != ret) { + return ret; + } + + rmw_topic_endpoint_info_array_t publishers_info = + rmw_get_zero_initialized_topic_endpoint_info_array(); + std::unique_ptr< + rmw_topic_endpoint_info_array_t, + std::function> + publishers_info_delete( + &publishers_info, + [allocator](rmw_topic_endpoint_info_array_t * p) { + rmw_ret_t ret = rmw_topic_endpoint_info_array_fini( + p, + allocator + ); + if (RMW_RET_OK != ret) { + RMW_SET_ERROR_MSG("Failed to destroy publishers_info when function failed."); + } + } + ); + ret = common_context->graph_cache.get_writers_info_by_topic( + mangled_rp_topic_name, + demangle_type, + allocator, + &publishers_info); + if(RMW_RET_OK != ret) { + return ret; + } + return common_context->graph_cache.get_servers_info_by_service( + &subscriptions_info, + &publishers_info, + allocator, + servers_info); +} +} // namespace rmw_fastrtps_shared_cpp From 9ffda3fd299072f57964727fb411461d4a1e02ad Mon Sep 17 00:00:00 2001 From: "Minju, Lee" Date: Sun, 22 Jun 2025 09:00:02 +0900 Subject: [PATCH 2/3] Fix rmw_count_services Signed-off-by: Minju, Lee --- rmw_fastrtps_shared_cpp/src/rmw_count.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rmw_fastrtps_shared_cpp/src/rmw_count.cpp b/rmw_fastrtps_shared_cpp/src/rmw_count.cpp index b24f12e684..5e8cf0621d 100644 --- a/rmw_fastrtps_shared_cpp/src/rmw_count.cpp +++ b/rmw_fastrtps_shared_cpp/src/rmw_count.cpp @@ -155,8 +155,8 @@ __rmw_count_services( } RMW_CHECK_ARGUMENT_FOR_NULL(count, RMW_RET_INVALID_ARGUMENT); auto common_context = static_cast(node->context->impl->common); - const std::string mangled_rp_service_name = - _mangle_topic_name(ros_service_response_prefix, service_name, "Reply").to_string(); - return common_context->graph_cache.get_writer_count(mangled_rp_service_name, count); + const std::string mangled_rq_service_name = + _mangle_topic_name(ros_service_requester_prefix, service_name, "Request").to_string(); + return common_context->graph_cache.get_reader_count(mangled_rq_service_name, count); } } // namespace rmw_fastrtps_shared_cpp From 950a7da6af6bd07a7004b2a2b25a925a1ab2d7a6 Mon Sep 17 00:00:00 2001 From: "Minju, Lee" Date: Wed, 25 Jun 2025 11:56:35 +0900 Subject: [PATCH 3/3] Fix headers from review Signed-off-by: Minju, Lee --- rmw_fastrtps_shared_cpp/src/qos.cpp | 1 + rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rmw_fastrtps_shared_cpp/src/qos.cpp b/rmw_fastrtps_shared_cpp/src/qos.cpp index 88862922fa..a9593e3d8b 100644 --- a/rmw_fastrtps_shared_cpp/src/qos.cpp +++ b/rmw_fastrtps_shared_cpp/src/qos.cpp @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include #include "rcutils/logging_macros.h" diff --git a/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp b/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp index 5326b78c05..368342f8e0 100644 --- a/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp +++ b/rmw_fastrtps_shared_cpp/src/rmw_get_service_endpoint_info.cpp @@ -13,7 +13,9 @@ // limitations under the License. #include +#include #include +#include #include #include #include @@ -60,7 +62,6 @@ static rmw_ret_t __validate_arguments( return RMW_RET_OK; } - rmw_ret_t __rmw_get_clients_info_by_service( const char * identifier,