http2: make connection re-use work
authorDaniel Stenberg <daniel@haxx.se>
Tue, 20 May 2014 14:50:24 +0000 (16:50 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 20 May 2014 14:50:24 +0000 (16:50 +0200)
Http2 connections would wrongly get closed after each individual
request.

Co-authored-by: Tatsuhiro Tsujikawa
Bug: http://curl.haxx.se/bug/view.cgi?id=1374

lib/http.c
lib/http2.c
lib/http2.h

index 1bb9ffb..7dde821 100644 (file)
@@ -1744,9 +1744,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      the rest of the request in the PERFORM phase. */
   *done = TRUE;
 
-  switch (conn->negnpn) {
+  if(conn->httpversion < 20) { /* unless the connection is re-used and already
+                                  http2 */
+    switch (conn->negnpn) {
     case NPN_HTTP2:
       Curl_http2_init(conn);
+      Curl_http2_setup(conn);
       Curl_http2_switched(conn);
       break;
     case NPN_HTTP1_1:
@@ -1755,7 +1758,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     default:
       /* and as fallback */
       break;
+    }
   }
+  else
+    /* prepare for a http2 request */
+    Curl_http2_setup(conn);
 
   http = data->req.protop;
 
@@ -2999,7 +3006,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
         k->header = FALSE; /* no more header to parse! */
 
         if((k->size == -1) && !k->chunk && !conn->bits.close &&
-           (conn->httpversion >= 11) &&
+           (conn->httpversion == 11) &&
            !(conn->handler->protocol & CURLPROTO_RTSP) &&
            data->set.httpreq != HTTPREQ_HEAD) {
           /* On HTTP 1.1, when connection is not to get closed, but no
index 3ee99e2..1e6e07d 100644 (file)
@@ -103,8 +103,8 @@ static CURLcode http2_disconnect(struct connectdata *conn,
 const struct Curl_handler Curl_handler_http2 = {
   "HTTP2",                              /* scheme */
   ZERO_NULL,                            /* setup_connection */
-  ZERO_NULL,                            /* do_it */
-  ZERO_NULL     ,                       /* done */
+  Curl_http,                            /* do_it */
+  ZERO_NULL,                            /* done */
   ZERO_NULL,                            /* do_more */
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
@@ -123,8 +123,8 @@ const struct Curl_handler Curl_handler_http2 = {
 const struct Curl_handler Curl_handler_http2_ssl = {
   "HTTP2",                              /* scheme */
   ZERO_NULL,                            /* setup_connection */
-  ZERO_NULL,                            /* do_it */
-  ZERO_NULL     ,                       /* done */
+  Curl_http,                            /* do_it */
+  ZERO_NULL,                            /* done */
   ZERO_NULL,                            /* do_more */
   ZERO_NULL,                            /* connect_it */
   ZERO_NULL,                            /* connecting */
@@ -778,24 +778,15 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   return len;
 }
 
-int Curl_http2_switched(struct connectdata *conn)
+void Curl_http2_setup(struct connectdata *conn)
 {
-  int rv;
-  CURLcode rc;
   struct http_conn *httpc = &conn->proto.httpc;
-  /* we are switched! */
-  /* Don't know this is needed here at this moment. Original
-     handler->flags is still useful. */
   if(conn->handler->flags & PROTOPT_SSL)
     conn->handler = &Curl_handler_http2_ssl;
   else
     conn->handler = &Curl_handler_http2;
 
-  httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
-  httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
-  conn->recv[FIRSTSOCKET] = http2_recv;
-  conn->send[FIRSTSOCKET] = http2_send;
-  infof(conn->data, "We have switched to HTTP2\n");
+  infof(conn->data, "Using HTTP2\n");
   httpc->bodystarted = FALSE;
   httpc->closed = FALSE;
   httpc->header_recvbuf = Curl_add_buffer_init();
@@ -805,13 +796,26 @@ int Curl_http2_switched(struct connectdata *conn)
   httpc->upload_left = 0;
   httpc->upload_mem = NULL;
   httpc->upload_len = 0;
+  httpc->stream_id = -1;
 
   conn->httpversion = 20;
 
   /* Put place holder for status line */
   Curl_add_buffer(httpc->header_recvbuf, "HTTP/2.0 200\r\n", 14);
+}
 
+int Curl_http2_switched(struct connectdata *conn)
+{
   /* TODO: May get CURLE_AGAIN */
+  CURLcode rc;
+  struct http_conn *httpc = &conn->proto.httpc;
+  int rv;
+
+  httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
+  httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+  conn->recv[FIRSTSOCKET] = http2_recv;
+  conn->send[FIRSTSOCKET] = http2_send;
+
   rv = (int) ((Curl_send*)httpc->send_underlying)
     (conn, FIRSTSOCKET,
      NGHTTP2_CLIENT_CONNECTION_PREFACE,
index ef994b7..5b14f21 100644 (file)
@@ -36,12 +36,14 @@ CURLcode Curl_http2_init(struct connectdata *conn);
 CURLcode Curl_http2_send_request(struct connectdata *conn);
 CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
                                     struct connectdata *conn);
+void Curl_http2_setup(struct connectdata *conn);
 int Curl_http2_switched(struct connectdata *conn);
 #else /* USE_NGHTTP2 */
 #define Curl_http2_init(x)
 #define Curl_http2_send_request(x)
 #define Curl_http2_request_upgrade(x,y) CURLE_OK
 #define Curl_http2_switched(x)
+#define Curl_http2_setup(x)
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */