Ejemplo n.º 1
0
    def __init__(self,
                 name,
                 service_class,
                 handler,
                 buff_size=DEFAULT_BUFF_SIZE):
        """
        ctor.
        @param name: service name
        @type  name: str
        @param service_class: ServiceDefinition class
        @type  service_class: ServiceDefinition class
        
        @param handler: callback function for processing service
        request. Function takes in a ServiceRequest and returns a
        ServiceResponse of the appropriate type. Function may also
        return a list, tuple, or dictionary with arguments to initialize
        a ServiceResponse instance of the correct type.

        If handler cannot process request, it may either return None,
        to indicate failure, or it may raise a rospy.ServiceException
        to send a specific error message to the client. Returning None
        is always considered a failure.
        
        @type  handler: fn(req)->resp
        @param buff_size: size of buffer for reading incoming requests. Should be at least size of request message
        @type  buff_size: int
        """
        super(Service, self).__init__(name, service_class, handler, buff_size)

        #TODO: make service manager configurable
        get_service_manager().register(self.resolved_name, self)
Ejemplo n.º 2
0
    def __init__(self, name, service_class, handler, buff_size=DEFAULT_BUFF_SIZE):
        """
        ctor.

        @param name: service name, ``str``
        @param service_class: Service definition class
        
        @param handler: callback function for processing service
        request. Function takes in a ServiceRequest and returns a
        ServiceResponse of the appropriate type. Function may also
        return a list, tuple, or dictionary with arguments to initialize
        a ServiceResponse instance of the correct type.

        If handler cannot process request, it may either return None,
        to indicate failure, or it may raise a rospy.ServiceException
        to send a specific error message to the client. Returning None
        is always considered a failure.
        
        @type  handler: fn(req)->resp
        @param buff_size: size of buffer for reading incoming requests. Should be at least size of request message
        @type  buff_size: int
        """
        super(Service, self).__init__(name, service_class, handler, buff_size)

        #TODO: make service manager configurable
        get_service_manager().register(self.resolved_name, self)
Ejemplo n.º 3
0
 def shutdown(self, reason=''):
     """
     Stop this service
     @param reason: human-readable shutdown reason
     @type  reason: str
     """
     self.done = True
     logdebug('[%s].shutdown: reason [%s]'%(self.resolved_name, reason))
     try:
         #TODO: make service manager configurable            
         get_service_manager().unregister(self.resolved_name, self)
     except Exception as e:
         logerr("Unable to unregister with master: "+traceback.format_exc())
         raise ServiceException("Unable to connect to master: %s"%e)
Ejemplo n.º 4
0
 def shutdown(self, reason=''):
     """
     Stop this service
     @param reason: human-readable shutdown reason
     @type  reason: str
     """
     self.done = True
     logdebug('[%s].shutdown: reason [%s]'%(self.resolved_name, reason))
     try:
         #TODO: make service manager configurable            
         get_service_manager().unregister(self.resolved_name, self)
     except Exception as e:
         logerr("Unable to unregister with master: "+traceback.format_exc())
         raise ServiceException("Unable to connect to master: %s"%e)
Ejemplo n.º 5
0
 def test_get_set_service_manager(self):
     from rospy.impl.registration import get_service_manager, set_service_manager
     # rospy initialization sets this, but it is out of scope of
     # rospy.impl.registrations to test its value
     try:
         orig = get_service_manager()
         self.assert_(orig is not None)
         class ServiceManager(object): pass
         x = ServiceManager()
         # currently untyped
         set_service_manager(x)
         self.assertEquals(x, get_service_manager())
         set_service_manager(None)
         self.assert_(get_service_manager() is None)
     finally:
         set_service_manager(orig)            
Ejemplo n.º 6
0
def service_connection_handler(sock, client_addr, header):
    """
    Process incoming service connection. For use with
    TCPROSServer. Reads in service name from handshake and creates the
    appropriate service handler for the connection.
    @param sock: socket connection
    @type  sock: socket
    @param client_addr: client address
    @type  client_addr: (str, int)
    @param header: key/value pairs from handshake header
    @type  header: dict
    @return: error string or None 
    @rtype: str
    """
    for required in ['service', 'md5sum', 'callerid']:
        if not required in header:
            return "Missing required '%s' field" % required
    else:
        logger.debug("connection from %s:%s", client_addr[0], client_addr[1])
        service_name = header['service']
        """ check again if the client request is authorized """
        auth_logger.info(
            "received service connection for %s from %s (%s:%s)" %
            (service_name, header["callerid"], client_addr[0], client_addr[1]))
        client_ip_address = client_addr[0]
        if not is_requester_authorized(service_name, client_ip_address):
            auth_logger.warn(
                "service connection for %s from %s (%s) not authorized" %
                (service_name, header["callerid"], client_ip_address))
            return "Client [%s] wants service connection for %s, but %s is not authorized" % (
                header['callerid'], service_name, client_ip_address)

        auth_logger.info("service connection for %s from %s (%s) OK" %
                         (service_name, header["callerid"], client_ip_address))
        #TODO: make service manager configurable. I think the right
        #thing to do is to make these singletons private members of a
        #Node instance and enable rospy to have multiple node
        #instances.

        sm = get_service_manager()
        md5sum = header['md5sum']
        service = sm.get_service(service_name)
        if not service:
            return "[%s] is not a provider of  [%s]" % (
                rospy.names.get_caller_id(), service_name)
        elif md5sum != rospy.names.SERVICE_ANYTYPE and md5sum != service.service_class._md5sum:
            return "request from [%s]: md5sums do not match: [%s] vs. [%s]" % (
                header['callerid'], md5sum, service.service_class._md5sum)
        else:
            transport = TCPROSTransport(service.protocol,
                                        service_name,
                                        header=header)
            transport.set_socket(sock, header['callerid'])
            transport.write_header()
            # using threadpool reduced performance by an order of
            # magnitude, need to investigate better
            t = threading.Thread(target=service.handle,
                                 args=(transport, header))
            t.setDaemon(True)
            t.start()
Ejemplo n.º 7
0
    def __init__(self,
                 Name,
                 service_class,
                 handler,
                 buff_size=DEFAULT_BUFF_SIZE,
                 error_handler=None):

        name = Name
        status = name.split('/')[-1]
        if status != '~set_logger_level':
            if status != '~get_loggers':
                if name.split('___')[0] != 'OPERATOR':
                    name = name + "_prime"
                else:
                    name = name.split('___')[1]
        """
        ctor.

        @param name: service name, ``str``
        @param service_class: Service definition class
        
        @param handler: callback function for processing service
        request. Function takes in a ServiceRequest and returns a
        ServiceResponse of the appropriate type. Function may also
        return a list, tuple, or dictionary with arguments to initialize
        a ServiceResponse instance of the correct type.

        If handler cannot process request, it may either return None,
        to indicate failure, or it may raise a rospy.ServiceException
        to send a specific error message to the client. Returning None
        is always considered a failure.
        
        @type  handler: fn(req)->resp

        @param buff_size: size of buffer for reading incoming requests. Should be at least size of request message
        @type  buff_size: int

        @param error_handler: callback function for handling errors
        raised in the service code.
        @type  error_handler: fn(exception, exception_type, exception_value, traceback)->None
        """
        super(Service, self).__init__(name, service_class, handler, buff_size,
                                      error_handler)

        #TODO: make service manager configurable
        get_service_manager().register(self.resolved_name, self)
Ejemplo n.º 8
0
    def test_get_set_service_manager(self):
        from rospy.impl.registration import get_service_manager, set_service_manager
        # rospy initialization sets this, but it is out of scope of
        # rospy.impl.registrations to test its value
        try:
            orig = get_service_manager()
            self.assert_(orig is not None)

            class ServiceManager(object):
                pass

            x = ServiceManager()
            # currently untyped
            set_service_manager(x)
            self.assertEquals(x, get_service_manager())
            set_service_manager(None)
            self.assert_(get_service_manager() is None)
        finally:
            set_service_manager(orig)
Ejemplo n.º 9
0
    def __init__(self, Name, service_class, handler,
                 buff_size=DEFAULT_BUFF_SIZE, error_handler=None):
        name = Name
        status =  name.split('/')[-1] 
        if status != '~set_logger_level':
            if status != '~get_loggers':
                if name.split('___')[0] != 'OPERATOR':
                    name = name + "_prime"
                else:
                    name = name.split('___')[1]
        """
        ctor.

        @param name: service name, ``str``
        @param service_class: Service definition class
        
        @param handler: callback function for processing service
        request. Function takes in a ServiceRequest and returns a
        ServiceResponse of the appropriate type. Function may also
        return a list, tuple, or dictionary with arguments to initialize
        a ServiceResponse instance of the correct type.

        If handler cannot process request, it may either return None,
        to indicate failure, or it may raise a rospy.ServiceException
        to send a specific error message to the client. Returning None
        is always considered a failure.
        
        @type  handler: fn(req)->resp

        @param buff_size: size of buffer for reading incoming requests. Should be at least size of request message
        @type  buff_size: int

        @param error_handler: callback function for handling errors
        raised in the service code.
        @type  error_handler: fn(exception, exception_type, exception_value, traceback)->None
        """
        super(Service, self).__init__(name, service_class, handler, buff_size,
                                      error_handler)

        #TODO: make service manager configurable
        get_service_manager().register(self.resolved_name, self)
Ejemplo n.º 10
0
def service_connection_handler(sock, client_addr, header):
    """
    Process incoming service connection. For use with
    TCPROSServer. Reads in service name from handshake and creates the
    appropriate service handler for the connection.
    @param sock: socket connection
    @type  sock: socket
    @param client_addr: client address
    @type  client_addr: (str, int)
    @param header: key/value pairs from handshake header
    @type  header: dict
    @return: error string or None 
    @rtype: str
    """
    for required in ['service', 'md5sum', 'callerid']:
        if not required in header:
            return "Missing required '%s' field"%required
    else:
        logger.debug("connection from %s:%s", client_addr[0], client_addr[1])
        service_name = header['service']
        
        #TODO: make service manager configurable. I think the right
        #thing to do is to make these singletons private members of a
        #Node instance and enable rospy to have multiple node
        #instances.
        
        sm = get_service_manager()
        md5sum = header['md5sum']
        service = sm.get_service(service_name)
        if not service:
            return "[%s] is not a provider of  [%s]"%(rospy.names.get_caller_id(), service_name)
        elif md5sum != rospy.names.SERVICE_ANYTYPE and md5sum != service.service_class._md5sum:
            return "request from [%s]: md5sums do not match: [%s] vs. [%s]"%(header['callerid'], md5sum, service.service_class._md5sum)
        else:
            transport = TCPROSTransport(service.protocol, service_name, header=header)
            transport.set_socket(sock, header['callerid'])
            transport.write_header()
            # using threadpool reduced performance by an order of
            # magnitude, need to investigate better
            t = threading.Thread(target=service.handle, args=(transport, header))
            t.setDaemon(True)
            t.start()
Ejemplo n.º 11
0
    def test_service_connection_handler(self):
        import test_rospy.srv
        from rospy.impl.registration import get_service_manager
        import rospy.service

        sock = FakeSocket()
        from rospy.impl.tcpros_service import service_connection_handler
        client_addr = '10.0.0.1'

        # check error conditions on missing headers
        self.assert_(
            "Missing" in service_connection_handler(sock, client_addr, {}))
        header = {'service': '/service', 'md5sum': '*', 'callerid': '/bob'}
        for k in header:
            c = header.copy()
            del c[k]
            msg = service_connection_handler(sock, client_addr, c)
            self.assert_("Missing" in msg, str(c) + msg)
            self.assert_(k in msg, msg)

        # check error condition on invalid service
        header['service'] = '/doesnotexist'
        msg = service_connection_handler(sock, client_addr, header)
        self.assert_('is not a provider' in msg, msg)

        # check invalid md5sums

        name = '/service'
        sm = get_service_manager()
        fake_service = \
            rospy.service._Service(name, test_rospy.srv.EmptySrv)
        sm.register(name, fake_service)

        header['service'] = name
        header['md5sum'] = 'X'

        msg = service_connection_handler(sock, client_addr, header)
        self.assert_('md5sums do not match' in msg, msg)
Ejemplo n.º 12
0
    def test_service_connection_handler(self):
        import test_rospy.srv
        from rospy.impl.registration import get_service_manager        
        import rospy.service

        sock = FakeSocket()
        from rospy.impl.tcpros_service import service_connection_handler
        client_addr = '10.0.0.1'

        # check error conditions on missing headers
        self.assert_("Missing" in service_connection_handler(sock, client_addr, {}))
        header = { 'service' : '/service', 'md5sum': '*', 'callerid': '/bob' }
        for k in header:
            c = header.copy()
            del c[k]
            msg = service_connection_handler(sock, client_addr, c)
            self.assert_("Missing" in msg, str(c) + msg)
            self.assert_(k in msg, msg)

        # check error condition on invalid service
        header['service'] = '/doesnotexist'
        msg = service_connection_handler(sock, client_addr, header)
        self.assert_('is not a provider' in msg, msg)

        # check invalid md5sums

        name = '/service'
        sm = get_service_manager()
        fake_service = \
            rospy.service._Service(name, test_rospy.srv.EmptySrv)
        sm.register(name, fake_service)
        
        header['service'] = name
        header['md5sum'] = 'X'

        msg = service_connection_handler(sock, client_addr, header)
        self.assert_('md5sums do not match' in msg, msg)
Ejemplo n.º 13
0
    def test_service_connection_handler(self):
        import test_rospy.srv
        from rospy.impl.registration import get_service_manager
        import rospy.service

        sock = FakeSocket()
        from rospy.impl.tcpros_service import service_connection_handler

        client_addr = "10.0.0.1"

        # check error conditions on missing headers
        self.assert_("Missing" in service_connection_handler(sock, client_addr, {}))
        header = {"service": "/service", "md5sum": "*", "callerid": "/bob"}
        for k in header:
            c = header.copy()
            del c[k]
            msg = service_connection_handler(sock, client_addr, c)
            self.assert_("Missing" in msg, str(c) + msg)
            self.assert_(k in msg, msg)

        # check error condition on invalid service
        header["service"] = "/doesnotexist"
        msg = service_connection_handler(sock, client_addr, header)
        self.assert_("is not a provider" in msg, msg)

        # check invalid md5sums

        name = "/service"
        sm = get_service_manager()
        fake_service = rospy.service._Service(name, test_rospy.srv.EmptySrv)
        sm.register(name, fake_service)

        header["service"] = name
        header["md5sum"] = "X"

        msg = service_connection_handler(sock, client_addr, header)
        self.assert_("md5sums do not match" in msg, msg)