Ejemplo n.º 1
0
 def unregisterPublisher(self, caller_id, topic, caller_api,
                         client_ip_address):
     """
     Unregister the caller as a publisher of the topic.
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param topic: Fully-qualified name of topic to unregister.
     @type  topic: str
     @param caller_api str: API URI of service to
        unregister. Unregistration will only occur if current
        registration matches.
     @type  caller_api: str
     @return: (code, statusMessage, numUnregistered). 
        If numUnregistered is zero it means that the caller was not registered as a publisher.
        The call still succeeds as the intended final state is reached.
     @rtype: (int, str, int)
     """
     if not is_uri_match(caller_api, client_ip_address):
         self.logger.warn(
             "unregisterPublisher( %s, %s, %s, %s ) caller_api not authorized"
             % (caller_id, topic, caller_api, client_ip_address))
         return -1, "caller_api not authorized", []
     try:
         self.ps_lock.acquire()
         retval = self.reg_manager.unregister_publisher(
             topic, caller_id, caller_api)
         if retval[VAL]:
             self._notify_topic_subscribers(
                 topic, self.publishers.get_apis(topic),
                 self.subscribers.get_apis(topic))
         mloginfo("-PUB [%s] %s %s", topic, caller_id, caller_api)
     finally:
         self.ps_lock.release()
     return retval
Ejemplo n.º 2
0
 def unsubscribeParam(self, caller_id, caller_api, key, client_ip_address):
     """
     Retrieve parameter value from server and subscribe to updates to that param. See
     paramUpdate() in the Node API. 
     @param caller_id str: ROS caller id
     @type  caller_id: str
     @param key: parameter to lookup.
     @type  key: str
     @param caller_api: API URI for paramUpdate callbacks.
     @type  caller_api: str
     @return: [code, statusMessage, numUnsubscribed]. 
        If numUnsubscribed is zero it means that the caller was not subscribed to the parameter.
     @rtype: [int, str, int]
     """
     if not is_uri_match(caller_api, client_ip_address):
         self.logger.warn(
             "unsubscribeParam( %s, %s, %s, %s) caller_api not authorized" %
             (caller_id, caller_api, key, client_ip_address))
         return -1, "caller_api not authorized", 0
     key = resolve_name(key, caller_id)
     try:
         # ps_lock is required due to potential self.reg_manager modification
         self.ps_lock.acquire()
         retval = self.param_server.unsubscribe_param(
             key, (caller_id, caller_api))
     finally:
         self.ps_lock.release()
     return 1, "Unsubscribe to parameter [%s]" % key, 1
Ejemplo n.º 3
0
 def unregisterService(self, caller_id, service, service_api,
                       client_ip_address):
     """
     Unregister the caller as a provider of the specified service.
     @param caller_id str: ROS caller id
     @type  caller_id: str
     @param service: Fully-qualified name of service
     @type  service: str
     @param service_api: API URI of service to unregister. Unregistration will only occur if current
        registration matches.
     @type  service_api: str
     @return: (code, message, numUnregistered). Number of unregistrations (either 0 or 1).
        If this is zero it means that the caller was not registered as a service provider.
        The call still succeeds as the intended final state is reached.
     @rtype: (int, str, int)
     """
     if not is_uri_match(service_api, client_ip_address):
         self.logger.warn(
             "unregisterService( %s, %s, %s, %s ) service_api not authorized"
             % (caller_id, service, service_api, client_ip_address))
         return -1, "service_api not authorized", 0
     try:
         self.ps_lock.acquire()
         retval = self.reg_manager.unregister_service(
             service, caller_id, service_api)
         mloginfo("-SERVICE [%s] %s %s", service, caller_id, service_api)
         return retval
     finally:
         self.ps_lock.release()
Ejemplo n.º 4
0
 def publisherUpdate(self, caller_id, topic, publishers, client_ip_address):
     """
     Callback from master of current publisher list for specified topic.
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param topic str: topic name
     @type  topic: str
     @param publishers: list of current publishers for topic in the form of XMLRPC URIs
     @type  publishers: [str]
     @return: [code, status, ignore]
     @rtype: [int, str, int]
     """
     """ Check if request is from master. if so, no need to check if publisher URI is authorized """
     if not is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn(
             "publisherUpdate( %s, %s, %s ) method not authorized" %
             (caller_id, topic, client_ip_address))
         return -1, "method not authorized", []
     auth_logger.info("publisherUpdate( %s, %s, %s ): OK" %
                      (caller_id, topic, client_ip_address))
     auth_logger.debug("  with %s" % publishers)
     if self.reg_man:
         for uri in publishers:
             self.reg_man.publisher_update(topic, publishers)
     return 1, "", 0
Ejemplo n.º 5
0
 def subscribeParam(self, caller_id, caller_api, key, client_ip_address):
     """
     Retrieve parameter value from server and subscribe to updates to that param. See
     paramUpdate() in the Node API. 
     @param caller_id str: ROS caller id
     @type  caller_id: str
     @param key: parameter to lookup.
     @type  key: str
     @param caller_api: API URI for paramUpdate callbacks.
     @type  caller_api: str
     @return: [code, statusMessage, parameterValue]. If code is not
        1, parameterValue should be ignored. parameterValue is an empty dictionary if the parameter
        has not been set yet.
     @rtype: [int, str, XMLRPCLegalValue]
     """
     key = resolve_name(key, caller_id)
     if not is_uri_match(caller_api, client_ip_address):
         self.logger.warn(
             "subscribeParam( %s, %s, %s, %s) caller_api not authorized" %
             (caller_id, caller_api, key, client_ip_address))
         return -1, "caller_api not authorized", 0
     if not self.auth.check_param_setter(key, client_ip_address):
         self.logger.warn(
             "subscribeParam( %s, %s, %s, %s) parameter not authorized" %
             (caller_id, caller_api, key, client_ip_address))
         return -1, "parameter not authorized", 0
     try:
         # ps_lock has precedence and is required due to
         # potential self.reg_manager modification
         self.ps_lock.acquire()
         val = self.param_server.subscribe_param(key,
                                                 (caller_id, caller_api))
     finally:
         self.ps_lock.release()
     return 1, "Subscribed to parameter [%s]" % key, val
Ejemplo n.º 6
0
 def getPid(self, caller_id, client_ip_address):
     """
     Get the PID of this server
     @param caller_id: ROS caller id
     @type  caller_id: str
     @return: [1, "", serverProcessPID]
     @rtype: [int, str, int]
     """
     if is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn("shutdown( %s, '%s', %s ) method not authorized" %
                          (caller_id, msg, client_ip_address))
     return 1, "", os.getpid()
Ejemplo n.º 7
0
 def getBusInfo(self, caller_id, client_ip_address):
     """
     Retrieve transport/topic connection information
     @param caller_id: ROS caller id    
     @type  caller_id: str
     """
     """ Only master is authorized to call this method """
     if is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn("getBusInfo( %s, %s ) method not authorized" %
                          (caller_id, client_ip_address))
         return 1, "bus info", get_topic_manager().get_pub_sub_info()
     else:
         return -1, "method not authorized", []
Ejemplo n.º 8
0
 def getPublications(self, caller_id, client_ip_address):
     """
     Retrieve a list of topics that this node publishes.
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: list of topics published by this node.
     @rtype: [int, str, [ [topic1, topicType1]...[topicN, topicTypeN]]]
     """
     if not is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn(
             "getPublications( %s, %s ) method not authorized" %
             (caller_id, client_ip_address))
         return -1, "method not authorized", []
     return 1, "publications", get_topic_manager().get_publications()
Ejemplo n.º 9
0
 def lookupNode(self, caller_id, node_name, client_ip_address):
     """
     Get the XML-RPC URI of the node with the associated name/caller_id.  
     A caller_id can get this information only if it has a relation with this node, ie, 
     it is a subscriber or publisher to a topic with this node. 
     This API is for looking information about publishers and subscribers. 
     Use lookupService instead to lookup ROS-RPC URIs.
     SecureROS: This will be called by publisher (client_ip_address) to subscriber (node_name)
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param node: name of node to lookup
     @type  node: str
     @return: (code, msg, URI)
     @rtype: (int, str, str)
     """
     try:
         self.ps_lock.acquire()
         node = self.reg_manager.get_node(node_name)
         if node is not None:
             retval = 1, "node api", node.api
         else:
             retval = -1, "unknown node [%s]" % node_name, ''
     finally:
         self.ps_lock.release()
     if is_uri_match(self.uri, client_ip_address):
         """ all requests from master are authorized  """
         return retval
     else:
         """ Allow if node is the subscriber to a topic for which client_ip_address is a peer_publisher
         """
         if node is not None:
             if self.auth.check_peer_publisher_to_api(
                     node.api, client_ip_address):
                 self.auth.logger.info(
                     "lookupNode( %s, %s, %s ): OK (%s is peer publisher to %s)"
                     % (caller_id, node_name, client_ip_address,
                        client_ip_address, node.api))
                 return retval
             else:
                 self.auth.logger.info(
                     "lookupNode( %s, %s, %s ): No (%s is not peer publisher to %s)"
                     % (caller_id, node_name, client_ip_address,
                        client_ip_address, node.api))
                 return -1, "node_name not authorized", ''
     self.auth.logger.warn(
         "lookupNode( %s, %s, %s ): node_name is not valid" %
         (caller_id, node_name, client_ip_address))
     return -1, "node_name not authorized", ''
Ejemplo n.º 10
0
 def shutdown(self, caller_id, msg, client_ip_address):
     """
     Stop this server
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param msg: a message describing why the node is being shutdown. (XXX no longer an optional argument)
     @type  msg: str
     @return: [code, msg, 0]
     @rtype: [int, str, int]
     """
     if not is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn("shutdown( %s, '%s', %s ) method not authorized" %
                          (caller_id, msg, client_ip_address))
         return -1, "method not authorized", 0
     if self._shutdown('external shutdown request from [%s]: %s' %
                       (caller_id, msg)):
         signal_shutdown('external shutdown request from [%s]: [%s]' %
                         (caller_id, msg))
     return 1, "shutdown", 0
Ejemplo n.º 11
0
 def getBusStats(self, caller_id, client_ip_address):
     """
     Retrieve transport/topic statistics
     @param caller_id: ROS caller id    
     @type  caller_id: str
     @return: [publishStats, subscribeStats, serviceStats]::
        publishStats: [[topicName, messageDataSent, pubConnectionData]...[topicNameN, messageDataSentN, pubConnectionDataN]]
            pubConnectionData: [connectionId, bytesSent, numSent, connected]* . 
        subscribeStats: [[topicName, subConnectionData]...[topicNameN, subConnectionDataN]]
            subConnectionData: [connectionId, bytesReceived, dropEstimate, connected]* . dropEstimate is -1 if no estimate. 
        serviceStats: not sure yet, probably akin to [numRequests, bytesReceived, bytesSent] 
     """
     is_master = is_uri_match(self.masterUri, client_ip_address)
     pub_stats, sub_stats = get_topic_manager().get_pub_sub_stats()
     #TODO: serviceStats
     if is_master:
         return 1, '', [pub_stats, sub_stats, []]
     else:
         return -1, "Only master authorized to call getBusStats()", []
Ejemplo n.º 12
0
def is_subscriber_authorized(topic, client_ip_address):
    """ Get list of subscriber nodes from master for each topic.
        For this given topic, check if the caller node is a valid node.
        If the caller node is valid, get the URI for this node and check if this URI matches 
        the caller IP address (client_ip_address).
        We use the valid URI list from master for this topic and checking if the 
        client_ip_address of the caller matches with one of the valid URIs.

        @param topic: Topic for which subscriber authorization is requested
        @param client_ip_address: Client IP address for which authorization check is requested 

        @return: If client_ip_address is authorized for topic 
        @rtype: bool
    """
    masterUri = rosgraph.get_master_uri()
    this_caller_id = rospy.names.get_caller_id()
    auth_logger.debug("Getting subscribers for topic [%s]" % topic)
    subs = get_subscriber_list(masterUri, topic, this_caller_id)
    auth_logger.debug("- [%s]" % (','.join('%s' % n for n in subs)))

    if len(subs) == 0:
        return False
    """ We want to check if client_ip_address matches one of n (for each n in subs)
        This node is the publisher and n is the subscriber
    """
    for n in subs:
        code, msg, uri = xmlrpcapi(masterUri).lookupNode(this_caller_id, n)
        auth_logger.debug(
            "lookupNode( %s, %s ) returned (code=%s, msg=%s, uri=%s)" %
            (this_caller_id, n, code, msg, uri))
        if code > 0:
            if is_uri_match(uri, client_ip_address):
                auth_logger.info(
                    "Subscriber %s XMLRPC URI (%s) matches client IP (%s)" %
                    (n, uri, client_ip_address))
                return True
            else:
                auth_logger.debug(
                    "Subscriber %s XMLRPC URI (%s) does not match client IP (%s)"
                    % (n, uri, client_ip_address))
    auth_logger.warn("Client (%s) not authorized for topic %s" %
                     (client_ip_address, topic))
    return False
Ejemplo n.º 13
0
 def shutdown(self, caller_id, msg, client_ip_address):
     """
     Stop this server
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param msg: a message describing why the node is being shutdown. (XXX no longer an optional argument)
     @type  msg: str 
     @return: [code, msg, 0]
     @rtype: [int, str, int]
     """
     if not is_uri_match(self.uri, client_ip_address):
         self.logger.warn("shutdown( %s, %s ) method not authorized" %
                          (caller_id, client_ip_address))
         return -1, "shutdown not authorized", 0
     if msg:
         print("shutdown request: %s" % msg, file=sys.stdout)
     else:
         print("shutdown request", file=sys.stdout)
     self._shutdown('external shutdown request from [%s]: %s' %
                    (caller_id, msg))
     return 1, "shutdown", 0
Ejemplo n.º 14
0
    def getSystemState(self, caller_id, client_ip_address):
        """
        Retrieve list representation of system state (i.e. publishers, subscribers, and services).
        @param caller_id: ROS caller id    
        @type  caller_id: str
        @rtype: (int, str, [[str,[str]], [str,[str]], [str,[str]]])
        @return: (code, statusMessage, systemState).

           System state is in list representation::
             [publishers, subscribers, services].
        
           publishers is of the form::
             [ [topic1, [topic1Publisher1...topic1PublisherN]] ... ]
        
           subscribers is of the form::
             [ [topic1, [topic1Subscriber1...topic1SubscriberN]] ... ]
        
           services is of the form::
             [ [service1, [service1Provider1...service1ProviderN]] ... ]
        """
        edges = []
        try:
            self.ps_lock.acquire()
            retval = [
                r.get_state()
                for r in (self.publishers, self.subscribers, self.services)
            ]
        finally:
            self.ps_lock.release()

        if not is_uri_match(self.uri, client_ip_address):
            pubs = [[t, tpubs] for [t, tpubs] in retval[0]
                    if self.auth.check_subscriber(t, client_ip_address)]
            subs = [[t, tsubs] for [t, tsubs] in retval[1]
                    if self.auth.check_publisher(t, client_ip_address)]
            services = retval[2]
            retval = [pubs, subs, services]
        return 1, "current system state", retval
Ejemplo n.º 15
0
 def paramUpdate(self, caller_id, parameter_key, parameter_value,
                 client_ip_address):
     """
     Callback from master of current publisher list for specified topic.
     @param caller_id: ROS caller id
     @type  caller_id: str
     @param parameter_key str: parameter name, globally resolved
     @type  parameter_key: str
     @param parameter_value New parameter value
     @type  parameter_value: XMLRPC-legal value
     @return: [code, status, ignore]. If code is -1 ERROR, the node
     is not subscribed to parameter_key
     @rtype: [int, str, int]
     """
     if not is_uri_match(self.masterUri, client_ip_address):
         auth_logger.warn(
             "paramUpdate( %s, %s, %s ) method not authorized" %
             (caller_id, parameter_key, client_ip_address))
         return -1, "method not authorized", []
     try:
         get_param_server_cache().update(parameter_key, parameter_value)
         return 1, '', 0
     except KeyError:
         return -1, 'not subscribed', 0