>From 3a2202508769a9a0a457218fef9b27c3f7d0ff29 Mon Sep 17 00:00:00 2001
From: Bill C Riemers <briemers@redhat.com>
Date: Fri, 13 Jun 2008 14:42:53 -0400
Subject: [PATCH] Correctly respond to a Connection: Close message.
 Restore http to be marked as non-fastseek and modify avi demux not to require
 fastseek.

---
 modules/access/http.c      |   86 +++++++++++++++++++++++++++++--------------
 modules/demux/avi/avi.c    |    2 +-
 modules/demux/avi/libavi.c |    4 +-
 3 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/modules/access/http.c b/modules/access/http.c
index fad1a8b..ae71267 100644
--- a/modules/access/http.c
+++ b/modules/access/http.c
@@ -202,6 +202,7 @@ struct access_sys_t
     bool b_reconnect;
     bool b_continuous;
     bool b_pace_control;
+    bool b_persist; /* true unless the server returned Connection: close */
 
     vlc_array_t * cookies;
 };
@@ -219,6 +220,7 @@ static int Control( access_t *, int, va_list );
 
 /* */
 static int Connect( access_t *, int64_t );
+static int ConnectBlockSize( access_t *, int64_t, int64_t );
 static int Request( access_t *p_access, int64_t i_tell );
 static void Disconnect( access_t * );
 
@@ -291,6 +293,7 @@ static int OpenWithCookies( vlc_object_t *p_this, vlc_array_t *cookies )
     p_sys->i_pos = 0;
     p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE;
     p_sys->cookies = saved_cookies;
+    p_sys->b_persist = true;
 
     /* Parse URI - remove spaces */
     p = psz = strdup( p_access->psz_path );
@@ -871,7 +874,16 @@ static int SkipForward( access_t *p_access, int64_t i_len ) {
     access_sys_t *p_sys = p_access->p_sys;
     int64_t i_tell = p_access->info.i_pos + i_len;
     if(p_sys->i_remaining > 0 ) {
-        size_t j_len = (size_t)((i_len > p_sys->i_remaining)?p_sys->i_remaining:i_len);
+        size_t j_len;
+        if(i_len >= p_sys->i_remaining ) {
+           if(! p_sys->b_persist) {
+               return Request( p_access, i_tell);
+           }
+           j_len = (size_t)p_sys->i_remaining; 
+        }
+        else {
+           j_len = (size_t)i_len;
+        }
         uint8_t *p_buffer = (uint8_t *)malloc(j_len);
         do {
             ssize_t i_read = Read(p_access, p_buffer, j_len);
@@ -897,19 +909,19 @@ static int SkipForward( access_t *p_access, int64_t i_len ) {
  *****************************************************************************/
 static int Seek( access_t *p_access, int64_t i_pos )
 {
-    if( i_pos < 0 )
-    {
+    if( i_pos < 0 ) {
         msg_Err( p_access, "seeking too early" );
-        return Seek( p_access, 0);
+        p_access->info.i_pos = 0;
     }
-    if( i_pos > p_access->info.i_size )
-    {
+    else if( i_pos > p_access->info.i_size ) {
         msg_Err( p_access, "seeking too far" );
         // Fix me: This replicates the file.c behavior of returning
         // success even when seeking too far.
-        return Seek( p_access, p_access->info.i_size );
+        p_access->info.i_pos = p_access->info.i_size - 1;
+    }
+    else {
+        p_access->info.i_pos = i_pos;
     }
-    p_access->info.i_pos = i_pos;
     return VLC_SUCCESS;
 }
 
@@ -926,7 +938,7 @@ static int SeekTo( access_t *p_access)
     }
     p_access->info.i_pos = p_sys->i_pos;
 
-    msg_Dbg( p_access, "trying to seek to %"PRId64"/"PRId64, i_pos, p_access->info.i_size );
+    msg_Dbg( p_access, "trying to seek to %"PRId64"/%"PRId64, i_pos, p_access->info.i_size );
 
     // we can use the skip data to seek forward
     if( i_pos > p_access->info.i_pos) {
@@ -940,24 +952,17 @@ static int SeekTo( access_t *p_access)
     }
     // Now we try skipping the remaining bytes and then making the next
     // request with our desired offset.
-    if( (p_sys->i_remaining > 0)  && (p_sys->i_remaining <= HTTP_SEEK_BLOCKSIZE)) {
+    int64_t i_blocksize = HTTP_MIN_BLOCKSIZE;
+    if( ! p_sys->b_persist) {
+        i_blocksize = p_access->info.i_size;
+    }
+    else if( (p_sys->i_remaining > 0)  && (p_sys->i_remaining <= HTTP_SEEK_BLOCKSIZE)) {
         if ( SkipForward( p_access, p_sys->i_remaining) == VLC_SUCCESS ) {
-            p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE;
-            if (Request(p_access, i_pos) == VLC_SUCCESS) {
-                return VLC_SUCCESS;
-            }
+            return VLC_SUCCESS;
         }
     }
-    // Since the server does not have to honour our keep-alive request
-    // we could end-up here.
     Disconnect( p_access );
-    int retval= Connect( p_access, i_pos );
-    if (retval != VLC_SUCCESS )
-    {
-        msg_Err( p_access, "seek failed" );
-        p_access->info.b_eof = true;
-    }
-    return retval;
+    return ConnectBlockSize( p_access, i_pos, i_blocksize );
 }
 
 /*****************************************************************************
@@ -980,8 +985,9 @@ static int Control( access_t *p_access, int i_query, va_list args )
             break;
         case ACCESS_CAN_FASTSEEK:
             pb_bool = (bool*)va_arg( args, bool* );
-            // http 1.1 should be just as fast as nfs...
-            *pb_bool = p_sys->b_seekable;
+            // http 1.1 should be just as fast as nfs...  But then again
+            // maybe nfs is not fastseek either when used across the internet.
+            *pb_bool = false;
             break;
         case ACCESS_CAN_PAUSE:
         case ACCESS_CAN_CONTROL_PACE:
@@ -1040,9 +1046,9 @@ static int Control( access_t *p_access, int i_query, va_list args )
 }
 
 /*****************************************************************************
- * Connect:
+ * ConnectBlockSize:
  *****************************************************************************/
-static int Connect( access_t *p_access, int64_t i_tell )
+static int ConnectBlockSize( access_t *p_access, int64_t i_tell, int64_t i_blocksize )
 {
     access_sys_t   *p_sys = p_access->p_sys;
     vlc_url_t      srv = p_sys->b_proxy ? p_sys->proxy : p_sys->url;
@@ -1067,7 +1073,7 @@ static int Connect( access_t *p_access, int64_t i_tell )
     p_sys->psz_icy_name = NULL;
     p_sys->psz_icy_genre = NULL;
     p_sys->psz_icy_title = NULL;
-    p_sys->i_blocksize = HTTP_MIN_BLOCKSIZE;
+    p_sys->i_blocksize = i_blocksize;
 
     p_access->info.i_size = 0;
     p_sys->i_pos = p_access->info.i_pos  = i_tell;
@@ -1161,6 +1167,14 @@ static int Connect( access_t *p_access, int64_t i_tell )
     return Request( p_access, i_tell ) ? -2 : 0;
 }
 
+/*****************************************************************************
+ * Connect:
+ *****************************************************************************/
+static int Connect( access_t *p_access, int64_t i_tell )
+{
+    return ConnectBlockSize( p_access, i_tell, HTTP_MIN_BLOCKSIZE);
+}
+
 
 static int Request( access_t *p_access, int64_t i_tell )
 {
@@ -1168,6 +1182,15 @@ static int Request( access_t *p_access, int64_t i_tell )
     char           *psz ;
     v_socket_t     *pvs = p_sys->p_vs;
 
+    if ( ! p_sys->b_persist ) {
+        int64_t i_blocksize = p_access->info.i_size;
+        Disconnect( p_access );
+        int retval = ConnectBlockSize( p_access , i_tell, i_blocksize);
+        if( retval != VLC_SUCCESS ) {
+            return retval;
+        } 
+    }
+
     if( p_sys->b_proxy )
     {
         if( p_sys->url.psz_path )
@@ -1382,6 +1405,13 @@ static int Request( access_t *p_access, int64_t i_tell )
             p_sys->i_remaining = j_end+1-j_tell;
             msg_Dbg( p_access, "stream size=%"PRId64",position=%"PRId64",remaining=%"PRId64,j_size,j_tell,p_sys->i_remaining);
         }
+        else if( !strcasecmp( psz, "Connection") ) {
+            int i = -1;
+            sscanf(p,"close%n",&i);
+            if( i >= 0) {
+                p_sys->b_persist = false;
+            }
+        }
         else if( !strcasecmp( psz, "Location" ) )
         {
             char * psz_new_loc;
diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c
index 1d7b6b7..2c9758a 100644
--- a/modules/demux/avi/avi.c
+++ b/modules/demux/avi/avi.c
@@ -263,7 +263,7 @@ static int Open( vlc_object_t * p_this )
     p_sys->track    = NULL;
     p_sys->meta     = NULL;
 
-    stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );
+    stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
 
     p_demux->pf_control = Control;
     p_demux->pf_demux = Demux_Seekable;
diff --git a/modules/demux/avi/libavi.c b/modules/demux/avi/libavi.c
index b91f070..5c179ee 100644
--- a/modules/demux/avi/libavi.c
+++ b/modules/demux/avi/libavi.c
@@ -130,7 +130,7 @@ static int AVI_ChunkRead_list( stream_t *s, avi_chunk_t *p_container )
         return VLC_EGENERIC;
     }
 
-    stream_Control( s, STREAM_CAN_FASTSEEK, &b_seekable );
+    stream_Control( s, STREAM_CAN_SEEK, &b_seekable );
 
     p_container->list.i_type = GetFOURCC( p_peek + 8 );
 
@@ -842,7 +842,7 @@ int AVI_ChunkReadRoot( stream_t *s, avi_chunk_t *p_root )
     avi_chunk_t      *p_chk;
     bool b_seekable;
 
-    stream_Control( s, STREAM_CAN_FASTSEEK, &b_seekable );
+    stream_Control( s, STREAM_CAN_SEEK, &b_seekable );
 
     p_list->i_chunk_pos  = 0;
     p_list->i_chunk_size = stream_Size( s );
-- 
1.5.5.1

