Ejemplo n.º 1
0
async def worker_serve(
    app: ASGIFramework,
    config: Config,
    *,
    sockets: Optional[Sockets] = None,
    shutdown_event: Optional[EventType] = None,
    task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED,
) -> None:
    lifespan = Lifespan(app, config)
    reload_ = False

    async with trio.open_nursery() as lifespan_nursery:
        await lifespan_nursery.start(lifespan.handle_lifespan)
        await lifespan.wait_for_startup()

        try:
            async with trio.open_nursery() as nursery:
                if config.use_reloader:
                    nursery.start_soon(observe_changes, trio.sleep)

                if shutdown_event is not None:
                    nursery.start_soon(check_shutdown, shutdown_event,
                                       trio.sleep)

                if sockets is None:
                    sockets = config.create_sockets()
                    for sock in sockets.secure_sockets:
                        sock.listen(config.backlog)
                    for sock in sockets.insecure_sockets:
                        sock.listen(config.backlog)

                ssl_context = config.create_ssl_context()
                listeners = [
                    trio.ssl.SSLListener(
                        trio.SocketListener(
                            trio.socket.from_stdlib_socket(sock)),
                        ssl_context,
                        https_compatible=True,
                    ) for sock in sockets.secure_sockets
                ]
                listeners.extend([
                    trio.SocketListener(trio.socket.from_stdlib_socket(sock))
                    for sock in sockets.insecure_sockets
                ])
                task_status.started()
                await trio.serve_listeners(partial(serve_stream, app, config),
                                           listeners)

        except MustReloadException:
            reload_ = True
        except (Shutdown, KeyboardInterrupt):
            pass
        finally:
            await lifespan.wait_for_shutdown()
            lifespan_nursery.cancel_scope.cancel()

    if reload_:
        restart()
Ejemplo n.º 2
0
    async def _run_server(self) -> None:
        async with trio.open_nursery() as nursery:
            # Store nursery on self so that we can access it for cancellation
            self._server_nursery = nursery

            self.logger.debug("%s: server starting", self)
            socket = trio.socket.socket(trio.socket.AF_UNIX,
                                        trio.socket.SOCK_STREAM)
            await socket.bind(self.ipc_path.__fspath__())
            socket.listen(self._connection_backlog)
            listener = trio.SocketListener(socket)

            async def set_socket_bound() -> None:
                self._socket_bound.set()

            # Use start_soon here so that we give serve_listeners() below a chance to run before
            # other endpoints start connecting to us.
            nursery.start_soon(set_socket_bound)

            try:
                await trio.serve_listeners(
                    handler=self._accept_conn,
                    listeners=(listener, ),
                    handler_nursery=nursery,
                )
            finally:
                self.logger.debug("%s: server finished", self)
Ejemplo n.º 3
0
    async def run_server(task_status=trio.TASK_STATUS_IGNORED):
        if sock:
            listeners = [trio.SocketListener(from_stdlib_socket(sock.sock))]
        else:
            if ssl:
                listeners = await trio.open_ssl_over_tcp_listeners(port,
                                                                   ssl,
                                                                   host=host)
            else:
                listeners = await trio.open_tcp_listeners(port, host=host)

        # An outer nursery to run connection tasks in.
        server = None
        async with trio.open_nursery() as connection_nursery:
            # We can cancel serve_listeners() via this scope, without cancelling
            # the connection tasks.
            with trio.open_cancel_scope() as cancel_scope:
                server = Server(listeners=listeners,
                                nursery=nursery,
                                cancel_scope=cancel_scope)
                task_status.started(server)
                await trio.serve_listeners(functools.partial(
                    handle_connection, protocol_factory),
                                           listeners,
                                           handler_nursery=connection_nursery)
        if server is not None:
            server._closed.set()
Ejemplo n.º 4
0
 async def orchestrate_tcp(self):
     with trio.socket.from_stdlib_socket(self.tcp) as sock:
         self.tcp = None  # we own cleanup
         listener = trio.SocketListener(sock)
         async with trio.open_nursery() as nursery:
             serve = functools.partial(trio.serve_listeners,
                                       self.serve_tcp, [listener],
                                       handler_nursery=nursery)
             nursery.start_soon(serve)
Ejemplo n.º 5
0
async def _main():
    pkdlog('runner daemon starting up')
    with trio.socket.socket(family=trio.socket.AF_UNIX) as sock:
        # XX TODO: better strategy for handoff between runner instances
        # Clear out any stale socket file
        sock_path = srdb.runner_socket_path()
        pkio.unchecked_remove(sock_path)
        await sock.bind(str(sock_path))
        sock.listen(_LISTEN_QUEUE)
        listener = trio.SocketListener(sock)

        async with trio.open_nursery() as nursery:
            nursery.start_soon(_tmp_dir_gc)
            job_tracker = _JobTracker(nursery)
            await trio.serve_listeners(
                functools.partial(_handle_conn, job_tracker),
                [listener],
            )
Ejemplo n.º 6
0
    async def _run_servers(self):
        import trio
        
        print('hello')
        listeners = await trio.open_tcp_listeners(self.port)


        if self.unix_socket:
            from trio.socket import socket, SOCK_STREAM, AF_UNIX, SOL_SOCKET, SO_REUSEADDR
            
            sock = socket(AF_UNIX, SOCK_STREAM)
            sock.setsockopt(
                SOL_SOCKET, SO_REUSEADDR, 1
            )
            await sock.bind(self.unix_socket)
            sock.listen(10)
            listeners.append(trio.SocketListener(sock))

        print(listeners)
        await trio.serve_listeners(self.handle_client, listeners)
Ejemplo n.º 7
0
def trio_streams(server_sock):
    import trio

    async def httpserve(stream):
        async with stream:
            data = bytearray()
            try:
                async for d in stream:
                    data += d
                    pos = data.find(b"\r\n\r\n", max(0,
                                                     len(data) - len(d) - 3))
                    if pos > -1:
                        del data[:pos + 4]
                        await stream.send_all(response)
            except trio.BrokenResourceError:
                pass

    # Streams API requires some trickery to use stdlib socket
    server_sock = trio.socket.from_stdlib_socket(server_sock)
    listeners = trio.SocketListener(server_sock),
    trio.run(trio.serve_listeners, httpserve, listeners)
Ejemplo n.º 8
0
    async def _run_server(self, ipc_path: trio.Path) -> None:
        async with trio.open_nursery() as nursery:
            # Store nursery on self so that we can access it for cancellation
            self._server_nursery = nursery

            self.logger.debug("%s: server starting", self)
            socket = trio.socket.socket(trio.socket.AF_UNIX,
                                        trio.socket.SOCK_STREAM)
            await socket.bind(self.ipc_path.__fspath__())
            socket.listen(1)
            listener = trio.SocketListener(socket)

            self._server_running.set()

            try:
                await trio.serve_listeners(
                    handler=self._accept_conn,
                    listeners=(listener, ),
                    handler_nursery=nursery,
                )
            finally:
                self.logger.debug("%s: server stopping", self)
Ejemplo n.º 9
0
async def serve_outbound(listen_addr,
                         gid: int,
                         task_status=trio.TASK_STATUS_IGNORED):
    """Serve a listening socket at listen_addr.
    Start a single handle_outbound for the first connection received to this socket.
    This will be run once per outbound connection made by C-Lightning (using rpc
    `proxy-connect`) so that each connection has it's own socket address.
    """
    # Setup the listening socket.
    sock = trio.socket.socket(trio.socket.AF_UNIX, trio.socket.SOCK_STREAM)
    await sock.bind(listen_addr)
    sock.listen()
    logger.debug(f"Listening for new outbound connection on {listen_addr}")
    # Report back to Trio that we've made the connection and are ready to receive
    task_status.started()
    # Start only a single handle_outbound for this connection.
    # TODO: If we keep this open, will it allow re-connects?
    await trio.serve_listeners(
        functools.partial(handle_outbound, gid=gid),
        [trio.SocketListener(sock)],
        handler_nursery=None,
        task_status=trio.TASK_STATUS_IGNORED,
    )
    logger.debug(f"serve_outbound for GID {gid} finished.")
Ejemplo n.º 10
0
async def worker_serve(
    app: ASGIFramework,
    config: Config,
    *,
    sockets: Optional[Sockets] = None,
    shutdown_trigger: Optional[Callable[..., Awaitable[None]]] = None,
    task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED,
) -> None:
    config.set_statsd_logger_class(StatsdLogger)

    lifespan = Lifespan(app, config)
    reload_ = False

    async with trio.open_nursery() as lifespan_nursery:
        await lifespan_nursery.start(lifespan.handle_lifespan)
        await lifespan.wait_for_startup()

        try:
            async with trio.open_nursery() as nursery:
                if config.use_reloader:
                    nursery.start_soon(observe_changes, trio.sleep)

                if shutdown_trigger is not None:
                    nursery.start_soon(raise_shutdown, shutdown_trigger)

                if sockets is None:
                    sockets = config.create_sockets()
                    for sock in sockets.secure_sockets:
                        sock.listen(config.backlog)
                    for sock in sockets.insecure_sockets:
                        sock.listen(config.backlog)

                ssl_context = config.create_ssl_context()
                listeners = []
                binds = []
                for sock in sockets.secure_sockets:
                    listeners.append(
                        trio.SSLListener(
                            trio.SocketListener(
                                trio.socket.from_stdlib_socket(sock)),
                            ssl_context,
                            https_compatible=True,
                        ))
                    bind = repr_socket_addr(sock.family, sock.getsockname())
                    binds.append(f"https://{bind}")
                    await config.log.info(
                        f"Running on https://{bind} (CTRL + C to quit)")

                for sock in sockets.insecure_sockets:
                    listeners.append(
                        trio.SocketListener(
                            trio.socket.from_stdlib_socket(sock)))
                    bind = repr_socket_addr(sock.family, sock.getsockname())
                    binds.append(f"http://{bind}")
                    await config.log.info(
                        f"Running on http://{bind} (CTRL + C to quit)")

                for sock in sockets.quic_sockets:
                    await nursery.start(
                        UDPServer(app, config, sock, nursery).run)
                    bind = repr_socket_addr(sock.family, sock.getsockname())
                    await config.log.info(
                        f"Running on https://{bind} (QUIC) (CTRL + C to quit)")

                task_status.started(binds)
                await trio.serve_listeners(partial(TCPServer, app, config),
                                           listeners,
                                           handler_nursery=lifespan_nursery)

        except MustReloadException:
            reload_ = True
        except (Shutdown, KeyboardInterrupt):
            pass
        finally:
            try:
                await trio.sleep(config.graceful_timeout)
            except (Shutdown, KeyboardInterrupt):
                pass

            await lifespan.wait_for_shutdown()
            lifespan_nursery.cancel_scope.cancel()

    if reload_:
        restart()
Ejemplo n.º 11
0
async def open_tcp_listeners(port, *, host=None, backlog=None):
    """Create :class:`SocketListener` objects to listen for TCP connections.

    Args:

      port (int): The port to listen on.

          If you use 0 as your port, then the kernel will automatically pick
          an arbitrary open port. But be careful: if you use this feature when
          binding to multiple IP addresses, then each IP address will get its
          own random port, and the returned listeners will probably be
          listening on different ports. In particular, this will happen if you
          use ``host=None`` – which is the default – because in this case
          :func:`open_tcp_listeners` will bind to both the IPv4 wildcard
          address (``0.0.0.0``) and also the IPv6 wildcard address (``::``).

      host (str, bytes-like, or None): The local interface to bind to. This is
          passed to :func:`~socket.getaddrinfo` with the ``AI_PASSIVE`` flag
          set.

          If you want to bind to the wildcard address on both IPv4 and IPv6,
          in order to accept connections on all available interfaces, then
          pass ``None``. This is the default.

          If you have a specific interface you want to bind to, pass its IP
          address or hostname here. If a hostname resolves to multiple IP
          addresses, this function will open one listener on each of them.

          If you want to use only IPv4, or only IPv6, but want to accept on
          all interfaces, pass the family-specific wildcard address:
          ``"0.0.0.0"`` for IPv4-only and ``"::"`` for IPv6-only.

      backlog (int or None): The listen backlog to use. If you leave this as
          ``None`` then Trio will pick a good default. (Currently: whatever
          your system has configured as the maximum backlog.)

    Returns:
      list of :class:`SocketListener`

    """
    # getaddrinfo sometimes allows port=None, sometimes not (depending on
    # whether host=None). And on some systems it treats "" as 0, others it
    # doesn't:
    #   http://klickverbot.at/blog/2012/01/getaddrinfo-edge-case-behavior-on-windows-linux-and-osx/
    if not isinstance(port, int):
        raise TypeError("port must be an int not {!r}".format(port))

    backlog = _compute_backlog(backlog)

    addresses = await tsocket.getaddrinfo(host,
                                          port,
                                          type=tsocket.SOCK_STREAM,
                                          flags=tsocket.AI_PASSIVE)

    listeners = []
    unsupported_address_families = []
    try:
        for family, type, proto, _, sockaddr in addresses:
            try:
                sock = tsocket.socket(family, type, proto)
            except OSError as ex:
                if ex.errno == errno.EAFNOSUPPORT:
                    # If a system only supports IPv4, or only IPv6, it
                    # is still likely that getaddrinfo will return
                    # both an IPv4 and an IPv6 address. As long as at
                    # least one of the returned addresses can be
                    # turned into a socket, we won't complain about a
                    # failure to create the other.
                    unsupported_address_families.append(ex)
                    continue
                else:
                    raise
            try:
                # See https://github.com/python-trio/trio/issues/39
                if sys.platform != "win32":
                    sock.setsockopt(tsocket.SOL_SOCKET, tsocket.SO_REUSEADDR,
                                    1)

                if family == tsocket.AF_INET6:
                    sock.setsockopt(tsocket.IPPROTO_IPV6, tsocket.IPV6_V6ONLY,
                                    1)

                await sock.bind(sockaddr)
                sock.listen(backlog)

                listeners.append(trio.SocketListener(sock))
            except:
                sock.close()
                raise
    except:
        for listener in listeners:
            listener.socket.close()
        raise

    if unsupported_address_families and not listeners:
        raise OSError(
            errno.EAFNOSUPPORT,
            "This system doesn't support any of the kinds of "
            "socket that that address could use",
        ) from trio.MultiError(unsupported_address_families)

    return listeners