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