vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
