]> git.sesse.net Git - vlc/commitdiff
access/http: Share cookies between all playlist items
authorAntti Ajanki <antti.ajanki@iki.fi>
Tue, 16 Sep 2014 18:24:41 +0000 (21:24 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 16 Sep 2014 20:31:49 +0000 (23:31 +0300)
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 <remi@remlab.net>
NEWS
include/vlc_http.h
modules/access/http.c
src/misc/httpcookies.c
src/playlist/engine.c

diff --git a/NEWS b/NEWS
index d56b0141d032f645abd40783e7c241a26d51c677..4ba274182814e53b8981ba9ce9502140071166fd 100644 (file)
--- 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
index 47e3139e275d89f040da31cf872fb0ccb38c99fd..ab04a8aab8b1cc6b01a6484627c8aed2fe35d815 100644 (file)
@@ -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 );
index 37df2337967db389a1414ab8de20fcf3ad8daa70..6148b95c5eb9fb77c88ddb5604482e4ff2f9ff79 100644 (file)
@@ -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;
+}
index 9eccbe74860ddf2602a9ba583f63f7de4f1a1349..2ec3d33707901d340b034a245ba6000d70f62402 100644 (file)
@@ -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;
 }
 
index de1f76b179ea6a401b7c74427685ef83b9d334a4..ca342a955152f994f78f73da3808e91083b3e1f2 100644 (file)
@@ -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 );
 }