Esempio n. 1
0
async def test_simple():
    task = asyncio_utils.create_task(ttask(),
                                     name="ttask",
                                     client=("127.0.0.1", 42313))
    assert asyncio_utils.task_repr(task) == "127.0.0.1:42313: ttask (age: 0s)"
    await asyncio.sleep(0)
    assert "newname" in asyncio_utils.task_repr(task)
    asyncio_utils.cancel_task(task, "bye")
    await asyncio.sleep(0)
    assert task.cancelled()
Esempio n. 2
0
 async def drain_writers(self):
     """
     Drain all writers to create some backpressure. We won't continue reading until there's space available in our
     write buffers, so if we cannot write fast enough our own read buffers run full and the TCP recv stream is throttled.
     """
     async with self._drain_lock:
         for transport in self.transports.values():
             if transport.writer is not None:
                 try:
                     await transport.writer.drain()
                 except OSError as e:
                     if transport.handler is not None:
                         asyncio_utils.cancel_task(transport.handler, f"Error sending data: {e}")
Esempio n. 3
0
    async def handle_client(self) -> None:
        watch = asyncio_utils.create_task(
            self.timeout_watchdog.watch(),
            name="timeout watchdog",
            client=self.client.peername,
        )
        if not watch:
            return  # this should not be needed, see asyncio_utils.create_task

        self.log("client connect")
        await self.handle_hook(server_hooks.ClientConnectedHook(self.client))
        if self.client.error:
            self.log("client kill connection")
            writer = self.transports.pop(self.client).writer
            assert writer
            writer.close()
        else:
            handler = asyncio_utils.create_task(
                self.handle_connection(self.client),
                name=f"client connection handler",
                client=self.client.peername,
            )
            if not handler:
                return  # this should not be needed, see asyncio_utils.create_task
            self.transports[self.client].handler = handler
            self.server_event(events.Start())
            await asyncio.wait([handler])

        watch.cancel()

        self.log("client disconnect")
        self.client.timestamp_end = time.time()
        await self.handle_hook(server_hooks.ClientDisconnectedHook(self.client)
                               )

        if self.transports:
            self.log("closing transports...", "debug")
            for io in self.transports.values():
                if io.handler:
                    asyncio_utils.cancel_task(io.handler,
                                              "client disconnected")
            await asyncio.wait(
                [x.handler for x in self.transports.values() if x.handler])
            self.log("transports closed!", "debug")
Esempio n. 4
0
    def close_connection(self, connection: Connection, half_close: bool = False) -> None:
        if half_close:
            if not connection.state & ConnectionState.CAN_WRITE:
                return
            self.log(f"half-closing {connection}", "debug")
            try:
                writer = self.transports[connection].writer
                assert writer
                writer.write_eof()
            except OSError:
                # if we can't write to the socket anymore we presume it completely dead.
                connection.state = ConnectionState.CLOSED
            else:
                connection.state &= ~ConnectionState.CAN_WRITE
        else:
            connection.state = ConnectionState.CLOSED

        if connection.state is ConnectionState.CLOSED:
            handler = self.transports[connection].handler
            assert handler
            asyncio_utils.cancel_task(handler, "closed by command")
Esempio n. 5
0
 async def on_timeout(self) -> None:
     self.log(f"Closing connection due to inactivity: {self.client}")
     handler = self.transports[self.client].handler
     assert handler
     asyncio_utils.cancel_task(handler, "timeout")