Commit 68699a32 authored by Antti Ajanki's avatar Antti Ajanki Committed by Rémi Denis-Courmont

access/http: Share cookies between all playlist items

Shared cookies are required, for example, by certain HDS and HLS streams
that set a cookie when the manifest is read and expect it to be sent
back on subsequent fragment requests.

The cookie jar is created during playlist initialization. HTTP requests
inherit the cookie jar from the playlist.
Signed-off-by: Rémi Denis-Courmont's avatarRémi Denis-Courmont <remi@remlab.net>
parent 18b4a0bf
......@@ -5,7 +5,8 @@ Access:
* Support HDS (Http Dynamic Streaming) from Adobe (f4m, f4v, etc.)
* New SMB access module using libdsm
* Support decompression and extraction through libarchive (tar, zip, rar...)
* Improvements of cookie handling (domain / path matching, Secure cookies)
* Improvements of cookie handling (share cookies between playlist items,
domain / path matching, Secure cookies)
Decoder:
* OMX GPU-zerocopy support for decoding and display on Android using OpenMax IL
......
......@@ -69,7 +69,7 @@ VLC_API char *http_auth_FormatAuthorizationHeader
/* RFC 6265: cookies */
typedef struct vlc_array_t vlc_http_cookie_jar_t;
typedef struct vlc_http_cookie_jar_t vlc_http_cookie_jar_t;
VLC_API vlc_http_cookie_jar_t * vlc_http_cookies_new( void ) VLC_USED;
VLC_API void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar );
......
......@@ -178,19 +178,20 @@ struct access_sys_t
uint64_t i_remaining;
uint64_t size;
/* cookie jar borrowed from playlist, do not free */
vlc_http_cookie_jar_t * cookies;
bool b_seekable;
bool b_reconnect;
bool b_continuous;
bool b_pace_control;
bool b_persist;
bool b_has_size;
vlc_http_cookie_jar_t * cookies;
};
/* */
static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
unsigned i_redirect, vlc_http_cookie_jar_t *cookies );
static int OpenRedirected( vlc_object_t *p_this, const char *psz_access,
unsigned i_redirect );
/* */
static ssize_t Read( access_t *, uint8_t *, size_t );
......@@ -208,6 +209,7 @@ static void AuthReply( access_t *p_acces, const char *psz_prefix,
vlc_url_t *p_url, http_auth_t *p_auth );
static int AuthCheckReply( access_t *p_access, const char *psz_header,
vlc_url_t *p_url, http_auth_t *p_auth );
static vlc_http_cookie_jar_t *GetCookieJar( vlc_object_t *p_this );
/*****************************************************************************
* Open:
......@@ -215,20 +217,19 @@ static int AuthCheckReply( access_t *p_access, const char *psz_header,
static int Open( vlc_object_t *p_this )
{
access_t *p_access = (access_t*)p_this;
return OpenWithCookies( p_this, p_access->psz_access, 5, NULL );
return OpenRedirected( p_this, p_access->psz_access, 5 );
}
/**
* Open the given url using the given cookies
* Open the given url with limited redirects
* @param p_this: the vlc object
* @psz_access: the acces to use (http, https, ...) (this value must be used
* instead of p_access->psz_access)
* @i_redirect: number of redirections remaining
* @cookies: the available cookies
* @return vlc error codes
*/
static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
unsigned i_redirect, vlc_http_cookie_jar_t *cookies )
static int OpenRedirected( vlc_object_t *p_this, const char *psz_access,
unsigned i_redirect )
{
access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys;
......@@ -278,7 +279,7 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
/* Only forward an store cookies if the corresponding option is activated */
if( var_CreateGetBool( p_access, "http-forward-cookies" ) )
p_sys->cookies = (cookies != NULL) ? cookies : vlc_http_cookies_new();
p_sys->cookies = GetCookieJar( p_this );
else
p_sys->cookies = NULL;
......@@ -509,15 +510,13 @@ connect:
Disconnect( p_access );
vlc_tls_Delete( p_sys->p_creds );
cookies = p_sys->cookies;
#ifdef HAVE_ZLIB_H
inflateEnd( &p_sys->inflate.stream );
#endif
free( p_sys );
/* Do new Open() run with new data */
return OpenWithCookies( p_this, psz_protocol, i_redirect - 1,
cookies );
return OpenRedirected( p_this, psz_protocol, i_redirect - 1 );
}
if( p_sys->b_mms )
......@@ -596,8 +595,6 @@ error:
Disconnect( p_access );
vlc_tls_Delete( p_sys->p_creds );
vlc_http_cookies_destroy( p_sys->cookies );
#ifdef HAVE_ZLIB_H
inflateEnd( &p_sys->inflate.stream );
#endif
......@@ -632,8 +629,6 @@ static void Close( vlc_object_t *p_this )
Disconnect( p_access );
vlc_tls_Delete( p_sys->p_creds );
vlc_http_cookies_destroy( p_sys->cookies );
#ifdef HAVE_ZLIB_H
inflateEnd( &p_sys->inflate.stream );
free( p_sys->inflate.p_buffer );
......@@ -1582,3 +1577,23 @@ static int AuthCheckReply( access_t *p_access, const char *psz_header,
p_url->psz_username,
p_url->psz_password );
}
/*****************************************************************************
* HTTP cookies
*****************************************************************************/
/**
* Inherit the cookie jar from the playlist
*
* @param p_this: http access object
* @return A borrowed reference to a vlc_http_cookie_jar_t, do not free
*/
static vlc_http_cookie_jar_t *GetCookieJar( vlc_object_t *p_this )
{
vlc_value_t val;
if ( var_Inherit( p_this, "http-cookies", VLC_VAR_ADDRESS, &val ) == VLC_SUCCESS )
return val.p_address;
else
return NULL;
}
/*****************************************************************************
* httpcookies.h: HTTP cookie utilities
* httpcookies.c: HTTP cookie utilities
*****************************************************************************
* Copyright (C) 2014 VLC authors and VideoLAN
* $Id$
......@@ -45,6 +45,12 @@ typedef struct http_cookie_t
bool b_secure;
} http_cookie_t;
struct vlc_http_cookie_jar_t
{
vlc_array_t cookies;
vlc_mutex_t lock;
};
static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t * url );
static void cookie_destroy( http_cookie_t * p_cookie );
static char * cookie_get_content( const char * cookie );
......@@ -60,7 +66,14 @@ static char * cookie_default_path( const char *request_path );
vlc_http_cookie_jar_t * vlc_http_cookies_new()
{
return vlc_array_new();
vlc_http_cookie_jar_t * jar = malloc( sizeof( vlc_http_cookie_jar_t ) );
if ( !jar )
return NULL;
vlc_array_init( &jar->cookies );
vlc_mutex_init( &jar->lock );
return jar;
}
void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar )
......@@ -69,9 +82,11 @@ void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar )
return;
int i;
for( i = 0; i < vlc_array_count( p_jar ); i++ )
cookie_destroy( vlc_array_item_at_index( p_jar, i ) );
vlc_array_destroy( p_jar );
for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ )
cookie_destroy( vlc_array_item_at_index( &p_jar->cookies, i ) );
vlc_array_clear( &p_jar->cookies );
vlc_mutex_destroy( &p_jar->lock );
}
bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_cookie_header, const vlc_url_t *p_url )
......@@ -85,9 +100,11 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co
return false;
}
for( i = 0; i < vlc_array_count( p_jar ); i++ )
vlc_mutex_lock( &p_jar->lock );
for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ )
{
http_cookie_t *iter = vlc_array_item_at_index( p_jar, i );
http_cookie_t *iter = vlc_array_item_at_index( &p_jar->cookies, i );
assert( iter->psz_name );
assert( iter->psz_domain );
......@@ -100,24 +117,28 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co
if( domains_match && paths_match && names_match )
{
/* Remove previous value for this cookie */
vlc_array_remove( p_jar, i );
vlc_array_remove( &p_jar->cookies, i );
cookie_destroy(iter);
break;
}
}
vlc_array_append( p_jar, cookie );
vlc_array_append( &p_jar->cookies, cookie );
vlc_mutex_unlock( &p_jar->lock );
return true;
}
char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * p_url )
{
int i;
char *psz_cookiebuf = NULL;
for( i = 0; i < vlc_array_count( p_jar ); i++ )
vlc_mutex_lock( &p_jar->lock );
for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ )
{
const http_cookie_t * cookie = vlc_array_item_at_index( p_jar, i );
const http_cookie_t * cookie = vlc_array_item_at_index( &p_jar->cookies, i );
if ( cookie_should_be_sent( cookie, p_url ) )
{
char *psz_updated_buf = NULL;
......@@ -129,6 +150,7 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t *
{
// TODO: report error
free( psz_cookiebuf );
vlc_mutex_unlock( &p_jar->lock );
return NULL;
}
free( psz_cookiebuf );
......@@ -136,6 +158,8 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t *
}
}
vlc_mutex_unlock( &p_jar->lock );
return psz_cookiebuf;
}
......
......@@ -32,6 +32,7 @@
#include <vlc_sout.h>
#include <vlc_playlist.h>
#include <vlc_interface.h>
#include <vlc_http.h>
#include "playlist_internal.h"
#include "input/resource.h"
......@@ -296,6 +297,15 @@ playlist_t *playlist_Create( vlc_object_t *p_parent )
if( aout != NULL )
input_resource_PutAout( p->p_input_resource, aout );
/* Initialize the shared HTTP cookie jar */
vlc_value_t cookies;
cookies.p_address = vlc_http_cookies_new();
if ( likely(cookies.p_address) )
{
var_Create( p_playlist, "http-cookies", VLC_VAR_ADDRESS );
var_SetChecked( p_playlist, "http-cookies", VLC_VAR_ADDRESS, cookies );
}
/* Thread */
playlist_Activate (p_playlist);
......@@ -366,6 +376,13 @@ void playlist_Destroy( playlist_t *p_playlist )
ARRAY_RESET( p_playlist->items );
ARRAY_RESET( p_playlist->current );
vlc_http_cookie_jar_t *cookies = var_GetAddress( p_playlist, "http-cookies" );
if ( cookies )
{
var_Destroy( p_playlist, "http-cookies" );
vlc_http_cookies_destroy( cookies );
}
vlc_object_release( p_playlist );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment