]> granicus.if.org Git - curl/commitdiff
http2: handle 101 responses and switch to HTTP2
authorDaniel Stenberg <daniel@haxx.se>
Thu, 12 Sep 2013 11:51:04 +0000 (13:51 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 29 Jan 2014 09:24:05 +0000 (10:24 +0100)
lib/http.c
lib/http2.c
lib/http2.h
lib/urldata.h

index da03a44c5ebc83baedd8e77eacb6acca3429de21..8df0105a1bb09b14dd369079a3fe92a9481a0ec7 100644 (file)
@@ -2872,10 +2872,27 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
         k->header = TRUE;
         k->headerline = 0; /* restart the header line counter */
 
-        /* if we did wait for this do enable write now! */
-        if(k->exp100) {
-          k->exp100 = EXP100_SEND_DATA;
-          k->keepon |= KEEP_SEND;
+        /* "A user agent MAY ignore unexpected 1xx status responses." */
+        switch(k->httpcode) {
+        case 100:
+          /* if we did wait for this do enable write now! */
+          if(k->exp100) {
+            k->exp100 = EXP100_SEND_DATA;
+            k->keepon |= KEEP_SEND;
+          }
+          break;
+        case 101:
+          /* Switching Protocols */
+          if(k->upgr101 == UPGR101_REQUESTED) {
+            infof(data, "Received 101\n");
+            k->upgr101 = UPGR101_RECEIVED;
+
+            /* switch to http2 now */
+            Curl_http2_switched(conn);
+          }
+          break;
+        default:
+          break;
         }
       }
       else {
index b876436e1a51468e84d464dcc9a268dc259d50c0..f15cb1700bc33f3c5e63e198f3dd232370393743 100644 (file)
 /* include memdebug.h last */
 #include "memdebug.h"
 
+/*
+ * HTTP2 handler interface. This isn't added to the general list of protocols
+ * but will be used at run-time when the protocol is dynamically switched from
+ * HTTP to HTTP2.
+ */
+const struct Curl_handler Curl_handler_http2 = {
+  "HTTP2",                              /* scheme */
+  ZERO_NULL,                            /* setup_connection */
+  ZERO_NULL,                            /* do_it */
+  ZERO_NULL     ,                       /* done */
+  ZERO_NULL,                            /* do_more */
+  ZERO_NULL,                            /* connect_it */
+  ZERO_NULL,                            /* connecting */
+  ZERO_NULL,                            /* doing */
+  ZERO_NULL,                            /* proto_getsock */
+  ZERO_NULL,                            /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  ZERO_NULL,                            /* perform_getsock */
+  ZERO_NULL,                            /* disconnect */
+  ZERO_NULL,                            /* readwrite */
+  PORT_HTTP,                            /* defport */
+  0,                                    /* protocol */
+  PROTOPT_NONE                          /* flags */
+};
+
+
 /*
  * Store nghttp2 version info in this buffer, Prefix with a space.  Return
  * total length written.
@@ -138,6 +164,7 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
   ssize_t binlen;
   char *base64;
   size_t blen;
+  struct SingleRequest *k = &conn->data->req;
 
   if(!conn->proto.httpc.h2) {
     /* The nghttp2 session is not yet setup, do it */
@@ -176,7 +203,16 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
                             NGHTTP2_PROTO_VERSION_ID, base64);
   free(base64);
 
+  k->upgr101 = UPGR101_REQUESTED;
+
   return result;
 }
 
+void Curl_http2_switched(struct connectdata *conn)
+{
+  /* we are switched! */
+  conn->handler = &Curl_handler_http2;
+  infof(conn->data, "We have switched to HTTP2\n");
+}
+
 #endif
index 09b91d11229b93ebc8b1a89ddc6d04ba1ab18d32..ffe16820e6eb06cc05ce9f592ae70cb7fce80210 100644 (file)
@@ -34,8 +34,10 @@ int Curl_http2_ver(char *p, size_t len);
 
 CURLcode Curl_http2_request(Curl_send_buffer *req,
                             struct connectdata *conn);
+void Curl_http2_switched(struct connectdata *conn);
 #else /* USE_NGHTTP2 */
 #define Curl_http2_request(x,y) CURLE_OK
+#define Curl_http2_switched(x)
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */
index a00894e5c472dbd118d52e5572647fc4d5a28ee1..7cb6857075cca3adf43c50f8333df068ba1aaeaf 100644 (file)
@@ -580,7 +580,6 @@ struct Curl_async {
 typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
 typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
 
-
 enum expect100 {
   EXP100_SEND_DATA,           /* enough waiting, just send the body now */
   EXP100_AWAITING_CONTINUE,   /* waiting for the 100 Continue header */
@@ -589,6 +588,13 @@ enum expect100 {
   EXP100_FAILED               /* used on 417 Expectation Failed */
 };
 
+enum upgrade101 {
+  UPGR101_INIT,               /* default state */
+  UPGR101_REQUESTED,          /* upgrade requested */
+  UPGR101_RECEIVED,           /* response received */
+  UPGR101_WORKING             /* talking upgraded protocol */
+};
+
 /*
  * Request specific data in the easy handle (SessionHandle).  Previously,
  * these members were on the connectdata struct but since a conn struct may
@@ -639,6 +645,7 @@ struct SingleRequest {
                                    'RTSP/1.? XXX' line */
   struct timeval start100;      /* time stamp to wait for the 100 code from */
   enum expect100 exp100;        /* expect 100 continue state */
+  enum upgrade101 upgr101;      /* 101 upgrade state */
 
   int auto_decoding;            /* What content encoding. sec 3.5, RFC2616. */