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