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