[vlc-commits] HTTP connection manager preliminary implementation

Rémi Denis-Courmont git at videolan.org
Sun Dec 13 17:20:30 CET 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Dec  5 17:15:40 2015 +0200| [c14323135d68539b7fd507022e8cf865378300b5] | committer: Rémi Denis-Courmont

HTTP connection manager preliminary implementation

This would keep track of HTTP(S) connections to enable reuse (HTTP 1)
or multiplexing (HTTP 2). Initially, the connection manager will be
scoped to the access module, so it only handles a single authority
and a single pending request.

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

 modules/access/http/connmgr.c |  223 +++++++++++++++++++++++++++++++++++++++++
 modules/access/http/connmgr.h |   29 ++++++
 2 files changed, 252 insertions(+)

diff --git a/modules/access/http/connmgr.c b/modules/access/http/connmgr.c
new file mode 100644
index 0000000..3d4f9b4
--- /dev/null
+++ b/modules/access/http/connmgr.c
@@ -0,0 +1,223 @@
+/*****************************************************************************
+ * connmgr.c: HTTP/TLS VLC connection manager
+ *****************************************************************************
+ * Copyright © 2015 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <vlc_common.h>
+#include <vlc_tls.h>
+#include <vlc_interrupt.h>
+#include "transport.h"
+#include "h2conn.h"
+#include "connmgr.h"
+#include "message.h"
+
+#pragma GCC visibility push(default)
+
+struct vlc_https_connecting
+{
+    vlc_tls_creds_t *creds;
+    const char *host;
+    unsigned port;
+    bool http2;
+    vlc_sem_t done;
+};
+
+static void *vlc_https_connect_thread(void *data)
+{
+    struct vlc_https_connecting *c = data;
+    vlc_tls_t *tls;
+
+    tls = vlc_https_connect(c->creds, c->host, c->port, &c->http2);
+    vlc_sem_post(&c->done);
+    return tls;
+}
+
+/** Interruptible vlc_https_connect() */
+static vlc_tls_t *vlc_https_connect_i11e(vlc_tls_creds_t *creds,
+                                         const char *host, unsigned port,
+                                         bool *restrict http_two)
+{
+    struct vlc_https_connecting c;
+    vlc_thread_t th;
+
+    c.creds = creds;
+    c.host = host;
+    c.port = port;
+    vlc_sem_init(&c.done, 0);
+
+    if (vlc_clone(&th, vlc_https_connect_thread, &c,
+                  VLC_THREAD_PRIORITY_INPUT))
+        return NULL;
+
+    /* This would be much simpler if vlc_join_i11e() existed. */
+    void *res;
+
+    if (vlc_sem_wait_i11e(&c.done))
+        vlc_cancel(th);
+    vlc_join(th, &res);
+    vlc_sem_destroy(&c.done);
+
+    if (res == VLC_THREAD_CANCELED)
+        res = NULL;
+    if (res != NULL)
+        *http_two = c.http2;
+    return res;
+}
+
+struct vlc_http_mgr
+{
+    vlc_tls_creds_t *creds;
+    struct vlc_h1_conn *conn1;
+    struct vlc_h2_conn *conn2;
+};
+
+static struct vlc_h1_conn *vlc_h1_conn_find(struct vlc_http_mgr *mgr,
+                                            const char *host, unsigned port)
+{
+    (void) host; (void) port;
+    return mgr->conn1;
+}
+
+static struct vlc_h2_conn *vlc_h2_conn_find(struct vlc_http_mgr *mgr,
+                                            const char *host, unsigned port)
+{
+    (void) host; (void) port;
+    return mgr->conn2;
+}
+
+static
+struct vlc_http_msg *vlc_https_request_reuse(struct vlc_http_mgr *mgr,
+                                             const char *host, unsigned port,
+                                             const struct vlc_http_msg *req)
+{
+    struct vlc_h2_conn *conn2 = vlc_h2_conn_find(mgr, host, port);
+    if (conn2 != NULL)
+    {
+        struct vlc_http_stream *s = vlc_h2_stream_open(conn2, req);
+        if (s != NULL)
+        {
+            struct vlc_http_msg *m = vlc_http_stream_read_headers(s);
+            if (m != NULL)
+                return m;
+
+            vlc_http_stream_close(s);
+            /* NOTE: If the request were not idempotent, NULL should be
+             * returned here. POST is not used/supported so far, and CONNECT is
+             * treated as if it were idempotent (which turns out OK here). */
+        }
+        /* Get rid of closing or reset connection */
+        vlc_h2_conn_release(conn2);
+        mgr->conn2 = NULL;
+    }
+
+    struct vlc_h1_conn *conn1 = vlc_h1_conn_find(mgr, host, port);
+    if (conn1 != NULL)
+    {
+#if 0
+        struct vlc_http_stream *s = vlc_h1_stream_open(conn2, req);
+        if (s != NULL)
+        {
+            struct vlc_http_msg *m = vlc_http_stream_read_headers(s);
+            if (m != NULL)
+                return m;
+
+            vlc_http_stream_close(s);
+        }
+        vlc_h1_conn_release(conn1);
+#endif
+        mgr->conn1 = NULL;
+    }
+    return NULL;
+}
+
+static struct vlc_h1_conn *vlc_h1_conn_create(vlc_tls_t *tls)
+{
+    msg_Err(tls, "HTTP/2 not supported, HTTP/1 not implemented");
+    return NULL;
+}
+
+static void vlc_h1_conn_release(struct vlc_h1_conn *conn)
+{
+    (void) conn;
+    vlc_assert_unreachable();
+}
+
+struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
+                                       const char *host, unsigned port,
+                                       const struct vlc_http_msg *req)
+{
+    /* TODO? non-idempotent request support */
+    struct vlc_http_msg *resp = vlc_https_request_reuse(mgr, host, port, req);
+    if (resp != NULL)
+        return resp;
+
+    bool http2;
+    vlc_tls_t *tls = vlc_https_connect_i11e(mgr->creds, host, port, &http2);
+
+    if (http2)
+    {
+        struct vlc_h2_conn *conn2 = vlc_h2_conn_create(tls);
+        if (likely(conn2 != NULL))
+            mgr->conn2 = conn2;
+        else
+            vlc_https_disconnect(tls);
+    }
+    else /* TODO: HTTP/1.x support */
+    {
+        struct vlc_h1_conn *conn1 = vlc_h1_conn_create(tls);
+        if (likely(conn1 != NULL))
+            mgr->conn1 = conn1;
+        else
+            vlc_https_disconnect(tls);
+    }
+
+    return vlc_https_request_reuse(mgr, host, port, req);
+}
+
+struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj)
+{
+    struct vlc_http_mgr *mgr = malloc(sizeof (*mgr));
+    if (unlikely(mgr == NULL))
+        return NULL;
+
+    mgr->creds = vlc_tls_ClientCreate(obj);
+    if (mgr->creds == NULL)
+    {
+        free(mgr);
+        return NULL;
+    }
+
+    mgr->conn1 = NULL;
+    mgr->conn2 = NULL;
+    return mgr;
+}
+
+void vlc_http_mgr_destroy(struct vlc_http_mgr *mgr)
+{
+    if (mgr->conn2 != NULL)
+        vlc_h2_conn_release(mgr->conn2);
+    if (mgr->conn1 != NULL)
+        vlc_h1_conn_release(mgr->conn1);
+    vlc_tls_Delete(mgr->creds);
+    free(mgr);
+}
diff --git a/modules/access/http/connmgr.h b/modules/access/http/connmgr.h
new file mode 100644
index 0000000..de9db2f
--- /dev/null
+++ b/modules/access/http/connmgr.h
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * connmgr.h: HTTP/TLS VLC connection manager declaration
+ *****************************************************************************
+ * Copyright © 2015 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+struct vlc_http_mgr;
+struct vlc_http_msg;
+
+struct vlc_http_msg *vlc_https_request(struct vlc_http_mgr *mgr,
+                                       const char *host, unsigned port,
+                                       const struct vlc_http_msg *req);
+
+struct vlc_http_mgr *vlc_http_mgr_create(vlc_object_t *obj);
+void vlc_http_mgr_destroy(struct vlc_http_mgr *mgr);



More information about the vlc-commits mailing list