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).
This commit is contained in:
Rémi Denis-Courmont 2015-10-22 21:48:16 +03:00
parent f1cdb745c7
commit 0506fdb335
2 changed files with 76 additions and 38 deletions

View File

@ -113,6 +113,15 @@ struct access_t
input_thread_t *p_input;
};
/**
* 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.
*

View File

@ -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;