Example #1
0
    async def _start_tls_connection(
        self,
        underlying_transport: asyncio.Transport,
        req: "ClientRequest",
        timeout: "ClientTimeout",
        client_error: Type[Exception] = ClientConnectorError,
    ) -> Tuple[asyncio.BaseTransport, ResponseHandler]:
        """Wrap the raw TCP transport with TLS."""
        tls_proto = self._factory()  # Create a brand new proto for TLS

        # Safety of the `cast()` call here is based on the fact that
        # internally `_get_ssl_context()` only returns `None` when
        # `req.is_ssl()` evaluates to `False` which is never gonna happen
        # in this code path. Of course, it's rather fragile
        # maintainability-wise but this is to be solved separately.
        sslcontext = cast(ssl.SSLContext, self._get_ssl_context(req))

        try:
            async with ceil_timeout(
                timeout.sock_connect, ceil_threshold=timeout.ceil_threshold
            ):
                try:
                    tls_transport = await self._loop.start_tls(
                        underlying_transport,
                        tls_proto,
                        sslcontext,
                        server_hostname=req.host,
                        ssl_handshake_timeout=timeout.total,
                    )
                except BaseException:
                    # We need to close the underlying transport since
                    # `start_tls()` probably failed before it had a
                    # chance to do this:
                    underlying_transport.close()
                    raise
        except cert_errors as exc:
            raise ClientConnectorCertificateError(req.connection_key, exc) from exc
        except ssl_errors as exc:
            raise ClientConnectorSSLError(req.connection_key, exc) from exc
        except OSError as exc:
            raise client_error(req.connection_key, exc) from exc
        except TypeError as type_err:
            # Example cause looks like this:
            # TypeError: transport <asyncio.sslproto._SSLProtocolTransport
            # object at 0x7f760615e460> is not supported by start_tls()

            raise ClientConnectionError(
                "Cannot initialize a TLS-in-TLS connection to host "
                f"{req.host!s}:{req.port:d} through an underlying connection "
                f"to an HTTPS proxy {req.proxy!s} ssl:{req.ssl or 'default'} "
                f"[{type_err!s}]"
            ) from type_err
        else:
            tls_proto.connection_made(
                tls_transport
            )  # Kick the state machine of the new TLS protocol

        return tls_transport, tls_proto
Example #2
0
def shutdown(_loop: Loop, _transport: asyncio.Transport, _server: Server,
             executors: List[Executor]):
    print('shutting down sockets, processes, threads and abort tasks')
    for task in asyncio.Task.all_tasks():
        task.cancel()
    for executor in executors:
        executor.shutdown()
    _transport.close()
    _server.close()
    _loop.stop()
Example #3
0
File: protocol.py Project: sdss/clu
    def connection_made(self, transport: asyncio.Transport):
        """Receives a connection and calls the connection callback."""

        if self.max_connections is None or (len(self.transports) <
                                            self.max_connections):
            self.transports.append(transport)
        else:
            transport.write("Maximum number of connections reached.")
            transport.close()

        if self.connection_callback:
            self.connection_callback(transport)
Example #4
0
    def connection_made(self, transport: asyncio.Transport):
        self.transport = transport
        self.client_cert = transport.get_extra_info("peercert")

        ssl_context = transport.get_extra_info("ssl_object")
        if ssl.HAS_ALPN:
            agreed_protocol = ssl_context.selected_alpn_protocol()
        else:
            agreed_protocol = ssl_context.selected_npn_protocol()

        if agreed_protocol is None:
            error("Connection error, client does not support HTTP/2")
            transport.close()
        else:
            self.conn.initiate_connection()
Example #5
0
async def start_tls(
    loop: asyncio.AbstractEventLoop,
    transport: asyncio.Transport,
    protocol: asyncio.Protocol,
    sslcontext: ssl.SSLContext,
    server_side: bool = False,
    server_hostname: Optional[str] = None,
    ssl_handshake_timeout: Optional[Union[float, int]] = None,
) -> asyncio.Transport:
    # We use hasattr here, as uvloop also supports start_tls.
    if hasattr(loop, "start_tls"):
        return await loop.start_tls(  # type: ignore
            transport,
            protocol,
            sslcontext,
            server_side=server_side,
            server_hostname=server_hostname,
            ssl_handshake_timeout=ssl_handshake_timeout,
        )

    waiter = loop.create_future()
    ssl_protocol = SSLProtocol(loop, protocol, sslcontext, waiter, server_side,
                               server_hostname)

    # Pause early so that "ssl_protocol.data_received()" doesn't
    # have a chance to get called before "ssl_protocol.connection_made()".
    transport.pause_reading()

    # Use set_protocol if we can
    if hasattr(transport, "set_protocol"):
        transport.set_protocol(ssl_protocol)  # type: ignore
    else:
        transport._protocol = ssl_protocol  # type: ignore

    conmade_cb = loop.call_soon(ssl_protocol.connection_made, transport)
    resume_cb = loop.call_soon(transport.resume_reading)

    try:
        await asyncio.wait_for(waiter, timeout=ssl_handshake_timeout)
    except Exception:
        transport.close()
        conmade_cb.cancel()
        resume_cb.cancel()
        raise

    return ssl_protocol._app_transport