22 #include "rcutils/logging_macros.h"
23 #include "rcutils/stdatomic_helper.h"
24 #include "rcutils/strdup.h"
26 #include "rmw/error_handling.h"
28 #include "tracetools/tracetools.h"
33 #include "rcl/error_handling.h"
39 #include "./arguments_impl.h"
41 #include "./context_impl.h"
42 #include "./init_options_impl.h"
44 static atomic_uint_least64_t __rcl_next_unique_id = ATOMIC_VAR_INIT(1);
49 char const *
const * argv,
57 for (
int i = 0; i < argc; ++i) {
62 RCL_SET_ERROR_MSG(
"argc is <= 0, but argv is not NULL");
72 RCUTILS_LOG_DEBUG_NAMED(
74 "Initializing ROS client library, for context at address: %p", (
void *) context);
77 if (NULL != context->
impl) {
80 RCL_SET_ERROR_MSG(
"rcl_init called on an already initialized context");
90 RCL_CHECK_FOR_NULL_WITH_MSG(
109 if (0 != argc && argv != NULL) {
110 context->
impl->
argv = (
char **)allocator.zero_allocate(argc,
sizeof(
char *), allocator.state);
111 RCL_CHECK_FOR_NULL_WITH_MSG(
113 "failed to allocate memory for argv",
116 for (i = 0; i < argc; ++i) {
117 size_t argv_i_length = strlen(argv[i]) + 1;
118 context->
impl->
argv[i] = (
char *)allocator.allocate(argv_i_length, allocator.state);
119 RCL_CHECK_FOR_NULL_WITH_MSG(
121 "failed to allocate memory for string entry in argv",
123 memcpy(context->
impl->
argv[i], argv[i], argv_i_length);
131 RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME,
"Failed to parse global arguments");
136 uint64_t next_instance_id = rcutils_atomic_fetch_add_uint64_t(&__rcl_next_unique_id, 1);
137 if (0 == next_instance_id) {
139 RCL_SET_ERROR_MSG(
"unique rcl instance ids exhausted");
141 rcutils_atomic_store(&__rcl_next_unique_id, -1);
144 rcutils_atomic_store((atomic_uint_least64_t *)(&context->instance_id_storage), next_instance_id);
157 rmw_localhost_only_t * localhost_only =
159 if (RMW_LOCALHOST_ONLY_DEFAULT != *localhost_only) {
160 RCUTILS_LOG_WARN_NAMED(
162 "'localhost_only' init option is deprecated but still honored if it is enabled. "
163 "Use 'automatic_discovery_range' and 'static_peers' instead.");
171 if (RMW_LOCALHOST_ONLY_DEFAULT != *localhost_only) {
172 RCUTILS_LOG_WARN_NAMED(
174 "ROS_LOCALHOST_ONLY is deprecated but still honored if it is enabled. "
175 "Use ROS_AUTOMATIC_DISCOVERY_RANGE and ROS_STATIC_PEERS instead.");
179 const rmw_discovery_options_t original_discovery_options =
180 options->
impl->rmw_init_options.discovery_options;
181 rmw_discovery_options_t * discovery_options =
188 if (*localhost_only == RMW_LOCALHOST_ONLY_ENABLED) {
189 RCUTILS_LOG_WARN_NAMED(
191 "'localhost_only' is enabled, "
192 "'automatic_discovery_range' and 'static_peers' will be ignored.");
193 discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST;
194 discovery_options->static_peers_count = 0;
196 if (*localhost_only == RMW_LOCALHOST_ONLY_DISABLED) {
197 RCUTILS_LOG_WARN_NAMED(
199 "'localhost_only' is disabled, "
200 "'automatic_discovery_range' and 'static_peers' will be used.");
206 RMW_AUTOMATIC_DISCOVERY_RANGE_NOT_SET == original_discovery_options.automatic_discovery_range)
215 if (0 == discovery_options->static_peers_count &&
216 discovery_options->automatic_discovery_range != RMW_AUTOMATIC_DISCOVERY_RANGE_OFF)
227 if (discovery_options->static_peers_count > 0 &&
228 discovery_options->automatic_discovery_range == RMW_AUTOMATIC_DISCOVERY_RANGE_OFF)
230 RCUTILS_LOG_WARN_NAMED(
232 "Note: ROS_AUTOMATIC_DISCOVERY_RANGE is set to OFF, but "
233 "found static peers in ROS_STATIC_PEERS. "
234 "ROS_STATIC_PEERS will be ignored.");
238 const char * discovery_range_string =
240 if (NULL == discovery_range_string) {
241 discovery_range_string =
"not recognized";
243 RCUTILS_LOG_DEBUG_NAMED(
245 "Automatic discovery range is %s (%d)",
246 discovery_range_string,
247 discovery_options->automatic_discovery_range);
248 RCUTILS_LOG_DEBUG_NAMED(
250 "Static peers count is %lu",
251 discovery_options->static_peers_count);
253 for (
size_t ii = 0; ii < discovery_options->static_peers_count; ++ii) {
254 RCUTILS_LOG_DEBUG_NAMED(
256 "\t%s", discovery_options->static_peers[ii].peer_address);
269 RCL_SET_ERROR_MSG(
"failed to set context name");
274 int validation_result;
275 size_t invalid_index;
281 RCL_SET_ERROR_MSG(
"rcl_validate_enclave_name() failed");
286 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
287 "Enclave name is not valid: '%s'. Invalid index: %zu",
294 rmw_security_options_t * security_options =
306 rmw_ret_t rmw_ret = rmw_init(
309 if (RMW_RET_OK != rmw_ret) {
310 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
311 fail_ret = rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
315 TRACETOOLS_TRACEPOINT(
rcl_init, (
const void *)context);
319 __cleanup_context(context);
326 RCUTILS_LOG_DEBUG_NAMED(
328 "Shutting down ROS client library, for context at address: %p", (
void *) context);
330 RCL_CHECK_FOR_NULL_WITH_MSG(
333 RCL_SET_ERROR_MSG(
"rcl_shutdown already called on the given context");
338 if (RMW_RET_OK != rmw_ret) {
339 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
340 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
344 rcutils_atomic_store((atomic_uint_least64_t *)(&context->instance_id_storage), 0);
#define RCL_CHECK_ALLOCATOR(allocator, fail_statement)
Check that the given allocator is initialized.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_parse_arguments(int argc, const char *const *argv, rcl_allocator_t allocator, rcl_arguments_t *args_output)
Parse command line arguments into a structure usable by code.
RCL_PUBLIC RCL_WARN_UNUSED rcl_arguments_t rcl_get_zero_initialized_arguments(void)
Return a rcl_arguments_t struct with members initialized to NULL.
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_context_is_valid(const rcl_context_t *context)
Return true if the given context is currently valid, otherwise false.
RCL_PUBLIC rcl_ret_t rcl_get_discovery_static_peers(rmw_discovery_options_t *discovery_options, rcutils_allocator_t *allocator)
Determine how the user wishes to discover other ROS nodes via statically-configured peers.
RCL_PUBLIC const char * rcl_automatic_discovery_range_to_string(rmw_automatic_discovery_range_t automatic_discovery_range)
Convert the automatic discovery range value to a string for easy printing.
RCL_PUBLIC rcl_ret_t rcl_get_automatic_discovery_range(rmw_discovery_options_t *discovery_options)
Determine how the user wishes to discover other ROS nodes automatically.
RCL_PUBLIC rcl_ret_t rcl_get_default_domain_id(size_t *domain_id)
Determine the default domain ID, based on the environment.
#define RCL_DEFAULT_DOMAIN_ID
The default domain ID used by RCL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_shutdown(rcl_context_t *context)
Shutdown a given rcl context.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_init(int argc, char const *const *argv, const rcl_init_options_t *options, rcl_context_t *context)
Initialization of rcl.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_init_options_copy(const rcl_init_options_t *src, rcl_init_options_t *dst)
Copy the given source init_options to the destination init_options.
RCL_PUBLIC rcl_ret_t rcl_get_localhost_only(rmw_localhost_only_t *localhost_only)
Determine if the user wants to communicate using loopback only.
RCL_PUBLIC rcl_ret_t rcl_get_security_options_from_environment(const char *name, const rcutils_allocator_t *allocator, rmw_security_options_t *security_options)
Initialize security options from values in the environment variables and given names.
char * enclave
Enclave to be used.
rcl_arguments_impl_t * impl
Private implementation pointer.
char ** argv
Copy of argv used during init (may be NULL).
rmw_context_t rmw_context
rmw context.
int64_t argc
Length of argv (may be 0).
rcl_init_options_t init_options
Copy of init options given during init.
rcl_allocator_t allocator
Allocator used during init and shutdown.
Encapsulates the non-global state of an init/shutdown cycle.
rcl_context_impl_t * impl
Implementation specific pointer.
rcl_arguments_t global_arguments
Global arguments for all nodes which share this context.
Encapsulation of init options and implementation defined init options.
rcl_init_options_impl_t * impl
Implementation specific pointer.
#define RCL_RET_ALREADY_INIT
rcl_init() already called return code.
#define RCL_RET_OK
Success return code.
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
#define RCL_RET_ALREADY_SHUTDOWN
rcl_shutdown() already called return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
#define RCL_ENCLAVE_NAME_VALID
The enclave name is valid.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_validate_enclave_name(const char *enclave, int *validation_result, size_t *invalid_index)
Determine if a given enclave name is valid.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_enclave_name_validation_result_string(int validation_result)
Return a validation result description, or NULL if unknown or RCL_ENCLAVE_NAME_VALID.