David Rose %!s(int64=23) %!d(string=hai) anos
pai
achega
27df52fbfe

+ 0 - 19
panda/src/downloader/httpChannel.I

@@ -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();
-  }
-}

+ 71 - 6
panda/src/downloader/httpChannel.cxx

@@ -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

+ 10 - 1
panda/src/downloader/httpChannel.h

@@ -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;
 

+ 9 - 2
panda/src/downloader/httpClient.cxx

@@ -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;
 }
 

+ 1 - 1
panda/src/downloader/httpClient.h

@@ -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());