hub_client.py
Go to the documentation of this file.
1 #
2 # License: BSD
3 #
4 # https://raw.github.com/robotics-in-concert/rocon_multimaster/license/LICENSE
5 #
6 ###############################################################################
7 # Imports
8 ###############################################################################
9 
10 from urlparse import urlparse
11 
12 import rospy
13 import rocon_python_redis as redis
14 import rocon_gateway_utils
15 
16 from . import hub_api
17 from .exceptions import HubNameNotFoundError, HubNotFoundError, \
18  HubConnectionBlacklistedError, HubConnectionNotWhitelistedError
19 
20 
21 ##############################################################################
22 # Hub
23 ##############################################################################
24 
25 
26 class HubConnection(redis.Connection):
27  '''
28  This might be useful if doing connections with socket timeouts and we
29  need special functionality. Not currently using though. Pass in to
30  the redis server constructor as connection_class=HubConnection
31  '''
32  def __init__(self, host='localhost', port=6379, db=0, password=None,
33  socket_timeout=1.0, encoding='utf-8',
34  encoding_errors='strict', decode_responses=False):
35  super(HubConnection, self).__init__(host, port, db, password,
36  socket_timeout, encoding,
37  encoding_errors, decode_responses)
38 
39 
40 ##############################################################################
41 # Ping
42 ##############################################################################
43 
44 
45 def ping_hub(ip, port, timeout=5.0):
46  '''
47  Pings the hub for identification. This is currently used
48  by the hub discovery module.
49 
50  @return Bool, Latency
51  '''
52  try:
53  connection_pool = redis.ConnectionPool(host=ip, port=port,
54  connection_class=HubConnection, socket_timeout=timeout)
55  r = redis.Redis(connection_pool=connection_pool)
56  name = r.get("rocon:hub:name")
57  except redis.exceptions.ConnectionError as e:
58  return False, str(e)
59  if name is None: # returns None if the server was there, but the key was not found.
60  return False, "Redis Server is there but name key is not found"
61  return (True, "")
62 
63 ##############################################################################
64 # Hub
65 ##############################################################################
66 
67 
68 class Hub(object):
69 
70  def __init__(self, ip, port, whitelist=[], blacklist=[]):
71  '''
72  @param remote_gateway_request_callbacks : to handle redis responses
73  @type list of function pointers (back to GatewaySync class
74 
75  @param ip : redis server ip
76  @param port : redis server port
77 
78  @raise HubNameNotFoundError, HubNotFoundError
79  '''
80  # variables
81  self.ip = ip
82  self.port = port
83  self.uri = str(ip) + ":" + str(port)
84  self._redis_keys = {}
85  self._redis_channels = {}
86 
87  # This is a temporary try-except block just to ping and see if the address we have here is
88  # actually resolvable or it times out. Ideally we want to use socket_timeouts throughout,
89  # but that will need modification of the way we handle the RedisListenerThread in
90  # gateway_hub.py
91  try:
92  unused_ping = redis.Redis(host=ip, socket_timeout=5.0, port=port).ping()
93  # should check ping result? Typically it just throws the timeout error
94  except redis.exceptions.ConnectionError:
95  self._redis_server = None
96  raise HubNotFoundError("couldn't connect to the redis server")
97  try:
98  self.pool = redis.ConnectionPool(host=ip, port=port, db=0, socket_timeout=5.0)
99  self._redis_server = redis.Redis(connection_pool=self.pool)
100  self._redis_pubsub_server = self._redis_server.pubsub()
101  hub_key_name = self._redis_server.get("rocon:hub:name")
102  # Be careful, hub_name is None, it means the redis server is
103  # found but hub_name not yet set or not set at all.
104 
105  # retrying for 5 seconds in case we started too fast
106  retries = 0
107  while self._redis_server and not hub_key_name and retries < 5:
108  rospy.logwarn("couldn't resolve hub name on the redis server [%s:%s]. Retrying..." % (ip, port))
109  retries += 1
110  rospy.rostime.wallsleep(1.0)
111  hub_key_name = self._redis_server.get("rocon:hub:name")
112 
113  if not hub_key_name:
114  self._redis_server = None
115  raise HubNameNotFoundError("couldn't resolve hub name on the redis server [%s:%s]" % (ip, port))
116  else:
117  self.name = hub_api.key_base_name(hub_key_name) # perhaps should store all key names somewhere central
118  rospy.logdebug("Gateway : resolved hub name [%s].", self.name)
119  except redis.exceptions.ConnectionError:
120  self._redis_server = None
121  raise HubNotFoundError("couldn't connect to the redis server")
122 
123  # whitelists, blacklists - check against uri's hash names and non-uuid names
124  uri_blacklist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in blacklist if urlparse(x).hostname is not None]
125  uri_whitelist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in whitelist if urlparse(x).hostname is not None]
126  nonuuid_blacklist = [rocon_gateway_utils.gateway_basename(x) for x in blacklist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
127  nonuuid_whitelist = [rocon_gateway_utils.gateway_basename(x) for x in whitelist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
128  if self.uri in uri_blacklist or self.name in blacklist or self.name in nonuuid_blacklist:
129  raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
130  if self.name in blacklist or self.name in nonuuid_whitelist:
131  raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
132  if not ((len(whitelist) == 0) or (self.uri in uri_whitelist) or (self.name in whitelist)):
133  raise HubConnectionNotWhitelistedError("hub/ip not in non-empty whitelist [%s, %s][%s]" % (self.name, self.uri, whitelist))
134 
135  def disconnect(self):
136  '''
137  Kills any open socket connections to the redis server. This is
138  necessary if the server is out of range, as the py-redis client
139  will hang all open connections indefinitely
140  '''
141  try:
142  self._redis_server.connection_pool.disconnect()
143  except AttributeError:
144  # Disconnecting individual connection takes some time. This
145  # exception is raised when disconnect is called on 2 connections
146  # simultaneously. The redis Connection object is not thread-safe
147  pass
148 
149  def __eq__(self, other):
150  return self.uri == other.uri
151 
152  def __ne__(self, other):
153  return not self.__eq__(other)
def ping_hub(ip, port, timeout=5.0)
Definition: hub_client.py:45
def __init__(self, ip, port, whitelist=[], blacklist=[])
Definition: hub_client.py:70
def __init__(self, host='localhost', port=6379, db=0, password=None, socket_timeout=1.0, encoding='utf-8', encoding_errors='strict', decode_responses=False)
Definition: hub_client.py:34


rocon_hub_client
Author(s): Daniel Stonier , Jihoon Lee
autogenerated on Mon Jun 10 2019 14:40:08