Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #ifdef USE_NGHTTP2
     26 #include <nghttp2/nghttp2.h>
     27 #include "urldata.h"
     28 #include "http2.h"
     29 #include "http.h"
     30 #include "sendf.h"
     31 #include "select.h"
     32 #include "curl_base64.h"
     33 #include "strcase.h"
     34 #include "multiif.h"
     35 #include "url.h"
     36 #include "connect.h"
     37 #include "strtoofft.h"
     38 #include "strdup.h"
     39 /* The last 3 #include files should be in this order */
     40 #include "curl_printf.h"
     41 #include "curl_memory.h"
     42 #include "memdebug.h"
     43 
     44 #define H2_BUFSIZE 32768
     45 
     46 #if (NGHTTP2_VERSION_NUM < 0x010000)
     47 #error too old nghttp2 version, upgrade!
     48 #endif
     49 
     50 #if (NGHTTP2_VERSION_NUM > 0x010800)
     51 #define NGHTTP2_HAS_HTTP2_STRERROR 1
     52 #endif
     53 
     54 #if (NGHTTP2_VERSION_NUM >= 0x010900)
     55 /* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or
     56    later */
     57 #define NGHTTP2_HAS_ERROR_CALLBACK 1
     58 #else
     59 #define nghttp2_session_callbacks_set_error_callback(x,y)
     60 #endif
     61 
     62 #if (NGHTTP2_VERSION_NUM >= 0x010c00)
     63 #define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
     64 #endif
     65 
     66 #define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
     67 
     68 #ifdef DEBUG_HTTP2
     69 #define H2BUGF(x) x
     70 #else
     71 #define H2BUGF(x) do { } WHILE_FALSE
     72 #endif
     73 
     74 
     75 static ssize_t http2_recv(struct connectdata *conn, int sockindex,
     76                           char *mem, size_t len, CURLcode *err);
     77 static bool http2_connisdead(struct connectdata *conn);
     78 static int h2_session_send(struct Curl_easy *data,
     79                            nghttp2_session *h2);
     80 static int h2_process_pending_input(struct connectdata *conn,
     81                                     struct http_conn *httpc,
     82                                     CURLcode *err);
     83 
     84 /*
     85  * Curl_http2_init_state() is called when the easy handle is created and
     86  * allows for HTTP/2 specific init of state.
     87  */
     88 void Curl_http2_init_state(struct UrlState *state)
     89 {
     90   state->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
     91 }
     92 
     93 /*
     94  * Curl_http2_init_userset() is called when the easy handle is created and
     95  * allows for HTTP/2 specific user-set fields.
     96  */
     97 void Curl_http2_init_userset(struct UserDefined *set)
     98 {
     99   set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
    100 }
    101 
    102 static int http2_perform_getsock(const struct connectdata *conn,
    103                                  curl_socket_t *sock, /* points to
    104                                                          numsocks
    105                                                          number of
    106                                                          sockets */
    107                                  int numsocks)
    108 {
    109   const struct http_conn *c = &conn->proto.httpc;
    110   struct SingleRequest *k = &conn->data->req;
    111   int bitmap = GETSOCK_BLANK;
    112   (void)numsocks;
    113 
    114   /* TODO We should check underlying socket state if it is SSL socket
    115      because of renegotiation. */
    116   sock[0] = conn->sock[FIRSTSOCKET];
    117 
    118   /* in a HTTP/2 connection we can basically always get a frame so we should
    119      always be ready for one */
    120   bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
    121 
    122   /* we're still uploading or the HTTP/2 layer wants to send data */
    123   if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
    124      nghttp2_session_want_write(c->h2))
    125     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
    126 
    127   return bitmap;
    128 }
    129 
    130 static int http2_getsock(struct connectdata *conn,
    131                          curl_socket_t *sock, /* points to numsocks
    132                                                  number of sockets */
    133                          int numsocks)
    134 {
    135   return http2_perform_getsock(conn, sock, numsocks);
    136 }
    137 
    138 /*
    139  * http2_stream_free() free HTTP2 stream related data
    140  */
    141 static void http2_stream_free(struct HTTP *http)
    142 {
    143   if(http) {
    144     Curl_add_buffer_free(&http->header_recvbuf);
    145     Curl_add_buffer_free(&http->trailer_recvbuf);
    146     for(; http->push_headers_used > 0; --http->push_headers_used) {
    147       free(http->push_headers[http->push_headers_used - 1]);
    148     }
    149     free(http->push_headers);
    150     http->push_headers = NULL;
    151   }
    152 }
    153 
    154 /*
    155  * Disconnects *a* connection used for HTTP/2. It might be an old one from the
    156  * connection cache and not the "main" one. Don't touch the easy handle!
    157  */
    158 
    159 static CURLcode http2_disconnect(struct connectdata *conn,
    160                                  bool dead_connection)
    161 {
    162   struct http_conn *c = &conn->proto.httpc;
    163   (void)dead_connection;
    164 
    165   H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
    166 
    167   nghttp2_session_del(c->h2);
    168   Curl_safefree(c->inbuf);
    169 
    170   H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
    171 
    172   return CURLE_OK;
    173 }
    174 
    175 /*
    176  * The server may send us data at any point (e.g. PING frames). Therefore,
    177  * we cannot assume that an HTTP/2 socket is dead just because it is readable.
    178  *
    179  * Instead, if it is readable, run Curl_connalive() to peek at the socket
    180  * and distinguish between closed and data.
    181  */
    182 static bool http2_connisdead(struct connectdata *conn)
    183 {
    184   int sval;
    185   bool dead = TRUE;
    186 
    187   if(conn->bits.close)
    188     return TRUE;
    189 
    190   sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
    191   if(sval == 0) {
    192     /* timeout */
    193     dead = FALSE;
    194   }
    195   else if(sval & CURL_CSELECT_ERR) {
    196     /* socket is in an error state */
    197     dead = TRUE;
    198   }
    199   else if(sval & CURL_CSELECT_IN) {
    200     /* readable with no error. could still be closed */
    201     dead = !Curl_connalive(conn);
    202     if(!dead) {
    203       /* This happens before we've sent off a request and the connection is
    204          not in use by any other transfer, there shouldn't be any data here,
    205          only "protocol frames" */
    206       CURLcode result;
    207       struct http_conn *httpc = &conn->proto.httpc;
    208       ssize_t nread = -1;
    209       if(httpc->recv_underlying)
    210         /* if called "too early", this pointer isn't setup yet! */
    211         nread = ((Curl_recv *)httpc->recv_underlying)(
    212           conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
    213       if(nread != -1) {
    214         infof(conn->data,
    215               "%d bytes stray data read before trying h2 connection\n",
    216               (int)nread);
    217         httpc->nread_inbuf = 0;
    218         httpc->inbuflen = nread;
    219         (void)h2_process_pending_input(conn, httpc, &result);
    220       }
    221       else
    222         /* the read failed so let's say this is dead anyway */
    223         dead = TRUE;
    224     }
    225   }
    226 
    227   return dead;
    228 }
    229 
    230 static unsigned int http2_conncheck(struct connectdata *check,
    231                                     unsigned int checks_to_perform)
    232 {
    233   unsigned int ret_val = CONNRESULT_NONE;
    234   struct http_conn *c = &check->proto.httpc;
    235   int rc;
    236   bool send_frames = false;
    237 
    238   if(checks_to_perform & CONNCHECK_ISDEAD) {
    239     if(http2_connisdead(check))
    240       ret_val |= CONNRESULT_DEAD;
    241   }
    242 
    243   if(checks_to_perform & CONNCHECK_KEEPALIVE) {
    244     struct curltime now = Curl_now();
    245     time_t elapsed = Curl_timediff(now, check->keepalive);
    246 
    247     if(elapsed > check->upkeep_interval_ms) {
    248       /* Perform an HTTP/2 PING */
    249       rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
    250       if(!rc) {
    251         /* Successfully added a PING frame to the session. Need to flag this
    252            so the frame is sent. */
    253         send_frames = true;
    254       }
    255       else {
    256        failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
    257              nghttp2_strerror(rc), rc);
    258       }
    259 
    260       check->keepalive = now;
    261     }
    262   }
    263 
    264   if(send_frames) {
    265     rc = nghttp2_session_send(c->h2);
    266     if(rc)
    267       failf(check->data, "nghttp2_session_send() failed: %s(%d)",
    268             nghttp2_strerror(rc), rc);
    269   }
    270 
    271   return ret_val;
    272 }
    273 
    274 /* called from Curl_http_setup_conn */
    275 void Curl_http2_setup_req(struct Curl_easy *data)
    276 {
    277   struct HTTP *http = data->req.protop;
    278 
    279   http->nread_header_recvbuf = 0;
    280   http->bodystarted = FALSE;
    281   http->status_code = -1;
    282   http->pausedata = NULL;
    283   http->pauselen = 0;
    284   http->closed = FALSE;
    285   http->close_handled = FALSE;
    286   http->mem = data->state.buffer;
    287   http->len = data->set.buffer_size;
    288   http->memlen = 0;
    289 }
    290 
    291 /* called from Curl_http_setup_conn */
    292 void Curl_http2_setup_conn(struct connectdata *conn)
    293 {
    294   conn->proto.httpc.settings.max_concurrent_streams =
    295     DEFAULT_MAX_CONCURRENT_STREAMS;
    296   conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
    297 }
    298 
    299 /*
    300  * HTTP2 handler interface. This isn't added to the general list of protocols
    301  * but will be used at run-time when the protocol is dynamically switched from
    302  * HTTP to HTTP2.
    303  */
    304 static const struct Curl_handler Curl_handler_http2 = {
    305   "HTTP",                               /* scheme */
    306   ZERO_NULL,                            /* setup_connection */
    307   Curl_http,                            /* do_it */
    308   Curl_http_done,                       /* done */
    309   ZERO_NULL,                            /* do_more */
    310   ZERO_NULL,                            /* connect_it */
    311   ZERO_NULL,                            /* connecting */
    312   ZERO_NULL,                            /* doing */
    313   http2_getsock,                        /* proto_getsock */
    314   http2_getsock,                        /* doing_getsock */
    315   ZERO_NULL,                            /* domore_getsock */
    316   http2_perform_getsock,                /* perform_getsock */
    317   http2_disconnect,                     /* disconnect */
    318   ZERO_NULL,                            /* readwrite */
    319   http2_conncheck,                      /* connection_check */
    320   PORT_HTTP,                            /* defport */
    321   CURLPROTO_HTTP,                       /* protocol */
    322   PROTOPT_STREAM                        /* flags */
    323 };
    324 
    325 static const struct Curl_handler Curl_handler_http2_ssl = {
    326   "HTTPS",                              /* scheme */
    327   ZERO_NULL,                            /* setup_connection */
    328   Curl_http,                            /* do_it */
    329   Curl_http_done,                       /* done */
    330   ZERO_NULL,                            /* do_more */
    331   ZERO_NULL,                            /* connect_it */
    332   ZERO_NULL,                            /* connecting */
    333   ZERO_NULL,                            /* doing */
    334   http2_getsock,                        /* proto_getsock */
    335   http2_getsock,                        /* doing_getsock */
    336   ZERO_NULL,                            /* domore_getsock */
    337   http2_perform_getsock,                /* perform_getsock */
    338   http2_disconnect,                     /* disconnect */
    339   ZERO_NULL,                            /* readwrite */
    340   http2_conncheck,                      /* connection_check */
    341   PORT_HTTP,                            /* defport */
    342   CURLPROTO_HTTPS,                      /* protocol */
    343   PROTOPT_SSL | PROTOPT_STREAM          /* flags */
    344 };
    345 
    346 /*
    347  * Store nghttp2 version info in this buffer, Prefix with a space.  Return
    348  * total length written.
    349  */
    350 int Curl_http2_ver(char *p, size_t len)
    351 {
    352   nghttp2_info *h2 = nghttp2_version(0);
    353   return msnprintf(p, len, " nghttp2/%s", h2->version_str);
    354 }
    355 
    356 /* HTTP/2 error code to name based on the Error Code Registry.
    357 https://tools.ietf.org/html/rfc7540#page-77
    358 nghttp2_error_code enums are identical.
    359 */
    360 static const char *http2_strerror(uint32_t err)
    361 {
    362 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
    363   const char *str[] = {
    364     "NO_ERROR",             /* 0x0 */
    365     "PROTOCOL_ERROR",       /* 0x1 */
    366     "INTERNAL_ERROR",       /* 0x2 */
    367     "FLOW_CONTROL_ERROR",   /* 0x3 */
    368     "SETTINGS_TIMEOUT",     /* 0x4 */
    369     "STREAM_CLOSED",        /* 0x5 */
    370     "FRAME_SIZE_ERROR",     /* 0x6 */
    371     "REFUSED_STREAM",       /* 0x7 */
    372     "CANCEL",               /* 0x8 */
    373     "COMPRESSION_ERROR",    /* 0x9 */
    374     "CONNECT_ERROR",        /* 0xA */
    375     "ENHANCE_YOUR_CALM",    /* 0xB */
    376     "INADEQUATE_SECURITY",  /* 0xC */
    377     "HTTP_1_1_REQUIRED"     /* 0xD */
    378   };
    379   return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
    380 #else
    381   return nghttp2_http2_strerror(err);
    382 #endif
    383 }
    384 
    385 /*
    386  * The implementation of nghttp2_send_callback type. Here we write |data| with
    387  * size |length| to the network and return the number of bytes actually
    388  * written. See the documentation of nghttp2_send_callback for the details.
    389  */
    390 static ssize_t send_callback(nghttp2_session *h2,
    391                              const uint8_t *data, size_t length, int flags,
    392                              void *userp)
    393 {
    394   struct connectdata *conn = (struct connectdata *)userp;
    395   struct http_conn *c = &conn->proto.httpc;
    396   ssize_t written;
    397   CURLcode result = CURLE_OK;
    398 
    399   (void)h2;
    400   (void)flags;
    401 
    402   if(!c->send_underlying)
    403     /* called before setup properly! */
    404     return NGHTTP2_ERR_CALLBACK_FAILURE;
    405 
    406   written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
    407                                              data, length, &result);
    408 
    409   if(result == CURLE_AGAIN) {
    410     return NGHTTP2_ERR_WOULDBLOCK;
    411   }
    412 
    413   if(written == -1) {
    414     failf(conn->data, "Failed sending HTTP2 data");
    415     return NGHTTP2_ERR_CALLBACK_FAILURE;
    416   }
    417 
    418   if(!written)
    419     return NGHTTP2_ERR_WOULDBLOCK;
    420 
    421   return written;
    422 }
    423 
    424 
    425 /* We pass a pointer to this struct in the push callback, but the contents of
    426    the struct are hidden from the user. */
    427 struct curl_pushheaders {
    428   struct Curl_easy *data;
    429   const nghttp2_push_promise *frame;
    430 };
    431 
    432 /*
    433  * push header access function. Only to be used from within the push callback
    434  */
    435 char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
    436 {
    437   /* Verify that we got a good easy handle in the push header struct, mostly to
    438      detect rubbish input fast(er). */
    439   if(!h || !GOOD_EASY_HANDLE(h->data))
    440     return NULL;
    441   else {
    442     struct HTTP *stream = h->data->req.protop;
    443     if(num < stream->push_headers_used)
    444       return stream->push_headers[num];
    445   }
    446   return NULL;
    447 }
    448 
    449 /*
    450  * push header access function. Only to be used from within the push callback
    451  */
    452 char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
    453 {
    454   /* Verify that we got a good easy handle in the push header struct,
    455      mostly to detect rubbish input fast(er). Also empty header name
    456      is just a rubbish too. We have to allow ":" at the beginning of
    457      the header, but header == ":" must be rejected. If we have ':' in
    458      the middle of header, it could be matched in middle of the value,
    459      this is because we do prefix match.*/
    460   if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] ||
    461      !strcmp(header, ":") || strchr(header + 1, ':'))
    462     return NULL;
    463   else {
    464     struct HTTP *stream = h->data->req.protop;
    465     size_t len = strlen(header);
    466     size_t i;
    467     for(i = 0; i<stream->push_headers_used; i++) {
    468       if(!strncmp(header, stream->push_headers[i], len)) {
    469         /* sub-match, make sure that it is followed by a colon */
    470         if(stream->push_headers[i][len] != ':')
    471           continue;
    472         return &stream->push_headers[i][len + 1];
    473       }
    474     }
    475   }
    476   return NULL;
    477 }
    478 
    479 /*
    480  * This specific transfer on this connection has been "drained".
    481  */
    482 static void drained_transfer(struct Curl_easy *data,
    483                              struct http_conn *httpc)
    484 {
    485   DEBUGASSERT(httpc->drain_total >= data->state.drain);
    486   httpc->drain_total -= data->state.drain;
    487   data->state.drain = 0;
    488 }
    489 
    490 /*
    491  * Mark this transfer to get "drained".
    492  */
    493 static void drain_this(struct Curl_easy *data,
    494                        struct http_conn *httpc)
    495 {
    496   data->state.drain++;
    497   httpc->drain_total++;
    498   DEBUGASSERT(httpc->drain_total >= data->state.drain);
    499 }
    500 
    501 static struct Curl_easy *duphandle(struct Curl_easy *data)
    502 {
    503   struct Curl_easy *second = curl_easy_duphandle(data);
    504   if(second) {
    505     /* setup the request struct */
    506     struct HTTP *http = calloc(1, sizeof(struct HTTP));
    507     if(!http) {
    508       (void)Curl_close(second);
    509       second = NULL;
    510     }
    511     else {
    512       second->req.protop = http;
    513       http->header_recvbuf = Curl_add_buffer_init();
    514       if(!http->header_recvbuf) {
    515         free(http);
    516         (void)Curl_close(second);
    517         second = NULL;
    518       }
    519       else {
    520         Curl_http2_setup_req(second);
    521         second->state.stream_weight = data->state.stream_weight;
    522       }
    523     }
    524   }
    525   return second;
    526 }
    527 
    528 
    529 static int push_promise(struct Curl_easy *data,
    530                         struct connectdata *conn,
    531                         const nghttp2_push_promise *frame)
    532 {
    533   int rv;
    534   H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
    535                frame->promised_stream_id));
    536   if(data->multi->push_cb) {
    537     struct HTTP *stream;
    538     struct HTTP *newstream;
    539     struct curl_pushheaders heads;
    540     CURLMcode rc;
    541     struct http_conn *httpc;
    542     size_t i;
    543     /* clone the parent */
    544     struct Curl_easy *newhandle = duphandle(data);
    545     if(!newhandle) {
    546       infof(data, "failed to duplicate handle\n");
    547       rv = 1; /* FAIL HARD */
    548       goto fail;
    549     }
    550 
    551     heads.data = data;
    552     heads.frame = frame;
    553     /* ask the application */
    554     H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
    555 
    556     stream = data->req.protop;
    557     if(!stream) {
    558       failf(data, "Internal NULL stream!\n");
    559       (void)Curl_close(newhandle);
    560       rv = 1;
    561       goto fail;
    562     }
    563 
    564     Curl_set_in_callback(data, true);
    565     rv = data->multi->push_cb(data, newhandle,
    566                               stream->push_headers_used, &heads,
    567                               data->multi->push_userp);
    568     Curl_set_in_callback(data, false);
    569 
    570     /* free the headers again */
    571     for(i = 0; i<stream->push_headers_used; i++)
    572       free(stream->push_headers[i]);
    573     free(stream->push_headers);
    574     stream->push_headers = NULL;
    575     stream->push_headers_used = 0;
    576 
    577     if(rv) {
    578       /* denied, kill off the new handle again */
    579       http2_stream_free(newhandle->req.protop);
    580       newhandle->req.protop = NULL;
    581       (void)Curl_close(newhandle);
    582       goto fail;
    583     }
    584 
    585     newstream = newhandle->req.protop;
    586     newstream->stream_id = frame->promised_stream_id;
    587     newhandle->req.maxdownload = -1;
    588     newhandle->req.size = -1;
    589 
    590     /* approved, add to the multi handle and immediately switch to PERFORM
    591        state with the given connection !*/
    592     rc = Curl_multi_add_perform(data->multi, newhandle, conn);
    593     if(rc) {
    594       infof(data, "failed to add handle to multi\n");
    595       http2_stream_free(newhandle->req.protop);
    596       newhandle->req.protop = NULL;
    597       Curl_close(newhandle);
    598       rv = 1;
    599       goto fail;
    600     }
    601 
    602     httpc = &conn->proto.httpc;
    603     rv = nghttp2_session_set_stream_user_data(httpc->h2,
    604                                               frame->promised_stream_id,
    605                                               newhandle);
    606     if(rv) {
    607       infof(data, "failed to set user_data for stream %d\n",
    608             frame->promised_stream_id);
    609       DEBUGASSERT(0);
    610       goto fail;
    611     }
    612   }
    613   else {
    614     H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
    615     rv = 1;
    616   }
    617   fail:
    618   return rv;
    619 }
    620 
    621 /*
    622  * multi_connchanged() is called to tell that there is a connection in
    623  * this multi handle that has changed state (pipelining become possible, the
    624  * number of allowed streams changed or similar), and a subsequent use of this
    625  * multi handle should move CONNECT_PEND handles back to CONNECT to have them
    626  * retry.
    627  */
    628 static void multi_connchanged(struct Curl_multi *multi)
    629 {
    630   multi->recheckstate = TRUE;
    631 }
    632 
    633 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
    634                          void *userp)
    635 {
    636   struct connectdata *conn = (struct connectdata *)userp;
    637   struct http_conn *httpc = &conn->proto.httpc;
    638   struct Curl_easy *data_s = NULL;
    639   struct HTTP *stream = NULL;
    640   int rv;
    641   size_t left, ncopy;
    642   int32_t stream_id = frame->hd.stream_id;
    643   CURLcode result;
    644 
    645   if(!stream_id) {
    646     /* stream ID zero is for connection-oriented stuff */
    647     if(frame->hd.type == NGHTTP2_SETTINGS) {
    648       uint32_t max_conn = httpc->settings.max_concurrent_streams;
    649       H2BUGF(infof(conn->data, "Got SETTINGS\n"));
    650       httpc->settings.max_concurrent_streams =
    651         nghttp2_session_get_remote_settings(
    652           session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    653       httpc->settings.enable_push =
    654         nghttp2_session_get_remote_settings(
    655           session, NGHTTP2_SETTINGS_ENABLE_PUSH);
    656       H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
    657                    httpc->settings.max_concurrent_streams));
    658       H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
    659                    httpc->settings.enable_push?"TRUE":"false"));
    660       if(max_conn != httpc->settings.max_concurrent_streams) {
    661         /* only signal change if the value actually changed */
    662         infof(conn->data,
    663               "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
    664               httpc->settings.max_concurrent_streams);
    665         multi_connchanged(conn->data->multi);
    666       }
    667     }
    668     return 0;
    669   }
    670   data_s = nghttp2_session_get_stream_user_data(session, stream_id);
    671   if(!data_s) {
    672     H2BUGF(infof(conn->data,
    673                  "No Curl_easy associated with stream: %x\n",
    674                  stream_id));
    675     return 0;
    676   }
    677 
    678   stream = data_s->req.protop;
    679   if(!stream) {
    680     H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
    681                  stream_id));
    682     return NGHTTP2_ERR_CALLBACK_FAILURE;
    683   }
    684 
    685   H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
    686                frame->hd.type, stream_id));
    687 
    688   switch(frame->hd.type) {
    689   case NGHTTP2_DATA:
    690     /* If body started on this stream, then receiving DATA is illegal. */
    691     if(!stream->bodystarted) {
    692       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
    693                                      stream_id, NGHTTP2_PROTOCOL_ERROR);
    694 
    695       if(nghttp2_is_fatal(rv)) {
    696         return NGHTTP2_ERR_CALLBACK_FAILURE;
    697       }
    698     }
    699     break;
    700   case NGHTTP2_HEADERS:
    701     if(stream->bodystarted) {
    702       /* Only valid HEADERS after body started is trailer HEADERS.  We
    703          buffer them in on_header callback. */
    704       break;
    705     }
    706 
    707     /* nghttp2 guarantees that :status is received, and we store it to
    708        stream->status_code. Fuzzing has proven this can still be reached
    709        without status code having been set. */
    710     if(stream->status_code == -1)
    711       return NGHTTP2_ERR_CALLBACK_FAILURE;
    712 
    713     /* Only final status code signals the end of header */
    714     if(stream->status_code / 100 != 1) {
    715       stream->bodystarted = TRUE;
    716       stream->status_code = -1;
    717     }
    718 
    719     result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
    720     if(result)
    721       return NGHTTP2_ERR_CALLBACK_FAILURE;
    722 
    723     left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
    724     ncopy = CURLMIN(stream->len, left);
    725 
    726     memcpy(&stream->mem[stream->memlen],
    727            stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
    728            ncopy);
    729     stream->nread_header_recvbuf += ncopy;
    730 
    731     H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
    732                  ncopy, stream_id, stream->mem));
    733 
    734     stream->len -= ncopy;
    735     stream->memlen += ncopy;
    736 
    737     drain_this(data_s, httpc);
    738     {
    739       /* get the pointer from userp again since it was re-assigned above */
    740       struct connectdata *conn_s = (struct connectdata *)userp;
    741 
    742       /* if we receive data for another handle, wake that up */
    743       if(conn_s->data != data_s)
    744         Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
    745     }
    746     break;
    747   case NGHTTP2_PUSH_PROMISE:
    748     rv = push_promise(data_s, conn, &frame->push_promise);
    749     if(rv) { /* deny! */
    750       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
    751                                      frame->push_promise.promised_stream_id,
    752                                      NGHTTP2_CANCEL);
    753       if(nghttp2_is_fatal(rv)) {
    754         return rv;
    755       }
    756     }
    757     break;
    758   default:
    759     H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n",
    760                  frame->hd.type, stream_id));
    761     break;
    762   }
    763   return 0;
    764 }
    765 
    766 static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
    767                               int32_t stream_id,
    768                               const uint8_t *data, size_t len, void *userp)
    769 {
    770   struct HTTP *stream;
    771   struct Curl_easy *data_s;
    772   size_t nread;
    773   struct connectdata *conn = (struct connectdata *)userp;
    774   (void)session;
    775   (void)flags;
    776   (void)data;
    777 
    778   DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
    779 
    780   /* get the stream from the hash based on Stream ID */
    781   data_s = nghttp2_session_get_stream_user_data(session, stream_id);
    782   if(!data_s)
    783     /* Receiving a Stream ID not in the hash should not happen, this is an
    784        internal error more than anything else! */
    785     return NGHTTP2_ERR_CALLBACK_FAILURE;
    786 
    787   stream = data_s->req.protop;
    788   if(!stream)
    789     return NGHTTP2_ERR_CALLBACK_FAILURE;
    790 
    791   nread = CURLMIN(stream->len, len);
    792   memcpy(&stream->mem[stream->memlen], data, nread);
    793 
    794   stream->len -= nread;
    795   stream->memlen += nread;
    796 
    797   drain_this(data_s, &conn->proto.httpc);
    798 
    799   /* if we receive data for another handle, wake that up */
    800   if(conn->data != data_s)
    801     Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
    802 
    803   H2BUGF(infof(data_s, "%zu data received for stream %u "
    804                "(%zu left in buffer %p, total %zu)\n",
    805                nread, stream_id,
    806                stream->len, stream->mem,
    807                stream->memlen));
    808 
    809   if(nread < len) {
    810     stream->pausedata = data + nread;
    811     stream->pauselen = len - nread;
    812     H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
    813                  ", stream %u\n",
    814                  len - nread, stream_id));
    815     data_s->conn->proto.httpc.pause_stream_id = stream_id;
    816 
    817     return NGHTTP2_ERR_PAUSE;
    818   }
    819 
    820   /* pause execution of nghttp2 if we received data for another handle
    821      in order to process them first. */
    822   if(conn->data != data_s) {
    823     data_s->conn->proto.httpc.pause_stream_id = stream_id;
    824 
    825     return NGHTTP2_ERR_PAUSE;
    826   }
    827 
    828   return 0;
    829 }
    830 
    831 static int on_stream_close(nghttp2_session *session, int32_t stream_id,
    832                            uint32_t error_code, void *userp)
    833 {
    834   struct Curl_easy *data_s;
    835   struct HTTP *stream;
    836   struct connectdata *conn = (struct connectdata *)userp;
    837   int rv;
    838   (void)session;
    839   (void)stream_id;
    840 
    841   if(stream_id) {
    842     struct http_conn *httpc;
    843     /* get the stream from the hash based on Stream ID, stream ID zero is for
    844        connection-oriented stuff */
    845     data_s = nghttp2_session_get_stream_user_data(session, stream_id);
    846     if(!data_s) {
    847       /* We could get stream ID not in the hash.  For example, if we
    848          decided to reject stream (e.g., PUSH_PROMISE). */
    849       return 0;
    850     }
    851     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
    852                  http2_strerror(error_code), error_code, stream_id));
    853     stream = data_s->req.protop;
    854     if(!stream)
    855       return NGHTTP2_ERR_CALLBACK_FAILURE;
    856 
    857     stream->closed = TRUE;
    858     httpc = &conn->proto.httpc;
    859     drain_this(data_s, httpc);
    860     httpc->error_code = error_code;
    861 
    862     /* remove the entry from the hash as the stream is now gone */
    863     rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
    864     if(rv) {
    865       infof(data_s, "http/2: failed to clear user_data for stream %d!\n",
    866             stream_id);
    867       DEBUGASSERT(0);
    868     }
    869     if(stream_id == httpc->pause_stream_id) {
    870       H2BUGF(infof(data_s, "Stopped the pause stream!\n"));
    871       httpc->pause_stream_id = 0;
    872     }
    873     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
    874     stream->stream_id = 0; /* cleared */
    875   }
    876   return 0;
    877 }
    878 
    879 static int on_begin_headers(nghttp2_session *session,
    880                             const nghttp2_frame *frame, void *userp)
    881 {
    882   struct HTTP *stream;
    883   struct Curl_easy *data_s = NULL;
    884   (void)userp;
    885 
    886   data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
    887   if(!data_s) {
    888     return 0;
    889   }
    890 
    891   H2BUGF(infof(data_s, "on_begin_headers() was called\n"));
    892 
    893   if(frame->hd.type != NGHTTP2_HEADERS) {
    894     return 0;
    895   }
    896 
    897   stream = data_s->req.protop;
    898   if(!stream || !stream->bodystarted) {
    899     return 0;
    900   }
    901 
    902   if(!stream->trailer_recvbuf) {
    903     stream->trailer_recvbuf = Curl_add_buffer_init();
    904     if(!stream->trailer_recvbuf) {
    905       return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
    906     }
    907   }
    908   return 0;
    909 }
    910 
    911 /* Decode HTTP status code.  Returns -1 if no valid status code was
    912    decoded. */
    913 static int decode_status_code(const uint8_t *value, size_t len)
    914 {
    915   int i;
    916   int res;
    917 
    918   if(len != 3) {
    919     return -1;
    920   }
    921 
    922   res = 0;
    923 
    924   for(i = 0; i < 3; ++i) {
    925     char c = value[i];
    926 
    927     if(c < '0' || c > '9') {
    928       return -1;
    929     }
    930 
    931     res *= 10;
    932     res += c - '0';
    933   }
    934 
    935   return res;
    936 }
    937 
    938 /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
    939 static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
    940                      const uint8_t *name, size_t namelen,
    941                      const uint8_t *value, size_t valuelen,
    942                      uint8_t flags,
    943                      void *userp)
    944 {
    945   struct HTTP *stream;
    946   struct Curl_easy *data_s;
    947   int32_t stream_id = frame->hd.stream_id;
    948   struct connectdata *conn = (struct connectdata *)userp;
    949   CURLcode result;
    950   (void)flags;
    951 
    952   DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
    953 
    954   /* get the stream from the hash based on Stream ID */
    955   data_s = nghttp2_session_get_stream_user_data(session, stream_id);
    956   if(!data_s)
    957     /* Receiving a Stream ID not in the hash should not happen, this is an
    958        internal error more than anything else! */
    959     return NGHTTP2_ERR_CALLBACK_FAILURE;
    960 
    961   stream = data_s->req.protop;
    962   if(!stream) {
    963     failf(data_s, "Internal NULL stream! 5\n");
    964     return NGHTTP2_ERR_CALLBACK_FAILURE;
    965   }
    966 
    967   /* Store received PUSH_PROMISE headers to be used when the subsequent
    968      PUSH_PROMISE callback comes */
    969   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
    970     char *h;
    971 
    972     if(!strcmp(":authority", (const char *)name)) {
    973       /* psuedo headers are lower case */
    974       int rc = 0;
    975       char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
    976       if(!check)
    977         /* no memory */
    978         return NGHTTP2_ERR_CALLBACK_FAILURE;
    979       if(!Curl_strcasecompare(check, (const char *)value)) {
    980         /* This is push is not for the same authority that was asked for in
    981          * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
    982          * PUSH_PROMISE for which the server is not authoritative as a stream
    983          * error of type PROTOCOL_ERROR."
    984          */
    985         (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
    986                                         stream_id, NGHTTP2_PROTOCOL_ERROR);
    987         rc = NGHTTP2_ERR_CALLBACK_FAILURE;
    988       }
    989       free(check);
    990       if(rc)
    991         return rc;
    992     }
    993 
    994     if(!stream->push_headers) {
    995       stream->push_headers_alloc = 10;
    996       stream->push_headers = malloc(stream->push_headers_alloc *
    997                                     sizeof(char *));
    998       if(!stream->push_headers)
    999         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
   1000       stream->push_headers_used = 0;
   1001     }
   1002     else if(stream->push_headers_used ==
   1003             stream->push_headers_alloc) {
   1004       char **headp;
   1005       stream->push_headers_alloc *= 2;
   1006       headp = Curl_saferealloc(stream->push_headers,
   1007                                stream->push_headers_alloc * sizeof(char *));
   1008       if(!headp) {
   1009         stream->push_headers = NULL;
   1010         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
   1011       }
   1012       stream->push_headers = headp;
   1013     }
   1014     h = aprintf("%s:%s", name, value);
   1015     if(h)
   1016       stream->push_headers[stream->push_headers_used++] = h;
   1017     return 0;
   1018   }
   1019 
   1020   if(stream->bodystarted) {
   1021     /* This is trailer fields. */
   1022     /* 4 is for ": " and "\r\n". */
   1023     uint32_t n = (uint32_t)(namelen + valuelen + 4);
   1024 
   1025     H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
   1026                  value));
   1027 
   1028     result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
   1029     if(result)
   1030       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1031     result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
   1032     if(result)
   1033       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1034     result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
   1035     if(result)
   1036       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1037     result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
   1038     if(result)
   1039       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1040     result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
   1041     if(result)
   1042       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1043 
   1044     return 0;
   1045   }
   1046 
   1047   if(namelen == sizeof(":status") - 1 &&
   1048      memcmp(":status", name, namelen) == 0) {
   1049     /* nghttp2 guarantees :status is received first and only once, and
   1050        value is 3 digits status code, and decode_status_code always
   1051        succeeds. */
   1052     stream->status_code = decode_status_code(value, valuelen);
   1053     DEBUGASSERT(stream->status_code != -1);
   1054 
   1055     result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
   1056     if(result)
   1057       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1058     result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
   1059     if(result)
   1060       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1061     /* the space character after the status code is mandatory */
   1062     result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
   1063     if(result)
   1064       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1065     /* if we receive data for another handle, wake that up */
   1066     if(conn->data != data_s)
   1067       Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
   1068 
   1069     H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
   1070                  stream->status_code, data_s));
   1071     return 0;
   1072   }
   1073 
   1074   /* nghttp2 guarantees that namelen > 0, and :status was already
   1075      received, and this is not pseudo-header field . */
   1076   /* convert to a HTTP1-style header */
   1077   result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
   1078   if(result)
   1079     return NGHTTP2_ERR_CALLBACK_FAILURE;
   1080   result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
   1081   if(result)
   1082     return NGHTTP2_ERR_CALLBACK_FAILURE;
   1083   result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
   1084   if(result)
   1085     return NGHTTP2_ERR_CALLBACK_FAILURE;
   1086   result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
   1087   if(result)
   1088     return NGHTTP2_ERR_CALLBACK_FAILURE;
   1089   /* if we receive data for another handle, wake that up */
   1090   if(conn->data != data_s)
   1091     Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
   1092 
   1093   H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
   1094                value));
   1095 
   1096   return 0; /* 0 is successful */
   1097 }
   1098 
   1099 static ssize_t data_source_read_callback(nghttp2_session *session,
   1100                                          int32_t stream_id,
   1101                                          uint8_t *buf, size_t length,
   1102                                          uint32_t *data_flags,
   1103                                          nghttp2_data_source *source,
   1104                                          void *userp)
   1105 {
   1106   struct Curl_easy *data_s;
   1107   struct HTTP *stream = NULL;
   1108   size_t nread;
   1109   (void)source;
   1110   (void)userp;
   1111 
   1112   if(stream_id) {
   1113     /* get the stream from the hash based on Stream ID, stream ID zero is for
   1114        connection-oriented stuff */
   1115     data_s = nghttp2_session_get_stream_user_data(session, stream_id);
   1116     if(!data_s)
   1117       /* Receiving a Stream ID not in the hash should not happen, this is an
   1118          internal error more than anything else! */
   1119       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1120 
   1121     stream = data_s->req.protop;
   1122     if(!stream)
   1123       return NGHTTP2_ERR_CALLBACK_FAILURE;
   1124   }
   1125   else
   1126     return NGHTTP2_ERR_INVALID_ARGUMENT;
   1127 
   1128   nread = CURLMIN(stream->upload_len, length);
   1129   if(nread > 0) {
   1130     memcpy(buf, stream->upload_mem, nread);
   1131     stream->upload_mem += nread;
   1132     stream->upload_len -= nread;
   1133     if(data_s->state.infilesize != -1)
   1134       stream->upload_left -= nread;
   1135   }
   1136 
   1137   if(stream->upload_left == 0)
   1138     *data_flags = NGHTTP2_DATA_FLAG_EOF;
   1139   else if(nread == 0)
   1140     return NGHTTP2_ERR_DEFERRED;
   1141 
   1142   H2BUGF(infof(data_s, "data_source_read_callback: "
   1143                "returns %zu bytes stream %u\n",
   1144                nread, stream_id));
   1145 
   1146   return nread;
   1147 }
   1148 
   1149 #if defined(NGHTTP2_HAS_ERROR_CALLBACK) &&      \
   1150   !defined(CURL_DISABLE_VERBOSE_STRINGS)
   1151 static int error_callback(nghttp2_session *session,
   1152                           const char *msg,
   1153                           size_t len,
   1154                           void *userp)
   1155 {
   1156   struct connectdata *conn = (struct connectdata *)userp;
   1157   (void)session;
   1158   infof(conn->data, "http2 error: %.*s\n", len, msg);
   1159   return 0;
   1160 }
   1161 #endif
   1162 
   1163 static void populate_settings(struct connectdata *conn,
   1164                               struct http_conn *httpc)
   1165 {
   1166   nghttp2_settings_entry *iv = httpc->local_settings;
   1167 
   1168   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
   1169   iv[0].value = 100;
   1170 
   1171   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
   1172   iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
   1173 
   1174   iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
   1175   iv[2].value = conn->data->multi->push_cb != NULL;
   1176 
   1177   httpc->local_settings_num = 3;
   1178 }
   1179 
   1180 void Curl_http2_done(struct connectdata *conn, bool premature)
   1181 {
   1182   struct Curl_easy *data = conn->data;
   1183   struct HTTP *http = data->req.protop;
   1184   struct http_conn *httpc = &conn->proto.httpc;
   1185 
   1186   /* there might be allocated resources done before this got the 'h2' pointer
   1187      setup */
   1188   if(http->header_recvbuf) {
   1189     Curl_add_buffer_free(&http->header_recvbuf);
   1190     Curl_add_buffer_free(&http->trailer_recvbuf);
   1191     if(http->push_headers) {
   1192       /* if they weren't used and then freed before */
   1193       for(; http->push_headers_used > 0; --http->push_headers_used) {
   1194         free(http->push_headers[http->push_headers_used - 1]);
   1195       }
   1196       free(http->push_headers);
   1197       http->push_headers = NULL;
   1198     }
   1199   }
   1200 
   1201   if(!httpc->h2) /* not HTTP/2 ? */
   1202     return;
   1203 
   1204   if(data->state.drain)
   1205     drained_transfer(data, httpc);
   1206 
   1207   if(premature) {
   1208     /* RST_STREAM */
   1209     if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
   1210                                   http->stream_id, NGHTTP2_STREAM_CLOSED))
   1211       (void)nghttp2_session_send(httpc->h2);
   1212 
   1213     if(http->stream_id == httpc->pause_stream_id) {
   1214       infof(data, "stopped the pause stream!\n");
   1215       httpc->pause_stream_id = 0;
   1216     }
   1217   }
   1218   /* -1 means unassigned and 0 means cleared */
   1219   if(http->stream_id > 0) {
   1220     int rv = nghttp2_session_set_stream_user_data(httpc->h2,
   1221                                                   http->stream_id, 0);
   1222     if(rv) {
   1223       infof(data, "http/2: failed to clear user_data for stream %d!\n",
   1224             http->stream_id);
   1225       DEBUGASSERT(0);
   1226     }
   1227     http->stream_id = 0;
   1228   }
   1229 }
   1230 
   1231 /*
   1232  * Initialize nghttp2 for a Curl connection
   1233  */
   1234 static CURLcode http2_init(struct connectdata *conn)
   1235 {
   1236   if(!conn->proto.httpc.h2) {
   1237     int rc;
   1238     nghttp2_session_callbacks *callbacks;
   1239 
   1240     conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
   1241     if(conn->proto.httpc.inbuf == NULL)
   1242       return CURLE_OUT_OF_MEMORY;
   1243 
   1244     rc = nghttp2_session_callbacks_new(&callbacks);
   1245 
   1246     if(rc) {
   1247       failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
   1248       return CURLE_OUT_OF_MEMORY; /* most likely at least */
   1249     }
   1250 
   1251     /* nghttp2_send_callback */
   1252     nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
   1253     /* nghttp2_on_frame_recv_callback */
   1254     nghttp2_session_callbacks_set_on_frame_recv_callback
   1255       (callbacks, on_frame_recv);
   1256     /* nghttp2_on_data_chunk_recv_callback */
   1257     nghttp2_session_callbacks_set_on_data_chunk_recv_callback
   1258       (callbacks, on_data_chunk_recv);
   1259     /* nghttp2_on_stream_close_callback */
   1260     nghttp2_session_callbacks_set_on_stream_close_callback
   1261       (callbacks, on_stream_close);
   1262     /* nghttp2_on_begin_headers_callback */
   1263     nghttp2_session_callbacks_set_on_begin_headers_callback
   1264       (callbacks, on_begin_headers);
   1265     /* nghttp2_on_header_callback */
   1266     nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
   1267 
   1268 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1269     nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
   1270 #endif
   1271 
   1272     /* The nghttp2 session is not yet setup, do it */
   1273     rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
   1274 
   1275     nghttp2_session_callbacks_del(callbacks);
   1276 
   1277     if(rc) {
   1278       failf(conn->data, "Couldn't initialize nghttp2!");
   1279       return CURLE_OUT_OF_MEMORY; /* most likely at least */
   1280     }
   1281   }
   1282   return CURLE_OK;
   1283 }
   1284 
   1285 /*
   1286  * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
   1287  */
   1288 CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
   1289                                     struct connectdata *conn)
   1290 {
   1291   CURLcode result;
   1292   ssize_t binlen;
   1293   char *base64;
   1294   size_t blen;
   1295   struct SingleRequest *k = &conn->data->req;
   1296   uint8_t *binsettings = conn->proto.httpc.binsettings;
   1297   struct http_conn *httpc = &conn->proto.httpc;
   1298 
   1299   populate_settings(conn, httpc);
   1300 
   1301   /* this returns number of bytes it wrote */
   1302   binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
   1303                                          httpc->local_settings,
   1304                                          httpc->local_settings_num);
   1305   if(!binlen) {
   1306     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
   1307     Curl_add_buffer_free(&req);
   1308     return CURLE_FAILED_INIT;
   1309   }
   1310   conn->proto.httpc.binlen = binlen;
   1311 
   1312   result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
   1313                                  &base64, &blen);
   1314   if(result) {
   1315     Curl_add_buffer_free(&req);
   1316     return result;
   1317   }
   1318 
   1319   result = Curl_add_bufferf(&req,
   1320                             "Connection: Upgrade, HTTP2-Settings\r\n"
   1321                             "Upgrade: %s\r\n"
   1322                             "HTTP2-Settings: %s\r\n",
   1323                             NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
   1324   free(base64);
   1325 
   1326   k->upgr101 = UPGR101_REQUESTED;
   1327 
   1328   return result;
   1329 }
   1330 
   1331 /*
   1332  * Returns nonzero if current HTTP/2 session should be closed.
   1333  */
   1334 static int should_close_session(struct http_conn *httpc)
   1335 {
   1336   return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) &&
   1337     !nghttp2_session_want_write(httpc->h2);
   1338 }
   1339 
   1340 /*
   1341  * h2_process_pending_input() processes pending input left in
   1342  * httpc->inbuf.  Then, call h2_session_send() to send pending data.
   1343  * This function returns 0 if it succeeds, or -1 and error code will
   1344  * be assigned to *err.
   1345  */
   1346 static int h2_process_pending_input(struct connectdata *conn,
   1347                                     struct http_conn *httpc,
   1348                                     CURLcode *err)
   1349 {
   1350   ssize_t nread;
   1351   char *inbuf;
   1352   ssize_t rv;
   1353   struct Curl_easy *data = conn->data;
   1354 
   1355   nread = httpc->inbuflen - httpc->nread_inbuf;
   1356   inbuf = httpc->inbuf + httpc->nread_inbuf;
   1357 
   1358   rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
   1359   if(rv < 0) {
   1360     failf(data,
   1361           "h2_process_pending_input: nghttp2_session_mem_recv() returned "
   1362           "%zd:%s\n", rv, nghttp2_strerror((int)rv));
   1363     *err = CURLE_RECV_ERROR;
   1364     return -1;
   1365   }
   1366 
   1367   if(nread == rv) {
   1368     H2BUGF(infof(data,
   1369                  "h2_process_pending_input: All data in connection buffer "
   1370                  "processed\n"));
   1371     httpc->inbuflen = 0;
   1372     httpc->nread_inbuf = 0;
   1373   }
   1374   else {
   1375     httpc->nread_inbuf += rv;
   1376     H2BUGF(infof(data,
   1377                  "h2_process_pending_input: %zu bytes left in connection "
   1378                  "buffer\n",
   1379                  httpc->inbuflen - httpc->nread_inbuf));
   1380   }
   1381 
   1382   rv = h2_session_send(data, httpc->h2);
   1383   if(rv != 0) {
   1384     *err = CURLE_SEND_ERROR;
   1385     return -1;
   1386   }
   1387 
   1388   if(should_close_session(httpc)) {
   1389     H2BUGF(infof(data,
   1390                  "h2_process_pending_input: nothing to do in this session\n"));
   1391     if(httpc->error_code)
   1392       *err = CURLE_HTTP2;
   1393     else {
   1394       /* not an error per se, but should still close the connection */
   1395       connclose(conn, "GOAWAY received");
   1396       *err = CURLE_OK;
   1397     }
   1398     return -1;
   1399   }
   1400 
   1401   return 0;
   1402 }
   1403 
   1404 /*
   1405  * Called from transfer.c:done_sending when we stop uploading.
   1406  */
   1407 CURLcode Curl_http2_done_sending(struct connectdata *conn)
   1408 {
   1409   CURLcode result = CURLE_OK;
   1410 
   1411   if((conn->handler == &Curl_handler_http2_ssl) ||
   1412      (conn->handler == &Curl_handler_http2)) {
   1413     /* make sure this is only attempted for HTTP/2 transfers */
   1414 
   1415     struct HTTP *stream = conn->data->req.protop;
   1416 
   1417     if(stream->upload_left) {
   1418       /* If the stream still thinks there's data left to upload. */
   1419       struct http_conn *httpc = &conn->proto.httpc;
   1420       nghttp2_session *h2 = httpc->h2;
   1421 
   1422       stream->upload_left = 0; /* DONE! */
   1423 
   1424       /* resume sending here to trigger the callback to get called again so
   1425          that it can signal EOF to nghttp2 */
   1426       (void)nghttp2_session_resume_data(h2, stream->stream_id);
   1427 
   1428       (void)h2_process_pending_input(conn, httpc, &result);
   1429     }
   1430   }
   1431   return result;
   1432 }
   1433 
   1434 static ssize_t http2_handle_stream_close(struct connectdata *conn,
   1435                                          struct Curl_easy *data,
   1436                                          struct HTTP *stream, CURLcode *err)
   1437 {
   1438   char *trailer_pos, *trailer_end;
   1439   CURLcode result;
   1440   struct http_conn *httpc = &conn->proto.httpc;
   1441 
   1442   if(httpc->pause_stream_id == stream->stream_id) {
   1443     httpc->pause_stream_id = 0;
   1444   }
   1445 
   1446   drained_transfer(data, httpc);
   1447 
   1448   if(httpc->pause_stream_id == 0) {
   1449     if(h2_process_pending_input(conn, httpc, err) != 0) {
   1450       return -1;
   1451     }
   1452   }
   1453 
   1454   DEBUGASSERT(data->state.drain == 0);
   1455 
   1456   /* Reset to FALSE to prevent infinite loop in readwrite_data function. */
   1457   stream->closed = FALSE;
   1458   if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
   1459     H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
   1460                  stream->stream_id));
   1461     connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
   1462     data->state.refused_stream = TRUE;
   1463     *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
   1464     return -1;
   1465   }
   1466   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
   1467     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
   1468           stream->stream_id, http2_strerror(httpc->error_code),
   1469           httpc->error_code);
   1470     *err = CURLE_HTTP2_STREAM;
   1471     return -1;
   1472   }
   1473 
   1474   if(!stream->bodystarted) {
   1475     failf(data, "HTTP/2 stream %d was closed cleanly, but before getting "
   1476           " all response header fields, treated as error",
   1477           stream->stream_id);
   1478     *err = CURLE_HTTP2_STREAM;
   1479     return -1;
   1480   }
   1481 
   1482   if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) {
   1483     trailer_pos = stream->trailer_recvbuf->buffer;
   1484     trailer_end = trailer_pos + stream->trailer_recvbuf->size_used;
   1485 
   1486     for(; trailer_pos < trailer_end;) {
   1487       uint32_t n;
   1488       memcpy(&n, trailer_pos, sizeof(n));
   1489       trailer_pos += sizeof(n);
   1490 
   1491       result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailer_pos, n);
   1492       if(result) {
   1493         *err = result;
   1494         return -1;
   1495       }
   1496 
   1497       trailer_pos += n + 1;
   1498     }
   1499   }
   1500 
   1501   stream->close_handled = TRUE;
   1502 
   1503   H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
   1504   return 0;
   1505 }
   1506 
   1507 /*
   1508  * h2_pri_spec() fills in the pri_spec struct, used by nghttp2 to send weight
   1509  * and dependency to the peer. It also stores the updated values in the state
   1510  * struct.
   1511  */
   1512 
   1513 static void h2_pri_spec(struct Curl_easy *data,
   1514                         nghttp2_priority_spec *pri_spec)
   1515 {
   1516   struct HTTP *depstream = (data->set.stream_depends_on?
   1517                             data->set.stream_depends_on->req.protop:NULL);
   1518   int32_t depstream_id = depstream? depstream->stream_id:0;
   1519   nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight,
   1520                              data->set.stream_depends_e);
   1521   data->state.stream_weight = data->set.stream_weight;
   1522   data->state.stream_depends_e = data->set.stream_depends_e;
   1523   data->state.stream_depends_on = data->set.stream_depends_on;
   1524 }
   1525 
   1526 /*
   1527  * h2_session_send() checks if there's been an update in the priority /
   1528  * dependency settings and if so it submits a PRIORITY frame with the updated
   1529  * info.
   1530  */
   1531 static int h2_session_send(struct Curl_easy *data,
   1532                            nghttp2_session *h2)
   1533 {
   1534   struct HTTP *stream = data->req.protop;
   1535   if((data->set.stream_weight != data->state.stream_weight) ||
   1536      (data->set.stream_depends_e != data->state.stream_depends_e) ||
   1537      (data->set.stream_depends_on != data->state.stream_depends_on) ) {
   1538     /* send new weight and/or dependency */
   1539     nghttp2_priority_spec pri_spec;
   1540     int rv;
   1541 
   1542     h2_pri_spec(data, &pri_spec);
   1543 
   1544     H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
   1545                  stream->stream_id, data));
   1546     rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
   1547                                  &pri_spec);
   1548     if(rv)
   1549       return rv;
   1550   }
   1551 
   1552   return nghttp2_session_send(h2);
   1553 }
   1554 
   1555 static ssize_t http2_recv(struct connectdata *conn, int sockindex,
   1556                           char *mem, size_t len, CURLcode *err)
   1557 {
   1558   CURLcode result = CURLE_OK;
   1559   ssize_t rv;
   1560   ssize_t nread;
   1561   struct http_conn *httpc = &conn->proto.httpc;
   1562   struct Curl_easy *data = conn->data;
   1563   struct HTTP *stream = data->req.protop;
   1564 
   1565   (void)sockindex; /* we always do HTTP2 on sockindex 0 */
   1566 
   1567   if(should_close_session(httpc)) {
   1568     H2BUGF(infof(data,
   1569                  "http2_recv: nothing to do in this session\n"));
   1570     *err = CURLE_HTTP2;
   1571     return -1;
   1572   }
   1573 
   1574   /* Nullify here because we call nghttp2_session_send() and they
   1575      might refer to the old buffer. */
   1576   stream->upload_mem = NULL;
   1577   stream->upload_len = 0;
   1578 
   1579   /*
   1580    * At this point 'stream' is just in the Curl_easy the connection
   1581    * identifies as its owner at this time.
   1582    */
   1583 
   1584   if(stream->bodystarted &&
   1585      stream->nread_header_recvbuf < stream->header_recvbuf->size_used) {
   1586     /* If there is body data pending for this stream to return, do that */
   1587     size_t left =
   1588       stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
   1589     size_t ncopy = CURLMIN(len, left);
   1590     memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
   1591            ncopy);
   1592     stream->nread_header_recvbuf += ncopy;
   1593 
   1594     H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
   1595                  (int)ncopy));
   1596     return ncopy;
   1597   }
   1598 
   1599   H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
   1600                data, stream->stream_id));
   1601 
   1602   if((data->state.drain) && stream->memlen) {
   1603     H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
   1604                  stream->memlen, stream->stream_id,
   1605                  stream->mem, mem));
   1606     if(mem != stream->mem) {
   1607       /* if we didn't get the same buffer this time, we must move the data to
   1608          the beginning */
   1609       memmove(mem, stream->mem, stream->memlen);
   1610       stream->len = len - stream->memlen;
   1611       stream->mem = mem;
   1612     }
   1613     if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) {
   1614       /* We have paused nghttp2, but we have no pause data (see
   1615          on_data_chunk_recv). */
   1616       httpc->pause_stream_id = 0;
   1617       if(h2_process_pending_input(conn, httpc, &result) != 0) {
   1618         *err = result;
   1619         return -1;
   1620       }
   1621     }
   1622   }
   1623   else if(stream->pausedata) {
   1624     DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
   1625     nread = CURLMIN(len, stream->pauselen);
   1626     memcpy(mem, stream->pausedata, nread);
   1627 
   1628     stream->pausedata += nread;
   1629     stream->pauselen -= nread;
   1630 
   1631     infof(data, "%zd data bytes written\n", nread);
   1632     if(stream->pauselen == 0) {
   1633       H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
   1634       DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
   1635       httpc->pause_stream_id = 0;
   1636 
   1637       stream->pausedata = NULL;
   1638       stream->pauselen = 0;
   1639 
   1640       /* When NGHTTP2_ERR_PAUSE is returned from
   1641          data_source_read_callback, we might not process DATA frame
   1642          fully.  Calling nghttp2_session_mem_recv() again will
   1643          continue to process DATA frame, but if there is no incoming
   1644          frames, then we have to call it again with 0-length data.
   1645          Without this, on_stream_close callback will not be called,
   1646          and stream could be hanged. */
   1647       if(h2_process_pending_input(conn, httpc, &result) != 0) {
   1648         *err = result;
   1649         return -1;
   1650       }
   1651     }
   1652     H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
   1653                  nread, stream->stream_id));
   1654     return nread;
   1655   }
   1656   else if(httpc->pause_stream_id) {
   1657     /* If a stream paused nghttp2_session_mem_recv previously, and has
   1658        not processed all data, it still refers to the buffer in
   1659        nghttp2_session.  If we call nghttp2_session_mem_recv(), we may
   1660        overwrite that buffer.  To avoid that situation, just return
   1661        here with CURLE_AGAIN.  This could be busy loop since data in
   1662        socket is not read.  But it seems that usually streams are
   1663        notified with its drain property, and socket is read again
   1664        quickly. */
   1665     H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
   1666                  stream->stream_id, httpc->pause_stream_id));
   1667     *err = CURLE_AGAIN;
   1668     return -1;
   1669   }
   1670   else {
   1671     char *inbuf;
   1672     /* remember where to store incoming data for this stream and how big the
   1673        buffer is */
   1674     stream->mem = mem;
   1675     stream->len = len;
   1676     stream->memlen = 0;
   1677 
   1678     if(httpc->inbuflen == 0) {
   1679       nread = ((Curl_recv *)httpc->recv_underlying)(
   1680           conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
   1681 
   1682       if(nread == -1) {
   1683         if(result != CURLE_AGAIN)
   1684           failf(data, "Failed receiving HTTP2 data");
   1685         else if(stream->closed)
   1686           /* received when the stream was already closed! */
   1687           return http2_handle_stream_close(conn, data, stream, err);
   1688 
   1689         *err = result;
   1690         return -1;
   1691       }
   1692 
   1693       if(nread == 0) {
   1694         H2BUGF(infof(data, "end of stream\n"));
   1695         *err = CURLE_OK;
   1696         return 0;
   1697       }
   1698 
   1699       H2BUGF(infof(data, "nread=%zd\n", nread));
   1700 
   1701       httpc->inbuflen = nread;
   1702       inbuf = httpc->inbuf;
   1703     }
   1704     else {
   1705       nread = httpc->inbuflen - httpc->nread_inbuf;
   1706       inbuf = httpc->inbuf + httpc->nread_inbuf;
   1707 
   1708       H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
   1709                    nread));
   1710     }
   1711     rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
   1712 
   1713     if(nghttp2_is_fatal((int)rv)) {
   1714       failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
   1715             rv, nghttp2_strerror((int)rv));
   1716       *err = CURLE_RECV_ERROR;
   1717       return -1;
   1718     }
   1719     H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
   1720     if(nread == rv) {
   1721       H2BUGF(infof(data, "All data in connection buffer processed\n"));
   1722       httpc->inbuflen = 0;
   1723       httpc->nread_inbuf = 0;
   1724     }
   1725     else {
   1726       httpc->nread_inbuf += rv;
   1727       H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
   1728                    httpc->inbuflen - httpc->nread_inbuf));
   1729     }
   1730     /* Always send pending frames in nghttp2 session, because
   1731        nghttp2_session_mem_recv() may queue new frame */
   1732     rv = h2_session_send(data, httpc->h2);
   1733     if(rv != 0) {
   1734       *err = CURLE_SEND_ERROR;
   1735       return -1;
   1736     }
   1737 
   1738     if(should_close_session(httpc)) {
   1739       H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
   1740       *err = CURLE_HTTP2;
   1741       return -1;
   1742     }
   1743   }
   1744   if(stream->memlen) {
   1745     ssize_t retlen = stream->memlen;
   1746     H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
   1747                  retlen, stream->stream_id));
   1748     stream->memlen = 0;
   1749 
   1750     if(httpc->pause_stream_id == stream->stream_id) {
   1751       /* data for this stream is returned now, but this stream caused a pause
   1752          already so we need it called again asap */
   1753       H2BUGF(infof(data, "Data returned for PAUSED stream %u\n",
   1754                    stream->stream_id));
   1755     }
   1756     else if(!stream->closed) {
   1757       drained_transfer(data, httpc);
   1758     }
   1759 
   1760     return retlen;
   1761   }
   1762   /* If stream is closed, return 0 to signal the http routine to close
   1763      the connection */
   1764   if(stream->closed) {
   1765     return http2_handle_stream_close(conn, data, stream, err);
   1766   }
   1767   *err = CURLE_AGAIN;
   1768   H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
   1769                stream->stream_id));
   1770   return -1;
   1771 }
   1772 
   1773 /* Index where :authority header field will appear in request header
   1774    field list. */
   1775 #define AUTHORITY_DST_IDX 3
   1776 
   1777 #define HEADER_OVERFLOW(x) \
   1778   (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
   1779 
   1780 /*
   1781  * Check header memory for the token "trailers".
   1782  * Parse the tokens as separated by comma and surrounded by whitespace.
   1783  * Returns TRUE if found or FALSE if not.
   1784  */
   1785 static bool contains_trailers(const char *p, size_t len)
   1786 {
   1787   const char *end = p + len;
   1788   for(;;) {
   1789     for(; p != end && (*p == ' ' || *p == '\t'); ++p)
   1790       ;
   1791     if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
   1792       return FALSE;
   1793     if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
   1794       p += sizeof("trailers") - 1;
   1795       for(; p != end && (*p == ' ' || *p == '\t'); ++p)
   1796         ;
   1797       if(p == end || *p == ',')
   1798         return TRUE;
   1799     }
   1800     /* skip to next token */
   1801     for(; p != end && *p != ','; ++p)
   1802       ;
   1803     if(p == end)
   1804       return FALSE;
   1805     ++p;
   1806   }
   1807 }
   1808 
   1809 typedef enum {
   1810   /* Send header to server */
   1811   HEADERINST_FORWARD,
   1812   /* Don't send header to server */
   1813   HEADERINST_IGNORE,
   1814   /* Discard header, and replace it with "te: trailers" */
   1815   HEADERINST_TE_TRAILERS
   1816 } header_instruction;
   1817 
   1818 /* Decides how to treat given header field. */
   1819 static header_instruction inspect_header(const char *name, size_t namelen,
   1820                                          const char *value, size_t valuelen) {
   1821   switch(namelen) {
   1822   case 2:
   1823     if(!strncasecompare("te", name, namelen))
   1824       return HEADERINST_FORWARD;
   1825 
   1826     return contains_trailers(value, valuelen) ?
   1827            HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
   1828   case 7:
   1829     return strncasecompare("upgrade", name, namelen) ?
   1830            HEADERINST_IGNORE : HEADERINST_FORWARD;
   1831   case 10:
   1832     return (strncasecompare("connection", name, namelen) ||
   1833             strncasecompare("keep-alive", name, namelen)) ?
   1834            HEADERINST_IGNORE : HEADERINST_FORWARD;
   1835   case 16:
   1836     return strncasecompare("proxy-connection", name, namelen) ?
   1837            HEADERINST_IGNORE : HEADERINST_FORWARD;
   1838   case 17:
   1839     return strncasecompare("transfer-encoding", name, namelen) ?
   1840            HEADERINST_IGNORE : HEADERINST_FORWARD;
   1841   default:
   1842     return HEADERINST_FORWARD;
   1843   }
   1844 }
   1845 
   1846 static ssize_t http2_send(struct connectdata *conn, int sockindex,
   1847                           const void *mem, size_t len, CURLcode *err)
   1848 {
   1849   /*
   1850    * BIG TODO: Currently, we send request in this function, but this
   1851    * function is also used to send request body. It would be nice to
   1852    * add dedicated function for request.
   1853    */
   1854   int rv;
   1855   struct http_conn *httpc = &conn->proto.httpc;
   1856   struct HTTP *stream = conn->data->req.protop;
   1857   nghttp2_nv *nva = NULL;
   1858   size_t nheader;
   1859   size_t i;
   1860   size_t authority_idx;
   1861   char *hdbuf = (char *)mem;
   1862   char *end, *line_end;
   1863   nghttp2_data_provider data_prd;
   1864   int32_t stream_id;
   1865   nghttp2_session *h2 = httpc->h2;
   1866   nghttp2_priority_spec pri_spec;
   1867 
   1868   (void)sockindex;
   1869 
   1870   H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
   1871 
   1872   if(stream->stream_id != -1) {
   1873     if(stream->close_handled) {
   1874       infof(conn->data, "stream %d closed\n", stream->stream_id);
   1875       *err = CURLE_HTTP2_STREAM;
   1876       return -1;
   1877     }
   1878     else if(stream->closed) {
   1879       return http2_handle_stream_close(conn, conn->data, stream, err);
   1880     }
   1881     /* If stream_id != -1, we have dispatched request HEADERS, and now
   1882        are going to send or sending request body in DATA frame */
   1883     stream->upload_mem = mem;
   1884     stream->upload_len = len;
   1885     nghttp2_session_resume_data(h2, stream->stream_id);
   1886     rv = h2_session_send(conn->data, h2);
   1887     if(nghttp2_is_fatal(rv)) {
   1888       *err = CURLE_SEND_ERROR;
   1889       return -1;
   1890     }
   1891     len -= stream->upload_len;
   1892 
   1893     /* Nullify here because we call nghttp2_session_send() and they
   1894        might refer to the old buffer. */
   1895     stream->upload_mem = NULL;
   1896     stream->upload_len = 0;
   1897 
   1898     if(should_close_session(httpc)) {
   1899       H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
   1900       *err = CURLE_HTTP2;
   1901       return -1;
   1902     }
   1903 
   1904     if(stream->upload_left) {
   1905       /* we are sure that we have more data to send here.  Calling the
   1906          following API will make nghttp2_session_want_write() return
   1907          nonzero if remote window allows it, which then libcurl checks
   1908          socket is writable or not.  See http2_perform_getsock(). */
   1909       nghttp2_session_resume_data(h2, stream->stream_id);
   1910     }
   1911 
   1912     H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
   1913                  stream->stream_id));
   1914     return len;
   1915   }
   1916 
   1917   /* Calculate number of headers contained in [mem, mem + len) */
   1918   /* Here, we assume the curl http code generate *correct* HTTP header
   1919      field block */
   1920   nheader = 0;
   1921   for(i = 1; i < len; ++i) {
   1922     if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') {
   1923       ++nheader;
   1924       ++i;
   1925     }
   1926   }
   1927   if(nheader < 2)
   1928     goto fail;
   1929 
   1930   /* We counted additional 2 \r\n in the first and last line. We need 3
   1931      new headers: :method, :path and :scheme. Therefore we need one
   1932      more space. */
   1933   nheader += 1;
   1934   nva = malloc(sizeof(nghttp2_nv) * nheader);
   1935   if(nva == NULL) {
   1936     *err = CURLE_OUT_OF_MEMORY;
   1937     return -1;
   1938   }
   1939 
   1940   /* Extract :method, :path from request line
   1941      We do line endings with CRLF so checking for CR is enough */
   1942   line_end = memchr(hdbuf, '\r', len);
   1943   if(!line_end)
   1944     goto fail;
   1945 
   1946   /* Method does not contain spaces */
   1947   end = memchr(hdbuf, ' ', line_end - hdbuf);
   1948   if(!end || end == hdbuf)
   1949     goto fail;
   1950   nva[0].name = (unsigned char *)":method";
   1951   nva[0].namelen = strlen((char *)nva[0].name);
   1952   nva[0].value = (unsigned char *)hdbuf;
   1953   nva[0].valuelen = (size_t)(end - hdbuf);
   1954   nva[0].flags = NGHTTP2_NV_FLAG_NONE;
   1955   if(HEADER_OVERFLOW(nva[0])) {
   1956     failf(conn->data, "Failed sending HTTP request: Header overflow");
   1957     goto fail;
   1958   }
   1959 
   1960   hdbuf = end + 1;
   1961 
   1962   /* Path may contain spaces so scan backwards */
   1963   end = NULL;
   1964   for(i = (size_t)(line_end - hdbuf); i; --i) {
   1965     if(hdbuf[i - 1] == ' ') {
   1966       end = &hdbuf[i - 1];
   1967       break;
   1968     }
   1969   }
   1970   if(!end || end == hdbuf)
   1971     goto fail;
   1972   nva[1].name = (unsigned char *)":path";
   1973   nva[1].namelen = strlen((char *)nva[1].name);
   1974   nva[1].value = (unsigned char *)hdbuf;
   1975   nva[1].valuelen = (size_t)(end - hdbuf);
   1976   nva[1].flags = NGHTTP2_NV_FLAG_NONE;
   1977   if(HEADER_OVERFLOW(nva[1])) {
   1978     failf(conn->data, "Failed sending HTTP request: Header overflow");
   1979     goto fail;
   1980   }
   1981 
   1982   nva[2].name = (unsigned char *)":scheme";
   1983   nva[2].namelen = strlen((char *)nva[2].name);
   1984   if(conn->handler->flags & PROTOPT_SSL)
   1985     nva[2].value = (unsigned char *)"https";
   1986   else
   1987     nva[2].value = (unsigned char *)"http";
   1988   nva[2].valuelen = strlen((char *)nva[2].value);
   1989   nva[2].flags = NGHTTP2_NV_FLAG_NONE;
   1990   if(HEADER_OVERFLOW(nva[2])) {
   1991     failf(conn->data, "Failed sending HTTP request: Header overflow");
   1992     goto fail;
   1993   }
   1994 
   1995   authority_idx = 0;
   1996   i = 3;
   1997   while(i < nheader) {
   1998     size_t hlen;
   1999 
   2000     hdbuf = line_end + 2;
   2001 
   2002     /* check for next CR, but only within the piece of data left in the given
   2003        buffer */
   2004     line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
   2005     if(!line_end || (line_end == hdbuf))
   2006       goto fail;
   2007 
   2008     /* header continuation lines are not supported */
   2009     if(*hdbuf == ' ' || *hdbuf == '\t')
   2010       goto fail;
   2011 
   2012     for(end = hdbuf; end < line_end && *end != ':'; ++end)
   2013       ;
   2014     if(end == hdbuf || end == line_end)
   2015       goto fail;
   2016     hlen = end - hdbuf;
   2017 
   2018     if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
   2019       authority_idx = i;
   2020       nva[i].name = (unsigned char *)":authority";
   2021       nva[i].namelen = strlen((char *)nva[i].name);
   2022     }
   2023     else {
   2024       nva[i].name = (unsigned char *)hdbuf;
   2025       nva[i].namelen = (size_t)(end - hdbuf);
   2026     }
   2027     hdbuf = end + 1;
   2028     while(*hdbuf == ' ' || *hdbuf == '\t')
   2029       ++hdbuf;
   2030     end = line_end;
   2031 
   2032     switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
   2033                           end - hdbuf)) {
   2034     case HEADERINST_IGNORE:
   2035       /* skip header fields prohibited by HTTP/2 specification. */
   2036       --nheader;
   2037       continue;
   2038     case HEADERINST_TE_TRAILERS:
   2039       nva[i].value = (uint8_t*)"trailers";
   2040       nva[i].valuelen = sizeof("trailers") - 1;
   2041       break;
   2042     default:
   2043       nva[i].value = (unsigned char *)hdbuf;
   2044       nva[i].valuelen = (size_t)(end - hdbuf);
   2045     }
   2046 
   2047     nva[i].flags = NGHTTP2_NV_FLAG_NONE;
   2048     if(HEADER_OVERFLOW(nva[i])) {
   2049       failf(conn->data, "Failed sending HTTP request: Header overflow");
   2050       goto fail;
   2051     }
   2052     ++i;
   2053   }
   2054 
   2055   /* :authority must come before non-pseudo header fields */
   2056   if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
   2057     nghttp2_nv authority = nva[authority_idx];
   2058     for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
   2059       nva[i] = nva[i - 1];
   2060     }
   2061     nva[i] = authority;
   2062   }
   2063 
   2064   /* Warn stream may be rejected if cumulative length of headers is too large.
   2065      It appears nghttp2 will not send a header frame larger than 64KB. */
   2066 #define MAX_ACC 60000  /* <64KB to account for some overhead */
   2067   {
   2068     size_t acc = 0;
   2069 
   2070     for(i = 0; i < nheader; ++i) {
   2071       acc += nva[i].namelen + nva[i].valuelen;
   2072 
   2073       H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
   2074                    nva[i].namelen, nva[i].name,
   2075                    nva[i].valuelen, nva[i].value));
   2076     }
   2077 
   2078     if(acc > MAX_ACC) {
   2079       infof(conn->data, "http2_send: Warning: The cumulative length of all "
   2080             "headers exceeds %zu bytes and that could cause the "
   2081             "stream to be rejected.\n", MAX_ACC);
   2082     }
   2083   }
   2084 
   2085   h2_pri_spec(conn->data, &pri_spec);
   2086 
   2087   switch(conn->data->set.httpreq) {
   2088   case HTTPREQ_POST:
   2089   case HTTPREQ_POST_FORM:
   2090   case HTTPREQ_POST_MIME:
   2091   case HTTPREQ_PUT:
   2092     if(conn->data->state.infilesize != -1)
   2093       stream->upload_left = conn->data->state.infilesize;
   2094     else
   2095       /* data sending without specifying the data amount up front */
   2096       stream->upload_left = -1; /* unknown, but not zero */
   2097 
   2098     data_prd.read_callback = data_source_read_callback;
   2099     data_prd.source.ptr = NULL;
   2100     stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
   2101                                        &data_prd, conn->data);
   2102     break;
   2103   default:
   2104     stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
   2105                                        NULL, conn->data);
   2106   }
   2107 
   2108   Curl_safefree(nva);
   2109 
   2110   if(stream_id < 0) {
   2111     H2BUGF(infof(conn->data, "http2_send() send error\n"));
   2112     *err = CURLE_SEND_ERROR;
   2113     return -1;
   2114   }
   2115 
   2116   infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
   2117         stream_id, (void *)conn->data);
   2118   stream->stream_id = stream_id;
   2119 
   2120   /* this does not call h2_session_send() since there can not have been any
   2121    * priority upodate since the nghttp2_submit_request() call above */
   2122   rv = nghttp2_session_send(h2);
   2123 
   2124   if(rv != 0) {
   2125     *err = CURLE_SEND_ERROR;
   2126     return -1;
   2127   }
   2128 
   2129   if(should_close_session(httpc)) {
   2130     H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
   2131     *err = CURLE_HTTP2;
   2132     return -1;
   2133   }
   2134 
   2135   if(stream->stream_id != -1) {
   2136     /* If whole HEADERS frame was sent off to the underlying socket,
   2137        the nghttp2 library calls data_source_read_callback. But only
   2138        it found that no data available, so it deferred the DATA
   2139        transmission. Which means that nghttp2_session_want_write()
   2140        returns 0 on http2_perform_getsock(), which results that no
   2141        writable socket check is performed. To workaround this, we
   2142        issue nghttp2_session_resume_data() here to bring back DATA
   2143        transmission from deferred state. */
   2144     nghttp2_session_resume_data(h2, stream->stream_id);
   2145   }
   2146 
   2147   return len;
   2148 
   2149 fail:
   2150   free(nva);
   2151   *err = CURLE_SEND_ERROR;
   2152   return -1;
   2153 }
   2154 
   2155 CURLcode Curl_http2_setup(struct connectdata *conn)
   2156 {
   2157   CURLcode result;
   2158   struct http_conn *httpc = &conn->proto.httpc;
   2159   struct HTTP *stream = conn->data->req.protop;
   2160 
   2161   stream->stream_id = -1;
   2162 
   2163   if(!stream->header_recvbuf) {
   2164     stream->header_recvbuf = Curl_add_buffer_init();
   2165     if(!stream->header_recvbuf)
   2166       return CURLE_OUT_OF_MEMORY;
   2167   }
   2168 
   2169   if((conn->handler == &Curl_handler_http2_ssl) ||
   2170      (conn->handler == &Curl_handler_http2))
   2171     return CURLE_OK; /* already done */
   2172 
   2173   if(conn->handler->flags & PROTOPT_SSL)
   2174     conn->handler = &Curl_handler_http2_ssl;
   2175   else
   2176     conn->handler = &Curl_handler_http2;
   2177 
   2178   result = http2_init(conn);
   2179   if(result) {
   2180     Curl_add_buffer_free(&stream->header_recvbuf);
   2181     return result;
   2182   }
   2183 
   2184   infof(conn->data, "Using HTTP2, server supports multi-use\n");
   2185   stream->upload_left = 0;
   2186   stream->upload_mem = NULL;
   2187   stream->upload_len = 0;
   2188 
   2189   httpc->inbuflen = 0;
   2190   httpc->nread_inbuf = 0;
   2191 
   2192   httpc->pause_stream_id = 0;
   2193   httpc->drain_total = 0;
   2194 
   2195   conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
   2196   conn->httpversion = 20;
   2197   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
   2198 
   2199   infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
   2200   multi_connchanged(conn->data->multi);
   2201 
   2202   return CURLE_OK;
   2203 }
   2204 
   2205 CURLcode Curl_http2_switched(struct connectdata *conn,
   2206                              const char *mem, size_t nread)
   2207 {
   2208   CURLcode result;
   2209   struct http_conn *httpc = &conn->proto.httpc;
   2210   int rv;
   2211   ssize_t nproc;
   2212   struct Curl_easy *data = conn->data;
   2213   struct HTTP *stream = conn->data->req.protop;
   2214 
   2215   result = Curl_http2_setup(conn);
   2216   if(result)
   2217     return result;
   2218 
   2219   httpc->recv_underlying = conn->recv[FIRSTSOCKET];
   2220   httpc->send_underlying = conn->send[FIRSTSOCKET];
   2221   conn->recv[FIRSTSOCKET] = http2_recv;
   2222   conn->send[FIRSTSOCKET] = http2_send;
   2223 
   2224   if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
   2225     /* stream 1 is opened implicitly on upgrade */
   2226     stream->stream_id = 1;
   2227     /* queue SETTINGS frame (again) */
   2228     rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
   2229                                  httpc->binlen, NULL);
   2230     if(rv != 0) {
   2231       failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
   2232             nghttp2_strerror(rv), rv);
   2233       return CURLE_HTTP2;
   2234     }
   2235 
   2236     rv = nghttp2_session_set_stream_user_data(httpc->h2,
   2237                                               stream->stream_id,
   2238                                               data);
   2239     if(rv) {
   2240       infof(data, "http/2: failed to set user_data for stream %d!\n",
   2241             stream->stream_id);
   2242       DEBUGASSERT(0);
   2243     }
   2244   }
   2245   else {
   2246     populate_settings(conn, httpc);
   2247 
   2248     /* stream ID is unknown at this point */
   2249     stream->stream_id = -1;
   2250     rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
   2251                                  httpc->local_settings,
   2252                                  httpc->local_settings_num);
   2253     if(rv != 0) {
   2254       failf(data, "nghttp2_submit_settings() failed: %s(%d)",
   2255             nghttp2_strerror(rv), rv);
   2256       return CURLE_HTTP2;
   2257     }
   2258   }
   2259 
   2260 #ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
   2261   rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
   2262                                              HTTP2_HUGE_WINDOW_SIZE);
   2263   if(rv != 0) {
   2264     failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
   2265           nghttp2_strerror(rv), rv);
   2266     return CURLE_HTTP2;
   2267   }
   2268 #endif
   2269 
   2270   /* we are going to copy mem to httpc->inbuf.  This is required since
   2271      mem is part of buffer pointed by stream->mem, and callbacks
   2272      called by nghttp2_session_mem_recv() will write stream specific
   2273      data into stream->mem, overwriting data already there. */
   2274   if(H2_BUFSIZE < nread) {
   2275     failf(data, "connection buffer size is too small to store data following "
   2276                 "HTTP Upgrade response header: buflen=%zu, datalen=%zu",
   2277           H2_BUFSIZE, nread);
   2278     return CURLE_HTTP2;
   2279   }
   2280 
   2281   infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer"
   2282                     " after upgrade: len=%zu\n",
   2283         nread);
   2284 
   2285   if(nread)
   2286     memcpy(httpc->inbuf, mem, nread);
   2287   httpc->inbuflen = nread;
   2288 
   2289   nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
   2290                                    httpc->inbuflen);
   2291 
   2292   if(nghttp2_is_fatal((int)nproc)) {
   2293     failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
   2294           nghttp2_strerror((int)nproc), (int)nproc);
   2295     return CURLE_HTTP2;
   2296   }
   2297 
   2298   H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
   2299 
   2300   if((ssize_t)nread == nproc) {
   2301     httpc->inbuflen = 0;
   2302     httpc->nread_inbuf = 0;
   2303   }
   2304   else {
   2305     httpc->nread_inbuf += nproc;
   2306   }
   2307 
   2308   /* Try to send some frames since we may read SETTINGS already. */
   2309   rv = h2_session_send(data, httpc->h2);
   2310 
   2311   if(rv != 0) {
   2312     failf(data, "nghttp2_session_send() failed: %s(%d)",
   2313           nghttp2_strerror(rv), rv);
   2314     return CURLE_HTTP2;
   2315   }
   2316 
   2317   if(should_close_session(httpc)) {
   2318     H2BUGF(infof(data,
   2319                  "nghttp2_session_send(): nothing to do in this session\n"));
   2320     return CURLE_HTTP2;
   2321   }
   2322 
   2323   return CURLE_OK;
   2324 }
   2325 
   2326 CURLcode Curl_http2_add_child(struct Curl_easy *parent,
   2327                               struct Curl_easy *child,
   2328                               bool exclusive)
   2329 {
   2330   if(parent) {
   2331     struct Curl_http2_dep **tail;
   2332     struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
   2333     if(!dep)
   2334       return CURLE_OUT_OF_MEMORY;
   2335     dep->data = child;
   2336 
   2337     if(parent->set.stream_dependents && exclusive) {
   2338       struct Curl_http2_dep *node = parent->set.stream_dependents;
   2339       while(node) {
   2340         node->data->set.stream_depends_on = child;
   2341         node = node->next;
   2342       }
   2343 
   2344       tail = &child->set.stream_dependents;
   2345       while(*tail)
   2346         tail = &(*tail)->next;
   2347 
   2348       DEBUGASSERT(!*tail);
   2349       *tail = parent->set.stream_dependents;
   2350       parent->set.stream_dependents = 0;
   2351     }
   2352 
   2353     tail = &parent->set.stream_dependents;
   2354     while(*tail) {
   2355       (*tail)->data->set.stream_depends_e = FALSE;
   2356       tail = &(*tail)->next;
   2357     }
   2358 
   2359     DEBUGASSERT(!*tail);
   2360     *tail = dep;
   2361   }
   2362 
   2363   child->set.stream_depends_on = parent;
   2364   child->set.stream_depends_e = exclusive;
   2365   return CURLE_OK;
   2366 }
   2367 
   2368 void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
   2369 {
   2370   struct Curl_http2_dep *last = 0;
   2371   struct Curl_http2_dep *data = parent->set.stream_dependents;
   2372   DEBUGASSERT(child->set.stream_depends_on == parent);
   2373 
   2374   while(data && data->data != child) {
   2375     last = data;
   2376     data = data->next;
   2377   }
   2378 
   2379   DEBUGASSERT(data);
   2380 
   2381   if(data) {
   2382     if(last) {
   2383       last->next = data->next;
   2384     }
   2385     else {
   2386       parent->set.stream_dependents = data->next;
   2387     }
   2388     free(data);
   2389   }
   2390 
   2391   child->set.stream_depends_on = 0;
   2392   child->set.stream_depends_e = FALSE;
   2393 }
   2394 
   2395 void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
   2396 {
   2397   while(data->set.stream_dependents) {
   2398     struct Curl_easy *tmp = data->set.stream_dependents->data;
   2399     Curl_http2_remove_child(data, tmp);
   2400     if(data->set.stream_depends_on)
   2401       Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
   2402   }
   2403 
   2404   if(data->set.stream_depends_on)
   2405     Curl_http2_remove_child(data->set.stream_depends_on, data);
   2406 }
   2407 
   2408 /* Only call this function for a transfer that already got a HTTP/2
   2409    CURLE_HTTP2_STREAM error! */
   2410 bool Curl_h2_http_1_1_error(struct connectdata *conn)
   2411 {
   2412   struct http_conn *httpc = &conn->proto.httpc;
   2413   return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
   2414 }
   2415 
   2416 #else /* !USE_NGHTTP2 */
   2417 
   2418 /* Satisfy external references even if http2 is not compiled in. */
   2419 
   2420 #define CURL_DISABLE_TYPECHECK
   2421 #include <curl/curl.h>
   2422 
   2423 char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
   2424 {
   2425   (void) h;
   2426   (void) num;
   2427   return NULL;
   2428 }
   2429 
   2430 char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
   2431 {
   2432   (void) h;
   2433   (void) header;
   2434   return NULL;
   2435 }
   2436 
   2437 #endif /* USE_NGHTTP2 */
   2438