]> granicus.if.org Git - curl/commitdiff
openssl: set up hooks with to perform NPN
authorFabian Frank <fabian@pagefault.de>
Thu, 30 Jan 2014 05:18:03 +0000 (21:18 -0800)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 30 Jan 2014 10:13:28 +0000 (11:13 +0100)
NPN is what is available in the wild today to negotiate SPDY or HTTP/2.0
connections. It is expected to be replaced by ALPN in the future. If
HTTP/2.0 is negotiated, this is indicated for the entire connection and
http.c is expected to initialize itself for HTTP/2.0 instead of
HTTP/1.1.

see:
http://technotes.googlecode.com/git/nextprotoneg.html
http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04

lib/urldata.h
lib/vtls/openssl.c

index e37971e02faa9d3a59cadd1e9aa99ac0cc12e117..1e1ef5d6b8a45044e93e6f55417321c87a33cc1f 100644 (file)
@@ -597,6 +597,12 @@ enum upgrade101 {
   UPGR101_WORKING             /* talking upgraded protocol */
 };
 
+enum negotiatenpn {
+  NPN_INIT,                   /* default state */
+  NPN_HTTP1_1,                /* HTTP/1.1 negotiated */
+  NPN_HTTP2_DRAFT09           /* HTTP-draft-0.9/2.0 negotiated */
+};
+
 /*
  * Request specific data in the easy handle (SessionHandle).  Previously,
  * these members were on the connectdata struct but since a conn struct may
@@ -1048,6 +1054,8 @@ struct connectdata {
     TUNNEL_COMPLETE /* CONNECT response received completely */
   } tunnel_state[2]; /* two separate ones to allow FTP */
   struct connectbundle *bundle; /* The bundle we are member of */
+
+  enum negotiatenpn negnpn;
 };
 
 /* The end of connectdata. */
index e83738f60604fb48a753206580d7f01305bbe5d3..7374c133f3c58b978786f1d12fae3bdefcf215cc 100644 (file)
@@ -1399,6 +1399,37 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
 #  define use_sni(x)  Curl_nop_stmt
 #endif
 
+#ifdef USE_NGHTTP2
+/*
+ * in is a list of lenght prefixed strings. this function has to select
+ * the protocol we want to use from the list and write its string into out.
+ */
+static int
+select_next_proto_cb(SSL *ssl,
+                     unsigned char **out, unsigned char *outlen,
+                     const unsigned char *in, unsigned int inlen,
+                     void *arg)
+{
+  struct connectdata *conn = (struct connectdata*) arg;
+  int retval = nghttp2_select_next_protocol(out, outlen, in, inlen);
+  (void)ssl;
+
+  if(retval == 1) {
+    infof(conn->data, "NPN, negotiated HTTP2\n");
+    conn->negnpn = NPN_HTTP2_DRAFT09;
+  }
+  else if(retval == 0) {
+    infof(conn->data, "NPN, negotiated HTTP1.1\n");
+    conn->negnpn = NPN_HTTP1_1;
+  }
+  else {
+    infof(conn->data, "NPN, no overlap, negotiated nothing\n");
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
 static CURLcode
 ossl_connect_step1(struct connectdata *conn,
                    int sockindex)
@@ -1617,6 +1648,10 @@ ossl_connect_step1(struct connectdata *conn,
 
   SSL_CTX_set_options(connssl->ctx, ctx_options);
 
+#ifdef USE_NGHTTP2
+  SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn);
+#endif
+
   if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
     if(!cert_stuff(conn,
                    connssl->ctx,