Commit 8d3608f2 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

http2: handle 101 responses and switch to HTTP2

parent 8bcf677a
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -2872,11 +2872,28 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
        k->header = TRUE;
        k->headerline = 0; /* restart the header line counter */

        /* "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 {
        k->header = FALSE; /* no more header to parse! */
+36 −0
Original line number Diff line number Diff line
@@ -37,6 +37,32 @@
/* 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
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+8 −1
Original line number Diff line number Diff line
@@ -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. */