Commit 2c166875 authored by Bill C. Riemers's avatar Bill C. Riemers Committed by Rémi Denis-Courmont

http: fix Content-Length and stream closure issues.

Changes:
1. Don't send Connection: close or Connection: Keep-Alive.
    So we will maintain a persistent connection with HTTP 1.1.
2. Close the connection if and only if the server does not send
   Connection: close, and a zero length is received indicated by either
   Content-Length: 0 or a 0 length size in the byte range.
3. Correct i_remaining to deal with file larger than 2GBi.
4. Update i_remaining in Read and OpenWithCookies.
5. Use -1 for uninitialized size so we can tell the difference from a
   zero length result.
Signed-off-by: default avatarRémi Denis-Courmont <rdenis@simphalempin.com>
parent f5623dec
...@@ -188,12 +188,13 @@ struct access_sys_t ...@@ -188,12 +188,13 @@ struct access_sys_t
char *psz_icy_genre; char *psz_icy_genre;
char *psz_icy_title; char *psz_icy_title;
int i_remaining; int64_t i_remaining;
bool b_seekable; bool b_seekable;
bool b_reconnect; bool b_reconnect;
bool b_continuous; bool b_continuous;
bool b_pace_control; bool b_pace_control;
bool b_persist;
vlc_array_t * cookies; vlc_array_t * cookies;
}; };
...@@ -279,6 +280,10 @@ static int OpenWithCookies( vlc_object_t *p_this, vlc_array_t *cookies ) ...@@ -279,6 +280,10 @@ static int OpenWithCookies( vlc_object_t *p_this, vlc_array_t *cookies )
p_sys->psz_icy_genre = NULL; p_sys->psz_icy_genre = NULL;
p_sys->psz_icy_title = NULL; p_sys->psz_icy_title = NULL;
p_sys->i_remaining = 0; p_sys->i_remaining = 0;
p_sys->b_persist = false;
p_access->info.i_size = -1;
p_access->info.i_pos = 0;
p_access->info.b_eof = false;
p_sys->cookies = saved_cookies; p_sys->cookies = saved_cookies;
...@@ -638,7 +643,7 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len ) ...@@ -638,7 +643,7 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
return 0; return 0;
} }
if( p_access->info.i_size > 0 && if( p_access->info.i_size >= 0 &&
i_len + p_access->info.i_pos > p_access->info.i_size ) i_len + p_access->info.i_pos > p_access->info.i_size )
{ {
if( ( i_len = p_access->info.i_size - p_access->info.i_pos ) == 0 ) if( ( i_len = p_access->info.i_size - p_access->info.i_pos ) == 0 )
...@@ -682,20 +687,16 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len ) ...@@ -682,20 +687,16 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
i_len = p_sys->i_chunk; i_len = p_sys->i_chunk;
} }
} }
else if( p_access->info.i_size != -1 && (int64_t)i_len > p_sys->i_remaining) {
if( p_sys->b_continuous && (ssize_t)i_len > p_sys->i_remaining )
{
/* Only ask for the remaining length */ /* Only ask for the remaining length */
int i_new_len = p_sys->i_remaining; i_len = (size_t)p_sys->i_remaining;
if( i_new_len == 0 ) if(i_len == 0) {
{ p_access->info.b_eof = true;
Request( p_access, 0 ); return 0;
i_read = Read( p_access, p_buffer, i_len );
return i_read;
} }
i_len = i_new_len;
} }
if( p_sys->i_icy_meta > 0 && p_access->info.i_pos > 0 ) if( p_sys->i_icy_meta > 0 && p_access->info.i_pos > 0 )
{ {
int64_t i_next = p_sys->i_icy_meta - int64_t i_next = p_sys->i_icy_meta -
...@@ -764,7 +765,7 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len ) ...@@ -764,7 +765,7 @@ static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
if( i_read == 0 ) p_access->info.b_eof = true; if( i_read == 0 ) p_access->info.b_eof = true;
} }
if( p_sys->b_continuous ) if( p_access->info.i_size != -1 )
{ {
p_sys->i_remaining -= i_read; p_sys->i_remaining -= i_read;
} }
...@@ -1007,8 +1008,10 @@ static int Connect( access_t *p_access, int64_t i_tell ) ...@@ -1007,8 +1008,10 @@ static int Connect( access_t *p_access, int64_t i_tell )
p_sys->psz_icy_name = NULL; p_sys->psz_icy_name = NULL;
p_sys->psz_icy_genre = NULL; p_sys->psz_icy_genre = NULL;
p_sys->psz_icy_title = NULL; p_sys->psz_icy_title = NULL;
p_sys->i_remaining = 0;
p_sys->b_persist = false;
p_access->info.i_size = 0; p_access->info.i_size = -1;
p_access->info.i_pos = i_tell; p_access->info.i_pos = i_tell;
p_access->info.b_eof = false; p_access->info.b_eof = false;
...@@ -1106,7 +1109,10 @@ static int Request( access_t *p_access, int64_t i_tell ) ...@@ -1106,7 +1109,10 @@ static int Request( access_t *p_access, int64_t i_tell )
access_sys_t *p_sys = p_access->p_sys; access_sys_t *p_sys = p_access->p_sys;
char *psz ; char *psz ;
v_socket_t *pvs = p_sys->p_vs; v_socket_t *pvs = p_sys->p_vs;
bool b_connection_close = false;
p_sys->b_persist = false;
p_sys->i_remaining = 0;
if( p_sys->b_proxy ) if( p_sys->b_proxy )
{ {
if( p_sys->url.psz_path ) if( p_sys->url.psz_path )
...@@ -1149,8 +1155,9 @@ static int Request( access_t *p_access, int64_t i_tell ) ...@@ -1149,8 +1155,9 @@ static int Request( access_t *p_access, int64_t i_tell )
net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "User-Agent: %s\r\n", net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "User-Agent: %s\r\n",
p_sys->psz_user_agent ); p_sys->psz_user_agent );
/* Offset */ /* Offset */
if( p_sys->i_version == 1 ) if( p_sys->i_version == 1 && ! p_sys->b_continuous )
{ {
p_sys->b_persist = true;
net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs,
"Range: bytes=%"PRIu64"-\r\n", i_tell ); "Range: bytes=%"PRIu64"-\r\n", i_tell );
} }
...@@ -1193,17 +1200,6 @@ static int Request( access_t *p_access, int64_t i_tell ) ...@@ -1193,17 +1200,6 @@ static int Request( access_t *p_access, int64_t i_tell )
net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Icy-MetaData: 1\r\n" ); net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Icy-MetaData: 1\r\n" );
if( p_sys->b_continuous )
{
net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs,
"Connection: Keep-Alive\r\n" );
}
else if( p_sys->i_version == 1 )
{
net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs,
"Connection: Close\r\n");
}
if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "\r\n" ) < 0 ) if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "\r\n" ) < 0 )
{ {
msg_Err( p_access, "failed to send request" ); msg_Err( p_access, "failed to send request" );
...@@ -1293,16 +1289,33 @@ static int Request( access_t *p_access, int64_t i_tell ) ...@@ -1293,16 +1289,33 @@ static int Request( access_t *p_access, int64_t i_tell )
if( !strcasecmp( psz, "Content-Length" ) ) if( !strcasecmp( psz, "Content-Length" ) )
{ {
if( p_sys->b_continuous ) int64_t i_size = i_tell + (p_sys->i_remaining = atoll( p ));
{ if(i_size > p_access->info.i_size) {
p_access->info.i_size = -1; p_access->info.i_size = i_size;
msg_Dbg( p_access, "this frame size=%lld", atoll(p ) );
p_sys->i_remaining = atoll( p );
} }
else msg_Dbg( p_access, "this frame size=%"PRId64, p_sys->i_remaining );
{ }
p_access->info.i_size = i_tell + atoll( p ); else if( !strcasecmp( psz, "Content-Range" ) ) {
msg_Dbg( p_access, "stream size=%"PRId64, p_access->info.i_size ); int64_t i_ntell = i_tell;
int64_t i_nend = (p_access->info.i_size > 0)?(p_access->info.i_size - 1):i_tell;
int64_t i_nsize = p_access->info.i_size;
sscanf(p,"bytes %"PRId64"-%"PRId64"/%"PRId64,&i_ntell,&i_nend,&i_nsize);
if(i_nend > i_ntell ) {
p_access->info.i_pos = i_ntell;
p_sys->i_remaining = i_nend+1-i_ntell;
int64_t i_size = (i_nsize > i_nend) ? i_nsize : (i_nend + 1);
if(i_size > p_access->info.i_size) {
p_access->info.i_size = i_size;
}
msg_Dbg( p_access, "stream size=%"PRId64",pos=%"PRId64",remaining=%"PRId64,i_nsize,i_ntell,p_sys->i_remaining);
}
}
else if( !strcasecmp( psz, "Connection" ) ) {
msg_Dbg( p_access, "Connection: %s",p );
int i = -1;
sscanf(p, "close%n",&i);
if( i >= 0 ) {
p_sys->b_persist = false;
} }
} }
else if( !strcasecmp( psz, "Location" ) ) else if( !strcasecmp( psz, "Location" ) )
...@@ -1456,6 +1469,12 @@ static int Request( access_t *p_access, int64_t i_tell ) ...@@ -1456,6 +1469,12 @@ static int Request( access_t *p_access, int64_t i_tell )
free( psz ); free( psz );
} }
/* We close the stream for zero length data, unless of course the
* server has already promised to do this for us.
*/
if( p_access->info.i_size != -1 && p_sys->i_remaining == 0 && p_sys->b_persist ) {
Disconnect( p_access );
}
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment