[vlc-devel] [PATCH] access/http: Persist cookies in the libvlc instance

Rémi Denis-Courmont remi at remlab.net
Mon Aug 11 18:10:12 CEST 2014


Le lundi 11 août 2014, 18:58:21 Antti Ajanki a écrit :
> Cookies are shared between all HTTP requests in a libvlc session.
> Sharing of cookies is 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 fragment requests.
> ---
>  NEWS                         |    3 ++-
>  modules/access/http.c        |   25 +++++++++--------------
>  modules/access/httpcookies.c |   46
> ++++++++++++++++++++++++++++++++---------- modules/access/httpcookies.h |  
>  2 +-
>  src/Makefile.am              |    1 +
>  src/libvlc.c                 |    5 +++++
>  6 files changed, 53 insertions(+), 29 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index f1e6256..5c3f092 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -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 HTTP cookie handling (persist cookies during a
> libvlc +   session, domain / path matching, Secure cookies)
> 
>  Decoder:
>   * OMX GPU-zerocopy support for decoding and display on Android using
> OpenMax IL diff --git a/modules/access/http.c b/modules/access/http.c
> index 8b0b305..3ed16be 100644
> --- a/modules/access/http.c
> +++ b/modules/access/http.c
> @@ -179,19 +179,19 @@ struct access_sys_t
>      uint64_t i_remaining;
>      uint64_t size;
> 
> +    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;
> -
> -    http_cookie_jar_t * cookies;
>  };
> 
>  /* */
> -static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
> -                            unsigned i_redirect, http_cookie_jar_t *cookies
> ); +static int OpenWithRedirects( vlc_object_t *p_this, const char
> *psz_access, +                              unsigned i_redirect );
> 
>  /* */
>  static ssize_t Read( access_t *, uint8_t *, size_t );
> @@ -216,7 +216,7 @@ 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 OpenWithRedirects( p_this, p_access->psz_access, 5 );
>  }
> 
>  /**
> @@ -225,11 +225,10 @@ static int Open( vlc_object_t *p_this )
>   * @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, http_cookie_jar_t *cookies
> ) +static int OpenWithRedirects( 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;
> @@ -279,7 +278,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 : http_cookies_new();
> +        p_sys->cookies = var_GetAddress( p_access->p_libvlc, "http-cookies"
> ); else
>          p_sys->cookies = NULL;
> 
> @@ -510,15 +509,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 OpenWithRedirects( p_this, psz_protocol, i_redirect - 1 );
>      }
> 
>      if( p_sys->b_mms )
> @@ -597,8 +594,6 @@ error:
>      Disconnect( p_access );
>      vlc_tls_Delete( p_sys->p_creds );
> 
> -    http_cookies_destroy( p_sys->cookies );
> -
>  #ifdef HAVE_ZLIB_H
>      inflateEnd( &p_sys->inflate.stream );
>  #endif
> @@ -633,8 +628,6 @@ static void Close( vlc_object_t *p_this )
>      Disconnect( p_access );
>      vlc_tls_Delete( p_sys->p_creds );
> 
> -    http_cookies_destroy( p_sys->cookies );
> -
>  #ifdef HAVE_ZLIB_H
>      inflateEnd( &p_sys->inflate.stream );
>      free( p_sys->inflate.p_buffer );
> diff --git a/modules/access/httpcookies.c b/modules/access/httpcookies.c
> index 2dc0a6b..dcef50d 100644
> --- a/modules/access/httpcookies.c
> +++ b/modules/access/httpcookies.c
> @@ -45,6 +45,12 @@ typedef struct http_cookie_t
>      bool b_secure;
>  } http_cookie_t;
> 
> +struct 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 );
> 
>  http_cookie_jar_t * http_cookies_new()
>  {
> -    return vlc_array_new();
> +    http_cookie_jar_t * jar = malloc( sizeof( http_cookie_jar_t ) );
> +    if ( !jar )
> +        return NULL;
> +
> +    vlc_array_init( &jar->cookies );
> +    vlc_mutex_init( &jar->lock );
> +
> +    return jar;
>  }
> 
>  void http_cookies_destroy( http_cookie_jar_t * p_jar )
> @@ -69,9 +82,11 @@ void http_cookies_destroy( 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 http_cookies_append( http_cookie_jar_t * p_jar, const char *
> psz_cookie_header, const vlc_url_t *p_url ) @@ -85,9 +100,11 @@ bool
> http_cookies_append( http_cookie_jar_t * p_jar, const char * psz_cookie_hea
> 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 http_cookies_append( http_cookie_jar_t * p_jar,
> const char * psz_cookie_hea 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 *http_cookies_for_url( 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 *http_cookies_for_url( http_cookie_jar_t * p_jar,
> const vlc_url_t * p_url ) {
>                  // TODO: report error
>                  free( psz_cookiebuf );
> +                vlc_mutex_unlock( &p_jar->lock );
>                  return NULL;
>              }
>              free( psz_cookiebuf );
> @@ -136,6 +158,8 @@ char *http_cookies_for_url( http_cookie_jar_t * p_jar,
> const vlc_url_t * p_url ) }
>      }
> 
> +    vlc_mutex_unlock( &p_jar->lock );
> +
>      return psz_cookiebuf;
>  }
> 
> diff --git a/modules/access/httpcookies.h b/modules/access/httpcookies.h
> index bf73191..21311d6 100644
> --- a/modules/access/httpcookies.h
> +++ b/modules/access/httpcookies.h
> @@ -31,7 +31,7 @@ extern "C" {
>  #include <vlc_url.h>
>  #include <vlc_arrays.h>
> 
> -typedef struct vlc_array_t http_cookie_jar_t;
> +typedef struct http_cookie_jar_t http_cookie_jar_t;
> 
>  http_cookie_jar_t * http_cookies_new( void );
>  void http_cookies_destroy( http_cookie_jar_t * p_jar );
> diff --git a/src/Makefile.am b/src/Makefile.am
> index fbe7ec2..3f57bfe 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -484,6 +484,7 @@ SOURCES_libvlc_common = \
>  	misc/text_style.c \
>  	misc/subpicture.c \
>  	misc/subpicture.h \
> +	../modules/access/httpcookies.c \

In my experience, this will break recursive GNU/automake.

>  	$(NULL)
> 
>  SOURCES_libvlc_httpd = \
> diff --git a/src/libvlc.c b/src/libvlc.c
> index 946ce2e..5751eb1 100644
> --- a/src/libvlc.c
> +++ b/src/libvlc.c
> @@ -69,6 +69,7 @@
>  #include "libvlc.h"
>  #include "playlist/playlist_internal.h"
>  #include "misc/variables.h"
> +#include "../modules/access/httpcookies.h"
> 
>  #include <vlc_vlm.h>
> 
> @@ -389,6 +390,8 @@ dbus_out:
>      var_Create( p_libvlc, "http-user-agent", VLC_VAR_STRING );
>      var_SetString( p_libvlc, "http-user-agent",
>                     "VLC/"PACKAGE_VERSION" LibVLC/"PACKAGE_VERSION );
> +    var_Create( p_libvlc, "http-cookies", VLC_VAR_ADDRESS );
> +    var_SetAddress( p_libvlc, "http-cookies", http_cookies_new() );

I would rather have expected this on the owner of the input thread (e.g. the 
playlist) rather than the whole VLC instance.

>      var_Create( p_libvlc, "app-icon-name", VLC_VAR_STRING );
>      var_SetString( p_libvlc, "app-icon-name", PACKAGE_NAME );
>      var_Create( p_libvlc, "app-id", VLC_VAR_STRING );
> @@ -547,6 +550,8 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
> 
>      vlc_DeinitActions( p_libvlc, priv->actions );
> 
> +    http_cookies_destroy( var_GetAddress( p_libvlc, "http-cookies" ) );
> +
>      /* Save the configuration */
>      if( !var_InheritBool( p_libvlc, "ignore-config" ) )
>          config_AutoSaveConfigFile( VLC_OBJECT(p_libvlc) );

-- 
Rémi Denis-Courmont
http://www.remlab.net/




More information about the vlc-devel mailing list