summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/http2.c
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2015-07-25 13:12:20 +0000
committerGeorge Hazan <george.hazan@gmail.com>2015-07-25 13:12:20 +0000
commitdae9bc184b44c2b0c70b7996f202d6a7fa2dd4a4 (patch)
tree2aa80518d791c24e939e6525901da4dea39d46df /libs/libcurl/src/http2.c
parentbc55bf103dc79145ddd24e93a8f96fc6e8cf46d7 (diff)
libcurl extracted to the separate lib
git-svn-id: http://svn.miranda-ng.org/main/trunk@14683 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'libs/libcurl/src/http2.c')
-rw-r--r--libs/libcurl/src/http2.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
new file mode 100644
index 0000000000..b876436e1a
--- /dev/null
+++ b/libs/libcurl/src/http2.c
@@ -0,0 +1,182 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NGHTTP2
+#define _MPRINTF_REPLACE
+#include <curl/mprintf.h>
+
+#include <nghttp2/nghttp2.h>
+#include "urldata.h"
+#include "http2.h"
+#include "http.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "curl_memory.h"
+
+/* include memdebug.h last */
+#include "memdebug.h"
+
+/*
+ * Store nghttp2 version info in this buffer, Prefix with a space. Return
+ * total length written.
+ */
+int Curl_http2_ver(char *p, size_t len)
+{
+ nghttp2_info *h2 = nghttp2_version(0);
+ return snprintf(p, len, " nghttp2/%s", h2->version_str);
+}
+
+/*
+ * The implementation of nghttp2_send_callback type. Here we write |data| with
+ * size |length| to the network and return the number of bytes actually
+ * written. See the documentation of nghttp2_send_callback for the details.
+ */
+static ssize_t send_callback(nghttp2_session *h2,
+ const uint8_t *data, size_t length, int flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ ssize_t written;
+ CURLcode rc =
+ Curl_write(conn, conn->sock[0], data, length, &written);
+ (void)h2;
+ (void)flags;
+
+ if(rc) {
+ failf(conn->data, "Failed sending HTTP2 data");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ else if(!written)
+ return NGHTTP2_ERR_WOULDBLOCK;
+
+ return written;
+}
+
+/*
+ * The implementation of nghttp2_recv_callback type. Here we read data from
+ * the network and write them in |buf|. The capacity of |buf| is |length|
+ * bytes. Returns the number of bytes stored in |buf|. See the documentation
+ * of nghttp2_recv_callback for the details.
+ */
+static ssize_t recv_callback(nghttp2_session *h2,
+ uint8_t *buf, size_t length, int flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ ssize_t nread;
+ CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread);
+ (void)h2;
+ (void)flags;
+
+ if(rc) {
+ failf(conn->data, "Failed recving HTTP2 data");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ if(!nread)
+ return NGHTTP2_ERR_WOULDBLOCK;
+
+ return nread;
+}
+
+/*
+ * This is all callbacks nghttp2 calls
+ */
+static const nghttp2_session_callbacks callbacks = {
+ send_callback,
+ recv_callback,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * The HTTP2 settings we send in the Upgrade request
+ */
+static nghttp2_settings_entry settings[] = {
+ { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
+ { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+};
+
+/*
+ * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
+ */
+CURLcode Curl_http2_request(Curl_send_buffer *req,
+ struct connectdata *conn)
+{
+ uint8_t binsettings[80];
+ CURLcode result;
+ ssize_t binlen;
+ char *base64;
+ size_t blen;
+
+ if(!conn->proto.httpc.h2) {
+ /* The nghttp2 session is not yet setup, do it */
+ int rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
+ &callbacks, &conn);
+ if(rc) {
+ failf(conn->data, "Couldn't initialize nghttp2!");
+ return CURLE_OUT_OF_MEMORY; /* most likely at least */
+ }
+ }
+
+ /* As long as we have a fixed set of settings, we don't have to dynamically
+ * figure out the base64 strings since it'll always be the same. However,
+ * the settings will likely not be fixed every time in the future.
+ */
+
+ /* this returns number of bytes it wrote */
+ binlen = nghttp2_pack_settings_payload(binsettings,
+ sizeof(binsettings),
+ settings,
+ sizeof(settings)/sizeof(settings[0]));
+ if(!binlen) {
+ failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ return CURLE_FAILED_INIT;
+ }
+
+ result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
+ &base64, &blen);
+ if(result)
+ return result;
+
+ result = Curl_add_bufferf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_PROTO_VERSION_ID, base64);
+ free(base64);
+
+ return result;
+}
+
+#endif