Skip to content

Commit

Permalink
Improve Subscription features and fix IntraTransport discovery (#106)
Browse files Browse the repository at this point in the history
* Add ServiceSubscription::UpdateServiceByType to c++ and python

* Fix parameter error on Linux in Subscription.cpp

* Fix debug build errors in Subscription.cpp

* Add subscription filter attribute filter

* Pass boost::regex by reference

* Pass boost::regex by reference

* Fix IntraTransport client node discovery

* Improve service attribute filter, add Python wrapper support

* Add python documentation for attribute filters

* Add service filter attributes to net wrappers

* Add service filter attributes to matlab wrapper

* Fix segfault in subscriber filter tests

* Fix potential segfaults in NET and Java for ServiceSubscriptionClientID

* Fix clang-tidy errors

* Fix clang-tidy errors

* Code formatting
  • Loading branch information
johnwason committed Jul 3, 2023
1 parent 7e7e0d0 commit 5660d41
Show file tree
Hide file tree
Showing 22 changed files with 1,456 additions and 14 deletions.
8 changes: 8 additions & 0 deletions RobotRaconteurCore/include/RobotRaconteur/IntraTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ class ROBOTRACONTEUR_CORE_API IntraTransport : public Transport, public RR_ENABL
*/
virtual void StartServer();

/**
* @brief Start the transport as a client
*
*/
virtual void StartClient();

protected:
virtual void CloseTransportConnection_timed(const boost::system::error_code& err, const RR_SHARED_PTR<Endpoint>& e,
const RR_SHARED_PTR<void>& timer);
Expand Down Expand Up @@ -156,6 +162,8 @@ class ROBOTRACONTEUR_CORE_API IntraTransport : public Transport, public RR_ENABL

void SendNodeDiscovery();

void DiscoverAllNodes();

protected:
virtual void register_transport(const RR_SHARED_PTR<ITransportConnection>& connection);
virtual void erase_transport(const RR_SHARED_PTR<ITransportConnection>& connection);
Expand Down
262 changes: 262 additions & 0 deletions RobotRaconteurCore/include/RobotRaconteur/Subscription.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,251 @@ class ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilterNode
RR_INTRUSIVE_PTR<RRMap<std::string, RRValue> > Credentials;
};

/**
* @brief Subscription filter attribute for use with ServiceSubscriptionFilter
*
*/
class ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilterAttribute
{
public:
/** @brief The attribute name. Empty for no name */
std::string Name;
/** @brief The string value of the attribute */
std::string Value;
/** @brief The regex value of the attribute */
boost::regex ValueRegex;
/** @brief True if ValueRegex is used, otherwise Value is matched */
bool UseRegex;

/**
* @brief Construct a new Service Subscription Filter Attribute object
*
*/
ServiceSubscriptionFilterAttribute();
/**
* @brief Construct a new Service Subscription Filter Attribute object
*
* This is a nameless attribute for use with attribute lists
*
* @param value The attribute value
*/
ServiceSubscriptionFilterAttribute(boost::string_ref value);
/**
* @brief Construct a new Service Subscription Filter Attribute object
*
* This is a nameless attribute for use with attribute lists. The value is compared using a regex
*
* @param value_regex The attribute value regex
*/
ServiceSubscriptionFilterAttribute(const boost::regex& value_regex);
/**
* @brief Construct a new Service Subscription Filter Attribute object
*
* This is a named attribute for use with attribute maps
*
* @param name The attribute name
* @param value The attribute value
*/
ServiceSubscriptionFilterAttribute(boost::string_ref name, boost::string_ref value);

/**
* @brief Construct a new Service Subscription Filter Attribute object
*
* This is a named attribute for use with attribute maps. The value is compared using a regex
*
* @param name The attribute name
* @param value_regex The attribute value regex
*/
ServiceSubscriptionFilterAttribute(boost::string_ref name, const boost::regex& value_regex);

/**
* @brief Compare the attribute to a value
*
* @param value The value to compare
* @return true
* @return false
*/
bool IsMatch(boost::string_ref value) const;
/**
* @brief Compare the attribute to a named value
*
* @param name The name to compare
* @param value The value to compare
* @return true
* @return false
*/
bool IsMatch(boost::string_ref name, boost::string_ref value) const;
/**
* @brief Compare the attribute to a value list using OR logic
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const std::vector<std::string>& values) const;
/**
* @brief Compare the attribute to a value list using OR logic
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const RR_INTRUSIVE_PTR<RRList<RRValue> >& values) const;
/**
* @brief Compare the attribute to a value map using OR logic
*
* @param values The value map to compare
* @return true
* @return false
*/
bool IsMatch(const RR_INTRUSIVE_PTR<RRMap<std::string, RRValue> >& values) const;
/**
* @brief Compare the attribute to a value map using OR logic
*
* @param values The value map to compare
* @return true
* @return false
*/
bool IsMatch(const std::map<std::string, std::string>& values) const;
};

/**
* @brief Create a ServiceSubscriptionFilterAttribute from a regex string
*
* @param regex_value The regex string to compile
* @return ServiceSubscriptionFilterAttribute The created attribute
*/
ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilterAttribute
CreateServiceSubscriptionFilterAttributeRegex(boost::string_ref regex_value);
/**
* @brief Create a ServiceSubscriptionFilterAttribute from a regex string
*
* @param name The attribute name
* @param regex_value The regex string to compile
* @return ROBOTRACONTEUR_CORE_API
*/
ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilterAttribute
CreateServiceSubscriptionFilterAttributeRegex(boost::string_ref name, boost::string_ref regex_value);

/**
* @brief Comparison operations for ServiceSubscriptionFilterAttributeGroup
*
*/
enum ServiceSubscriptionFilterAttributeGroupOperation
{
/** @brief OR operation */
ServiceSubscriptionFilterAttributeGroupOperation_OR,
/** @brief AND operation */
ServiceSubscriptionFilterAttributeGroupOperation_AND,
/** @brief NOR operation. Also used for NOT */
ServiceSubscriptionFilterAttributeGroupOperation_NOR,
/** @brief NAND operation */
ServiceSubscriptionFilterAttributeGroupOperation_NAND
};

/**
* @brief Subscription filter attribute group for use with ServiceSubscriptionFilter
*
* Used to combine multiple ServiceSubscriptionFilterAttribute objects for comparison using
* AND, OR, NOR, or NAND logic. Other groups can be nested, to allow for complex comparisons.
*/
class ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilterAttributeGroup
{
public:
/** @brief The attributes in the group */
std::vector<ServiceSubscriptionFilterAttribute> Attributes;
/** @brief The nested groups in the group */
std::vector<ServiceSubscriptionFilterAttributeGroup> Groups;
/** @brief The operation to use for matching the attributes and groups */
ServiceSubscriptionFilterAttributeGroupOperation Operation;

/** @brief True if string attributes will be split into a list with delimiter (default ",") */
bool SplitStringAttribute;
/** @brief Delimiter to use to split string attributes (default ",")*/
char SplitStringDelimiter;

/**
* @brief Construct a new Service Subscription Filter Attribute Group object
*
*/
ServiceSubscriptionFilterAttributeGroup();
/**
* @brief Construct a new Service Subscription Filter Attribute Group object
*
* @param operation The operation to use for matching the attributes and groups
*/
ServiceSubscriptionFilterAttributeGroup(ServiceSubscriptionFilterAttributeGroupOperation operation);
/**
* @brief Construct a new Service Subscription Filter Attribute Group object
*
* @param operation The operation to use for matching the attributes and groups
* @param attributes The attributes in the group
*/
ServiceSubscriptionFilterAttributeGroup(ServiceSubscriptionFilterAttributeGroupOperation operation,
std::vector<ServiceSubscriptionFilterAttribute> attributes);
/**
* @brief Construct a new Service Subscription Filter Attribute Group object
*
* @param operation The operation to use for matching the attributes and groups
* @param groups The nested groups in the group
*/
ServiceSubscriptionFilterAttributeGroup(ServiceSubscriptionFilterAttributeGroupOperation operation,
std::vector<ServiceSubscriptionFilterAttributeGroup> groups);

/**
* @brief Compare the group to a value
*
* @param value The value to compare
* @return true
* @return false
*/
bool IsMatch(boost::string_ref value) const;

/**
* @brief Compare the group to a value
*
* @param value The value to compare
* @return true
* @return false
*/
bool IsMatch(RR_INTRUSIVE_PTR<RRArray<char> >& value) const;

/**
* @brief Compare the group to a list of values
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const std::vector<std::string>& values) const;
/**
* @brief Compare the group to a list of values
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const RR_INTRUSIVE_PTR<RRList<RRValue> >& values) const;
/**
* @brief Compare the group to a map of values
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const RR_INTRUSIVE_PTR<RRMap<std::string, RRValue> >& values) const;
/**
* @brief Compare the group to a map of values
*
* @param values The values to compare
* @return true
* @return false
*/
bool IsMatch(const std::map<std::string, std::string>& values) const;

bool IsMatch(const RR_INTRUSIVE_PTR<RRValue>& value) const;
};

/**
* @brief Subscription filter
*
Expand All @@ -100,6 +345,10 @@ class ROBOTRACONTEUR_CORE_API ServiceSubscriptionFilter
std::vector<std::string> ServiceNames;
/** Vector of transport schemes. Empty means match any transport scheme. **/
std::vector<std::string> TransportSchemes;
/** Attributes to match */
std::map<std::string, ServiceSubscriptionFilterAttributeGroup> Attributes;
/** Operation to use to match attributes. Defaults to AND */
ServiceSubscriptionFilterAttributeGroupOperation AttributesMatchOperation;
/** A user specified predicate function. If nullptr, the predicate is not checked. **/
boost::function<bool(const ServiceInfo2&)> Predicate;
/** The maximum number of connections the subscription will create. Zero means unlimited connections. **/
Expand Down Expand Up @@ -668,6 +917,19 @@ class ROBOTRACONTEUR_CORE_API ServiceSubscription : public IServiceSubscription,
(RR_INTRUSIVE_PTR<RRMap<std::string, RRValue> >()),
boost::string_ref object_type = "", bool close_connected = false);

/**
* @brief Update the service type and filter for subscription
*
* Updates the existing target service types and filter for a running subscription
*
* @param service_types A std::vector of service types to listen for, ie `com.robotraconteur.robotics.robot.Robot`
* @param filter A filter to select individual services based on specified criteria
*/

void UpdateServiceByType(
const std::vector<std::string>& service_types,
const RR_SHARED_PTR<ServiceSubscriptionFilter>& filter = RR_SHARED_PTR<ServiceSubscriptionFilter>());

RR_SHARED_PTR<RobotRaconteurNode> GetNode();

protected:
Expand Down
11 changes: 10 additions & 1 deletion RobotRaconteurCore/src/Discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1989,10 +1989,19 @@ void Discovery::DoSubscribe(const std::vector<std::string>& service_types,
boost::mutex::scoped_lock lock(m_DiscoveredNodes_lock);
subscriptions.push_back(s);
s->Init(service_types, filter);
lock.unlock();
DoUpdateAllDetectedServices(s);
}

void Discovery::DoUpdateAllDetectedServices(const RR_SHARED_PTR<IServiceSubscription>& s)
{
boost::mutex::scoped_lock lock(m_DiscoveredNodes_lock);
if (this->is_shutdown)
{
return;
}
std::vector<RR_SHARED_PTR<Discovery_nodestorage> > storage;
boost::range::copy(m_DiscoveredNodes | boost::adaptors::map_values, std::back_inserter(storage));

lock.unlock();

BOOST_FOREACH (RR_SHARED_PTR<Discovery_nodestorage>& n, storage)
Expand Down
2 changes: 2 additions & 0 deletions RobotRaconteurCore/src/Discovery_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class Discovery : public RR_ENABLE_SHARED_FROM_THIS<Discovery>
void DoSubscribe(const std::vector<std::string>& service_types,
const RR_SHARED_PTR<ServiceSubscriptionFilter>& filter,
const RR_SHARED_PTR<IServiceSubscription>& subscription);

void DoUpdateAllDetectedServices(const RR_SHARED_PTR<IServiceSubscription>& s);
};

class Discovery_updatediscoverednodes : public RR_ENABLE_SHARED_FROM_THIS<Discovery_updatediscoverednodes>
Expand Down

0 comments on commit 5660d41

Please sign in to comment.