From 41c1bd07faa249992d40594c3d18eb750ebe4f9c Mon Sep 17 00:00:00 2001
From: Jacob Perron <jacob@openrobotics.org>
Date: Wed, 12 Jun 2019 07:16:28 -0700
Subject: [PATCH] Add function for getting clients by node

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
---
 .../src/rmw_node_info_and_types.cpp           | 13 +++++
 .../src/rmw_node_info_and_types.cpp           | 17 ++++++
 .../rmw_fastrtps_shared_cpp/rmw_common.hpp    | 10 ++++
 .../src/rmw_node_info_and_types.cpp           | 55 ++++++++++++++++++-
 4 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp b/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp
index 7e388ade8..972fc3184 100644
--- a/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp
+++ b/rmw_fastrtps_cpp/src/rmw_node_info_and_types.cpp
@@ -65,4 +65,17 @@ rmw_get_service_names_and_types_by_node(
     eprosima_fastrtps_identifier, node, allocator, node_name, node_namespace,
     service_names_and_types);
 }
+
+rmw_ret_t
+rmw_get_client_names_and_types_by_node(
+  const rmw_node_t * node,
+  rcutils_allocator_t * allocator,
+  const char * node_name,
+  const char * node_namespace,
+  rmw_names_and_types_t * service_names_and_types)
+{
+  return rmw_fastrtps_shared_cpp::__rmw_get_client_names_and_types_by_node(
+    eprosima_fastrtps_identifier, node, allocator, node_name, node_namespace,
+    service_names_and_types);
+}
 }  // extern "C"
diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_node_info_and_types.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_node_info_and_types.cpp
index 2131cc93d..6867628c8 100644
--- a/rmw_fastrtps_dynamic_cpp/src/rmw_node_info_and_types.cpp
+++ b/rmw_fastrtps_dynamic_cpp/src/rmw_node_info_and_types.cpp
@@ -80,4 +80,21 @@ rmw_get_service_names_and_types_by_node(
     node_namespace,
     service_names_and_types);
 }
+
+rmw_ret_t
+rmw_get_client_names_and_types_by_node(
+  const rmw_node_t * node,
+  rcutils_allocator_t * allocator,
+  const char * node_name,
+  const char * node_namespace,
+  rmw_names_and_types_t * service_names_and_types)
+{
+  return rmw_fastrtps_shared_cpp::__rmw_get_client_names_and_types_by_node(
+    eprosima_fastrtps_identifier,
+    node,
+    allocator,
+    node_name,
+    node_namespace,
+    service_names_and_types);
+}
 }  // extern "C"
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 8ffc8cd02..1cd1b669b 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
@@ -226,6 +226,16 @@ __rmw_get_service_names_and_types_by_node(
   const char * node_namespace,
   rmw_names_and_types_t * service_names_and_types);
 
+RMW_FASTRTPS_SHARED_CPP_PUBLIC
+rmw_ret_t
+__rmw_get_client_names_and_types_by_node(
+  const char * identifier,
+  const rmw_node_t * node,
+  rcutils_allocator_t * allocator,
+  const char * node_name,
+  const char * node_namespace,
+  rmw_names_and_types_t * service_names_and_types);
+
 RMW_FASTRTPS_SHARED_CPP_PUBLIC
 rmw_ret_t
 __rmw_get_subscriber_names_and_types_by_node(
diff --git a/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp b/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp
index 7713f3528..ac1d94474 100644
--- a/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp
+++ b/rmw_fastrtps_shared_cpp/src/rmw_node_info_and_types.cpp
@@ -385,15 +385,18 @@ __rmw_get_publisher_names_and_types_by_node(
            node_namespace, no_demangle, retrieve_pub_cache, topic_names_and_types);
 }
 
+static
 rmw_ret_t
-__rmw_get_service_names_and_types_by_node(
+__get_service_names_and_types_by_node(
   const char * identifier,
   const rmw_node_t * node,
   rcutils_allocator_t * allocator,
   const char * node_name,
   const char * node_namespace,
-  rmw_names_and_types_t * service_names_and_types)
+  rmw_names_and_types_t * service_names_and_types,
+  const char * topic_suffix)
 {
+  const std::string topic_suffix_stdstr(topic_suffix);
   rmw_ret_t valid_input = __validate_input(identifier, node, allocator, node_name,
       node_namespace, service_names_and_types);
   if (valid_input != RMW_RET_OK) {
@@ -420,6 +423,15 @@ __rmw_get_service_names_and_types_by_node(
           // not a service
           continue;
         }
+        // Check if the topic suffix matches and is at the end of the name
+        const std::string & topic_name = topic_pair.first;
+        auto suffix_position = topic_name.rfind(topic_suffix_stdstr);
+        if (suffix_position == std::string::npos ||
+          topic_name.length() - suffix_position - topic_suffix_stdstr.length() != 0)
+        {
+          continue;
+        }
+
         for (auto & itt : topic_pair.second) {
           std::string service_type = _demangle_service_type_only(itt);
           if (!service_type.empty()) {
@@ -484,4 +496,43 @@ __rmw_get_service_names_and_types_by_node(
   }      // for each service
   return RMW_RET_OK;
 }
+
+rmw_ret_t
+__rmw_get_service_names_and_types_by_node(
+  const char * identifier,
+  const rmw_node_t * node,
+  rcutils_allocator_t * allocator,
+  const char * node_name,
+  const char * node_namespace,
+  rmw_names_and_types_t * service_names_and_types)
+{
+  return __get_service_names_and_types_by_node(
+    identifier,
+    node,
+    allocator,
+    node_name,
+    node_namespace,
+    service_names_and_types,
+    "Request");
+}
+
+rmw_ret_t
+__rmw_get_client_names_and_types_by_node(
+  const char * identifier,
+  const rmw_node_t * node,
+  rcutils_allocator_t * allocator,
+  const char * node_name,
+  const char * node_namespace,
+  rmw_names_and_types_t * service_names_and_types)
+{
+  return __get_service_names_and_types_by_node(
+    identifier,
+    node,
+    allocator,
+    node_name,
+    node_namespace,
+    service_names_and_types,
+    "Reply");
+}
+
 }  // namespace rmw_fastrtps_shared_cpp