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
00038
00039 class CallService(Capability):
00040
00041 call_service_msg_fields = [(True, "service", (str, unicode)),
00042 (False, "fragment_size", (int, type(None))),
00043 (False, "compression", (str, unicode))]
00044
00045 services_glob = None
00046
00047 def __init__(self, protocol):
00048
00049 Capability.__init__(self, protocol)
00050
00051
00052 protocol.register_operation("call_service", self.call_service)
00053
00054 def call_service(self, message):
00055
00056 cid = message.get("id", None)
00057
00058
00059 self.basic_type_check(message, self.call_service_msg_fields)
00060
00061
00062 service = message["service"]
00063 fragment_size = message.get("fragment_size", None)
00064 compression = message.get("compression", "none")
00065 args = message.get("args", [])
00066
00067 if CallService.services_glob is not None and CallService.services_glob:
00068 self.protocol.log("debug", "Service security glob enabled, checking service: " + service)
00069 match = False
00070 for glob in CallService.services_glob:
00071 if (fnmatch.fnmatch(service, glob)):
00072 self.protocol.log("debug", "Found match with glob " + glob + ", continuing service call...")
00073 match = True
00074 break
00075 if not match:
00076 self.protocol.log("warn", "No match found for service, cancelling service call for: " + service)
00077 return
00078 else:
00079 self.protocol.log("debug", "No service security glob, not checking service call.")
00080
00081
00082 cid = extract_id(service, cid)
00083
00084
00085 s_cb = partial(self._success, cid, service, fragment_size, compression)
00086 e_cb = partial(self._failure, cid, service)
00087
00088
00089 ServiceCaller(trim_servicename(service), args, s_cb, e_cb).start()
00090
00091 def _success(self, cid, service, fragment_size, compression, message):
00092 outgoing_message = {
00093 "op": "service_response",
00094 "service": service,
00095 "values": message,
00096 "result": True
00097 }
00098 if cid is not None:
00099 outgoing_message["id"] = cid
00100
00101 self.protocol.send(outgoing_message)
00102
00103 def _failure(self, cid, service, exc):
00104 self.protocol.log("error", "call_service %s: %s" %
00105 (type(exc).__name__, str(exc)), cid)
00106
00107 outgoing_message = {
00108 "op": "service_response",
00109 "service": service,
00110 "values": str(exc),
00111 "result": False
00112 }
00113 if cid is not None:
00114 outgoing_message["id"] = cid
00115 self.protocol.send(outgoing_message)
00116
00117
00118 def trim_servicename(service):
00119 if '#' in service:
00120 return service[:service.find('#')]
00121 return service
00122
00123
00124 def extract_id(service, cid):
00125 if cid is not None:
00126 return cid
00127 elif '#' in service:
00128 return service[service.find('#') + 1:]