support file:// urls
This commit is contained in:
parent
865ea20789
commit
7406014cbc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue