id,summary,reporter,owner,description,type,status,priority,milestone,component,resolution,keywords,cc,branch,branch_author,launchpad_bug
5015,Add an API which makes it easy to start (and stop) speaking TLS over an arbitrary transport,exarkun,,"For historical reasons, we have `IReactorSSL` and `ITLSTransport`.  There was no way to implement this functionality except directly with the support of the reactor.

With `twisted.protocols.tls`, we now have an implementation that is independent of any TLS-specific support in the reactor.  However, `twisted.protocols.tls` is very geared towards being used to replace `IReactorSSL.connectSSL`/`listenSSL`.  It is possible to use it to replace `ITLSTransport.startTLS`, but:

  1. It's complicated.  There is an unfortunate special case in `twisted.protocols.tls` to deal with this (the `_connectWrapped` argument to `TLSMemoryBIOPRotocol.__init__`).
  1. The very nature of `ITLSTransport` requires direct support from the reactor.  Outside code cannot (cleanly) add a `startTLS` method to an arbitrary transport.

Instead, to remove the need to have support in the reactor, it would be nice to have an API like this:

{{{
#!python
    class SomeProtocol(Protocol):
        def dataReceived(self, bytes):
            if somecondition():
                tls = TLSTransport(ctx, self.transport, self)
                self.transport.switchProtocol(tls)
                self.transport = tls
                # Perhaps also...
                self.transport.handshake()
}}}

These details might even all be wrapped up inside an even simpler helper API:

{{{
#!python
    class SomeProtocol(Protocol):
        def dataReceived(self, bytes):
            if somecondition():
                self.transport = startTLS(ctx, self.transport, self)
}}}

The details might differ, but importantly an API like this can be implemented entirely outside the reactor, except for the new `switchProtocol` method (proposed already in #3204).

This has other nice properties.

  1. Compared to the current APIs and implementation, it's easier to see how stacking works.
  1. Buffering is simplified because the original transport and the TLS transport are separate objects each dealing with buffering on their own.
  1. TLS shutdown without underlying transport shutdown is more obvious, since it just means going back to the original transport and discarding the TLS transport.
",enhancement,new,normal,,core,,,adi@…,,,
