I'm working on porting pypostgresql (pure python postgresql driver) library to use asyncio as its underlying IO machinery. And it appears that PQ3 protocol starts as clear text, and then upgrades to use TLS (if server or connection configured so).
I've been experimenting with various approaches to how we can design an API for this, and below are some of my thoughts:
1. The API cannot be implemented on event loop. Loops generally know nothing about the internal structure of transports, i.e. what loop or protocol the transport is attached to.
2. The API cannot be implemented on protocols. Protocols are decoupled from transports (they only receive a reference to the corresponding transport in their connection_made method). Access to the transport is requires to create an SSL proxy transport/protocol pair.
3. Therefore, the most convenient place to add the new API are *transports*. I propose to add a 'start_ssl' method to transports with the following signature:
def start_ssl(self, sslcontext=None,
server_side=False, server_hostname=None) -> Transport:
It will only be implemented on Python 3.5 (because of SSL MemoryBIO requirement).
Protocols can call 'start_ssl' any time after 'connection_made' is called. 'start_ssl' returns a new Transport (ssl proxy) that has to be used from that moment on. In case the SSL handshake fails, protocol's 'connection_lost' method will be called.