hub_client.py
Go to the documentation of this file.
00001 #
00002 # License: BSD
00003 #
00004 #   https://raw.github.com/robotics-in-concert/rocon_multimaster/license/LICENSE
00005 #
00006 ###############################################################################
00007 # Imports
00008 ###############################################################################
00009 
00010 from urlparse import urlparse
00011 
00012 import rospy
00013 import rocon_python_redis as redis
00014 import rocon_gateway_utils
00015 
00016 from . import hub_api
00017 from .exceptions import HubNameNotFoundError, HubNotFoundError, \
00018     HubConnectionBlacklistedError, HubConnectionNotWhitelistedError
00019 
00020 
00021 ##############################################################################
00022 # Hub
00023 ##############################################################################
00024 
00025 
00026 class HubConnection(redis.Connection):
00027     '''
00028       This might be useful if doing connections with socket timeouts and we
00029       need special functionality. Not currently using though. Pass in to
00030       the redis server constructor as connection_class=HubConnection
00031     '''
00032     def __init__(self, host='localhost', port=6379, db=0, password=None,
00033                  socket_timeout=1.0, encoding='utf-8',
00034                  encoding_errors='strict', decode_responses=False):
00035         super(HubConnection, self).__init__(host, port, db, password,
00036                                             socket_timeout, encoding,
00037                                             encoding_errors, decode_responses)
00038 
00039 
00040 ##############################################################################
00041 # Ping
00042 ##############################################################################
00043 
00044 
00045 def ping_hub(ip, port, timeout=5.0):
00046     '''
00047       Pings the hub for identification. This is currently used
00048       by the hub discovery module.
00049 
00050       @return Bool, Latency
00051     '''
00052     try:
00053         connection_pool = redis.ConnectionPool(host=ip, port=port,
00054                                                connection_class=HubConnection, socket_timeout=timeout)
00055         r = redis.Redis(connection_pool=connection_pool)
00056         name = r.get("rocon:hub:name")
00057     except redis.exceptions.ConnectionError as e:
00058         return False, str(e)
00059     if name is None:  # returns None if the server was there, but the key was not found.
00060         return False, "Redis Server is there but name key is not found"
00061     return (True, "")
00062 
00063 ##############################################################################
00064 # Hub
00065 ##############################################################################
00066 
00067 
00068 class Hub(object):
00069 
00070     def __init__(self, ip, port, whitelist=[], blacklist=[]):
00071         '''
00072           @param remote_gateway_request_callbacks : to handle redis responses
00073           @type list of function pointers (back to GatewaySync class
00074 
00075           @param ip : redis server ip
00076           @param port : redis server port
00077 
00078           @raise HubNameNotFoundError, HubNotFoundError
00079         '''
00080         # variables
00081         self.ip = ip
00082         self.port = port
00083         self.uri = str(ip) + ":" + str(port)
00084         self._redis_keys = {}
00085         self._redis_channels = {}
00086 
00087         # This is a temporary try-except block just to ping and see if the address we have here is
00088         # actually resolvable or it times out. Ideally we want to use socket_timeouts throughout,
00089         # but that will need modification of the way we handle the RedisListenerThread in
00090         # gateway_hub.py
00091         try:
00092             unused_ping = redis.Redis(host=ip, socket_timeout=5.0, port=port).ping()
00093             # should check ping result? Typically it just throws the timeout error
00094         except redis.exceptions.ConnectionError:
00095             self._redis_server = None
00096             raise HubNotFoundError("couldn't connect to the redis server")
00097         try:
00098             self.pool = redis.ConnectionPool(host=ip, port=port, db=0, socket_timeout=5.0)
00099             self._redis_server = redis.Redis(connection_pool=self.pool)
00100             self._redis_pubsub_server = self._redis_server.pubsub()
00101             hub_key_name = self._redis_server.get("rocon:hub:name")
00102             # Be careful, hub_name is None, it means the redis server is
00103             # found but hub_name not yet set or not set at all.
00104 
00105             # retrying for 5 seconds in case we started too fast
00106             retries = 0
00107             while self._redis_server and not hub_key_name and retries < 5:
00108                 rospy.logwarn("couldn't resolve hub name on the redis server [%s:%s]. Retrying..." % (ip, port))
00109                 retries += 1
00110                 rospy.rostime.wallsleep(1.0)
00111                 hub_key_name = self._redis_server.get("rocon:hub:name")
00112 
00113             if not hub_key_name:
00114                 self._redis_server = None
00115                 raise HubNameNotFoundError("couldn't resolve hub name on the redis server [%s:%s]" % (ip, port))
00116             else:
00117                 self.name = hub_api.key_base_name(hub_key_name)  # perhaps should store all key names somewhere central
00118                 rospy.logdebug("Gateway : resolved hub name [%s].", self.name)
00119         except redis.exceptions.ConnectionError:
00120             self._redis_server = None
00121             raise HubNotFoundError("couldn't connect to the redis server")
00122 
00123         # whitelists, blacklists - check against uri's hash names and non-uuid names
00124         uri_blacklist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in blacklist if urlparse(x).hostname is not None]
00125         uri_whitelist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in whitelist if urlparse(x).hostname is not None]
00126         nonuuid_blacklist = [rocon_gateway_utils.gateway_basename(x) for x in blacklist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
00127         nonuuid_whitelist = [rocon_gateway_utils.gateway_basename(x) for x in whitelist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
00128         if self.uri in uri_blacklist or self.name in blacklist or self.name in nonuuid_blacklist:
00129             raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
00130         if self.name in blacklist or self.name in nonuuid_whitelist:
00131             raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
00132         if not ((len(whitelist) == 0) or (self.uri in uri_whitelist) or (self.name in whitelist)):
00133             raise HubConnectionNotWhitelistedError("hub/ip not in non-empty whitelist [%s, %s][%s]" % (self.name, self.uri, whitelist))
00134 
00135     def disconnect(self):
00136         '''
00137           Kills any open socket connections to the redis server. This is
00138           necessary if the server is out of range, as the py-redis client
00139           will hang all open connections indefinitely
00140         '''
00141         try:
00142             self._redis_server.connection_pool.disconnect()
00143         except AttributeError:
00144             # Disconnecting individual connection takes some time. This
00145             # exception is raised when disconnect is called on 2 connections
00146             # simultaneously. The redis Connection object is not thread-safe
00147             pass
00148 
00149     def __eq__(self, other):
00150         return self.uri == other.uri
00151 
00152     def __ne__(self, other):
00153         return not self.__eq__(other)


rocon_hub_client
Author(s): Daniel Stonier , Jihoon Lee
autogenerated on Sat Jun 8 2019 18:48:43