This commit is contained in:
David Rose 2002-10-18 16:32:39 +00:00
parent f3065fbb3e
commit 27df52fbfe
5 changed files with 91 additions and 29 deletions

View File

@ -484,22 +484,3 @@ is_download_complete() const {
return (_download_dest != DD_none &&
(_state == S_read_body || _state == S_read_trailer));
}
////////////////////////////////////////////////////////////////////
// Function: HTTPChannel::check_socket
// Access: Private
// Description: Checks whether the connection to the server has been
// closed after a failed read. If it has, issues a
// warning and calls free_bio().
////////////////////////////////////////////////////////////////////
INLINE void HTTPChannel::
check_socket() {
nassertv(!_source.is_null());
if ((*_source)->is_closed()) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "Lost connection to server unexpectedly during read.\n";
}
free_bio();
}
}

View File

@ -64,6 +64,7 @@ HTTPChannel(HTTPClient *client) :
_bytes_requested = 0;
_status_code = 0;
_status_string = string();
_response_type = RT_none;
_proxy = _client->get_proxy();
_http_version = _client->get_http_version();
_http_version_string = _client->get_http_version_string();
@ -602,11 +603,21 @@ run_proxy_request_sent() {
// Wait for the first line to come back from the server.
string line;
if (!http_getline(line)) {
if (_bio.is_null()) {
// Huh, the proxy hung up on us as soon as we tried to connect.
if (_response_type == RT_hangup) {
// This was our second immediate hangup in a row. Give up.
_state = S_failure;
} else {
// Try again, once.
_response_type = RT_hangup;
}
}
return true;
}
if (!parse_http_response(line)) {
_state = S_failure;
return false;
}
@ -614,6 +625,7 @@ run_proxy_request_sent() {
_current_field_name = string();
_current_field_value = string();
_headers.clear();
_file_size = 0;
return false;
}
@ -832,11 +844,21 @@ run_request_sent() {
// Wait for the first line to come back from the server.
string line;
if (!http_getline(line)) {
if (_bio.is_null()) {
// Huh, the server hung up on us as soon as we tried to connect.
if (_response_type == RT_hangup) {
// This was our second immediate hangup in a row. Give up.
_state = S_failure;
} else {
// Try again, once.
_response_type = RT_hangup;
}
}
return true;
}
if (!parse_http_response(line)) {
_state = S_failure;
return false;
}
@ -844,6 +866,7 @@ run_request_sent() {
_current_field_name = string();
_current_field_value = string();
_headers.clear();
_file_size = 0;
return false;
}
@ -997,6 +1020,18 @@ run_begin_body() {
// Therefore, we have already read the (nonexistent) body.
_state = S_ready;
} else if (_file_size > 8192) {
// If we know the size of the body we are about to skip and it's
// too large (and here we arbitrarily say 8KB is too large), then
// don't bother skipping it--just drop the connection and get a
// new one.
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "Dropping connection rather than skipping past " << _file_size
<< " bytes.\n";
}
free_bio();
} else {
nassertr(_body_stream == NULL, false);
_body_stream = read_body();
@ -1281,11 +1316,9 @@ begin_request(const string &method, const URLSpec &url, const string &body,
void HTTPChannel::
reset_for_new_request() {
reset_download_to();
_status_code = 0;
_status_string = string();
_redirect_trail.clear();
_last_status_code = 0;
_file_size = 0;
_response_type = RT_none;
_redirect_trail.clear();
_bytes_downloaded = 0;
_bytes_requested = 0;
}
@ -1397,9 +1430,22 @@ parse_http_response(const string &line) {
// Not an HTTP response.
_status_code = 0;
_status_string = "Not an HTTP response";
if (_response_type == RT_non_http) {
// This was our second non-HTTP response in a row. Give up.
_state = S_failure;
} else {
// Maybe we were just in some bad state. Drop the connection
// and try again, once.
free_bio();
_response_type = RT_non_http;
}
return false;
}
// Okay, we're sane.
_response_type = RT_http;
// Split out the first line into its three components.
size_t p = 5;
while (p < line.length() && !isspace(line[p])) {
@ -1530,6 +1576,25 @@ parse_content_range(const string &content_range) {
}
////////////////////////////////////////////////////////////////////
// Function: HTTPChannel::check_socket
// Access: Private
// Description: Checks whether the connection to the server has been
// closed after a failed read. If it has, issues a
// warning and calls free_bio().
////////////////////////////////////////////////////////////////////
void HTTPChannel::
check_socket() {
nassertv(!_source.is_null());
if ((*_source)->is_closed()) {
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "Lost connection to server unexpectedly during read.\n";
}
free_bio();
}
}
////////////////////////////////////////////////////////////////////
// Function: HTTPChannel::verify_server
// Access: Private

View File

@ -153,7 +153,7 @@ private:
bool parse_http_header();
bool parse_content_range(const string &content_range);
INLINE void check_socket();
void check_socket();
bool verify_server(X509_NAME *subject) const;
static string get_x509_name_component(X509_NAME *name, int nid);
@ -218,6 +218,15 @@ private:
string _realm;
URLSpec _redirect;
enum ResponseType {
RT_none,
RT_hangup,
RT_non_http,
RT_http
};
ResponseType _response_type;
typedef pmap<string, string> Headers;
Headers _headers;

View File

@ -301,11 +301,18 @@ clear_expected_servers() {
// connection, for greater network efficiency than
// calling HTTPClient::get_document() repeatedly (and
// thus forcing a new connection for each document).
//
// Pass true for persistent_connection to gain this
// network efficiency. If, on the other hand, your
// intention is to use the channel to retrieve only one
// document, then pass false to inform the server that
// we will be dropping the connection after the first
// document.
////////////////////////////////////////////////////////////////////
PT(HTTPChannel) HTTPClient::
make_channel() {
make_channel(bool persistent_connection) {
PT(HTTPChannel) doc = new HTTPChannel(this);
doc->set_persistent_connection(true);
doc->set_persistent_connection(persistent_connection);
return doc;
}

View File

@ -89,7 +89,7 @@ PUBLISHED:
bool add_expected_server(const string &server_attributes);
void clear_expected_servers();
PT(HTTPChannel) make_channel();
PT(HTTPChannel) make_channel(bool persistent_connection);
PT(HTTPChannel) post_form(const URLSpec &url, const string &body);
PT(HTTPChannel) get_document(const URLSpec &url,
const string &body = string());