Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 import roslib
00012 roslib.load_manifest('rocon_gateway')
00013 import threading
00014 from gateway_msgs.msg import RemoteRule
00015 import re
00016 import copy
00017
00018
00019 import utils
00020
00021
00022
00023
00024
00025
00026 class InteractiveInterface(object):
00027 '''
00028 Parent interface for flip and pull interfaces.
00029 '''
00030 def __init__(self, default_rule_blacklist, default_rules, all_targets):
00031 '''
00032 @param default_rule_blacklist : used when in flip/pull all mode
00033 @type dictionary of gateway
00034 @param default_rules : static rules to flip/pull on startup
00035 @type gateway_msgs.msg.RemoteRule[]
00036 @param all_targets : static flip/pull all targets to flip/pull to on startup
00037 @type string[]
00038 '''
00039
00040
00041
00042
00043 self.active = utils.createEmptyConnectionTypeDictionary()
00044
00045
00046 self._default_blacklist = default_rule_blacklist
00047
00048
00049 self.watchlist = utils.createEmptyConnectionTypeDictionary()
00050
00051
00052 self.registrations = utils.createEmptyConnectionTypeDictionary()
00053
00054
00055 self._blacklist = {}
00056
00057 self._lock = threading.Lock()
00058
00059
00060 for rule in default_rules:
00061 self.add_rule(rule)
00062 for gateway in all_targets:
00063 self.add_all(gateway,[])
00064
00065
00066
00067
00068
00069 def add_rule(self, remote_rule):
00070 '''
00071 Add a remote rule to the watchlist for monitoring.
00072
00073 @param remote_rule : the remote rule to add to the watchlist
00074 @type gateway_msgs.msg.RemoteRule
00075
00076 @return the remote rule, or None if the rule already exists.
00077 @rtype gateway_msgs.msg.RemoteRule || None
00078 '''
00079 result = None
00080 self._lock.acquire()
00081 rule_already_exists = False
00082
00083
00084 for watched_rule in self.watchlist[remote_rule.rule.type]:
00085 if watched_rule.gateway == remote_rule.gateway and \
00086 watched_rule.rule.name == remote_rule.rule.name and \
00087 watched_rule.rule.node == remote_rule.rule.node:
00088 rule_already_exists = True
00089 break
00090 if not rule_already_exists:
00091 self.watchlist[remote_rule.rule.type].append(remote_rule)
00092 result = remote_rule
00093 self._lock.release()
00094 return result
00095
00096 def remove_rule(self, remote_rule):
00097 '''
00098 Remove a rule. Be a bit careful looking for a rule to remove, depending
00099 on the node name, which can be set (exact rule/node name match) or
00100 None in which case all nodes of that kind of flip will match.
00101
00102 Handle the remapping appropriately.
00103
00104 @param remote_rule : the remote rule to remove from the watchlist.
00105 @type gateway_msgs.msg.RemoteRule
00106
00107 @return Rules remaining in the watchlist
00108 @rtype RemoteRule[]
00109 '''
00110 if remote_rule.rule.node:
00111
00112 try:
00113 self._lock.acquire()
00114 self.watchlist[remote_rule.rule.type].remove(remote_rule)
00115 self._lock.release()
00116 return [remote_rule]
00117 except ValueError:
00118 self._lock.release()
00119 return []
00120 else:
00121
00122 existing_rules = []
00123 self._lock.acquire()
00124 for existing_rule in self.watchlist[remote_rule.rule.type]:
00125 if (existing_rule.gateway == remote_rule.gateway) and \
00126 (existing_rule.rule.name == remote_rule.rule.name):
00127 existing_rules.append(existing_rule)
00128 for rule in existing_rules:
00129 self.watchlist[remote_rule.rule.type].remove(rule)
00130 self._lock.release()
00131 return existing_rules
00132
00133 def add_all(self, gateway, blacklist):
00134 '''
00135 Instead of watching/acting on specific rules, take action
00136 on everything except for rules in a blacklist.
00137
00138 @param gateway : target remote gateway string id
00139 @type str
00140
00141 @param blacklist : do not act on rules matching these patterns
00142 @type gateway_msgs.msg.Rule[]
00143
00144 @return success or failure depending on if it ahs already been set or not
00145 @rtype Bool
00146 '''
00147 self._lock.acquire()
00148
00149 if gateway in self._blacklist:
00150 self._lock.release()
00151 return False
00152 self._blacklist[gateway] = self._default_blacklist
00153 for rule in blacklist:
00154 self._blacklist[gateway][rule.type].append(rule)
00155
00156 for connection_type in utils.connection_types:
00157 remote_rule = RemoteRule()
00158 remote_rule.gateway = gateway
00159 remote_rule.rule.name = '.*'
00160 remote_rule.rule.node = None
00161 remote_rule.rule.type = connection_type
00162
00163 self.watchlist[connection_type][:] = [rule for rule in self.watchlist[connection_type] if rule.gateway != gateway]
00164
00165 self.watchlist[connection_type].append(remote_rule)
00166 self._lock.release()
00167 return True
00168
00169 def remove_all(self, gateway):
00170 '''
00171 Remove the add all rule for the specified gateway.
00172
00173 @param gateway : target remote gateway string id
00174 @type str
00175 '''
00176 self._lock.acquire()
00177 if gateway in self._blacklist:
00178 del self._blacklist[gateway]
00179 for connection_type in utils.connection_types:
00180 for rule in self.watchlist[connection_type]:
00181 if rule.gateway == gateway:
00182
00183 try:
00184 self.watchlist[connection_type].remove(rule)
00185 except ValueError:
00186 pass
00187 self._lock.release()
00188
00189
00190
00191
00192
00193 def is_matched(self, rule, rule_name, name, node):
00194 matched = False
00195 name_match_result = re.match(rule_name, name)
00196 if name_match_result and name_match_result.group() == name:
00197 if utils.isAllPattern(rule_name):
00198 if self._isInBlacklist(rule.gateway, type, name, node):
00199 return False
00200 if rule.rule.node:
00201 node_match_result = re.match(rule.rule.node, node)
00202 if node_match_result and node_match_result.group() == node:
00203 matched = True
00204 else:
00205 matched = True
00206 return matched
00207
00208 def getLocalRegistrations(self):
00209 '''
00210 Gets the local registrations for GatewayInfo consumption (flipped ins/pulls).
00211
00212 We don't need to show the service and node uri's here.
00213
00214 Basic operation : convert Registration -> RemoteRule for each registration
00215
00216 @return the list of registrations corresponding to remote interactions
00217 @rtype RemoteRule[]
00218 '''
00219 local_registrations = []
00220 for connection_type in utils.connection_types:
00221 for registration in self.registrations[connection_type]:
00222 remote_rule = RemoteRule()
00223 remote_rule.gateway = registration.remote_gateway
00224 remote_rule.rule.name = registration.connection.rule.name
00225 remote_rule.rule.node = registration.connection.rule.node
00226 remote_rule.rule.type = connection_type
00227 local_registrations.append(remote_rule)
00228 return local_registrations
00229
00230 def getWatchlist(self):
00231 '''
00232 Gets the watchlist for GatewayInfo consumption.
00233
00234 @return the list of flip rules that are being watched
00235 @rtype gateway_msgs.msg.RemoteRule[]
00236 '''
00237 watchlist = []
00238 for connection_type in utils.connection_types:
00239 watchlist.extend(copy.deepcopy(self.watchlist[connection_type]))
00240
00241 for remote in watchlist:
00242 if not remote.rule.node:
00243 remote.rule.node = 'None'
00244 return watchlist
00245
00246
00247
00248
00249
00250 def findRegistrationMatch(self, remote_gateway, remote_name, remote_node, connection_type):
00251 '''
00252 Check to see if a registration exists. Note that it doesn't use the
00253 local node name in the check. We will get things like unflip requests that
00254 don't have this variable set (that gets autogenerated when registering
00255 the flip), but we need to find the matching registration.
00256
00257 We then return the registration that matches.
00258
00259 @param remote_gateway : string remote gateway id
00260 @type string
00261 @param remote_name, remote_node, connection_type : remote connection details
00262 @type string
00263
00264 @return matching registration or none
00265 @rtype utils.Registration
00266 '''
00267
00268 matched_registration = None
00269 self._lock.acquire()
00270 for registration in self.registrations[connection_type]:
00271 if (registration.remote_gateway == remote_gateway) and \
00272 (registration.connection.rule.name == remote_name) and \
00273 (registration.connection.rule.node == remote_node) and \
00274 (registration.connection.rule.type == connection_type):
00275 matched_registration = registration
00276 break
00277 else:
00278 continue
00279 self._lock.release()
00280 return matched_registration
00281
00282 def _isInBlacklist(self, gateway, type, name, node):
00283 '''
00284 Check if a particular connection is in the blacklist. Use this to
00285 filter connections from the flip_all command.
00286
00287 @todo move to utils - should be shared with the public interface.
00288 '''
00289 for blacklist_rule in self._blacklist[gateway][type]:
00290 name_match_result = re.match(blacklist_rule.name, name)
00291 if name_match_result and name_match_result.group() == name:
00292 if blacklist_rule.node:
00293 node_match_result = re.match(blacklist_rule.node, node)
00294 if node_match_result and node_match_result.group() == node:
00295 return True
00296 else:
00297 return True
00298 return False