def send_flip_request(self, remote_gateway, connection): ''' Sends a message to the remote gateway via redis pubsub channel. This is called from the watcher thread, when a flip rule gets activated. - redis channel name: rocon:<remote_gateway_name> - data : list of [ command, gateway, rule type, type, xmlrpc_uri ] - [0] - command : in this case 'flip' - [1] - gateway : the name of this gateway, i.e. the flipper - [2] - name : local name - [3] - node : local node name - [4] - connection_type : one of ConnectionType.PUBLISHER etc - [5] - type_info : a ros format type (e.g. std_msgs/String or service api) - [6] - xmlrpc_uri : the xmlrpc node uri @param command : string command name - either 'flip' or 'unflip' @type str @param flip_rule : the flip to send @type gateway_msgs.RemoteRule @param type_info : topic type (e.g. std_msgs/String) @param str @param xmlrpc_uri : the node uri @param str ''' source = hub_api.key_base_name(self._redis_keys['gateway']) cmd = utils.serialize_connection_request('flip', source, connection) try: self._redis_server.publish( hub_api.create_rocon_key(remote_gateway), cmd) except Exception as unused_e: return False return True
def _update_flip_request_status(self, registration, status): ''' Updates the flip request status for this hub @param registration : the flip registration for which we are updating status @type utils.Registration @param status : pending/accepted/blocked @type same as gateway_msgs.msg.RemoteRuleWithStatus.status @return True if this hub was used to send the flip request, and the status was updated. False otherwise. @rtype Boolean ''' hub_found = False key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, 'flip_ins') encoded_flip_ins = self._redis_server.smembers(key) for flip_in in encoded_flip_ins: old_status, source, connection_list = utils.deserialize_request( flip_in) connection = utils.get_connection_from_list(connection_list) connection = utils.decrypt_connection(connection, self.private_key) if source == registration.remote_gateway and connection == registration.connection: self._redis_server.srem(key, flip_in) hub_found = True if hub_found: encrypted_connection = utils.encrypt_connection( registration.connection, self.private_key) serialized_data = utils.serialize_connection_request( status, registration.remote_gateway, encrypted_connection) self._redis_server.sadd(key, serialized_data) return True return False
def send_flip_request(self, remote_gateway, connection, timeout=15.0): ''' Sends a message to the remote gateway via redis pubsub channel. This is called from the watcher thread, when a flip rule gets activated. - redis channel name: rocon:<remote_gateway_name> - data : list of [ command, gateway, rule type, type, xmlrpc_uri ] - [0] - command : in this case 'flip' - [1] - gateway : the name of this gateway, i.e. the flipper - [2] - name : local name - [3] - node : local node name - [4] - connection_type : one of ConnectionType.PUBLISHER etc - [5] - type_info : a ros format type (e.g. std_msgs/String or service api) - [6] - xmlrpc_uri : the xmlrpc node uri @param command : string command name - either 'flip' or 'unflip' @type str @param flip_rule : the flip to send @type gateway_msgs.RemoteRule @param type_info : topic type (e.g. std_msgs/String) @param str @param xmlrpc_uri : the node uri @param str ''' key = hub_api.create_rocon_gateway_key(remote_gateway, 'flip_ins') source = hub_api.key_base_name(self._redis_keys['gateway']) # Check if a flip request already exists on the hub if self.get_flip_request_status(remote_gateway, connection.rule) is not None: return True # Encrypt the transmission start_time = time.time() while time.time() - start_time <= timeout: remote_gateway_public_key_str = self._redis_server.get( hub_api.create_rocon_gateway_key(remote_gateway, 'public_key')) if remote_gateway_public_key_str is not None: break if remote_gateway_public_key_str is None: rospy.logerr("Gateway : flip to " + remote_gateway + " failed as public key not found") return False remote_gateway_public_key = utils.deserialize_key( remote_gateway_public_key_str) encrypted_connection = utils.encrypt_connection( connection, remote_gateway_public_key) # Send data serialized_data = utils.serialize_connection_request( FlipStatus.PENDING, source, encrypted_connection) self._redis_server.sadd(key, serialized_data) return True
def update_multiple_flip_request_status(self, registrations_with_status): ''' Updates the flip request status for multiple registrations on this hub @param registrations_with_status : the flip registration for which we are updating status @type list of (utils.Registration, str) where str is the status @param status : pending/accepted/blocked @type same as gateway_msgs.msg.RemoteRuleWithStatus.status @return True if this hub was used to send the flip request, false otherwise. @rtype Boolean ''' result = [False] * len(registrations_with_status) update_registrations = [] hub_found = False key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, 'flip_ins') try: encoded_flip_ins = self._redis_server.smembers(key) for flip_in in encoded_flip_ins: old_status, source, connection_list = utils.deserialize_request(flip_in) connection = utils.get_connection_from_list(connection_list) connection = utils.decrypt_connection(connection, self.private_key) for index, (registration, new_status) in enumerate(registrations_with_status): if source == registration.remote_gateway and connection == registration.connection: if new_status != old_status: self._redis_server.srem(key, flip_in) update_registrations.append((index, (registration, new_status))) else: result[index] = True for (index, (registration, new_status)) in update_registrations: encrypted_connection = utils.encrypt_connection(registration.connection, self.private_key) serialized_data = utils.serialize_connection_request(new_status, registration.remote_gateway, encrypted_connection) self._redis_server.sadd(key, serialized_data) result[index] = True except redis.exceptions.ConnectionError: # Means the hub has gone down (typically on shutdown so just be quiet) # If we really need to know that a hub is crashed, change this policy pass return result
def _resend_all_flip_ins(self): ''' Marks all flip ins to be resent. Until these flips are resent, they will not be processed ''' key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, 'flip_ins') encoded_flip_ins = [] try: encoded_flip_ins = self._redis_server.smembers(key) self._redis_server.delete(key) for flip_in in encoded_flip_ins: status, source, connection_list = utils.deserialize_request(flip_in) connection = utils.get_connection_from_list(connection_list) status = FlipStatus.RESEND serialized_data = utils.serialize_connection_request(status, source, connection) self._redis_server.sadd(key, serialized_data) except (redis.ConnectionError, AttributeError) as unused_e: # probably disconnected from the hub pass