From: short <> Date: Mon, 1 Sep 2003 16:31:00 +0000 (+0000) Subject: Implemented seek() and tell() for r/o streams of 'http'. X-Git-Tag: gnome_vfs_httpcaptive_2_3_8captive1~12 X-Git-Url: http://git.jankratochvil.net/?p=gnome-vfs-httpcaptive.git;a=commitdiff_plain;h=b681983bd9666febbe1cecda5357b8b003cd7257 Implemented seek() and tell() for r/o streams of 'http'. --- diff --git a/modules/http-method.c b/modules/http-method.c index 317513d..cba1274 100644 --- a/modules/http-method.c +++ b/modules/http-method.c @@ -100,6 +100,9 @@ http_debug_printf (char *fmt, ...) /* Standard HTTP proxy port */ #define DEFAULT_HTTP_PROXY_PORT 8080 +/* Maximum amount of data to read if seek()ed forward. Otherwise make a new connection. */ +#define MAX_BUFFER_SEEK_SKIP_READ 0x10000 + /* GConf paths and keys */ #define PATH_GCONF_GNOME_VFS "/system/http_proxy" #define ITEM_GCONF_HTTP_PROXY_PORT "port" @@ -211,8 +214,11 @@ typedef struct { /* File info for this file */ GnomeVFSFileInfo *file_info; - /* Bytes read so far. */ - GnomeVFSFileSize bytes_read; + /* File offset of current pointer of 'socket_buffer'. */ + GnomeVFSFileOffset socket_buffer_offset; + + /* Offset; Current file position. */ + GnomeVFSFileOffset offset; /* Bytes to be written... */ GByteArray *to_be_written; @@ -1825,7 +1831,7 @@ do_close (GnomeVFSMethod *method, } else { result = GNOME_VFS_OK; } - + http_handle_close (old_handle, context); g_free (old_handle); @@ -1840,7 +1846,7 @@ do_write (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, gconstpointer buffer, GnomeVFSFileSize num_bytes, - GnomeVFSFileSize *bytes_read, + GnomeVFSFileSize *bytes_written, GnomeVFSContext *context) { HttpFileHandle *handle; @@ -1849,11 +1855,14 @@ do_write (GnomeVFSMethod *method, handle = (HttpFileHandle *) method_handle; + if (handle->offset != 0) + return GNOME_VFS_ERROR_NOT_SUPPORTED; + if(handle->to_be_written == NULL) { handle->to_be_written = g_byte_array_new(); } handle->to_be_written = g_byte_array_append(handle->to_be_written, buffer, num_bytes); - *bytes_read = num_bytes; + *bytes_written = num_bytes; DEBUG_HTTP (("-Write (0)")); @@ -1880,10 +1889,50 @@ do_read (GnomeVFSMethod *method, if (handle->file_info->flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE) { GnomeVFSFileSize max_bytes; - max_bytes = handle->file_info->size - handle->bytes_read; + max_bytes = MAX (0, handle->file_info->size - handle->offset); num_bytes = MIN (max_bytes, num_bytes); } + if (!num_bytes) { + *bytes_read = 0; + return GNOME_VFS_OK; + } + + if (1 + && handle->offset > handle->socket_buffer_offset + && handle->offset <= handle->socket_buffer_offset+MAX_BUFFER_SEEK_SKIP_READ) { +static char drop_buffer[0x1000]; +GnomeVFSFileSize bytes, bytes_read; +GnomeVFSResult result; + + while ((bytes=MIN(sizeof(drop_buffer), handle->offset - handle->socket_buffer_offset))) { + result = gnome_vfs_socket_buffer_read (handle->socket_buffer, drop_buffer, + bytes, &bytes_read); + if (result != GNOME_VFS_OK) + return result; + handle->socket_buffer_offset += bytes_read; + } + } + + if (handle->offset != handle->socket_buffer_offset) { + GnomeVFSURI *uri = handle->uri; + gchar *extra_headers; + + gnome_vfs_uri_ref(uri); + http_handle_close (handle, context); + extra_headers = g_strdup_printf("Range: bytes=%" G_GINT64_FORMAT "-\r\n",(gint64)handle->offset); + result = make_request (handle, uri, "GET", NULL, extra_headers, + context); + g_free (extra_headers); + gnome_vfs_uri_unref(uri); + if (result != GNOME_VFS_OK) { + /* FIXME: 'method_handle' is now broken! */ + memset(handle, 0, sizeof (*handle)); + return result; + } + handle->socket_buffer_offset = handle->offset; + } + result = gnome_vfs_socket_buffer_read (handle->socket_buffer, buffer, num_bytes, bytes_read); @@ -1891,7 +1940,8 @@ do_read (GnomeVFSMethod *method, return GNOME_VFS_ERROR_EOF; } - handle->bytes_read += *bytes_read; + handle->socket_buffer_offset += *bytes_read; + handle->offset += *bytes_read; DEBUG_HTTP (("-Read (%d)", result)); ANALYZE_HTTP ("==> -do_read"); @@ -1899,6 +1949,53 @@ do_read (GnomeVFSMethod *method, return result; } +static GnomeVFSResult +do_seek (GnomeVFSMethod *method, + GnomeVFSMethodHandle *method_handle, + GnomeVFSSeekPosition whence, + GnomeVFSFileOffset offset, + GnomeVFSContext *context) +{ + HttpFileHandle *handle; + + handle = (HttpFileHandle *) method_handle; + + if (handle->to_be_written != NULL) + return GNOME_VFS_ERROR_NOT_SUPPORTED; + + switch (whence) { + case GNOME_VFS_SEEK_START: + handle->offset = offset; + break; + case GNOME_VFS_SEEK_CURRENT: + handle->offset += offset; + break; + case GNOME_VFS_SEEK_END: + if (!(handle->file_info->flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) + return GNOME_VFS_ERROR_NOT_SUPPORTED; + handle->offset = handle->file_info->size + offset; + break; + default: + g_return_val_if_reached(GNOME_VFS_ERROR_NOT_SUPPORTED); + } + + return GNOME_VFS_OK; +} + +static GnomeVFSResult +do_tell (GnomeVFSMethod *method, + GnomeVFSMethodHandle *method_handle, + GnomeVFSFileOffset *offset_return) +{ + HttpFileHandle *handle; + + handle = (HttpFileHandle *) method_handle; + + *offset_return = handle->offset; + + return GNOME_VFS_OK; +} + /* Directory handling - WebDAV servers only */ static void @@ -2788,8 +2885,8 @@ static GnomeVFSMethod method = { do_close, do_read, do_write, - NULL, /* seek */ - NULL, /* tell */ + do_seek, + do_tell, NULL, /* truncate_handle */ do_open_directory, do_close_directory,