Esempio n. 1
0
    async def open_connection(self, command: commands.OpenConnection) -> None:
        if not command.connection.address:
            self.log(f"Cannot open connection, no hostname given.")
            self.server_event(events.OpenConnectionCompleted(command, f"Cannot open connection, no hostname given."))
            return

        hook_data = server_hooks.ServerConnectionHookData(
            client=self.client,
            server=command.connection
        )
        await self.handle_hook(server_hooks.ServerConnectHook(hook_data))
        if err := command.connection.error:
            self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect: {err}")
            self.server_event(events.OpenConnectionCompleted(command, f"Connection killed: {err}"))
            return
Esempio n. 2
0
    async def open_connection(self, command: commands.OpenConnection) -> None:
        if not command.connection.address:
            self.log(f"Cannot open connection, no hostname given.")
            self.server_event(events.OpenConnectionCompleted(command, f"Cannot open connection, no hostname given."))
            return

        hook_data = server_hooks.ServerConnectionHookData(
            client=self.client,
            server=command.connection
        )
        await self.handle_hook(server_hooks.ServerConnectHook(hook_data))
        if command.connection.error:
            self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect.")
            self.server_event(events.OpenConnectionCompleted(command, "Connection killed."))
            return

        async with self.max_conns[command.connection.address]:
            try:
                command.connection.timestamp_start = time.time()
                reader, writer = await asyncio.open_connection(*command.connection.address)
            except (IOError, asyncio.CancelledError) as e:
                err = str(e)
                if not err:  # str(CancelledError()) returns empty string.
                    err = "connection cancelled"
                self.log(f"error establishing server connection: {err}")
                command.connection.error = err
                self.server_event(events.OpenConnectionCompleted(command, err))
                if isinstance(e, asyncio.CancelledError):
                    # From https://docs.python.org/3/library/asyncio-exceptions.html#asyncio.CancelledError:
                    # > In almost all situations the exception must be re-raised.
                    # It is not really defined what almost means here, but we play safe.
                    raise
            else:
                command.connection.timestamp_tcp_setup = time.time()
                command.connection.state = ConnectionState.OPEN
                command.connection.peername = writer.get_extra_info('peername')
                command.connection.sockname = writer.get_extra_info('sockname')
                self.transports[command.connection].reader = reader
                self.transports[command.connection].writer = writer

                assert command.connection.peername
                if command.connection.address[0] != command.connection.peername[0]:
                    addr = f"{command.connection.address[0]} ({human.format_address(command.connection.peername)})"
                else:
                    addr = human.format_address(command.connection.address)
                self.log(f"server connect {addr}")
                connected_hook = asyncio_utils.create_task(
                    self.handle_hook(server_hooks.ServerConnectedHook(hook_data)),
                    name=f"handle_hook(server_connected) {addr}",
                    client=self.client.peername,
                )
                if not connected_hook:
                    return  # this should not be needed, see asyncio_utils.create_task

                self.server_event(events.OpenConnectionCompleted(command, None))

                # during connection opening, this function is the designated handler that can be cancelled.
                # once we have a connection, we do want the teardown here to happen in any case, so we
                # reassign the handler to .handle_connection and then clean up here once that is done.
                new_handler = asyncio_utils.create_task(
                    self.handle_connection(command.connection),
                    name=f"server connection handler for {addr}",
                    client=self.client.peername,
                )
                if not new_handler:
                    return  # this should not be needed, see asyncio_utils.create_task
                self.transports[command.connection].handler = new_handler
                await asyncio.wait([new_handler])

                self.log(f"server disconnect {addr}")
                command.connection.timestamp_end = time.time()
                await connected_hook  # wait here for this so that closed always comes after connected.
                await self.handle_hook(server_hooks.ServerDisconnectedHook(hook_data))