Ejemplo n.º 1
0
    async def connect(self) -> None:
        """Connect the multiplexer."""
        self._loop = asyncio.get_event_loop()
        self.logger.debug("Multiplexer connecting...")
        self._connection_consistency_checks()
        self._set_default_connection_if_none()
        self._out_queue = asyncio.Queue()

        async with self._lock:
            if self.connection_status.is_connected:
                self.logger.debug("Multiplexer already connected.")
                return
            try:
                self.connection_status.set(ConnectionStates.connecting)
                await self._connect_all()

                if all(c.is_connected for c in self._connections):
                    self.connection_status.set(ConnectionStates.connected)
                else:  # pragma: nocover
                    raise AEAConnectionError(
                        "Failed to connect the multiplexer.")

                self._recv_loop_task = self._loop.create_task(
                    self._receiving_loop())
                self._send_loop_task = self._loop.create_task(
                    self._send_loop())
                self.logger.debug("Multiplexer connected and running.")
            except (CancelledError, asyncio.CancelledError):  # pragma: nocover
                await self._stop()
                raise asyncio.CancelledError()
            except Exception:
                self.logger.exception("Exception on connect:")
                await self._stop()
                raise AEAConnectionError("Failed to connect the multiplexer.")
Ejemplo n.º 2
0
 async def send(self, envelope: Envelope):
     """Send a message."""
     if not self.connection_status.is_connected:
         raise AEAConnectionError(
             "Connection not established yet. Please use 'connect()'.")
     self._writer._loop.call_soon_threadsafe(self._writer.put_nowait,
                                             envelope)  # type: ignore
Ejemplo n.º 3
0
 def _check_and_set_disconnected_state(self) -> None:
     """Check every connection is disconnected and set disconnected state."""
     if all([c.is_disconnected for c in self.connections]):
         self.connection_status.set(ConnectionStates.disconnected)
     else:
         raise AEAConnectionError(
             "Failed to disconnect multiplexer, some connections are not disconnected!"
         )
Ejemplo n.º 4
0
 def try_register(self) -> bool:
     """Try to register to the provider."""
     try:
         assert self._httpCall is not None
         self.logger.info(self.address)
         query = self._httpCall.register(sender_address=self.address, mailbox=True)
         return query["status"] == "OK"
     except Exception:  # pragma: no cover
         self.logger.warning("Could not register to the provider.")
         raise AEAConnectionError()
Ejemplo n.º 5
0
    async def _send(self, envelope: Envelope) -> None:
        """
        Send an envelope.

        :param envelope: the envelope to send.
        :return: None
        :raises ValueError: if the connection id provided is not valid.
        :raises AEAConnectionError: if the connection id provided is not valid.
        """
        connection_id = None  # type: Optional[PublicId]
        envelope_context = envelope.context
        # first, try to route by context
        if envelope_context is not None:
            connection_id = envelope_context.connection_id

        # second, try to route by default routing
        if connection_id is None and envelope.protocol_id in self.default_routing:
            connection_id = self.default_routing[envelope.protocol_id]
            self.logger.debug("Using default routing: {}".format(connection_id))

        if connection_id is not None and connection_id not in self._id_to_connection:
            raise AEAConnectionError(
                "No connection registered with id: {}.".format(connection_id)
            )

        # third, if no other option route by default connection
        if connection_id is None:
            self.logger.debug(
                "Using default connection: {}".format(self.default_connection)
            )
            connection = self.default_connection
        else:
            connection = self._id_to_connection[connection_id]

        connection = cast(Connection, connection)
        if (
            len(connection.restricted_to_protocols) > 0
            and envelope.protocol_id not in connection.restricted_to_protocols
        ):
            self.logger.warning(
                "Connection {} cannot handle protocol {}. Cannot send the envelope.".format(
                    connection.connection_id, envelope.protocol_id
                )
            )
            return

        try:
            await connection.send(envelope)
        except Exception as e:  # pylint: disable=broad-except
            self._handle_exception(self._send, e)
Ejemplo n.º 6
0
 async def disconnect(self) -> None:
     """Disconnect the multiplexer."""
     self.logger.debug("Multiplexer disconnecting...")
     async with self._lock:
         if self.connection_status.is_disconnected:
             self.logger.debug("Multiplexer already disconnected.")
             return
         try:
             self.connection_status.set(ConnectionStates.disconnecting)
             await asyncio.wait_for(self._stop(), timeout=60)
             self.logger.debug("Multiplexer disconnected.")
         except (CancelledError, Exception):
             self.logger.exception("Exception on disconnect:")
             raise AEAConnectionError("Failed to disconnect the multiplexer.")
Ejemplo n.º 7
0
    async def _send(self, envelope: Envelope) -> None:
        """
        Send an envelope.

        :param envelope: the envelope to send.
        :return: None
        :raises ValueError: if the connection id provided is not valid.
        :raises AEAConnectionError: if the connection id provided is not valid.
        """
        connection_id = None  # type: Optional[PublicId]
        envelope_context = envelope.context
        # first, try to route by context
        if envelope_context is not None:
            connection_id = envelope_context.connection_id

        envelope_protocol_id = self._get_protocol_id_for_envelope(envelope)

        # second, try to route by default routing
        if connection_id is None and envelope_protocol_id in self.default_routing:
            connection_id = self.default_routing[envelope_protocol_id]
            self.logger.debug(
                "Using default routing: {}".format(connection_id))

        if connection_id is not None and connection_id not in self._id_to_connection:
            raise AEAConnectionError(
                "No connection registered with id: {}.".format(connection_id))

        # third, if no other option route by default connection
        if connection_id is None:
            self.logger.debug("Using default connection: {}".format(
                self.default_connection))
            connection = self.default_connection
        else:
            connection = self._id_to_connection[connection_id]

        if connection is None:
            self.logger.warning(
                f"Dropping envelope, no connection available for sending: {envelope}"
            )
            return

        if not self._is_connection_supported_protocol(connection,
                                                      envelope_protocol_id):
            return

        try:
            await connection.send(envelope)
        except Exception as e:  # pylint: disable=broad-except
            self._handle_exception(self._send, e)
Ejemplo n.º 8
0
    async def receive(self, *args, **kwargs) -> Optional["Envelope"]:
        """
        Receive an envelope. Blocking.

        :return: the envelope received, or None.
        """
        if not self.connection_status.is_connected:
            raise AEAConnectionError(
                "Connection not established yet. Please use 'connect()'.")
        try:
            assert self._reader is not None
            envelope = await self._reader.get()
            if envelope is None:
                logger.debug("Receiving task terminated.")
                return None
            logger.debug("Received envelope {}".format(envelope))
            return envelope
        except Exception:
            return None
Ejemplo n.º 9
0
 async def connect(self) -> None:
     """Connect the multiplexer."""
     self.logger.debug("Multiplexer connecting...")
     self._connection_consistency_checks()
     self._set_default_connection_if_none()
     self._out_queue = asyncio.Queue()
     async with self._lock:
         if self.connection_status.is_connected:
             self.logger.debug("Multiplexer already connected.")
             return
         try:
             await self._connect_all()
             assert self.is_connected, "At least one connection failed to connect!"
             self._connection_status.is_connected = True
             self._recv_loop_task = self._loop.create_task(
                 self._receiving_loop())
             self._send_loop_task = self._loop.create_task(
                 self._send_loop())
             self.logger.debug("Multiplexer connected and running.")
         except (CancelledError, Exception):
             self.logger.exception("Exception on connect:")
             self._connection_status.is_connected = False
             await self._stop()
             raise AEAConnectionError("Failed to connect the multiplexer.")