def wait_for_remote_gateway(remote_gateway_name,
                            ns=_gateway_namespace,
                            timeout=rospy.Duration(5.0)):
    '''
      Slowly loop (and block) until remote the gateway is visible on our hub.
    '''
    rospy.wait_for_service(ns + '/remote_gateway_info')
    remote_gateway_info_service = rospy.ServiceProxy(
        ns + '/remote_gateway_info', gateway_srvs.RemoteGatewayInfo)
    req = gateway_srvs.RemoteGatewayInfoRequest()
    start_time = rospy.Time.now()
    while not rospy.is_shutdown():
        req = gateway_srvs.RemoteGatewayInfoRequest()
        req.gateways = []
        resp = remote_gateway_info_service(req)
        matched = False
        if rospy.Time.now() - start_time > timeout:
            raise GatewaySampleRuntimeError(
                "timed out waiting for a remote gateway to appear")
        for gateway in resp.gateways:
            if remote_gateway_name == gateway.name:
                matched = True
                break
            remote_gateway_basename = rocon_gateway_utils.gateway_basename(
                gateway.name)
            print("Samples: gateway comparison [%s][%s]" %
                  (remote_gateway_basename, remote_gateway_name))
            if remote_gateway_name == remote_gateway_basename:
                matched = True
                break
        if matched:
            break
def find_first_remote_gateway(ns=_gateway_namespace,
                              timeout=rospy.Duration(15.0)):
    '''
      Parses the remote gateway list to find a gateway to use for testing.

      It's a dumb hack to make testing quite convenient.

      @return gateway string name
      @rtype string
    '''
    rospy.wait_for_service(ns + '/remote_gateway_info')
    remote_gateway_info = rospy.ServiceProxy(ns + '/remote_gateway_info',
                                             gateway_srvs.RemoteGatewayInfo)
    start_time = rospy.Time.now()
    while not rospy.is_shutdown():
        req = gateway_srvs.RemoteGatewayInfoRequest()
        req.gateways = []
        resp = remote_gateway_info(req)
        if rospy.Time.now() - start_time > timeout:
            raise GatewaySampleRuntimeError(
                "timed out waiting for a remote gateway to appear")
        if len(resp.gateways) > 0:
            break
        rospy.sleep(0.5)
    return resp.gateways[0].name
 def update(self):
     if not self._resolve_gateway_namespace():
         return
     self._local_gateway = self._gateway_info()
     req = gateway_srvs.RemoteGatewayInfoRequest()
     req.gateways = []
     self._remote_gateways = self._remote_gateway_info(req).gateways
     self._last_update = rospy.get_rostime()
     # Gateways
     self.gateway_nodes.append(self._local_gateway.name)
     self.gateway_nodes.extend([remote_gateway.name for remote_gateway in self._remote_gateways])
     # Edges
     self.pulled_edges = EdgeList()
     self.gateway_edges = EdgeList()
     self.pulled_edges = EdgeList()
     self.flipped_edges = EdgeList()
     # Check local gateway
     for remote_rule in self._local_gateway.flipped_connections:
         self.gateway_edges.add(Edge(self._local_gateway.name, remote_rule.gateway))
         # this adds a bloody magic space, to help disambiguate node names from topic names
         connection_id = rosgraph.impl.graph.topic_node(remote_rule.rule.name + '-' + remote_rule.rule.type)
         self.flipped_nodes.append(connection_id)
         self.flipped_edges.add(Edge(self._local_gateway.name, connection_id))
         self.flipped_edges.add(Edge(connection_id, remote_rule.gateway))
     for remote_rule in self._local_gateway.pulled_connections:
         connection_id = rosgraph.impl.graph.topic_node(remote_rule.rule.name + '-' + remote_rule.rule.type)
         self.pulled_nodes.append(connection_id)
         self.pulled_edges.add(Edge(self._local_gateway.name, connection_id))
         self.pulled_edges.add(Edge(connection_id, remote_rule.gateway))
     for rule in self._local_gateway.public_interface:
         connection_id = rosgraph.impl.graph.topic_node(rule.name + '-' + rule.type)
         #print "pulled edge: %s->%s" % (self._local_gateway.name, connection_id)
         self.pulled_nodes.append(connection_id)
         self.pulled_edges.add(Edge(self._local_gateway.name, connection_id))
     # Check remote gateways
     for remote_gateway in self._remote_gateways:
         for remote_rule in remote_gateway.flipped_interface:
             connection_id = rosgraph.impl.graph.topic_node(remote_rule.rule.name + '-' + remote_rule.rule.type)
             self.flipped_nodes.append(connection_id)
             self.flipped_edges.add(Edge(remote_gateway.name, connection_id))
             self.flipped_edges.add(Edge(connection_id, remote_rule.gateway))
             self.gateway_edges.add(Edge(remote_gateway.name, remote_rule.gateway))
         for remote_rule in remote_gateway.pulled_interface:
             connection_id = rosgraph.impl.graph.topic_node(remote_rule.rule.name + '-' + remote_rule.rule.type)
             self.pulled_nodes.append(connection_id)
             self.pulled_edges.add(Edge(remote_rule.gateway, connection_id))
             self.pulled_edges.add(Edge(connection_id, remote_gateway.name))
             self.gateway_edges.add(Edge(remote_gateway.name, remote_rule.gateway))
    def _process_invite(self, req):
        '''
          @todo This needs better arranging for logic. Currently it ignores whitelists/blacklists if the local_remote_controllers
          only is flagged. Not an urgent use case though.

          To fix, just do abort checks for local remote controllers first, then put it through the rest of the logic as well.
        '''
        # Todo : add checks for whether client is currently busy or not
        response = rapp_manager_srvs.InviteResponse(
            True, rapp_manager_msgs.ErrorCodes.SUCCESS, "")
        if self._param['local_remote_controllers_only'] and not req.cancel:
            # Don't run this code if cancelling - sometimes our hub will have disappeared and we
            # just want to cancel regardless. Not the cleanest exit, but it will do.
            if self._gateway_name is None:
                return rapp_manager_srvs.InviteResponse(
                    False, rapp_manager_msgs.ErrorCodes.NO_LOCAL_GATEWAY,
                    "no gateway connection yet, invite impossible.")
            remote_gateway_info_request = gateway_srvs.RemoteGatewayInfoRequest(
            )
            remote_gateway_info_request.gateways = []
            remote_gateway_info_response = self._gateway_services[
                'remote_gateway_info'](remote_gateway_info_request)
            remote_target_name = req.remote_target_name
            remote_target_ip = None
            for gateway in remote_gateway_info_response.gateways:
                if gateway.name == remote_target_name:
                    remote_target_ip = gateway.ip
                    break
            if remote_target_ip is not None and self._gateway_ip == remote_target_ip:
                response = self._accept_invitation(req)
            elif remote_target_ip is not None and rosgraph.network.is_local_address(
                    remote_target_ip):
                response = self._accept_invitation(req)
            else:
                return rapp_manager_srvs.InviteResponse(
                    False, rapp_manager_msgs.ErrorCodes.LOCAL_INVITATIONS_ONLY,
                    "local invitations only permitted.")
        elif req.remote_target_name in self._param[
                'remote_controller_whitelist']:
            response = self._accept_invitation(req)
        elif len(self._param['remote_controller_whitelist']
                 ) == 0 and req.remote_target_name not in self._param[
                     'remote_controller_blacklist']:
            response = self._accept_invitation(req)
        else:
            # If we get here, we are not permitted to accept, either not in the whitelist, or in the blacklist
            if len(self._param['remote_controller_whitelist']) != 0:
                response = rapp_manager_srvs.InviteResponse(
                    False, rapp_manager_msgs.ErrorCodes.
                    INVITING_CONTROLLER_NOT_WHITELISTED,
                    "not flagged in a non-empty whitelist")
            else:
                response = rapp_manager_srvs.InviteResponse(
                    False, rapp_manager_msgs.ErrorCodes.
                    INVITING_CONTROLLER_BLACKLISTED,
                    "this remote controller has been blacklisted")
        # publish an update locally
        if response.result:
            remote_controller = rapp_manager_msgs.Constants.NO_REMOTE_CONTROLLER if req.cancel else req.remote_target_name
            self._private_publishers['remote_controller'].publish(
                std_msgs.String(remote_controller))
        return response