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