00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import fnmatch
00034 from functools import partial
00035 from rosbridge_library.capability import Capability
00036 from rosbridge_library.internal.services import ServiceCaller
00037 from rosbridge_library.util import string_types
00038
00039
00040 class CallService(Capability):
00041
00042 call_service_msg_fields = [(True, "service", string_types),
00043 (False, "fragment_size", (int, type(None))),
00044 (False, "compression", string_types)]
00045
00046 services_glob = None
00047
00048 def __init__(self, protocol):
00049
00050 Capability.__init__(self, protocol)
00051
00052
00053 protocol.register_operation("call_service", self.call_service)
00054
00055 def call_service(self, message):
00056
00057 cid = message.get("id", None)
00058
00059
00060 self.basic_type_check(message, self.call_service_msg_fields)
00061
00062
00063 service = message["service"]
00064 fragment_size = message.get("fragment_size", None)
00065 compression = message.get("compression", "none")
00066 args = message.get("args", [])
00067
00068 if CallService.services_glob is not None and CallService.services_glob:
00069 self.protocol.log("debug", "Service security glob enabled, checking service: " + service)
00070 match = False
00071 for glob in CallService.services_glob:
00072 if (fnmatch.fnmatch(service, glob)):
00073 self.protocol.log("debug", "Found match with glob " + glob + ", continuing service call...")
00074 match = True
00075 break
00076 if not match:
00077 self.protocol.log("warn", "No match found for service, cancelling service call for: " + service)
00078 return
00079 else:
00080 self.protocol.log("debug", "No service security glob, not checking service call.")
00081
00082
00083 cid = extract_id(service, cid)
00084
00085
00086 s_cb = partial(self._success, cid, service, fragment_size, compression)
00087 e_cb = partial(self._failure, cid, service)
00088
00089
00090 ServiceCaller(trim_servicename(service), args, s_cb, e_cb).start()
00091
00092 def _success(self, cid, service, fragment_size, compression, message):
00093 outgoing_message = {
00094 "op": "service_response",
00095 "service": service,
00096 "values": message,
00097 "result": True
00098 }
00099 if cid is not None:
00100 outgoing_message["id"] = cid
00101
00102 self.protocol.send(outgoing_message)
00103
00104 def _failure(self, cid, service, exc):
00105 self.protocol.log("error", "call_service %s: %s" %
00106 (type(exc).__name__, str(exc)), cid)
00107
00108 outgoing_message = {
00109 "op": "service_response",
00110 "service": service,
00111 "values": str(exc),
00112 "result": False
00113 }
00114 if cid is not None:
00115 outgoing_message["id"] = cid
00116 self.protocol.send(outgoing_message)
00117
00118
00119 def trim_servicename(service):
00120 if '#' in service:
00121 return service[:service.find('#')]
00122 return service
00123
00124
00125 def extract_id(service, cid):
00126 if cid is not None:
00127 return cid
00128 elif '#' in service:
00129 return service[service.find('#') + 1:]