Skip to content
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

Handle duplicate node names by including zenoh session id in liveliness tokens #87

Merged
merged 6 commits into from
Jan 2, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Include zenoh session id in liveliness tokens
Signed-off-by: Yadunund <[email protected]>
  • Loading branch information
Yadunund committed Dec 13, 2023
commit eb6e066554e5999c109d038fcba6e03b161eb3db
35 changes: 25 additions & 10 deletions rmw_zenoh_cpp/src/detail/liveliness_utils.cpp
Original file line number Diff line number Diff line change
@@ -83,6 +83,17 @@ static const std::unordered_map<std::string, EntityType> str_to_entity = {
{CLI_STR, EntityType::Client}
};

std::string convert(z_id_t id) {
std::stringstream ss;
ss << std::hex;
size_t i = 0;
for (; i < (sizeof(id.id) - 1); i++) {
ss << static_cast<int>(id.id[i]) << ".";
}
ss << static_cast<int>(id.id[i]) << std::dec;
return ss.str();
}

} // namespace

///=============================================================================
@@ -94,6 +105,7 @@ std::string subscription_token(size_t domain_id)

///=============================================================================
Entity::Entity(
std::string id,
EntityType type,
NodeInfo node_info,
std::optional<TopicInfo> topic_info)
@@ -120,7 +132,7 @@ Entity::Entity(
*/
std::stringstream token_ss;
const std::string & ns = node_info_.ns_;
token_ss << ADMIN_SPACE << "/" << node_info_.domain_id_ << "/" << entity_to_str.at(type_) << ns;
token_ss << ADMIN_SPACE << "/" << node_info_.domain_id_ << "/" << id << "/" << entity_to_str.at(type_) << ns;
// An empty namespace from rcl will contain "/" but zenoh does not allow keys with "//".
// Hence we add an "_" to denote an empty namespace such that splitting the key
// will always result in 5 parts.
@@ -143,6 +155,7 @@ Entity::Entity(

///=============================================================================
std::optional<Entity> Entity::make(
z_id_t id,
EntityType type,
NodeInfo node_info,
std::optional<TopicInfo> topic_info)
@@ -160,7 +173,7 @@ std::optional<Entity> Entity::make(
return std::nullopt;
}

Entity entity{std::move(type), std::move(node_info), std::move(topic_info)};
Entity entity{convert(id), std::move(type), std::move(node_info), std::move(topic_info)};
return entity;
}

@@ -206,7 +219,7 @@ std::optional<Entity> Entity::make(const std::string & keyexpr)
// A token will contain at least 5 parts:
// (ADMIN_SPACE, domain_id, entity_str, namespace, node_name).
// Basic validation.
if (parts.size() < 5) {
if (parts.size() < 6) {
RCUTILS_LOG_ERROR_NAMED(
"rmw_zenoh_cpp",
"Received invalid liveliness token");
@@ -229,7 +242,7 @@ std::optional<Entity> Entity::make(const std::string & keyexpr)
}

// Get the entity, ie NN, MP, MS, SS, SC.
std::string & entity_str = parts[2];
std::string & entity_str = parts[3];
std::unordered_map<std::string, EntityType>::const_iterator entity_it =
str_to_entity.find(entity_str);
if (entity_it == str_to_entity.end()) {
@@ -241,25 +254,27 @@ std::optional<Entity> Entity::make(const std::string & keyexpr)

EntityType entity_type = entity_it->second;
std::size_t domain_id = std::stoul(parts[1]);
std::string ns = parts[3] == "_" ? "/" : "/" + std::move(parts[3]);
std::string node_name = std::move(parts[4]);
std::string& id = parts[2];
std::string ns = parts[4] == "_" ? "/" : "/" + std::move(parts[4]);
std::string node_name = std::move(parts[5]);
std::optional<TopicInfo> topic_info = std::nullopt;

// Populate topic_info if we have a token for an entity other than a node.
if (entity_type != EntityType::Node) {
if (parts.size() < 8) {
if (parts.size() < 9) {
RCUTILS_LOG_ERROR_NAMED(
"rmw_zenoh_cpp",
"Received liveliness token for non-node entity without required parameters.");
return std::nullopt;
}
topic_info = TopicInfo{
"/" + std::move(parts[5]),
std::move(parts[6]),
std::move(parts[7])};
"/" + std::move(parts[6]),
std::move(parts[7]),
std::move(parts[8])};
}

return Entity{
std::move(id),
std::move(entity_type),
NodeInfo{std::move(domain_id), std::move(ns), std::move(node_name), ""},
std::move(topic_info)};
4 changes: 4 additions & 0 deletions rmw_zenoh_cpp/src/detail/liveliness_utils.hpp
Original file line number Diff line number Diff line change
@@ -79,13 +79,16 @@ class Entity
/// fields are not present for the EntityType.
// TODO(Yadunund): Find a way to better bundle the type and the associated data.
static std::optional<Entity> make(
z_id_t id,
EntityType type,
NodeInfo node_info,
std::optional<TopicInfo> topic_info = std::nullopt);

/// Make an Entity from a liveliness keyexpr.
static std::optional<Entity> make(const std::string & keyexpr);

std::string id() const;

/// Get the entity type.
EntityType type() const;

@@ -103,6 +106,7 @@ class Entity

private:
Entity(
std::string id,
EntityType type,
NodeInfo node_info,
std::optional<TopicInfo> topic_info);
3 changes: 3 additions & 0 deletions rmw_zenoh_cpp/src/rmw_zenoh.cpp
Original file line number Diff line number Diff line change
@@ -196,6 +196,7 @@ rmw_create_node(
// Initialize liveliness token for the node to advertise that a new node is in town.
rmw_node_data_t * node_data = static_cast<rmw_node_data_t *>(node->data);
const auto liveliness_entity = liveliness::Entity::make(
z_info_zid(z_loan(context->impl->session)),
liveliness::EntityType::Node,
liveliness::NodeInfo{context->actual_domain_id, namespace_, name, ""});
if (!liveliness_entity.has_value()) {
@@ -578,6 +579,7 @@ rmw_create_publisher(
// return nullptr;
// }
const auto liveliness_entity = liveliness::Entity::make(
z_info_zid(z_loan(node->context->impl->session)),
liveliness::EntityType::Publisher,
liveliness::NodeInfo{node->context->actual_domain_id, node->namespace_, node->name, ""},
liveliness::TopicInfo{rmw_publisher->topic_name,
@@ -1270,6 +1272,7 @@ rmw_create_subscription(

// Publish to the graph that a new subscription is in town
const auto liveliness_entity = liveliness::Entity::make(
z_info_zid(z_loan(node->context->impl->session)),
liveliness::EntityType::Subscription,
liveliness::NodeInfo{node->context->actual_domain_id, node->namespace_, node->name, ""},
liveliness::TopicInfo{rmw_subscription->topic_name,