support file:// urls

This commit is contained in:
David Rose 2009-07-22 01:03:44 +00:00
parent 865ea20789
commit 7406014cbc
4 changed files with 105 additions and 24 deletions

View File

@ -29,10 +29,35 @@
////////////////////////////////////////////////////////////////////
BioPtr::
BioPtr(const URLSpec &url) {
_server_name = url.get_server();
_port = url.get_port();
_bio = BIO_new_connect((char *)_server_name.c_str());
BIO_set_conn_int_port(_bio, &_port);
if (url.get_scheme() == "file") {
// We're just reading a disk file.
string filename = url.get_path();
#ifdef _WIN32
// On Windows, we have to munge the filename specially, because it's
// been URL-munged. It might begin with a leading slash as well as
// a drive letter. Clean up that nonsense.
if (!filename.empty()) {
if (filename[0] == '/' || filename[0] == '\\') {
Filename fname = Filename::from_os_specific(filename.substr(1));
if (fname.is_local()) {
// Put the slash back on.
fname = string("/") + fname.get_fullpath();
}
filename = fname.to_os_specific();
}
}
#endif // _WIN32
_server_name = "";
_port = 0;
_bio = BIO_new_file(filename.c_str(), "rb");
} else {
// A normal network-based URL.
_server_name = url.get_server();
_port = url.get_port();
_bio = BIO_new_connect((char *)_server_name.c_str());
BIO_set_conn_int_port(_bio, &_port);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -193,7 +193,7 @@ underflow() {
// which that never returns true, if the socket is closed by
// the server. But BIO_should_retry() *appears* to be
// reliable.
_read_open = (bool)BIO_should_retry(*_source);
_read_open = (BIO_should_retry(*_source) != 0);
if (!_read_open) {
downloader_cat.info()
<< "Lost connection to "
@ -262,7 +262,7 @@ write_chars(const char *start, size_t length) {
// without a retry request
//_write_open = BIO_should_retry(*_source);
//_write_open = !BIO_eof(*_source);
_write_open = (bool)BIO_should_write(*_source);
_write_open = (BIO_should_write(*_source) != 0);
if (!_write_open) {
return wrote_so_far;
}

View File

@ -23,6 +23,8 @@
#include "virtualFileMountHTTP.h"
#include "ramfile.h"
#include <stdio.h>
#ifdef HAVE_OPENSSL
#include "openssl/x509.h"
@ -462,6 +464,10 @@ run() {
repeat_later = run_reading_header();
break;
case S_start_direct_file_read:
repeat_later = run_start_direct_file_read();
break;
case S_read_header:
repeat_later = run_read_header();
break;
@ -912,7 +918,7 @@ reached_done_state() {
if (_body_stream == (ISocketStream *)NULL) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "Unable to download body.\n";
<< "Unable to download body: " << _request.get_url() << "\n";
}
return false;
@ -1981,6 +1987,18 @@ run_reading_header() {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: HTTPChannel::run_start_direct_file_read
// Access: Private
// Description: This is the first state when reading a file:// URL.
// All it does is skip past the non-existent "header".
////////////////////////////////////////////////////////////////////
bool HTTPChannel::
run_start_direct_file_read() {
_state = S_read_header;
return false;
}
////////////////////////////////////////////////////////////////////
// Function: HTTPChannel::run_read_header
// Access: Private
@ -2436,27 +2454,60 @@ begin_request(HTTPEnum::Method method, const DocumentSpec &url,
reconsider_proxy();
// Also, reset from whatever previous request might still be pending.
if (_state == S_failure || (_state < S_read_header && _state != S_ready)) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "resetting to clear previous request.\n";
}
// Reset from whatever previous request might still be pending.
if (_request.get_url().get_scheme() == "file") {
// A "file" URL just means we're reading a raw file. This only
// supports actual disk files, not the VFS, because we use a
// BIO_new_file() underneath this.
reset_to_new();
_bio = new BioPtr(_request.get_url());
if (_bio->get_bio() != NULL) {
// Successfully opened the file.
_source = new BioStreamPtr(new BioStream(_bio));
_status_entry._status_code = 200;
_state = S_start_direct_file_read;
} else if (TrueClock::get_global_ptr()->get_short_time() - _last_run_time >= _idle_timeout) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "resetting old connection: "
<< TrueClock::get_global_ptr()->get_short_time() - _last_run_time
<< " s old.\n";
// Get the file size.
FILE *fp = NULL;
BIO_get_fp(_bio->get_bio(), &fp);
if (fp != NULL) {
if (fseek(fp, 0, SEEK_END) == 0) {
_file_size = ftell(fp);
_got_file_size = true;
fseek(fp, 0, SEEK_SET);
}
}
} else {
// Couldn't read the file.
notify_ssl_errors();
_status_entry._status_code = SC_no_connection;
_state = S_failure;
}
reset_to_new();
} else if (_state == S_read_header) {
// Roll one step forwards to start skipping past the previous
// body.
_state = S_begin_body;
} else {
// We're reading a normal network URL.
if (_state == S_failure || (_state < S_read_header && _state != S_ready)) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "resetting to clear previous request.\n";
}
reset_to_new();
} else if (TrueClock::get_global_ptr()->get_short_time() - _last_run_time >= _idle_timeout) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "resetting old connection: "
<< TrueClock::get_global_ptr()->get_short_time() - _last_run_time
<< " s old.\n";
}
reset_to_new();
} else if (_state == S_read_header) {
// Roll one step forwards to start skipping past the previous
// body.
_state = S_begin_body;
}
}
if (_method == HTTPEnum::M_connect) {
@ -3823,6 +3874,9 @@ operator << (ostream &out, HTTPChannel::State state) {
case HTTPChannel::S_reading_header:
return out << "reading_header";
case HTTPChannel::S_start_direct_file_read:
return out << "start_direct_file_read";
case HTTPChannel::S_read_header:
return out << "read_header";

View File

@ -215,6 +215,7 @@ private:
bool run_ready();
bool run_request_sent();
bool run_reading_header();
bool run_start_direct_file_read();
bool run_read_header();
bool run_begin_body();
bool run_reading_body();
@ -287,6 +288,7 @@ public:
S_ready,
S_request_sent,
S_reading_header,
S_start_direct_file_read,
S_read_header,
S_begin_body,
S_reading_body,