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()
def test_TCPROSTransport(self): import rospy.impl.tcpros_base from rospy.impl.tcpros_base import TCPROSTransport, TCPROSTransportProtocol from rospy.impl.transport import OUTBOUND p = TCPROSTransportProtocol('Bob', rospy.AnyMsg) p.direction = OUTBOUND try: TCPROSTransport(p, '') self.fail("TCPROSTransport should not accept bad name") except rospy.impl.tcpros_base.TransportInitError: pass t = TCPROSTransport(p, 'transport-name') self.assert_(t.socket is None) self.assert_(t.md5sum is None) self.assert_(t.type is None) self.assertEquals(p, t.protocol) self.assertEquals('TCPROS', t.transport_type) self.assertEquals(OUTBOUND, t.direction) self.assertEquals('unknown', t.endpoint_id) self.assertEquals('', t.read_buff.getvalue()) self.assertEquals('', t.write_buff.getvalue()) s = MockSock('12345') t.set_socket(s, 'new_endpoint_id') self.assertEquals('new_endpoint_id', t.endpoint_id) self.assertEquals(s, t.socket) t.close() self.assert_(t.socket is None) self.assert_(t.read_buff is None) self.assert_(t.write_buff is None) self.assert_(t.protocol is None)
def inbound_handler(sock, addr): print "%s connected." % (str(addr)) t = TCPROSTransport(TestServerProtocol(), "testservice") t.set_socket(sock, "client") t.write_header() t.read_header() inputs.append(sock)
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()
def service_connection_handler(self, sock, client_addr, header): """ @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 """ # This is a cturtle hack. rospy's service_connection_handler # is wired to the ServiceManager singleton. If we replace the # singleton with something more configurable, then we simply # have to run our own ServiceManager to handle the forwarding # behavior. 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'] sm = self.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() thread.start_new_thread(service.handle, (transport, header))
def service_connection_handler(self, sock, client_addr, header): """ @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 """ # This is a cturtle hack. rospy's service_connection_handler # is wired to the ServiceManager singleton. If we replace the # singleton with something more configurable, then we simply # have to run our own ServiceManager to handle the forwarding # behavior. 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'] sm = self.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() thread.start_new_thread(service.handle, (transport, header))
t.write_header() t.read_header() inputs.append(sock) if __name__ == '__main__': s = TCPServer(inbound_handler, PORT) s.start() while True: inputready,outputready,exceptready = select.select(inputs, [], [], 1) for s in inputready: # s is really just a python socket, but let's use # ROS to parse the message and write a response t = TCPROSTransport(TestServerProtocol(), "testservice") t.set_socket(s, "client") try: data = t.receive_once() # Echo all messages seq = 0 for msg in data: msg.data = "This is a reply of the message '%s'." % (msg.data) t.send_message(msg, seq) seq += 1 print "Echoed data" except rospy.exceptions.TransportTerminated: print "Closing connection" s.close() inputs.remove(s)