ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
node_resolve_name.c
1 // Copyright 2020 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "rcl/node.h"
16 
17 #include "rcutils/error_handling.h"
18 #include "rcutils/logging_macros.h"
19 #include "rcutils/types/string_map.h"
20 
21 #include "rmw/error_handling.h"
22 #include "rmw/validate_full_topic_name.h"
23 
24 #include "rcl/error_handling.h"
25 #include "rcl/expand_topic_name.h"
26 #include "rcl/remap.h"
27 
28 #include "./remap_impl.h"
29 
30 static
32 rcl_resolve_name(
33  const rcl_arguments_t * local_args,
34  const rcl_arguments_t * global_args,
35  const char * input_topic_name,
36  const char * node_name,
37  const char * node_namespace,
38  rcl_allocator_t allocator,
39  bool is_service,
40  bool only_expand,
41  char ** output_topic_name)
42 {
43  // the other arguments are checked by rcl_expand_topic_name() and rcl_remap_name()
44  RCL_CHECK_ARGUMENT_FOR_NULL(output_topic_name, RCL_RET_INVALID_ARGUMENT);
45  // Create default topic name substitutions map
46  rcutils_string_map_t substitutions_map = rcutils_get_zero_initialized_string_map();
47  rcutils_ret_t rcutils_ret = rcutils_string_map_init(&substitutions_map, 0, allocator);
48  if (rcutils_ret != RCUTILS_RET_OK) {
49  rcutils_error_string_t error = rcutils_get_error_string();
50  rcutils_reset_error();
51  RCL_SET_ERROR_MSG(error.str);
52  if (RCUTILS_RET_BAD_ALLOC == rcutils_ret) {
53  return RCL_RET_BAD_ALLOC;
54  }
55  return RCL_RET_ERROR;
56  }
57  char * expanded_topic_name = NULL;
58  char * remapped_topic_name = NULL;
59  rcl_ret_t ret = rcl_get_default_topic_name_substitutions(&substitutions_map);
60  if (ret != RCL_RET_OK) {
61  if (RCL_RET_BAD_ALLOC != ret) {
62  ret = RCL_RET_ERROR;
63  }
64  goto cleanup;
65  }
66  // expand topic name
68  input_topic_name,
69  node_name,
70  node_namespace,
71  &substitutions_map,
72  allocator,
73  &expanded_topic_name);
74  if (RCL_RET_OK != ret) {
75  goto cleanup;
76  }
77  // remap topic name
78  if (!only_expand) {
79  ret = rcl_remap_name(
80  local_args, global_args, is_service ? RCL_SERVICE_REMAP : RCL_TOPIC_REMAP,
81  expanded_topic_name, node_name, node_namespace, &substitutions_map, allocator,
82  &remapped_topic_name);
83  if (RCL_RET_OK != ret) {
84  goto cleanup;
85  }
86  }
87  if (NULL == remapped_topic_name) {
88  remapped_topic_name = expanded_topic_name;
89  expanded_topic_name = NULL;
90  }
91  // validate the result
92  int validation_result;
93  rmw_ret_t rmw_ret = rmw_validate_full_topic_name(remapped_topic_name, &validation_result, NULL);
94  if (rmw_ret != RMW_RET_OK) {
95  rcutils_error_string_t error = rmw_get_error_string();
96  rmw_reset_error();
97  RCL_SET_ERROR_MSG(error.str);
98  ret = RCL_RET_ERROR;
99  goto cleanup;
100  }
101  if (validation_result != RMW_TOPIC_VALID) {
102  RCL_SET_ERROR_MSG(rmw_full_topic_name_validation_result_string(validation_result));
104  goto cleanup;
105  }
106  *output_topic_name = remapped_topic_name;
107  remapped_topic_name = NULL;
108 
109 cleanup:
110  rcutils_ret = rcutils_string_map_fini(&substitutions_map);
111  if (rcutils_ret != RCUTILS_RET_OK) {
112  rcutils_error_string_t error = rcutils_get_error_string();
113  rcutils_reset_error();
114  if (RCL_RET_OK == ret) {
115  RCL_SET_ERROR_MSG(error.str);
116  ret = RCL_RET_ERROR;
117  } else {
118  RCUTILS_LOG_ERROR_NAMED(
119  ROS_PACKAGE_NAME,
120  "failed to fini string_map (%d) during error handling: %s",
121  rcutils_ret,
122  error.str);
123  }
124  }
125  allocator.deallocate(expanded_topic_name, allocator.state);
126  allocator.deallocate(remapped_topic_name, allocator.state);
127  if (is_service && RCL_RET_TOPIC_NAME_INVALID == ret) {
129  }
130  return ret;
131 }
132 
133 rcl_ret_t
135  const rcl_node_t * node,
136  const char * input_topic_name,
137  rcl_allocator_t allocator,
138  bool is_service,
139  bool only_expand,
140  char ** output_topic_name)
141 {
142  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
143  const rcl_node_options_t * node_options = rcl_node_get_options(node);
144  if (NULL == node_options) {
145  return RCL_RET_ERROR;
146  }
147  rcl_arguments_t * global_args = NULL;
148  if (node_options->use_global_arguments) {
149  global_args = &(node->context->global_arguments);
150  }
151 
152  return rcl_resolve_name(
153  &(node_options->arguments),
154  global_args,
155  input_topic_name,
156  rcl_node_get_name(node),
158  allocator,
159  is_service,
160  only_expand,
161  output_topic_name);
162 }
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_expand_topic_name(const char *input_topic_name, const char *node_name, const char *node_namespace, const rcutils_string_map_t *substitutions, rcl_allocator_t allocator, char **output_topic_name)
Expand a given topic name into a fully-qualified topic name.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_default_topic_name_substitutions(rcutils_string_map_t *string_map)
Fill a given string map with the default substitution pairs.
RCL_PUBLIC RCL_WARN_UNUSED const rcl_node_options_t * rcl_node_get_options(const rcl_node_t *node)
Return the rcl node options.
Definition: node.c:462
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_name(const rcl_node_t *node)
Return the name of the node.
Definition: node.c:435
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_namespace(const rcl_node_t *node)
Return the namespace of the node.
Definition: node.c:444
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_resolve_name(const rcl_node_t *node, const char *input_name, rcl_allocator_t allocator, bool is_service, bool only_expand, char **output_name)
Expand a given name into a fully-qualified topic name and apply remapping rules.
Hold output of parsing command line arguments.
Definition: arguments.h:36
rcl_arguments_t global_arguments
Global arguments for all nodes which share this context.
Definition: context.h:117
Structure which encapsulates the options for creating a rcl_node_t.
Definition: node_options.h:35
bool use_global_arguments
If false then only use arguments in this struct, otherwise use global arguments also.
Definition: node_options.h:47
rcl_arguments_t arguments
Command line arguments that apply only to this node.
Definition: node_options.h:50
Structure which encapsulates a ROS Node.
Definition: node.h:42
rcl_context_t * context
Context associated with this node.
Definition: node.h:44
#define RCL_RET_SERVICE_NAME_INVALID
Service name (same as topic name) does not pass validation.
Definition: types.h:48
#define RCL_RET_OK
Success return code.
Definition: types.h:26
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:32
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:34
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:28
#define RCL_RET_TOPIC_NAME_INVALID
Topic name does not pass validation.
Definition: types.h:46
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:23