Base code merged to SPIN 2.4
[platform/upstream/curl.git] / lib / http2.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, 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 http://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 #define _MPRINTF_REPLACE
27 #include <curl/mprintf.h>
28
29 #include <nghttp2/nghttp2.h>
30 #include "urldata.h"
31 #include "http2.h"
32 #include "http.h"
33 #include "sendf.h"
34 #include "curl_base64.h"
35 #include "curl_memory.h"
36 #include "rawstr.h"
37 #include "multiif.h"
38
39 /* include memdebug.h last */
40 #include "memdebug.h"
41
42 #if (NGHTTP2_VERSION_NUM < 0x000600)
43 #error too old nghttp2 version, upgrade!
44 #endif
45
46 static int http2_perform_getsock(const struct connectdata *conn,
47                                  curl_socket_t *sock, /* points to
48                                                          numsocks
49                                                          number of
50                                                          sockets */
51                                  int numsocks)
52 {
53   const struct http_conn *httpc = &conn->proto.httpc;
54   int bitmap = GETSOCK_BLANK;
55   (void)numsocks;
56
57   /* TODO We should check underlying socket state if it is SSL socket
58      because of renegotiation. */
59   sock[0] = conn->sock[FIRSTSOCKET];
60
61   if(nghttp2_session_want_read(httpc->h2))
62     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
63
64   if(nghttp2_session_want_write(httpc->h2))
65     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
66
67   return bitmap;
68 }
69
70 static int http2_getsock(struct connectdata *conn,
71                          curl_socket_t *sock, /* points to numsocks
72                                                  number of sockets */
73                          int numsocks)
74 {
75   return http2_perform_getsock(conn, sock, numsocks);
76 }
77
78 static CURLcode http2_disconnect(struct connectdata *conn,
79                                  bool dead_connection)
80 {
81   struct http_conn *httpc = &conn->proto.httpc;
82   (void)dead_connection;
83
84   infof(conn->data, "HTTP/2 DISCONNECT starts now\n");
85
86   nghttp2_session_del(httpc->h2);
87
88   Curl_safefree(httpc->header_recvbuf->buffer);
89   Curl_safefree(httpc->header_recvbuf);
90
91   Curl_safefree(httpc->inbuf);
92
93   infof(conn->data, "HTTP/2 DISCONNECT done\n");
94
95   return CURLE_OK;
96 }
97
98 /*
99  * HTTP2 handler interface. This isn't added to the general list of protocols
100  * but will be used at run-time when the protocol is dynamically switched from
101  * HTTP to HTTP2.
102  */
103 const struct Curl_handler Curl_handler_http2 = {
104   "HTTP2",                              /* scheme */
105   ZERO_NULL,                            /* setup_connection */
106   Curl_http,                            /* do_it */
107   ZERO_NULL,                            /* done */
108   ZERO_NULL,                            /* do_more */
109   ZERO_NULL,                            /* connect_it */
110   ZERO_NULL,                            /* connecting */
111   ZERO_NULL,                            /* doing */
112   http2_getsock,                        /* proto_getsock */
113   http2_getsock,                        /* doing_getsock */
114   ZERO_NULL,                            /* domore_getsock */
115   http2_perform_getsock,                /* perform_getsock */
116   http2_disconnect,                     /* disconnect */
117   ZERO_NULL,                            /* readwrite */
118   PORT_HTTP,                            /* defport */
119   CURLPROTO_HTTP,                       /* protocol */
120   PROTOPT_NONE                          /* flags */
121 };
122
123 const struct Curl_handler Curl_handler_http2_ssl = {
124   "HTTP2",                              /* scheme */
125   ZERO_NULL,                            /* setup_connection */
126   Curl_http,                            /* do_it */
127   ZERO_NULL,                            /* done */
128   ZERO_NULL,                            /* do_more */
129   ZERO_NULL,                            /* connect_it */
130   ZERO_NULL,                            /* connecting */
131   ZERO_NULL,                            /* doing */
132   http2_getsock,                        /* proto_getsock */
133   http2_getsock,                        /* doing_getsock */
134   ZERO_NULL,                            /* domore_getsock */
135   http2_perform_getsock,                /* perform_getsock */
136   http2_disconnect,                     /* disconnect */
137   ZERO_NULL,                            /* readwrite */
138   PORT_HTTP,                            /* defport */
139   CURLPROTO_HTTPS,                      /* protocol */
140   PROTOPT_SSL                           /* flags */
141 };
142
143 /*
144  * Store nghttp2 version info in this buffer, Prefix with a space.  Return
145  * total length written.
146  */
147 int Curl_http2_ver(char *p, size_t len)
148 {
149   nghttp2_info *h2 = nghttp2_version(0);
150   return snprintf(p, len, " nghttp2/%s", h2->version_str);
151 }
152
153 /*
154  * The implementation of nghttp2_send_callback type. Here we write |data| with
155  * size |length| to the network and return the number of bytes actually
156  * written. See the documentation of nghttp2_send_callback for the details.
157  */
158 static ssize_t send_callback(nghttp2_session *h2,
159                              const uint8_t *data, size_t length, int flags,
160                              void *userp)
161 {
162   struct connectdata *conn = (struct connectdata *)userp;
163   struct http_conn *httpc = &conn->proto.httpc;
164   ssize_t written;
165   CURLcode result = CURLE_OK;
166
167   (void)h2;
168   (void)flags;
169
170   written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET,
171                                                  data, length, &result);
172
173   if(result == CURLE_AGAIN) {
174     return NGHTTP2_ERR_WOULDBLOCK;
175   }
176
177   if(written == -1) {
178     failf(conn->data, "Failed sending HTTP2 data");
179     return NGHTTP2_ERR_CALLBACK_FAILURE;
180   }
181
182   if(!written)
183     return NGHTTP2_ERR_WOULDBLOCK;
184
185   return written;
186 }
187
188 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
189                          void *userp)
190 {
191   struct connectdata *conn = (struct connectdata *)userp;
192   struct http_conn *c = &conn->proto.httpc;
193   int rv;
194   size_t left, ncopy;
195
196   (void)session;
197   (void)frame;
198   infof(conn->data, "on_frame_recv() was called with header %x\n",
199         frame->hd.type);
200   switch(frame->hd.type) {
201   case NGHTTP2_DATA:
202     /* If body started, then receiving DATA is illegal. */
203     if(!c->bodystarted) {
204       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
205                                      frame->hd.stream_id,
206                                      NGHTTP2_PROTOCOL_ERROR);
207
208       if(nghttp2_is_fatal(rv)) {
209         return NGHTTP2_ERR_CALLBACK_FAILURE;
210       }
211     }
212     break;
213   case NGHTTP2_HEADERS:
214     if(frame->headers.cat == NGHTTP2_HCAT_REQUEST)
215       break;
216
217     if(c->bodystarted) {
218       /* Only valid HEADERS after body started is trailer header,
219          which is not fully supported in this code.  If HEADERS is not
220          trailer, then it is a PROTOCOL_ERROR. */
221       if((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
222         rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
223                                        frame->hd.stream_id,
224                                        NGHTTP2_PROTOCOL_ERROR);
225
226         if(nghttp2_is_fatal(rv)) {
227           return NGHTTP2_ERR_CALLBACK_FAILURE;
228         }
229       }
230       break;
231     }
232
233     if(c->status_code == -1) {
234       /* No :status header field means PROTOCOL_ERROR. */
235       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
236                                      frame->hd.stream_id,
237                                      NGHTTP2_PROTOCOL_ERROR);
238
239       if(nghttp2_is_fatal(rv)) {
240         return NGHTTP2_ERR_CALLBACK_FAILURE;
241       }
242
243       break;
244     }
245
246     /* Only final status code signals the end of header */
247     if(c->status_code / 100 != 1) {
248       c->bodystarted = TRUE;
249     }
250
251     c->status_code = -1;
252
253     Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
254
255     left = c->header_recvbuf->size_used - c->nread_header_recvbuf;
256     ncopy = c->len < left ? c->len : left;
257
258     memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy);
259     c->nread_header_recvbuf += ncopy;
260
261     c->mem += ncopy;
262     c->len -= ncopy;
263     break;
264   case NGHTTP2_PUSH_PROMISE:
265     rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
266                                    frame->push_promise.promised_stream_id,
267                                    NGHTTP2_CANCEL);
268     if(nghttp2_is_fatal(rv)) {
269       return rv;
270     }
271     break;
272   }
273   return 0;
274 }
275
276 static int on_invalid_frame_recv(nghttp2_session *session,
277                                  const nghttp2_frame *frame,
278                                  uint32_t error_code, void *userp)
279 {
280   struct connectdata *conn = (struct connectdata *)userp;
281   (void)session;
282   (void)frame;
283   infof(conn->data, "on_invalid_frame_recv() was called, error_code = %d\n",
284         error_code);
285   return 0;
286 }
287
288 static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
289                               int32_t stream_id,
290                               const uint8_t *data, size_t len, void *userp)
291 {
292   struct connectdata *conn = (struct connectdata *)userp;
293   struct http_conn *c = &conn->proto.httpc;
294   size_t nread;
295   (void)session;
296   (void)flags;
297   (void)data;
298   infof(conn->data, "on_data_chunk_recv() "
299         "len = %u, stream = %x\n", len, stream_id);
300
301   if(stream_id != c->stream_id) {
302     return 0;
303   }
304
305   nread = c->len < len ? c->len : len;
306   memcpy(c->mem, data, nread);
307
308   c->mem += nread;
309   c->len -= nread;
310
311   infof(conn->data, "%zu data written\n", nread);
312
313   if(nread < len) {
314     c->data = data + nread;
315     c->datalen = len - nread;
316     return NGHTTP2_ERR_PAUSE;
317   }
318   return 0;
319 }
320
321 static int before_frame_send(nghttp2_session *session,
322                              const nghttp2_frame *frame,
323                              void *userp)
324 {
325   struct connectdata *conn = (struct connectdata *)userp;
326   (void)session;
327   (void)frame;
328   infof(conn->data, "before_frame_send() was called\n");
329   return 0;
330 }
331 static int on_frame_send(nghttp2_session *session,
332                          const nghttp2_frame *frame,
333                          void *userp)
334 {
335   struct connectdata *conn = (struct connectdata *)userp;
336   (void)session;
337   (void)frame;
338   infof(conn->data, "on_frame_send() was called\n");
339   return 0;
340 }
341 static int on_frame_not_send(nghttp2_session *session,
342                              const nghttp2_frame *frame,
343                              int lib_error_code, void *userp)
344 {
345   struct connectdata *conn = (struct connectdata *)userp;
346   (void)session;
347   (void)frame;
348   infof(conn->data, "on_frame_not_send() was called, lib_error_code = %d\n",
349         lib_error_code);
350   return 0;
351 }
352 static int on_stream_close(nghttp2_session *session, int32_t stream_id,
353                            uint32_t error_code, void *userp)
354 {
355   struct connectdata *conn = (struct connectdata *)userp;
356   struct http_conn *c = &conn->proto.httpc;
357   (void)session;
358   (void)stream_id;
359   infof(conn->data, "on_stream_close() was called, error_code = %d\n",
360         error_code);
361
362   if(stream_id != c->stream_id) {
363     return 0;
364   }
365
366   c->closed = TRUE;
367
368   return 0;
369 }
370
371 static int on_begin_headers(nghttp2_session *session,
372                             const nghttp2_frame *frame, void *userp)
373 {
374   struct connectdata *conn = (struct connectdata *)userp;
375   (void)session;
376   (void)frame;
377   infof(conn->data, "on_begin_headers() was called\n");
378   return 0;
379 }
380
381 /* Decode HTTP status code.  Returns -1 if no valid status code was
382    decoded. */
383 static int decode_status_code(const uint8_t *value, size_t len)
384 {
385   int i;
386   int res;
387
388   if(len != 3) {
389     return -1;
390   }
391
392   res = 0;
393
394   for(i = 0; i < 3; ++i) {
395     char c = value[i];
396
397     if(c < '0' || c > '9') {
398       return -1;
399     }
400
401     res *= 10;
402     res += c - '0';
403   }
404
405   return res;
406 }
407
408 static const char STATUS[] = ":status";
409
410 /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
411 static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
412                      const uint8_t *name, size_t namelen,
413                      const uint8_t *value, size_t valuelen,
414                      uint8_t flags,
415                      void *userp)
416 {
417   struct connectdata *conn = (struct connectdata *)userp;
418   struct http_conn *c = &conn->proto.httpc;
419   int rv;
420   int goodname;
421   int goodheader;
422
423   (void)session;
424   (void)frame;
425   (void)flags;
426
427   if(frame->hd.stream_id != c->stream_id) {
428     return 0;
429   }
430
431   if(c->bodystarted) {
432     /* Ignore trailer or HEADERS not mapped to HTTP semantics.  The
433        consequence is handled in on_frame_recv(). */
434     return 0;
435   }
436
437   goodname = nghttp2_check_header_name(name, namelen);
438   goodheader = nghttp2_check_header_value(value, valuelen);
439
440   if(!goodname || !goodheader) {
441
442     infof(conn->data, "Detected bad incoming header %s%s, reset stream!\n",
443           goodname?"":"name",
444           goodheader?"":"value");
445
446     rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
447                                    frame->hd.stream_id,
448                                    NGHTTP2_PROTOCOL_ERROR);
449
450     if(nghttp2_is_fatal(rv)) {
451       return NGHTTP2_ERR_CALLBACK_FAILURE;
452     }
453
454     return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
455   }
456
457   if(namelen == sizeof(":status") - 1 &&
458      memcmp(STATUS, name, namelen) == 0) {
459
460     /* :status must appear exactly once. */
461     if(c->status_code != -1 ||
462        (c->status_code = decode_status_code(value, valuelen)) == -1) {
463
464       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
465                                      frame->hd.stream_id,
466                                      NGHTTP2_PROTOCOL_ERROR);
467       if(nghttp2_is_fatal(rv)) {
468         return NGHTTP2_ERR_CALLBACK_FAILURE;
469       }
470
471       return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
472     }
473
474     Curl_add_buffer(c->header_recvbuf, "HTTP/2.0 ", 9);
475     Curl_add_buffer(c->header_recvbuf, value, valuelen);
476     Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
477
478     return 0;
479   }
480   else {
481     /* Here we are sure that namelen > 0 because of
482        nghttp2_check_header_name().  Pseudo header other than :status
483        is illegal. */
484     if(c->status_code == -1 || name[0] == ':') {
485       rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
486                                      frame->hd.stream_id,
487                                      NGHTTP2_PROTOCOL_ERROR);
488       if(nghttp2_is_fatal(rv)) {
489         return NGHTTP2_ERR_CALLBACK_FAILURE;
490       }
491
492       return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
493     }
494
495     /* convert to a HTTP1-style header */
496     Curl_add_buffer(c->header_recvbuf, name, namelen);
497     Curl_add_buffer(c->header_recvbuf, ":", 1);
498     Curl_add_buffer(c->header_recvbuf, value, valuelen);
499     Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
500
501     infof(conn->data, "got http2 header: %.*s: %.*s\n",
502           namelen, name, valuelen, value);
503   }
504
505   return 0; /* 0 is successful */
506 }
507
508 static ssize_t data_source_read_callback(nghttp2_session *session,
509                                          int32_t stream_id,
510                                          uint8_t *buf, size_t length,
511                                          uint32_t *data_flags,
512                                          nghttp2_data_source *source,
513                                          void *userp)
514 {
515   struct connectdata *conn = (struct connectdata *)userp;
516   struct http_conn *c = &conn->proto.httpc;
517   size_t nread;
518   (void)session;
519   (void)stream_id;
520   (void)source;
521
522   nread = c->upload_len < length ? c->upload_len : length;
523   if(nread > 0) {
524     memcpy(buf, c->upload_mem, nread);
525     c->upload_mem += nread;
526     c->upload_len -= nread;
527     c->upload_left -= nread;
528   }
529
530   if(c->upload_left == 0)
531     *data_flags = 1;
532   else if(nread == 0)
533     return NGHTTP2_ERR_DEFERRED;
534
535   return nread;
536 }
537
538 /*
539  * The HTTP2 settings we send in the Upgrade request
540  */
541 static nghttp2_settings_entry settings[] = {
542   { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
543   { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
544 };
545
546 #define H2_BUFSIZE 4096
547
548 /*
549  * Initialize nghttp2 for a Curl connection
550  */
551 CURLcode Curl_http2_init(struct connectdata *conn)
552 {
553   if(!conn->proto.httpc.h2) {
554     int rc;
555     nghttp2_session_callbacks *callbacks;
556
557     conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
558     if(conn->proto.httpc.inbuf == NULL)
559       return CURLE_OUT_OF_MEMORY;
560
561     rc = nghttp2_session_callbacks_new(&callbacks);
562
563     if(rc) {
564       failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
565       return CURLE_OUT_OF_MEMORY; /* most likely at least */
566     }
567
568     /* nghttp2_send_callback */
569     nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
570     /* nghttp2_on_frame_recv_callback */
571     nghttp2_session_callbacks_set_on_frame_recv_callback
572       (callbacks, on_frame_recv);
573     /* nghttp2_on_invalid_frame_recv_callback */
574     nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
575       (callbacks, on_invalid_frame_recv);
576     /* nghttp2_on_data_chunk_recv_callback */
577     nghttp2_session_callbacks_set_on_data_chunk_recv_callback
578       (callbacks, on_data_chunk_recv);
579     /* nghttp2_before_frame_send_callback */
580     nghttp2_session_callbacks_set_before_frame_send_callback
581       (callbacks, before_frame_send);
582     /* nghttp2_on_frame_send_callback */
583     nghttp2_session_callbacks_set_on_frame_send_callback
584       (callbacks, on_frame_send);
585     /* nghttp2_on_frame_not_send_callback */
586     nghttp2_session_callbacks_set_on_frame_not_send_callback
587       (callbacks, on_frame_not_send);
588     /* nghttp2_on_stream_close_callback */
589     nghttp2_session_callbacks_set_on_stream_close_callback
590       (callbacks, on_stream_close);
591     /* nghttp2_on_begin_headers_callback */
592     nghttp2_session_callbacks_set_on_begin_headers_callback
593       (callbacks, on_begin_headers);
594     /* nghttp2_on_header_callback */
595     nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
596
597     /* The nghttp2 session is not yet setup, do it */
598     rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
599                                     callbacks, conn);
600
601     nghttp2_session_callbacks_del(callbacks);
602
603     if(rc) {
604       failf(conn->data, "Couldn't initialize nghttp2!");
605       return CURLE_OUT_OF_MEMORY; /* most likely at least */
606     }
607   }
608   return CURLE_OK;
609 }
610
611 /*
612  * Send a request using http2
613  */
614 CURLcode Curl_http2_send_request(struct connectdata *conn)
615 {
616   (void)conn;
617   return CURLE_OK;
618 }
619
620 /*
621  * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
622  */
623 CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
624                                     struct connectdata *conn)
625 {
626   CURLcode result;
627   ssize_t binlen;
628   char *base64;
629   size_t blen;
630   struct SingleRequest *k = &conn->data->req;
631   uint8_t *binsettings = conn->proto.httpc.binsettings;
632
633   result = Curl_http2_init(conn);
634   if(result)
635     return result;
636
637   result = Curl_http2_setup(conn);
638   if(result)
639     return result;
640
641   /* As long as we have a fixed set of settings, we don't have to dynamically
642    * figure out the base64 strings since it'll always be the same. However,
643    * the settings will likely not be fixed every time in the future.
644    */
645
646   /* this returns number of bytes it wrote */
647   binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
648                                          settings,
649                                          sizeof(settings)/sizeof(settings[0]));
650   if(!binlen) {
651     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
652     return CURLE_FAILED_INIT;
653   }
654   conn->proto.httpc.binlen = binlen;
655
656   result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
657                                  &base64, &blen);
658   if(result)
659     return result;
660
661   result = Curl_add_bufferf(req,
662                             "Connection: Upgrade, HTTP2-Settings\r\n"
663                             "Upgrade: %s\r\n"
664                             "HTTP2-Settings: %s\r\n",
665                             NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
666   Curl_safefree(base64);
667
668   k->upgr101 = UPGR101_REQUESTED;
669
670   return result;
671 }
672
673 /*
674  * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
675  * a regular CURLcode value.
676  */
677 static ssize_t http2_recv(struct connectdata *conn, int sockindex,
678                           char *mem, size_t len, CURLcode *err)
679 {
680   CURLcode result = CURLE_OK;
681   ssize_t rv;
682   ssize_t nread;
683   struct http_conn *httpc = &conn->proto.httpc;
684
685   (void)sockindex; /* we always do HTTP2 on sockindex 0 */
686
687   if(httpc->closed) {
688     /* Reset to FALSE to prevent infinite loop in readwrite_data
689        function. */
690     httpc->closed = FALSE;
691     return 0;
692   }
693
694   /* Nullify here because we call nghttp2_session_send() and they
695      might refer to the old buffer. */
696   httpc->upload_mem = NULL;
697   httpc->upload_len = 0;
698
699   if(httpc->bodystarted &&
700      httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) {
701     size_t left =
702       httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf;
703     size_t ncopy = len < left ? len : left;
704     memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf,
705            ncopy);
706     httpc->nread_header_recvbuf += ncopy;
707     return ncopy;
708   }
709
710   if(httpc->data) {
711     nread = len < httpc->datalen ? len : httpc->datalen;
712     memcpy(mem, httpc->data, nread);
713
714     httpc->data += nread;
715     httpc->datalen -= nread;
716
717     infof(conn->data, "%zu data written\n", nread);
718     if(httpc->datalen == 0) {
719       httpc->data = NULL;
720       httpc->datalen = 0;
721     }
722     return nread;
723   }
724
725   conn->proto.httpc.mem = mem;
726   conn->proto.httpc.len = len;
727
728   infof(conn->data, "http2_recv: %d bytes buffer\n",
729         conn->proto.httpc.len);
730
731   nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET,
732                                                httpc->inbuf, H2_BUFSIZE,
733                                                &result);
734   if(result == CURLE_AGAIN) {
735     *err = result;
736     return -1;
737   }
738
739   if(nread == -1) {
740     failf(conn->data, "Failed receiving HTTP2 data");
741     *err = result;
742     return 0;
743   }
744
745   infof(conn->data, "nread=%zd\n", nread);
746
747   if(nread == 0) {
748     failf(conn->data, "EOF");
749     return 0;
750   }
751
752   rv = nghttp2_session_mem_recv(httpc->h2,
753                                 (const uint8_t *)httpc->inbuf, nread);
754
755   if(nghttp2_is_fatal((int)rv)) {
756     failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n",
757           rv, nghttp2_strerror((int)rv));
758     *err = CURLE_RECV_ERROR;
759     return 0;
760   }
761   infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv);
762   /* Always send pending frames in nghttp2 session, because
763      nghttp2_session_mem_recv() may queue new frame */
764   rv = nghttp2_session_send(httpc->h2);
765   if(rv != 0) {
766     *err = CURLE_SEND_ERROR;
767     return 0;
768   }
769   if(len != httpc->len) {
770     return len - conn->proto.httpc.len;
771   }
772   /* If stream is closed, return 0 to signal the http routine to close
773      the connection */
774   if(httpc->closed) {
775     /* Reset to FALSE to prevent infinite loop in readwrite_data
776        function. */
777     httpc->closed = FALSE;
778     return 0;
779   }
780   *err = CURLE_AGAIN;
781   return -1;
782 }
783
784 /* Index where :authority header field will appear in request header
785    field list. */
786 #define AUTHORITY_DST_IDX 3
787
788 /* return number of received (decrypted) bytes */
789 static ssize_t http2_send(struct connectdata *conn, int sockindex,
790                           const void *mem, size_t len, CURLcode *err)
791 {
792   /*
793    * BIG TODO: Currently, we send request in this function, but this
794    * function is also used to send request body. It would be nice to
795    * add dedicated function for request.
796    */
797   int rv;
798   struct http_conn *httpc = &conn->proto.httpc;
799   nghttp2_nv *nva;
800   size_t nheader;
801   size_t i;
802   size_t authority_idx;
803   char *hdbuf = (char*)mem;
804   char *end;
805   nghttp2_data_provider data_prd;
806   int32_t stream_id;
807
808   (void)sockindex;
809
810   infof(conn->data, "http2_send len=%zu\n", len);
811
812   if(httpc->stream_id != -1) {
813     /* If stream_id != -1, we have dispatched request HEADERS, and now
814        are going to send or sending request body in DATA frame */
815     httpc->upload_mem = mem;
816     httpc->upload_len = len;
817     nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
818     rv = nghttp2_session_send(httpc->h2);
819     if(nghttp2_is_fatal(rv)) {
820       *err = CURLE_SEND_ERROR;
821       return -1;
822     }
823     return len - httpc->upload_len;
824   }
825
826   /* Calculate number of headers contained in [mem, mem + len) */
827   /* Here, we assume the curl http code generate *correct* HTTP header
828      field block */
829   nheader = 0;
830   for(i = 0; i < len; ++i) {
831     if(hdbuf[i] == 0x0a) {
832       ++nheader;
833     }
834   }
835   /* We counted additional 2 \n in the first and last line. We need 3
836      new headers: :method, :path and :scheme. Therefore we need one
837      more space. */
838   nheader += 1;
839   nva = malloc(sizeof(nghttp2_nv) * nheader);
840   if(nva == NULL) {
841     *err = CURLE_OUT_OF_MEMORY;
842     return -1;
843   }
844   /* Extract :method, :path from request line */
845   end = strchr(hdbuf, ' ');
846   nva[0].name = (unsigned char *)":method";
847   nva[0].namelen = (uint16_t)strlen((char *)nva[0].name);
848   nva[0].value = (unsigned char *)hdbuf;
849   nva[0].valuelen = (uint16_t)(end - hdbuf);
850   nva[0].flags = NGHTTP2_NV_FLAG_NONE;
851
852   hdbuf = end + 1;
853
854   end = strchr(hdbuf, ' ');
855   nva[1].name = (unsigned char *)":path";
856   nva[1].namelen = (uint16_t)strlen((char *)nva[1].name);
857   nva[1].value = (unsigned char *)hdbuf;
858   nva[1].valuelen = (uint16_t)(end - hdbuf);
859   nva[1].flags = NGHTTP2_NV_FLAG_NONE;
860
861   nva[2].name = (unsigned char *)":scheme";
862   nva[2].namelen = (uint16_t)strlen((char *)nva[2].name);
863   if(conn->handler->flags & PROTOPT_SSL)
864     nva[2].value = (unsigned char *)"https";
865   else
866     nva[2].value = (unsigned char *)"http";
867   nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value);
868   nva[2].flags = NGHTTP2_NV_FLAG_NONE;
869
870   hdbuf = strchr(hdbuf, 0x0a);
871   ++hdbuf;
872
873   authority_idx = 0;
874
875   for(i = 3; i < nheader; ++i) {
876     end = strchr(hdbuf, ':');
877     assert(end);
878     if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
879       authority_idx = i;
880       nva[i].name = (unsigned char *)":authority";
881       nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
882     }
883     else {
884       nva[i].name = (unsigned char *)hdbuf;
885       nva[i].namelen = (uint16_t)(end - hdbuf);
886     }
887     hdbuf = end + 1;
888     for(; *hdbuf == ' '; ++hdbuf);
889     end = strchr(hdbuf, 0x0d);
890     assert(end);
891     nva[i].value = (unsigned char *)hdbuf;
892     nva[i].valuelen = (uint16_t)(end - hdbuf);
893     nva[i].flags = NGHTTP2_NV_FLAG_NONE;
894
895     hdbuf = end + 2;
896     /* Inspect Content-Length header field and retrieve the request
897        entity length so that we can set END_STREAM to the last DATA
898        frame. */
899     if(nva[i].namelen == 14 &&
900        Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
901       size_t j;
902       for(j = 0; j < nva[i].valuelen; ++j) {
903         httpc->upload_left *= 10;
904         httpc->upload_left += nva[i].value[j] - '0';
905       }
906       infof(conn->data, "request content-length=%zu\n", httpc->upload_left);
907     }
908   }
909
910   /* :authority must come before non-pseudo header fields */
911   if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
912     nghttp2_nv authority = nva[authority_idx];
913     for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
914       nva[i] = nva[i - 1];
915     }
916     nva[i] = authority;
917   }
918
919   switch(conn->data->set.httpreq) {
920   case HTTPREQ_POST:
921   case HTTPREQ_POST_FORM:
922   case HTTPREQ_PUT:
923     data_prd.read_callback = data_source_read_callback;
924     data_prd.source.ptr = NULL;
925     stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
926                                        &data_prd, NULL);
927     break;
928   default:
929     stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
930                                        NULL, NULL);
931   }
932
933   Curl_safefree(nva);
934
935   if(stream_id < 0) {
936     *err = CURLE_SEND_ERROR;
937     return -1;
938   }
939
940   httpc->stream_id = stream_id;
941
942   rv = nghttp2_session_send(httpc->h2);
943
944   if(rv != 0) {
945     *err = CURLE_SEND_ERROR;
946     return -1;
947   }
948
949   if(httpc->stream_id != -1) {
950     /* If whole HEADERS frame was sent off to the underlying socket,
951        the nghttp2 library calls data_source_read_callback. But only
952        it found that no data available, so it deferred the DATA
953        transmission. Which means that nghttp2_session_want_write()
954        returns 0 on http2_perform_getsock(), which results that no
955        writable socket check is performed. To workaround this, we
956        issue nghttp2_session_resume_data() here to bring back DATA
957        transmission from deferred state. */
958     nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
959   }
960
961   return len;
962 }
963
964 CURLcode Curl_http2_setup(struct connectdata *conn)
965 {
966   struct http_conn *httpc = &conn->proto.httpc;
967   if(conn->handler->flags & PROTOPT_SSL)
968     conn->handler = &Curl_handler_http2_ssl;
969   else
970     conn->handler = &Curl_handler_http2;
971
972   infof(conn->data, "Using HTTP2\n");
973   httpc->bodystarted = FALSE;
974   httpc->closed = FALSE;
975   httpc->header_recvbuf = Curl_add_buffer_init();
976   httpc->nread_header_recvbuf = 0;
977   httpc->data = NULL;
978   httpc->datalen = 0;
979   httpc->upload_left = 0;
980   httpc->upload_mem = NULL;
981   httpc->upload_len = 0;
982   httpc->stream_id = -1;
983   httpc->status_code = -1;
984
985   conn->httpversion = 20;
986
987   return 0;
988 }
989
990 CURLcode Curl_http2_switched(struct connectdata *conn,
991                              const char *mem, size_t nread)
992 {
993   CURLcode result;
994   struct http_conn *httpc = &conn->proto.httpc;
995   int rv;
996   struct SessionHandle *data = conn->data;
997
998   httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
999   httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
1000   conn->recv[FIRSTSOCKET] = http2_recv;
1001   conn->send[FIRSTSOCKET] = http2_send;
1002
1003   rv = (int) ((Curl_send*)httpc->send_underlying)
1004     (conn, FIRSTSOCKET,
1005      NGHTTP2_CLIENT_CONNECTION_PREFACE,
1006      NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN,
1007      &result);
1008   if(result)
1009     /* TODO: This may get CURLE_AGAIN */
1010     return result;
1011
1012   if(rv != 24) {
1013     failf(data, "Only sent partial HTTP2 packet");
1014     return CURLE_SEND_ERROR;
1015   }
1016
1017   if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
1018     /* stream 1 is opened implicitly on upgrade */
1019     httpc->stream_id = 1;
1020     /* queue SETTINGS frame (again) */
1021     rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
1022                                  httpc->binlen, NULL);
1023     if(rv != 0) {
1024       failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
1025             nghttp2_strerror(rv), rv);
1026       return CURLE_HTTP2;
1027     }
1028   }
1029   else {
1030     /* stream ID is unknown at this point */
1031     httpc->stream_id = -1;
1032     rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
1033     if(rv != 0) {
1034       failf(data, "nghttp2_submit_settings() failed: %s(%d)",
1035             nghttp2_strerror(rv), rv);
1036       return CURLE_HTTP2;
1037     }
1038   }
1039
1040   rv = (int)nghttp2_session_mem_recv(httpc->h2, (const uint8_t*)mem, nread);
1041
1042   if(rv != (int)nread) {
1043     failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
1044           nghttp2_strerror(rv), rv);
1045     return CURLE_HTTP2;
1046   }
1047
1048   return CURLE_OK;
1049 }
1050
1051 #endif