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
00034 import fnmatch
00035 from rosbridge_library.capability import Capability
00036 from rosbridge_library.internal.publishers import manager
00037 from rosbridge_library.util import string_types
00038
00039
00040 class Registration():
00041 """ Keeps track of how many times a client has requested to advertise
00042 a publisher.
00043
00044 A client could advertise and unadvertise a topic multiple times, and we
00045 must make sure that the underlying publisher is only created and destroyed
00046 at the appropriate moments
00047
00048 """
00049
00050 def __init__(self, client_id, topic):
00051
00052 self.client_id = client_id
00053 self.topic = topic
00054 self.clients = {}
00055
00056 def unregister(self):
00057 manager.unregister(self.client_id, self.topic)
00058
00059 def register_advertisement(self, msg_type, adv_id=None, latch=False, queue_size=100):
00060
00061 manager.register(self.client_id, self.topic, msg_type, latch=latch, queue_size=queue_size)
00062
00063 self.clients[adv_id] = True
00064
00065 def unregister_advertisement(self, adv_id=None):
00066 if adv_id is None:
00067 self.clients.clear()
00068 elif adv_id in self.clients:
00069 del self.clients[adv_id]
00070
00071 def is_empty(self):
00072 return len(self.clients) == 0
00073
00074
00075 class Advertise(Capability):
00076
00077 advertise_msg_fields = [(True, "topic", string_types), (True, "type", string_types)]
00078 unadvertise_msg_fields = [(True, "topic", string_types)]
00079
00080 topics_glob = None
00081
00082 def __init__(self, protocol):
00083
00084 Capability.__init__(self, protocol)
00085
00086
00087 protocol.register_operation("advertise", self.advertise)
00088 protocol.register_operation("unadvertise", self.unadvertise)
00089
00090
00091 self._registrations = {}
00092
00093 def advertise(self, message):
00094
00095 aid = message.get("id", None)
00096
00097 self.basic_type_check(message, self.advertise_msg_fields)
00098 topic = message["topic"]
00099 msg_type = message["type"]
00100 latch = message.get("latch", False)
00101 queue_size = message.get("queue_size", 100)
00102
00103 if Advertise.topics_glob is not None and Advertise.topics_glob:
00104 self.protocol.log("debug", "Topic security glob enabled, checking topic: " + topic)
00105 match = False
00106 for glob in Advertise.topics_glob:
00107 if (fnmatch.fnmatch(topic, glob)):
00108 self.protocol.log("debug", "Found match with glob " + glob + ", continuing advertisement...")
00109 match = True
00110 break
00111 if not match:
00112 self.protocol.log("warn", "No match found for topic, cancelling advertisement of: " + topic)
00113 return
00114 else:
00115 self.protocol.log("debug", "No topic security glob, not checking advertisement.")
00116
00117
00118 if not topic in self._registrations:
00119 client_id = self.protocol.client_id
00120 self._registrations[topic] = Registration(client_id, topic)
00121
00122
00123 self._registrations[topic].register_advertisement(msg_type, aid, latch, queue_size)
00124
00125 def unadvertise(self, message):
00126
00127 aid = message.get("id", None)
00128
00129 self.basic_type_check(message, self.unadvertise_msg_fields)
00130 topic = message["topic"]
00131
00132 if Advertise.topics_glob is not None and Advertise.topics_glob:
00133 self.protocol.log("debug", "Topic security glob enabled, checking topic: " + topic)
00134 match = False
00135 for glob in Advertise.topics_glob:
00136 if (fnmatch.fnmatch(topic, glob)):
00137 self.protocol.log("debug", "Found match with glob " + glob + ", continuing unadvertisement...")
00138 match = True
00139 break
00140 if not match:
00141 self.protocol.log("warn", "No match found for topic, cancelling unadvertisement of: " + topic)
00142 return
00143 else:
00144 self.protocol.log("debug", "No topic security glob, not checking unadvertisement.")
00145
00146
00147 if topic not in self._registrations:
00148 return
00149 self._registrations[topic].unregister_advertisement(aid)
00150
00151
00152 if self._registrations[topic].is_empty():
00153 self._registrations[topic].unregister()
00154 del self._registrations[topic]
00155
00156 def finish(self):
00157 for registration in self._registrations.values():
00158 registration.unregister()
00159 self._registrations.clear()
00160 self.protocol.unregister_operation("advertise")
00161 self.protocol.unregister_operation("unadvertise")