[vlc-commits] http: add vlc_h1_request() for TCP Fast Open

Rémi Denis-Courmont git at videolan.org
Sat Mar 4 18:56:02 CET 2017


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Mar  4 19:11:22 2017 +0200| [af7d7c742ca2090272411dbfdaeaa8580372ff95] | committer: Rémi Denis-Courmont

http: add vlc_h1_request() for TCP Fast Open

...with insecure HTTP.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=af7d7c742ca2090272411dbfdaeaa8580372ff95
---

 modules/access/http/conn.h   | 36 +++++++++++++++++++++++++
 modules/access/http/h1conn.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+)

diff --git a/modules/access/http/conn.h b/modules/access/http/conn.h
index 27f0e31..1f6705f 100644
--- a/modules/access/http/conn.h
+++ b/modules/access/http/conn.h
@@ -66,6 +66,42 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, struct vlc_tls *,
 struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *,
                                          struct vlc_tls *);
 
+/**
+ * Sends an HTTP/1.x request through a new connection.
+ *
+ * This function resolves a the specified HTTP server hostname, establishes a
+ * connection to specified TCP port of the server, then sends an HTTP request.
+ * The connection is not protected with TLS.
+ *
+ * All those operations are combined in a single function call in order to
+ * support TCP Fast Open. That can save one round-trip when establishing a new
+ * HTTP connection.
+
+ * \note In the case of TLS, TCP Fast Open would convey the TLS Client Hello
+ * message rather than the HTTP request header. The HTTP request header can
+ * however be sent with the TLS False Start. This is handled by the TLS stack
+ * and does not require a combined function call.
+ *
+ * \param ctx opaque context pointer for the HTTP connection
+ * \param hostname HTTP server or proxy hostname to connect to
+ * \param port TCP port number to connect to
+ * \param proxy true of the hostname and port correspond to an HTTP proxy,
+ *              or false if they correspond to an HTTP origin server
+ * \param req HTTP request message
+ * \param idempotent whether the HTTP request is idempotent (e.g. GET),
+ *                   or not (e.g. POST)
+ * \param connp pointer to storage space for the established HTTP connection
+ *              (or NULL if the connection is not to be reused) [OUT]
+ *              can be NULL if the connection is not meant to be reused
+ * \return an HTTP stream on success, NULL on error
+ * \note *connp is undefined on error.
+ */
+struct vlc_http_stream *vlc_h1_request(void *ctx, const char *hostname,
+                                       unsigned port, bool proxy,
+                                       const struct vlc_http_msg *req,
+                                       bool idempotent,
+                                       struct vlc_http_conn **restrict connp);
+
 /** @} */
 
 /**
diff --git a/modules/access/http/h1conn.c b/modules/access/http/h1conn.c
index eaedcbf..963715f 100644
--- a/modules/access/http/h1conn.c
+++ b/modules/access/http/h1conn.c
@@ -338,3 +338,66 @@ struct vlc_http_conn *vlc_h1_conn_create(void *ctx, vlc_tls_t *tls, bool proxy)
 
     return &conn->conn;
 }
+
+struct vlc_http_stream *vlc_h1_request(void *ctx, const char *hostname,
+                                       unsigned port, bool proxy,
+                                       const struct vlc_http_msg *req,
+                                       bool idempotent,
+                                       struct vlc_http_conn **restrict connp)
+{
+    struct addrinfo hints =
+    {
+        .ai_socktype = SOCK_STREAM,
+        .ai_protocol = IPPROTO_TCP,
+    }, *res;
+
+    vlc_http_dbg(ctx, "resolving %s ...", hostname);
+
+    int val = vlc_getaddrinfo_i11e(hostname, port, &hints, &res);
+    if (val != 0)
+    {   /* TODO: C locale for gai_strerror() */
+        vlc_http_err(ctx, "cannot resolve %s: %s", hostname,
+                     gai_strerror(val));
+        return NULL;
+    }
+
+    for (const struct addrinfo *p = res; p != NULL; p = p->ai_next)
+    {
+        vlc_tls_t *tcp = vlc_tls_SocketOpenAddrInfo(p, idempotent);
+        if (tcp == NULL)
+        {
+            vlc_http_err(ctx, "socket error: %s", vlc_strerror_c(errno));
+            continue;
+        }
+
+        struct vlc_http_conn *conn = vlc_h1_conn_create(ctx, tcp, proxy);
+        if (unlikely(conn == NULL))
+        {
+            vlc_tls_SessionDelete(tcp);
+            continue;
+        }
+
+        /* Send the HTTP request */
+        struct vlc_http_stream *stream = vlc_http_stream_open(conn, req);
+
+        if (stream != NULL)
+        {
+            if (connp != NULL)
+                *connp = conn;
+            else
+                vlc_http_conn_release(conn);
+
+            freeaddrinfo(res);
+            return stream;
+        }
+
+        vlc_http_conn_release(conn);
+
+        if (!idempotent)
+            break; /* If the request is nonidempotent, it cannot be resent. */
+    }
+
+    /* All address info failed. */
+    freeaddrinfo(res);
+    return NULL;
+}



More information about the vlc-commits mailing list