-
Notifications
You must be signed in to change notification settings - Fork 182
[rcl] Improve handling of dynamic discovery #1023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
1bb953e
Get discovery preferences from the environment
gbiggs 8ecb6b3
Support specification of discovery range and static peers
gbiggs 6d4f0e6
Add some debug helpers
gbiggs f557eea
Cleanup the LOCALHOST_ONLY deprecation a bit.
clalancette 02015ff
Rewrite parsing of static peers.
clalancette 4529112
Fix some silly bugs.
clalancette 8b99c1f
Use names instead of integers for discovery range env vars
mxgrey 0d117f6
Add support for dynamic allocation
arjo129 137ea61
Add a warning if ROS_AUTOMATIC_DISCOVERY_OFF is set and STATIC_PEERS are
arjo129 0bbaabd
Update to latest rmw API
mxgrey 5225a54
Uncrustify
mxgrey f7d4487
Merge branch 'rolling' into gbiggs/discovery-peers-specification
sloretz 7deb711
Update for rmw_discovery_options_t changes
sloretz 911932f
Address feedback: use strncmp
arjo129 df48726
Address feedback: Log levels
arjo129 ac342ad
Address feedback: remove TODO
arjo129 ffd5000
Address feedback: rename function
arjo129 c3f1c77
ddress feedback: Docstring
arjo129 81fa1f0
Address feedback: comment
arjo129 211d4a6
Add `RCL_RET_ERROR` if fini fails.
arjo129 18c8800
`snprintf`->`rcutils_snprintf`
arjo129 185d5ae
Rename tests
arjo129 06efd9d
rcl_get_discovery_automatic_range -> rcl_get_automatic_discovery_rang…
sloretz 1945a0c
Annotate tests
arjo129 4260e6f
More comments
arjo129 d3bb058
Style
arjo129 fe50db2
Style
arjo129 b644644
Uncrustify
arjo129 32e6cce
Constness and warning
arjo129 cd2eeb8
address TODO about IP address validation in the static peers
wjwwood 5b568ca
NOT_SET and SYSTEM_DEFAULT values
sloretz a610f99
refactor discovery options to handle env vars better and simplify str…
wjwwood 4c4248f
fixup docs
wjwwood 12e55f0
(re)improve the discovery range debug message
wjwwood 4101c90
Set discovery options to NOT_SET to detect user changse
sloretz 2cb6d41
lint
sloretz 90ba86d
Merge branch 'rolling' into gbiggs/discovery-peers-specification
sloretz 07ad46f
strncpy_s on windows
sloretz bf024b8
Merge branch 'rolling' into gbiggs/discovery-peers-specification
sloretz ee00c56
Change default range to SUBNET, and allow configuring it at build time
sloretz e5e8877
Merge branch 'rolling' into gbiggs/discovery-peers-specification
sloretz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| // Copyright 2022 Open Source Robotics Foundation, Inc. | ||
| // | ||
| // 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. | ||
|
|
||
| /// @file | ||
|
|
||
| #ifndef RCL__DISCOVERY_OPTIONS_H_ | ||
| #define RCL__DISCOVERY_OPTIONS_H_ | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" | ||
| { | ||
| #endif | ||
|
|
||
| #include "rcl/types.h" | ||
| #include "rcl/visibility_control.h" | ||
|
|
||
| #include "rcutils/allocator.h" | ||
|
|
||
| #include "rmw/discovery_options.h" | ||
|
|
||
| /// Determine how the user wishes to discover other ROS nodes automatically. | ||
| /** | ||
| * Use the ROS_AUTOMATIC_DISCOVERY_RANGE environment variable to determine how | ||
| * far automatic discovery should be allowed to propagate: | ||
| * | ||
| * - not at all (no automatic discovery), | ||
| * - the local machine only, | ||
| * - or the subnet (or as far beyond the local system as the middleware can) | ||
| * | ||
| * When the subnet is specified the automatic discovery mechanism used by the | ||
| * rmw implementation dictates how far discovery can propagate on the network, | ||
| * e.g. for multicast-based discovery this will be the local subnet, hence the | ||
| * name. | ||
| * | ||
| * The option indicated by the environment variable will be stored in the | ||
| * automatic_discovery_range field of the given discovery_options struct. | ||
| * | ||
| * If the environment variable isn't set, then the default discovery range | ||
| * will be the value of the preprocessor definition | ||
| * `RCL_DEFAULT_DISCOVERY_RANGE`. | ||
| * If the definition is undefined, then the default will be SUBNET. | ||
| * It is intended that the default will be LOCALHOST in future versions of ROS. | ||
| * | ||
| * \param[out] discovery_options Must not be NULL. | ||
| * \return #RCL_RET_INVALID_ARGUMENT if an argument is invalid, or | ||
| * \return #RCL_RET_ERROR if an unexpected error happened, or | ||
| * \return #RCL_RET_OK. | ||
| */ | ||
| RCL_PUBLIC | ||
| rcl_ret_t | ||
| rcl_get_automatic_discovery_range(rmw_discovery_options_t * discovery_options); | ||
|
|
||
| /// Convert the automatic discovery range value to a string for easy printing. | ||
| /** | ||
| * \param[in] automatic_discovery_range range enum to stringify | ||
| * \return string version of enum, or NULL if not recognized | ||
| */ | ||
| RCL_PUBLIC | ||
| const char * | ||
| rcl_automatic_discovery_range_to_string(rmw_automatic_discovery_range_t automatic_discovery_range); | ||
|
|
||
| /// Determine how the user wishes to discover other ROS nodes via statically-configured peers. | ||
| /** | ||
| * Use the ROS_STATIC_PEERS environment variable to determine which hosts | ||
| * the user wants to communicate with, in addition to localhost. | ||
| * | ||
| * Values for the static peers are not validated beyond basic string checks, | ||
| * e.g. avoiding empty strings, etc. | ||
| * Any validation of IP addresses or hostnames is left up to the | ||
| * rmw implementation, and therefore what is and is not acceptable in these | ||
| * fields is dependent on it. | ||
| * | ||
| * The general expectation, however, is that IP addresses and hostnames are | ||
| * acceptable. | ||
| * | ||
| * The static peers are split by ';' and returned as a list of fixed length | ||
| * c-strings in the static_peers and static_peers_count fields of the given | ||
| * discovery_options struct. | ||
| * Each peer may only be RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH long, | ||
| * and if it is longer it will be skipped and a warning log message will be | ||
| * produced. | ||
| * | ||
| * \param[out] discovery_options Must not be NULL. | ||
| * \return #RCL_RET_INVALID_ARGUMENT if an argument is invalid, or | ||
| * \return #RCL_RET_ERROR if an unexpected error happened, or | ||
| * \return #RCL_RET_OK. | ||
| */ | ||
| RCL_PUBLIC | ||
| rcl_ret_t | ||
| rcl_get_discovery_static_peers( | ||
| rmw_discovery_options_t * discovery_options, | ||
| rcutils_allocator_t * allocator); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif // RCL__DISCOVERY_OPTIONS_H_ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| // Copyright 2022 Open Source Robotics Foundation, Inc. | ||
| // | ||
| // 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 "rcl/discovery_options.h" | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "rcutils/allocator.h" | ||
| #include "rcutils/env.h" | ||
| #include "rcutils/logging_macros.h" | ||
| #include "rcutils/snprintf.h" | ||
| #include "rcutils/split.h" | ||
| #include "rcutils/types/string_array.h" | ||
|
|
||
| #include "rcl/error_handling.h" | ||
| #include "rcl/types.h" | ||
|
|
||
| #include "rmw/error_handling.h" | ||
|
|
||
| #include "./common.h" | ||
|
|
||
| static const char * const RCL_STATIC_PEERS_ENV_VAR = "ROS_STATIC_PEERS"; | ||
| static const char * const RCL_AUTOMATIC_DISCOVERY_RANGE_ENV_VAR = "ROS_AUTOMATIC_DISCOVERY_RANGE"; | ||
|
|
||
| #define GET_RMW_DISCOVERY_RANGE(x) \ | ||
| _GET_DEFAULT_DISCOVERY_RANGE(x) | ||
| #define _GET_DEFAULT_DISCOVERY_RANGE(x) \ | ||
| RMW_AUTOMATIC_DISCOVERY_RANGE_ ## x | ||
|
|
||
| rcl_ret_t | ||
| rcl_get_automatic_discovery_range(rmw_discovery_options_t * discovery_options) | ||
| { | ||
| const char * ros_automatic_discovery_range_env_val = NULL; | ||
| const char * get_env_error_str = NULL; | ||
|
|
||
| RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT); | ||
| RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(RCL_RET_ERROR); | ||
| RCL_CHECK_ARGUMENT_FOR_NULL(discovery_options, RCL_RET_INVALID_ARGUMENT); | ||
|
|
||
| get_env_error_str = rcutils_get_env( | ||
| RCL_AUTOMATIC_DISCOVERY_RANGE_ENV_VAR, | ||
| &ros_automatic_discovery_range_env_val); | ||
| if (NULL != get_env_error_str) { | ||
| RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( | ||
| "Error getting env var '%s': %s", RCL_AUTOMATIC_DISCOVERY_RANGE_ENV_VAR, | ||
| get_env_error_str); | ||
| return RCL_RET_ERROR; | ||
| } | ||
| if (strcmp(ros_automatic_discovery_range_env_val, "") == 0) { | ||
| #ifdef RCL_DEFAULT_DISCOVERY_RANGE | ||
| discovery_options->automatic_discovery_range = | ||
| GET_RMW_DISCOVERY_RANGE(RCL_DEFAULT_DISCOVERY_RANGE); | ||
| #else | ||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_SUBNET; | ||
| #endif | ||
| } else if (strcmp(ros_automatic_discovery_range_env_val, "OFF") == 0) { | ||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_OFF; | ||
| } else if (strcmp(ros_automatic_discovery_range_env_val, "LOCALHOST") == 0) { | ||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST; | ||
| } else if (strcmp(ros_automatic_discovery_range_env_val, "SUBNET") == 0) { | ||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_SUBNET; | ||
| } else if (strcmp(ros_automatic_discovery_range_env_val, "SYSTEM_DEFAULT") == 0) { | ||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_SYSTEM_DEFAULT; | ||
| } else { | ||
| RCUTILS_LOG_WARN_NAMED( | ||
| ROS_PACKAGE_NAME, | ||
| "Invalid value '%s' specified for '%s', assuming localhost only", | ||
| ros_automatic_discovery_range_env_val, | ||
| RCL_AUTOMATIC_DISCOVERY_RANGE_ENV_VAR); | ||
|
|
||
| discovery_options->automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST; | ||
| } | ||
|
|
||
| return RCL_RET_OK; | ||
| } | ||
|
|
||
| RCL_PUBLIC | ||
| const char * | ||
| rcl_automatic_discovery_range_to_string(rmw_automatic_discovery_range_t automatic_discovery_range) | ||
| { | ||
| switch (automatic_discovery_range) { | ||
| case RMW_AUTOMATIC_DISCOVERY_RANGE_NOT_SET: | ||
| return "RMW_AUTOMATIC_DISCOVERY_RANGE_NOT_SET"; | ||
| case RMW_AUTOMATIC_DISCOVERY_RANGE_OFF: | ||
| return "RMW_AUTOMATIC_DISCOVERY_RANGE_OFF"; | ||
| case RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST: | ||
| return "RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST"; | ||
| case RMW_AUTOMATIC_DISCOVERY_RANGE_SUBNET: | ||
| return "RMW_AUTOMATIC_DISCOVERY_RANGE_SUBNET"; | ||
| case RMW_AUTOMATIC_DISCOVERY_RANGE_SYSTEM_DEFAULT: | ||
| return "RMW_AUTOMATIC_DISCOVERY_RANGE_SYSTEM_DEFAULT"; | ||
| default: | ||
| return NULL; | ||
| } | ||
| } | ||
|
|
||
| rcl_ret_t | ||
| rcl_get_discovery_static_peers( | ||
| rmw_discovery_options_t * discovery_options, | ||
| rcutils_allocator_t * allocator) | ||
| { | ||
| const char * ros_peers_env_val = NULL; | ||
| const char * get_env_error_str = NULL; | ||
|
|
||
| RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT); | ||
| RCUTILS_CAN_SET_MSG_AND_RETURN_WITH_ERROR_OF(RCL_RET_ERROR); | ||
| RCL_CHECK_ARGUMENT_FOR_NULL(discovery_options, RCL_RET_INVALID_ARGUMENT); | ||
| RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT); | ||
|
|
||
| get_env_error_str = rcutils_get_env(RCL_STATIC_PEERS_ENV_VAR, &ros_peers_env_val); | ||
| if (NULL != get_env_error_str) { | ||
| RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( | ||
| "Error getting environment variable '%s': %s", | ||
| RCL_STATIC_PEERS_ENV_VAR, get_env_error_str); | ||
| return RCL_RET_ERROR; | ||
| } | ||
|
|
||
| // The value of the env var should be at least "", even when not set. | ||
| if (NULL == ros_peers_env_val) { | ||
| RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( | ||
| "Environment variable value unexpectedly NULL when checking '%s'", | ||
| RCL_STATIC_PEERS_ENV_VAR); | ||
| return RCL_RET_ERROR; | ||
| } | ||
|
|
||
| rcutils_string_array_t array = rcutils_get_zero_initialized_string_array(); | ||
| rcutils_ret_t split_ret = rcutils_split(ros_peers_env_val, ';', *allocator, &array); | ||
| if (RCUTILS_RET_OK != split_ret) { | ||
| RCL_SET_ERROR_MSG(rcutils_get_error_string().str); | ||
| return RCL_RET_ERROR; | ||
| } | ||
|
|
||
| rmw_ret_t rmw_ret = rmw_discovery_options_init(discovery_options, array.size, allocator); | ||
| if (RMW_RET_OK != rmw_ret) { | ||
| RCL_SET_ERROR_MSG(rmw_get_error_string().str); | ||
| return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret); | ||
| } | ||
|
|
||
| for (size_t i = 0; i < array.size; ++i) { | ||
| if (strlen(array.data[i]) > (RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH - 1)) { | ||
| RCUTILS_LOG_WARN_NAMED( | ||
| ROS_PACKAGE_NAME, | ||
| "Static peer %s specified to '%s' is too long (maximum of %d); skipping", | ||
| array.data[i], RCL_STATIC_PEERS_ENV_VAR, | ||
| RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH - 1); | ||
| continue; | ||
| } | ||
| #ifdef _WIN32 | ||
| strncpy_s( | ||
| discovery_options->static_peers[i].peer_address, | ||
| RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH, | ||
| array.data[i], | ||
| RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH); | ||
| #else | ||
| strncpy( | ||
| discovery_options->static_peers[i].peer_address, | ||
| array.data[i], | ||
| RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH); | ||
| discovery_options->static_peers[i].peer_address[ | ||
| RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH - 1] = '\0'; | ||
| #endif | ||
| } | ||
|
|
||
| if (RCUTILS_RET_OK != rcutils_string_array_fini(&array)) { | ||
| RCL_SET_ERROR_MSG(rcutils_get_error_string().str); | ||
| return RCL_RET_ERROR; | ||
| } | ||
|
|
||
| return RCL_RET_OK; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.