[vlc-commits] http: simplify and fix size handling (fixes #17540)

Rémi Denis-Courmont git at videolan.org
Tue Oct 25 14:10:19 CEST 2016


vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Oct 25 15:04:41 2016 +0300| [315d4c0a42479363b5027dfad59491c1c312f872] | committer: Rémi Denis-Courmont

http: simplify and fix size handling (fixes #17540)

The Content-Range header line indicates the size of the underlying
resource; it has bearings on the size of the response body at the
HTTP protocol level.

Also the start offset in the Content-Range should be ignored, as
overriding it can lead to unexpected situations in VLC. Only a broken
server will not match the requested value anyway.

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=315d4c0a42479363b5027dfad59491c1c312f872
---

 modules/access/http.c | 87 +++++++++++++++++++++++++--------------------------
 1 file changed, 42 insertions(+), 45 deletions(-)

diff --git a/modules/access/http.c b/modules/access/http.c
index 0abe269..1ccd8fd 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -175,7 +175,7 @@ struct access_sys_t
     char       *psz_icy_genre;
     char       *psz_icy_title;
 
-    uint64_t i_remaining;
+    uintmax_t i_remaining;
     uint64_t size;
 
     bool b_seekable;
@@ -183,7 +183,6 @@ struct access_sys_t
     bool b_continuous;
     bool b_pace_control;
     bool b_persist;
-    bool b_has_size;
 
     vlc_array_t * cookies;
 };
@@ -275,10 +274,9 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
     p_sys->psz_icy_name = NULL;
     p_sys->psz_icy_genre = NULL;
     p_sys->psz_icy_title = NULL;
-    p_sys->i_remaining = 0;
+    p_sys->i_remaining = -1;
     p_sys->b_persist = false;
-    p_sys->b_has_size = false;
-    p_sys->size = 0;
+    p_sys->size = -1;
     p_access->info.i_pos  = 0;
     p_access->info.b_eof  = false;
 
@@ -724,15 +722,9 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
     if( p_sys->fd == -1 )
         goto fatal;
 
-    if( p_sys->b_has_size )
-    {
-        /* Remaining bytes in the file */
-        uint64_t remainder = p_sys->size - p_access->info.i_pos;
-        if( remainder < i_len )
-            i_len = remainder;
-
-        /* Remaining bytes in the response */
-        if( p_sys->i_remaining < i_len )
+    if( p_sys->i_remaining != UINTMAX_MAX )
+    {   /* Remaining bytes in the response */
+        if( i_len > p_sys->i_remaining )
             i_len = p_sys->i_remaining;
     }
     if( i_len == 0 )
@@ -798,9 +790,8 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
 
     assert( i_read >= 0 );
     p_access->info.i_pos += i_read;
-    if( p_sys->b_has_size )
+    if( p_sys->i_remaining != UINTMAX_MAX )
     {
-        assert( p_access->info.i_pos <= p_sys->size );
         assert( (unsigned)i_read <= p_sys->i_remaining );
         p_sys->i_remaining -= i_read;
     }
@@ -936,7 +927,7 @@ static int Seek( access_t *p_access, uint64_t i_pos )
     msg_Dbg( p_access, "trying to seek to %"PRId64, i_pos );
     Disconnect( p_access );
 
-    if( p_sys->size && i_pos >= p_sys->size )
+    if( p_sys->size != UINT64_MAX && i_pos >= p_sys->size )
     {
         msg_Err( p_access, "seek too far" );
         int retval = Seek( p_access, p_sys->size - 1 );
@@ -996,9 +987,10 @@ static int Control( access_t *p_access, int i_query, va_list args )
             break;
 
         case ACCESS_GET_SIZE:
-            pi_64 = (int64_t*)va_arg( args, int64_t * );
-            *pi_64 = p_sys->size;
-           break;
+            if( p_sys->size == UINT64_MAX )
+                return VLC_EGENERIC;
+            *va_arg( args, int64_t * ) = p_sys->size;
+            break;
 
         /* */
         case ACCESS_SET_PAUSE_STATE:
@@ -1045,10 +1037,9 @@ static int Connect( access_t *p_access, uint64_t i_tell )
     p_sys->psz_icy_name = NULL;
     p_sys->psz_icy_genre = NULL;
     p_sys->psz_icy_title = NULL;
-    p_sys->i_remaining = 0;
+    p_sys->i_remaining = -1;
     p_sys->b_persist = false;
-    p_sys->b_has_size = false;
-    p_sys->size = 0;
+    p_sys->size = -1;
     p_access->info.i_pos  = i_tell;
     p_access->info.b_eof  = false;
 
@@ -1149,7 +1140,7 @@ static int Request( access_t *p_access, uint64_t i_tell )
     v_socket_t     *pvs = p_sys->p_vs;
     p_sys->b_persist = false;
 
-    p_sys->i_remaining = 0;
+    p_sys->i_remaining = -1;
 
     const char *psz_path = p_sys->url.psz_path;
     if( !psz_path || !*psz_path )
@@ -1326,30 +1317,36 @@ static int Request( access_t *p_access, uint64_t i_tell )
 
         if( !strcasecmp( psz, "Content-Length" ) )
         {
-            uint64_t i_size = i_tell + (p_sys->i_remaining = (uint64_t)atoll( p ));
-            if(i_size > p_sys->size) {
-                p_sys->b_has_size = true;
-                p_sys->size = i_size;
+            if( sscanf( p, "%"SCNuMAX, &p_sys->i_remaining ) < 1 )
+            {
+                free( psz );
+                goto error;
             }
-            msg_Dbg( p_access, "this frame size=%"PRIu64, p_sys->i_remaining );
+
+            msg_Dbg( p_access, "response body size=%"PRIuMAX,
+                     p_sys->i_remaining );
+            if( p_sys->size == UINT64_MAX )
+                p_sys->size = i_tell + p_sys->i_remaining;
         }
         else if( !strcasecmp( psz, "Content-Range" ) ) {
-            uint64_t i_ntell = i_tell;
-            uint64_t i_nend = (p_sys->size > 0) ? (p_sys->size - 1) : i_tell;
-            uint64_t i_nsize = p_sys->size;
-            sscanf(p,"bytes %"SCNu64"-%"SCNu64"/%"SCNu64,&i_ntell,&i_nend,&i_nsize);
-            if(i_nend > i_ntell ) {
-                p_access->info.i_pos = i_ntell;
-                p_sys->i_icy_offset  = i_ntell;
-                p_sys->i_remaining = i_nend+1-i_ntell;
-                uint64_t i_size = (i_nsize > i_nend) ? i_nsize : (i_nend + 1);
-                if(i_size > p_sys->size) {
-                    p_sys->b_has_size = true;
-                    p_sys->size = i_size;
-                }
-                msg_Dbg( p_access, "stream size=%"PRIu64",pos=%"PRIu64",remaining=%"PRIu64,
-                         i_nsize, i_ntell, p_sys->i_remaining);
+            uint64_t end, size;
+
+            p_sys->size = -1;
+
+            switch( sscanf( p, "bytes %*u-%"SCNu64"/%"SCNu64, &end, &size ) )
+            {
+                case 1:
+                    if( unlikely(size == UINT64_MAX) )
+                        break;
+                    size = end + 1;
+                    /* fall through */
+                case 2:
+                    p_sys->size = size;
+                    msg_Dbg( p_access, "resource size=%"PRIu64, size );
+                    break;
             }
+
+            p_sys->i_icy_offset  = i_tell;
         }
         else if( !strcasecmp( psz, "Connection" ) ) {
             msg_Dbg( p_access, "Connection: %s",p );
@@ -1557,7 +1554,7 @@ static int Request( access_t *p_access, uint64_t i_tell )
     /* We close the stream for zero length data, unless of course the
      * server has already promised to do this for us.
      */
-    if( p_sys->b_has_size && p_sys->i_remaining == 0 && p_sys->b_persist ) {
+    if( p_sys->i_remaining == 0 && p_sys->b_persist ) {
         Disconnect( p_access );
     }
     return VLC_SUCCESS;



More information about the vlc-commits mailing list