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