call_service.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2012, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 import fnmatch
34 from functools import partial
35 from rosbridge_library.capability import Capability
36 from rosbridge_library.internal.services import ServiceCaller
37 from rosbridge_library.util import string_types
38 
39 
41 
42  call_service_msg_fields = [(True, "service", string_types),
43  (False, "fragment_size", (int, type(None))),
44  (False, "compression", string_types)]
45 
46  services_glob = None
47 
48  def __init__(self, protocol):
49  # Call superclas constructor
50  Capability.__init__(self, protocol)
51 
52  # Register the operations that this capability provides
53  protocol.register_operation("call_service", self.call_service)
54 
55  def call_service(self, message):
56  # Pull out the ID
57  cid = message.get("id", None)
58 
59  # Typecheck the args
60  self.basic_type_check(message, self.call_service_msg_fields)
61 
62  # Extract the args
63  service = message["service"]
64  fragment_size = message.get("fragment_size", None)
65  compression = message.get("compression", "none")
66  args = message.get("args", [])
67 
68  if CallService.services_glob is not None and CallService.services_glob:
69  self.protocol.log("debug", "Service security glob enabled, checking service: " + service)
70  match = False
71  for glob in CallService.services_glob:
72  if (fnmatch.fnmatch(service, glob)):
73  self.protocol.log("debug", "Found match with glob " + glob + ", continuing service call...")
74  match = True
75  break
76  if not match:
77  self.protocol.log("warn", "No match found for service, cancelling service call for: " + service)
78  return
79  else:
80  self.protocol.log("debug", "No service security glob, not checking service call.")
81 
82  # Check for deprecated service ID, eg. /rosbridge/topics#33
83  cid = extract_id(service, cid)
84 
85  # Create the callbacks
86  s_cb = partial(self._success, cid, service, fragment_size, compression)
87  e_cb = partial(self._failure, cid, service)
88 
89  # Kick off the service caller thread
90  ServiceCaller(trim_servicename(service), args, s_cb, e_cb).start()
91 
92  def _success(self, cid, service, fragment_size, compression, message):
93  outgoing_message = {
94  "op": "service_response",
95  "service": service,
96  "values": message,
97  "result": True
98  }
99  if cid is not None:
100  outgoing_message["id"] = cid
101  # TODO: fragmentation, compression
102  self.protocol.send(outgoing_message)
103 
104  def _failure(self, cid, service, exc):
105  self.protocol.log("error", "call_service %s: %s" %
106  (type(exc).__name__, str(exc)), cid)
107  # send response with result: false
108  outgoing_message = {
109  "op": "service_response",
110  "service": service,
111  "values": str(exc),
112  "result": False
113  }
114  if cid is not None:
115  outgoing_message["id"] = cid
116  self.protocol.send(outgoing_message)
117 
118 
119 def trim_servicename(service):
120  if '#' in service:
121  return service[:service.find('#')]
122  return service
123 
124 
125 def extract_id(service, cid):
126  if cid is not None:
127  return cid
128  elif '#' in service:
129  return service[service.find('#') + 1:]
def _success(self, cid, service, fragment_size, compression, message)
Definition: call_service.py:92
def basic_type_check(self, msg, types_info)
Definition: capability.py:76


rosbridge_library
Author(s): Jonathan Mace
autogenerated on Wed Jun 3 2020 03:55:14