From 25c1d3810f821550ed8653c54e962221a7f8aaf1 Mon Sep 17 00:00:00 2001
From: Fabian Frank <fabian@pagefault.de>
Date: Fri, 31 Jan 2014 03:06:34 -0800
Subject: [PATCH] http2: send GET request

initialize the connection with client header and
settings before sending the actual HTTP2 request.
verified with nghttpd on localhost, also tested
against twitter.

TODO:
1.cancel HTTP1 code in http.c after calling
http2_send_request.
2. initialize connection only once (keep state).
3. swap out send/recv callback while keeping
openssl/vtls in the loop for decryption. (today
Curl_http2_switched just removes the SSL functions)
---
 lib/http.c  |  3 +--
 lib/http2.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/lib/http.c b/lib/http.c
index 063e1fa..2cc172d 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1671,9 +1671,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   switch (conn->negnpn) {
     case NPN_HTTP2_DRAFT09:
       infof(data, "http, we have to use HTTP-draft-09/2\n");
-      Curl_http2_init(conn);
-      Curl_http2_switched(conn);
       Curl_http2_send_request(conn);
+      //return CURLE_OK;
       break;
     case NPN_HTTP1_1:
       /* continue with HTTP/1.1 when explicitly requested */
diff --git a/lib/http2.c b/lib/http2.c
index b54df25..07302e7 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -93,6 +93,9 @@ static ssize_t send_callback(nghttp2_session *h2,
   (void)h2;
   (void)flags;
 
+  infof(conn->data, "send_callback should write %d "
+        "and wrote %d bytes\n", length, written);
+
   if(rc) {
     failf(conn->data, "Failed sending HTTP2 data");
     return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -298,12 +301,59 @@ CURLcode Curl_http2_init(struct connectdata *conn) {
   return CURLE_OK;
 }
 
+
+#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
+#define MAKE_NV(NAME, VALUE, VALUELEN)                                  \
+{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN }
+
+#define MAKE_NV2(NAME, VALUE)                                           \
+{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 }
+
 /*
  * Send a request using http2
  */
 CURLcode Curl_http2_send_request(struct connectdata *conn)
 {
-  (void)conn;
+  long written = 0;
+  int res;
+  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+
+  Curl_http2_init(conn);
+
+  /* magic client header, todo: only once per TCP stream */
+  res = Curl_write(conn, conn->sock[FIRSTSOCKET],
+                   NGHTTP2_CLIENT_CONNECTION_HEADER,
+                   NGHTTP2_CLIENT_CONNECTION_HEADER_LEN, &written);
+  if(res) {
+    failf(conn->data, "http2, failed to send client header\n");
+  }
+  infof(conn->data, "http2, sent client header, wrote %d bytes\n", written);
+
+  /* http2 settings, todo: only once per TCP stream */
+  res = nghttp2_submit_settings(conn->proto.httpc.h2, NGHTTP2_FLAG_NONE,
+                                settings,
+                                sizeof(settings)/sizeof(settings[0]));
+  if(res) {
+    failf(conn->data, "http2, failed to send client settings\n");
+  }
+  infof(conn->data, "http2, client settings sent\n");
+
+  nghttp2_nv hdrs[] = {
+    MAKE_NV2(":method", "GET"),
+    MAKE_NV(":scheme",
+            "https", 5),
+    MAKE_NV(":authority", conn->host.name, strlen(conn->host.name)),
+    MAKE_NV(":path", conn->data->state.path, strlen(conn->data->state.path))
+  };
+
+  res = nghttp2_submit_request(conn->proto.httpc.h2, NGHTTP2_PRI_DEFAULT,
+                              hdrs, ARRLEN(hdrs), NULL, conn->data);
+  if(res) {
+    failf(conn->data, "http2, failed to submit request\n");
+  }
+  infof(conn->data, "http2, request sent\n");
+  nghttp2_session_send(conn->proto.httpc.h2);
+
   return CURLE_OK;
 }
 
@@ -418,6 +468,8 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
 static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
 {
+  infof(conn->data, "http2_send() called\n");
+
   /* TODO: proper implementation */
   (void)conn;
   (void)sockindex;
-- 
1.8.3.2

