ROS 2 rclcpp + rcl - rolling  rolling-e7363f10
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 <stdbool.h>
18 #include <stddef.h>
19 
20 #include "rcutils/error_handling.h"
21 #include "rcutils/logging_macros.h"
22 #include "rcutils/types/rcutils_ret.h"
23 #include "rcutils/types/string_map.h"
24 
25 #include "rmw/error_handling.h"
26 #include "rmw/ret_types.h"
27 #include "rmw/validate_full_topic_name.h"
28 
29 #include "rcl/allocator.h"
30 #include "rcl/error_handling.h"
31 #include "rcl/expand_topic_name.h"
32 #include "rcl/remap.h"
33 #include "rcl/types.h"
34 
35 #include "./remap_impl.h"
36 
37 static
39 rcl_resolve_name(
40  const rcl_arguments_t * local_args,
41  const rcl_arguments_t * global_args,
42  const char * input_topic_name,
43  const char * node_name,
44  const char * node_namespace,
45  rcl_allocator_t allocator,
46  bool is_service,
47  bool only_expand,
48  char ** output_topic_name)
49 {
50  // the other arguments are checked by rcl_expand_topic_name() and rcl_remap_name()
51  RCL_CHECK_ARGUMENT_FOR_NULL(output_topic_name, RCL_RET_INVALID_ARGUMENT);
52  // Create default topic name substitutions map
53  rcutils_string_map_t substitutions_map = rcutils_get_zero_initialized_string_map();
54  rcutils_ret_t rcutils_ret = rcutils_string_map_init(&substitutions_map, 0, allocator);
55  if (rcutils_ret != RCUTILS_RET_OK) {
56  rcutils_error_string_t error = rcutils_get_error_string();
57  rcutils_reset_error();
58  RCL_SET_ERROR_MSG(error.str);
59  if (RCUTILS_RET_BAD_ALLOC == rcutils_ret) {
60  return RCL_RET_BAD_ALLOC;
61  }
62  return RCL_RET_ERROR;
63  }
64  char * expanded_topic_name = NULL;
65  char * remapped_topic_name = NULL;
66  rcl_ret_t ret = rcl_get_default_topic_name_substitutions(&substitutions_map);
67  if (ret != RCL_RET_OK) {
68  if (RCL_RET_BAD_ALLOC != ret) {
69  ret = RCL_RET_ERROR;
70  }
71  goto cleanup;
72  }
73  // expand topic name
75  input_topic_name,
76  node_name,
77  node_namespace,
78  &substitutions_map,
79  allocator,
80  &expanded_topic_name);
81  if (RCL_RET_OK != ret) {
82  goto cleanup;
83  }
84  // remap topic name
85  if (!only_expand) {
86  ret = rcl_remap_name(
87  local_args, global_args, is_service ? RCL_SERVICE_REMAP : RCL_TOPIC_REMAP,
88  expanded_topic_name, node_name, node_namespace, &substitutions_map, allocator,
89  &remapped_topic_name);
90  if (RCL_RET_OK != ret) {
91  goto cleanup;
92  }
93  }
94  if (NULL == remapped_topic_name) {
95  remapped_topic_name = expanded_topic_name;
96  expanded_topic_name = NULL;
97  }
98  // validate the result
99  int validation_result;
100  rmw_ret_t rmw_ret = rmw_validate_full_topic_name(remapped_topic_name, &validation_result, NULL);
101  if (rmw_ret != RMW_RET_OK) {
102  rcutils_error_string_t error = rmw_get_error_string();
103  rmw_reset_error();
104  RCL_SET_ERROR_MSG(error.str);
105  ret = RCL_RET_ERROR;
106  goto cleanup;
107  }
108  if (validation_result != RMW_TOPIC_VALID) {
109  RCL_SET_ERROR_MSG(rmw_full_topic_name_validation_result_string(validation_result));
111  goto cleanup;
112  }
113  *output_topic_name = remapped_topic_name;
114  remapped_topic_name = NULL;
115 
116 cleanup:
117  rcutils_ret = rcutils_string_map_fini(&substitutions_map);
118  if (rcutils_ret != RCUTILS_RET_OK) {
119  rcutils_error_string_t error = rcutils_get_error_string();
120  rcutils_reset_error();
121  if (RCL_RET_OK == ret) {
122  RCL_SET_ERROR_MSG(error.str);
123  ret = RCL_RET_ERROR;
124  } else {
125  RCUTILS_LOG_ERROR_NAMED(
126  ROS_PACKAGE_NAME,
127  "failed to fini string_map (%d) during error handling: %s",
128  rcutils_ret,
129  error.str);
130  }
131  }
132  allocator.deallocate(expanded_topic_name, allocator.state);
133  allocator.deallocate(remapped_topic_name, allocator.state);
134  if (is_service && RCL_RET_TOPIC_NAME_INVALID == ret) {
136  }
137  return ret;
138 }
139 
140 rcl_ret_t
142  const rcl_node_t * node,
143  const char * input_topic_name,
144  rcl_allocator_t allocator,
145  bool is_service,
146  bool only_expand,
147  char ** output_topic_name)
148 {
149  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
150  const rcl_node_options_t * node_options = rcl_node_get_options(node);
151  if (NULL == node_options) {
152  return RCL_RET_ERROR;
153  }
154  rcl_arguments_t * global_args = NULL;
155  if (node_options->use_global_arguments) {
156  global_args = &(node->context->global_arguments);
157  }
158 
159  return rcl_resolve_name(
160  &(node_options->arguments),
161  global_args,
162  input_topic_name,
163  rcl_node_get_name(node),
165  allocator,
166  is_service,
167  only_expand,
168  output_topic_name);
169 }
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:447
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:420
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:429
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:120
Structure which encapsulates the options for creating a rcl_node_t.
Definition: node_options.h:41
bool use_global_arguments
If false then only use arguments in this struct, otherwise use global arguments also.
Definition: node_options.h:53
rcl_arguments_t arguments
Command line arguments that apply only to this node.
Definition: node_options.h:56
Structure which encapsulates a ROS Node.
Definition: node.h:49
rcl_context_t * context
Context associated with this node.
Definition: node.h:51
#define RCL_RET_SERVICE_NAME_INVALID
Service name (same as topic name) does not pass validation.
Definition: types.h:50
#define RCL_RET_OK
Success return code.
Definition: types.h:28
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:34
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:36
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:30
#define RCL_RET_TOPIC_NAME_INVALID
Topic name does not pass validation.
Definition: types.h:48
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:25