Hi, The ALPN (RFC 7301) [0] API that the Jetty project has implemented, and used for a while, to support SPDY and HTTP2 (h2), is here [1].
It consists of 2 provider interfaces, one for the client and one for the server, with methods that are called by the JDK implementation at the right times to let the application decide what protocol should be negotiated. However, I believe they can be greatly simplified (to a lambda) for JDK 9. The providers needs these moments of interaction. For the client: C1) providing the list of protocols (before the ClientHello is sent) C2) knowing whether the server support ALPN, and if so, what was the protocol chosen (upon receiving the ServerHello) For the server: S1) knowing if the client supports ALPN, and if so what is the list of protocols, and returning the chosen protocol (upon receiving the ClientHello). While C1 is a value that may be provided easily, C2 and S1 require application code to be called by the TLS implementation. The API that I would like to propose is something along these lines. For the client: SSLEngine engine = ...; TLSExtension alpn = new ALPNClientExtension(protocol -> { ... }, "h2", "spdy/3", "http/1.1"); engine.getLocalExtensions().add(alpn); engine.beginHandshake(); For the server: SSLEngine engine = ...; TLSExtension alpn = new ALPNServerExtension(protocols -> { ... }); engine.getLocalExtensions().add(alpn); The two lambdas will be called "as soon as possible", that is for the client just after having received the ServerHello, and for the server just after having received the ClientHello. I say "as soon as possible" this because the h2 specification is still in flux for what regards the constraints that needs to be put in place to accept the negotiation of the h2 protocol (but see the other email about). It may well be that the connection must be closed before the end of the TLS handshake. Alternatively, lacking a full fledged TLS Extensions API, something similar may be put into SSLParameters, although it would require two "container" classes akin to ALPNClientExtension and ALPNServerExtension (in particular for the client, to "link" the lambda with the list of protocols offered). The lambdas would be, for the client: void selected(String protocol) with the semantic that: * a null parameter would mean the server does not support ALPN. If the server cannot negotiate the protocol, it shall (per RFC 7301) close the connection. This leaves open a case where an uncompliant server sends down an empty/null protocol, but I guess this can be treated by the client as if the server does not support ALPN (in fact, it does not support it correctly). * an exception thrown would mean the client is not happy with the protocol chosen (for any reason), and the TLS implementation must close the connection with alert code 120 (per 7301). The lambda for the server would be: String select(List<String> protocols) with the semantic that: * a null list would mean the client does not support (correctly) ALPN. * a null return value or an exception thrown would mean the server could not negotiate the protocol and the connection must be closed with alert code 120 (per 7301). I'd be happy to contribute code and experience about this, but I need guidance on where to start and how to proceed. In particular, if a larger effort for a TLS Extension API is considered useful, then the ALPN implementation is trivial; the bulk of the work would be to design this new TLS Extension API. For a more complete picture about why I think a TLS Extension API would be beneficial, see also the other emails. Thanks ! [0] http://tools.ietf.org/html/rfc7301 [1] https://github.com/eclipse/jetty.alpn/blob/master/src/main/java/org/eclipse/jetty/alpn/ALPN.java -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz