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