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