[vlc-commits] input: support for (inter-)access redirection

Rémi Denis-Courmont git at videolan.org
Thu Oct 22 21:45:25 CEST 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu Oct 22 21:48:16 2015 +0300| [0506fdb335f4cb8dbd569b5d86667bdd80836cdc] | committer: Rémi Denis-Courmont

input: support for (inter-)access redirection

Handling the redirection in the access core enables support for
redirection between different protocols (e.g. HTTP to FTP) and more
generally different access plugins (e.g. HTTP to HTTP2 in future).

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

 include/vlc_access.h |    9 +++++
 src/input/access.c   |  105 ++++++++++++++++++++++++++++++++------------------
 2 files changed, 76 insertions(+), 38 deletions(-)

diff --git a/include/vlc_access.h b/include/vlc_access.h
index 6663c08..e90edf1 100644
--- a/include/vlc_access.h
+++ b/include/vlc_access.h
@@ -114,6 +114,15 @@ struct access_t
 };
 
 /**
+ * Special redirection error code.
+ *
+ * In case of redirection, the access open function should clean up (as in
+ * normal failure case), store the heap-allocated redirection URL in
+ * access_t.psz_url, and return this value.
+ */
+#define VLC_ACCESS_REDIRECT VLC_ETIMEOUT
+
+/**
  * Opens a new read-only byte stream.
  *
  * This function might block.
diff --git a/src/input/access.c b/src/input/access.c
index 70441bd..dd2c837 100644
--- a/src/input/access.c
+++ b/src/input/access.c
@@ -54,59 +54,89 @@ char *get_path(const char *location)
     return path;
 }
 
+#define MAX_REDIR 5
+
 /*****************************************************************************
  * access_New:
  *****************************************************************************/
 static access_t *access_New(vlc_object_t *parent, input_thread_t *input,
                             const char *mrl)
 {
-    const char *p = strstr(mrl, "://");
-    if (p == NULL)
-        return NULL;
+    char *redirv[MAX_REDIR];
+    unsigned redirc = 0;
 
     access_t *access = vlc_custom_create(parent, sizeof (*access), "access");
     if (unlikely(access == NULL))
         return NULL;
 
-    char *scheme = strndup(mrl, p - mrl);
-    char *url = strdup(mrl);
-
-    if (unlikely(scheme == NULL || url == NULL))
-    {
-        free(url);
-        free(scheme);
-        vlc_object_release(access);
-        return NULL;
-    }
-
     access->p_input = input;
-    access->psz_access = scheme;
-    access->psz_url = url;
-    access->psz_location = url + (p + 3 - mrl);
-    access->psz_filepath = get_path(access->psz_location);
-    access->pf_read    = NULL;
-    access->pf_block   = NULL;
+    access->psz_access = NULL;
+    access->psz_url = strdup(mrl);
+    access->psz_filepath = NULL;
+    access->pf_read = NULL;
+    access->pf_block = NULL;
     access->pf_readdir = NULL;
-    access->pf_seek    = NULL;
+    access->pf_seek = NULL;
     access->pf_control = NULL;
-    access->p_sys      = NULL;
+    access->p_sys = NULL;
     access_InitFields(access);
 
-    msg_Dbg(access, "creating access '%s' location='%s', path='%s'", scheme,
-            access->psz_location,
-            access->psz_filepath ? access->psz_filepath : "(null)");
+    if (unlikely(access->psz_url == NULL))
+        goto error;
 
-    access->p_module = module_need(access, "access", scheme, true);
-    if (access->p_module == NULL)
+    while (redirc < MAX_REDIR)
     {
-        free(access->psz_filepath);
-        free(access->psz_url);
-        free(access->psz_access);
-        vlc_object_release(access);
-        access = NULL;
+        char *url = access->psz_url;
+        msg_Dbg(access, "creating access: %s", url);
+
+        const char *p = strstr(url, "://");
+        if (p == NULL)
+            goto error;
+
+        access->psz_access = strndup(url, p - url);
+        if (unlikely(access->psz_access == NULL))
+            goto error;
+
+        access->psz_location = p + 3;
+        access->psz_filepath = get_path(access->psz_location);
+        if (access->psz_filepath != NULL)
+            msg_Dbg(access, " (path: %s)", access->psz_filepath);
+
+        access->p_module = module_need(access, "access", access->psz_access,
+                                       true);
+        if (access->p_module != NULL) /* success */
+        {
+            while (redirc > 0)
+                free(redirv[--redirc]);
+
+            assert(access->pf_control != NULL);
+            return access;
+        }
+
+        if (access->psz_url == url) /* failure (no redirection) */
+            goto error;
+
+        /* redirection */
+        msg_Dbg(access, "redirecting to: %s", access->psz_url);
+        redirv[redirc++] = url;
+
+        for (unsigned j = 0; j < redirc; j++)
+            if (!strcmp(redirv[j], access->psz_url))
+            {
+                msg_Err(access, "redirection loop");
+                goto error;
+            }
     }
-    assert(access == NULL || access->pf_control != NULL);
-    return access;
+
+    msg_Err(access, "too many redirections");
+error:
+    while (redirc > 0)
+        free(redirv[--redirc]);
+    free(access->psz_filepath);
+    free(access->psz_url);
+    free(access->psz_access);
+    vlc_object_release(access);
+    return NULL;
 }
 
 access_t *vlc_access_NewMRL(vlc_object_t *parent, const char *mrl)
@@ -351,11 +381,8 @@ stream_t *stream_AccessNew(vlc_object_t *parent, input_thread_t *input,
     if (unlikely(s == NULL))
         return NULL;
 
-    s->p_input = input;
-    s->psz_url = strdup(url);
-
     stream_sys_t *sys = malloc(sizeof (*sys));
-    if (unlikely(s->psz_url == NULL || sys == NULL))
+    if (unlikely(sys == NULL))
         goto error;
 
     sys->access = access_New(VLC_OBJECT(s), input, url);
@@ -363,6 +390,8 @@ stream_t *stream_AccessNew(vlc_object_t *parent, input_thread_t *input,
         goto error;
 
     sys->block = NULL;
+    s->p_input = input;
+    s->psz_url = strdup(sys->access->psz_url);
 
     const char *cachename;
 



More information about the vlc-commits mailing list