00001
00002
00003
00004
00005
00006
00007
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
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
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:
00060 return False, "Redis Server is there but name key is not found"
00061 return (True, "")
00062
00063
00064
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
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
00088
00089
00090
00091 try:
00092 unused_ping = redis.Redis(host=ip, socket_timeout=5.0, port=port).ping()
00093
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
00103
00104
00105
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)
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
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
00145
00146
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)