[vlc-devel] [PATCH 2/2] access/http: Share cookies between all playlist items

Antti Ajanki antti.ajanki at iki.fi
Tue Sep 16 20:24:41 CEST 2014


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.
---
 NEWS                   |    3 ++-
 include/vlc_http.h     |    2 +-
 modules/access/http.c  |   49 +++++++++++++++++++++++++++++++-----------------
 src/misc/httpcookies.c |   48 +++++++++++++++++++++++++++++++++++------------
 src/playlist/engine.c  |   17 +++++++++++++++++
 5 files changed, 88 insertions(+), 31 deletions(-)

diff --git a/NEWS b/NEWS
index d56b014..4ba2741 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 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
diff --git a/include/vlc_http.h b/include/vlc_http.h
index 47e3139..ab04a8a 100644
--- a/include/vlc_http.h
+++ b/include/vlc_http.h
@@ -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 );
diff --git a/modules/access/http.c b/modules/access/http.c
index 37df233..6148b95 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -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;
+}
diff --git a/src/misc/httpcookies.c b/src/misc/httpcookies.c
index 9eccbe7..2ec3d33 100644
--- a/src/misc/httpcookies.c
+++ b/src/misc/httpcookies.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * 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;
 }
 
diff --git a/src/playlist/engine.c b/src/playlist/engine.c
index de1f76b..ca342a9 100644
--- a/src/playlist/engine.c
+++ b/src/playlist/engine.c
@@ -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 );
 }
 
-- 
1.7.10.4




More information about the vlc-devel mailing list