I'm writing a toy http server using CFNetwork/CFStream/SecureTransport. It's been a fun exercise and http/https is all working fine.
I've now moved on to adding http2, and thus I want to support ALPN so ciients can detect 'h2' support.
When connecting to my server via safari I can see the ALPN data from safari on the wire, e.g. "\2h2\5h2-16\5h2-15\5h2-14\10spdy/3.1\6spdy/3\10http/1.1\0", and upon the first kCFStreamEventHasBytesAvailable I can dump the SSL/TLS info from the stream which correctly says the expected protocol and cipher.
However, when I also add the following to investigate the ALPN data within SSLContext
SSLContextRef secContext = (SSLContextRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLContext);
CFArrayRef protocols = NULL;
OSStatus err = SSLCopyALPNProtocols(secContext, &protocols)Then protocols remains NULL, and err is always errSecParam.
Given I actually have TLS/SSL working, the failure of using the ALPN calls to do anything useful makes me wonder if ALPN is actually implemented in SecureTransport for server usage... or am I doing something wrong, or is this framework being deprecated and should I be using something else, i.e. the nw_* framework?
The above represents testing, the true objective is to use SSLSetALPNProtocols() to set "h2" as a server protocol at the same point in my code where I add certficates and enable TLS/SSL, but this seems to have no effect...
In other investigation I've tried adding SSLSetALPNProtocols() and SSLCopyALPNProtocols() into Apples own TLSTool code, again with no useful outcome.
Tested on 10.14.4
I'm writing a toy http server using CFNetwork / CFStream / SecureTransport.
Why? I understand why folks would use this stack for for a real project, but for modern code with no deployment target restrictions you should use the Network framework; it’s much nicer.
I think that Secure Transport supports server-side ALPN, although I’ve never used this so I can’t be sure. The most common cause of problems like this is that you’re making the call in the wrong state, but it seems like you’re doing the right thing here (looking for it when you get the first
kCFStreamEventHasBytesAvailable event).
Regardless, I recommend that you do this just using the Network framework (although be aware that the API to wrangle ALPN comes,
sec_protocol_options_add_tls_application_protocol and
sec_protocol_metadata_get_negotiated_protocol, Security framework).
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"