
On 13 Jan 2017, at 15:45, Nick Coghlan <ncoghlan@gmail.com> wrote:
So the essential stack would look like:
TLSConfig[uration?]: implementation independent, settings only TLSClientContext: ABC to combine settings with a specific TLS implementation TLSServerContext: ABC to combine settings with a specific TLS implementation TLSSocket: ABC to combine a context with a network socket TLSBuffer: ABC to combine a context with a pair of data buffers
And then TLSPolicy would be a potential future implementation independent addition that could be used to constrain acceptable TLS configurations.
If we were going this way, I’d want to add one extra caveat: I think I’d want the Contexts to become immutable. The logic for the SNI callback would then become: you are called with the Context that created the socket/buffer, and you return a Configuration object that contains any changes you want to make, and the Context applies them if it can (or errors out if it cannot). A new Context is created. This relegates Context to the role of “socket/buffer factory”. The advantage of this is that we have vastly reduced the moving parts: a Context can ensure that, once initiated, the Policy that belongs to it will not change under its feet. It also allows the Context to refuse to change settings that a given concrete implementation cannot change in the SNI callback. Essentially, the logic in the callback would be: def sni_callback(buffer, hostname, context): # This creates a writable copy of the configuration: it does not # mutate the original. configuration = context.configuration configuration.certificates = certs_for_hostname(hostname) configuration.inner_protocols = [NextProtocol.H2, NextProtocol.HTTP1] return configuration This would almost certainly make Context implementation easier, as there is no longer a requirement to monitor your configuration and support live-updates. Cory