diff --git a/include/gz/transport/HandlerStorage.hh b/include/gz/transport/HandlerStorage.hh index 37d3f9f7f..3775fafaf 100644 --- a/include/gz/transport/HandlerStorage.hh +++ b/include/gz/transport/HandlerStorage.hh @@ -26,244 +26,241 @@ #include "gz/transport/config.hh" #include "gz/transport/TransportTypes.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class HandlerStorage HandlerStorage.hh + /// gz/transport/HandlerStorage.hh + /// \brief Class to store and manage service call handlers. + template class HandlerStorage { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class HandlerStorage HandlerStorage.hh - /// gz/transport/HandlerStorage.hh - /// \brief Class to store and manage service call handlers. - template class HandlerStorage - { - /// \brief Stores all the service call data for each topic. The key of - /// _data is the topic name. The value is another map, where the key is - /// the node UUID and the value is a smart pointer to the handler. - /// \TODO(Carlos) review this names and fix them - using UUIDHandler_M = std::map>; - using UUIDHandler_Collection_M = std::map; + /// \brief Stores all the service call data for each topic. The key of + /// _data is the topic name. The value is another map, where the key is + /// the node UUID and the value is a smart pointer to the handler. + /// \TODO(Carlos) review this names and fix them + using UUIDHandler_M = std::map>; + using UUIDHandler_Collection_M = std::map; - /// \brief key is a topic name and value is UUIDHandler_Collection_M - using TopicServiceCalls_M = - std::map; + /// \brief key is a topic name and value is UUIDHandler_Collection_M + using TopicServiceCalls_M = + std::map; - /// \brief Constructor. - public: HandlerStorage() = default; + /// \brief Constructor. + public: HandlerStorage() = default; - /// \brief Destructor. - public: virtual ~HandlerStorage() = default; + /// \brief Destructor. + public: virtual ~HandlerStorage() = default; - /// \brief Get the data handlers for a topic. A request - /// handler stores the callback and types associated to a service call - /// request. - /// \param[in] _topic Topic name. - /// \param[out] _handlers Request handlers. The key of _handlers is the - /// topic name. The value is another map, where the key is the node - /// UUID and the value is a smart pointer to the handler. - /// \return true if the topic contains at least one request. - public: bool Handlers(const std::string &_topic, - std::map >> &_handlers) const - { - if (this->data.find(_topic) == this->data.end()) - return false; + /// \brief Get the data handlers for a topic. A request + /// handler stores the callback and types associated to a service call + /// request. + /// \param[in] _topic Topic name. + /// \param[out] _handlers Request handlers. The key of _handlers is the + /// topic name. The value is another map, where the key is the node + /// UUID and the value is a smart pointer to the handler. + /// \return true if the topic contains at least one request. + public: bool Handlers(const std::string &_topic, + std::map >> &_handlers) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - _handlers = this->data.at(_topic); - return true; - } + _handlers = this->data.at(_topic); + return true; + } - /// \brief Get the first handler for a topic that matches a specific pair - /// of request/response types. - /// \param[in] _topic Topic name. - /// \param[in] _reqTypeName Type of the service request. - /// \param[in] _repTypeName Type of the service response. - /// \param[out] _handler handler. - /// \return true if a handler was found. - public: bool FirstHandler(const std::string &_topic, - const std::string &_reqTypeName, - const std::string &_repTypeName, - std::shared_ptr &_handler) const - { - if (this->data.find(_topic) == this->data.end()) - return false; + /// \brief Get the first handler for a topic that matches a specific pair + /// of request/response types. + /// \param[in] _topic Topic name. + /// \param[in] _reqTypeName Type of the service request. + /// \param[in] _repTypeName Type of the service response. + /// \param[out] _handler handler. + /// \return true if a handler was found. + public: bool FirstHandler(const std::string &_topic, + const std::string &_reqTypeName, + const std::string &_repTypeName, + std::shared_ptr &_handler) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - const auto &m = this->data.at(_topic); - for (const auto &node : m) + const auto &m = this->data.at(_topic); + for (const auto &node : m) + { + for (const auto &handler : node.second) { - for (const auto &handler : node.second) + if (_reqTypeName == handler.second->ReqTypeName() && + _repTypeName == handler.second->RepTypeName()) { - if (_reqTypeName == handler.second->ReqTypeName() && - _repTypeName == handler.second->RepTypeName()) - { - _handler = handler.second; - return true; - } + _handler = handler.second; + return true; } } - return false; } + return false; + } - /// \brief Get the first handler for a topic that matches a specific - /// message type. - /// \param[in] _topic Topic name. - /// \param[in] _msgTypeName Type of the msg in string format. - /// \param[out] _handler handler. - /// \return true if a handler was found. - public: bool FirstHandler(const std::string &_topic, - const std::string &_msgTypeName, - std::shared_ptr &_handler) const - { - if (this->data.find(_topic) == this->data.end()) - return false; + /// \brief Get the first handler for a topic that matches a specific + /// message type. + /// \param[in] _topic Topic name. + /// \param[in] _msgTypeName Type of the msg in string format. + /// \param[out] _handler handler. + /// \return true if a handler was found. + public: bool FirstHandler(const std::string &_topic, + const std::string &_msgTypeName, + std::shared_ptr &_handler) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - const auto &m = this->data.at(_topic); - for (const auto &node : m) + const auto &m = this->data.at(_topic); + for (const auto &node : m) + { + for (const auto &handler : node.second) { - for (const auto &handler : node.second) + if (_msgTypeName == handler.second->TypeName() || + handler.second->TypeName() == kGenericMessageType) { - if (_msgTypeName == handler.second->TypeName() || - handler.second->TypeName() == kGenericMessageType) - { - _handler = handler.second; - return true; - } + _handler = handler.second; + return true; } } - return false; } + return false; + } - /// \brief Get a specific handler. - /// \param[in] _topic Topic name. - /// \param[in] _nUuid Node UUID of the handler. - /// \param[in] _hUuid Handler UUID. - /// \param[out] _handler Handler requested. - /// \return true if the handler was found. - public: bool Handler(const std::string &_topic, - const std::string &_nUuid, - const std::string &_hUuid, - std::shared_ptr &_handler) const - { - if (this->data.find(_topic) == this->data.end()) - return false; - - auto const &m = this->data.at(_topic); - if (m.find(_nUuid) == m.end()) - return false; - - if (m.at(_nUuid).find(_hUuid) == m.at(_nUuid).end()) - return false; + /// \brief Get a specific handler. + /// \param[in] _topic Topic name. + /// \param[in] _nUuid Node UUID of the handler. + /// \param[in] _hUuid Handler UUID. + /// \param[out] _handler Handler requested. + /// \return true if the handler was found. + public: bool Handler(const std::string &_topic, + const std::string &_nUuid, + const std::string &_hUuid, + std::shared_ptr &_handler) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - _handler = m.at(_nUuid).at(_hUuid); - return true; - } + auto const &m = this->data.at(_topic); + if (m.find(_nUuid) == m.end()) + return false; - /// \brief Get a reference to all the handlers. - /// \return All the handlers. - public: TopicServiceCalls_M &AllHandlers() - { - return this->data; - } + if (m.at(_nUuid).find(_hUuid) == m.at(_nUuid).end()) + return false; - /// \brief Add a request handler to a topic. A request handler stores - /// the callback and types associated to a service call request. - /// \param[in] _topic Topic name. - /// \param[in] _nUuid Node's unique identifier. - /// \param[in] _handler Request handler. - public: void AddHandler(const std::string &_topic, - const std::string &_nUuid, - const std::shared_ptr &_handler) - { - // Create the topic entry. - if (this->data.find(_topic) == this->data.end()) - this->data[_topic] = UUIDHandler_Collection_M(); + _handler = m.at(_nUuid).at(_hUuid); + return true; + } - // Create the Node UUID entry. - if (this->data[_topic].find(_nUuid) == this->data[_topic].end()) - this->data[_topic][_nUuid] = UUIDHandler_M(); + /// \brief Get a reference to all the handlers. + /// \return All the handlers. + public: TopicServiceCalls_M &AllHandlers() + { + return this->data; + } - // Add/Replace the Req handler. - this->data[_topic][_nUuid].insert( - std::make_pair(_handler->HandlerUuid(), _handler)); - } + /// \brief Add a request handler to a topic. A request handler stores + /// the callback and types associated to a service call request. + /// \param[in] _topic Topic name. + /// \param[in] _nUuid Node's unique identifier. + /// \param[in] _handler Request handler. + public: void AddHandler(const std::string &_topic, + const std::string &_nUuid, + const std::shared_ptr &_handler) + { + // Create the topic entry. + if (this->data.find(_topic) == this->data.end()) + this->data[_topic] = UUIDHandler_Collection_M(); - /// \brief Return true if we have stored at least one request for the - /// topic. - /// \param[in] _topic Topic name. - /// \return true if we have stored at least one request for the topic. - public: bool HasHandlersForTopic(const std::string &_topic) const - { - if (this->data.find(_topic) == this->data.end()) - return false; + // Create the Node UUID entry. + if (this->data[_topic].find(_nUuid) == this->data[_topic].end()) + this->data[_topic][_nUuid] = UUIDHandler_M(); - return !this->data.at(_topic).empty(); - } + // Add/Replace the Req handler. + this->data[_topic][_nUuid].insert( + std::make_pair(_handler->HandlerUuid(), _handler)); + } - /// \brief Check if a node has at least one handler. - /// \param[in] _topic Topic name. - /// \param[in] _nUuid Node's unique identifier. - /// \return true if the node has at least one handler registered. - public: bool HasHandlersForNode(const std::string &_topic, - const std::string &_nUuid) const - { - if (this->data.find(_topic) == this->data.end()) - return false; + /// \brief Return true if we have stored at least one request for the + /// topic. + /// \param[in] _topic Topic name. + /// \return true if we have stored at least one request for the topic. + public: bool HasHandlersForTopic(const std::string &_topic) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - return this->data.at(_topic).find(_nUuid) != - this->data.at(_topic).end(); - } + return !this->data.at(_topic).empty(); + } - /// \brief Remove a request handler. The node's uuid is used as a key to - /// remove the appropriate request handler. - /// \param[in] _topic Topic name. - /// \param[in] _nUuid Node's unique identifier. - /// \param[in] _reqUuid Request's UUID to remove. - /// \return True when the handler is removed or false otherwise. - public: bool RemoveHandler(const std::string &_topic, - const std::string &_nUuid, - const std::string &_reqUuid) - { - size_t counter = 0; - if (this->data.find(_topic) != this->data.end()) - { - if (this->data[_topic].find(_nUuid) != this->data[_topic].end()) - { - counter = this->data[_topic][_nUuid].erase(_reqUuid); - if (this->data[_topic][_nUuid].empty()) - this->data[_topic].erase(_nUuid); - if (this->data[_topic].empty()) - this->data.erase(_topic); - } - } + /// \brief Check if a node has at least one handler. + /// \param[in] _topic Topic name. + /// \param[in] _nUuid Node's unique identifier. + /// \return true if the node has at least one handler registered. + public: bool HasHandlersForNode(const std::string &_topic, + const std::string &_nUuid) const + { + if (this->data.find(_topic) == this->data.end()) + return false; - return counter > 0; - } + return this->data.at(_topic).find(_nUuid) != + this->data.at(_topic).end(); + } - /// \brief Remove all the handlers from a given node. - /// \param[in] _topic Topic name. - /// \param[in] _nUuid Node's unique identifier. - /// \return True when at least one handler was removed or false otherwise. - public: bool RemoveHandlersForNode(const std::string &_topic, - const std::string &_nUuid) + /// \brief Remove a request handler. The node's uuid is used as a key to + /// remove the appropriate request handler. + /// \param[in] _topic Topic name. + /// \param[in] _nUuid Node's unique identifier. + /// \param[in] _reqUuid Request's UUID to remove. + /// \return True when the handler is removed or false otherwise. + public: bool RemoveHandler(const std::string &_topic, + const std::string &_nUuid, + const std::string &_reqUuid) + { + size_t counter = 0; + if (this->data.find(_topic) != this->data.end()) { - size_t counter = 0; - if (this->data.find(_topic) != this->data.end()) + if (this->data[_topic].find(_nUuid) != this->data[_topic].end()) { - counter = this->data[_topic].erase(_nUuid); + counter = this->data[_topic][_nUuid].erase(_reqUuid); + if (this->data[_topic][_nUuid].empty()) + this->data[_topic].erase(_nUuid); if (this->data[_topic].empty()) this->data.erase(_topic); } + } + + return counter > 0; + } - return counter > 0; + /// \brief Remove all the handlers from a given node. + /// \param[in] _topic Topic name. + /// \param[in] _nUuid Node's unique identifier. + /// \return True when at least one handler was removed or false otherwise. + public: bool RemoveHandlersForNode(const std::string &_topic, + const std::string &_nUuid) + { + size_t counter = 0; + if (this->data.find(_topic) != this->data.end()) + { + counter = this->data[_topic].erase(_nUuid); + if (this->data[_topic].empty()) + this->data.erase(_topic); } - /// \brief Stores all the service call data for each topic. The key of - /// _data is the topic name. The value is another map, where the key is - /// the node UUID and the value is a smart pointer to the handler. - private: TopicServiceCalls_M data; - }; + return counter > 0; } + + /// \brief Stores all the service call data for each topic. The key of + /// _data is the topic name. The value is another map, where the key is + /// the node UUID and the value is a smart pointer to the handler. + private: TopicServiceCalls_M data; + }; } } diff --git a/include/gz/transport/Helpers.hh b/include/gz/transport/Helpers.hh index feff06b19..d7e6fdf0f 100644 --- a/include/gz/transport/Helpers.hh +++ b/include/gz/transport/Helpers.hh @@ -43,48 +43,45 @@ #endif #endif -namespace gz +namespace gz::transport { - namespace transport - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \brief Constant used when not interested in throttling. - static const uint64_t kUnthrottled = std::numeric_limits::max(); + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \brief Constant used when not interested in throttling. + static const uint64_t kUnthrottled = std::numeric_limits::max(); - /// \brief Find the environment variable '_name' and return its value. - /// \param[in] _name Name of the environment variable. - /// \param[out] _value Value if the variable was found. - /// \return True if the variable was found or false otherwise. - bool GZ_TRANSPORT_VISIBLE env(const std::string &_name, - std::string &_value); + /// \brief Find the environment variable '_name' and return its value. + /// \param[in] _name Name of the environment variable. + /// \param[out] _value Value if the variable was found. + /// \return True if the variable was found or false otherwise. + bool GZ_TRANSPORT_VISIBLE env(const std::string &_name, + std::string &_value); - /// \brief split at a one character delimiter to get a vector of something - /// \param[in] _orig The string to split - /// \param[in] _delim a character to split the string at - /// \returns vector of split pieces of the string excluding the delimiter - std::vector GZ_TRANSPORT_VISIBLE split( - const std::string &_orig, - char _delim); + /// \brief split at a one character delimiter to get a vector of something + /// \param[in] _orig The string to split + /// \param[in] _delim a character to split the string at + /// \returns vector of split pieces of the string excluding the delimiter + std::vector GZ_TRANSPORT_VISIBLE split( + const std::string &_orig, + char _delim); - /// \brief Portable function to get the id of the current process. - /// \returns id of current process - unsigned int GZ_TRANSPORT_VISIBLE getProcessId(); + /// \brief Portable function to get the id of the current process. + /// \returns id of current process + unsigned int GZ_TRANSPORT_VISIBLE getProcessId(); - // Use safer functions on Windows - #ifdef _MSC_VER - #define gz_strcat strcat_s - #define gz_strcpy strcpy_s - #define gz_sprintf sprintf_s - #define gz_strdup _strdup - #else - #define gz_strcat std::strcat - #define gz_strcpy std::strcpy - #define gz_sprintf std::sprintf - #define gz_strdup strdup - #endif - } + // Use safer functions on Windows + #ifdef _MSC_VER + #define gz_strcat strcat_s + #define gz_strcpy strcpy_s + #define gz_sprintf sprintf_s + #define gz_strdup _strdup + #else + #define gz_strcat std::strcat + #define gz_strcpy std::strcpy + #define gz_sprintf std::sprintf + #define gz_strdup strdup + #endif } } diff --git a/include/gz/transport/MessageInfo.hh b/include/gz/transport/MessageInfo.hh index 3458ba59a..84f60d747 100644 --- a/include/gz/transport/MessageInfo.hh +++ b/include/gz/transport/MessageInfo.hh @@ -24,70 +24,68 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + class MessageInfoPrivate; + + /// \brief A class that provides information about the message received. + class GZ_TRANSPORT_VISIBLE MessageInfo { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - class MessageInfoPrivate; - - /// \brief A class that provides information about the message received. - class GZ_TRANSPORT_VISIBLE MessageInfo - { - /// \brief Default constructor. - public: MessageInfo(); - - /// \brief Explicit copy constructor (The copy constructor is deleted by - /// default due to the use of std::unique_ptr member). - /// \param[in] _other an instance to copy data from - public: MessageInfo(const MessageInfo &_other); - - /// \brief Move constructor - /// \param[in] _other an instance data is moved from - public: MessageInfo(MessageInfo &&_other); // NOLINT - - /// \brief Destructor. - public: ~MessageInfo(); - - /// \brief Get the topic name associated to the message. - /// \return The topic name. - public: const std::string &Topic() const; - - /// \brief Set the topic name associated to the message. - public: void SetTopic(const std::string &_topic); - - /// \brief Get the name of the message type. - /// \return The message type name. - public: const std::string &Type() const; - - /// \brief Set the name of the message type. - /// \param[in] _type the type name to set. - public: void SetType(const std::string &_type); - - /// \brief Get the name of the partition. - /// \return The partition name. - public: const std::string &Partition() const; - - /// \brief Set the partition of the topic the message was on. - /// \param[in] _partition of the topic. - public: void SetPartition(const std::string &_partition); - - /// \brief Set both the topic and the partition from a single string. - /// \param[in] _fullyQualifiedName The topic string with the partition - /// information included. - /// \return true if the topic and partition were set - /// \sa TopicUtils::FullyQualifiedName - public: bool SetTopicAndPartition(const std::string &_fullyQualifiedName); - - /// \brief Whether the message is coming from a node within this process. - /// \return True when intra-process, false otherwise. - public: bool IntraProcess() const; - - /// \brief Set whether this message is intra-process or not. - /// \param[in] _value The intra-process value. - public: void SetIntraProcess(bool _value); + /// \brief Default constructor. + public: MessageInfo(); + + /// \brief Explicit copy constructor (The copy constructor is deleted by + /// default due to the use of std::unique_ptr member). + /// \param[in] _other an instance to copy data from + public: MessageInfo(const MessageInfo &_other); + + /// \brief Move constructor + /// \param[in] _other an instance data is moved from + public: MessageInfo(MessageInfo &&_other); // NOLINT + + /// \brief Destructor. + public: ~MessageInfo(); + + /// \brief Get the topic name associated to the message. + /// \return The topic name. + public: const std::string &Topic() const; + + /// \brief Set the topic name associated to the message. + public: void SetTopic(const std::string &_topic); + + /// \brief Get the name of the message type. + /// \return The message type name. + public: const std::string &Type() const; + + /// \brief Set the name of the message type. + /// \param[in] _type the type name to set. + public: void SetType(const std::string &_type); + + /// \brief Get the name of the partition. + /// \return The partition name. + public: const std::string &Partition() const; + + /// \brief Set the partition of the topic the message was on. + /// \param[in] _partition of the topic. + public: void SetPartition(const std::string &_partition); + + /// \brief Set both the topic and the partition from a single string. + /// \param[in] _fullyQualifiedName The topic string with the partition + /// information included. + /// \return true if the topic and partition were set + /// \sa TopicUtils::FullyQualifiedName + public: bool SetTopicAndPartition(const std::string &_fullyQualifiedName); + + /// \brief Whether the message is coming from a node within this process. + /// \return True when intra-process, false otherwise. + public: bool IntraProcess() const; + + /// \brief Set whether this message is intra-process or not. + /// \param[in] _value The intra-process value. + public: void SetIntraProcess(bool _value); #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -95,14 +93,13 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \internal - /// \brief Pointer to private data. - protected: std::unique_ptr dataPtr; + /// \internal + /// \brief Pointer to private data. + protected: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } #endif diff --git a/include/gz/transport/NetUtils.hh b/include/gz/transport/NetUtils.hh index 7dbd70d69..82e5bfa4c 100644 --- a/include/gz/transport/NetUtils.hh +++ b/include/gz/transport/NetUtils.hh @@ -24,49 +24,46 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \brief Determine if an IP is private. - /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ - /// roscpp/src/libros/network.cpp - /// \param[in] _ip Input IP address. - /// \return true if the IP address is private. - bool isPrivateIP(const char *_ip); + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \brief Determine if an IP is private. + /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ + /// roscpp/src/libros/network.cpp + /// \param[in] _ip Input IP address. + /// \return true if the IP address is private. + bool isPrivateIP(const char *_ip); - /// \brief Determine if an IP is private. - /// \param[in] _hostname Hostname - /// \param[out] _ip IP associated to the input hostname. - /// \return 0 when success. - int hostnameToIp(char *_hostname, std::string &_ip); + /// \brief Determine if an IP is private. + /// \param[in] _hostname Hostname + /// \param[out] _ip IP associated to the input hostname. + /// \return 0 when success. + int hostnameToIp(char *_hostname, std::string &_ip); - /// \brief Determine IP or hostname. - /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ - /// roscpp/src/libros/network.cpp - /// \return The IP or hostname of this host. - std::string GZ_TRANSPORT_VISIBLE determineHost(); + /// \brief Determine IP or hostname. + /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ + /// roscpp/src/libros/network.cpp + /// \return The IP or hostname of this host. + std::string GZ_TRANSPORT_VISIBLE determineHost(); - /// \brief Determine the list of network interfaces for this machine. - /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ - /// roscpp/src/libros/network.cpp - /// \return The list of network interfaces. - std::vector GZ_TRANSPORT_VISIBLE determineInterfaces(); + /// \brief Determine the list of network interfaces for this machine. + /// Reference: https://github.com/ros/ros_comm/blob/hydro-devel/clients/ + /// roscpp/src/libros/network.cpp + /// \return The list of network interfaces. + std::vector GZ_TRANSPORT_VISIBLE determineInterfaces(); - /// \brief Determine the computer's hostname. - /// \return The computer's hostname. - std::string GZ_TRANSPORT_VISIBLE hostname(); + /// \brief Determine the computer's hostname. + /// \return The computer's hostname. + std::string GZ_TRANSPORT_VISIBLE hostname(); - /// \brief Determine your login name. - /// \return Name used to gain access to the computer. - /// On linux and Mac only, if determination - /// of your login name fails then a string of the form "error-UUID" - /// is returned where UUID is a universally unique identifier. - std::string GZ_TRANSPORT_VISIBLE username(); - } + /// \brief Determine your login name. + /// \return Name used to gain access to the computer. + /// On linux and Mac only, if determination + /// of your login name fails then a string of the form "error-UUID" + /// is returned where UUID is a universally unique identifier. + std::string GZ_TRANSPORT_VISIBLE username(); } } diff --git a/include/gz/transport/Node.hh b/include/gz/transport/Node.hh index 6bf808716..62552b8d3 100644 --- a/include/gz/transport/Node.hh +++ b/include/gz/transport/Node.hh @@ -40,870 +40,868 @@ #include "gz/transport/TopicUtils.hh" #include "gz/transport/TransportTypes.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + // Forward declarations. + class NodePrivate; + + /// \brief Get the capacity of the buffer (High Water Mark) + /// that stores incoming Gazebo Transport messages. Note that this is a + /// global queue shared by all subscribers within the same process. + /// \return The capacity of the buffer storing incoming messages (units are + /// messages). A value of 0 indicates an unlimited buffer and -1 + /// that the socket cannot be queried. The default buffer size is + /// contained in the #kDefaultRcvHwm variable. + /// If the buffer is set to unlimited, then your buffer will grow until + /// you run out of memory (and probably crash). + /// If your buffer reaches the maximum capacity data will be dropped. + int GZ_TRANSPORT_VISIBLE rcvHwm(); + + /// \brief Get the capacity of the buffer (High Water Mark) + /// that stores outgoing Gazebo Transport messages. Note that this is a + /// global queue shared by all publishers within the same process. + /// \return The capacity of the buffer storing outgoing messages (units are + /// messages). A value of 0 indicates an unlimited buffer and -1 + /// that the socket cannot be queried. The default buffer size is + /// contained in the #kDefaultSndHwm variable. + /// If the buffer is set to unlimited, then your buffer will grow until + /// you run out of memory (and probably crash). + /// If your buffer reaches the maximum capacity data will be dropped. + int GZ_TRANSPORT_VISIBLE sndHwm(); + + /// \brief Block the current thread until a SIGINT or SIGTERM is received. + /// Note that this function registers a signal handler. Do not use this + /// function if you want to manage yourself SIGINT/SIGTERM. + void GZ_TRANSPORT_VISIBLE waitForShutdown(); + + /// \class Node Node.hh gz/transport/Node.hh + /// \brief A class that allows a client to communicate with other peers. + /// There are two main communication modes: pub/sub messages and service + /// calls. + class GZ_TRANSPORT_VISIBLE Node { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - // Forward declarations. - class NodePrivate; - - /// \brief Get the capacity of the buffer (High Water Mark) - /// that stores incoming Gazebo Transport messages. Note that this is a - /// global queue shared by all subscribers within the same process. - /// \return The capacity of the buffer storing incoming messages (units are - /// messages). A value of 0 indicates an unlimited buffer and -1 - /// that the socket cannot be queried. The default buffer size is - /// contained in the #kDefaultRcvHwm variable. - /// If the buffer is set to unlimited, then your buffer will grow until - /// you run out of memory (and probably crash). - /// If your buffer reaches the maximum capacity data will be dropped. - int GZ_TRANSPORT_VISIBLE rcvHwm(); - - /// \brief Get the capacity of the buffer (High Water Mark) - /// that stores outgoing Gazebo Transport messages. Note that this is a - /// global queue shared by all publishers within the same process. - /// \return The capacity of the buffer storing outgoing messages (units are - /// messages). A value of 0 indicates an unlimited buffer and -1 - /// that the socket cannot be queried. The default buffer size is - /// contained in the #kDefaultSndHwm variable. - /// If the buffer is set to unlimited, then your buffer will grow until - /// you run out of memory (and probably crash). - /// If your buffer reaches the maximum capacity data will be dropped. - int GZ_TRANSPORT_VISIBLE sndHwm(); - - /// \brief Block the current thread until a SIGINT or SIGTERM is received. - /// Note that this function registers a signal handler. Do not use this - /// function if you want to manage yourself SIGINT/SIGTERM. - void GZ_TRANSPORT_VISIBLE waitForShutdown(); - - /// \class Node Node.hh gz/transport/Node.hh - /// \brief A class that allows a client to communicate with other peers. - /// There are two main communication modes: pub/sub messages and service - /// calls. - class GZ_TRANSPORT_VISIBLE Node + class PublisherPrivate; + class SubscriberPrivate; + + /// \brief A class that is used to store information about an + /// advertised publisher. An instance of this class is returned + /// from Node::Advertise, and should be used in subsequent + /// Node::Publisher::Publish calls. + /// + /// ## Pseudo code example ## + /// + /// auto pub = myNode.Advertise("topic_name"); + /// if (pub) + /// { + /// MsgType msg; + /// + /// // Note that this version of Publish will copy the message + /// // when publishing to interprocess subscribers. + /// pub.Publish(msg); + /// } + public: class GZ_TRANSPORT_VISIBLE Publisher { - class PublisherPrivate; - class SubscriberPrivate; + /// \brief Default constructor. + public: Publisher(); - /// \brief A class that is used to store information about an - /// advertised publisher. An instance of this class is returned - /// from Node::Advertise, and should be used in subsequent - /// Node::Publisher::Publish calls. + /// \brief Constructor. + /// \param[in] _publisher A message publisher. + public: explicit Publisher(const MessagePublisher &_publisher); + + /// \brief Destructor. + public: virtual ~Publisher(); + + /// \brief Allows this class to be evaluated as a boolean. + /// \return True if valid + /// \sa Valid + public: operator bool(); + + /// \brief Allows this class to be evaluated as a boolean (const). + /// \return True if valid + /// \sa Valid + public: operator bool() const; + + /// \brief Return true if valid information, such as a non-empty + /// topic name, is present. + /// \return True if this object can be used in Publish() calls. + public: bool Valid() const; + + /// \brief Publish a message. This function will copy the message + /// when publishing to interprocess subscribers. This copy is + /// necessary to facilitate asynchronous publication. + /// \param[in] _msg A google::protobuf message. + /// \return true when success. + public: bool Publish(const ProtoMsg &_msg); + + /// \brief Publish a raw pre-serialized message. + /// + /// \warning This function is only intended for advanced users. The + /// standard publishing function, Publish(const ProtoMsg &_msg), will + /// ensure that your message is correctly serialized. It is strongly + /// recommended that you use the standard publishing function unless + /// there is a specific reason for using this one (e.g. you are + /// forwarding or playing back data instead of serializing/deserializing + /// it). We currently only support the serialization scheme of protobuf. /// - /// ## Pseudo code example ## + /// \warning This function will copy the message data when + /// publishing to remote subscribers (interprocess communication). /// - /// auto pub = myNode.Advertise("topic_name"); - /// if (pub) - /// { - /// MsgType msg; + /// \note This function will deserialize the message when sending it to + /// local (intraprocess) subscribers. /// - /// // Note that this version of Publish will copy the message - /// // when publishing to interprocess subscribers. - /// pub.Publish(msg); - /// } - public: class GZ_TRANSPORT_VISIBLE Publisher - { - /// \brief Default constructor. - public: Publisher(); - - /// \brief Constructor. - /// \param[in] _publisher A message publisher. - public: explicit Publisher(const MessagePublisher &_publisher); - - /// \brief Destructor. - public: virtual ~Publisher(); - - /// \brief Allows this class to be evaluated as a boolean. - /// \return True if valid - /// \sa Valid - public: operator bool(); - - /// \brief Allows this class to be evaluated as a boolean (const). - /// \return True if valid - /// \sa Valid - public: operator bool() const; - - /// \brief Return true if valid information, such as a non-empty - /// topic name, is present. - /// \return True if this object can be used in Publish() calls. - public: bool Valid() const; - - /// \brief Publish a message. This function will copy the message - /// when publishing to interprocess subscribers. This copy is - /// necessary to facilitate asynchronous publication. - /// \param[in] _msg A google::protobuf message. - /// \return true when success. - public: bool Publish(const ProtoMsg &_msg); - - /// \brief Publish a raw pre-serialized message. - /// - /// \warning This function is only intended for advanced users. The - /// standard publishing function, Publish(const ProtoMsg &_msg), will - /// ensure that your message is correctly serialized. It is strongly - /// recommended that you use the standard publishing function unless - /// there is a specific reason for using this one (e.g. you are - /// forwarding or playing back data instead of serializing/deserializing - /// it). We currently only support the serialization scheme of protobuf. - /// - /// \warning This function will copy the message data when - /// publishing to remote subscribers (interprocess communication). - /// - /// \note This function will deserialize the message when sending it to - /// local (intraprocess) subscribers. - /// - /// \param[in] _msgData A std::string that represents a - /// serialized google::protobuf message. - /// \param[in] _msgType A std::string that contains the message type - /// name. - /// \return true when success. - public: bool PublishRaw( - const std::string &_msgData, - const std::string &_msgType); - - /// \brief Check if message publication is throttled. If so, verify - /// whether the next message should be published or not. - /// - /// This may be used to skip resource or time-intensive operations - /// in the case that the message won't be published. - /// - /// \return true if the message should be published or false otherwise. - /// Additionally always returns true if the topic is not throttled. - public: bool ThrottledUpdateReady() const; - - /// \brief Check if message publication is throttled. If so, verify - /// whether the next message should be published or not. - /// \return true if the message should be published or false otherwise. - private: bool UpdateThrottling(); - - /// \brief Return true if this publisher has subscribers. - /// \return True if subscribers have connected to this publisher. - public: bool HasConnections() const; - - /// \internal - /// \brief Smart pointer to private data. - /// This is std::shared_ptr because we want to trigger the destructor - /// only once: when all references to PublisherPrivate are out of scope. - /// The destructor of PublisherPrivate unadvertise the topic. + /// \param[in] _msgData A std::string that represents a + /// serialized google::protobuf message. + /// \param[in] _msgType A std::string that contains the message type + /// name. + /// \return true when success. + public: bool PublishRaw( + const std::string &_msgData, + const std::string &_msgType); + + /// \brief Check if message publication is throttled. If so, verify + /// whether the next message should be published or not. + /// + /// This may be used to skip resource or time-intensive operations + /// in the case that the message won't be published. + /// + /// \return true if the message should be published or false otherwise. + /// Additionally always returns true if the topic is not throttled. + public: bool ThrottledUpdateReady() const; + + /// \brief Check if message publication is throttled. If so, verify + /// whether the next message should be published or not. + /// \return true if the message should be published or false otherwise. + private: bool UpdateThrottling(); + + /// \brief Return true if this publisher has subscribers. + /// \return True if subscribers have connected to this publisher. + public: bool HasConnections() const; + + /// \internal + /// \brief Smart pointer to private data. + /// This is std::shared_ptr because we want to trigger the destructor + /// only once: when all references to PublisherPrivate are out of scope. + /// The destructor of PublisherPrivate unadvertise the topic. #ifdef _WIN32 // Disable warning C4251 which is triggered by // std::shared_ptr #pragma warning(push) #pragma warning(disable: 4251) #endif - private: std::shared_ptr dataPtr; + private: std::shared_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; + }; - /// \brief A class that is used to store information about an - /// subscriber. An instance of this class is returned - /// from Node::CreateSubscribe. When the object is destroyed, - /// the corresponding subscription handler is removed from the node. - /// - /// ## Pseudo code example ## - /// - /// std::function cb = - /// [](const msgs::Int32 &) - /// { - /// // Do something - /// }; - /// Node::Subscriber sub = myNode.CreateSubscriber("topic_name", cb); - public: class GZ_TRANSPORT_VISIBLE Subscriber - { - /// \brief Default constructor. - public: Subscriber(); - - /// \brief Constructor - /// \param[in] _topic Subscribed topic name - /// \param[in] _nUuid Node to which this subscriber belongs - /// \param[in] _nOpts Node options for the node - /// \param[in] _hUuid Subscriber's handler UUID - public: Subscriber(const std::string &_topic, - const std::string &_nUuid, - const NodeOptions &_nOpts, - const std::string &_hUuid); - - /// \brief Destructor. - /// Unsubscribe to the topic and remove the subcription handler - public: virtual ~Subscriber(); - - /// \brief Unsubscribe from the topic. - /// \return True if the topic was successfully unsubscribed - public: bool Unsubscribe(); - - /// \brief Allows this class to be evaluated as a boolean. - /// \return True if valid - /// \sa Valid - public: operator bool(); - - /// \brief Allows this class to be evaluated as a boolean (const). - /// \return True if valid - /// \sa Valid - public: operator bool() const; - - /// \brief Move constructor - /// \param[in] _other The other Node::Subscriber - public: Subscriber(Subscriber &&_other); - - /// \brief Move assignment operator - /// \param[in] _other The other Node::Subscriber - /// \return Reference to this - public: Node::Subscriber &operator=(Subscriber &&_other); - - /// \brief Return true if valid information, such as a non-empty - /// topic name, node and handler UUIDs. - /// \return True if this object has a valid subscription. - public: bool Valid() const; - - /// \internal - /// \brief Smart pointer to private data. + /// \brief A class that is used to store information about an + /// subscriber. An instance of this class is returned + /// from Node::CreateSubscribe. When the object is destroyed, + /// the corresponding subscription handler is removed from the node. + /// + /// ## Pseudo code example ## + /// + /// std::function cb = + /// [](const msgs::Int32 &) + /// { + /// // Do something + /// }; + /// Node::Subscriber sub = myNode.CreateSubscriber("topic_name", cb); + public: class GZ_TRANSPORT_VISIBLE Subscriber + { + /// \brief Default constructor. + public: Subscriber(); + + /// \brief Constructor + /// \param[in] _topic Subscribed topic name + /// \param[in] _nUuid Node to which this subscriber belongs + /// \param[in] _nOpts Node options for the node + /// \param[in] _hUuid Subscriber's handler UUID + public: Subscriber(const std::string &_topic, + const std::string &_nUuid, + const NodeOptions &_nOpts, + const std::string &_hUuid); + + /// \brief Destructor. + /// Unsubscribe to the topic and remove the subcription handler + public: virtual ~Subscriber(); + + /// \brief Unsubscribe from the topic. + /// \return True if the topic was successfully unsubscribed + public: bool Unsubscribe(); + + /// \brief Allows this class to be evaluated as a boolean. + /// \return True if valid + /// \sa Valid + public: operator bool(); + + /// \brief Allows this class to be evaluated as a boolean (const). + /// \return True if valid + /// \sa Valid + public: operator bool() const; + + /// \brief Move constructor + /// \param[in] _other The other Node::Subscriber + public: Subscriber(Subscriber &&_other); + + /// \brief Move assignment operator + /// \param[in] _other The other Node::Subscriber + /// \return Reference to this + public: Node::Subscriber &operator=(Subscriber &&_other); + + /// \brief Return true if valid information, such as a non-empty + /// topic name, node and handler UUIDs. + /// \return True if this object has a valid subscription. + public: bool Valid() const; + + /// \internal + /// \brief Smart pointer to private data. #ifdef _WIN32 // Disable warning C4251 which is triggered by // std::shared_ptr #pragma warning(push) #pragma warning(disable: 4251) #endif - private: std::shared_ptr dataPtr; + private: std::shared_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; + }; - public: Node(); + public: Node(); + + /// \brief Constructor. + /// \param[in] _options Node options. + public: explicit Node(const NodeOptions &_options); + + /// \brief Destructor. + public: virtual ~Node(); + + /// \brief Advertise a new topic. If a topic is currently advertised, + /// you cannot advertise it a second time (regardless of its type). + /// \param[in] _topic Topic name to be advertised. + /// \param[in] _options Advertise options. + /// \return A PublisherId, which can be used in Node::Publish calls. + /// The PublisherId also acts as boolean, where true occurs if the topic + /// was successfully advertised. + /// \sa AdvertiseOptions. + public: template + Node::Publisher Advertise( + const std::string &_topic, + const AdvertiseMessageOptions &_options = AdvertiseMessageOptions()); + + /// \brief Advertise a new topic. If a topic is currently advertised, + /// you cannot advertise it a second time (regardless of its type). + /// \param[in] _topic Topic name to be advertised. + /// \param[in] _msgTypeName Name of the message type that will be + /// published on the topic. The message type name can be retrieved + /// from a protobuf message using the GetTypeName() function. + /// \param[in] _options Advertise options. + /// \return A PublisherId, which can be used in Node::Publish calls. + /// The PublisherId also acts as boolean, where true occurs if the topic + /// was successfully advertised. + /// \sa AdvertiseOptions. + public: Node::Publisher Advertise( + const std::string &_topic, + const std::string &_msgTypeName, + const AdvertiseMessageOptions &_options = AdvertiseMessageOptions()); + + /// \brief Get the list of topics advertised by this node. + /// \return A vector containing all the topics advertised by this node. + public: std::vector AdvertisedTopics() const; + + /// \brief Subscribe to a topic registering a callback. + /// This is function is overloaded with different variants of callback + /// functions. + /// Supported function callbacks are: + /// * free function + /// * member function + /// * lambda function + /// The callback function can contain one (_msg) or both (_msg, _info) of + /// the following parameters: + /// * _msg Protobuf message containing a new topic update. + /// * _info Message information (e.g.: topic name). + /// \param[in] args Arguments to be forwarded to SubscribeImpl + /// \return true when successfully subscribed or false otherwise. + /// \sa SubscribeImpl + public: template + bool Subscribe(Args && ...args); + + /// \brief Create a subscriber to a topic registering a callback + /// This is function is overloaded with different variants of callback + /// functions. It returns a Node::Subscriber object that maintains the + /// subscription while the object is alive. When the subscriber object + /// goes out of scope, it automatically unsubscribes to the topic, + /// removing just one single subscription handler from the node that it + /// belongs to. + /// Supported function callbacks are: + /// * free function + /// * member function + /// * lambda function + /// The callback function can contain one (_msg) or both (_msg, _info) of + /// the following parameters: + /// * _msg Protobuf message containing a new topic update. + /// * _info Message information (e.g.: topic name). + /// \param[in] _topic Topic to be subscribed. + /// \param[in] args Arguments to be forwarded to SubscribeImpl + /// \return true when successfully subscribed or false otherwise. + /// \sa SubscribeImpl + public: template + Node::Subscriber CreateSubscriber(const std::string &_topic, + Args && ...args); + + /// \brief Get the list of topics subscribed by this node. Note that + /// we might be interested in one topic but we still don't know the + /// address of a publisher. + /// \return A vector containing the subscribed topics (even if we do not + /// have an address for a particular topic yet). + public: std::vector SubscribedTopics() const; + + /// \brief Unsubscribe from a topic. + /// \param[in] _topic Topic name to be unsubscribed. + /// \return true when successfully unsubscribed or false otherwise. + public: bool Unsubscribe(const std::string &_topic); + + /// \brief Advertise a new service. + /// In this version the callback is a plain function pointer. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + bool(*_callback)(const RequestT &_request, ReplyT &_reply), + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without input parameter. + /// In this version the callback is a free function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + bool(*_callback)(ReplyT &_reply), + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without any output parameter. + /// In this version the callback is a free function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + void(*_callback)(const RequestT &_request), + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service. + /// In this version the callback is a lambda function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + std::function _callback, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without input parameter. + /// In this version the callback is a lambda function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + std::function &_callback, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without any output parameter. + /// In this version the callback is a lambda function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + std::function &_callback, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service. + /// In this version the callback is a member function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _obj Instance containing the member function. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + bool(ClassT::*_callback)(const RequestT &_request, ReplyT &_reply), + ClassT *_obj, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without input parameter. + /// In this version the callback is a member function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _reply Protobuf message containing the response. + /// * Returns Service call result. + /// \param[in] _obj Instance containing the member function. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions. + public: template + bool Advertise( + const std::string &_topic, + bool(ClassT::*_callback)(ReplyT &_reply), + ClassT *_obj, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Advertise a new service without any output parameter. + /// In this version the callback is a member function. + /// \param[in] _topic Topic name associated to the service. + /// \param[in] _callback Callback to handle the service request with the + /// following parameters: + /// * _request Protobuf message containing the request. + /// \param[in] _obj Instance containing the member function. + /// \param[in] _options Advertise options. + /// \return true when the topic has been successfully advertised or + /// false otherwise. + /// \sa AdvertiseOptions + public: template + bool Advertise( + const std::string &_topic, + void(ClassT::*_callback)(const RequestT &_request), + ClassT *_obj, + const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); + + /// \brief Get the list of services advertised by this node. + /// \return A vector containing all services advertised by this node. + public: std::vector AdvertisedServices() const; + + /// \brief Request a new service using a non-blocking call. + /// In this version the callback is a free function. + /// \param[in] _topic Service name requested. + /// \param[in] _request Protobuf message containing the request's + /// parameters. + /// \param[in] _callback Pointer to the callback function executed when + /// the response arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + const RequestT &_request, + void(*_callback)(const ReplyT &_reply, const bool _result)); + + /// \brief Request a new service without input parameter using a + /// non-blocking call. + /// In this version the callback is a free function. + /// \param[in] _topic Service name requested. + /// \param[in] _callback Pointer to the callback function executed when + /// the response arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + void(*_callback)(const ReplyT &_reply, const bool _result)); + + /// \brief Request a new service using a non-blocking call. + /// In this version the callback is a lambda function. + /// \param[in] _topic Service name requested. + /// \param[in] _request Protobuf message containing the request's + /// parameters. + /// \param[in] _callback Lambda function executed when the response + /// arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + const RequestT &_request, + std::function &_callback); + + /// \brief Request a new service without input parameter using a + /// non-blocking call. + /// In this version the callback is a lambda function. + /// \param[in] _topic Service name requested. + /// \param[in] _callback Lambda function executed when the response + /// arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + std::function &_callback); + + /// \brief Request a new service using a non-blocking call. + /// In this version the callback is a member function. + /// \param[in] _topic Service name requested. + /// \param[in] _request Protobuf message containing the request's + /// parameters. + /// \param[in] _callback Pointer to the callback function executed when + /// the response arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \param[in] _obj Instance containing the member function. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + const RequestT &_request, + void(ClassT::*_callback)(const ReplyT &_reply, const bool _result), + ClassT *_obj); + + /// \brief Request a new service without input parameter using a + /// non-blocking call. + /// In this version the callback is a member function. + /// \param[in] _topic Service name requested. + /// \param[in] _callback Pointer to the callback function executed when + /// the response arrives. The callback has the following parameters: + /// * _reply Protobuf message containing the response. + /// * _result Result of the service call. If false, there was + /// a problem executing your request. + /// \param[in] _obj Instance containing the member function. + /// \return true when the service call was successfully requested. + public: template + bool Request( + const std::string &_topic, + void(ClassT::*_callback)(const ReplyT &_reply, const bool _result), + ClassT *_obj); + + /// \brief Request a new service using a blocking call. + /// \param[in] _topic Service name requested. + /// \param[in] _request Protobuf message containing the request's + /// parameters. + /// \param[in] _timeout The request will timeout after '_timeout' ms. + /// \param[out] _reply Protobuf message containing the response. + /// \param[out] _result Result of the service call. + /// \return true when the request was executed or false if the timeout + /// expired. + public: template + bool Request( + const std::string &_topic, + const RequestT &_request, + const unsigned int &_timeout, + ReplyT &_reply, + bool &_result); + + /// \brief Request a new service without input parameter using a blocking + /// call. + /// \param[in] _topic Service name requested. + /// \param[in] _timeout The request will timeout after '_timeout' ms. + /// \param[out] _reply Protobuf message containing the response. + /// \param[out] _result Result of the service call. + /// \return true when the request was executed or false if the timeout + /// expired. + public: template + bool Request( + const std::string &_topic, + const unsigned int &_timeout, + ReplyT &_reply, + bool &_result); + + /// \brief Request a new service without waiting for response. + /// \param[in] _topic Topic requested. + /// \param[in] _request Protobuf message containing the request's + /// parameters. + /// \return true when the service call was successfully requested. + public: template + bool Request(const std::string &_topic, const RequestT &_request); + + /// \brief Request a new service using a blocking call. This request + /// function expects a serialized protobuf message as the request and + /// returns a serialized protobuf message as the response. + /// \param[in] _topic Service name requested. + /// \param[in] _request Protobuf message serialized into a string + /// containing the request's parameters. + /// \param[in] _requestType Message type of the request. + /// \param[in] _responseType Message type of the response. + /// \param[in] _timeout The request will timeout after '_timeout' ms. + /// \param[out] _response Serialized protobuf message containing the + /// response. + /// \param[out] _result Result of the service call. + /// \return true when the request was executed or false if the timeout + /// expired. + public: bool RequestRaw(const std::string &_topic, + const std::string &_request, const std::string &_requestType, + const std::string &_responseType, unsigned int _timeout, + std::string &_response, + bool &_result); + + /// \brief Unadvertise a service. + /// \param[in] _topic Service name to be unadvertised. + /// \return true if the service was successfully unadvertised. + public: bool UnadvertiseSrv(const std::string &_topic); + + /// \brief Get the list of topics currently advertised in the network. + /// Note that this function can block for some time if the + /// discovery is in its initialization phase. + /// The value of the "heartbeatInterval" constant, with a default + /// value of 1000 ms, sets the maximum blocking time period. + /// \param[out] _topics List of advertised topics. + public: void TopicList(std::vector &_topics) const; + + /// \brief Get the information about a topic. + /// \param[in] _topic Name of the topic. + /// \param[out] _publishers List of publishers on the topic. + /// \param[out] _subscribers List of subscribers on the topic. + /// \return False if unable to get topic info. + public: bool TopicInfo(const std::string &_topic, + std::vector &_publishers, + std::vector &_subscribers) const; + + /// \brief Get the list of topics currently advertised in the network. + /// Note that this function can block for some time if the + /// discovery is in its initialization phase. + /// The value of the "heartbeatInterval" constant, with a default + /// value of 1000ms, sets the maximum blocking time period. + /// \param[out] _services List of advertised services. + public: void ServiceList(std::vector &_services) const; + + /// \brief Get the information about a service. + /// \param[in] _service Name of the service. + /// \param[out] _publishers List of publishers on the service. + /// \return False if unable to get service info. + public: bool ServiceInfo( + const std::string &_service, + std::vector &_publishers) const; + + /// \brief Subscribe to a topic registering a callback. The callback must + /// accept a std::string to represent the message data, and a MessageInfo + /// which provides metadata about the message. + /// \param[in] _topic Name of the topic to subscribe to + /// \param[in] _callback A function pointer or std::function object that + /// has a void return value and accepts two arguments: + /// (const std::string &_msgData, const MessageInfo &_info). + /// \param[in] _msgType The type of message to subscribe to. Using + /// kGenericMessageType (the default) will allow this subscriber to listen + /// to all message types. The callback function can identify the type for + /// each message by inspecting its const MessageInfo& input argument. + /// \param[in] _opts Options for subscribing. + /// \return True if subscribing was successful. + public: bool SubscribeRaw( + const std::string &_topic, + const RawCallback &_callback, + const std::string &_msgType = kGenericMessageType, + const SubscribeOptions &_opts = SubscribeOptions()); + + /// \brief Get the reference to the current node options. + /// \return Reference to the current node options. + public: const NodeOptions &Options() const; + + /// \brief Turn topic statistics on or off. + /// \param[in] _topic The name of the topic on which to enable or disable + /// statistics. + /// \param[in] _enable True to enable statistics, false to disable. + /// \param[in] _publicationTopic Topic on which to publish statistics. + /// \param[in] _publicationRate Rate at which to publish statistics. + public: bool EnableStats(const std::string &_topic, bool _enable, + const std::string &_publicationTopic = "/statistics", + uint64_t _publicationRate = 1); + + /// \brief Get the current statistics for a topic. Statistics must + /// have been enabled using the EnableStatistics function, otherwise + /// the return value will be std::nullopt. + /// \param[in] _topic The name of the topic to get statistics for. + /// return A TopicStatistics class, or std::nullopt if statistics were + /// not enabled. + public: std::optional TopicStats( + const std::string &_topic) const; + + /// \brief Adds a unicast relay IP. All nodes in this process will send + /// UDP unicast traffic to the address to connect networks when UDP + /// multicast traffic is not forwarded. + /// It's also possible to use the environment variable GZ_RELAY to add + /// relays. + /// \param[in] _relayAddress IPv4 address of the relay to add. + public: void AddGlobalRelay(const std::string& _relayAddress); + + /// \brief Gets the relay addresses configured for all nodes in this + /// process. + /// \return The relay addresses. + public: std::vector GlobalRelays() const; + + /// \brief Get a pointer to the shared node (singleton shared by all the + /// nodes). + /// \return The pointer to the shared node. + private: NodeShared *Shared() const; + + /// \brief Get the UUID of this node. + /// \return The node UUID. + private: const std::string &NodeUuid() const; + + /// \brief Get the set of topics subscribed by this node. + /// \return The set of subscribed topics. + private: std::unordered_set &TopicsSubscribed() const; + + /// \brief Get the set of services advertised by this node. + /// \return The set of advertised services. + private: std::unordered_set &SrvsAdvertised() const; + + /// \brief Helper function for Subscribe. + /// \param[in] _fullyQualifiedTopic Fully qualified topic name + /// \return True on success. + private: bool SubscribeHelper(const std::string &_fullyQualifiedTopic); + + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback does not include any message information. + /// In this version the callback is a free function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Pointer to the callback function with the + /// following parameters: + /// * _msg Protobuf message containing a new topic update. + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( + const std::string &_topic, + void(*_callback)(const MessageT &_msg), + const SubscribeOptions &_opts = SubscribeOptions()); - /// \brief Constructor. - /// \param[in] _options Node options. - public: explicit Node(const NodeOptions &_options); + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback does not include any message information. + /// In this version the callback is a lambda function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Lambda function with the following parameters: + /// * _msg Protobuf message containing a new topic update. + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( + const std::string &_topic, + std::function _callback, + const SubscribeOptions &_opts = SubscribeOptions()); - /// \brief Destructor. - public: virtual ~Node(); - - /// \brief Advertise a new topic. If a topic is currently advertised, - /// you cannot advertise it a second time (regardless of its type). - /// \param[in] _topic Topic name to be advertised. - /// \param[in] _options Advertise options. - /// \return A PublisherId, which can be used in Node::Publish calls. - /// The PublisherId also acts as boolean, where true occurs if the topic - /// was successfully advertised. - /// \sa AdvertiseOptions. - public: template - Node::Publisher Advertise( - const std::string &_topic, - const AdvertiseMessageOptions &_options = AdvertiseMessageOptions()); - - /// \brief Advertise a new topic. If a topic is currently advertised, - /// you cannot advertise it a second time (regardless of its type). - /// \param[in] _topic Topic name to be advertised. - /// \param[in] _msgTypeName Name of the message type that will be - /// published on the topic. The message type name can be retrieved - /// from a protobuf message using the GetTypeName() function. - /// \param[in] _options Advertise options. - /// \return A PublisherId, which can be used in Node::Publish calls. - /// The PublisherId also acts as boolean, where true occurs if the topic - /// was successfully advertised. - /// \sa AdvertiseOptions. - public: Node::Publisher Advertise( - const std::string &_topic, - const std::string &_msgTypeName, - const AdvertiseMessageOptions &_options = AdvertiseMessageOptions()); - - /// \brief Get the list of topics advertised by this node. - /// \return A vector containing all the topics advertised by this node. - public: std::vector AdvertisedTopics() const; - - /// \brief Subscribe to a topic registering a callback. - /// This is function is overloaded with different variants of callback - /// functions. - /// Supported function callbacks are: - /// * free function - /// * member function - /// * lambda function - /// The callback function can contain one (_msg) or both (_msg, _info) of - /// the following parameters: - /// * _msg Protobuf message containing a new topic update. - /// * _info Message information (e.g.: topic name). - /// \param[in] args Arguments to be forwarded to SubscribeImpl - /// \return true when successfully subscribed or false otherwise. - /// \sa SubscribeImpl - public: template - bool Subscribe(Args && ...args); - - /// \brief Create a subscriber to a topic registering a callback - /// This is function is overloaded with different variants of callback - /// functions. It returns a Node::Subscriber object that maintains the - /// subscription while the object is alive. When the subscriber object - /// goes out of scope, it automatically unsubscribes to the topic, - /// removing just one single subscription handler from the node that it - /// belongs to. - /// Supported function callbacks are: - /// * free function - /// * member function - /// * lambda function - /// The callback function can contain one (_msg) or both (_msg, _info) of - /// the following parameters: - /// * _msg Protobuf message containing a new topic update. - /// * _info Message information (e.g.: topic name). - /// \param[in] _topic Topic to be subscribed. - /// \param[in] args Arguments to be forwarded to SubscribeImpl - /// \return true when successfully subscribed or false otherwise. - /// \sa SubscribeImpl - public: template - Node::Subscriber CreateSubscriber(const std::string &_topic, - Args && ...args); - - /// \brief Get the list of topics subscribed by this node. Note that - /// we might be interested in one topic but we still don't know the - /// address of a publisher. - /// \return A vector containing the subscribed topics (even if we do not - /// have an address for a particular topic yet). - public: std::vector SubscribedTopics() const; - - /// \brief Unsubscribe from a topic. - /// \param[in] _topic Topic name to be unsubscribed. - /// \return true when successfully unsubscribed or false otherwise. - public: bool Unsubscribe(const std::string &_topic); - - /// \brief Advertise a new service. - /// In this version the callback is a plain function pointer. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - bool(*_callback)(const RequestT &_request, ReplyT &_reply), - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without input parameter. - /// In this version the callback is a free function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - bool(*_callback)(ReplyT &_reply), - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without any output parameter. - /// In this version the callback is a free function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - void(*_callback)(const RequestT &_request), - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service. - /// In this version the callback is a lambda function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - std::function _callback, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without input parameter. - /// In this version the callback is a lambda function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - std::function &_callback, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without any output parameter. - /// In this version the callback is a lambda function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - std::function &_callback, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service. - /// In this version the callback is a member function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _obj Instance containing the member function. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - bool(ClassT::*_callback)(const RequestT &_request, ReplyT &_reply), - ClassT *_obj, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without input parameter. - /// In this version the callback is a member function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _reply Protobuf message containing the response. - /// * Returns Service call result. - /// \param[in] _obj Instance containing the member function. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions. - public: template - bool Advertise( - const std::string &_topic, - bool(ClassT::*_callback)(ReplyT &_reply), - ClassT *_obj, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Advertise a new service without any output parameter. - /// In this version the callback is a member function. - /// \param[in] _topic Topic name associated to the service. - /// \param[in] _callback Callback to handle the service request with the - /// following parameters: - /// * _request Protobuf message containing the request. - /// \param[in] _obj Instance containing the member function. - /// \param[in] _options Advertise options. - /// \return true when the topic has been successfully advertised or - /// false otherwise. - /// \sa AdvertiseOptions - public: template - bool Advertise( - const std::string &_topic, - void(ClassT::*_callback)(const RequestT &_request), - ClassT *_obj, - const AdvertiseServiceOptions &_options = AdvertiseServiceOptions()); - - /// \brief Get the list of services advertised by this node. - /// \return A vector containing all services advertised by this node. - public: std::vector AdvertisedServices() const; - - /// \brief Request a new service using a non-blocking call. - /// In this version the callback is a free function. - /// \param[in] _topic Service name requested. - /// \param[in] _request Protobuf message containing the request's - /// parameters. - /// \param[in] _callback Pointer to the callback function executed when - /// the response arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - const RequestT &_request, - void(*_callback)(const ReplyT &_reply, const bool _result)); - - /// \brief Request a new service without input parameter using a - /// non-blocking call. - /// In this version the callback is a free function. - /// \param[in] _topic Service name requested. - /// \param[in] _callback Pointer to the callback function executed when - /// the response arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - void(*_callback)(const ReplyT &_reply, const bool _result)); - - /// \brief Request a new service using a non-blocking call. - /// In this version the callback is a lambda function. - /// \param[in] _topic Service name requested. - /// \param[in] _request Protobuf message containing the request's - /// parameters. - /// \param[in] _callback Lambda function executed when the response - /// arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - const RequestT &_request, - std::function &_callback); - - /// \brief Request a new service without input parameter using a - /// non-blocking call. - /// In this version the callback is a lambda function. - /// \param[in] _topic Service name requested. - /// \param[in] _callback Lambda function executed when the response - /// arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - std::function &_callback); - - /// \brief Request a new service using a non-blocking call. - /// In this version the callback is a member function. - /// \param[in] _topic Service name requested. - /// \param[in] _request Protobuf message containing the request's - /// parameters. - /// \param[in] _callback Pointer to the callback function executed when - /// the response arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \param[in] _obj Instance containing the member function. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - const RequestT &_request, - void(ClassT::*_callback)(const ReplyT &_reply, const bool _result), - ClassT *_obj); - - /// \brief Request a new service without input parameter using a - /// non-blocking call. - /// In this version the callback is a member function. - /// \param[in] _topic Service name requested. - /// \param[in] _callback Pointer to the callback function executed when - /// the response arrives. The callback has the following parameters: - /// * _reply Protobuf message containing the response. - /// * _result Result of the service call. If false, there was - /// a problem executing your request. - /// \param[in] _obj Instance containing the member function. - /// \return true when the service call was successfully requested. - public: template - bool Request( - const std::string &_topic, - void(ClassT::*_callback)(const ReplyT &_reply, const bool _result), - ClassT *_obj); - - /// \brief Request a new service using a blocking call. - /// \param[in] _topic Service name requested. - /// \param[in] _request Protobuf message containing the request's - /// parameters. - /// \param[in] _timeout The request will timeout after '_timeout' ms. - /// \param[out] _reply Protobuf message containing the response. - /// \param[out] _result Result of the service call. - /// \return true when the request was executed or false if the timeout - /// expired. - public: template - bool Request( - const std::string &_topic, - const RequestT &_request, - const unsigned int &_timeout, - ReplyT &_reply, - bool &_result); - - /// \brief Request a new service without input parameter using a blocking - /// call. - /// \param[in] _topic Service name requested. - /// \param[in] _timeout The request will timeout after '_timeout' ms. - /// \param[out] _reply Protobuf message containing the response. - /// \param[out] _result Result of the service call. - /// \return true when the request was executed or false if the timeout - /// expired. - public: template - bool Request( - const std::string &_topic, - const unsigned int &_timeout, - ReplyT &_reply, - bool &_result); - - /// \brief Request a new service without waiting for response. - /// \param[in] _topic Topic requested. - /// \param[in] _request Protobuf message containing the request's - /// parameters. - /// \return true when the service call was successfully requested. - public: template - bool Request(const std::string &_topic, const RequestT &_request); - - /// \brief Request a new service using a blocking call. This request - /// function expects a serialized protobuf message as the request and - /// returns a serialized protobuf message as the response. - /// \param[in] _topic Service name requested. - /// \param[in] _request Protobuf message serialized into a string - /// containing the request's parameters. - /// \param[in] _requestType Message type of the request. - /// \param[in] _responseType Message type of the response. - /// \param[in] _timeout The request will timeout after '_timeout' ms. - /// \param[out] _response Serialized protobuf message containing the - /// response. - /// \param[out] _result Result of the service call. - /// \return true when the request was executed or false if the timeout - /// expired. - public: bool RequestRaw(const std::string &_topic, - const std::string &_request, const std::string &_requestType, - const std::string &_responseType, unsigned int _timeout, - std::string &_response, - bool &_result); - - /// \brief Unadvertise a service. - /// \param[in] _topic Service name to be unadvertised. - /// \return true if the service was successfully unadvertised. - public: bool UnadvertiseSrv(const std::string &_topic); - - /// \brief Get the list of topics currently advertised in the network. - /// Note that this function can block for some time if the - /// discovery is in its initialization phase. - /// The value of the "heartbeatInterval" constant, with a default - /// value of 1000 ms, sets the maximum blocking time period. - /// \param[out] _topics List of advertised topics. - public: void TopicList(std::vector &_topics) const; - - /// \brief Get the information about a topic. - /// \param[in] _topic Name of the topic. - /// \param[out] _publishers List of publishers on the topic. - /// \param[out] _subscribers List of subscribers on the topic. - /// \return False if unable to get topic info. - public: bool TopicInfo(const std::string &_topic, - std::vector &_publishers, - std::vector &_subscribers) const; - - /// \brief Get the list of topics currently advertised in the network. - /// Note that this function can block for some time if the - /// discovery is in its initialization phase. - /// The value of the "heartbeatInterval" constant, with a default - /// value of 1000ms, sets the maximum blocking time period. - /// \param[out] _services List of advertised services. - public: void ServiceList(std::vector &_services) const; - - /// \brief Get the information about a service. - /// \param[in] _service Name of the service. - /// \param[out] _publishers List of publishers on the service. - /// \return False if unable to get service info. - public: bool ServiceInfo( - const std::string &_service, - std::vector &_publishers) const; - - /// \brief Subscribe to a topic registering a callback. The callback must - /// accept a std::string to represent the message data, and a MessageInfo - /// which provides metadata about the message. - /// \param[in] _topic Name of the topic to subscribe to - /// \param[in] _callback A function pointer or std::function object that - /// has a void return value and accepts two arguments: - /// (const std::string &_msgData, const MessageInfo &_info). - /// \param[in] _msgType The type of message to subscribe to. Using - /// kGenericMessageType (the default) will allow this subscriber to listen - /// to all message types. The callback function can identify the type for - /// each message by inspecting its const MessageInfo& input argument. - /// \param[in] _opts Options for subscribing. - /// \return True if subscribing was successful. - public: bool SubscribeRaw( + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback does not include any message information. + /// In this version the callback is a member function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Pointer to the callback function with the + /// following parameters: + /// * _msg Protobuf message containing a new topic update. + /// \param[in] _obj Instance containing the member function. + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( const std::string &_topic, - const RawCallback &_callback, - const std::string &_msgType = kGenericMessageType, + void(ClassT::*_callback)(const MessageT &_msg), + ClassT *_obj, const SubscribeOptions &_opts = SubscribeOptions()); - /// \brief Get the reference to the current node options. - /// \return Reference to the current node options. - public: const NodeOptions &Options() const; - - /// \brief Turn topic statistics on or off. - /// \param[in] _topic The name of the topic on which to enable or disable - /// statistics. - /// \param[in] _enable True to enable statistics, false to disable. - /// \param[in] _publicationTopic Topic on which to publish statistics. - /// \param[in] _publicationRate Rate at which to publish statistics. - public: bool EnableStats(const std::string &_topic, bool _enable, - const std::string &_publicationTopic = "/statistics", - uint64_t _publicationRate = 1); - - /// \brief Get the current statistics for a topic. Statistics must - /// have been enabled using the EnableStatistics function, otherwise - /// the return value will be std::nullopt. - /// \param[in] _topic The name of the topic to get statistics for. - /// return A TopicStatistics class, or std::nullopt if statistics were - /// not enabled. - public: std::optional TopicStats( - const std::string &_topic) const; - - /// \brief Adds a unicast relay IP. All nodes in this process will send - /// UDP unicast traffic to the address to connect networks when UDP - /// multicast traffic is not forwarded. - /// It's also possible to use the environment variable GZ_RELAY to add - /// relays. - /// \param[in] _relayAddress IPv4 address of the relay to add. - public: void AddGlobalRelay(const std::string& _relayAddress); - - /// \brief Gets the relay addresses configured for all nodes in this - /// process. - /// \return The relay addresses. - public: std::vector GlobalRelays() const; - - /// \brief Get a pointer to the shared node (singleton shared by all the - /// nodes). - /// \return The pointer to the shared node. - private: NodeShared *Shared() const; - - /// \brief Get the UUID of this node. - /// \return The node UUID. - private: const std::string &NodeUuid() const; - - /// \brief Get the set of topics subscribed by this node. - /// \return The set of subscribed topics. - private: std::unordered_set &TopicsSubscribed() const; - - /// \brief Get the set of services advertised by this node. - /// \return The set of advertised services. - private: std::unordered_set &SrvsAdvertised() const; - - /// \brief Helper function for Subscribe. - /// \param[in] _fullyQualifiedTopic Fully qualified topic name - /// \return True on success. - private: bool SubscribeHelper(const std::string &_fullyQualifiedTopic); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback does not include any message information. - /// In this version the callback is a free function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Pointer to the callback function with the - /// following parameters: - /// * _msg Protobuf message containing a new topic update. - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - void(*_callback)(const MessageT &_msg), - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback does not include any message information. - /// In this version the callback is a lambda function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Lambda function with the following parameters: - /// * _msg Protobuf message containing a new topic update. - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - std::function _callback, - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback does not include any message information. - /// In this version the callback is a member function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Pointer to the callback function with the - /// following parameters: - /// * _msg Protobuf message containing a new topic update. - /// \param[in] _obj Instance containing the member function. - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - void(ClassT::*_callback)(const MessageT &_msg), - ClassT *_obj, - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback includes message information. - /// In this version the callback is a free function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Pointer to the callback function with the - /// following parameters: - /// * _msg Protobuf message containing a new topic update. - /// * _info Message information (e.g.: topic name). - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - void(*_callback)(const MessageT &_msg, const MessageInfo &_info), - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback includes message information. - /// In this version the callback is a lambda function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Lambda function with the following parameters: - /// * _msg Protobuf message containing a new topic update. - /// * _info Message information (e.g.: topic name). - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - std::function _callback, - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Subscribe to a topic registering a callback. - /// Note that this callback includes message information. - /// In this version the callback is a member function. - /// \param[in] _topic Topic to be subscribed. - /// \param[in] _callback Pointer to the callback function with the - /// following parameters: - /// * _msg Protobuf message containing a new topic update. - /// * _info Message information (e.g.: topic name). - /// \param[in] _obj Instance containing the member function. - /// \param[in] _opts Subscription options. - /// \return true when successfully subscribed or false otherwise. - private: template - std::shared_ptr> SubscribeImpl( - const std::string &_topic, - void(ClassT::*_callback)(const MessageT &_msg, - const MessageInfo &_info), - ClassT *_obj, - const SubscribeOptions &_opts = SubscribeOptions()); + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback includes message information. + /// In this version the callback is a free function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Pointer to the callback function with the + /// following parameters: + /// * _msg Protobuf message containing a new topic update. + /// * _info Message information (e.g.: topic name). + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( + const std::string &_topic, + void(*_callback)(const MessageT &_msg, const MessageInfo &_info), + const SubscribeOptions &_opts = SubscribeOptions()); + + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback includes message information. + /// In this version the callback is a lambda function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Lambda function with the following parameters: + /// * _msg Protobuf message containing a new topic update. + /// * _info Message information (e.g.: topic name). + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( + const std::string &_topic, + std::function _callback, + const SubscribeOptions &_opts = SubscribeOptions()); + + /// \brief Subscribe to a topic registering a callback. + /// Note that this callback includes message information. + /// In this version the callback is a member function. + /// \param[in] _topic Topic to be subscribed. + /// \param[in] _callback Pointer to the callback function with the + /// following parameters: + /// * _msg Protobuf message containing a new topic update. + /// * _info Message information (e.g.: topic name). + /// \param[in] _obj Instance containing the member function. + /// \param[in] _opts Subscription options. + /// \return true when successfully subscribed or false otherwise. + private: template + std::shared_ptr> SubscribeImpl( + const std::string &_topic, + void(ClassT::*_callback)(const MessageT &_msg, + const MessageInfo &_info), + ClassT *_obj, + const SubscribeOptions &_opts = SubscribeOptions()); #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -911,14 +909,13 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \internal - /// \brief Smart pointer to private data. - private: std::unique_ptr dataPtr; + /// \internal + /// \brief Smart pointer to private data. + private: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } diff --git a/include/gz/transport/NodeOptions.hh b/include/gz/transport/NodeOptions.hh index 409b62e97..e338f0563 100644 --- a/include/gz/transport/NodeOptions.hh +++ b/include/gz/transport/NodeOptions.hh @@ -24,107 +24,105 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - // Forward declarations. - class NodeOptionsPrivate; + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + // Forward declarations. + class NodeOptionsPrivate; - /// \class NodeOptions NodeOptions.hh gz/transport/NodeOptions.hh - /// \brief A class for customizing the behavior of the Node. - /// E.g.: Set a custom namespace or a partition name. - class GZ_TRANSPORT_VISIBLE NodeOptions - { - /// \brief Constructor. - public: NodeOptions(); + /// \class NodeOptions NodeOptions.hh gz/transport/NodeOptions.hh + /// \brief A class for customizing the behavior of the Node. + /// E.g.: Set a custom namespace or a partition name. + class GZ_TRANSPORT_VISIBLE NodeOptions + { + /// \brief Constructor. + public: NodeOptions(); - /// \brief Copy constructor. - /// \param[in] _other NodeOptions to copy. - public: NodeOptions(const NodeOptions &_other); + /// \brief Copy constructor. + /// \param[in] _other NodeOptions to copy. + public: NodeOptions(const NodeOptions &_other); - /// \brief Destructor. - public: virtual ~NodeOptions(); + /// \brief Destructor. + public: virtual ~NodeOptions(); - /// \brief Assignment operator. - /// \param[in] _other The new NodeOptions. - /// \return A reference to this instance. - public: NodeOptions &operator=(const NodeOptions &_other); + /// \brief Assignment operator. + /// \param[in] _other The new NodeOptions. + /// \return A reference to this instance. + public: NodeOptions &operator=(const NodeOptions &_other); - /// \brief Get the namespace used in this node. - /// \return The namespace. - /// \sa SetNameSpace. - public: const std::string &NameSpace() const; + /// \brief Get the namespace used in this node. + /// \return The namespace. + /// \sa SetNameSpace. + public: const std::string &NameSpace() const; - /// \brief Set the node's namespace. A namespace is considered a prefix - /// that might be potentially applied to some of the topic/services - /// advertised in a node. - /// E.g.: Node1 sets a namespace 'ns1' and advertises the topics - /// 't1', 't2' and '/t3'. '/t3' is considered an absolute topic (starts - /// with '/') and it won't be affected by a namespace. However, 't1' and - /// 't2' will be advertised as '/ns1/t1' and '/ns1/t2'. - /// A namespace is any alphanumeric string with a few exceptions. - /// The symbol '/' is allowed as part of a namespace but just '/' is not - /// allowed. The symbols '@', '~' and ' ' are not allowed as part of a - /// namespace. Two or more consecutive slashes ('//') are not allowed. - /// \param[in] _ns The namespace. - /// \return True when operation succeed or false if the namespace was - /// invalid. - /// \sa NameSpace. - public: bool SetNameSpace(const std::string &_ns); + /// \brief Set the node's namespace. A namespace is considered a prefix + /// that might be potentially applied to some of the topic/services + /// advertised in a node. + /// E.g.: Node1 sets a namespace 'ns1' and advertises the topics + /// 't1', 't2' and '/t3'. '/t3' is considered an absolute topic (starts + /// with '/') and it won't be affected by a namespace. However, 't1' and + /// 't2' will be advertised as '/ns1/t1' and '/ns1/t2'. + /// A namespace is any alphanumeric string with a few exceptions. + /// The symbol '/' is allowed as part of a namespace but just '/' is not + /// allowed. The symbols '@', '~' and ' ' are not allowed as part of a + /// namespace. Two or more consecutive slashes ('//') are not allowed. + /// \param[in] _ns The namespace. + /// \return True when operation succeed or false if the namespace was + /// invalid. + /// \sa NameSpace. + public: bool SetNameSpace(const std::string &_ns); - /// \brief Get the partition used in this node. - /// \return The partition name. - /// \sa SetPartition. - public: const std::string &Partition() const; + /// \brief Get the partition used in this node. + /// \return The partition name. + /// \sa SetPartition. + public: const std::string &Partition() const; - /// \brief Set the node's partition name. A partition is used to - /// isolate a set of topics or services from other nodes that use the same - /// names. E.g.: Node1 advertises topics '/foo' and Node2 advertises - /// '/foo' too. If we don't use a partition, a node subscribed to '/foo' - /// will receive the messages published from Node1 and Node2. - /// Alternatively, we could specify 'p1' as a partition for Node1 and 'p2' - /// as a partition for Node2. When we create the node for our subscriber, - /// if we specify 'p1' as a partition name, we'll receive the messages - /// published only by Node1. If we use 'p2', we'll only receive the - /// messages published by Node2. If we don't set a partition name, we - /// won't receive any messages from Node1 or Node2. - /// A partition name is any alphanumeric string with a few exceptions. - /// The symbol '/' is allowed as part of a partition name but just '/' is - /// not allowed. The symbols '@', '~' and ' ' are not allowed as part of a - /// partition name. Two or more consecutive slashes ('//') are not allowed - /// \param[in] _partition The partition's name. - /// The default partition value is created using a combination of your - /// hostname, followed by ':' and your username. E.g.: "bb9:caguero" . - /// It's also possible to use the environment variable GZ_PARTITION for - /// setting a partition name. - /// \return True when operation succeed or false if the partition name was - /// invalid. - /// \sa Partition - public: bool SetPartition(const std::string &_partition); + /// \brief Set the node's partition name. A partition is used to + /// isolate a set of topics or services from other nodes that use the same + /// names. E.g.: Node1 advertises topics '/foo' and Node2 advertises + /// '/foo' too. If we don't use a partition, a node subscribed to '/foo' + /// will receive the messages published from Node1 and Node2. + /// Alternatively, we could specify 'p1' as a partition for Node1 and 'p2' + /// as a partition for Node2. When we create the node for our subscriber, + /// if we specify 'p1' as a partition name, we'll receive the messages + /// published only by Node1. If we use 'p2', we'll only receive the + /// messages published by Node2. If we don't set a partition name, we + /// won't receive any messages from Node1 or Node2. + /// A partition name is any alphanumeric string with a few exceptions. + /// The symbol '/' is allowed as part of a partition name but just '/' is + /// not allowed. The symbols '@', '~' and ' ' are not allowed as part of a + /// partition name. Two or more consecutive slashes ('//') are not allowed + /// \param[in] _partition The partition's name. + /// The default partition value is created using a combination of your + /// hostname, followed by ':' and your username. E.g.: "bb9:caguero" . + /// It's also possible to use the environment variable GZ_PARTITION for + /// setting a partition name. + /// \return True when operation succeed or false if the partition name was + /// invalid. + /// \sa Partition + public: bool SetPartition(const std::string &_partition); - /// \brief Add a new topic remapping. Any [Un]Advertise(), - /// [Un]Subscribe() or Request() operation will check for topic - /// remappings. If a topic is remapped, the '_fromTopic' topic will be - /// renamed to '_toTopic' in any of the previous functions. - /// Is not possible to add two remaps over the same '_fromTopic'. - /// \param[in] _fromTopic Original topic to be renamed. - /// \param[in] _toTopic New topic to be used. - /// \return True if the topic remap is possible or false otherwise. - public: bool AddTopicRemap(const std::string &_fromTopic, - const std::string &_toTopic); + /// \brief Add a new topic remapping. Any [Un]Advertise(), + /// [Un]Subscribe() or Request() operation will check for topic + /// remappings. If a topic is remapped, the '_fromTopic' topic will be + /// renamed to '_toTopic' in any of the previous functions. + /// Is not possible to add two remaps over the same '_fromTopic'. + /// \param[in] _fromTopic Original topic to be renamed. + /// \param[in] _toTopic New topic to be used. + /// \return True if the topic remap is possible or false otherwise. + public: bool AddTopicRemap(const std::string &_fromTopic, + const std::string &_toTopic); - /// \brief Get a topic remapping. - /// \param[in] _fromTopic The original topic. - /// \param[out] _toTopic The new topic name. - /// _toTopic is unchanged if there is no remapping. - /// \return True if a topic remap was found for '_fromTopic' or - /// false otherwise. - public: bool TopicRemap(const std::string &_fromTopic, - std::string &_toTopic) const; + /// \brief Get a topic remapping. + /// \param[in] _fromTopic The original topic. + /// \param[out] _toTopic The new topic name. + /// _toTopic is unchanged if there is no remapping. + /// \return True if a topic remap was found for '_fromTopic' or + /// false otherwise. + public: bool TopicRemap(const std::string &_fromTopic, + std::string &_toTopic) const; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -132,14 +130,13 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \internal - /// \brief Smart pointer to private data. - protected: std::unique_ptr dataPtr; + /// \internal + /// \brief Smart pointer to private data. + protected: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } #endif diff --git a/include/gz/transport/NodeShared.hh b/include/gz/transport/NodeShared.hh index b6463e2e9..74fde6ed6 100644 --- a/include/gz/transport/NodeShared.hh +++ b/include/gz/transport/NodeShared.hh @@ -49,331 +49,329 @@ #include "gz/transport/TransportTypes.hh" #include "gz/transport/Uuid.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + // Forward declarations. + class Node; + class NodePrivate; + + /// \brief Private data pointer + class NodeSharedPrivate; + + /// \class NodeShared NodeShared.hh gz/transport/NodeShared.hh + /// \brief Private data for the Node class. This class should not be + /// directly used. You should use the Node class. + class GZ_TRANSPORT_VISIBLE NodeShared { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - // Forward declarations. - class Node; - class NodePrivate; - - /// \brief Private data pointer - class NodeSharedPrivate; - - /// \class NodeShared NodeShared.hh gz/transport/NodeShared.hh - /// \brief Private data for the Node class. This class should not be - /// directly used. You should use the Node class. - class GZ_TRANSPORT_VISIBLE NodeShared + /// \brief NodeShared is a singleton. This method gets the + /// NodeShared instance shared between all the nodes. + /// \return Pointer to the current NodeShared instance. + public: static NodeShared *Instance(); + + /// \brief Receive data and control messages. + public: void RunReceptionTask(); + + /// \brief Publish data. + /// \param[in] _topic Topic to be published. + /// \param[in, out] _data Serialized data. Note that this buffer will be + /// automatically deallocated by ZMQ when all data has been published. + /// \param[in] _dataSize Data size (bytes). + /// \param[in, out] _ffn Deallocation function. This function is + /// executed by ZeroMQ when the data is published. This function + /// deallocates the buffer containing the published data. + /// \sa http://zeromq.org/blog:zero-copy + /// \param[in] _msgType Message type in string format. + /// \return true when success or false otherwise. + public: bool Publish(const std::string &_topic, + char *_data, + const size_t _dataSize, + DeallocFunc *_ffn, + const std::string &_msgType); + + /// \brief Method in charge of receiving the topic updates. + public: void RecvMsgUpdate(); + + /// \brief HandlerInfo contains information about callback handlers which + /// is useful for local publishers and message receivers. You should only + /// retrieve a HandlerInfo by calling + /// CheckHandlerInfo(const std::string &_topic) const + public: struct HandlerInfo { - /// \brief NodeShared is a singleton. This method gets the - /// NodeShared instance shared between all the nodes. - /// \return Pointer to the current NodeShared instance. - public: static NodeShared *Instance(); - - /// \brief Receive data and control messages. - public: void RunReceptionTask(); - - /// \brief Publish data. - /// \param[in] _topic Topic to be published. - /// \param[in, out] _data Serialized data. Note that this buffer will be - /// automatically deallocated by ZMQ when all data has been published. - /// \param[in] _dataSize Data size (bytes). - /// \param[in, out] _ffn Deallocation function. This function is - /// executed by ZeroMQ when the data is published. This function - /// deallocates the buffer containing the published data. - /// \sa http://zeromq.org/blog:zero-copy - /// \param[in] _msgType Message type in string format. - /// \return true when success or false otherwise. - public: bool Publish(const std::string &_topic, - char *_data, - const size_t _dataSize, - DeallocFunc *_ffn, - const std::string &_msgType); - - /// \brief Method in charge of receiving the topic updates. - public: void RecvMsgUpdate(); - - /// \brief HandlerInfo contains information about callback handlers which - /// is useful for local publishers and message receivers. You should only - /// retrieve a HandlerInfo by calling - /// CheckHandlerInfo(const std::string &_topic) const - public: struct HandlerInfo - { - /// \brief This is a map of the standard local callback handlers. The - /// key is the topic name, and the value is another map whose key is - /// the node UUID and whose value is a smart pointer to the handler. - public: std::map localHandlers; - - /// \brief This is a map of the raw local callback handlers. The key is - /// the topic name, and the value is another map whose key is the node - /// UUID and whose value is a smart pointer to the handler. - public: std::map rawHandlers; - - /// \brief True iff there are any standard local subscribers. - public: bool haveLocal; - - /// \brief True iff there are any raw local subscribers - public: bool haveRaw; - - // Friendship. This allows HandlerInfo to be created by - // CheckHandlerInfo() - friend class NodeShared; - - // TODO(sloretz) private default constructor (visual studio 2017?) - }; - - /// \brief Get information about the local and raw subscribers that are - /// attached to this NodeShared. - /// \param[in] _topic Information will only be returned for handlers that - /// are subscribed to the given topic name. - /// \return Information about local subscription handlers that are held by - /// this NodeShared. - HandlerInfo CheckHandlerInfo(const std::string &_topic) const; - - /// \brief This struct provides information about the Subscribers of a - /// Publisher. It should only be retrieved using - /// CheckSubscriberInfo(const std::string&, const std::string&) const. - /// The relevant subscriber info is a superset of the relevant HandlerInfo - /// so we extend that struct. - /// - /// This struct is used internally by publishers to determine what kind of - /// subscribers they have. - public: struct SubscriberInfo : public HandlerInfo - { - /// \brief True if this Publisher has any remote subscribers - // cppcheck-suppress unusedStructMember - public: bool haveRemote; - - // Friendship declaration - friend class NodeShared; - - // TODO(sloretz) private default constructor (visual studio 2017?) - }; - - /// \brief Get information about the nodes that are subscribed to the - /// publishers of this NodeShared. - /// \param[in] _topic Only information about subscribers to this topic - /// will be returned. - /// \param[in] _msgType If there are no remote subscribers listening for - /// this message type, then SubscriberInfo::haveRemote will be false in - /// the return value of this function. - /// \return Information about subscribers. - SubscriberInfo CheckSubscriberInfo( - const std::string &_topic, - const std::string &_msgType) const; + /// \brief This is a map of the standard local callback handlers. The + /// key is the topic name, and the value is another map whose key is + /// the node UUID and whose value is a smart pointer to the handler. + public: std::map localHandlers; - /// \brief Call the SubscriptionHandler callbacks (local and raw) for this - /// NodeShared. - /// \param[in] _info Message information. - /// \param[in] _msgData The raw serialized data for the message - /// \param[in] _handlerInfo Information for the handlers of this node, - /// as generated by CheckHandlerInfo(const std::string&) const - public: void TriggerCallbacks( - const MessageInfo &_info, - const std::string &_msgData, - const HandlerInfo &_handlerInfo); - - /// \brief Method in charge of receiving the service call requests. - public: void RecvSrvRequest(); - - /// \brief Method in charge of receiving the service call responses. - public: void RecvSrvResponse(); - - /// \brief Try to send all the requests for a given service call and a - /// pair of request/response types. - /// \param[in] _topic Topic name. - /// \param[in] _reqType Type of the request in string format. - /// \param[in] _repType Type of the response in string format. - public: void SendPendingRemoteReqs(const std::string &_topic, - const std::string &_reqType, - const std::string &_repType); - - /// \brief Callback executed when the discovery detects new topics. - /// \param[in] _pub Information of the publisher in charge of the topic. - public: void OnNewConnection(const MessagePublisher &_pub); - - /// \brief Callback executed when the discovery detects disconnections. - /// \param[in] _pub Information of the publisher in charge of the topic. - public: void OnNewDisconnection(const MessagePublisher &_pub); - - /// \brief Callback executed when the discovery detects a new service call - /// \param[in] _pub Information of the publisher in charge of the service. - public: void OnNewSrvConnection(const ServicePublisher &_pub); - - /// \brief Callback executed when a service call is no longer available. - /// \param[in] _pub Information of the publisher in charge of the service. - public: void OnNewSrvDisconnection(const ServicePublisher &_pub); - - /// \brief Callback executed when a remote subscriber connects. - /// \param[in] _pub Information of the remote subscriber. - public: void OnNewRegistration(const MessagePublisher &_pub); - - /// \brief Callback executed when a remote subscriber unregisters. - /// \param[in] _pub Information of the remote subscriber. - public: void OnEndRegistration(const MessagePublisher &_pub); - - /// \brief Callback executed when a SUBSCRIBERS request is received. - public: void OnSubscribers(); - - /// \brief Pass through to bool Publishers(const std::string &_topic, - /// Addresses_M &_publishers) const - /// \param[in] _topic Service name. - /// \param[out] _publishers Collection of service publishers. - /// \return True if the service is found and - // there is at least one publisher. - /// \sa bool Publishers(const std::string &_topic, - /// Addresses_M &_publishers) const - public: bool TopicPublishers(const std::string &_topic, - SrvAddresses_M &_publishers) const; - - /// \brief Pass through to bool Discovery::Discover(const std::string - /// &_topic) const - /// \param[in] _topic Service name. - /// \return True if the method succeeded or false otherwise - /// (e.g. if the discovery has not been started). - /// \sa bool Discovery::Discover(const std::string &_topic) const - public: bool DiscoverService(const std::string &_topic) const; - - /// \brief Pass through to bool Advertise(const Pub &_publisher) - /// \param[in] _publisher Publisher's information to advertise. - /// \return True if the method succeed or false otherwise - /// (e.g. if the discovery has not been started). - /// \sa Pass through to bool Advertise(const Pub &_publisher) - public: bool AdvertisePublisher(const ServicePublisher &_publisher); - - /// \brief Get the capacity of the buffer (High Water Mark) - /// that stores incoming Gazebo Transport messages. Note that this is a - /// global queue shared by all subscribers within the same process. - /// \return The capacity of the buffer storing incoming messages (units - /// are messages). A value of 0 indicates an unlimited buffer and -1 - /// that the socket cannot be queried. The default buffer size is - /// contained in the #kDefaultRcvHwm variable. - /// If the buffer is set to unlimited, then your buffer will grow until - /// you run out of memory (and probably crash). - /// If your buffer reaches the maximum capacity data will be dropped. - public: int RcvHwm(); - - /// \brief Get the capacity of the buffer (High Water Mark) - /// that stores outgoing Gazebo Transport messages. Note that this is a - /// global queue shared by all publishers within the same process. - /// \return The capacity of the buffer storing outgoing messages (units - /// are messages). A value of 0 indicates an unlimited buffer and -1 - /// that the socket cannot be queried. The default buffer size is - /// contained in the #kDefaultSndHwm variable. - /// If the buffer is set to unlimited, then your buffer will grow until - /// you run out of memory (and probably crash). - /// If your buffer reaches the maximum capacity data will be dropped. - public: int SndHwm(); - - /// \brief Turn topic statistics on or off. - /// \param[in] _topic The name of the topic on which to enable or disable - /// statistics. - /// \param[in] _enable True to enable statistics, false to disable. - /// \param[in] _cb Callback that is triggered whenever statistics are - /// updated. - public: void EnableStats(const std::string &_topic, bool _enable, - std::function _cb); - - /// \brief Get the current statistics for a topic. Statistics must - /// have been enabled using the EnableStatistics function, otherwise - /// the return value will be std::nullopt. - /// \param[in] _topic The name of the topic to get statistics for. - /// \return A TopicStatistics class, or std::nullopt if statistics were - /// not enabled. - public: std::optional TopicStats( - const std::string &_topic) const; - - /// \brief Adds a unicast relay IP. All nodes in this process will send - /// UDP unicast traffic to the address to connect networks when UDP - /// multicast traffic is not forwarded. - /// It's also possible to use the environment variable GZ_RELAY to add - /// relays. - /// \param[in] _relayAddress IPv4 address of the relay to add. - public: void AddGlobalRelay(const std::string& _relayAddress); - - /// \brief Gets the relay addresses configured for all nodes in this - /// process. - /// \return The relay addresses. - public: std::vector GlobalRelays() const; - - /// \brief Unsubscribe a node from a topic. - /// If the handler UUID argument is empty, all subscription handlers in - /// the node for the specified topic are removed - /// \param[in] _topic Topic name to be unsubscribed. - /// \param[in] _nUuid Node UUID. - /// \param[in] _nOpt Node options. - /// \param[in] _hUuid Hander UUID. - /// \return True when successfully unsubscribed or false otherwise. - public: bool Unsubscribe(const std::string &_topic, - const std::string &_nUuid, - const NodeOptions &_nOpt, - const std::string &_hUuid = ""); - - /// \brief Get the set of topics subscribed by a node. - /// \param[in] _nUuid Node UUID. - /// \return The set of subscribed topics. - private: std::unordered_set &TopicsSubscribed( - const std::string &_nUuid) const; - - /// \brief Remove a subscribed topic for a node - /// \param[in] _topic Topic to remove. - /// \param[in] _nUuid Node UUID. - /// \return True if the topic is successfully removed, false otherwise. - private: bool RemoveSubscribedTopic(const std::string &_topic, - const std::string &_nUuid); - - /// \brief Helper function to remove handlers from the shared publish - /// queue for a node. This is called when the node unsubscribes to a topic - /// \param[in] _topic Topic that the node unsubscribed to. - /// \param[in] _nUuid Node UUID. - /// \return True on success. - public: bool RemoveHandlersFromPubQueue(const std::string &_topic, - const std::string &_nUuid); - - /// \brief Helper function to remove one handler from the shared publish - /// queue for a node. This is called when the node unsubscribes to a - /// topic for a single handler. - /// \param[in] _topic Topic that the node unsubscribed to. - /// \param[in] _nUuid Node UUID. - /// \param[in] _hUuid Handler UUID. - /// \return True on success. - public: bool RemoveHandlerFromPubQueue(const std::string &_topic, - const std::string &_nUuid, - const std::string &_hUuid); - - /// \brief Helper function for Subscribe. This adds the fully qualified - /// topic name to a map of node to topic names, which helps track - /// a list of topics subscribed by a node. - /// \param[in] _fullyQualifiedTopic Fully qualified topic name - /// \param[in] _nUuid Node UUID. - /// \return True on success. - /// \sa TopicUtils::FullyQualifiedName - public: bool SubscribeHelper(const std::string &_fullyQualifiedTopic, - const std::string &_nUuid); + /// \brief This is a map of the raw local callback handlers. The key is + /// the topic name, and the value is another map whose key is the node + /// UUID and whose value is a smart pointer to the handler. + public: std::map rawHandlers; - /// \brief Constructor. - protected: NodeShared(); + /// \brief True iff there are any standard local subscribers. + public: bool haveLocal; - /// \brief Destructor. - protected: virtual ~NodeShared(); + /// \brief True iff there are any raw local subscribers + public: bool haveRaw; - /// \brief Initialize all sockets. - /// \return True when success or false otherwise. This function might - /// return false if any operation on a ZMQ socket triggered an exception. - private: bool InitializeSockets(); + // Friendship. This allows HandlerInfo to be created by + // CheckHandlerInfo() + friend class NodeShared; - ////////////////////////////////////////////////// - /////// Declare here other member variables ////// - ////////////////////////////////////////////////// + // TODO(sloretz) private default constructor (visual studio 2017?) + }; - /// \brief Response receiver socket identity. - public: Uuid responseReceiverId; + /// \brief Get information about the local and raw subscribers that are + /// attached to this NodeShared. + /// \param[in] _topic Information will only be returned for handlers that + /// are subscribed to the given topic name. + /// \return Information about local subscription handlers that are held by + /// this NodeShared. + HandlerInfo CheckHandlerInfo(const std::string &_topic) const; + + /// \brief This struct provides information about the Subscribers of a + /// Publisher. It should only be retrieved using + /// CheckSubscriberInfo(const std::string&, const std::string&) const. + /// The relevant subscriber info is a superset of the relevant HandlerInfo + /// so we extend that struct. + /// + /// This struct is used internally by publishers to determine what kind of + /// subscribers they have. + public: struct SubscriberInfo : public HandlerInfo + { + /// \brief True if this Publisher has any remote subscribers + // cppcheck-suppress unusedStructMember + public: bool haveRemote; + + // Friendship declaration + friend class NodeShared; + + // TODO(sloretz) private default constructor (visual studio 2017?) + }; - /// \brief Replier socket identity. - public: Uuid replierId; + /// \brief Get information about the nodes that are subscribed to the + /// publishers of this NodeShared. + /// \param[in] _topic Only information about subscribers to this topic + /// will be returned. + /// \param[in] _msgType If there are no remote subscribers listening for + /// this message type, then SubscriberInfo::haveRemote will be false in + /// the return value of this function. + /// \return Information about subscribers. + SubscriberInfo CheckSubscriberInfo( + const std::string &_topic, + const std::string &_msgType) const; + + /// \brief Call the SubscriptionHandler callbacks (local and raw) for this + /// NodeShared. + /// \param[in] _info Message information. + /// \param[in] _msgData The raw serialized data for the message + /// \param[in] _handlerInfo Information for the handlers of this node, + /// as generated by CheckHandlerInfo(const std::string&) const + public: void TriggerCallbacks( + const MessageInfo &_info, + const std::string &_msgData, + const HandlerInfo &_handlerInfo); + + /// \brief Method in charge of receiving the service call requests. + public: void RecvSrvRequest(); + + /// \brief Method in charge of receiving the service call responses. + public: void RecvSrvResponse(); + + /// \brief Try to send all the requests for a given service call and a + /// pair of request/response types. + /// \param[in] _topic Topic name. + /// \param[in] _reqType Type of the request in string format. + /// \param[in] _repType Type of the response in string format. + public: void SendPendingRemoteReqs(const std::string &_topic, + const std::string &_reqType, + const std::string &_repType); + + /// \brief Callback executed when the discovery detects new topics. + /// \param[in] _pub Information of the publisher in charge of the topic. + public: void OnNewConnection(const MessagePublisher &_pub); + + /// \brief Callback executed when the discovery detects disconnections. + /// \param[in] _pub Information of the publisher in charge of the topic. + public: void OnNewDisconnection(const MessagePublisher &_pub); + + /// \brief Callback executed when the discovery detects a new service call + /// \param[in] _pub Information of the publisher in charge of the service. + public: void OnNewSrvConnection(const ServicePublisher &_pub); + + /// \brief Callback executed when a service call is no longer available. + /// \param[in] _pub Information of the publisher in charge of the service. + public: void OnNewSrvDisconnection(const ServicePublisher &_pub); + + /// \brief Callback executed when a remote subscriber connects. + /// \param[in] _pub Information of the remote subscriber. + public: void OnNewRegistration(const MessagePublisher &_pub); + + /// \brief Callback executed when a remote subscriber unregisters. + /// \param[in] _pub Information of the remote subscriber. + public: void OnEndRegistration(const MessagePublisher &_pub); + + /// \brief Callback executed when a SUBSCRIBERS request is received. + public: void OnSubscribers(); + + /// \brief Pass through to bool Publishers(const std::string &_topic, + /// Addresses_M &_publishers) const + /// \param[in] _topic Service name. + /// \param[out] _publishers Collection of service publishers. + /// \return True if the service is found and + // there is at least one publisher. + /// \sa bool Publishers(const std::string &_topic, + /// Addresses_M &_publishers) const + public: bool TopicPublishers(const std::string &_topic, + SrvAddresses_M &_publishers) const; + + /// \brief Pass through to bool Discovery::Discover(const std::string + /// &_topic) const + /// \param[in] _topic Service name. + /// \return True if the method succeeded or false otherwise + /// (e.g. if the discovery has not been started). + /// \sa bool Discovery::Discover(const std::string &_topic) const + public: bool DiscoverService(const std::string &_topic) const; + + /// \brief Pass through to bool Advertise(const Pub &_publisher) + /// \param[in] _publisher Publisher's information to advertise. + /// \return True if the method succeed or false otherwise + /// (e.g. if the discovery has not been started). + /// \sa Pass through to bool Advertise(const Pub &_publisher) + public: bool AdvertisePublisher(const ServicePublisher &_publisher); + + /// \brief Get the capacity of the buffer (High Water Mark) + /// that stores incoming Gazebo Transport messages. Note that this is a + /// global queue shared by all subscribers within the same process. + /// \return The capacity of the buffer storing incoming messages (units + /// are messages). A value of 0 indicates an unlimited buffer and -1 + /// that the socket cannot be queried. The default buffer size is + /// contained in the #kDefaultRcvHwm variable. + /// If the buffer is set to unlimited, then your buffer will grow until + /// you run out of memory (and probably crash). + /// If your buffer reaches the maximum capacity data will be dropped. + public: int RcvHwm(); + + /// \brief Get the capacity of the buffer (High Water Mark) + /// that stores outgoing Gazebo Transport messages. Note that this is a + /// global queue shared by all publishers within the same process. + /// \return The capacity of the buffer storing outgoing messages (units + /// are messages). A value of 0 indicates an unlimited buffer and -1 + /// that the socket cannot be queried. The default buffer size is + /// contained in the #kDefaultSndHwm variable. + /// If the buffer is set to unlimited, then your buffer will grow until + /// you run out of memory (and probably crash). + /// If your buffer reaches the maximum capacity data will be dropped. + public: int SndHwm(); + + /// \brief Turn topic statistics on or off. + /// \param[in] _topic The name of the topic on which to enable or disable + /// statistics. + /// \param[in] _enable True to enable statistics, false to disable. + /// \param[in] _cb Callback that is triggered whenever statistics are + /// updated. + public: void EnableStats(const std::string &_topic, bool _enable, + std::function _cb); + + /// \brief Get the current statistics for a topic. Statistics must + /// have been enabled using the EnableStatistics function, otherwise + /// the return value will be std::nullopt. + /// \param[in] _topic The name of the topic to get statistics for. + /// \return A TopicStatistics class, or std::nullopt if statistics were + /// not enabled. + public: std::optional TopicStats( + const std::string &_topic) const; + + /// \brief Adds a unicast relay IP. All nodes in this process will send + /// UDP unicast traffic to the address to connect networks when UDP + /// multicast traffic is not forwarded. + /// It's also possible to use the environment variable GZ_RELAY to add + /// relays. + /// \param[in] _relayAddress IPv4 address of the relay to add. + public: void AddGlobalRelay(const std::string& _relayAddress); + + /// \brief Gets the relay addresses configured for all nodes in this + /// process. + /// \return The relay addresses. + public: std::vector GlobalRelays() const; + + /// \brief Unsubscribe a node from a topic. + /// If the handler UUID argument is empty, all subscription handlers in + /// the node for the specified topic are removed + /// \param[in] _topic Topic name to be unsubscribed. + /// \param[in] _nUuid Node UUID. + /// \param[in] _nOpt Node options. + /// \param[in] _hUuid Hander UUID. + /// \return True when successfully unsubscribed or false otherwise. + public: bool Unsubscribe(const std::string &_topic, + const std::string &_nUuid, + const NodeOptions &_nOpt, + const std::string &_hUuid = ""); + + /// \brief Get the set of topics subscribed by a node. + /// \param[in] _nUuid Node UUID. + /// \return The set of subscribed topics. + private: std::unordered_set &TopicsSubscribed( + const std::string &_nUuid) const; + + /// \brief Remove a subscribed topic for a node + /// \param[in] _topic Topic to remove. + /// \param[in] _nUuid Node UUID. + /// \return True if the topic is successfully removed, false otherwise. + private: bool RemoveSubscribedTopic(const std::string &_topic, + const std::string &_nUuid); + + /// \brief Helper function to remove handlers from the shared publish + /// queue for a node. This is called when the node unsubscribes to a topic + /// \param[in] _topic Topic that the node unsubscribed to. + /// \param[in] _nUuid Node UUID. + /// \return True on success. + public: bool RemoveHandlersFromPubQueue(const std::string &_topic, + const std::string &_nUuid); + + /// \brief Helper function to remove one handler from the shared publish + /// queue for a node. This is called when the node unsubscribes to a + /// topic for a single handler. + /// \param[in] _topic Topic that the node unsubscribed to. + /// \param[in] _nUuid Node UUID. + /// \param[in] _hUuid Handler UUID. + /// \return True on success. + public: bool RemoveHandlerFromPubQueue(const std::string &_topic, + const std::string &_nUuid, + const std::string &_hUuid); + + /// \brief Helper function for Subscribe. This adds the fully qualified + /// topic name to a map of node to topic names, which helps track + /// a list of topics subscribed by a node. + /// \param[in] _fullyQualifiedTopic Fully qualified topic name + /// \param[in] _nUuid Node UUID. + /// \return True on success. + /// \sa TopicUtils::FullyQualifiedName + public: bool SubscribeHelper(const std::string &_fullyQualifiedTopic, + const std::string &_nUuid); + + /// \brief Constructor. + protected: NodeShared(); + + /// \brief Destructor. + protected: virtual ~NodeShared(); + + /// \brief Initialize all sockets. + /// \return True when success or false otherwise. This function might + /// return false if any operation on a ZMQ socket triggered an exception. + private: bool InitializeSockets(); + + ////////////////////////////////////////////////// + /////// Declare here other member variables ////// + ////////////////////////////////////////////////// + + /// \brief Response receiver socket identity. + public: Uuid responseReceiverId; + + /// \brief Replier socket identity. + public: Uuid replierId; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -381,128 +379,128 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Process UUID. - public: std::string pUuid; + /// \brief Process UUID. + public: std::string pUuid; - /// \brief thread in charge of receiving and handling incoming messages. - public: std::thread threadReception; + /// \brief thread in charge of receiving and handling incoming messages. + public: std::thread threadReception; - /// \brief Mutex to guarantee exclusive access between all threads. - public: mutable std::recursive_mutex mutex; + /// \brief Mutex to guarantee exclusive access between all threads. + public: mutable std::recursive_mutex mutex; - /// \brief Default IP address used by the message discovery layer. - public: std::string discoveryIP = "239.255.0.7"; + /// \brief Default IP address used by the message discovery layer. + public: std::string discoveryIP = "239.255.0.7"; - /// \brief Default port used by the message discovery layer. - public: static const int kDefaultMsgDiscPort = 10317; + /// \brief Default port used by the message discovery layer. + public: static const int kDefaultMsgDiscPort = 10317; - /// \brief Default port used by the service discovery layer. - public: static const int kDefaultSrvDiscPort = 10318; + /// \brief Default port used by the service discovery layer. + public: static const int kDefaultSrvDiscPort = 10318; - /// \brief Port used by the message discovery layer. - public: int msgDiscPort = kDefaultMsgDiscPort; + /// \brief Port used by the message discovery layer. + public: int msgDiscPort = kDefaultMsgDiscPort; - /// \brief Port used by the service discovery layer. - public: int srvDiscPort = kDefaultSrvDiscPort; + /// \brief Port used by the service discovery layer. + public: int srvDiscPort = kDefaultSrvDiscPort; - /// \brief Remote connections for pub/sub messages. - private: TopicStorage connections; + /// \brief Remote connections for pub/sub messages. + private: TopicStorage connections; - /// \brief List of connected zmq end points for request/response. - private: std::vector srvConnections; + /// \brief List of connected zmq end points for request/response. + private: std::vector srvConnections; - /// \brief Remote subscribers. - public: TopicStorage remoteSubscribers; + /// \brief Remote subscribers. + public: TopicStorage remoteSubscribers; #ifdef _WIN32 #pragma warning(pop) #endif - /// \brief This struct wraps up the two different types of subscription - /// handlers: normal (deserialized) and raw (serialized). This wrapper - /// keeps the two sets of subscription handlers coordinated while allowing - /// them to act independently when necessary. - struct HandlerWrapper - { - /// \brief Returns true if this wrapper contains any subscriber that - /// matches the given topic name and message type name. - /// \param[in] _fullyQualifiedTopic Fully-qualified topic name - /// \param[in] _msgType Name of message type - /// \return True if this contains a matching subscriber, otherwise false - /// \sa TopicUtils::FullyQualifiedName - public: bool HasSubscriber( - const std::string &_fullyQualifiedTopic, - const std::string &_msgType) const; - - /// \brief Returns true if this wrapper contains any subscriber that - /// matches the given fully-qualified topic name. The message type name - /// of the subscriber is irrelevant. - /// \param[in] _fullyQualifiedTopic Fully-qualified topic name - /// \return True if this contains a matching subscriber, otherwise false - public: bool HasSubscriber( - const std::string &_fullyQualifiedTopic) const; - - /// \brief Returns true if this wrapper contains any subscriber that - /// matches the given fully-qualified topic name and node UUID. - /// The message type name of the subscriber is irrelevant. - /// \param[in] _fullyQualifiedTopic Fully-qualified topic name - /// \param[in] _nUuid Node UUID - /// \return True if this contains a matching subscriber, otherwise false - public: bool HasSubscriberForNode( - const std::string &_fullyQualifiedTopic, const std::string &_nUuid) - const; - - /// \brief Get a set of node UUIDs for subscribers in this wrapper that - /// match the topic and message type criteria. - /// \param[in] _fullyQualifiedTopic Fully-qualified topic name that the - /// subscribers must be listening to. - /// \param[in] _msgTypeName Name of the message type that the - /// subscribers must be listening for. - /// \return The node UUIDs of all subscribers that match the criteria - public: std::vector NodeUuids( - const std::string &_fullyQualifiedTopic, - const std::string &_msgTypeName) const; - - /// \brief Remove the handlers for the given topic name that belong to - /// a specific node. - /// \param[in] _fullyQualifiedTopic The fully-qualified name of the - /// topic whose subscribers should be removed. - /// \param[in] _nUuid The UUID of the node whose subscribers should be - /// removed. - /// \return True if at least one subscriber was removed. - public: bool RemoveHandlersForNode( - const std::string &_fullyQualifiedTopic, - const std::string &_nUuid); - - /// \brief Remove one handler for the given topic name that belong to - /// a specific node. - /// \param[in] _fullyQualifiedTopic The fully-qualified name of the - /// topic whose subscribers should be removed. - /// \param[in] _nUuid The UUID of the node whose subscribers should be - /// removed. - /// \param[in] _hUuid The UUID of the handler to remove. - /// \return True if the subscriber was removed. - public: bool RemoveHandler( - const std::string &_fullyQualifiedTopic, - const std::string &_nUuid, - const std::string &_hUuid); - - /// \brief Convert all the HandlerStorages into a vector of publishers. - /// \param[in] _addr The pub/sub address. - /// \param[in] _pUuid The process UUID. - /// \return The vector of message publishers. - public: std::vector Convert(const std::string &_addr, - const std::string &_pUuid); - - /// \brief Normal local subscriptions. - public: HandlerStorage normal; - - /// \brief Raw local subscriptions. Keeping these separate from - /// localSubscriptions allows us to avoid an unnecessary deserialization - /// followed by an immediate reserialization. - public: HandlerStorage raw; - }; - - public: HandlerWrapper localSubscribers; + /// \brief This struct wraps up the two different types of subscription + /// handlers: normal (deserialized) and raw (serialized). This wrapper + /// keeps the two sets of subscription handlers coordinated while allowing + /// them to act independently when necessary. + struct HandlerWrapper + { + /// \brief Returns true if this wrapper contains any subscriber that + /// matches the given topic name and message type name. + /// \param[in] _fullyQualifiedTopic Fully-qualified topic name + /// \param[in] _msgType Name of message type + /// \return True if this contains a matching subscriber, otherwise false + /// \sa TopicUtils::FullyQualifiedName + public: bool HasSubscriber( + const std::string &_fullyQualifiedTopic, + const std::string &_msgType) const; + + /// \brief Returns true if this wrapper contains any subscriber that + /// matches the given fully-qualified topic name. The message type name + /// of the subscriber is irrelevant. + /// \param[in] _fullyQualifiedTopic Fully-qualified topic name + /// \return True if this contains a matching subscriber, otherwise false + public: bool HasSubscriber( + const std::string &_fullyQualifiedTopic) const; + + /// \brief Returns true if this wrapper contains any subscriber that + /// matches the given fully-qualified topic name and node UUID. + /// The message type name of the subscriber is irrelevant. + /// \param[in] _fullyQualifiedTopic Fully-qualified topic name + /// \param[in] _nUuid Node UUID + /// \return True if this contains a matching subscriber, otherwise false + public: bool HasSubscriberForNode( + const std::string &_fullyQualifiedTopic, const std::string &_nUuid) + const; + + /// \brief Get a set of node UUIDs for subscribers in this wrapper that + /// match the topic and message type criteria. + /// \param[in] _fullyQualifiedTopic Fully-qualified topic name that the + /// subscribers must be listening to. + /// \param[in] _msgTypeName Name of the message type that the + /// subscribers must be listening for. + /// \return The node UUIDs of all subscribers that match the criteria + public: std::vector NodeUuids( + const std::string &_fullyQualifiedTopic, + const std::string &_msgTypeName) const; + + /// \brief Remove the handlers for the given topic name that belong to + /// a specific node. + /// \param[in] _fullyQualifiedTopic The fully-qualified name of the + /// topic whose subscribers should be removed. + /// \param[in] _nUuid The UUID of the node whose subscribers should be + /// removed. + /// \return True if at least one subscriber was removed. + public: bool RemoveHandlersForNode( + const std::string &_fullyQualifiedTopic, + const std::string &_nUuid); + + /// \brief Remove one handler for the given topic name that belong to + /// a specific node. + /// \param[in] _fullyQualifiedTopic The fully-qualified name of the + /// topic whose subscribers should be removed. + /// \param[in] _nUuid The UUID of the node whose subscribers should be + /// removed. + /// \param[in] _hUuid The UUID of the handler to remove. + /// \return True if the subscriber was removed. + public: bool RemoveHandler( + const std::string &_fullyQualifiedTopic, + const std::string &_nUuid, + const std::string &_hUuid); + + /// \brief Convert all the HandlerStorages into a vector of publishers. + /// \param[in] _addr The pub/sub address. + /// \param[in] _pUuid The process UUID. + /// \return The vector of message publishers. + public: std::vector Convert(const std::string &_addr, + const std::string &_pUuid); + + /// \brief Normal local subscriptions. + public: HandlerStorage normal; + + /// \brief Raw local subscriptions. Keeping these separate from + /// localSubscriptions allows us to avoid an unnecessary deserialization + /// followed by an immediate reserialization. + public: HandlerStorage raw; + }; + + public: HandlerWrapper localSubscribers; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -510,39 +508,38 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Service call repliers. - public: HandlerStorage repliers; + /// \brief Service call repliers. + public: HandlerStorage repliers; - /// \brief Pending service call requests. - public: HandlerStorage requests; + /// \brief Pending service call requests. + public: HandlerStorage requests; - /// \brief Print activity to stdout. - public: int verbose; + /// \brief Print activity to stdout. + public: int verbose; - /// \brief My pub/sub address. - public: std::string myAddress; + /// \brief My pub/sub address. + public: std::string myAddress; - /// \brief My pub/sub control address. - public: std::string myControlAddress; + /// \brief My pub/sub control address. + public: std::string myControlAddress; - /// \brief My requester service call address. - public: std::string myRequesterAddress; + /// \brief My requester service call address. + public: std::string myRequesterAddress; - /// \brief My replier service call address. - public: std::string myReplierAddress; + /// \brief My replier service call address. + public: std::string myReplierAddress; - /// \brief IP address of this host. - public: std::string hostAddr; + /// \brief IP address of this host. + public: std::string hostAddr; - /// \brief Internal data pointer. - private: std::unique_ptr dataPtr; + /// \brief Internal data pointer. + private: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - private: friend Node; - private: friend NodePrivate; - }; - } + private: friend Node; + private: friend NodePrivate; + }; } } #endif diff --git a/include/gz/transport/Publisher.hh b/include/gz/transport/Publisher.hh index ba18c16ed..faf317db7 100644 --- a/include/gz/transport/Publisher.hh +++ b/include/gz/transport/Publisher.hh @@ -27,124 +27,122 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + + /// \class Publisher Publisher.hh + /// gz/transport/Publisher.hh + /// \brief This class stores all the information about a publisher. + /// It stores the topic name that publishes, addresses, UUIDs, scope, etc. + class GZ_TRANSPORT_VISIBLE Publisher { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - - /// \class Publisher Publisher.hh - /// gz/transport/Publisher.hh - /// \brief This class stores all the information about a publisher. - /// It stores the topic name that publishes, addresses, UUIDs, scope, etc. - class GZ_TRANSPORT_VISIBLE Publisher + /// \brief Default constructor. + public: Publisher() = default; + + /// \brief Constructor. + /// \param[in] _topic Topic name. + /// \param[in] _addr ZeroMQ address. + /// \param[in] _pUuid Process UUID. + /// \param[in] _nUuid node UUID. + /// \param[in] _opts The advertise options. + public: Publisher(const std::string &_topic, + const std::string &_addr, + const std::string &_pUuid, + const std::string &_nUuid, + const AdvertiseOptions &_opts); + + /// \brief Destructor. + public: virtual ~Publisher() = default; + + /// \brief Get the topic published by this publisher. + /// \return Topic name. + /// \sa SetTopic. + public: std::string Topic() const; + + /// \brief Get the ZeroMQ address of the publisher. + /// \return ZeroMQ address. + /// \sa SetAddr. + public: std::string Addr() const; + + /// \brief Get the process UUID of the publisher. + /// return Process UUID. + /// \sa SetPUuid. + public: std::string PUuid() const; + + /// \brief Get the node UUID of the publisher. + /// \return Node UUID. + /// \sa SetNUuid. + public: std::string NUuid() const; + + /// \brief Get the advertised options. + /// \return The advertised options. + /// \sa SetOptions. + public: virtual const AdvertiseOptions &Options() const; + + /// \brief Set the topic name published by this publisher. + /// \param[in] _topic New topic name. + /// \sa Topic. + public: void SetTopic(const std::string &_topic); + + /// \brief Set ZeroMQ address of the publisher. + /// \param[in] _addr New address. + /// \sa Addr. + public: void SetAddr(const std::string &_addr); + + /// \brief Set the process UUID of the publisher. + /// \param[in] _pUuid New process UUID. + /// \sa PUuid. + public: void SetPUuid(const std::string &_pUuid); + + /// \brief Set the node UUID of the publisher. + /// \param[in] _nUuid New node UUID. + /// \sa NUuid. + public: void SetNUuid(const std::string &_nUuid); + + /// \brief Set the advertised options. + /// \param[in] _opts New advertised options. + /// \sa Options. + public: void SetOptions(const AdvertiseOptions &_opts); + + /// \brief Populate a discovery message. + /// \param[in] _msg Message to fill. + public: virtual void FillDiscovery(msgs::Discovery &_msg) const; + + /// \brief Set data from a discovery message. + /// \param[in] _msg Discovery message. + public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); + + /// \brief Equality operator. This function checks if the given + /// publisher has identical Topic, Addr, PUuid, NUuid, and Scope + /// strings to this object. + /// \param[in] _pub The publisher to compare against. + /// \return True if this object matches the provided object. + public: bool operator==(const Publisher &_pub) const; + + /// \brief Inequality operator. This function checks if the given + /// publisher does not have identical Topic, Addr, PUuid, NUuid, and Scope + /// strings to this object. + /// \param[in] _pub The publisher to compare against. + /// \return True if this object does not match the provided object. + public: bool operator!=(const Publisher &_pub) const; + + /// \brief Stream insertion operator. + /// \param[out] _out The output stream. + /// \param[in] _msg Publisher to write to the stream. + public: friend std::ostream &operator<<(std::ostream &_out, + const Publisher &_msg) { - /// \brief Default constructor. - public: Publisher() = default; - - /// \brief Constructor. - /// \param[in] _topic Topic name. - /// \param[in] _addr ZeroMQ address. - /// \param[in] _pUuid Process UUID. - /// \param[in] _nUuid node UUID. - /// \param[in] _opts The advertise options. - public: Publisher(const std::string &_topic, - const std::string &_addr, - const std::string &_pUuid, - const std::string &_nUuid, - const AdvertiseOptions &_opts); - - /// \brief Destructor. - public: virtual ~Publisher() = default; - - /// \brief Get the topic published by this publisher. - /// \return Topic name. - /// \sa SetTopic. - public: std::string Topic() const; - - /// \brief Get the ZeroMQ address of the publisher. - /// \return ZeroMQ address. - /// \sa SetAddr. - public: std::string Addr() const; - - /// \brief Get the process UUID of the publisher. - /// return Process UUID. - /// \sa SetPUuid. - public: std::string PUuid() const; - - /// \brief Get the node UUID of the publisher. - /// \return Node UUID. - /// \sa SetNUuid. - public: std::string NUuid() const; - - /// \brief Get the advertised options. - /// \return The advertised options. - /// \sa SetOptions. - public: virtual const AdvertiseOptions &Options() const; - - /// \brief Set the topic name published by this publisher. - /// \param[in] _topic New topic name. - /// \sa Topic. - public: void SetTopic(const std::string &_topic); - - /// \brief Set ZeroMQ address of the publisher. - /// \param[in] _addr New address. - /// \sa Addr. - public: void SetAddr(const std::string &_addr); - - /// \brief Set the process UUID of the publisher. - /// \param[in] _pUuid New process UUID. - /// \sa PUuid. - public: void SetPUuid(const std::string &_pUuid); - - /// \brief Set the node UUID of the publisher. - /// \param[in] _nUuid New node UUID. - /// \sa NUuid. - public: void SetNUuid(const std::string &_nUuid); - - /// \brief Set the advertised options. - /// \param[in] _opts New advertised options. - /// \sa Options. - public: void SetOptions(const AdvertiseOptions &_opts); - - /// \brief Populate a discovery message. - /// \param[in] _msg Message to fill. - public: virtual void FillDiscovery(msgs::Discovery &_msg) const; - - /// \brief Set data from a discovery message. - /// \param[in] _msg Discovery message. - public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); - - /// \brief Equality operator. This function checks if the given - /// publisher has identical Topic, Addr, PUuid, NUuid, and Scope - /// strings to this object. - /// \param[in] _pub The publisher to compare against. - /// \return True if this object matches the provided object. - public: bool operator==(const Publisher &_pub) const; - - /// \brief Inequality operator. This function checks if the given - /// publisher does not have identical Topic, Addr, PUuid, NUuid, and Scope - /// strings to this object. - /// \param[in] _pub The publisher to compare against. - /// \return True if this object does not match the provided object. - public: bool operator!=(const Publisher &_pub) const; - - /// \brief Stream insertion operator. - /// \param[out] _out The output stream. - /// \param[in] _msg Publisher to write to the stream. - public: friend std::ostream &operator<<(std::ostream &_out, - const Publisher &_msg) - { - _out << "Publisher:" << std::endl - << "\tTopic: [" << _msg.Topic() << "]" << std::endl - << "\tAddress: " << _msg.Addr() << std::endl - << "\tProcess UUID: " << _msg.PUuid() << std::endl - << "\tNode UUID: " << _msg.NUuid() << std::endl - << _msg.Options(); - - return _out; - } + _out << "Publisher:" << std::endl + << "\tTopic: [" << _msg.Topic() << "]" << std::endl + << "\tAddress: " << _msg.Addr() << std::endl + << "\tProcess UUID: " << _msg.PUuid() << std::endl + << "\tNode UUID: " << _msg.NUuid() << std::endl + << _msg.Options(); + + return _out; + } #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -152,121 +150,121 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Topic name. - protected: std::string topic; + /// \brief Topic name. + protected: std::string topic; - /// \brief ZeroMQ address of the publisher. - protected: std::string addr; + /// \brief ZeroMQ address of the publisher. + protected: std::string addr; - /// \brief Process UUID of the publisher. - protected: std::string pUuid; + /// \brief Process UUID of the publisher. + protected: std::string pUuid; - /// \brief Node UUID of the publisher. - protected: std::string nUuid; + /// \brief Node UUID of the publisher. + protected: std::string nUuid; #ifdef _WIN32 #pragma warning(pop) #endif - /// \brief Advertised options. - /// This member is not used when we have a derived publisher. - private: AdvertiseOptions opts; - }; + /// \brief Advertised options. + /// This member is not used when we have a derived publisher. + private: AdvertiseOptions opts; + }; - /// \class MessagePublisher Publisher.hh - /// gz/transport/Publisher.hh - /// \brief This class stores all the information about a message publisher. - class GZ_TRANSPORT_VISIBLE MessagePublisher : public Publisher + /// \class MessagePublisher Publisher.hh + /// gz/transport/Publisher.hh + /// \brief This class stores all the information about a message publisher. + class GZ_TRANSPORT_VISIBLE MessagePublisher : public Publisher + { + /// \brief Default constructor. + public: MessagePublisher() = default; + + /// \brief Constructor. + /// \param[in] _topic Topic name. + /// \param[in] _addr ZeroMQ address. + /// \param[in] _ctrl ZeroMQ control address. + /// \param[in] _pUuid Process UUID. + /// \param[in] _nUuid node UUID. + /// \param[in] _msgTypeName Message type advertised by this publisher. + /// \param[in] _opts Advertise options. + public: explicit MessagePublisher(const std::string &_topic, + const std::string &_addr, + const std::string &_ctrl, + const std::string &_pUuid, + const std::string &_nUuid, + const std::string &_msgTypeName, + const AdvertiseMessageOptions &_opts); + + /// \brief Destructor. + public: virtual ~MessagePublisher() = default; + + /// \brief Get the ZeroMQ control address. This address is used by the + /// subscribers to notify the publisher about the new subscription. + /// \return ZeroMQ control address of the publisher. + /// \sa SetCtrl. + public: std::string Ctrl() const; + + /// \brief Set the ZeroMQ control address of the publisher. + /// \param[in] _ctrl New control address. + /// \sa Ctrl. + public: void SetCtrl(const std::string &_ctrl); + + /// \brief Get the message type advertised by this publisher. + /// \return Message type. + public: std::string MsgTypeName() const; + + /// \brief Set the message type advertised by this publisher. + /// \param[in] _msgTypeName New message type. + /// \sa MsgTypeName. + public: void SetMsgTypeName(const std::string &_msgTypeName); + + /// \brief Get the advertised options. + /// \return The advertised options. + /// \sa SetOptions. + public: virtual const AdvertiseMessageOptions &Options() const; + + /// \brief Set the advertised options. + /// \param[in] _opts New advertised options. + /// \sa Options. + public: void SetOptions(const AdvertiseMessageOptions &_opts); + + /// \brief Populate a discovery message. + /// \param[in] _msg Message to fill. + public: virtual void FillDiscovery(msgs::Discovery &_msg) const final; + + /// \brief Set data from a discovery message. + /// \param[in] _msg Discovery message. + public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); + + /// \brief Stream insertion operator. + /// \param[out] _out The output stream. + /// \param[in] _msg MessagePublisher to write to the stream. + public: friend std::ostream &operator<<(std::ostream &_out, + const MessagePublisher &_msg) { - /// \brief Default constructor. - public: MessagePublisher() = default; - - /// \brief Constructor. - /// \param[in] _topic Topic name. - /// \param[in] _addr ZeroMQ address. - /// \param[in] _ctrl ZeroMQ control address. - /// \param[in] _pUuid Process UUID. - /// \param[in] _nUuid node UUID. - /// \param[in] _msgTypeName Message type advertised by this publisher. - /// \param[in] _opts Advertise options. - public: explicit MessagePublisher(const std::string &_topic, - const std::string &_addr, - const std::string &_ctrl, - const std::string &_pUuid, - const std::string &_nUuid, - const std::string &_msgTypeName, - const AdvertiseMessageOptions &_opts); - - /// \brief Destructor. - public: virtual ~MessagePublisher() = default; - - /// \brief Get the ZeroMQ control address. This address is used by the - /// subscribers to notify the publisher about the new subscription. - /// \return ZeroMQ control address of the publisher. - /// \sa SetCtrl. - public: std::string Ctrl() const; - - /// \brief Set the ZeroMQ control address of the publisher. - /// \param[in] _ctrl New control address. - /// \sa Ctrl. - public: void SetCtrl(const std::string &_ctrl); - - /// \brief Get the message type advertised by this publisher. - /// \return Message type. - public: std::string MsgTypeName() const; - - /// \brief Set the message type advertised by this publisher. - /// \param[in] _msgTypeName New message type. - /// \sa MsgTypeName. - public: void SetMsgTypeName(const std::string &_msgTypeName); - - /// \brief Get the advertised options. - /// \return The advertised options. - /// \sa SetOptions. - public: virtual const AdvertiseMessageOptions &Options() const; - - /// \brief Set the advertised options. - /// \param[in] _opts New advertised options. - /// \sa Options. - public: void SetOptions(const AdvertiseMessageOptions &_opts); - - /// \brief Populate a discovery message. - /// \param[in] _msg Message to fill. - public: virtual void FillDiscovery(msgs::Discovery &_msg) const final; - - /// \brief Set data from a discovery message. - /// \param[in] _msg Discovery message. - public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); - - /// \brief Stream insertion operator. - /// \param[out] _out The output stream. - /// \param[in] _msg MessagePublisher to write to the stream. - public: friend std::ostream &operator<<(std::ostream &_out, - const MessagePublisher &_msg) - { - _out << "Publisher:" << std::endl - << "\tTopic: [" << _msg.Topic() << "]" << std::endl - << "\tAddress: " << _msg.Addr() << std::endl - << "\tProcess UUID: " << _msg.PUuid() << std::endl - << "\tNode UUID: " << _msg.NUuid() << std::endl - << "\tControl address: " << _msg.Ctrl() << std::endl - << "\tMessage type: " << _msg.MsgTypeName() << std::endl - << _msg.Options(); - return _out; - } - - /// \brief Equality operator. This function checks if the given - /// message publisher has identical Topic, Addr, PUuid, NUuid, Scope, - /// Ctrl, and MsgTypeName strings to this object. - /// \param[in] _pub The message publisher to compare against. - /// \return True if this object matches the provided object. - public: bool operator==(const MessagePublisher &_pub) const; - - /// \brief Inequality operator. This function checks if the given - /// message publisher does not have identical Topic, Addr, PUuid, NUuid, - /// Scope, Ctrl, and MsgTypeName strings to this object. - /// \param[in] _pub The message publisher to compare against. - /// \return True if this object does not match the provided object. - public: bool operator!=(const MessagePublisher &_pub) const; + _out << "Publisher:" << std::endl + << "\tTopic: [" << _msg.Topic() << "]" << std::endl + << "\tAddress: " << _msg.Addr() << std::endl + << "\tProcess UUID: " << _msg.PUuid() << std::endl + << "\tNode UUID: " << _msg.NUuid() << std::endl + << "\tControl address: " << _msg.Ctrl() << std::endl + << "\tMessage type: " << _msg.MsgTypeName() << std::endl + << _msg.Options(); + return _out; + } + + /// \brief Equality operator. This function checks if the given + /// message publisher has identical Topic, Addr, PUuid, NUuid, Scope, + /// Ctrl, and MsgTypeName strings to this object. + /// \param[in] _pub The message publisher to compare against. + /// \return True if this object matches the provided object. + public: bool operator==(const MessagePublisher &_pub) const; + + /// \brief Inequality operator. This function checks if the given + /// message publisher does not have identical Topic, Addr, PUuid, NUuid, + /// Scope, Ctrl, and MsgTypeName strings to this object. + /// \param[in] _pub The message publisher to compare against. + /// \return True if this object does not match the provided object. + public: bool operator!=(const MessagePublisher &_pub) const; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -274,129 +272,129 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief ZeroMQ control address of the publisher. - private: std::string ctrl; + /// \brief ZeroMQ control address of the publisher. + private: std::string ctrl; - /// \brief Message type advertised by this publisher. - private: std::string msgTypeName; + /// \brief Message type advertised by this publisher. + private: std::string msgTypeName; #ifdef _WIN32 #pragma warning(pop) #endif - /// \brief Advertise options (e.g.: msgsPerSec). - private: AdvertiseMessageOptions msgOpts; - }; + /// \brief Advertise options (e.g.: msgsPerSec). + private: AdvertiseMessageOptions msgOpts; + }; - /// \class ServicePublisher Publisher.hh - /// gz/transport/Publisher.hh - /// \brief This class stores all the information about a service publisher. - class GZ_TRANSPORT_VISIBLE ServicePublisher : public Publisher + /// \class ServicePublisher Publisher.hh + /// gz/transport/Publisher.hh + /// \brief This class stores all the information about a service publisher. + class GZ_TRANSPORT_VISIBLE ServicePublisher : public Publisher + { + /// \brief Default constructor. + public: ServicePublisher() = default; + + /// \brief Constructor. + /// \param[in] _topic Topic name. + /// \param[in] _addr ZeroMQ address. + /// \param[in] _id ZeroMQ socket ID. + /// \param[in] _pUuid Process UUID. + /// \param[in] _nUuid node UUID. + /// \param[in] _reqType Message type used in the service request. + /// \param[in] _repType Message type used in the service response. + /// \param[in] _opts Advertise options. + public: ServicePublisher(const std::string &_topic, + const std::string &_addr, + const std::string &_id, + const std::string &_pUuid, + const std::string &_nUuid, + const std::string &_reqType, + const std::string &_repType, + const AdvertiseServiceOptions &_opts); + + /// \brief Destructor. + public: virtual ~ServicePublisher() = default; + + /// \brief Get the ZeroMQ socket ID used by this publisher. + /// \return The socket ID. + /// \sa SetSocketId. + public: std::string SocketId() const; + + /// \brief Set the ZeroMQ socket ID for this publisher. + /// \param[in] _socketId New socket ID. + /// \sa SocketId. + public: void SetSocketId(const std::string &_socketId); + + /// \brief Get the name of the request's protobuf message advertised. + /// \return The protobuf message type. + /// \sa SetReqTypeName. + public: std::string ReqTypeName() const; + + /// \brief Get the name of the response's protobuf message advertised. + /// \return The protobuf message type. + /// \sa SetRepTypeName. + public: std::string RepTypeName() const; + + /// \brief Set the name of the request's protobuf message advertised. + /// \param[in] _reqTypeName The protobuf message type. + /// \sa ReqTypeName. + public: void SetReqTypeName(const std::string &_reqTypeName); + + /// \brief Set the name of the response's protobuf message advertised. + /// \param[in] _repTypeName The protobuf message type. + /// \sa RepTypeName. + public: void SetRepTypeName(const std::string &_repTypeName); + + /// \brief Get the advertised options. + /// \return The advertised options. + /// \sa SetOptions. + public: virtual const AdvertiseServiceOptions& Options() const; + + /// \brief Set the advertised options. + /// \param[in] _opts New advertised options. + /// \sa Options. + public: void SetOptions(const AdvertiseServiceOptions &_opts); + + /// \brief Populate a discovery message. + /// \param[in] _msg Message to fill. + public: virtual void FillDiscovery(msgs::Discovery &_msg) const final; + + /// \brief Populate a discovery message. + /// \brief Set data from a discovery message. + /// \param[in] _msg Discovery message. + public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); + + /// \brief Stream insertion operator. + /// \param[out] _out The output stream. + /// \param[in] _msg ServicePublisher to write to the stream. + public: friend std::ostream &operator<<(std::ostream &_out, + const ServicePublisher &_msg) { - /// \brief Default constructor. - public: ServicePublisher() = default; - - /// \brief Constructor. - /// \param[in] _topic Topic name. - /// \param[in] _addr ZeroMQ address. - /// \param[in] _id ZeroMQ socket ID. - /// \param[in] _pUuid Process UUID. - /// \param[in] _nUuid node UUID. - /// \param[in] _reqType Message type used in the service request. - /// \param[in] _repType Message type used in the service response. - /// \param[in] _opts Advertise options. - public: ServicePublisher(const std::string &_topic, - const std::string &_addr, - const std::string &_id, - const std::string &_pUuid, - const std::string &_nUuid, - const std::string &_reqType, - const std::string &_repType, - const AdvertiseServiceOptions &_opts); - - /// \brief Destructor. - public: virtual ~ServicePublisher() = default; - - /// \brief Get the ZeroMQ socket ID used by this publisher. - /// \return The socket ID. - /// \sa SetSocketId. - public: std::string SocketId() const; - - /// \brief Set the ZeroMQ socket ID for this publisher. - /// \param[in] _socketId New socket ID. - /// \sa SocketId. - public: void SetSocketId(const std::string &_socketId); - - /// \brief Get the name of the request's protobuf message advertised. - /// \return The protobuf message type. - /// \sa SetReqTypeName. - public: std::string ReqTypeName() const; - - /// \brief Get the name of the response's protobuf message advertised. - /// \return The protobuf message type. - /// \sa SetRepTypeName. - public: std::string RepTypeName() const; - - /// \brief Set the name of the request's protobuf message advertised. - /// \param[in] _reqTypeName The protobuf message type. - /// \sa ReqTypeName. - public: void SetReqTypeName(const std::string &_reqTypeName); - - /// \brief Set the name of the response's protobuf message advertised. - /// \param[in] _repTypeName The protobuf message type. - /// \sa RepTypeName. - public: void SetRepTypeName(const std::string &_repTypeName); - - /// \brief Get the advertised options. - /// \return The advertised options. - /// \sa SetOptions. - public: virtual const AdvertiseServiceOptions& Options() const; - - /// \brief Set the advertised options. - /// \param[in] _opts New advertised options. - /// \sa Options. - public: void SetOptions(const AdvertiseServiceOptions &_opts); - - /// \brief Populate a discovery message. - /// \param[in] _msg Message to fill. - public: virtual void FillDiscovery(msgs::Discovery &_msg) const final; - - /// \brief Populate a discovery message. - /// \brief Set data from a discovery message. - /// \param[in] _msg Discovery message. - public: virtual void SetFromDiscovery(const msgs::Discovery &_msg); - - /// \brief Stream insertion operator. - /// \param[out] _out The output stream. - /// \param[in] _msg ServicePublisher to write to the stream. - public: friend std::ostream &operator<<(std::ostream &_out, - const ServicePublisher &_msg) - { - _out << "Publisher:" << std::endl - << "\tTopic: [" << _msg.Topic() << "]" << std::endl - << "\tAddress: " << _msg.Addr() << std::endl - << "\tProcess UUID: " << _msg.PUuid() << std::endl - << "\tNode UUID: " << _msg.NUuid() << std::endl - << "\tSocket ID: " << _msg.SocketId() << std::endl - << "\tRequest type: " << _msg.ReqTypeName() << std::endl - << "\tResponse type: " << _msg.RepTypeName() << std::endl - << _msg.Options(); - - return _out; - } - - /// \brief Equality operator. This function checks if the given - /// service has identical Topic, Addr, PUuid, NUuid, Scope, - /// SocketId, ReqTypeName, RepTypeName strings to this object. - /// \param[in] _srv The service publisher to compare against. - /// \return True if this object matches the provided object. - public: bool operator==(const ServicePublisher &_srv) const; - - /// \brief Inequality operator. This function checks if the given - /// service does not have identical Topic, Addr, PUuid, NUuid, Scope, - /// SocketId, ReqTypeName, RepTypeName strings to this object. - /// \param[in] _srv The service publisher to compare against. - /// \return True if this object does not match the provided object. - public: bool operator!=(const ServicePublisher &_srv) const; + _out << "Publisher:" << std::endl + << "\tTopic: [" << _msg.Topic() << "]" << std::endl + << "\tAddress: " << _msg.Addr() << std::endl + << "\tProcess UUID: " << _msg.PUuid() << std::endl + << "\tNode UUID: " << _msg.NUuid() << std::endl + << "\tSocket ID: " << _msg.SocketId() << std::endl + << "\tRequest type: " << _msg.ReqTypeName() << std::endl + << "\tResponse type: " << _msg.RepTypeName() << std::endl + << _msg.Options(); + + return _out; + } + + /// \brief Equality operator. This function checks if the given + /// service has identical Topic, Addr, PUuid, NUuid, Scope, + /// SocketId, ReqTypeName, RepTypeName strings to this object. + /// \param[in] _srv The service publisher to compare against. + /// \return True if this object matches the provided object. + public: bool operator==(const ServicePublisher &_srv) const; + + /// \brief Inequality operator. This function checks if the given + /// service does not have identical Topic, Addr, PUuid, NUuid, Scope, + /// SocketId, ReqTypeName, RepTypeName strings to this object. + /// \param[in] _srv The service publisher to compare against. + /// \return True if this object does not match the provided object. + public: bool operator!=(const ServicePublisher &_srv) const; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -404,22 +402,21 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief ZeroMQ socket ID used by this publisher. - private: std::string socketId; + /// \brief ZeroMQ socket ID used by this publisher. + private: std::string socketId; - /// \brief The name of the request's protobuf message advertised. - private: std::string reqTypeName; + /// \brief The name of the request's protobuf message advertised. + private: std::string reqTypeName; - /// \brief The name of the response's protobuf message advertised. - private: std::string repTypeName; + /// \brief The name of the response's protobuf message advertised. + private: std::string repTypeName; #ifdef _WIN32 #pragma warning(pop) #endif - /// \brief Advertise options. - private: AdvertiseServiceOptions srvOpts; - }; - } + /// \brief Advertise options. + private: AdvertiseServiceOptions srvOpts; + }; } } diff --git a/include/gz/transport/RepHandler.hh b/include/gz/transport/RepHandler.hh index ca1c578de..d3fcad1e3 100644 --- a/include/gz/transport/RepHandler.hh +++ b/include/gz/transport/RepHandler.hh @@ -41,56 +41,54 @@ #include "gz/transport/TransportTypes.hh" #include "gz/transport/Uuid.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class IRepHandler RepHandler.hh gz/transport/RepHandler.hh + /// \brief Interface class used to manage a replier handler. + class GZ_TRANSPORT_VISIBLE IRepHandler { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class IRepHandler RepHandler.hh gz/transport/RepHandler.hh - /// \brief Interface class used to manage a replier handler. - class GZ_TRANSPORT_VISIBLE IRepHandler + /// \brief Constructor. + public: IRepHandler() + : hUuid(Uuid().ToString()) { - /// \brief Constructor. - public: IRepHandler() - : hUuid(Uuid().ToString()) - { - } + } - /// \brief Destructor. - public: virtual ~IRepHandler() = default; + /// \brief Destructor. + public: virtual ~IRepHandler() = default; - /// \brief Executes the local callback registered for this handler. - /// \param[in] _msgReq Input parameter (Protobuf message). - /// \param[out] _msgRep Output parameter (Protobuf message). - /// \return Service call result. - public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq, - transport::ProtoMsg &_msgRep) = 0; + /// \brief Executes the local callback registered for this handler. + /// \param[in] _msgReq Input parameter (Protobuf message). + /// \param[out] _msgRep Output parameter (Protobuf message). + /// \return Service call result. + public: virtual bool RunLocalCallback(const transport::ProtoMsg &_msgReq, + transport::ProtoMsg &_msgRep) = 0; - /// \brief Executes the callback registered for this handler. - /// \param[in] _req Serialized data received. The data will be used - /// to compose a specific protobuf message and will be passed to the - /// callback function. - /// \param[out] _rep Out parameter with the data serialized. - /// \return Service call result. - public: virtual bool RunCallback(const std::string &_req, - std::string &_rep) = 0; + /// \brief Executes the callback registered for this handler. + /// \param[in] _req Serialized data received. The data will be used + /// to compose a specific protobuf message and will be passed to the + /// callback function. + /// \param[out] _rep Out parameter with the data serialized. + /// \return Service call result. + public: virtual bool RunCallback(const std::string &_req, + std::string &_rep) = 0; - /// \brief Get the unique UUID of this handler. - /// \return a string representation of the handler UUID. - public: std::string HandlerUuid() const - { - return this->hUuid; - } + /// \brief Get the unique UUID of this handler. + /// \return a string representation of the handler UUID. + public: std::string HandlerUuid() const + { + return this->hUuid; + } - /// \brief Get the message type name used in the service request. - /// \return Message type name. - public: virtual std::string ReqTypeName() const = 0; + /// \brief Get the message type name used in the service request. + /// \return Message type name. + public: virtual std::string ReqTypeName() const = 0; - /// \brief Get the message type name used in the service response. - /// \return Message type name. - public: virtual std::string RepTypeName() const = 0; + /// \brief Get the message type name used in the service response. + /// \return Message type name. + public: virtual std::string RepTypeName() const = 0; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -98,176 +96,175 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Unique handler's UUID. - protected: std::string hUuid; + /// \brief Unique handler's UUID. + protected: std::string hUuid; #ifdef _WIN32 #pragma warning(pop) #endif - }; + }; + + /// \class RepHandler RepHandler.hh + /// \brief It creates a service reply handler for a pair of protobuf + /// messages containing the request parameters and the response. + /// 'Req' is the protobuf message type containing the input parameters of + // the service call. 'Rep' is the protobuf message type that will be filled + /// with the service response. + template class RepHandler + : public IRepHandler + { + // Documentation inherited. + public: RepHandler() = default; - /// \class RepHandler RepHandler.hh - /// \brief It creates a service reply handler for a pair of protobuf - /// messages containing the request parameters and the response. - /// 'Req' is the protobuf message type containing the input parameters of - // the service call. 'Rep' is the protobuf message type that will be filled - /// with the service response. - template class RepHandler - : public IRepHandler + /// \brief Set the callback for this handler. + /// \param[in] _cb The callback with the following parameters: + /// * _req Protobuf message containing the service request params + /// * _rep Protobuf message containing the service response. + /// * Returns true when the service response is considered + /// successful or false otherwise. + public: void SetCallback( + const std::function &_cb) { - // Documentation inherited. - public: RepHandler() = default; + this->cb = _cb; + } - /// \brief Set the callback for this handler. - /// \param[in] _cb The callback with the following parameters: - /// * _req Protobuf message containing the service request params - /// * _rep Protobuf message containing the service response. - /// * Returns true when the service response is considered - /// successful or false otherwise. - public: void SetCallback( - const std::function &_cb) + // Documentation inherited. + public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq, + transport::ProtoMsg &_msgRep) + { + // Execute the callback (if existing) + if (!this->cb) { - this->cb = _cb; + std::cerr << "RepHandler::RunLocalCallback() error: " + << "Callback is NULL" << std::endl; + return false; } - // Documentation inherited. - public: bool RunLocalCallback(const transport::ProtoMsg &_msgReq, - transport::ProtoMsg &_msgRep) - { - // Execute the callback (if existing) - if (!this->cb) - { - std::cerr << "RepHandler::RunLocalCallback() error: " - << "Callback is NULL" << std::endl; - return false; - } - #if GOOGLE_PROTOBUF_VERSION >= 5028000 - const auto msgReq = - google::protobuf::DynamicCastMessage(&_msgReq); - auto msgRep = - google::protobuf::DynamicCastMessage(&_msgRep); + const auto msgReq = + google::protobuf::DynamicCastMessage(&_msgReq); + auto msgRep = + google::protobuf::DynamicCastMessage(&_msgRep); #elif GOOGLE_PROTOBUF_VERSION >= 4022000 - auto msgReq = - google::protobuf::internal::DownCast(&_msgReq); - auto msgRep = google::protobuf::internal::DownCast(&_msgRep); + auto msgReq = + google::protobuf::internal::DownCast(&_msgReq); + auto msgRep = google::protobuf::internal::DownCast(&_msgRep); #elif GOOGLE_PROTOBUF_VERSION > 2999999 - auto msgReq = google::protobuf::down_cast(&_msgReq); - auto msgRep = google::protobuf::down_cast(&_msgRep); + auto msgReq = google::protobuf::down_cast(&_msgReq); + auto msgRep = google::protobuf::down_cast(&_msgRep); #else - auto msgReq = - google::protobuf::internal::down_cast(&_msgReq); - auto msgRep = google::protobuf::internal::down_cast(&_msgRep); + auto msgReq = + google::protobuf::internal::down_cast(&_msgReq); + auto msgRep = google::protobuf::internal::down_cast(&_msgRep); #endif - // Verify the dynamically casted messages are valid - if (msgReq == nullptr || msgRep == nullptr) + // Verify the dynamically casted messages are valid + if (msgReq == nullptr || msgRep == nullptr) + { + if (msgReq == nullptr) { - if (msgReq == nullptr) + if (_msgReq.GetDescriptor() != nullptr) { - if (_msgReq.GetDescriptor() != nullptr) - { - std::cerr << "RepHandler::RunLocalCallback() error: " - << "Failed to cast the request of the type " - << _msgReq.GetDescriptor()->full_name() - << " to the specified type" << '\n'; - } - else - { - std::cerr << "RepHandler::RunLocalCallback() error: " - << "Failed to cast the request of an unknown type" - << " to the specified type" << '\n'; - } + std::cerr << "RepHandler::RunLocalCallback() error: " + << "Failed to cast the request of the type " + << _msgReq.GetDescriptor()->full_name() + << " to the specified type" << '\n'; } - if (msgRep == nullptr) + else { - if (_msgRep.GetDescriptor() != nullptr) - { - std::cerr << "RepHandler::RunLocalCallback() error: " - << "Failed to cast the response of the type " - << _msgRep.GetDescriptor()->full_name() - << " to the specified type" << '\n'; - } - else - { - std::cerr << "RepHandler::RunLocalCallback() error: " - << "Failed to cast the response of an unknown type" - << " to the specified type" << '\n'; - } + std::cerr << "RepHandler::RunLocalCallback() error: " + << "Failed to cast the request of an unknown type" + << " to the specified type" << '\n'; } - std::cerr.flush(); - return false; - } - - return this->cb(*msgReq, *msgRep); - } - - // Documentation inherited. - public: bool RunCallback(const std::string &_req, - std::string &_rep) - { - // Check if we have a callback registered. - if (!this->cb) - { - std::cerr << "RepHandler::RunCallback() error: " - << "Callback is NULL" << std::endl; - return false; } - - // Instantiate the specific protobuf message associated to this topic. - auto msgReq = this->CreateMsg(_req); - if (!msgReq) + if (msgRep == nullptr) { - return false; + if (_msgRep.GetDescriptor() != nullptr) + { + std::cerr << "RepHandler::RunLocalCallback() error: " + << "Failed to cast the response of the type " + << _msgRep.GetDescriptor()->full_name() + << " to the specified type" << '\n'; + } + else + { + std::cerr << "RepHandler::RunLocalCallback() error: " + << "Failed to cast the response of an unknown type" + << " to the specified type" << '\n'; + } } + std::cerr.flush(); + return false; + } - Rep msgRep; - if (!this->cb(*msgReq, msgRep)) - return false; - - if (!msgRep.SerializeToString(&_rep)) - { - std::cerr << "RepHandler::RunCallback(): Error serializing the " - << "response" << std::endl; - return false; - } + return this->cb(*msgReq, *msgRep); + } - return true; + // Documentation inherited. + public: bool RunCallback(const std::string &_req, + std::string &_rep) + { + // Check if we have a callback registered. + if (!this->cb) + { + std::cerr << "RepHandler::RunCallback() error: " + << "Callback is NULL" << std::endl; + return false; } - // Documentation inherited. - public: virtual std::string ReqTypeName() const + // Instantiate the specific protobuf message associated to this topic. + auto msgReq = this->CreateMsg(_req); + if (!msgReq) { - return std::string(Req().GetTypeName()); + return false; } - // Documentation inherited. - public: virtual std::string RepTypeName() const + Rep msgRep; + if (!this->cb(*msgReq, msgRep)) + return false; + + if (!msgRep.SerializeToString(&_rep)) { - return std::string(Rep().GetTypeName()); + std::cerr << "RepHandler::RunCallback(): Error serializing the " + << "response" << std::endl; + return false; } - /// \brief Create a specific protobuf message given its serialized data. - /// \param[in] _data The serialized data. - /// \return Pointer to the specific protobuf message. - private: std::shared_ptr CreateMsg(const std::string &_data) const - { - // Instantiate a specific protobuf message - auto msgPtr = std::make_shared(); + return true; + } - // Create the message using some serialized data - if (!msgPtr->ParseFromString(_data)) - { - std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed" - << std::endl; - } + // Documentation inherited. + public: virtual std::string ReqTypeName() const + { + return std::string(Req().GetTypeName()); + } + + // Documentation inherited. + public: virtual std::string RepTypeName() const + { + return std::string(Rep().GetTypeName()); + } + + /// \brief Create a specific protobuf message given its serialized data. + /// \param[in] _data The serialized data. + /// \return Pointer to the specific protobuf message. + private: std::shared_ptr CreateMsg(const std::string &_data) const + { + // Instantiate a specific protobuf message + auto msgPtr = std::make_shared(); - return msgPtr; + // Create the message using some serialized data + if (!msgPtr->ParseFromString(_data)) + { + std::cerr << "RepHandler::CreateMsg() error: ParseFromString failed" + << std::endl; } - /// \brief Callback to the function registered for this handler. - private: std::function cb; - }; + return msgPtr; } + + /// \brief Callback to the function registered for this handler. + private: std::function cb; + }; } } diff --git a/include/gz/transport/ReqHandler.hh b/include/gz/transport/ReqHandler.hh index df3404581..5fc26501c 100644 --- a/include/gz/transport/ReqHandler.hh +++ b/include/gz/transport/ReqHandler.hh @@ -37,114 +37,112 @@ #include "gz/transport/TransportTypes.hh" #include "gz/transport/Uuid.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class IReqHandler ReqHandler.hh gz/transport/ReqHandler.hh + /// \brief Interface class used to manage a request handler. + class GZ_TRANSPORT_VISIBLE IReqHandler { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class IReqHandler ReqHandler.hh gz/transport/ReqHandler.hh - /// \brief Interface class used to manage a request handler. - class GZ_TRANSPORT_VISIBLE IReqHandler + /// \brief Constructor. + /// \param[in] _nUuid UUID of the node registering the request handler. + public: explicit IReqHandler(const std::string &_nUuid) + : rep(""), + hUuid(Uuid().ToString()), + nUuid(_nUuid), + result(false), + requested(false), + repAvailable(false) { - /// \brief Constructor. - /// \param[in] _nUuid UUID of the node registering the request handler. - public: explicit IReqHandler(const std::string &_nUuid) - : rep(""), - hUuid(Uuid().ToString()), - nUuid(_nUuid), - result(false), - requested(false), - repAvailable(false) - { - } + } - /// \brief Destructor. - public: virtual ~IReqHandler() = default; - - /// \brief Executes the callback registered for this handler and notify - /// a potential requester waiting on a blocking call. - /// \param[in] _rep Serialized data containing the response coming from - /// the service call responser. - /// \param[in] _result Contains the result of the service call coming from - /// the service call responser. - public: virtual void NotifyResult(const std::string &_rep, - const bool _result) = 0; - - /// \brief Get the node UUID. - /// \return The string representation of the node UUID. - public: std::string NodeUuid() const - { - return this->nUuid; - } + /// \brief Destructor. + public: virtual ~IReqHandler() = default; + + /// \brief Executes the callback registered for this handler and notify + /// a potential requester waiting on a blocking call. + /// \param[in] _rep Serialized data containing the response coming from + /// the service call responser. + /// \param[in] _result Contains the result of the service call coming from + /// the service call responser. + public: virtual void NotifyResult(const std::string &_rep, + const bool _result) = 0; + + /// \brief Get the node UUID. + /// \return The string representation of the node UUID. + public: std::string NodeUuid() const + { + return this->nUuid; + } - /// \brief Get the service response as raw bytes. - /// \return The string containing the service response. - public: std::string Response() const - { - return this->rep; - } + /// \brief Get the service response as raw bytes. + /// \return The string containing the service response. + public: std::string Response() const + { + return this->rep; + } - /// \brief Get the result of the service response. - /// \return The boolean result. - public: bool Result() const - { - return this->result; - } + /// \brief Get the result of the service response. + /// \return The boolean result. + public: bool Result() const + { + return this->result; + } - /// \brief Returns if this service call request has already been requested - /// \return True when the service call has been requested. - public: bool Requested() const - { - return this->requested; - } + /// \brief Returns if this service call request has already been requested + /// \return True when the service call has been requested. + public: bool Requested() const + { + return this->requested; + } - /// \brief Mark the service call as requested (or not). - /// \param[in] _value true when you want to flag this REQ as requested. - public: void Requested(const bool _value) - { - this->requested = _value; - } + /// \brief Mark the service call as requested (or not). + /// \param[in] _value true when you want to flag this REQ as requested. + public: void Requested(const bool _value) + { + this->requested = _value; + } - /// \brief Serialize the Req protobuf message stored. - /// \param[out] _buffer The serialized data. - /// \return True if the serialization succeed or false otherwise. - public: virtual bool Serialize(std::string &_buffer) const = 0; + /// \brief Serialize the Req protobuf message stored. + /// \param[out] _buffer The serialized data. + /// \return True if the serialization succeed or false otherwise. + public: virtual bool Serialize(std::string &_buffer) const = 0; - /// \brief Returns the unique handler UUID. - /// \return The handler's UUID. - public: std::string HandlerUuid() const - { - return this->hUuid; - } + /// \brief Returns the unique handler UUID. + /// \return The handler's UUID. + public: std::string HandlerUuid() const + { + return this->hUuid; + } - /// \brief Block the current thread until the response to the - /// service request is available or until the timeout expires. - /// This method uses a condition variable to notify when the response is - /// available. - /// \param[in] _lock Lock used to protect the condition variable. - /// \param[in] _timeout Maximum waiting time in milliseconds. - /// \return True if the service call was executed or false otherwise. - public: template bool WaitUntil(Lock &_lock, - const unsigned int _timeout) - { - auto now = std::chrono::steady_clock::now(); - return this->condition.wait_until(_lock, - now + std::chrono::milliseconds(_timeout), - [this] - { - return this->repAvailable; - }); - } + /// \brief Block the current thread until the response to the + /// service request is available or until the timeout expires. + /// This method uses a condition variable to notify when the response is + /// available. + /// \param[in] _lock Lock used to protect the condition variable. + /// \param[in] _timeout Maximum waiting time in milliseconds. + /// \return True if the service call was executed or false otherwise. + public: template bool WaitUntil(Lock &_lock, + const unsigned int _timeout) + { + auto now = std::chrono::steady_clock::now(); + return this->condition.wait_until(_lock, + now + std::chrono::milliseconds(_timeout), + [this] + { + return this->repAvailable; + }); + } - /// \brief Get the message type name used in the service request. - /// \return Message type name. - public: virtual std::string ReqTypeName() const = 0; + /// \brief Get the message type name used in the service request. + /// \return Message type name. + public: virtual std::string ReqTypeName() const = 0; - /// \brief Get the message type name used in the service response. - /// \return Message type name. - public: virtual std::string RepTypeName() const = 0; + /// \brief Get the message type name used in the service response. + /// \return Message type name. + public: virtual std::string RepTypeName() const = 0; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -152,265 +150,264 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Condition variable used to wait until a service call REP is - /// available. - protected: std::condition_variable_any condition; + /// \brief Condition variable used to wait until a service call REP is + /// available. + protected: std::condition_variable_any condition; - /// \brief Stores the service response as raw bytes. - protected: std::string rep; + /// \brief Stores the service response as raw bytes. + protected: std::string rep; - /// \brief Unique handler's UUID. - protected: std::string hUuid; + /// \brief Unique handler's UUID. + protected: std::string hUuid; - /// \brief Node UUID. - private: std::string nUuid; + /// \brief Node UUID. + private: std::string nUuid; #ifdef _WIN32 #pragma warning(pop) #endif - /// \brief Stores the result of the service call. - protected: bool result; - - /// \brief When true, the REQ was already sent and the REP should be on - /// its way. Used to not resend the same REQ more than one time. - private: bool requested; - - /// \brief When there is a blocking service call request, the call can - /// be unlocked when a service call REP is available. This variable - /// captures if we have found a node that can satisfy our request. - public: bool repAvailable; - }; - - /// \class ReqHandler ReqHandler.hh - /// \brief It creates a reply handler for the specific protobuf - /// messages used. 'Req' is a protobuf message type containing the input - /// parameters of the service request. 'Rep' is a protobuf message type - /// that will be filled with the service response. - template class ReqHandler - : public IReqHandler + /// \brief Stores the result of the service call. + protected: bool result; + + /// \brief When true, the REQ was already sent and the REP should be on + /// its way. Used to not resend the same REQ more than one time. + private: bool requested; + + /// \brief When there is a blocking service call request, the call can + /// be unlocked when a service call REP is available. This variable + /// captures if we have found a node that can satisfy our request. + public: bool repAvailable; + }; + + /// \class ReqHandler ReqHandler.hh + /// \brief It creates a reply handler for the specific protobuf + /// messages used. 'Req' is a protobuf message type containing the input + /// parameters of the service request. 'Rep' is a protobuf message type + /// that will be filled with the service response. + template class ReqHandler + : public IReqHandler + { + // Documentation inherited. + public: explicit ReqHandler(const std::string &_nUuid) + : IReqHandler(_nUuid) { - // Documentation inherited. - public: explicit ReqHandler(const std::string &_nUuid) - : IReqHandler(_nUuid) - { - } + } - /// \brief Create a specific protobuf message given its serialized data. - /// \param[in] _data The serialized data. - /// \return Pointer to the specific protobuf message. - public: std::shared_ptr CreateMsg(const std::string &_data) const + /// \brief Create a specific protobuf message given its serialized data. + /// \param[in] _data The serialized data. + /// \return Pointer to the specific protobuf message. + public: std::shared_ptr CreateMsg(const std::string &_data) const + { + // Instantiate a specific protobuf message + auto msgPtr = std::make_shared(); + + // Create the message using some serialized data + if (!msgPtr->ParseFromString(_data)) { - // Instantiate a specific protobuf message - auto msgPtr = std::make_shared(); + std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed" + << std::endl; + } - // Create the message using some serialized data - if (!msgPtr->ParseFromString(_data)) - { - std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed" - << std::endl; - } + return msgPtr; + } - return msgPtr; - } + /// \brief Set the callback for this handler. + /// \param[in] _cb The callback with the following parameters: + /// * _rep Protobuf message containing the service response. + /// * _result True when the service request was successful or + /// false otherwise. + public: void SetCallback(const std::function &_cb) + { + this->cb = _cb; + } - /// \brief Set the callback for this handler. - /// \param[in] _cb The callback with the following parameters: - /// * _rep Protobuf message containing the service response. - /// * _result True when the service request was successful or - /// false otherwise. - public: void SetCallback(const std::function &_cb) + /// \brief Set the REQ protobuf message for this handler. + /// \param[in] _reqMsg Protobuf message containing the input parameters of + /// of the service request. + public: void SetMessage(const Req *_reqMsg) + { + if (!_reqMsg) { - this->cb = _cb; + std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl; + return; } - /// \brief Set the REQ protobuf message for this handler. - /// \param[in] _reqMsg Protobuf message containing the input parameters of - /// of the service request. - public: void SetMessage(const Req *_reqMsg) - { - if (!_reqMsg) - { - std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl; - return; - } + this->reqMsg.CopyFrom(*_reqMsg); + } - this->reqMsg.CopyFrom(*_reqMsg); - } + /// \brief This function is only used for compatibility with + /// SetResponse() when [REP = google::protobuf::Message]. + /// It shouldn't do anything. + /// \param[in] _repMsg Protobuf message containing the variable where + /// the result will be stored. + public: void SetResponse(const Rep *_repMsg) + { + (void)_repMsg; + } - /// \brief This function is only used for compatibility with - /// SetResponse() when [REP = google::protobuf::Message]. - /// It shouldn't do anything. - /// \param[in] _repMsg Protobuf message containing the variable where - /// the result will be stored. - public: void SetResponse(const Rep *_repMsg) + // Documentation inherited + public: bool Serialize(std::string &_buffer) const + { + if (!this->reqMsg.SerializeToString(&_buffer)) { - (void)_repMsg; + std::cerr << "ReqHandler::Serialize(): Error serializing the request" + << std::endl; + return false; } - // Documentation inherited - public: bool Serialize(std::string &_buffer) const + return true; + } + + // Documentation inherited. + public: void NotifyResult(const std::string &_rep, const bool _result) + { + // Execute the callback (if existing). + if (this->cb) { - if (!this->reqMsg.SerializeToString(&_buffer)) - { - std::cerr << "ReqHandler::Serialize(): Error serializing the request" - << std::endl; - return false; - } + // Instantiate the specific protobuf message associated to this topic. + auto msg = this->CreateMsg(_rep); - return true; + this->cb(*msg, _result); } - - // Documentation inherited. - public: void NotifyResult(const std::string &_rep, const bool _result) + else { - // Execute the callback (if existing). - if (this->cb) - { - // Instantiate the specific protobuf message associated to this topic. - auto msg = this->CreateMsg(_rep); + this->rep = _rep; + this->result = _result; + } - this->cb(*msg, _result); - } - else - { - this->rep = _rep; - this->result = _result; - } + this->repAvailable = true; + this->condition.notify_one(); + } - this->repAvailable = true; - this->condition.notify_one(); - } + // Documentation inherited. + public: virtual std::string ReqTypeName() const + { + return std::string(Req().GetTypeName()); + } - // Documentation inherited. - public: virtual std::string ReqTypeName() const - { - return std::string(Req().GetTypeName()); - } + // Documentation inherited. + public: virtual std::string RepTypeName() const + { + return std::string(Rep().GetTypeName()); + } - // Documentation inherited. - public: virtual std::string RepTypeName() const - { - return std::string(Rep().GetTypeName()); - } + /// \brief Protobuf message containing the request's parameters. + private: Req reqMsg; + + /// \brief Callback to the function registered for this handler with the + /// following parameters: + /// \param[in] _rep Protobuf message containing the service response. + /// \param[in] _result True when the service request was successful or + /// false otherwise. + private: std::function cb; + }; + + /// \class ReqHandler ReqHandler.hh + /// \brief Template specialization for google::protobuf::Message. + /// This is only used by some gz command line tools. + template <> class ReqHandler + : public IReqHandler + { + // Documentation inherited. + public: explicit ReqHandler(const std::string &_nUuid) + : IReqHandler(_nUuid) + { + } - /// \brief Protobuf message containing the request's parameters. - private: Req reqMsg; - - /// \brief Callback to the function registered for this handler with the - /// following parameters: - /// \param[in] _rep Protobuf message containing the service response. - /// \param[in] _result True when the service request was successful or - /// false otherwise. - private: std::function cb; - }; - - /// \class ReqHandler ReqHandler.hh - /// \brief Template specialization for google::protobuf::Message. - /// This is only used by some gz command line tools. - template <> class ReqHandler - : public IReqHandler + /// \brief Set the REQ protobuf message for this handler. + /// \param[in] _reqMsg Protobuf message containing the input parameters of + /// of the service request. + public: void SetMessage(const google::protobuf::Message *_reqMsg) { - // Documentation inherited. - public: explicit ReqHandler(const std::string &_nUuid) - : IReqHandler(_nUuid) + if (!_reqMsg) { + std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl; + return; } - /// \brief Set the REQ protobuf message for this handler. - /// \param[in] _reqMsg Protobuf message containing the input parameters of - /// of the service request. - public: void SetMessage(const google::protobuf::Message *_reqMsg) - { - if (!_reqMsg) - { - std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl; - return; - } + this->reqMsg = _reqMsg->New(); + this->reqMsg->CopyFrom(*_reqMsg); + } - this->reqMsg = _reqMsg->New(); - this->reqMsg->CopyFrom(*_reqMsg); + /// \brief Set the REP protobuf message for this handler. + /// \param[in] _repMsg Protobuf message containing the variable where + /// the result will be stored. The only purpose of this function is to + /// store the type information of _repMsg. + public: void SetResponse(const google::protobuf::Message *_repMsg) + { + if (!_repMsg) + { + std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl; + return; } - /// \brief Set the REP protobuf message for this handler. - /// \param[in] _repMsg Protobuf message containing the variable where - /// the result will be stored. The only purpose of this function is to - /// store the type information of _repMsg. - public: void SetResponse(const google::protobuf::Message *_repMsg) - { - if (!_repMsg) - { - std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl; - return; - } + this->repMsg = _repMsg->New(); + this->repMsg->CopyFrom(*_repMsg); + } - this->repMsg = _repMsg->New(); - this->repMsg->CopyFrom(*_repMsg); + // Documentation inherited + public: bool Serialize(std::string &_buffer) const + { + if (!this->reqMsg) + { + std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl; + return false; } - // Documentation inherited - public: bool Serialize(std::string &_buffer) const + if (!this->reqMsg->SerializeToString(&_buffer)) { - if (!this->reqMsg) - { - std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl; - return false; - } - - if (!this->reqMsg->SerializeToString(&_buffer)) - { - std::cerr << "ReqHandler::Serialize(): Error serializing the request" - << std::endl; - return false; - } - - return true; + std::cerr << "ReqHandler::Serialize(): Error serializing the request" + << std::endl; + return false; } - // Documentation inherited. - public: void NotifyResult(const std::string &_rep, const bool _result) - { - this->rep = _rep; - this->result = _result; + return true; + } - this->repAvailable = true; - this->condition.notify_one(); - } + // Documentation inherited. + public: void NotifyResult(const std::string &_rep, const bool _result) + { + this->rep = _rep; + this->result = _result; - // Documentation inherited. - public: virtual std::string ReqTypeName() const + this->repAvailable = true; + this->condition.notify_one(); + } + + // Documentation inherited. + public: virtual std::string ReqTypeName() const + { + if (this->reqMsg) + return std::string(this->reqMsg->GetTypeName()); + else { - if (this->reqMsg) - return std::string(this->reqMsg->GetTypeName()); - else - { - std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() " - << "without type information" << std::endl; - return ""; - } + std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() " + << "without type information" << std::endl; + return ""; } + } - //// Documentation inherited. - public: virtual std::string RepTypeName() const + //// Documentation inherited. + public: virtual std::string RepTypeName() const + { + if (this->repMsg) + return std::string(this->repMsg->GetTypeName()); + else { - if (this->repMsg) - return std::string(this->repMsg->GetTypeName()); - else - { - std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() " - << "without type information" << std::endl; - return ""; - } + std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() " + << "without type information" << std::endl; + return ""; } + } - /// \brief Protobuf message containing the request's parameters. - private: google::protobuf::Message *reqMsg = nullptr; + /// \brief Protobuf message containing the request's parameters. + private: google::protobuf::Message *reqMsg = nullptr; - /// \brief Protobuf message containing the response. - private: google::protobuf::Message *repMsg = nullptr; - }; - } + /// \brief Protobuf message containing the response. + private: google::protobuf::Message *repMsg = nullptr; + }; } } diff --git a/include/gz/transport/SubscribeOptions.hh b/include/gz/transport/SubscribeOptions.hh index 1c1f0ef49..a7ad04724 100644 --- a/include/gz/transport/SubscribeOptions.hh +++ b/include/gz/transport/SubscribeOptions.hh @@ -24,59 +24,57 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - class SubscribeOptionsPrivate; + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + class SubscribeOptionsPrivate; - /// \class SubscribeOptions SubscribeOptions.hh - /// gz/transport/SubscribeOptions.hh - /// \brief A class to provide different options for a subscription. - class GZ_TRANSPORT_VISIBLE SubscribeOptions - { - /// \brief Constructor. - public: SubscribeOptions(); + /// \class SubscribeOptions SubscribeOptions.hh + /// gz/transport/SubscribeOptions.hh + /// \brief A class to provide different options for a subscription. + class GZ_TRANSPORT_VISIBLE SubscribeOptions + { + /// \brief Constructor. + public: SubscribeOptions(); - /// \brief Copy constructor. - /// \param[in] _otherSubscribeOpts SubscribeOptions to copy. - public: SubscribeOptions(const SubscribeOptions &_otherSubscribeOpts); + /// \brief Copy constructor. + /// \param[in] _otherSubscribeOpts SubscribeOptions to copy. + public: SubscribeOptions(const SubscribeOptions &_otherSubscribeOpts); - /// \brief Destructor. - public: ~SubscribeOptions(); + /// \brief Destructor. + public: ~SubscribeOptions(); - /// \brief Whether the subscription has been throttled. - /// \return true when the subscription is throttled or false otherwise. - /// \sa SetMsgsPerSec - /// \sa MsgsPerSec - public: bool Throttled() const; + /// \brief Whether the subscription has been throttled. + /// \return true when the subscription is throttled or false otherwise. + /// \sa SetMsgsPerSec + /// \sa MsgsPerSec + public: bool Throttled() const; - /// \brief Set the maximum number of messages per second received per - /// topic. Note that we calculate the minimum period of a message based - /// on the msgs/sec rate. Any message received since the last subscription - /// callback and the duration of the period will be discarded. - /// \param[in] _newMsgsPerSec Maximum number of messages per second. - public: void SetMsgsPerSec(const uint64_t _newMsgsPerSec); + /// \brief Set the maximum number of messages per second received per + /// topic. Note that we calculate the minimum period of a message based + /// on the msgs/sec rate. Any message received since the last subscription + /// callback and the duration of the period will be discarded. + /// \param[in] _newMsgsPerSec Maximum number of messages per second. + public: void SetMsgsPerSec(const uint64_t _newMsgsPerSec); - /// \brief Get the maximum number of messages per seconds received per - /// topic. - /// \return The maximum number of messages per second. - public: uint64_t MsgsPerSec() const; + /// \brief Get the maximum number of messages per seconds received per + /// topic. + /// \return The maximum number of messages per second. + public: uint64_t MsgsPerSec() const; - /// \brief Set the value to ignore local messages or not. - /// \param[in] _ignore True when ignoring local messages - /// or false otherwise. - /// \sa IgnoreLocalMessages - public: void SetIgnoreLocalMessages(bool _ignore); + /// \brief Set the value to ignore local messages or not. + /// \param[in] _ignore True when ignoring local messages + /// or false otherwise. + /// \sa IgnoreLocalMessages + public: void SetIgnoreLocalMessages(bool _ignore); - /// \brief Whether the local messages should be ignored. - /// \return true when the local messages should be ignored or - /// false otherwise. - /// \sa SetIgnoreLocalMessages - public: bool IgnoreLocalMessages() const; + /// \brief Whether the local messages should be ignored. + /// \return true when the local messages should be ignored or + /// false otherwise. + /// \sa SetIgnoreLocalMessages + public: bool IgnoreLocalMessages() const; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -84,14 +82,13 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \internal - /// \brief Pointer to private data. - protected: std::unique_ptr dataPtr; + /// \internal + /// \brief Pointer to private data. + protected: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } #endif diff --git a/include/gz/transport/SubscriptionHandler.hh b/include/gz/transport/SubscriptionHandler.hh index a612cc40d..e3ba3afe0 100644 --- a/include/gz/transport/SubscriptionHandler.hh +++ b/include/gz/transport/SubscriptionHandler.hh @@ -46,55 +46,53 @@ #include "gz/transport/TransportTypes.hh" #include "gz/transport/Uuid.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \brief SubscriptionHandlerBase contains functions and data which are + /// common to all SubscriptionHandler types. + class GZ_TRANSPORT_VISIBLE SubscriptionHandlerBase { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \brief SubscriptionHandlerBase contains functions and data which are - /// common to all SubscriptionHandler types. - class GZ_TRANSPORT_VISIBLE SubscriptionHandlerBase - { - /// \brief Constructor. - /// \param[in] _nUuid UUID of the node registering the handler. - /// \param[in] _opts Subscription options. - public: explicit SubscriptionHandlerBase( - const std::string &_nUuid, - const SubscribeOptions &_opts = SubscribeOptions()); + /// \brief Constructor. + /// \param[in] _nUuid UUID of the node registering the handler. + /// \param[in] _opts Subscription options. + public: explicit SubscriptionHandlerBase( + const std::string &_nUuid, + const SubscribeOptions &_opts = SubscribeOptions()); - /// \brief Destructor. - public: virtual ~SubscriptionHandlerBase() = default; + /// \brief Destructor. + public: virtual ~SubscriptionHandlerBase() = default; - /// \brief Get the type of the messages from which this subscriber - /// handler is subscribed. - /// \return String representation of the message type. - public: virtual std::string TypeName() = 0; + /// \brief Get the type of the messages from which this subscriber + /// handler is subscribed. + /// \return String representation of the message type. + public: virtual std::string TypeName() = 0; - /// \brief Get the node UUID. - /// \return The string representation of the node UUID. - public: std::string NodeUuid() const; + /// \brief Get the node UUID. + /// \return The string representation of the node UUID. + public: std::string NodeUuid() const; - /// \brief Get the unique UUID of this handler. - /// \return A string representation of the handler UUID. - public: std::string HandlerUuid() const; + /// \brief Get the unique UUID of this handler. + /// \return A string representation of the handler UUID. + public: std::string HandlerUuid() const; - /// \brief Return whether local messages are ignored or not. - /// \return True when local messages are ignored or false otherwise. - public: bool IgnoreLocalMessages() const; + /// \brief Return whether local messages are ignored or not. + /// \return True when local messages are ignored or false otherwise. + public: bool IgnoreLocalMessages() const; - /// \brief Check if message subscription is throttled. If so, verify - /// whether the callback should be executed or not. - /// \return true if the callback should be executed or false otherwise. - protected: bool UpdateThrottling(); + /// \brief Check if message subscription is throttled. If so, verify + /// whether the callback should be executed or not. + /// \return true if the callback should be executed or false otherwise. + protected: bool UpdateThrottling(); - /// \brief Subscribe options. - protected: SubscribeOptions opts; + /// \brief Subscribe options. + protected: SubscribeOptions opts; - /// \brief If throttling is enabled, the minimum period for receiving a - /// message in nanoseconds. - protected: double periodNs; + /// \brief If throttling is enabled, the minimum period for receiving a + /// message in nanoseconds. + protected: double periodNs; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -102,279 +100,279 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Unique handler's UUID. - protected: std::string hUuid; + /// \brief Unique handler's UUID. + protected: std::string hUuid; - /// \brief Timestamp of the last callback executed. - protected: Timestamp lastCbTimestamp; + /// \brief Timestamp of the last callback executed. + protected: Timestamp lastCbTimestamp; - /// \brief Node UUID. - private: std::string nUuid; + /// \brief Node UUID. + private: std::string nUuid; #ifdef _WIN32 #pragma warning(pop) #endif - }; - - /// \class ISubscriptionHandler SubscriptionHandler.hh - /// gz/transport/SubscriptionHandler.hh - /// \brief Interface class used to manage generic protobuf messages. - /// - /// This extends SubscriptionHandlerBase by defining virtual functions for - /// deserializing protobuf message data, and for receiving deserialized - /// messages. Those functions are not needed by the RawSubscriptionHandler - /// class. - class GZ_TRANSPORT_VISIBLE ISubscriptionHandler - : public SubscriptionHandlerBase + }; + + /// \class ISubscriptionHandler SubscriptionHandler.hh + /// gz/transport/SubscriptionHandler.hh + /// \brief Interface class used to manage generic protobuf messages. + /// + /// This extends SubscriptionHandlerBase by defining virtual functions for + /// deserializing protobuf message data, and for receiving deserialized + /// messages. Those functions are not needed by the RawSubscriptionHandler + /// class. + class GZ_TRANSPORT_VISIBLE ISubscriptionHandler + : public SubscriptionHandlerBase + { + /// \brief Constructor. + /// \param[in] _nUuid UUID of the node registering the handler. + /// \param[in] _opts Subscription options. + public: explicit ISubscriptionHandler( + const std::string &_nUuid, + const SubscribeOptions &_opts = SubscribeOptions()); + + /// \brief Destructor. + public: virtual ~ISubscriptionHandler() = default; + + /// \brief Executes the local callback registered for this handler. + /// \param[in] _msg Protobuf message received. + /// \param[in] _info Message information (e.g.: topic name). + /// \return True when success, false otherwise. + public: virtual bool RunLocalCallback( + const ProtoMsg &_msg, + const MessageInfo &_info) = 0; + + /// \brief Create a specific protobuf message given its serialized data. + /// \param[in] _data The serialized data. + /// \param[in] _type The data type. + /// \return Pointer to the specific protobuf message. + public: virtual const std::shared_ptr CreateMsg( + const std::string &_data, + const std::string &_type) const = 0; + }; + + /// \class SubscriptionHandler SubscriptionHandler.hh + /// \brief It creates a subscription handler for a specific protobuf + /// message. 'T' is the Protobuf message type that will be used for this + /// particular handler. + template class SubscriptionHandler + : public ISubscriptionHandler + { + // Documentation inherited. + public: explicit SubscriptionHandler(const std::string &_nUuid, + const SubscribeOptions &_opts = SubscribeOptions()) + : ISubscriptionHandler(_nUuid, _opts) { - /// \brief Constructor. - /// \param[in] _nUuid UUID of the node registering the handler. - /// \param[in] _opts Subscription options. - public: explicit ISubscriptionHandler( - const std::string &_nUuid, - const SubscribeOptions &_opts = SubscribeOptions()); - - /// \brief Destructor. - public: virtual ~ISubscriptionHandler() = default; - - /// \brief Executes the local callback registered for this handler. - /// \param[in] _msg Protobuf message received. - /// \param[in] _info Message information (e.g.: topic name). - /// \return True when success, false otherwise. - public: virtual bool RunLocalCallback( - const ProtoMsg &_msg, - const MessageInfo &_info) = 0; - - /// \brief Create a specific protobuf message given its serialized data. - /// \param[in] _data The serialized data. - /// \param[in] _type The data type. - /// \return Pointer to the specific protobuf message. - public: virtual const std::shared_ptr CreateMsg( - const std::string &_data, - const std::string &_type) const = 0; - }; - - /// \class SubscriptionHandler SubscriptionHandler.hh - /// \brief It creates a subscription handler for a specific protobuf - /// message. 'T' is the Protobuf message type that will be used for this - /// particular handler. - template class SubscriptionHandler - : public ISubscriptionHandler + } + + // Documentation inherited. + public: const std::shared_ptr CreateMsg( + const std::string &_data, + const std::string &/*_type*/) const { - // Documentation inherited. - public: explicit SubscriptionHandler(const std::string &_nUuid, - const SubscribeOptions &_opts = SubscribeOptions()) - : ISubscriptionHandler(_nUuid, _opts) - { - } + // Instantiate a specific protobuf message + auto msgPtr = std::make_shared(); - // Documentation inherited. - public: const std::shared_ptr CreateMsg( - const std::string &_data, - const std::string &/*_type*/) const + // Create the message using some serialized data + if (!msgPtr->ParseFromString(_data)) { - // Instantiate a specific protobuf message - auto msgPtr = std::make_shared(); + std::cerr << "SubscriptionHandler::CreateMsg() error: ParseFromString" + << " failed" << std::endl; + } - // Create the message using some serialized data - if (!msgPtr->ParseFromString(_data)) - { - std::cerr << "SubscriptionHandler::CreateMsg() error: ParseFromString" - << " failed" << std::endl; - } + return msgPtr; + } - return msgPtr; - } + // Documentation inherited. + public: std::string TypeName() + { + return std::string(T().GetTypeName()); + } - // Documentation inherited. - public: std::string TypeName() - { - return std::string(T().GetTypeName()); - } + /// \brief Set the callback for this handler. + /// \param[in] _cb The callback with the following parameters: + public: void SetCallback(const MsgCallback &_cb) + { + this->cb = _cb; + } - /// \brief Set the callback for this handler. - /// \param[in] _cb The callback with the following parameters: - public: void SetCallback(const MsgCallback &_cb) + // Documentation inherited. + public: bool RunLocalCallback(const ProtoMsg &_msg, + const MessageInfo &_info) + { + // No callback stored. + if (!this->cb) { - this->cb = _cb; + std::cerr << "SubscriptionHandler::RunLocalCallback() error: " + << "Callback is NULL" << std::endl; + return false; } - // Documentation inherited. - public: bool RunLocalCallback(const ProtoMsg &_msg, - const MessageInfo &_info) - { - // No callback stored. - if (!this->cb) - { - std::cerr << "SubscriptionHandler::RunLocalCallback() error: " - << "Callback is NULL" << std::endl; - return false; - } - - // Check the subscription throttling option. - if (!this->UpdateThrottling()) - return true; + // Check the subscription throttling option. + if (!this->UpdateThrottling()) + return true; #if GOOGLE_PROTOBUF_VERSION >= 5028000 - auto msgPtr = google::protobuf::DynamicCastMessage(&_msg); + auto msgPtr = google::protobuf::DynamicCastMessage(&_msg); #elif GOOGLE_PROTOBUF_VERSION >= 4022000 - auto msgPtr = google::protobuf::internal::DownCast(&_msg); + auto msgPtr = google::protobuf::internal::DownCast(&_msg); #elif GOOGLE_PROTOBUF_VERSION >= 3000000 - auto msgPtr = google::protobuf::down_cast(&_msg); + auto msgPtr = google::protobuf::down_cast(&_msg); #else - auto msgPtr = google::protobuf::internal::down_cast(&_msg); + auto msgPtr = google::protobuf::internal::down_cast(&_msg); #endif - // Verify the dynamically casted message is valid - if (msgPtr == nullptr) - { - if (_msg.GetDescriptor() != nullptr) - { - std::cerr << "SubscriptionHandler::RunLocalCallback() error: " - << "Failed to cast the message of the type " - << _msg.GetDescriptor()->full_name() - << " to the specified type" << '\n'; - } - else - { - std::cerr << "SubscriptionHandler::RunLocalCallback() error: " - << "Failed to cast the message of an unknown type" - << " to the specified type" << '\n'; - } - std::cerr.flush(); - return false; - } - - this->cb(*msgPtr, _info); - return true; - } - - /// \brief Callback to the function registered for this handler. - private: MsgCallback cb; - }; - - /// \brief Specialized template when the user prefers a callbacks that - /// accepts a generic google::protobuf::message instead of a specific type. - template <> class SubscriptionHandler - : public ISubscriptionHandler - { - // Documentation inherited. - public: explicit SubscriptionHandler(const std::string &_nUuid, - const SubscribeOptions &_opts = SubscribeOptions()) - : ISubscriptionHandler(_nUuid, _opts) + // Verify the dynamically casted message is valid + if (msgPtr == nullptr) { - } - - // Documentation inherited. - public: const std::shared_ptr CreateMsg( - const std::string &_data, - const std::string &_type) const - { - std::shared_ptr msgPtr; - - const google::protobuf::Descriptor *desc = - google::protobuf::DescriptorPool::generated_pool() - ->FindMessageTypeByName(_type); - - // First, check if we have the descriptor from the generated proto - // classes. - if (desc) + if (_msg.GetDescriptor() != nullptr) { - msgPtr.reset(google::protobuf::MessageFactory::generated_factory() - ->GetPrototype(desc)->New()); + std::cerr << "SubscriptionHandler::RunLocalCallback() error: " + << "Failed to cast the message of the type " + << _msg.GetDescriptor()->full_name() + << " to the specified type" << '\n'; } else { - // Fallback on Gazebo Msgs if the message type is not found. - msgPtr = gz::msgs::Factory::New(_type); + std::cerr << "SubscriptionHandler::RunLocalCallback() error: " + << "Failed to cast the message of an unknown type" + << " to the specified type" << '\n'; } + std::cerr.flush(); + return false; + } - if (!msgPtr) - return nullptr; + this->cb(*msgPtr, _info); + return true; + } - // Create the message using some serialized data - if (!msgPtr->ParseFromString(_data)) - { - std::cerr << "CreateMsg() error: ParseFromString failed" << std::endl; - return nullptr; - } + /// \brief Callback to the function registered for this handler. + private: MsgCallback cb; + }; - return msgPtr; - } + /// \brief Specialized template when the user prefers a callbacks that + /// accepts a generic google::protobuf::message instead of a specific type. + template <> class SubscriptionHandler + : public ISubscriptionHandler + { + // Documentation inherited. + public: explicit SubscriptionHandler(const std::string &_nUuid, + const SubscribeOptions &_opts = SubscribeOptions()) + : ISubscriptionHandler(_nUuid, _opts) + { + } + + // Documentation inherited. + public: const std::shared_ptr CreateMsg( + const std::string &_data, + const std::string &_type) const + { + std::shared_ptr msgPtr; + + const google::protobuf::Descriptor *desc = + google::protobuf::DescriptorPool::generated_pool() + ->FindMessageTypeByName(_type); - // Documentation inherited. - public: std::string TypeName() + // First, check if we have the descriptor from the generated proto + // classes. + if (desc) { - return kGenericMessageType; + msgPtr.reset(google::protobuf::MessageFactory::generated_factory() + ->GetPrototype(desc)->New()); } - - /// \brief Set the callback for this handler. - /// \param[in] _cb The callback. - public: void SetCallback(const MsgCallback &_cb) + else { - this->cb = _cb; + // Fallback on Gazebo Msgs if the message type is not found. + msgPtr = gz::msgs::Factory::New(_type); } - // Documentation inherited. - public: bool RunLocalCallback(const ProtoMsg &_msg, - const MessageInfo &_info) + if (!msgPtr) + return nullptr; + + // Create the message using some serialized data + if (!msgPtr->ParseFromString(_data)) { - // No callback stored. - if (!this->cb) - { - std::cerr << "SubscriptionHandler::RunLocalCallback() " - << "error: Callback is NULL" << std::endl; - return false; - } + std::cerr << "CreateMsg() error: ParseFromString failed" << std::endl; + return nullptr; + } - // Check the subscription throttling option. - if (!this->UpdateThrottling()) - return true; + return msgPtr; + } - this->cb(_msg, _info); - return true; - } + // Documentation inherited. + public: std::string TypeName() + { + return kGenericMessageType; + } - /// \brief Callback to the function registered for this handler. - private: MsgCallback cb; - }; + /// \brief Set the callback for this handler. + /// \param[in] _cb The callback. + public: void SetCallback(const MsgCallback &_cb) + { + this->cb = _cb; + } - ////////////////////////////////////////////////// - /// RawSubscriptionHandler is used to manage the callback of a raw - /// subscription. - class RawSubscriptionHandler : public SubscriptionHandlerBase + // Documentation inherited. + public: bool RunLocalCallback(const ProtoMsg &_msg, + const MessageInfo &_info) { - /// \brief Constructor - /// \param[in] _nUuid UUID of the node registering the handler - /// \param[in] _msgType Name of message type that this handler should - /// listen for. Setting this to kGenericMessageType will tell this handler - /// to listen for all message types. - /// \param[in] _opts Subscription options. - public: explicit RawSubscriptionHandler( - const std::string &_nUuid, - const std::string &_msgType = kGenericMessageType, - const SubscribeOptions &_opts = SubscribeOptions()); - - // Documentation inherited - public: std::string TypeName() override; - - /// \brief Set the callback of this handler. - /// \param[in] _callback The callback function that will be triggered when - /// a message is received. - public: void SetCallback(const RawCallback &_callback); - - /// \brief Executes the raw callback registered for this handler. - /// \param[in] _msgData Serialized string of message data - /// \param[in] _size Number of bytes in the serialized message data - /// \param[in] _info Meta-data for the message - /// \return True if the callback was triggered, false if the callback was - /// not set. - public: bool RunRawCallback(const char *_msgData, const size_t _size, - const MessageInfo &_info); - - /// \brief Destructor - public: ~RawSubscriptionHandler(); - - private: class Implementation; + // No callback stored. + if (!this->cb) + { + std::cerr << "SubscriptionHandler::RunLocalCallback() " + << "error: Callback is NULL" << std::endl; + return false; + } + + // Check the subscription throttling option. + if (!this->UpdateThrottling()) + return true; + + this->cb(_msg, _info); + return true; + } + + /// \brief Callback to the function registered for this handler. + private: MsgCallback cb; + }; + + ////////////////////////////////////////////////// + /// RawSubscriptionHandler is used to manage the callback of a raw + /// subscription. + class RawSubscriptionHandler : public SubscriptionHandlerBase + { + /// \brief Constructor + /// \param[in] _nUuid UUID of the node registering the handler + /// \param[in] _msgType Name of message type that this handler should + /// listen for. Setting this to kGenericMessageType will tell this handler + /// to listen for all message types. + /// \param[in] _opts Subscription options. + public: explicit RawSubscriptionHandler( + const std::string &_nUuid, + const std::string &_msgType = kGenericMessageType, + const SubscribeOptions &_opts = SubscribeOptions()); + + // Documentation inherited + public: std::string TypeName() override; + + /// \brief Set the callback of this handler. + /// \param[in] _callback The callback function that will be triggered when + /// a message is received. + public: void SetCallback(const RawCallback &_callback); + + /// \brief Executes the raw callback registered for this handler. + /// \param[in] _msgData Serialized string of message data + /// \param[in] _size Number of bytes in the serialized message data + /// \param[in] _info Meta-data for the message + /// \return True if the callback was triggered, false if the callback was + /// not set. + public: bool RunRawCallback(const char *_msgData, const size_t _size, + const MessageInfo &_info); + + /// \brief Destructor + public: ~RawSubscriptionHandler(); + + private: class Implementation; #ifdef _WIN32 // Disable warning C4251 which is triggered by @@ -382,14 +380,13 @@ namespace gz #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \internal - /// \brief Pointer to the implementation of the class - private: std::unique_ptr pimpl; + /// \internal + /// \brief Pointer to the implementation of the class + private: std::unique_ptr pimpl; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } diff --git a/include/gz/transport/TopicStatistics.hh b/include/gz/transport/TopicStatistics.hh index 207004846..f0cd3dfde 100644 --- a/include/gz/transport/TopicStatistics.hh +++ b/include/gz/transport/TopicStatistics.hh @@ -37,131 +37,128 @@ #include #endif -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + // Forward declarations. + class TopicStatisticsPrivate; + + /// \brief Computes the rolling average, min, max, and standard + /// deviation for a set of samples. + class GZ_TRANSPORT_VISIBLE Statistics { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - // Forward declarations. - class TopicStatisticsPrivate; - - /// \brief Computes the rolling average, min, max, and standard - /// deviation for a set of samples. - class GZ_TRANSPORT_VISIBLE Statistics - { - /// \brief Default constructor. - public: Statistics() = default; - - /// \brief Default destructor. - public: ~Statistics() = default; - - /// \brief Update with a new sample. - /// \param[in] _stat New statistic sample. - public: void Update(double _stat); - - /// \brief Get the average value. - /// \return the average value. - public: double Avg() const; - - /// \brief Get the standard deviation. - /// \return The standard deviation. - public: double StdDev() const; - - /// \brief Get the minimum sample value. - /// \return The minimum sample value. - public: double Min() const; - - /// \brief Get the maximum sample value. - /// \return The maximum sample value. - public: double Max() const; - - /// \brief Get the number of samples. - /// \return The number of samples. - public: uint64_t Count() const; - - /// \brief Count of the samples. - private: uint64_t count = 0; - - /// \brief Average value. - private: double average = 0; - - /// \brief Sum of the squared mean distance between samples. This is - /// used to calculate the standard deviation. - private: double sumSquareMeanDist = 0; - - /// \brief Minimum sample. - private: double min = std::numeric_limits::max(); - - /// \brief Maximum sample. - private: double max = std::numeric_limits::min(); - }; - - /// \brief Encapsulates statistics for a single topic. The set of - /// statistics include: - /// - /// 1. Number of dropped messages. - /// max time between publications. - /// 3. Receive statistics: The reception hz rate, standard - /// deviation between receiving messages, min time between receiving - /// messages, and max time between receiving messages. - /// - /// Publication statistics utilize time stamps generated by the - /// publisher. Receive statistics use time stamps generated by the - /// subscriber. - class GZ_TRANSPORT_VISIBLE TopicStatistics - { - /// \brief Default constructor. - public: TopicStatistics(); - - /// \brief Copy constructor. - /// \param[in] _stats Statistics to copy. - public: TopicStatistics(const TopicStatistics &_stats); - - /// \brief Default destructor. - public: ~TopicStatistics(); - - /// \brief Update the topic statistics. - /// \param[in] _sender Address of the sender. - /// \param[in] _stamp Publication time stamp. - /// \param[in] _seq Publication sequence number. - public: void Update(const std::string &_sender, - uint64_t _stamp, uint64_t _seq); - - /// \brief Populate a gz::msgs::Metric message with topic - /// statistics. - /// \param[in] _msg Message to populate. - public: void FillMessage(msgs::Metric &_msg) const; - - /// \brief Get the number of dropped messages. - /// \return Number of dropped messages. - public: uint64_t DroppedMsgCount() const; - - /// \brief Get statistics about publication of messages. - /// \return Publication statistics. - public: Statistics PublicationStatistics() const; - - /// \brief Get the statistics about reception of messages. - /// \return Reception statistics. - public: Statistics ReceptionStatistics() const; - - /// \brief Get the message age statistics. - /// \return Age statistics. - public: Statistics AgeStatistics() const; + /// \brief Default constructor. + public: Statistics() = default; + + /// \brief Default destructor. + public: ~Statistics() = default; + + /// \brief Update with a new sample. + /// \param[in] _stat New statistic sample. + public: void Update(double _stat); + + /// \brief Get the average value. + /// \return the average value. + public: double Avg() const; + + /// \brief Get the standard deviation. + /// \return The standard deviation. + public: double StdDev() const; + + /// \brief Get the minimum sample value. + /// \return The minimum sample value. + public: double Min() const; + + /// \brief Get the maximum sample value. + /// \return The maximum sample value. + public: double Max() const; + + /// \brief Get the number of samples. + /// \return The number of samples. + public: uint64_t Count() const; + + /// \brief Count of the samples. + private: uint64_t count = 0; + + /// \brief Average value. + private: double average = 0; + + /// \brief Sum of the squared mean distance between samples. This is + /// used to calculate the standard deviation. + private: double sumSquareMeanDist = 0; + + /// \brief Minimum sample. + private: double min = std::numeric_limits::max(); + + /// \brief Maximum sample. + private: double max = std::numeric_limits::min(); + }; + + /// \brief Encapsulates statistics for a single topic. The set of + /// statistics include: + /// + /// 1. Number of dropped messages. + /// max time between publications. + /// 3. Receive statistics: The reception hz rate, standard + /// deviation between receiving messages, min time between receiving + /// messages, and max time between receiving messages. + /// + /// Publication statistics utilize time stamps generated by the + /// publisher. Receive statistics use time stamps generated by the + /// subscriber. + class GZ_TRANSPORT_VISIBLE TopicStatistics + { + /// \brief Default constructor. + public: TopicStatistics(); + + /// \brief Copy constructor. + /// \param[in] _stats Statistics to copy. + public: TopicStatistics(const TopicStatistics &_stats); + + /// \brief Default destructor. + public: ~TopicStatistics(); + + /// \brief Update the topic statistics. + /// \param[in] _sender Address of the sender. + /// \param[in] _stamp Publication time stamp. + /// \param[in] _seq Publication sequence number. + public: void Update(const std::string &_sender, + uint64_t _stamp, uint64_t _seq); + + /// \brief Populate a gz::msgs::Metric message with topic + /// statistics. + /// \param[in] _msg Message to populate. + public: void FillMessage(msgs::Metric &_msg) const; + + /// \brief Get the number of dropped messages. + /// \return Number of dropped messages. + public: uint64_t DroppedMsgCount() const; + + /// \brief Get statistics about publication of messages. + /// \return Publication statistics. + public: Statistics PublicationStatistics() const; + + /// \brief Get the statistics about reception of messages. + /// \return Reception statistics. + public: Statistics ReceptionStatistics() const; + + /// \brief Get the message age statistics. + /// \return Age statistics. + public: Statistics AgeStatistics() const; #ifdef _WIN32 // Disable warning C4251 which is triggered by // std::unique_ptr #pragma warning(push) #pragma warning(disable: 4251) #endif - /// \brief Private data pointer. - private: std::unique_ptr dataPtr; + /// \brief Private data pointer. + private: std::unique_ptr dataPtr; #ifdef _WIN32 #pragma warning(pop) #endif - }; - } + }; } } #endif diff --git a/include/gz/transport/TopicStorage.hh b/include/gz/transport/TopicStorage.hh index 8cdfa557e..fa82ca6d6 100644 --- a/include/gz/transport/TopicStorage.hh +++ b/include/gz/transport/TopicStorage.hh @@ -28,352 +28,349 @@ #include "gz/transport/Publisher.hh" #include "gz/transport/TransportTypes.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class TopicStorage TopicStorage.hh gz/transport/TopicStorage.hh + /// \brief Store address information about topics and provide convenient + /// methods for adding new topics, removing them, etc. + template class TopicStorage { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class TopicStorage TopicStorage.hh gz/transport/TopicStorage.hh - /// \brief Store address information about topics and provide convenient - /// methods for adding new topics, removing them, etc. - template class TopicStorage - { - /// \brief Constructor. - public: TopicStorage() = default; + /// \brief Constructor. + public: TopicStorage() = default; - /// \brief Destructor. - public: virtual ~TopicStorage() = default; + /// \brief Destructor. + public: virtual ~TopicStorage() = default; - /// \brief Add a new address associated to a given topic and node UUID. - /// \param[in] _publisher New publisher. - /// \return true if the new entry is added or false if not (because it - /// was already stored). - public: bool AddPublisher(const T &_publisher) + /// \brief Add a new address associated to a given topic and node UUID. + /// \param[in] _publisher New publisher. + /// \return true if the new entry is added or false if not (because it + /// was already stored). + public: bool AddPublisher(const T &_publisher) + { + // The topic does not exist. + if (this->data.find(_publisher.Topic()) == this->data.end()) { - // The topic does not exist. - if (this->data.find(_publisher.Topic()) == this->data.end()) - { - // VS2013 is buggy with initializer list here {} - this->data[_publisher.Topic()] = - std::map>(); - } - - // Check if the process uuid exists. - auto &m = this->data[_publisher.Topic()]; - if (m.find(_publisher.PUuid()) != m.end()) - { - // Check that the Publisher does not exist. - auto &v = m[_publisher.PUuid()]; - auto found = std::find_if(v.begin(), v.end(), - [&](const T &_pub) - { - return _pub.Addr() == _publisher.Addr() && - _pub.NUuid() == _publisher.NUuid(); - }); - - // The publisher was already existing, just exit. - if (found != v.end()) - return false; - } - - // Add a new Publisher entry. - m[_publisher.PUuid()].push_back(T(_publisher)); - return true; + // VS2013 is buggy with initializer list here {} + this->data[_publisher.Topic()] = + std::map>(); } - /// \brief Return if there is any publisher stored for the given topic. - /// \param[in] _topic Topic name. - /// \return True if there is at least one entry stored for the topic. - public: bool HasTopic(const std::string &_topic) const + // Check if the process uuid exists. + auto &m = this->data[_publisher.Topic()]; + if (m.find(_publisher.PUuid()) != m.end()) { - return this->data.find(_topic) != this->data.end(); - } + // Check that the Publisher does not exist. + auto &v = m[_publisher.PUuid()]; + auto found = std::find_if(v.begin(), v.end(), + [&](const T &_pub) + { + return _pub.Addr() == _publisher.Addr() && + _pub.NUuid() == _publisher.NUuid(); + }); - /// \brief Return if there is any publisher stored for the given topic and - /// type. - /// \param[in] _topic Topic name. - /// \param[in] _type Topic type. - /// \return True if there is at least one entry stored for the topic and - /// type. - public: bool HasTopic(const std::string &_topic, - const std::string &_type) const - { - if (!this->HasTopic(_topic)) + // The publisher was already existing, just exit. + if (found != v.end()) return false; + } - // m is {pUUID=>std::vector}. - auto &m = this->data.at(_topic); - - for (auto const &procs : m) - { - // Vector of publishers for a given topic and pUuid. - auto &v = procs.second; - auto found = std::find_if(v.begin(), v.end(), - [&](const T &_pub) - { - return _pub.MsgTypeName() == _type || - _pub.MsgTypeName() == kGenericMessageType; - }); + // Add a new Publisher entry. + m[_publisher.PUuid()].push_back(T(_publisher)); + return true; + } - // Type found! - if (found != v.end()) - return true; - } + /// \brief Return if there is any publisher stored for the given topic. + /// \param[in] _topic Topic name. + /// \return True if there is at least one entry stored for the topic. + public: bool HasTopic(const std::string &_topic) const + { + return this->data.find(_topic) != this->data.end(); + } + /// \brief Return if there is any publisher stored for the given topic and + /// type. + /// \param[in] _topic Topic name. + /// \param[in] _type Topic type. + /// \return True if there is at least one entry stored for the topic and + /// type. + public: bool HasTopic(const std::string &_topic, + const std::string &_type) const + { + if (!this->HasTopic(_topic)) return false; - } - /// \brief Return if there is any publisher stored for the given topic and - /// process UUID. - /// \param[in] _topic Topic name. - /// \param[in] _pUuid Process UUID of the publisher. - /// \return True if there is at least one address stored for the topic and - /// process UUID. - public: bool HasAnyPublishers(const std::string &_topic, - const std::string &_pUuid) const + // m is {pUUID=>std::vector}. + auto &m = this->data.at(_topic); + + for (auto const &procs : m) { - if (!this->HasTopic(_topic)) - return false; + // Vector of publishers for a given topic and pUuid. + auto &v = procs.second; + auto found = std::find_if(v.begin(), v.end(), + [&](const T &_pub) + { + return _pub.MsgTypeName() == _type || + _pub.MsgTypeName() == kGenericMessageType; + }); - return this->data.at(_topic).find(_pUuid) != - this->data.at(_topic).end(); + // Type found! + if (found != v.end()) + return true; } - /// \brief Return if the requested publisher's address is stored. - /// \param[in] _addr Publisher's address requested - /// \return true if the publisher's address is stored. - public: bool HasPublisher(const std::string &_addr) const + return false; + } + + /// \brief Return if there is any publisher stored for the given topic and + /// process UUID. + /// \param[in] _topic Topic name. + /// \param[in] _pUuid Process UUID of the publisher. + /// \return True if there is at least one address stored for the topic and + /// process UUID. + public: bool HasAnyPublishers(const std::string &_topic, + const std::string &_pUuid) const + { + if (!this->HasTopic(_topic)) + return false; + + return this->data.at(_topic).find(_pUuid) != + this->data.at(_topic).end(); + } + + /// \brief Return if the requested publisher's address is stored. + /// \param[in] _addr Publisher's address requested + /// \return true if the publisher's address is stored. + public: bool HasPublisher(const std::string &_addr) const + { + for (auto const &topic : this->data) { - for (auto const &topic : this->data) + for (auto const &proc : topic.second) { - for (auto const &proc : topic.second) + for (auto const &pub : proc.second) { - for (auto const &pub : proc.second) - { - if (pub.Addr() == _addr) - return true; - } + if (pub.Addr() == _addr) + return true; } } - return false; } + return false; + } - /// \brief Get the address information for a given topic and node UUID. - /// \param[in] _topic Topic name. - /// \param[in] _pUuid Process UUID of the publisher. - /// \param[in] _nUuid Node UUID of the publisher. - /// \param[out] _publisher Publisher's information requested. - /// \return true if a publisher is found for the given topic and UUID pair - public: bool Publisher(const std::string &_topic, - const std::string &_pUuid, - const std::string &_nUuid, - T &_publisher) const - { - // Topic not found. - if (this->data.find(_topic) == this->data.end()) - return false; - - // m is {pUUID=>Publisher}. - auto &m = this->data.at(_topic); - - // pUuid not found. - if (m.find(_pUuid) == m.end()) - return false; + /// \brief Get the address information for a given topic and node UUID. + /// \param[in] _topic Topic name. + /// \param[in] _pUuid Process UUID of the publisher. + /// \param[in] _nUuid Node UUID of the publisher. + /// \param[out] _publisher Publisher's information requested. + /// \return true if a publisher is found for the given topic and UUID pair + public: bool Publisher(const std::string &_topic, + const std::string &_pUuid, + const std::string &_nUuid, + T &_publisher) const + { + // Topic not found. + if (this->data.find(_topic) == this->data.end()) + return false; - // Vector of 0MQ known addresses for a given topic and pUuid. - auto &v = m.at(_pUuid); - auto found = std::find_if(v.begin(), v.end(), - [&](const T &_pub) - { - return _pub.NUuid() == _nUuid; - }); - // Address found! - if (found != v.end()) - { - _publisher = *found; - return true; - } + // m is {pUUID=>Publisher}. + auto &m = this->data.at(_topic); - // nUuid not found. + // pUuid not found. + if (m.find(_pUuid) == m.end()) return false; - } - /// \brief Get the map of publishers stored for a given topic. - /// \param[in] _topic Topic name. - /// \param[out] _info Map of publishers requested. - /// \return true if at least there is one publisher stored. - public: bool Publishers(const std::string &_topic, - std::map> &_info) const + // Vector of 0MQ known addresses for a given topic and pUuid. + auto &v = m.at(_pUuid); + auto found = std::find_if(v.begin(), v.end(), + [&](const T &_pub) + { + return _pub.NUuid() == _nUuid; + }); + // Address found! + if (found != v.end()) { - if (!this->HasTopic(_topic)) - return false; - - _info = this->data.at(_topic); + _publisher = *found; return true; } - /// \brief Remove a publisher associated to a given topic and UUID pair. - /// \param[in] _topic Topic name - /// \param[in] _pUuid Process UUID of the publisher. - /// \param[in] _nUuid Node UUID of the publisher. - /// \return True when the publisher was removed or false otherwise. - public: bool DelPublisherByNode(const std::string &_topic, - const std::string &_pUuid, - const std::string &_nUuid) - { - size_t counter = 0; + // nUuid not found. + return false; + } - // Iterate over all the topics. - if (this->data.find(_topic) != this->data.end()) - { - // m is {pUUID=>Publisher}. - auto &m = this->data[_topic]; + /// \brief Get the map of publishers stored for a given topic. + /// \param[in] _topic Topic name. + /// \param[out] _info Map of publishers requested. + /// \return true if at least there is one publisher stored. + public: bool Publishers(const std::string &_topic, + std::map> &_info) const + { + if (!this->HasTopic(_topic)) + return false; - // The pUuid exists. - if (m.find(_pUuid) != m.end()) - { - // Vector of 0MQ known addresses for a given topic and pUuid. - auto &v = m[_pUuid]; - auto priorSize = v.size(); - v.erase(std::remove_if(v.begin(), v.end(), - [&](const T &_pub) - { - return _pub.NUuid() == _nUuid; - }), - v.end()); - counter = priorSize - v.size(); - - if (v.empty()) - m.erase(_pUuid); - - if (m.empty()) - this->data.erase(_topic); - } - } + _info = this->data.at(_topic); + return true; + } - return counter > 0; - } + /// \brief Remove a publisher associated to a given topic and UUID pair. + /// \param[in] _topic Topic name + /// \param[in] _pUuid Process UUID of the publisher. + /// \param[in] _nUuid Node UUID of the publisher. + /// \return True when the publisher was removed or false otherwise. + public: bool DelPublisherByNode(const std::string &_topic, + const std::string &_pUuid, + const std::string &_nUuid) + { + size_t counter = 0; - /// \brief Remove all the publishers associated to a given process. - /// \param[in] _pUuid Process' UUID of the publisher. - /// \return True when at least one address was removed or false otherwise. - public: bool DelPublishersByProc(const std::string &_pUuid) + // Iterate over all the topics. + if (this->data.find(_topic) != this->data.end()) { - size_t counter = 0; + // m is {pUUID=>Publisher}. + auto &m = this->data[_topic]; - // Iterate over all the topics. - for (auto it = this->data.begin(); it != this->data.end();) + // The pUuid exists. + if (m.find(_pUuid) != m.end()) { - // m is {pUUID=>Publisher}. - auto &m = it->second; - counter += m.erase(_pUuid); + // Vector of 0MQ known addresses for a given topic and pUuid. + auto &v = m[_pUuid]; + auto priorSize = v.size(); + v.erase(std::remove_if(v.begin(), v.end(), + [&](const T &_pub) + { + return _pub.NUuid() == _nUuid; + }), + v.end()); + counter = priorSize - v.size(); + + if (v.empty()) + m.erase(_pUuid); + if (m.empty()) - this->data.erase(it++); - else - ++it; + this->data.erase(_topic); } - - return counter > 0; } - /// \brief Given a process UUID, the function returns the list of - /// publishers contained in this process UUID with its address information - /// \param[in] _pUuid Process UUID. - /// \param[out] _pubs Map of publishers where the keys are the node UUIDs - /// and the value is its address information. - public: void PublishersByProc(const std::string &_pUuid, - std::map> &_pubs) const + return counter > 0; + } + + /// \brief Remove all the publishers associated to a given process. + /// \param[in] _pUuid Process' UUID of the publisher. + /// \return True when at least one address was removed or false otherwise. + public: bool DelPublishersByProc(const std::string &_pUuid) + { + size_t counter = 0; + + // Iterate over all the topics. + for (auto it = this->data.begin(); it != this->data.end();) { - _pubs.clear(); + // m is {pUUID=>Publisher}. + auto &m = it->second; + counter += m.erase(_pUuid); + if (m.empty()) + this->data.erase(it++); + else + ++it; + } + + return counter > 0; + } + + /// \brief Given a process UUID, the function returns the list of + /// publishers contained in this process UUID with its address information + /// \param[in] _pUuid Process UUID. + /// \param[out] _pubs Map of publishers where the keys are the node UUIDs + /// and the value is its address information. + public: void PublishersByProc(const std::string &_pUuid, + std::map> &_pubs) const + { + _pubs.clear(); - // Iterate over all the topics. - for (auto const &topic : this->data) + // Iterate over all the topics. + for (auto const &topic : this->data) + { + // m is {pUUID=>Publisher}. + auto &m = topic.second; + if (m.find(_pUuid) != m.end()) { - // m is {pUUID=>Publisher}. - auto &m = topic.second; - if (m.find(_pUuid) != m.end()) + auto &v = m.at(_pUuid); + for (auto const &pub : v) { - auto &v = m.at(_pUuid); - for (auto const &pub : v) - { - _pubs[pub.NUuid()].push_back(T(pub)); - } + _pubs[pub.NUuid()].push_back(T(pub)); } } } + } - /// \brief Given a process UUID and the node UUID, the function returns - /// the list of publishers contained in the node. - /// \param[in] _pUuid Process UUID. - /// \param[in] _nUuid Node UUID. - /// \param[out] _pubs Vector of publishers. - public: void PublishersByNode(const std::string &_pUuid, - const std::string &_nUuid, - std::vector &_pubs) const - { - _pubs.clear(); + /// \brief Given a process UUID and the node UUID, the function returns + /// the list of publishers contained in the node. + /// \param[in] _pUuid Process UUID. + /// \param[in] _nUuid Node UUID. + /// \param[out] _pubs Vector of publishers. + public: void PublishersByNode(const std::string &_pUuid, + const std::string &_nUuid, + std::vector &_pubs) const + { + _pubs.clear(); - // Iterate over all the topics. - for (auto const &topic : this->data) + // Iterate over all the topics. + for (auto const &topic : this->data) + { + // m is {pUUID=>Publisher}. + auto const &m = topic.second; + if (m.find(_pUuid) != m.end()) { - // m is {pUUID=>Publisher}. - auto const &m = topic.second; - if (m.find(_pUuid) != m.end()) + auto const &v = m.at(_pUuid); + for (auto const &pub : v) { - auto const &v = m.at(_pUuid); - for (auto const &pub : v) + if (pub.NUuid() == _nUuid) { - if (pub.NUuid() == _nUuid) - { - _pubs.push_back(T(pub)); - } + _pubs.push_back(T(pub)); } } } } + } - /// \brief Get the list of topics currently stored. - /// \param[out] _topics List of stored topics. - public: void TopicList(std::vector &_topics) const - { - for (auto const &topic : this->data) - _topics.push_back(topic.first); - } + /// \brief Get the list of topics currently stored. + /// \param[out] _topics List of stored topics. + public: void TopicList(std::vector &_topics) const + { + for (auto const &topic : this->data) + _topics.push_back(topic.first); + } - /// \brief Print all the information for debugging purposes. - public: void Print() const + /// \brief Print all the information for debugging purposes. + public: void Print() const + { + std::cout << "---" << std::endl; + for (auto const &topic : this->data) { - std::cout << "---" << std::endl; - for (auto const &topic : this->data) + std::cout << "[" << topic.first << "]" << std::endl; + auto &m = topic.second; + for (auto const &proc : m) { - std::cout << "[" << topic.first << "]" << std::endl; - auto &m = topic.second; - for (auto const &proc : m) + std::cout << "\tProc. UUID: " << proc.first << std::endl; + auto &v = proc.second; + for (auto const &publisher : v) { - std::cout << "\tProc. UUID: " << proc.first << std::endl; - auto &v = proc.second; - for (auto const &publisher : v) - { - std::cout << publisher; - } + std::cout << publisher; } } } + } - /// \brief Clear the content. - public: void Clear() - { - this->data.clear(); - } - - /// \brief The keys are topics. The values are another map, where the key - /// is the process UUID and the value a vector of publishers. - private: std::map>> data; - }; + /// \brief Clear the content. + public: void Clear() + { + this->data.clear(); } + + /// \brief The keys are topics. The values are another map, where the key + /// is the process UUID and the value a vector of publishers. + private: std::map>> data; + }; } } diff --git a/include/gz/transport/TopicUtils.hh b/include/gz/transport/TopicUtils.hh index df022f8d3..1d889ed0a 100644 --- a/include/gz/transport/TopicUtils.hh +++ b/include/gz/transport/TopicUtils.hh @@ -24,125 +24,122 @@ #include "gz/transport/config.hh" #include "gz/transport/Export.hh" -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class TopicUtils TopicUtils.hh gz/transport/TopicUtils.hh + /// \brief This class provides different utilities related with topics. + class GZ_TRANSPORT_VISIBLE TopicUtils { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class TopicUtils TopicUtils.hh gz/transport/TopicUtils.hh - /// \brief This class provides different utilities related with topics. - class GZ_TRANSPORT_VISIBLE TopicUtils - { - /// \brief Determines if a namespace is valid. A namespace's length must - /// not exceed kMaxNameLength. - /// The following symbols are not allowed as part of the - /// namespace: '@', ':=', '~'. - /// \param[in] _ns Namespace to be checked. - /// \return true if the namespace is valid. - public: static bool IsValidNamespace(const std::string &_ns); + /// \brief Determines if a namespace is valid. A namespace's length must + /// not exceed kMaxNameLength. + /// The following symbols are not allowed as part of the + /// namespace: '@', ':=', '~'. + /// \param[in] _ns Namespace to be checked. + /// \return true if the namespace is valid. + public: static bool IsValidNamespace(const std::string &_ns); - /// \brief Determines if a partition is valid. - /// The same rules to validate a topic name applies to a partition with - /// the addition of the empty string, which is a valid partition (meaning - /// no partition is used). A partition name's length must not exceed - /// kMaxNameLength. - /// \param[in] _partition Partition to be checked. - /// \return true if the partition is valid. - public: static bool IsValidPartition(const std::string &_partition); + /// \brief Determines if a partition is valid. + /// The same rules to validate a topic name applies to a partition with + /// the addition of the empty string, which is a valid partition (meaning + /// no partition is used). A partition name's length must not exceed + /// kMaxNameLength. + /// \param[in] _partition Partition to be checked. + /// \return true if the partition is valid. + public: static bool IsValidPartition(const std::string &_partition); - /// \brief Determines if a topic name is valid. A topic name is any - /// non-empty alphanumeric string. The symbol '/' is also allowed as part - /// of a topic name. - /// The following symbols are not allowed as part of the - /// topic name: '@', ':=', '~'. - /// A topic name's length must not exceed kMaxNameLength. - /// Examples of valid topics: abc, /abc, /abc/de, /abc/de/ - /// \param[in] _topic Topic name to be checked. - /// \return true if the topic name is valid. - public: static bool IsValidTopic(const std::string &_topic); + /// \brief Determines if a topic name is valid. A topic name is any + /// non-empty alphanumeric string. The symbol '/' is also allowed as part + /// of a topic name. + /// The following symbols are not allowed as part of the + /// topic name: '@', ':=', '~'. + /// A topic name's length must not exceed kMaxNameLength. + /// Examples of valid topics: abc, /abc, /abc/de, /abc/de/ + /// \param[in] _topic Topic name to be checked. + /// \return true if the topic name is valid. + public: static bool IsValidTopic(const std::string &_topic); - /// \brief Get the full topic path given a namespace and a topic name. - /// A fully qualified topic name's length must not exceed kMaxNameLength. - /// The fully qualified name follows the next syntax: - /// \@\\@\/\ - /// where: - /// \: The name of the partition or empty string. - /// A "/" will be prefixed to the partition name unless is - /// empty or it already starts with slash. A trailing slash - /// will always be removed. - /// \: The namespace or empty string. A namespace is a prefix - /// applied to the topic name. If not empty, it will always - /// start with a "/". A trailing slash will always be - /// removed - /// \: The topic name. A trailing slash will always be removed. - /// - /// Note: Intuitively, you can imagine the fully qualified name as a - /// UNIX absolute path, where the partition is always surrounded by "@". - /// A namespace, if present, corresponds with the directories of the - /// path, and you can imagine the topic as the filename. - /// - /// E.g.: - /// Only topic: @@/topic - /// No partition: @@/namespace/topic1 - /// No namespace: @/partition@/topic1 - /// Partition+namespace+topic: @/my_partition@/name/space/topic - /// - /// \param[in] _partition Partition name. - /// \param[in] _ns Namespace. - /// \param[in] _topic Topic name. - /// \param[out] _name Fully qualified topic name. - /// \return True if the fully qualified name is valid - /// (if partition, namespace and topic are correct). - /// \sa IsValidPartition - /// \sa IsValidNamespace - /// \sa IsValidTopic - /// \sa DecomposeFullyQualifiedTopic - public: static bool FullyQualifiedName(const std::string &_partition, - const std::string &_ns, - const std::string &_topic, - std::string &_name); + /// \brief Get the full topic path given a namespace and a topic name. + /// A fully qualified topic name's length must not exceed kMaxNameLength. + /// The fully qualified name follows the next syntax: + /// \@\\@\/\ + /// where: + /// \: The name of the partition or empty string. + /// A "/" will be prefixed to the partition name unless is + /// empty or it already starts with slash. A trailing slash + /// will always be removed. + /// \: The namespace or empty string. A namespace is a prefix + /// applied to the topic name. If not empty, it will always + /// start with a "/". A trailing slash will always be + /// removed + /// \: The topic name. A trailing slash will always be removed. + /// + /// Note: Intuitively, you can imagine the fully qualified name as a + /// UNIX absolute path, where the partition is always surrounded by "@". + /// A namespace, if present, corresponds with the directories of the + /// path, and you can imagine the topic as the filename. + /// + /// E.g.: + /// Only topic: @@/topic + /// No partition: @@/namespace/topic1 + /// No namespace: @/partition@/topic1 + /// Partition+namespace+topic: @/my_partition@/name/space/topic + /// + /// \param[in] _partition Partition name. + /// \param[in] _ns Namespace. + /// \param[in] _topic Topic name. + /// \param[out] _name Fully qualified topic name. + /// \return True if the fully qualified name is valid + /// (if partition, namespace and topic are correct). + /// \sa IsValidPartition + /// \sa IsValidNamespace + /// \sa IsValidTopic + /// \sa DecomposeFullyQualifiedTopic + public: static bool FullyQualifiedName(const std::string &_partition, + const std::string &_ns, + const std::string &_topic, + std::string &_name); - /// \brief Decompose a fully qualified topic name into its partition and - /// topic strings. Note that if the topic is preceded by a namespace, then - /// the namespace and topic name will remain together as one string. - /// - /// Given a fully qualified topic name with the following syntax: - /// - /// \@\\@\/\ - /// - /// The _partition output argument will be set to \, and the - /// _namespaceAndTopic output argument will be set to - /// \/\. - /// - /// \param[in] _fullyQualifiedName The fully qualified topic name. - /// \param[out] _partition The partition component of the fully qualified - /// topic name. - /// \param[out] _namespaceAndTopic The namespace and topic name component. - /// Note that there is no way to distinguish between where a namespace - /// ends and a topic name begins, since topic names may contain slashes. - /// \return True if the topic and partition were set. - /// \sa FullyQualifiedName - public: static bool DecomposeFullyQualifiedTopic( - const std::string &_fullyQualifiedName, - std::string &_partition, - std::string &_namespaceAndTopic); + /// \brief Decompose a fully qualified topic name into its partition and + /// topic strings. Note that if the topic is preceded by a namespace, then + /// the namespace and topic name will remain together as one string. + /// + /// Given a fully qualified topic name with the following syntax: + /// + /// \@\\@\/\ + /// + /// The _partition output argument will be set to \, and the + /// _namespaceAndTopic output argument will be set to + /// \/\. + /// + /// \param[in] _fullyQualifiedName The fully qualified topic name. + /// \param[out] _partition The partition component of the fully qualified + /// topic name. + /// \param[out] _namespaceAndTopic The namespace and topic name component. + /// Note that there is no way to distinguish between where a namespace + /// ends and a topic name begins, since topic names may contain slashes. + /// \return True if the topic and partition were set. + /// \sa FullyQualifiedName + public: static bool DecomposeFullyQualifiedTopic( + const std::string &_fullyQualifiedName, + std::string &_partition, + std::string &_namespaceAndTopic); - /// \brief Convert a topic name to a valid topic. The input topic is - /// modified by: - /// * turning white space into `_`. - /// * removing special characters and combinations. - /// \param[in] _topic Input topic, which may be invalid. - /// \return A valid topic, or empty string if not possible to convert. - public: static std::string AsValidTopic(const std::string &_topic); + /// \brief Convert a topic name to a valid topic. The input topic is + /// modified by: + /// * turning white space into `_`. + /// * removing special characters and combinations. + /// \param[in] _topic Input topic, which may be invalid. + /// \return A valid topic, or empty string if not possible to convert. + public: static std::string AsValidTopic(const std::string &_topic); - /// \brief The kMaxNameLength specifies the maximum number of characters - /// allowed in a namespace, a partition name, a topic name, and a fully - /// qualified topic name. - public: static const uint16_t kMaxNameLength = 65535; - }; - } + /// \brief The kMaxNameLength specifies the maximum number of characters + /// allowed in a namespace, a partition name, a topic name, and a fully + /// qualified topic name. + public: static const uint16_t kMaxNameLength = 65535; + }; } } diff --git a/include/gz/transport/TransportTypes.hh b/include/gz/transport/TransportTypes.hh index 6c524671d..ecc1707d6 100644 --- a/include/gz/transport/TransportTypes.hh +++ b/include/gz/transport/TransportTypes.hh @@ -36,152 +36,149 @@ #include "gz/transport/config.hh" #include "gz/transport/Publisher.hh" -namespace gz +namespace gz::transport { - namespace transport - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \brief Forward declarations. - class IRepHandler; - class IReqHandler; - class ISubscriptionHandler; - class RawSubscriptionHandler; - class MessageInfo; - - /// \def Addresses_M - /// \brief Map that stores all generic publishers. - /// The keys are the process uuids of the nodes. For each uuid key, the - /// value contains the list of publishers advertising the topic within the - /// same process uuid. - template - using Addresses_M = std::map>; - - /// \def MsgAddresses_M - /// \brief Specialized Addresses_M map for message publishers. - using MsgAddresses_M = Addresses_M; - - /// \def SrvAddresses_M - /// \brief Specialized Addresses_M map for service publishers. - using SrvAddresses_M = Addresses_M; - - /// \def ProtoMsg - /// \brief An abbreviated protobuf message type. - using ProtoMsg = google::protobuf::Message; - - /// \def ProtoMsgPtr - /// \brief Shared pointer to any protobuf message. - using ProtoMsgPtr = std::shared_ptr; - - /// \def ISubscriptionHandlerPtr - /// \brief Shared pointer to ISubscriptionHandler. - using ISubscriptionHandlerPtr = std::shared_ptr; - - /// \def RawSubscriptionHandlerPtr - /// \brief Shared pointer to RawSubscriptionHandler - using RawSubscriptionHandlerPtr = std::shared_ptr; - - /// \def ISubscriptionHandler_M - /// \brief Map to store the different subscription handlers for a topic. - /// Each node can have its own subscription handler. The node id - /// is used as key and a pointer to a generic subscription handler is the - /// value. - using ISubscriptionHandler_M = - std::map; - - /// \def RawSubscriptionHandler_M - /// \brief Map to store the raw subscription handlers for a topic. - /// Each node can have its own raw subscription handler. The node id is used - /// as the key and a pointer to a raw subscription handler is the value. - using RawSubscriptionHandler_M = - std::map; - - /// \def IRepHandlerPtr - /// \brief Shared pointer to IRepHandler. - using IRepHandlerPtr = std::shared_ptr; - - /// \def IReqHandlerPtr - /// \brief Shared pointer to IReqHandler. - using IReqHandlerPtr = std::shared_ptr; - - /// \def IReqHandler_M - /// \brief Map to store the different service request handlers for a - /// topic. Each node can have its own request handler. The node id - /// is used as key. The value is another map, where the key is the request - /// UUID and the value is pointer to a generic request handler. - using IReqHandler_M = - std::map>; - - /// \def DiscoveryCallback - /// \brief The user can register callbacks of this type when new connections - /// or disconnections are detected by the discovery. The prototype of the - /// callback contains the publisher's information advertising a topic. - /// E.g.: void onDiscoveryResponse(const MessagePublisher &_publisher). - template - using DiscoveryCallback = std::function; - - /// \def MsgDiscoveryCallback - /// \brief Specialized DiscoveryCallback function for receiving a message - /// publisher. - using MsgDiscoveryCallback = - std::function; - - /// \def SrvDiscoveryCallback - /// \brief Specialized DiscoveryCallback function for receiving a service - /// publisher. - using SrvDiscoveryCallback = - std::function; - - /// \def MsgCallback - /// \brief User callback used for receiving messages: - /// \param[in] _msg Protobuf message containing the topic update. - /// \param[in] _info Message information (e.g.: topic name). - template - using MsgCallback = - std::function; - - /// \def RawCallback - /// \brief User callback used for receiving raw message data: - /// \param[in] _msgData string of a serialized protobuf message - /// \param[in] _size Number of bytes in the serialized message data - /// string. - /// \param[in] _info Message information - using RawCallback = - std::function; - - /// \def Timestamp - /// \brief Used to evaluate the validity of a discovery entry. - using Timestamp = std::chrono::steady_clock::time_point; - - /// \def DeallocFunc - /// \brief Used when passing data to be published using ZMQ. - /// \param[in] _data The buffer containing the message to be published. - /// \param[in] _hint This parameter can be used if more complex allocation - /// mechanism is used. Say we allocated the chunk using some "allocator" - /// object and we have to deallocate it via the same object. - /// In such case we can pass the pointer to allocator as a hint to - /// zmq::message_t and modify the deallocation function as follows: - /// - /// void my_free (void *data, void *hint) - /// { - /// ((allocator_t*) hint)->free (data); - /// } - /// \ref http://zeromq.org/blog:zero-copy - using DeallocFunc = void(void *_data, void *_hint); - - /// \brief The string type used for generic messages. - const std::string kGenericMessageType = "google.protobuf.Message"; - - /// \brief The high water mark of the receive message buffer. - /// \sa NodeShared::RcvHwm - const int kDefaultRcvHwm = 1000; - - /// \brief The high water mark of the send message buffer. - /// \sa NodeShared::SndHwm - const int kDefaultSndHwm = 1000; - } + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \brief Forward declarations. + class IRepHandler; + class IReqHandler; + class ISubscriptionHandler; + class RawSubscriptionHandler; + class MessageInfo; + + /// \def Addresses_M + /// \brief Map that stores all generic publishers. + /// The keys are the process uuids of the nodes. For each uuid key, the + /// value contains the list of publishers advertising the topic within the + /// same process uuid. + template + using Addresses_M = std::map>; + + /// \def MsgAddresses_M + /// \brief Specialized Addresses_M map for message publishers. + using MsgAddresses_M = Addresses_M; + + /// \def SrvAddresses_M + /// \brief Specialized Addresses_M map for service publishers. + using SrvAddresses_M = Addresses_M; + + /// \def ProtoMsg + /// \brief An abbreviated protobuf message type. + using ProtoMsg = google::protobuf::Message; + + /// \def ProtoMsgPtr + /// \brief Shared pointer to any protobuf message. + using ProtoMsgPtr = std::shared_ptr; + + /// \def ISubscriptionHandlerPtr + /// \brief Shared pointer to ISubscriptionHandler. + using ISubscriptionHandlerPtr = std::shared_ptr; + + /// \def RawSubscriptionHandlerPtr + /// \brief Shared pointer to RawSubscriptionHandler + using RawSubscriptionHandlerPtr = std::shared_ptr; + + /// \def ISubscriptionHandler_M + /// \brief Map to store the different subscription handlers for a topic. + /// Each node can have its own subscription handler. The node id + /// is used as key and a pointer to a generic subscription handler is the + /// value. + using ISubscriptionHandler_M = + std::map; + + /// \def RawSubscriptionHandler_M + /// \brief Map to store the raw subscription handlers for a topic. + /// Each node can have its own raw subscription handler. The node id is used + /// as the key and a pointer to a raw subscription handler is the value. + using RawSubscriptionHandler_M = + std::map; + + /// \def IRepHandlerPtr + /// \brief Shared pointer to IRepHandler. + using IRepHandlerPtr = std::shared_ptr; + + /// \def IReqHandlerPtr + /// \brief Shared pointer to IReqHandler. + using IReqHandlerPtr = std::shared_ptr; + + /// \def IReqHandler_M + /// \brief Map to store the different service request handlers for a + /// topic. Each node can have its own request handler. The node id + /// is used as key. The value is another map, where the key is the request + /// UUID and the value is pointer to a generic request handler. + using IReqHandler_M = + std::map>; + + /// \def DiscoveryCallback + /// \brief The user can register callbacks of this type when new connections + /// or disconnections are detected by the discovery. The prototype of the + /// callback contains the publisher's information advertising a topic. + /// E.g.: void onDiscoveryResponse(const MessagePublisher &_publisher). + template + using DiscoveryCallback = std::function; + + /// \def MsgDiscoveryCallback + /// \brief Specialized DiscoveryCallback function for receiving a message + /// publisher. + using MsgDiscoveryCallback = + std::function; + + /// \def SrvDiscoveryCallback + /// \brief Specialized DiscoveryCallback function for receiving a service + /// publisher. + using SrvDiscoveryCallback = + std::function; + + /// \def MsgCallback + /// \brief User callback used for receiving messages: + /// \param[in] _msg Protobuf message containing the topic update. + /// \param[in] _info Message information (e.g.: topic name). + template + using MsgCallback = + std::function; + + /// \def RawCallback + /// \brief User callback used for receiving raw message data: + /// \param[in] _msgData string of a serialized protobuf message + /// \param[in] _size Number of bytes in the serialized message data + /// string. + /// \param[in] _info Message information + using RawCallback = + std::function; + + /// \def Timestamp + /// \brief Used to evaluate the validity of a discovery entry. + using Timestamp = std::chrono::steady_clock::time_point; + + /// \def DeallocFunc + /// \brief Used when passing data to be published using ZMQ. + /// \param[in] _data The buffer containing the message to be published. + /// \param[in] _hint This parameter can be used if more complex allocation + /// mechanism is used. Say we allocated the chunk using some "allocator" + /// object and we have to deallocate it via the same object. + /// In such case we can pass the pointer to allocator as a hint to + /// zmq::message_t and modify the deallocation function as follows: + /// + /// void my_free (void *data, void *hint) + /// { + /// ((allocator_t*) hint)->free (data); + /// } + /// \ref http://zeromq.org/blog:zero-copy + using DeallocFunc = void(void *_data, void *_hint); + + /// \brief The string type used for generic messages. + const std::string kGenericMessageType = "google.protobuf.Message"; + + /// \brief The high water mark of the receive message buffer. + /// \sa NodeShared::RcvHwm + const int kDefaultRcvHwm = 1000; + + /// \brief The high water mark of the send message buffer. + /// \sa NodeShared::SndHwm + const int kDefaultSndHwm = 1000; } } #endif diff --git a/include/gz/transport/Uuid.hh b/include/gz/transport/Uuid.hh index 42001f751..37fb0112b 100644 --- a/include/gz/transport/Uuid.hh +++ b/include/gz/transport/Uuid.hh @@ -33,49 +33,46 @@ using portable_uuid_t = uuid_t; #endif -namespace gz +namespace gz::transport { - namespace transport + // Inline bracket to help doxygen filtering. + inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { + // + /// \class Uuid Uuid.hh gz/transport/Uuid.hh + /// \brief A portable class for representing a Universally Unique Identifier + class GZ_TRANSPORT_VISIBLE Uuid { - // Inline bracket to help doxygen filtering. - inline namespace GZ_TRANSPORT_VERSION_NAMESPACE { - // - /// \class Uuid Uuid.hh gz/transport/Uuid.hh - /// \brief A portable class for representing a Universally Unique Identifier - class GZ_TRANSPORT_VISIBLE Uuid - { - /// \brief Constructor. - public: Uuid(); + /// \brief Constructor. + public: Uuid(); - /// \brief Destructor. - public: virtual ~Uuid(); + /// \brief Destructor. + public: virtual ~Uuid(); - /// \brief Return the string representation of the Uuid. - /// \return the UUID in string format. - public: std::string ToString() const; + /// \brief Return the string representation of the Uuid. + /// \return the UUID in string format. + public: std::string ToString() const; - /// \brief Stream insertion operator. - /// \param[out] _out The output stream. - /// \param[in] _uuid UUID to write to the stream. - public: friend std::ostream &operator<<(std::ostream &_out, - const gz::transport::Uuid &_uuid) - { - _out << _uuid.ToString(); - return _out; - } + /// \brief Stream insertion operator. + /// \param[out] _out The output stream. + /// \param[in] _uuid UUID to write to the stream. + public: friend std::ostream &operator<<(std::ostream &_out, + const gz::transport::Uuid &_uuid) + { + _out << _uuid.ToString(); + return _out; + } - /// \brief Length of a UUID in string format. - /// A UUID is a 16-octet number. In its string representation, every octet - /// is divided in two parts, and each part (4 bits) is represented as an - /// hexadecimal value. A UUID is also displayed in five groups separated - /// by hyphens, in the form 8-4-4-4-12 for a total of 36 characters. - /// To summarize: 36 octets + \0 = 37 octets. - private: static const int UuidStrLen = 37; + /// \brief Length of a UUID in string format. + /// A UUID is a 16-octet number. In its string representation, every octet + /// is divided in two parts, and each part (4 bits) is represented as an + /// hexadecimal value. A UUID is also displayed in five groups separated + /// by hyphens, in the form 8-4-4-4-12 for a total of 36 characters. + /// To summarize: 36 octets + \0 = 37 octets. + private: static const int UuidStrLen = 37; - /// \brief Internal representation. - private: portable_uuid_t data; - }; - } + /// \brief Internal representation. + private: portable_uuid_t data; + }; } } #endif