Panda3D
 All Classes Functions Variables Enumerations
httpChannel.cxx
00001 // Filename: httpChannel.cxx
00002 // Created by:  drose (24Sep02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "httpChannel.h"
00016 #include "httpClient.h"
00017 #include "httpCookie.h"
00018 #include "bioStream.h"
00019 #include "chunkedStream.h"
00020 #include "identityStream.h"
00021 #include "config_downloader.h"
00022 #include "virtualFileSystem.h"
00023 #include "virtualFileMountHTTP.h"
00024 #include "ramfile.h"
00025 #include "globPattern.h"
00026 
00027 #include <stdio.h>
00028 
00029 #ifdef HAVE_OPENSSL
00030 
00031 #if defined(WIN32_VC) || defined(WIN64_VC)
00032   #include <WinSock2.h>
00033   #include <windows.h>  // for select()
00034   #undef X509_NAME
00035 #endif  // WIN32_VC
00036 
00037 TypeHandle HTTPChannel::_type_handle;
00038 
00039 #define _NOTIFY_HTTP_CHANNEL_ID   "[" << this << "] "
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: HTTPChannel::Constructor
00043 //       Access: Private
00044 //  Description: 
00045 ////////////////////////////////////////////////////////////////////
00046 HTTPChannel::
00047 HTTPChannel(HTTPClient *client) :
00048   _client(client)
00049 {
00050   if (downloader_cat.is_debug()) {
00051     downloader_cat.debug()
00052       << _NOTIFY_HTTP_CHANNEL_ID 
00053     << "created.\n";
00054   }
00055 
00056   ConfigVariableDouble extra_ssl_handshake_time
00057     ("extra-ssl-handshake-time", 0.0,
00058      PRC_DESC("This specifies how much extra time to try to establish"
00059                "the ssl handshake before we bail."));
00060   _extra_ssl_handshake_time = extra_ssl_handshake_time;
00061   _proxy_next_index = 0;
00062   _persistent_connection = false;
00063   _allow_proxy = true;
00064   _proxy_tunnel = http_proxy_tunnel;
00065   _connect_timeout = http_connect_timeout;
00066   _http_timeout = http_timeout;
00067   _skip_body_size = http_skip_body_size;
00068   _idle_timeout = http_idle_timeout;
00069   _blocking_connect = false;
00070   _download_throttle = download_throttle;
00071   _max_bytes_per_second = downloader_byte_rate;
00072   _seconds_per_update = downloader_frequency;
00073   _max_updates_per_second = 1.0f / _seconds_per_update;
00074   _bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
00075   
00076   // _nonblocking is true if the socket is actually in non-blocking mode.
00077   _nonblocking = false;
00078 
00079   // _wanted_nonblocking is true if the user specifically requested
00080   // one of the non-blocking interfaces.  It is false if the socket is
00081   // only incidentally non-blocking (for instance, because
00082   // SIMPLE_THREADS is on).
00083   _wanted_nonblocking = false;
00084 
00085   _want_ssl = false;
00086   _proxy_serves_document = false;
00087   _proxy_tunnel_now = false;
00088   _first_byte_requested = 0;
00089   _last_byte_requested = 0;
00090   _first_byte_delivered = 0;
00091   _last_byte_delivered = 0;
00092   _read_index = 0;
00093   _expected_file_size = 0;
00094   _file_size = 0;
00095   _transfer_file_size = 0;
00096   _got_expected_file_size = false;
00097   _got_file_size = false;
00098   _got_transfer_file_size = false;
00099   _bytes_downloaded = 0;
00100   _bytes_requested = 0;
00101   _status_entry = StatusEntry();
00102   _response_type = RT_none;
00103   _http_version = _client->get_http_version();
00104   _http_version_string = _client->get_http_version_string();
00105   _state = S_new;
00106   _done_state = S_new;
00107   _started_download = false;
00108   _sent_so_far = 0;
00109   _body_stream = NULL;
00110   _owns_body_stream = false;
00111   _sbio = NULL;
00112   _cipher_list = _client->get_cipher_list();
00113   _last_status_code = 0;
00114   _last_run_time = 0.0f;
00115   _download_to_ramfile = NULL;
00116   _download_to_stream = NULL;
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: HTTPChannel::Destructor
00121 //       Access: Public, Virtual
00122 //  Description: 
00123 ////////////////////////////////////////////////////////////////////
00124 HTTPChannel::
00125 ~HTTPChannel() {
00126   if (downloader_cat.is_debug()) {
00127     downloader_cat.debug()
00128       << _NOTIFY_HTTP_CHANNEL_ID 
00129     << "destroyed.\n";
00130   }
00131 
00132   close_connection();
00133   reset_download_to();
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: HTTPChannel::get_status_string
00138 //       Access: Published
00139 //  Description: Returns the string as returned by the server
00140 //               describing the status code for humans.  This may or
00141 //               may not be meaningful.
00142 ////////////////////////////////////////////////////////////////////
00143 string HTTPChannel::
00144 get_status_string() const {
00145   switch (_status_entry._status_code) {
00146   case SC_incomplete:
00147     return "Connection in progress";
00148 
00149   case SC_internal_error:
00150     return "Internal error";
00151 
00152   case SC_no_connection:
00153     return "No connection";
00154 
00155   case SC_timeout:
00156     return "Timeout on connection";
00157 
00158   case SC_lost_connection:
00159     return "Lost connection";
00160 
00161   case SC_non_http_response:
00162     return "Non-HTTP response";
00163 
00164   case SC_invalid_http:
00165     return "Could not understand HTTP response";
00166 
00167   case SC_socks_invalid_version:
00168     return "Unsupported SOCKS version";
00169 
00170   case SC_socks_no_acceptable_login_method:
00171     return "No acceptable SOCKS login method";
00172 
00173   case SC_socks_refused:
00174     return "SOCKS proxy refused connection";
00175 
00176   case SC_socks_no_connection:
00177     return "SOCKS proxy unable to connect";
00178 
00179   case SC_ssl_internal_failure:
00180     return "SSL internal failure";
00181 
00182   case SC_ssl_no_handshake:
00183     return "No SSL handshake";
00184 
00185   case SC_http_error_watermark:
00186     // This shouldn't be triggered.
00187     return "Internal error";
00188 
00189   case SC_ssl_invalid_server_certificate:
00190     return "SSL invalid server certificate";
00191 
00192   case SC_ssl_unexpected_server:
00193     return "Unexpected SSL server";
00194 
00195   case SC_download_open_error:
00196     return "Error opening file";
00197 
00198   case SC_download_write_error:
00199     return "Error writing to disk";
00200 
00201   case SC_download_invalid_range:
00202     return "Invalid subrange requested";
00203   }
00204 
00205   return _status_entry._status_string;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: HTTPChannel::get_header_value
00210 //       Access: Published
00211 //  Description: Returns the HTML header value associated with the
00212 //               indicated key, or empty string if the key was not
00213 //               defined in the message returned by the server.
00214 ////////////////////////////////////////////////////////////////////
00215 string HTTPChannel::
00216 get_header_value(const string &key) const {
00217   Headers::const_iterator hi = _headers.find(downcase(key));
00218   if (hi != _headers.end()) {
00219     return (*hi).second;
00220   }
00221   return string();
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: HTTPChannel::will_close_connection
00226 //       Access: Published
00227 //  Description: Returns true if the server has indicated it will
00228 //               close the connection after this document has been
00229 //               read, or false if it will remain open (and future
00230 //               documents may be requested on the same connection).
00231 ////////////////////////////////////////////////////////////////////
00232 bool HTTPChannel::
00233 will_close_connection() const {
00234   if (get_http_version() < HTTPEnum::HV_11) {
00235     // pre-HTTP 1.1 always closes.
00236     return true;
00237   }
00238 
00239   string connection = get_header_value("Connection");
00240   if (downcase(connection) == "close") {
00241     // The server says it will close.
00242     return true;
00243   }
00244 
00245   if (connection.empty() && !get_persistent_connection()) {
00246     // The server didn't say, but we asked it to close.
00247     return true;
00248   }
00249 
00250   // Assume the server will keep it open.
00251   return false;
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: HTTPChannel::get_file_size
00256 //       Access: Published, Virtual
00257 //  Description: Returns the size of the file, if it is known.
00258 //               Returns the value set by set_expected_file_size() if
00259 //               the file size is not known, or 0 if this value was
00260 //               not set.
00261 //
00262 //               If the file is dynamically generated, the size may
00263 //               not be available until a read has started
00264 //               (e.g. open_read_body() has been called); and even
00265 //               then it may increase as more of the file is read due
00266 //               to the nature of HTTP/1.1 requests which can change
00267 //               their minds midstream about how much data they're
00268 //               sending you.
00269 ////////////////////////////////////////////////////////////////////
00270 off_t HTTPChannel::
00271 get_file_size() const {
00272   if (_got_file_size) {
00273     return _file_size;
00274   } else if (_got_transfer_file_size) {
00275     return _transfer_file_size;
00276   } else if (_got_expected_file_size) {
00277     return _expected_file_size;
00278   } else {
00279     return 0;
00280   }
00281 }
00282 
00283 ////////////////////////////////////////////////////////////////////
00284 //     Function: HTTPChannel::write_headers
00285 //       Access: Published
00286 //  Description: Outputs a list of all headers defined by the server
00287 //               to the indicated output stream.
00288 ////////////////////////////////////////////////////////////////////
00289 void HTTPChannel::
00290 write_headers(ostream &out) const {
00291   Headers::const_iterator hi;
00292   for (hi = _headers.begin(); hi != _headers.end(); ++hi) {
00293     out << (*hi).first << ": " << (*hi).second << "\n";
00294   }
00295 }
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: HTTPChannel::run
00299 //       Access: Published
00300 //  Description: This must be called from time to time when
00301 //               non-blocking I/O is in use.  It checks for data
00302 //               coming in on the socket and writes data out to the
00303 //               socket when possible, and does whatever processing is
00304 //               required towards completing the current task.
00305 //
00306 //               The return value is true if the task is still pending
00307 //               (and run() will need to be called again in the
00308 //               future), or false if the current task is complete.
00309 ////////////////////////////////////////////////////////////////////
00310 bool HTTPChannel::
00311 run() {
00312   if (downloader_cat.is_spam()) {
00313     downloader_cat.spam()
00314       << _NOTIFY_HTTP_CHANNEL_ID 
00315       << "run().\n";
00316   }
00317 
00318   if (_state == _done_state || _state == S_failure) {
00319     clear_extra_headers();
00320     if (!reached_done_state()) {
00321       return false;
00322     }
00323   }
00324 
00325   if (_started_download) {
00326     if (_wanted_nonblocking && _download_throttle) {
00327       double now = TrueClock::get_global_ptr()->get_short_time();
00328       double elapsed = now - _last_run_time;
00329       if (elapsed < _seconds_per_update) {
00330         // Come back later.
00331         thread_yield();
00332         return true;
00333       }
00334       int num_potential_updates = (int)(elapsed / _seconds_per_update);
00335       _last_run_time = now;
00336       _bytes_requested += _bytes_per_update * num_potential_updates;
00337       if (downloader_cat.is_spam()) {
00338         downloader_cat.spam()
00339           << _NOTIFY_HTTP_CHANNEL_ID 
00340           << "elapsed = " << elapsed << " num_potential_updates = " 
00341           << num_potential_updates << " bytes_requested = " 
00342           << _bytes_requested << "\n";
00343       }
00344     }
00345 
00346     bool repeat_later = false;
00347     switch (_download_dest) {
00348     case DD_none:
00349       // We're done.
00350       break;
00351 
00352     case DD_file:
00353       repeat_later = run_download_to_file();
00354       break;
00355 
00356     case DD_ram:
00357       repeat_later = run_download_to_ram();
00358       break;
00359 
00360     case DD_stream:
00361       repeat_later = run_download_to_stream();
00362       break;
00363     }
00364     if (repeat_later) {
00365       thread_yield();
00366     }
00367     return repeat_later;
00368   }
00369 
00370   /*
00371   if (downloader_cat.is_spam()) {
00372     downloader_cat.spam()
00373       << _NOTIFY_HTTP_CHANNEL_ID 
00374       << "begin run(), _state = " << _state << ", _done_state = "
00375       << _done_state << "\n";
00376   }
00377   */
00378 
00379   if (_state == _done_state) {
00380     return reached_done_state();
00381   }
00382 
00383   bool repeat_later;
00384   do {
00385     // If we're in a state that expects to have a connection already
00386     // (that is, any state other that S_try_next_proxy), then
00387     // reestablish the connection if it has been dropped.
00388     if (_bio.is_null() && _state != S_try_next_proxy) {
00389       if (_connect_count > http_max_connect_count) {
00390         // Too many connection attempts; just give up.  We should
00391         // never trigger this failsafe, since the code in each
00392         // individual case has similar logic to prevent more than two
00393         // consecutive lost connections.
00394         downloader_cat.warning()
00395           << _NOTIFY_HTTP_CHANNEL_ID 
00396           << "Too many lost connections, giving up.\n";
00397         _status_entry._status_code = SC_lost_connection;
00398         _state = S_failure;
00399         return false;
00400       }
00401 
00402       // No connection.  Attempt to establish one.
00403       if (_proxy.empty()) {
00404         _bio = new BioPtr(_request.get_url());
00405       } else {
00406         _bio = new BioPtr(_proxy);
00407       }
00408       _source = new BioStreamPtr(new BioStream(_bio));
00409       if (_nonblocking) {
00410         BIO_set_nbio(*_bio, 1);
00411       }
00412 
00413       if (downloader_cat.is_debug()) {
00414         if (_connect_count > 0) {
00415           downloader_cat.debug()
00416             << _NOTIFY_HTTP_CHANNEL_ID 
00417             << "Reconnecting to " << _bio->get_server_name() << ":" 
00418             << _bio->get_port() << "\n";
00419         } else {
00420           downloader_cat.debug()
00421             << _NOTIFY_HTTP_CHANNEL_ID 
00422             << "Connecting to " << _bio->get_server_name() << ":" 
00423             << _bio->get_port() << "\n";
00424         }
00425       }
00426       
00427       _state = S_connecting;
00428       _started_connecting_time = 
00429         TrueClock::get_global_ptr()->get_short_time();
00430       _connect_count++;
00431     }
00432 
00433     /*
00434     if (downloader_cat.is_spam()) {
00435       downloader_cat.spam()
00436         << _NOTIFY_HTTP_CHANNEL_ID 
00437         << "continue run(), _state = " << _state << "\n";
00438     }
00439     */
00440 
00441     switch (_state) {
00442     case S_try_next_proxy:
00443       repeat_later = run_try_next_proxy();
00444       break;
00445 
00446     case S_connecting:
00447       repeat_later = run_connecting();
00448       break;
00449       
00450     case S_connecting_wait:
00451       repeat_later = run_connecting_wait();
00452       break;
00453       
00454     case S_http_proxy_ready:
00455       repeat_later = run_http_proxy_ready();
00456       break;
00457       
00458     case S_http_proxy_request_sent:
00459       repeat_later = run_http_proxy_request_sent();
00460       break;
00461       
00462     case S_http_proxy_reading_header:
00463       repeat_later = run_http_proxy_reading_header();
00464       break;
00465       
00466     case S_socks_proxy_greet:
00467       repeat_later = run_socks_proxy_greet();
00468       break;
00469       
00470     case S_socks_proxy_greet_reply:
00471       repeat_later = run_socks_proxy_greet_reply();
00472       break;
00473       
00474     case S_socks_proxy_connect:
00475       repeat_later = run_socks_proxy_connect();
00476       break;
00477       
00478     case S_socks_proxy_connect_reply:
00479       repeat_later = run_socks_proxy_connect_reply();
00480       break;
00481       
00482     case S_setup_ssl:
00483       repeat_later = run_setup_ssl();
00484       break;
00485       
00486     case S_ssl_handshake:
00487       repeat_later = run_ssl_handshake();
00488       break;
00489       
00490     case S_ready:
00491       repeat_later = run_ready();
00492       break;
00493       
00494     case S_request_sent:
00495       repeat_later = run_request_sent();
00496       break;
00497       
00498     case S_reading_header:
00499       repeat_later = run_reading_header();
00500       break;
00501       
00502     case S_start_direct_file_read:
00503       repeat_later = run_start_direct_file_read();
00504       break;
00505       
00506     case S_read_header:
00507       repeat_later = run_read_header();
00508       break;
00509       
00510     case S_begin_body:
00511       repeat_later = run_begin_body();
00512       break;
00513       
00514     case S_reading_body:
00515       repeat_later = run_reading_body();
00516       break;
00517 
00518     case S_read_body:
00519       repeat_later = run_read_body();
00520       break;
00521 
00522     case S_read_trailer:
00523       repeat_later = run_read_trailer();
00524       break;
00525       
00526     default:
00527       downloader_cat.warning()
00528         << _NOTIFY_HTTP_CHANNEL_ID 
00529         << "Unhandled state " << _state << "\n";
00530       return false;
00531     }
00532 
00533     if (_state == _done_state || _state == S_failure) {
00534       clear_extra_headers();
00535       // We've reached our terminal state.
00536       return reached_done_state();
00537     }
00538     thread_consider_yield();
00539   } while (!repeat_later || _bio.is_null());
00540 
00541   /*
00542   if (downloader_cat.is_spam()) {
00543     downloader_cat.spam()
00544       << _NOTIFY_HTTP_CHANNEL_ID 
00545       << "later run(), _state = " << _state
00546       << ", _done_state = " << _done_state << "\n";
00547   }
00548   */
00549 
00550   thread_yield();
00551   return true;
00552 }
00553 
00554 ////////////////////////////////////////////////////////////////////
00555 //     Function: HTTPChannel::open_read_body
00556 //       Access: Published
00557 //  Description: Returns a newly-allocated istream suitable for
00558 //               reading the body of the document.  This may only be
00559 //               called immediately after a call to get_document() or
00560 //               post_form(), or after a call to run() has returned
00561 //               false.
00562 //
00563 //               Note that, in nonblocking mode, the returned stream
00564 //               may report an early EOF, even before the actual end
00565 //               of file.  When this happens, you should call
00566 //               stream->is_closed() to determine whether you should
00567 //               attempt to read some more later.
00568 //
00569 //               The user is responsible for passing the returned
00570 //               istream to close_read_body() later.
00571 ////////////////////////////////////////////////////////////////////
00572 ISocketStream *HTTPChannel::
00573 open_read_body() {
00574   reset_body_stream();
00575 
00576   if ((_state != S_read_header && _state != S_begin_body) || _source.is_null()) {
00577     return NULL;
00578   }
00579 
00580   string transfer_coding = downcase(get_header_value("Transfer-Encoding"));
00581 
00582   ISocketStream *result;
00583   if (transfer_coding == "chunked") {
00584     // "chunked" transfer encoding.  This means we will have to decode
00585     // the length of the file as we read it in chunks.  The
00586     // IChunkedStream does this.
00587     _state = S_reading_body;
00588     _read_index++;
00589     result = new IChunkedStream(_source, this);
00590 
00591   } else {
00592     // If the transfer encoding is anything else, assume "identity".
00593     // This is just the literal characters following the header, up
00594     // until _file_size bytes have been read (if content-length was
00595     // specified), or till end of file otherwise.
00596     _state = S_reading_body;
00597     _read_index++;
00598     result = new IIdentityStream(_source, this, _got_file_size, _file_size);
00599   }
00600 
00601   result->_channel = this;
00602   _body_stream = result;
00603   _owns_body_stream = false;
00604 
00605   return result;
00606 }
00607 
00608 ////////////////////////////////////////////////////////////////////
00609 //     Function: HTTPChannel::close_read_body
00610 //       Access: Public
00611 //  Description: Closes a file opened by a previous call to
00612 //               open_read_body().  This really just deletes the
00613 //               istream pointer, but it is recommended to use this
00614 //               interface instead of deleting it explicitly, to help
00615 //               work around compiler issues.
00616 ////////////////////////////////////////////////////////////////////
00617 void HTTPChannel::
00618 close_read_body(istream *stream) const {
00619   if (stream != (istream *)NULL) {
00620     // For some reason--compiler bug in gcc 3.2?--explicitly deleting
00621     // the stream pointer does not call the appropriate global delete
00622     // function; instead apparently calling the system delete
00623     // function.  So we call the delete function by hand instead.
00624 #if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW)
00625     stream->~istream();
00626     (*global_operator_delete)(stream);
00627 #else
00628     delete stream;
00629 #endif
00630   }
00631 }
00632 
00633 ////////////////////////////////////////////////////////////////////
00634 //     Function: HTTPChannel::download_to_file
00635 //       Access: Published
00636 //  Description: Specifies the name of a file to download the
00637 //               resulting document to.  This should be called
00638 //               immediately after get_document() or
00639 //               begin_get_document() or related functions.
00640 //
00641 //               In the case of the blocking I/O methods like
00642 //               get_document(), this function will download the
00643 //               entire document to the file and return true if it was
00644 //               successfully downloaded, false otherwise.
00645 //
00646 //               In the case of non-blocking I/O methods like
00647 //               begin_get_document(), this function simply indicates an
00648 //               intention to download to the indicated file.  It
00649 //               returns true if the file can be opened for writing,
00650 //               false otherwise, but the contents will not be
00651 //               completely downloaded until run() has returned false.
00652 //               At this time, it is possible that a communications
00653 //               error will have left a partial file, so
00654 //               is_download_complete() may be called to test this.
00655 //
00656 //               If subdocument_resumes is true and the document in
00657 //               question was previously requested as a subdocument
00658 //               (i.e. get_subdocument() with a first_byte value
00659 //               greater than zero), this will automatically seek to
00660 //               the appropriate byte within the file for writing the
00661 //               output.  In this case, the file must already exist
00662 //               and must have at least first_byte bytes in it.  If
00663 //               subdocument_resumes is false, a subdocument will
00664 //               always be downloaded beginning at the first byte of
00665 //               the file.
00666 ////////////////////////////////////////////////////////////////////
00667 bool HTTPChannel::
00668 download_to_file(const Filename &filename, bool subdocument_resumes) {
00669   reset_download_to();
00670   _download_to_filename = filename;
00671   _download_to_filename.set_binary();
00672   _subdocument_resumes = subdocument_resumes;
00673 
00674   _download_dest = DD_file;
00675 
00676   if (_wanted_nonblocking && _state != S_read_header) {
00677     // In nonblocking mode, we can't start the download yet; that will
00678     // be done later as run() is called.
00679     return true;
00680   }
00681 
00682   // In normal, blocking mode, go ahead and do the download.
00683   if (!open_download_file()) {
00684     reset_download_to();
00685     return false;
00686   }
00687 
00688   while (run()) {
00689   }
00690   return is_download_complete() && is_valid();
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: HTTPChannel::download_to_ram
00695 //       Access: Published
00696 //  Description: Specifies a Ramfile object to download the
00697 //               resulting document to.  This should be called
00698 //               immediately after get_document() or
00699 //               begin_get_document() or related functions.
00700 //
00701 //               In the case of the blocking I/O methods like
00702 //               get_document(), this function will download the
00703 //               entire document to the Ramfile and return true if it
00704 //               was successfully downloaded, false otherwise.
00705 //
00706 //               In the case of non-blocking I/O methods like
00707 //               begin_get_document(), this function simply indicates an
00708 //               intention to download to the indicated Ramfile.  It
00709 //               returns true if the file can be opened for writing,
00710 //               false otherwise, but the contents will not be
00711 //               completely downloaded until run() has returned false.
00712 //               At this time, it is possible that a communications
00713 //               error will have left a partial file, so
00714 //               is_download_complete() may be called to test this.
00715 //
00716 //               If subdocument_resumes is true and the document in
00717 //               question was previously requested as a subdocument
00718 //               (i.e. get_subdocument() with a first_byte value
00719 //               greater than zero), this will automatically seek to
00720 //               the appropriate byte within the Ramfile for writing
00721 //               the output.  In this case, the Ramfile must already
00722 //               have at least first_byte bytes in it.
00723 ////////////////////////////////////////////////////////////////////
00724 bool HTTPChannel::
00725 download_to_ram(Ramfile *ramfile, bool subdocument_resumes) {
00726   nassertr(ramfile != (Ramfile *)NULL, false);
00727   reset_download_to();
00728   ramfile->_pos = 0;
00729   _download_to_ramfile = ramfile;
00730   _download_dest = DD_ram;
00731   _subdocument_resumes = (subdocument_resumes && _first_byte_delivered != 0);
00732 
00733   if (_wanted_nonblocking && _state != S_read_header) {
00734     // In nonblocking mode, we can't start the download yet; that will
00735     // be done later as run() is called.
00736     return true;
00737   }
00738 
00739   // In normal, blocking mode, go ahead and do the download.
00740   if (!open_download_file()) {
00741     reset_download_to();
00742     return false;
00743   }
00744 
00745   while (run()) {
00746   }
00747   return is_download_complete() && is_valid();
00748 }
00749 
00750 ////////////////////////////////////////////////////////////////////
00751 //     Function: HTTPChannel::download_to_stream
00752 //       Access: Published
00753 //  Description: Specifies the name of an ostream to download the
00754 //               resulting document to.  This should be called
00755 //               immediately after get_document() or
00756 //               begin_get_document() or related functions.
00757 //
00758 //               In the case of the blocking I/O methods like
00759 //               get_document(), this function will download the
00760 //               entire document to the file and return true if it was
00761 //               successfully downloaded, false otherwise.
00762 //
00763 //               In the case of non-blocking I/O methods like
00764 //               begin_get_document(), this function simply indicates an
00765 //               intention to download to the indicated file.  It
00766 //               returns true if the file can be opened for writing,
00767 //               false otherwise, but the contents will not be
00768 //               completely downloaded until run() has returned false.
00769 //               At this time, it is possible that a communications
00770 //               error will have left a partial file, so
00771 //               is_download_complete() may be called to test this.
00772 //
00773 //               If subdocument_resumes is true and the document in
00774 //               question was previously requested as a subdocument
00775 //               (i.e. get_subdocument() with a first_byte value
00776 //               greater than zero), this will automatically seek to
00777 //               the appropriate byte within the file for writing the
00778 //               output.  In this case, the file must already exist
00779 //               and must have at least first_byte bytes in it.  If
00780 //               subdocument_resumes is false, a subdocument will
00781 //               always be downloaded beginning at the first byte of
00782 //               the file.
00783 ////////////////////////////////////////////////////////////////////
00784 bool HTTPChannel::
00785 download_to_stream(ostream *strm, bool subdocument_resumes) {
00786   reset_download_to();
00787   _download_to_stream = strm;
00788   _download_to_stream->clear();
00789   _subdocument_resumes = subdocument_resumes;
00790 
00791   _download_dest = DD_stream;
00792 
00793   if (_wanted_nonblocking && _state != S_read_header) {
00794     // In nonblocking mode, we can't start the download yet; that will
00795     // be done later as run() is called.
00796     return true;
00797   }
00798 
00799   // In normal, blocking mode, go ahead and do the download.
00800   if (!open_download_file()) {
00801     reset_download_to();
00802     return false;
00803   }
00804 
00805   while (run()) {
00806   }
00807   return is_download_complete() && is_valid();
00808 }
00809 
00810 ////////////////////////////////////////////////////////////////////
00811 //     Function: HTTPChannel::get_connection
00812 //       Access: Published
00813 //  Description: Returns the connection that was established via a
00814 //               previous call to connect_to() or begin_connect_to(),
00815 //               or NULL if the connection attempt failed or if those
00816 //               methods have not recently been called.
00817 //
00818 //               This stream has been allocated from the free store.
00819 //               It is the user's responsibility to delete this
00820 //               pointer when finished with it.
00821 ////////////////////////////////////////////////////////////////////
00822 SocketStream *HTTPChannel::
00823 get_connection() {
00824   if (!is_connection_ready()) {
00825     return NULL;
00826   }
00827 
00828   BioStream *stream = _source->get_stream();
00829   _source->set_stream(NULL);
00830 
00831   // We're now passing ownership of the connection to the caller.
00832   if (downloader_cat.is_debug()) {
00833     downloader_cat.debug()
00834       << _NOTIFY_HTTP_CHANNEL_ID 
00835       << "passing ownership of connection to caller.\n";
00836   }
00837   reset_to_new();
00838 
00839   return stream;
00840 }
00841 
00842 ////////////////////////////////////////////////////////////////////
00843 //     Function: HTTPChannel::downcase
00844 //       Access: Public, Static
00845 //  Description: Returns the input string with all uppercase letters
00846 //               converted to lowercase.
00847 ////////////////////////////////////////////////////////////////////
00848 string HTTPChannel::
00849 downcase(const string &s) {
00850   string result;
00851   result.reserve(s.size());
00852   string::const_iterator p;
00853   for (p = s.begin(); p != s.end(); ++p) {
00854     result += tolower(*p);
00855   }
00856   return result;
00857 }
00858 
00859 ////////////////////////////////////////////////////////////////////
00860 //     Function: HTTPChannel::body_stream_destructs
00861 //       Access: Public
00862 //  Description: Called by ISocketStream destructor when _body_stream
00863 //               is destructing.
00864 ////////////////////////////////////////////////////////////////////
00865 void HTTPChannel::
00866 body_stream_destructs(ISocketStream *stream) {
00867   if (stream == _body_stream) {
00868     if (_state == S_reading_body) {
00869       switch (_body_stream->get_read_state()) {
00870       case ISocketStream::RS_complete:
00871         finished_body(false);
00872         break;
00873         
00874       case ISocketStream::RS_error:
00875         _state = HTTPChannel::S_failure;
00876         _status_entry._status_code = HTTPChannel::SC_lost_connection;
00877         break;
00878     
00879       default:
00880         break;
00881       }
00882     }
00883     _body_stream = NULL;
00884     _owns_body_stream = false;
00885   }
00886 }
00887 
00888 
00889 ////////////////////////////////////////////////////////////////////
00890 //     Function: HTTPChannel::reached_done_state
00891 //       Access: Private
00892 //  Description: Called by run() after it reaches the done state, this
00893 //               simply checks to see if a download was requested, and
00894 //               begins the download if it has been.
00895 ////////////////////////////////////////////////////////////////////
00896 bool HTTPChannel::
00897 reached_done_state() {
00898   /*
00899   if (downloader_cat.is_spam()) {
00900     downloader_cat.spam()
00901       << _NOTIFY_HTTP_CHANNEL_ID 
00902       << "terminating run(), _state = " << _state
00903       << ", _done_state = " << _done_state << "\n";
00904   }
00905   */
00906 
00907   if (_state == S_failure) {
00908     // We had to give up.  Each proxy we tried, in sequence, failed.
00909     // But maybe the last attempt didn't give us the most informative
00910     // response; go back and find the best one.
00911     if (!_status_list.empty()) {
00912       _status_list.push_back(_status_entry);
00913       if (downloader_cat.is_debug()) {
00914         downloader_cat.debug()
00915           << _NOTIFY_HTTP_CHANNEL_ID 
00916           << "Reexamining failure responses.\n";
00917       }
00918       size_t best_i = 0;
00919       if (downloader_cat.is_debug()) {
00920         downloader_cat.debug()
00921           << _NOTIFY_HTTP_CHANNEL_ID 
00922           << "  " << 0 << ". " << _status_list[0]._status_code << " "
00923           << _status_list[0]._status_string << "\n";
00924       }
00925       for (size_t i = 1; i < _status_list.size(); i++) {
00926         if (downloader_cat.is_debug()) {
00927           downloader_cat.debug()
00928             << _NOTIFY_HTTP_CHANNEL_ID 
00929             << "  " << i << ". " << _status_list[i]._status_code << " "
00930             << _status_list[i]._status_string << "\n";
00931         }
00932         if (more_useful_status_code(_status_list[i]._status_code, 
00933                                     _status_list[best_i]._status_code)) {
00934           best_i = i;
00935         }
00936       }
00937       if (downloader_cat.is_debug()) {
00938         downloader_cat.debug()
00939           << _NOTIFY_HTTP_CHANNEL_ID 
00940           << "chose index " << best_i << ", above.\n";
00941       }
00942       _status_entry = _status_list[best_i];
00943       _status_list.clear();
00944     }
00945 
00946     return false;
00947   }
00948 
00949   // We don't need the list of previous failures any more--we've connected.
00950   _status_list.clear();
00951 
00952   if (_download_dest == DD_none) {
00953     // All done.
00954     return false;
00955     
00956   } else {
00957     // Oops, we have to download the body now.
00958     open_read_body();
00959     if (_body_stream == (ISocketStream *)NULL) {
00960       if (downloader_cat.is_debug()) {
00961         downloader_cat.debug()
00962           << _NOTIFY_HTTP_CHANNEL_ID 
00963           << "Unable to download body: " << _request.get_url() << "\n";
00964       }
00965       return false;
00966 
00967     } else {
00968       _owns_body_stream = true;
00969       if (_state != S_reading_body) {
00970         reset_body_stream();
00971       }
00972       _started_download = true;
00973 
00974       _done_state = S_read_trailer;
00975       _last_run_time = TrueClock::get_global_ptr()->get_short_time();
00976       return true;
00977     }
00978   }
00979 }
00980   
00981 ////////////////////////////////////////////////////////////////////
00982 //     Function: HTTPChannel::run_try_next_proxy
00983 //       Access: Private
00984 //  Description: This state is reached when a previous connection
00985 //               attempt fails.  If we have multiple proxies in line
00986 //               to try, it sets us up for the next proxy and tries to
00987 //               connect again; otherwise, it sets the state to
00988 //               S_failure.
00989 ////////////////////////////////////////////////////////////////////
00990 bool HTTPChannel::
00991 run_try_next_proxy() {
00992   if (_proxy_next_index < _proxies.size()) {
00993     // Record the previous proxy's status entry, so we can come back
00994     // to it later if we get nonsense from the remaining proxies.
00995     _status_list.push_back(_status_entry);
00996     _status_entry = StatusEntry();
00997 
00998     // Now try the next proxy in sequence.
00999     _proxy = _proxies[_proxy_next_index];
01000     _proxy_auth = (HTTPAuthorization *)NULL;
01001     _proxy_next_index++;
01002     close_connection();
01003     reconsider_proxy();
01004     _state = S_connecting;
01005 
01006     return false;
01007   }
01008 
01009   // No more proxies to try, or we're not using a proxy.
01010   _state = S_failure;
01011   return false;
01012 }
01013   
01014 ////////////////////////////////////////////////////////////////////
01015 //     Function: HTTPChannel::run_connecting
01016 //       Access: Private
01017 //  Description: In this state, we have not yet established a
01018 //               network connection to the server (or proxy).
01019 ////////////////////////////////////////////////////////////////////
01020 bool HTTPChannel::
01021 run_connecting() {
01022   _status_entry = StatusEntry();
01023 
01024   if (BIO_do_connect(*_bio) <= 0) {
01025     if (BIO_should_retry(*_bio)) {
01026       _state = S_connecting_wait;
01027       return false;
01028     }
01029     downloader_cat.info()
01030       << _NOTIFY_HTTP_CHANNEL_ID 
01031       << "Could not connect to " << _bio->get_server_name() << ":" 
01032       << _bio->get_port() << "\n";
01033     OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
01034     _status_entry._status_code = SC_no_connection;
01035     _state = S_try_next_proxy;
01036     return false;
01037   }
01038 
01039   if (downloader_cat.is_debug()) {
01040     downloader_cat.debug()
01041       << _NOTIFY_HTTP_CHANNEL_ID 
01042       << "Connected to " << _bio->get_server_name() << ":" 
01043       << _bio->get_port() << "\n";
01044   }
01045 
01046   if (_proxy_tunnel_now) {
01047     if (_proxy.get_scheme() == "socks") {
01048       _state = S_socks_proxy_greet;
01049     } else {
01050       _state = S_http_proxy_ready;
01051     }
01052 
01053   } else {
01054     if (_want_ssl) {
01055       _state = S_setup_ssl;
01056     } else {
01057       _state = S_ready;
01058     }
01059   }
01060   return false;
01061 }
01062 
01063 ////////////////////////////////////////////////////////////////////
01064 //     Function: HTTPChannel::run_connecting_wait
01065 //       Access: Private
01066 //  Description: Here we have begun to establish a nonblocking
01067 //               connection, but we got a come-back-later message, so
01068 //               we are waiting for the socket to finish connecting.
01069 ////////////////////////////////////////////////////////////////////
01070 bool HTTPChannel::
01071 run_connecting_wait() {
01072   int fd = -1;
01073   BIO_get_fd(*_bio, &fd);
01074   if (fd < 0) {
01075     downloader_cat.warning()
01076       << _NOTIFY_HTTP_CHANNEL_ID 
01077       << "nonblocking socket BIO has no file descriptor.\n";
01078     // This shouldn't be possible.
01079     _status_entry._status_code = SC_internal_error;
01080     _state = S_try_next_proxy;
01081     return false;
01082   }
01083 
01084   if (downloader_cat.is_spam()) {
01085     downloader_cat.spam()
01086       << _NOTIFY_HTTP_CHANNEL_ID 
01087       << "waiting to connect to " << _request.get_url().get_server_and_port() << ".\n";
01088   }
01089   fd_set wset;
01090   FD_ZERO(&wset);
01091   FD_SET(fd, &wset);
01092   struct timeval tv;
01093   if (get_blocking_connect()) {
01094     // Since we'll be blocking on this connect, fill in the timeout
01095     // into the structure.
01096     tv.tv_sec = (int)_connect_timeout;
01097     tv.tv_usec = (int)((_connect_timeout - tv.tv_sec) * 1000000.0);
01098   } else {
01099     // We won't block on this connect, so select() for 0 time.
01100     tv.tv_sec = 0;
01101     tv.tv_usec = 0;
01102   }
01103   int errcode = select(fd + 1, NULL, &wset, NULL, &tv);
01104   if (errcode < 0) {
01105     downloader_cat.warning()
01106       << _NOTIFY_HTTP_CHANNEL_ID 
01107       << "Error in select.\n";
01108     // This shouldn't be possible.
01109     _status_entry._status_code = SC_internal_error;
01110     _state = S_try_next_proxy;
01111     return false;
01112   }
01113   
01114   if (errcode == 0) {
01115     // Nothing's happened so far; come back later.
01116     if (get_blocking_connect() ||
01117         (TrueClock::get_global_ptr()->get_short_time() - 
01118          _started_connecting_time > get_connect_timeout())) {
01119       // Time to give up.
01120       downloader_cat.info()
01121         << _NOTIFY_HTTP_CHANNEL_ID 
01122         << "Timeout connecting to " 
01123         << _request.get_url().get_server_and_port() 
01124         << " for " << _request.get_url()
01125         << ".\n";
01126       _status_entry._status_code = SC_timeout;
01127       _state = S_try_next_proxy;
01128       return false;
01129     }
01130     return true;
01131   }
01132   
01133   // The socket is now ready for writing.
01134   _state = S_connecting;
01135   return false;
01136 }
01137 
01138 
01139 ////////////////////////////////////////////////////////////////////
01140 //     Function: HTTPChannel::run_http_proxy_ready
01141 //       Access: Private
01142 //  Description: This state is reached only after first establishing a
01143 //               connection to the proxy, if a proxy is in use and we
01144 //               are tunneling through it via a CONNECT command.
01145 ////////////////////////////////////////////////////////////////////
01146 bool HTTPChannel::
01147 run_http_proxy_ready() {
01148   // If there's a request to be sent to the proxy, send it now.
01149   nassertr(!_proxy_request_text.empty(), false);
01150   if (!server_send(_proxy_request_text, false)) {
01151     return true;
01152   }
01153     
01154   // All done sending request.
01155   _state = S_http_proxy_request_sent;
01156   _sent_request_time = TrueClock::get_global_ptr()->get_short_time();
01157   return false;
01158 }
01159 
01160 ////////////////////////////////////////////////////////////////////
01161 //     Function: HTTPChannel::run_http_proxy_request_sent
01162 //       Access: Private
01163 //  Description: This state is reached only after we have sent a
01164 //               special message to the proxy and we are waiting for
01165 //               the proxy's response.  It is not used in the normal
01166 //               http-over-proxy case, which does not require a
01167 //               special message to the proxy.
01168 ////////////////////////////////////////////////////////////////////
01169 bool HTTPChannel::
01170 run_http_proxy_request_sent() {
01171   // Wait for the first line to come back from the server.
01172   string line;
01173   if (!server_getline_failsafe(line)) {
01174     return true;
01175   }
01176 
01177   // Skip unexpected blank lines.  We're just being generous here.
01178   while (line.empty()) {
01179     if (!server_getline_failsafe(line)) {
01180       return true;
01181     }
01182   }
01183 
01184   if (!parse_http_response(line)) {
01185     return false;
01186   }
01187 
01188   _state = S_http_proxy_reading_header;
01189   _current_field_name = string();
01190   _current_field_value = string();
01191   _headers.clear();
01192   _got_file_size = false;
01193   _got_transfer_file_size = false;
01194   return false;
01195 }
01196 
01197 ////////////////////////////////////////////////////////////////////
01198 //     Function: HTTPChannel::run_http_proxy_reading_header
01199 //       Access: Private
01200 //  Description: In this state we are reading the header lines from
01201 //               the proxy's response to our special message.
01202 ////////////////////////////////////////////////////////////////////
01203 bool HTTPChannel::
01204 run_http_proxy_reading_header() {
01205   if (parse_http_header()) {
01206     return true;
01207   }
01208 
01209   _redirect = get_header_value("Location");
01210   // We can take the proxy's word for it that this is the actual URL
01211   // for the redirect.
01212 
01213   _server_response_has_no_body = 
01214     (get_status_code() / 100 == 1 ||
01215      get_status_code() == 204 ||
01216      get_status_code() == 304);
01217 
01218   int last_status = _last_status_code;
01219   _last_status_code = get_status_code();
01220 
01221   if (get_status_code() == 407 && last_status != 407 && !_proxy.empty()) {
01222     // 407: not authorized to proxy.  Try to get the authorization.
01223     string authenticate_request = get_header_value("Proxy-Authenticate");
01224     _proxy_auth = _client->generate_auth(_proxy, true, authenticate_request);
01225     if (_proxy_auth != (HTTPAuthorization *)NULL) {
01226       _proxy_realm = _proxy_auth->get_realm();
01227       _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
01228       if (!_proxy_username.empty()) {
01229         make_proxy_request_text();
01230 
01231         // Roll the state forward to force a new request.
01232         _state = S_begin_body;
01233         return false;
01234       }
01235     }
01236   }
01237 
01238   if (!is_valid()) {
01239     // Proxy wouldn't open connection.
01240 
01241     // Change some of the status codes a proxy might return to
01242     // differentiate them from similar status codes the destination
01243     // server might have returned.
01244     if (get_status_code() != 407) {
01245       _status_entry._status_code += 1000;
01246     }
01247 
01248     _state = S_try_next_proxy;
01249     return false;
01250   }
01251 
01252   // Now we have a tunnel opened through the proxy.
01253   make_request_text();
01254 
01255   if (_want_ssl) {
01256     _state = S_setup_ssl;
01257   } else {
01258     _state = S_ready;
01259   }
01260 
01261   return false;
01262 }
01263 
01264 ////////////////////////////////////////////////////////////////////
01265 //     Function: HTTPChannel::run_socks_proxy_greet
01266 //       Access: Private
01267 //  Description: This state is reached only after first establishing a
01268 //               connection to a SOCKS proxy, with which we now have
01269 //               to negotiate a connection.
01270 ////////////////////////////////////////////////////////////////////
01271 bool HTTPChannel::
01272 run_socks_proxy_greet() {
01273   static const char socks_greeting[] = {
01274     0x05, // Socks version 5
01275     0x01, // Number of supported login methods
01276     0x00, // Login method 0: no authentication
01277     /*
01278     0x01, // Login method 1: GSSAPI
01279     0x02  // Login method 2: username/password
01280     */
01281   };
01282   static const int socks_greeting_len = sizeof(socks_greeting);
01283   if (!server_send(string(socks_greeting, socks_greeting_len), true)) {
01284     return true;
01285   }
01286   _sent_request_time = TrueClock::get_global_ptr()->get_short_time();
01287     
01288   // All done sending request.
01289   _state = S_socks_proxy_greet_reply;
01290   return false;
01291 }
01292 
01293 ////////////////////////////////////////////////////////////////////
01294 //     Function: HTTPChannel::run_socks_proxy_greet_reply
01295 //       Access: Private
01296 //  Description: We are waiting for the SOCKS proxy to respond to our
01297 //               greeting.
01298 ////////////////////////////////////////////////////////////////////
01299 bool HTTPChannel::
01300 run_socks_proxy_greet_reply() {
01301   string reply;
01302 
01303   // Get the two-byte reply from the SOCKS server.
01304   if (!server_get_failsafe(reply, 2)) {
01305     return true;
01306   }
01307 
01308   if (reply[0] != 0x05) {
01309     // We only speak Socks5.
01310     downloader_cat.info()
01311       << _NOTIFY_HTTP_CHANNEL_ID 
01312       << "Rejecting Socks version " << (int)reply[0] << "\n";
01313     _status_entry._status_code = SC_socks_invalid_version;
01314     _state = S_try_next_proxy;
01315     return false;
01316   }
01317 
01318   if (reply[1] == (char)0xff) {
01319     downloader_cat.info()
01320       << _NOTIFY_HTTP_CHANNEL_ID 
01321       << "Socks server does not accept our available login methods.\n";
01322     _status_entry._status_code = SC_socks_no_acceptable_login_method;
01323     _state = S_try_next_proxy;
01324     return false;
01325   }
01326 
01327   if (reply[1] == 0x00) {
01328     // No login method required.  Proceed directly to the connect
01329     // message.
01330     _state = S_socks_proxy_connect;
01331     return false;
01332   }
01333 
01334   // The server accepted a login method we didn't offer!
01335   downloader_cat.info()
01336     << _NOTIFY_HTTP_CHANNEL_ID 
01337     << "Socks server accepted unrequested login method "
01338     << (int)reply[1] << "\n";
01339   _status_entry._status_code = SC_socks_no_acceptable_login_method;
01340   _state = S_try_next_proxy;
01341   return false;
01342 }
01343 
01344 ////////////////////////////////////////////////////////////////////
01345 //     Function: HTTPChannel::run_socks_proxy_connect
01346 //       Access: Private
01347 //  Description: The SOCKS proxy has accepted us, and now we may issue
01348 //               the connect request.
01349 ////////////////////////////////////////////////////////////////////
01350 bool HTTPChannel::
01351 run_socks_proxy_connect() {
01352   static const char socks_connect[] = {
01353     0x05, // Socks version 5
01354     0x01, // Command 1: connect
01355     0x00, // reserved
01356     0x03, // DNS name
01357   };
01358   static const int socks_connect_len = sizeof(socks_connect);
01359 
01360   string hostname = _request.get_url().get_server();
01361   int port = _request.get_url().get_port();
01362 
01363   if (downloader_cat.is_debug()) {
01364     downloader_cat.debug()
01365       << _NOTIFY_HTTP_CHANNEL_ID 
01366       << "Requesting SOCKS5 connection to " 
01367       << _request.get_url().get_server_and_port() << "\n";
01368   }
01369 
01370   string connect = 
01371     string(socks_connect, socks_connect_len) +
01372     string(1, (char)hostname.length()) +
01373     hostname +
01374     string(1, (char)((port >> 8) & 0xff)) +
01375     string(1, (char)(port & 0xff));
01376 
01377   if (!server_send(connect, true)) {
01378     return true;
01379   }
01380   _sent_request_time = TrueClock::get_global_ptr()->get_short_time();
01381     
01382   _state = S_socks_proxy_connect_reply;
01383   return false;
01384 }
01385 
01386 ////////////////////////////////////////////////////////////////////
01387 //     Function: HTTPChannel::run_socks_proxy_connect_reply
01388 //       Access: Private
01389 //  Description: We are waiting for the SOCKS proxy to honor our
01390 //               connect request.
01391 ////////////////////////////////////////////////////////////////////
01392 bool HTTPChannel::
01393 run_socks_proxy_connect_reply() {
01394   string reply;
01395 
01396   // Get the first two bytes of the connect reply.
01397   if (!server_get_failsafe(reply, 2)) {
01398     return true;
01399   }
01400 
01401   if (reply[0] != 0x05) {
01402     // We only speak Socks5.
01403     downloader_cat.info()
01404       << _NOTIFY_HTTP_CHANNEL_ID 
01405       << "Rejecting Socks version " << (int)reply[0] << "\n";
01406     close_connection();  // connection is now bad.
01407     _status_entry._status_code = SC_socks_invalid_version;
01408     _state = S_try_next_proxy;
01409     return false;
01410   }
01411 
01412   if (reply[1] != 0x00) {
01413     downloader_cat.info()
01414       << _NOTIFY_HTTP_CHANNEL_ID 
01415       << "Connection refused, SOCKS code " << (int)reply[1] << "\n";
01416     /*
01417       Socks error codes (from RFC1928):
01418              o  X'00' succeeded
01419              o  X'01' general SOCKS server failure
01420              o  X'02' connection not allowed by ruleset
01421              o  X'03' Network unreachable
01422              o  X'04' Host unreachable
01423              o  X'05' Connection refused
01424              o  X'06' TTL expired
01425              o  X'07' Command not supported
01426              o  X'08' Address type not supported
01427              o  X'09' to X'FF' unassigned
01428     */
01429 
01430     switch (reply[1]) {
01431     case 0x03:
01432     case 0x04:
01433     case 0x05:
01434     case 0x06:
01435       // These generally mean the same thing: the SOCKS proxy tried,
01436       // but couldn't reach the host.
01437       _status_entry._status_code = SC_socks_no_connection;
01438       break;
01439 
01440     default:
01441       _status_entry._status_code = SC_socks_refused;
01442     }
01443     
01444     close_connection();  // connection is now bad.
01445     _state = S_try_next_proxy;
01446     return false;
01447   }
01448 
01449   // Now put those bytes back, and get five bytes of the reply.
01450   _working_get = reply;
01451   if (!server_get_failsafe(reply, 5)) {
01452     return true;
01453   }
01454 
01455   // Figure out how many bytes total we will expect for the reply.
01456   int total_bytes = 6;
01457 
01458   switch (reply[3]) {
01459   case 0x01:  // IPv4
01460     total_bytes += 4;
01461     break;
01462 
01463   case 0x03:  // DNS
01464     total_bytes += (unsigned int)reply[4];
01465     break;
01466 
01467   default:
01468     downloader_cat.info()
01469       << _NOTIFY_HTTP_CHANNEL_ID 
01470       << "Unsupported SOCKS address type: " << (int)reply[3] << "\n";
01471     _status_entry._status_code = SC_socks_invalid_version;
01472     _state = S_try_next_proxy;
01473     return false;
01474   }
01475 
01476   // Now put back the bytes we've read so far, and get the rest of
01477   // them.
01478   _working_get = reply;
01479   if (!server_get_failsafe(reply, total_bytes)) {
01480     return true;
01481   }
01482 
01483   if (downloader_cat.is_debug()) {
01484     // Finally, we can decode the whole thing.
01485     string connect_host;
01486 
01487     switch (reply[3]) {
01488     case 0x01:  // IPv4
01489       {
01490         ostringstream strm;
01491         strm << (unsigned int)(unsigned char)reply[4] << "." 
01492              << (unsigned int)(unsigned char)reply[5] << "."
01493              << (unsigned int)(unsigned char)reply[6] << "." 
01494              << (unsigned int)(unsigned char)reply[7];
01495         connect_host = strm.str();
01496       }
01497       break;
01498       
01499     case 0x03:  // DNS
01500       connect_host = string(&reply[5], (unsigned int)reply[4]);
01501       break;
01502     }
01503     
01504     int connect_port =
01505       (((unsigned int)(unsigned char)reply[total_bytes - 2]) << 8) |
01506       ((unsigned int)(unsigned char)reply[total_bytes - 1]);
01507     
01508     downloader_cat.debug()
01509       << _NOTIFY_HTTP_CHANNEL_ID 
01510       << _proxy << " directed us to " << connect_host << ":"
01511       << connect_port << "\n";
01512   }
01513 
01514   if (_want_ssl) {
01515     _state = S_setup_ssl;
01516   } else {
01517     _state = S_ready;
01518   }
01519 
01520   return false;
01521 }
01522 
01523 ////////////////////////////////////////////////////////////////////
01524 //     Function: HTTPChannel::run_setup_ssl
01525 //       Access: Private
01526 //  Description: This state begins elevating our existing, unsecure
01527 //               connection to a secure, SSL connection.
01528 ////////////////////////////////////////////////////////////////////
01529 bool HTTPChannel::
01530 run_setup_ssl() {
01531   _sbio = BIO_new_ssl(_client->get_ssl_ctx(), true);
01532   BIO_push(_sbio, *_bio);
01533 
01534   SSL *ssl = NULL;
01535   BIO_get_ssl(_sbio, &ssl);
01536   nassertr(ssl != (SSL *)NULL, false);
01537 
01538   // We only take one word at a time from the _cipher_list.  If that
01539   // connection fails, then we take the next word.
01540   string cipher_list = _cipher_list;
01541   if (!cipher_list.empty()) {
01542     size_t space = cipher_list.find(" ");
01543     if (space != string::npos) {
01544       cipher_list = cipher_list.substr(0, space);
01545     }
01546   }
01547 
01548   if (downloader_cat.is_debug()) {
01549     downloader_cat.debug()
01550       << _NOTIFY_HTTP_CHANNEL_ID 
01551       << "Setting ssl-cipher-list '" << cipher_list << "'\n";
01552   }
01553   int result = SSL_set_cipher_list(ssl, cipher_list.c_str());
01554   if (result == 0) {
01555     downloader_cat.error()
01556       << _NOTIFY_HTTP_CHANNEL_ID 
01557       << "Invalid cipher list: '" << cipher_list << "'\n";
01558     OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
01559     _status_entry._status_code = SC_ssl_internal_failure;
01560     _state = S_failure;
01561     return false;
01562   }
01563 
01564   // It would be nice to use something like SSL_set_client_cert_cb()
01565   // here to set a callback to provide the certificate should it be
01566   // requested, or even to potentially provide any of a number of
01567   // certificates according to the server's CA presented, but that
01568   // interface as provided by OpenSSL is broken since there's no way
01569   // to pass additional data to the callback function (and hence no
01570   // way to tie it back to the HTTPChannel object, other than by
01571   // building a messy mapping of SSL pointers back to HTTPChannel
01572   // pointers).
01573   if (_client->load_client_certificate()) {
01574     SSL_use_certificate(ssl, _client->_client_certificate_pub);
01575     SSL_use_PrivateKey(ssl, _client->_client_certificate_priv);
01576     if (!SSL_check_private_key(ssl)) {
01577       downloader_cat.warning()
01578         << _NOTIFY_HTTP_CHANNEL_ID 
01579         << "Client private key does not match public key!\n";
01580     }
01581   }
01582 
01583   if (downloader_cat.is_spam()) {
01584     downloader_cat.spam()
01585       << _NOTIFY_HTTP_CHANNEL_ID 
01586       << "SSL Ciphers available:\n";
01587     const char *name;
01588     int pri = 0;
01589     name = SSL_get_cipher_list(ssl, pri);
01590     while (name != NULL) {
01591       downloader_cat.spam()
01592         << _NOTIFY_HTTP_CHANNEL_ID 
01593         << "  " << pri + 1 << ". " << name << "\n";
01594       pri++;
01595       name = SSL_get_cipher_list(ssl, pri);
01596     }
01597   }
01598 
01599   if (downloader_cat.is_debug()) {
01600     downloader_cat.debug()
01601       << _NOTIFY_HTTP_CHANNEL_ID 
01602       << "performing SSL handshake\n";
01603   }
01604   _state = S_ssl_handshake;
01605 
01606   // We start the connect timer over again when we reach the SSL
01607   // handshake.
01608   _started_connecting_time = 
01609     TrueClock::get_global_ptr()->get_short_time();
01610 
01611   return false;
01612 }
01613 
01614 ////////////////////////////////////////////////////////////////////
01615 //     Function: HTTPChannel::run_ssl_handshake
01616 //       Access: Private
01617 //  Description: This state performs the SSL handshake with the
01618 //               server, and also verifies the server's identity when
01619 //               the handshake has successfully completed.
01620 ////////////////////////////////////////////////////////////////////
01621 bool HTTPChannel::
01622 run_ssl_handshake() {
01623   if (BIO_do_handshake(_sbio) <= 0) {
01624     if (BIO_should_retry(_sbio)) {
01625       double elapsed =
01626         TrueClock::get_global_ptr()->get_short_time() -
01627         _started_connecting_time;
01628       if (elapsed <= get_connect_timeout() + _extra_ssl_handshake_time) {
01629         // Keep trying.
01630         return true;
01631       }
01632       // Time to give up on the handshake.
01633     }
01634 
01635     downloader_cat.info()
01636       << _NOTIFY_HTTP_CHANNEL_ID 
01637       << "Could not establish SSL handshake with " 
01638       << _request.get_url().get_server_and_port() << "\n";
01639     OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
01640 
01641     // It seems to be an error to free sbio at this point; perhaps
01642     // it's already been freed?
01643 
01644     if (!_cipher_list.empty()) {
01645       // If we've got another cipher to try, do so.
01646       size_t space = _cipher_list.find(" ");
01647       if (space != string::npos) {
01648         while (space < _cipher_list.length() && _cipher_list[space] == ' ') {
01649           ++space;
01650         }
01651         _cipher_list = _cipher_list.substr(space);
01652         if (!_cipher_list.empty()) {
01653           close_connection();
01654           reconsider_proxy();
01655           _state = S_connecting;
01656           return false;
01657         }
01658       }
01659     }
01660 
01661     // All done trying ciphers; they all failed.
01662     _cipher_list = _client->get_cipher_list();
01663     _status_entry._status_code = SC_ssl_no_handshake;
01664     _state = S_failure;
01665     return false;
01666   }
01667 
01668   SSL *ssl = NULL;
01669   BIO_get_ssl(_sbio, &ssl);
01670   nassertr(ssl != (SSL *)NULL, false);
01671 
01672   if (!_nonblocking) {
01673     SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
01674   }
01675 
01676   const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
01677   if (cipher == (const SSL_CIPHER *)NULL) {
01678     downloader_cat.warning()
01679       << _NOTIFY_HTTP_CHANNEL_ID 
01680       << "No current cipher on SSL connection.\n";
01681   } else {
01682     if (downloader_cat.is_debug()) {
01683       downloader_cat.debug()
01684         << _NOTIFY_HTTP_CHANNEL_ID 
01685         << "Using cipher " << SSL_CIPHER_get_name((SSL_CIPHER *) cipher) << "\n";
01686     }
01687   }
01688 
01689   // Now that we've made an SSL handshake, we can use the SSL bio to
01690   // do all of our communication henceforth.
01691   _bio->set_bio(_sbio);
01692   _sbio = NULL;
01693 
01694   X509 *cert = SSL_get_peer_certificate(ssl);
01695   if (cert == (X509 *)NULL) {
01696     downloader_cat.info()
01697       << _NOTIFY_HTTP_CHANNEL_ID 
01698       << "No certificate was presented by server.\n";
01699 
01700     // This shouldn't be possible, per the SSL specs.
01701     _status_entry._status_code = SC_ssl_invalid_server_certificate;
01702     _state = S_failure;
01703     return false;
01704   }
01705   
01706   X509_NAME *subject = X509_get_subject_name(cert);
01707   if (downloader_cat.is_debug()) {
01708     string org_name = get_x509_name_component(subject, NID_organizationName);
01709     string org_unit_name = get_x509_name_component(subject, NID_organizationalUnitName);
01710     string common_name = get_x509_name_component(subject, NID_commonName);
01711     
01712     downloader_cat.debug()
01713       << _NOTIFY_HTTP_CHANNEL_ID 
01714       << "Server is " << common_name << " from " << org_unit_name
01715       << " / " << org_name << "\n";
01716 
01717     if (downloader_cat.is_spam()) {
01718       downloader_cat.spam()
01719         << _NOTIFY_HTTP_CHANNEL_ID 
01720         << "Received certificate from server:\n" << flush;
01721       X509_print_fp(stderr, cert);
01722       fflush(stderr);
01723     }
01724   }
01725 
01726   bool cert_preapproved = false;
01727   bool cert_name_preapproved = false;
01728   check_preapproved_server_certificate(cert, cert_preapproved, cert_name_preapproved);
01729 
01730   // Now verify the server certificate is valid.
01731   long verify_result = SSL_get_verify_result(ssl);
01732   bool cert_valid = true;
01733 
01734   if (verify_result == X509_V_ERR_CERT_HAS_EXPIRED) {
01735     downloader_cat.info()
01736       << _NOTIFY_HTTP_CHANNEL_ID 
01737       << "Expired certificate from " << _request.get_url().get_server_and_port() << "\n";
01738     if (_client->get_verify_ssl() == HTTPClient::VS_normal && !cert_preapproved) { 
01739       cert_valid = false;
01740     }
01741 
01742   } else if (verify_result == X509_V_ERR_CERT_NOT_YET_VALID) {
01743     downloader_cat.info()
01744       << _NOTIFY_HTTP_CHANNEL_ID 
01745       << "Premature certificate from " << _request.get_url().get_server_and_port() << "\n";
01746     if (_client->get_verify_ssl() == HTTPClient::VS_normal && !cert_preapproved) {
01747       cert_valid = false;
01748     }
01749 
01750   } else if (verify_result == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
01751              verify_result == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
01752     downloader_cat.info()
01753       << _NOTIFY_HTTP_CHANNEL_ID 
01754       << "Self-signed certificate from " << _request.get_url().get_server_and_port() << "\n";
01755     if (_client->get_verify_ssl() != HTTPClient::VS_no_verify && !cert_preapproved) {
01756       cert_valid = false;
01757     }
01758 
01759   } else if (verify_result != X509_V_OK) {
01760     downloader_cat.info()
01761       << _NOTIFY_HTTP_CHANNEL_ID 
01762       << "Unable to verify identity of " << _request.get_url().get_server_and_port()
01763       << ", verify error code " << verify_result << "\n";
01764     if (_client->get_verify_ssl() != HTTPClient::VS_no_verify && !cert_preapproved) {
01765       cert_valid = false;
01766     }
01767   }
01768   
01769   if (!cert_valid) {
01770     _status_entry._status_code = SC_ssl_invalid_server_certificate;
01771     _state = S_failure;
01772     return false;
01773   }
01774   
01775   if (_client->get_verify_ssl() != HTTPClient::VS_no_verify && !cert_name_preapproved) {
01776     // Check that the server is someone we expected to be talking
01777     // to.
01778     if (!validate_server_name(cert)) {
01779       _status_entry._status_code = SC_ssl_unexpected_server;
01780       _state = S_failure;
01781       return false;
01782     }
01783   }
01784   
01785   X509_free(cert);
01786 
01787   _state = S_ready;
01788   return false;
01789 }
01790 
01791 ////////////////////////////////////////////////////////////////////
01792 //     Function: HTTPChannel::run_ready
01793 //       Access: Private
01794 //  Description: This is the main "ready" state.  In this state, we
01795 //               have established a (possibly secure) connection to
01796 //               the server (or proxy), and the server (or proxy) is
01797 //               idle and waiting for us to send a request.
01798 //
01799 //               If persistent_connection is true, we will generally
01800 //               come back to this state after finishing each request
01801 //               on a given connection.
01802 ////////////////////////////////////////////////////////////////////
01803 bool HTTPChannel::
01804 run_ready() {
01805   // If there's a request to be sent upstream, send it now.
01806   if (!_request_text.empty()) {
01807    if (!server_send(_request_text, false)) {
01808       return true;
01809     }
01810   }
01811     
01812   // All done sending request.
01813   _state = S_request_sent;
01814   _sent_request_time = TrueClock::get_global_ptr()->get_short_time();
01815   return false;
01816 }
01817 
01818 ////////////////////////////////////////////////////////////////////
01819 //     Function: HTTPChannel::run_request_sent
01820 //       Access: Private
01821 //  Description: In this state we have sent our request to the server
01822 //               (or proxy) and we are waiting for a response.
01823 ////////////////////////////////////////////////////////////////////
01824 bool HTTPChannel::
01825 run_request_sent() {
01826   // Wait for the first line to come back from the server.
01827   string line;
01828   if (!server_getline_failsafe(line)) {
01829     return true;
01830   }
01831 
01832   // Skip unexpected blank lines.  We're just being generous here.
01833   while (line.empty()) {
01834     if (!server_getline_failsafe(line)) {
01835       return true;
01836     }
01837   }
01838 
01839   if (!parse_http_response(line)) {
01840     // Not an HTTP response.  _state is already set appropriately.
01841     return false;
01842   }
01843 
01844   _state = S_reading_header;
01845   _current_field_name = string();
01846   _current_field_value = string();
01847   _headers.clear();
01848   _got_file_size = false;
01849   _got_transfer_file_size = false;
01850   return false;
01851 }
01852 
01853 ////////////////////////////////////////////////////////////////////
01854 //     Function: HTTPChannel::run_reading_header
01855 //       Access: Private
01856 //  Description: In this state we have received the first response to
01857 //               our request from the server (or proxy) and we are
01858 //               reading the set of header lines preceding the
01859 //               requested document.
01860 ////////////////////////////////////////////////////////////////////
01861 bool HTTPChannel::
01862 run_reading_header() {
01863   if (parse_http_header()) {
01864     if (_bio.is_null()) {
01865       downloader_cat.info()
01866         << _NOTIFY_HTTP_CHANNEL_ID 
01867         << "Connection lost while reading HTTP response.\n";
01868       if (_response_type == RT_http_hangup) {
01869         // This was our second hangup in a row.  Give up.
01870         _status_entry._status_code = SC_lost_connection;
01871         _state = S_try_next_proxy;
01872         
01873       } else {
01874         // Try again, once.
01875         _response_type = RT_http_hangup;
01876       }
01877 
01878     } else {
01879       double elapsed =
01880         TrueClock::get_global_ptr()->get_short_time() -
01881         _sent_request_time;
01882       if (elapsed > get_http_timeout()) {
01883         // Time to give up.
01884         downloader_cat.info()
01885           << _NOTIFY_HTTP_CHANNEL_ID 
01886           << "Timeout waiting for "
01887           << _request.get_url().get_server_and_port() 
01888           << " in run_reading_header (" << elapsed 
01889           << " seconds elapsed).\n";
01890         _status_entry._status_code = SC_timeout;
01891         _state = S_try_next_proxy;
01892       }
01893     }
01894     return true;
01895   }
01896   _response_type = RT_http_complete;
01897 
01898   // Ok, we've established an HTTP connection to the server.  Our
01899   // extra send headers have done their job; clear them for next time.
01900   clear_extra_headers();
01901 
01902   _server_response_has_no_body = 
01903     (get_status_code() / 100 == 1 ||
01904      get_status_code() == 204 ||
01905      get_status_code() == 304 || 
01906      _method == HTTPEnum::M_head);
01907 
01908   // Look for key properties in the header fields.
01909   if (get_status_code() == 206) {
01910     string content_range = get_header_value("Content-Range");
01911     if (content_range.empty()) {
01912       downloader_cat.warning()
01913         << _NOTIFY_HTTP_CHANNEL_ID 
01914         << "Got 206 response without Content-Range header!\n";
01915       _status_entry._status_code = SC_invalid_http;
01916       _state = S_failure;
01917       return false;
01918 
01919     } else {
01920       if (!parse_content_range(content_range)) {
01921         downloader_cat.warning()
01922           << _NOTIFY_HTTP_CHANNEL_ID 
01923           << "Couldn't parse Content-Range: " << content_range << "\n";
01924         _status_entry._status_code = SC_invalid_http;
01925         _state = S_failure;
01926         return false;
01927       }
01928     }
01929 
01930   } else {
01931     _first_byte_delivered = 0;
01932     _last_byte_delivered = 0;
01933   }
01934   if (downloader_cat.is_debug()) {
01935     if (_first_byte_requested != 0 || _last_byte_requested != 0 ||
01936         _first_byte_delivered != 0 || _last_byte_delivered != 0) {
01937       downloader_cat.debug()
01938         << _NOTIFY_HTTP_CHANNEL_ID 
01939         << "Requested byte range " << _first_byte_requested
01940         << " to " << _last_byte_delivered
01941         << "; server delivers range " << _first_byte_delivered
01942         << " to " << _last_byte_delivered
01943         << "\n";
01944     }
01945   }
01946 
01947   // Set the _document_spec to reflect what we just retrieved.
01948   _document_spec = DocumentSpec(_request.get_url());
01949   string tag = get_header_value("ETag");
01950   if (!tag.empty()) {
01951     _document_spec.set_tag(HTTPEntityTag(tag));
01952   }
01953   string date = get_header_value("Last-Modified");
01954   if (!date.empty()) {
01955     _document_spec.set_date(HTTPDate(date));
01956   }
01957 
01958   // In case we've got a download in effect, now we know what the
01959   // first byte of the subdocument request will be, so we can open the
01960   // file and position it.
01961   if (_server_response_has_no_body) {
01962     // Never mind on the download.
01963     reset_download_to();
01964   }
01965 
01966   if (!open_download_file()) {
01967     return false;
01968   }
01969 
01970   _got_expected_file_size = false;
01971   _got_file_size = false;
01972   _got_transfer_file_size = false;
01973   
01974   string content_length = get_header_value("Content-Length");
01975   if (!content_length.empty()) {
01976     _file_size = atoi(content_length.c_str());
01977     _got_file_size = true;
01978 
01979   } else if (get_status_code() == 206) {
01980     // Well, we didn't get a content-length from the server, but we
01981     // can infer the number of bytes based on the range we're given.
01982     _file_size = _last_byte_delivered - _first_byte_delivered + 1;
01983     _got_file_size = true;
01984   }
01985   _redirect = get_header_value("Location");
01986 
01987   // The server might have given us just a filename for the redirect.
01988   // In that case, it's relative to the same server.  If it's a
01989   // relative path, it's relative to the same directory.
01990   if (_redirect.has_path() && !_redirect.has_authority()) {
01991     URLSpec url = _document_spec.get_url();
01992     Filename path = _redirect.get_path();
01993     if (path.is_local()) {
01994       Filename rel_to = Filename(url.get_path()).get_dirname();
01995       _redirect.set_path(Filename(rel_to, path));
01996     }
01997     _redirect.set_scheme(url.get_scheme());
01998     _redirect.set_authority(url.get_authority());
01999   }
02000 
02001   _state = S_read_header;
02002 
02003   if (_server_response_has_no_body && will_close_connection()) {
02004     // If the server said it will close the connection, we should
02005     // close it too.
02006     close_connection();
02007   }
02008 
02009   // Handle automatic retries and redirects.
02010   int last_status = _last_status_code;
02011   _last_status_code = get_status_code();
02012 
02013   if (get_status_code() == 407 && last_status != 407 && !_proxy.empty()) {
02014     // 407: not authorized to proxy.  Try to get the authorization.
02015     string authenticate_request = get_header_value("Proxy-Authenticate");
02016     _proxy_auth = 
02017       _client->generate_auth(_proxy, true, authenticate_request);
02018     if (_proxy_auth != (HTTPAuthorization *)NULL) {
02019       _proxy_realm = _proxy_auth->get_realm();
02020       _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
02021       if (!_proxy_username.empty()) {
02022         make_request_text();
02023 
02024         // Roll the state forward to force a new request.
02025         _state = S_begin_body;
02026         return false;
02027       }
02028     }
02029   }
02030 
02031   if (get_status_code() == 401 && last_status != 401) {
02032     // 401: not authorized to remote server.  Try to get the authorization.
02033     string authenticate_request = get_header_value("WWW-Authenticate");
02034     _www_auth = _client->generate_auth(_request.get_url(), false, authenticate_request);
02035     if (_www_auth != (HTTPAuthorization *)NULL) {
02036       _www_realm = _www_auth->get_realm();
02037       _www_username = _client->select_username(_request.get_url(), false, _www_realm);
02038       if (!_www_username.empty()) {
02039         make_request_text();
02040       
02041         // Roll the state forward to force a new request.
02042         _state = S_begin_body;
02043         return false;
02044       }
02045     }
02046   }
02047 
02048   if ((get_status_code() == 300 || 
02049        get_status_code() == 301 ||
02050        get_status_code() == 302 ||
02051        get_status_code() == 303 ||
02052        get_status_code() == 307) && !get_redirect().empty()) {
02053     // Redirect.  Should we handle it automatically?
02054 
02055     // According to the letter of RFC 2616, 301 and 302 responses to
02056     // POST requests must not be automatically redirected without
02057     // confirmation by the user.  In reality, browsers do allow
02058     // automatic redirection of these responses, changing the POST to
02059     // a GET, and we reproduce this behavior here.
02060     if (_method == HTTPEnum::M_post) {
02061       _method = HTTPEnum::M_get;
02062       _body = string();
02063     }
02064 
02065     if (_method == HTTPEnum::M_get || _method == HTTPEnum::M_head) {
02066       // Sure!
02067       URLSpec new_url = get_redirect();
02068       if (find(_redirect_trail.begin(), _redirect_trail.end(),
02069                new_url) != _redirect_trail.end()) {
02070         downloader_cat.warning()
02071           << _NOTIFY_HTTP_CHANNEL_ID 
02072           << "cycle detected in redirect to " << new_url << "\n";
02073         
02074       } else {
02075         _redirect_trail.push_back(new_url);
02076 
02077         if (downloader_cat.is_debug()) {
02078           downloader_cat.debug()
02079             << _NOTIFY_HTTP_CHANNEL_ID 
02080             << "following redirect to " << new_url << "\n";
02081         }
02082         if (_request.get_url().has_username()) {
02083           new_url.set_username(_request.get_url().get_username());
02084         }
02085         reset_url(_request.get_url(), new_url);
02086         _request.set_url(new_url);
02087         _want_ssl = _request.get_url().is_ssl();
02088         reconsider_proxy();
02089         make_header();
02090         make_request_text();
02091 
02092         // Roll the state forward to force a new request.
02093         _state = S_begin_body;
02094         return false;
02095       }
02096     }
02097   }
02098 
02099   if (_state == S_read_header && 
02100       ((get_status_code() / 100) == 4 || (get_status_code() / 100) == 5) &&
02101       _proxy_serves_document && _proxy_next_index < _proxies.size()) {
02102     // If we were using a proxy (but not tunneling through the proxy)
02103     // and we got some kind of a server error, try the next proxy in
02104     // sequence (if we have one).  This handles the case of a working
02105     // proxy that cannot see the host (and so returns 504 or something
02106     // along those lines).  Some proxies are so broken they return a
02107     // 404 in this case, so we have to consider that along the same
02108     // lines.
02109     _state = S_try_next_proxy;
02110     return false;
02111   }
02112 
02113   // Otherwise, we're good to go.
02114   return false;
02115 }
02116 
02117 ////////////////////////////////////////////////////////////////////
02118 //     Function: HTTPChannel::run_start_direct_file_read
02119 //       Access: Private
02120 //  Description: This is the first state when reading a file:// URL.
02121 //               All it does is skip past the non-existent "header".
02122 ////////////////////////////////////////////////////////////////////
02123 bool HTTPChannel::
02124 run_start_direct_file_read() {
02125   _state = S_read_header;
02126   if (!open_download_file()) {
02127     return false;
02128   }
02129   return false;
02130 }
02131 
02132 ////////////////////////////////////////////////////////////////////
02133 //     Function: HTTPChannel::run_read_header
02134 //       Access: Private
02135 //  Description: In this state we have completely read the header
02136 //               lines returned by the server (or proxy) in response
02137 //               to our request.  This state represents the normal
02138 //               stopping point of a call to get_document(), etc.;
02139 //               further reads will return the body of the request,
02140 //               the requested document.
02141 //
02142 //               Normally run_read_header() is not called unless the
02143 //               user has elected not to read the returned document
02144 //               himself.  In fact, the state itself only exists so we
02145 //               can make a distinction between S_read_header and
02146 //               S_begin_body, where S_read_header is safe to return
02147 //               to the user and S_begin_body means we need to start
02148 //               skipping the document.
02149 ////////////////////////////////////////////////////////////////////
02150 bool HTTPChannel::
02151 run_read_header() {
02152   _state = S_begin_body;
02153   return false;
02154 }
02155 
02156 ////////////////////////////////////////////////////////////////////
02157 //     Function: HTTPChannel::run_begin_body
02158 //       Access: Private
02159 //  Description: This state begins to skip over the body in
02160 //               preparation for making a new request.
02161 ////////////////////////////////////////////////////////////////////
02162 bool HTTPChannel::
02163 run_begin_body() {
02164   if (will_close_connection()) {
02165     // If the socket will close anyway, no point in skipping past the
02166     // previous body; just reset.
02167     if (downloader_cat.is_debug()) {
02168       downloader_cat.debug()
02169         << _NOTIFY_HTTP_CHANNEL_ID 
02170         << "resetting to begin body; server would close anyway.\n";
02171     }
02172     reset_to_new();
02173     return false;
02174   }
02175 
02176   if (_server_response_has_no_body) {
02177     // We have already "read" the nonexistent body.
02178     _state = S_read_trailer;
02179 
02180   } else if (get_file_size() > (int)_skip_body_size) {
02181     // If we know the size of the body we are about to skip and it's
02182     // too large, then don't bother skipping it--just drop the
02183     // connection and get a new one.
02184     if (downloader_cat.is_debug()) {
02185       downloader_cat.debug()
02186         << _NOTIFY_HTTP_CHANNEL_ID 
02187         << "Dropping connection rather than skipping past " 
02188         << get_file_size() << " bytes.\n";
02189     }
02190     reset_to_new();
02191 
02192   } else {
02193     open_read_body();
02194     if (_body_stream == (ISocketStream *)NULL) {
02195       if (downloader_cat.is_debug()) {
02196         downloader_cat.debug()
02197           << _NOTIFY_HTTP_CHANNEL_ID 
02198           << "Unable to skip body.\n";
02199       }
02200       reset_to_new();
02201       
02202     } else {
02203       _owns_body_stream = true;
02204       if (_state != S_reading_body) {
02205         reset_body_stream();
02206       }
02207     }
02208   }
02209 
02210   return false;
02211 }
02212 
02213 ////////////////////////////////////////////////////////////////////
02214 //     Function: HTTPChannel::run_reading_body
02215 //       Access: Private
02216 //  Description: In this state we are in the process of reading the
02217 //               response's body.  We will only come to this function
02218 //               if the user did not choose to read the entire body
02219 //               himself (by calling open_read_body()).
02220 //
02221 //               In this case we should skip past the body to reset
02222 //               the connection for making a new request.
02223 ////////////////////////////////////////////////////////////////////
02224 bool HTTPChannel::
02225 run_reading_body() {
02226   if (will_close_connection()) {
02227     // If the socket will close anyway, no point in skipping past the
02228     // previous body; just reset.
02229     if (downloader_cat.is_debug()) {
02230       downloader_cat.debug()
02231         << _NOTIFY_HTTP_CHANNEL_ID 
02232         << "resetting to read body; server would close anyway.\n";
02233     }
02234     reset_to_new();
02235     return false;
02236   }
02237 
02238   // Skip the body we've already started.
02239   if (_body_stream == NULL || !_owns_body_stream) {
02240     // Whoops, we're not in skip-body mode.  Better reset.
02241     if (downloader_cat.is_debug()) {
02242       downloader_cat.debug()
02243         << _NOTIFY_HTTP_CHANNEL_ID 
02244         << "resetting, not in skip-body mode.\n";
02245     }
02246     reset_to_new();
02247     return false;
02248   }
02249 
02250   string line;
02251   getline(*_body_stream, line);
02252   while (!_body_stream->fail() && !_body_stream->eof()) {
02253     if (downloader_cat.is_spam()) {
02254       downloader_cat.spam() 
02255         << _NOTIFY_HTTP_CHANNEL_ID 
02256         << "skip: " << line << "\n";
02257     }
02258     getline(*_body_stream, line);
02259   }
02260 
02261   if (!_body_stream->is_closed()) {
02262     // There's more to come later.
02263     return true;
02264   }
02265 
02266   reset_body_stream();
02267 
02268   // This should have been set by the call to finished_body(), above.
02269   nassertr(_state != S_reading_body, false);
02270   return false;
02271 }
02272 
02273 ////////////////////////////////////////////////////////////////////
02274 //     Function: HTTPChannel::run_read_body
02275 //       Access: Private
02276 //  Description: In this state we have completely read (or skipped
02277 //               over) the body of the response.  We should continue
02278 //               skipping past the trailer following the body.
02279 //
02280 //               Not all bodies come with trailers; in particular, the
02281 //               "identity" transfer encoding does not include a
02282 //               trailer.  It is therefore the responsibility of the
02283 //               IdentityStreamBuf or ChunkedStreamBuf to set the
02284 //               state appropriately to either S_read_body or
02285 //               S_read_trailer following the completion of the body.
02286 ////////////////////////////////////////////////////////////////////
02287 bool HTTPChannel::
02288 run_read_body() {
02289   if (will_close_connection()) {
02290     // If the socket will close anyway, no point in skipping past the
02291     // previous body; just reset.
02292     if (downloader_cat.is_debug()) {
02293       downloader_cat.debug()
02294         << _NOTIFY_HTTP_CHANNEL_ID 
02295         << "resetting to read body; server would close anyway.\n";
02296     }
02297     reset_to_new();
02298     return false;
02299   }
02300   // Skip the trailer following the recently-read body.
02301 
02302   string line;
02303   if (!server_getline(line)) {
02304     return true;
02305   }
02306   while (!line.empty()) {
02307     if (!server_getline(line)) {
02308       return true;
02309     }
02310   }
02311 
02312   _state = S_read_trailer;
02313   return false;
02314 }
02315 
02316 ////////////////////////////////////////////////////////////////////
02317 //     Function: HTTPChannel::run_read_trailer
02318 //       Access: Private
02319 //  Description: In this state we have completely read the body and
02320 //               the trailer.  This state is simply a pass-through
02321 //               back to S_ready.
02322 ////////////////////////////////////////////////////////////////////
02323 bool HTTPChannel::
02324 run_read_trailer() {
02325   if (will_close_connection()) {
02326     // If the socket will close anyway, no point in skipping past the
02327     // previous body; just reset.
02328     if (downloader_cat.is_debug()) {
02329       downloader_cat.debug()
02330         << _NOTIFY_HTTP_CHANNEL_ID 
02331         << "resetting to read trailer; server would close anyway.\n";
02332     }
02333     reset_to_new();
02334     return false;
02335   }
02336 
02337   _state = S_ready;
02338   return false;
02339 }
02340 
02341 ////////////////////////////////////////////////////////////////////
02342 //     Function: HTTPChannel::run_download_to_file
02343 //       Access: Private
02344 //  Description: After the headers, etc. have been read, this streams
02345 //               the download to the named file.
02346 ////////////////////////////////////////////////////////////////////
02347 bool HTTPChannel::
02348 run_download_to_file() {
02349   nassertr(_body_stream != (ISocketStream *)NULL && _owns_body_stream, false);
02350 
02351   bool do_throttle = _wanted_nonblocking && _download_throttle;
02352 
02353   static const size_t buffer_size = 4096;
02354   char buffer[buffer_size];
02355 
02356   size_t remaining_this_pass = buffer_size;
02357   if (do_throttle) {
02358     remaining_this_pass = _bytes_per_update;
02359   }
02360 
02361   _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02362   size_t count = _body_stream->gcount();
02363   while (count != 0) {
02364     _download_to_stream->write(buffer, count);
02365     _bytes_downloaded += count;
02366     if (do_throttle) {
02367       nassertr(count <= remaining_this_pass, false);
02368       remaining_this_pass -= count;
02369       if (remaining_this_pass == 0) {
02370         // That's enough for now.
02371         return true;
02372       }
02373     }
02374 
02375     thread_consider_yield();
02376     _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02377     count = _body_stream->gcount();
02378   }
02379 
02380   if (_download_to_stream->fail()) {
02381     downloader_cat.warning()
02382       << _NOTIFY_HTTP_CHANNEL_ID 
02383       << "Error writing to " << _download_to_filename << "\n";
02384     _status_entry._status_code = SC_download_write_error;
02385     _state = S_failure;
02386     reset_download_to();
02387     return false;
02388   }
02389 
02390   _download_to_stream->flush();
02391 
02392   if (_body_stream->is_closed()) {
02393     // Done.
02394     reset_body_stream();
02395     close_download_stream();
02396     _started_download = false;
02397     return false;
02398   } else {
02399     // More to come.
02400     return true;
02401   }
02402 }
02403 
02404 ////////////////////////////////////////////////////////////////////
02405 //     Function: HTTPChannel::run_download_to_ram
02406 //       Access: Private
02407 //  Description: After the headers, etc. have been read, this streams
02408 //               the download to the specified Ramfile object.
02409 ////////////////////////////////////////////////////////////////////
02410 bool HTTPChannel::
02411 run_download_to_ram() {
02412   nassertr(_body_stream != (ISocketStream *)NULL && _owns_body_stream, false);
02413   nassertr(_download_to_ramfile != (Ramfile *)NULL, false);
02414 
02415   bool do_throttle = _wanted_nonblocking && _download_throttle;
02416 
02417   static const size_t buffer_size = 4096;
02418   char buffer[buffer_size];
02419 
02420   size_t remaining_this_pass = buffer_size;
02421   if (do_throttle) {
02422     remaining_this_pass = _bytes_per_update;
02423   }
02424 
02425   _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02426   size_t count = _body_stream->gcount();
02427   while (count != 0) {
02428     _download_to_ramfile->_data += string(buffer, count);
02429     _bytes_downloaded += count;
02430     if (do_throttle) {
02431       nassertr(count <= remaining_this_pass, false);
02432       remaining_this_pass -= count;
02433       if (remaining_this_pass == 0) {
02434         // That's enough for now.
02435         return true;
02436       }
02437     }
02438 
02439     thread_consider_yield();
02440     _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02441     count = _body_stream->gcount();
02442   }
02443 
02444   if (_body_stream->is_closed()) {
02445     // Done.
02446     reset_body_stream();
02447     close_download_stream();
02448     _started_download = false;
02449     return false;
02450   } else {
02451     // More to come.
02452     return true;
02453   }
02454 }
02455 
02456 ////////////////////////////////////////////////////////////////////
02457 //     Function: HTTPChannel::run_download_to_stream
02458 //       Access: Private
02459 //  Description: After the headers, etc. have been read, this streams
02460 //               the download to the named file.
02461 ////////////////////////////////////////////////////////////////////
02462 bool HTTPChannel::
02463 run_download_to_stream() {
02464   nassertr(_body_stream != (ISocketStream *)NULL && _owns_body_stream, false);
02465 
02466   bool do_throttle = _wanted_nonblocking && _download_throttle;
02467 
02468   static const size_t buffer_size = 4096;
02469   char buffer[buffer_size];
02470 
02471   size_t remaining_this_pass = buffer_size;
02472   if (do_throttle) {
02473     remaining_this_pass = _bytes_per_update;
02474   }
02475 
02476   _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02477   size_t count = _body_stream->gcount();
02478   while (count != 0) {
02479     _download_to_stream->write(buffer, count);
02480     _bytes_downloaded += count;
02481     if (do_throttle) {
02482       nassertr(count <= remaining_this_pass, false);
02483       remaining_this_pass -= count;
02484       if (remaining_this_pass == 0) {
02485         // That's enough for now.
02486         return true;
02487       }
02488     }
02489 
02490     thread_consider_yield();
02491     _body_stream->read(buffer, min(buffer_size, remaining_this_pass));
02492     count = _body_stream->gcount();
02493   }
02494 
02495   if (_download_to_stream->fail()) {
02496     downloader_cat.warning()
02497       << _NOTIFY_HTTP_CHANNEL_ID 
02498       << "Error writing to stream\n";
02499     _status_entry._status_code = SC_download_write_error;
02500     _state = S_failure;
02501     reset_download_to();
02502     return false;
02503   }
02504 
02505   _download_to_stream->flush();
02506 
02507   if (_body_stream->is_closed()) {
02508     // Done.
02509     reset_body_stream();
02510     close_download_stream();
02511     _started_download = false;
02512     return false;
02513   } else {
02514     // More to come.
02515     return true;
02516   }
02517 }
02518 
02519 
02520 ////////////////////////////////////////////////////////////////////
02521 //     Function: HTTPChannel::begin_request
02522 //       Access: Private
02523 //  Description: Begins a new document request to the server, throwing
02524 //               away whatever request was currently pending if
02525 //               necessary.
02526 ////////////////////////////////////////////////////////////////////
02527 void HTTPChannel::
02528 begin_request(HTTPEnum::Method method, const DocumentSpec &url,
02529               const string &body, bool nonblocking, 
02530               size_t first_byte, size_t last_byte) {
02531   
02532   downloader_cat.info()
02533     << _NOTIFY_HTTP_CHANNEL_ID 
02534     << "begin " << method << " " << url << "\n";
02535                 
02536   reset_for_new_request();
02537 
02538   _wanted_nonblocking = nonblocking;
02539 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
02540   // In the presence of SIMPLE_THREADS, we always use non-blocking
02541   // I/O.  We simulate blocking by yielding the thread.
02542   nonblocking = true;
02543 #endif
02544 
02545   // Get the set of proxies that are appropriate for this URL.
02546   _proxies.clear();
02547   _proxy_next_index = 0;
02548   if (get_allow_proxy()) {
02549     _client->get_proxies_for_url(url.get_url(), _proxies);
02550   }
02551 
02552   // If we still have a live connection to a proxy that is on the
02553   // list, that proxy should be moved immediately to the front of the
02554   // list (to minimize restarting connections unnecessarily).
02555   if (!_bio.is_null() && !_proxies.empty() && !_proxy.empty()) {
02556     Proxies::iterator pi = find(_proxies.begin(), _proxies.end(), _proxy);
02557     if (pi != _proxies.end()) {
02558       _proxies.erase(pi);
02559       _proxies.insert(_proxies.begin(), _proxy);
02560     }
02561   }
02562 
02563   URLSpec new_proxy;
02564   if (_proxy_next_index < _proxies.size()) {
02565     new_proxy = _proxies[_proxy_next_index];
02566     _proxy_next_index++;
02567   }
02568 
02569   // Changing the proxy is grounds for dropping the old connection, if
02570   // any.
02571   if (_proxy != new_proxy) {
02572     _proxy = new_proxy;
02573     _proxy_auth = (HTTPAuthorization *)NULL;
02574     if (downloader_cat.is_debug()) {
02575       downloader_cat.debug()
02576         << _NOTIFY_HTTP_CHANNEL_ID 
02577         << "resetting to change proxy to " << _proxy << "\n";
02578     }
02579     reset_to_new();
02580   }
02581 
02582   // Ditto with changing the nonblocking state.
02583   if (_nonblocking != nonblocking) {
02584     _nonblocking = nonblocking;
02585     if (downloader_cat.is_debug()) {
02586       downloader_cat.debug()
02587         << _NOTIFY_HTTP_CHANNEL_ID 
02588         << "resetting to change nonblocking state to " << _nonblocking << ".\n";
02589     }
02590     reset_to_new();
02591   }
02592 
02593   reset_url(_request.get_url(), url.get_url());
02594   _request = url;
02595   _document_spec = DocumentSpec();
02596   _method = method;
02597   _body = body;
02598 
02599   // An https-style request means we'll need to establish an SSL
02600   // connection.
02601   _want_ssl = _request.get_url().is_ssl();
02602 
02603   _first_byte_requested = first_byte;
02604   _last_byte_requested = last_byte;
02605   _connect_count = 0;
02606 
02607   reconsider_proxy();
02608 
02609   // Reset from whatever previous request might still be pending.
02610   if (_request.get_url().get_scheme() == "file") {
02611     // A "file" URL just means we're reading a raw file.  This only
02612     // supports actual disk files, not the VFS, because we use a
02613     // BIO_new_file() underneath this.
02614     reset_to_new();
02615     _bio = new BioPtr(_request.get_url());
02616     if (_bio->get_bio() != NULL) {
02617       // Successfully opened the file.
02618       _source = new BioStreamPtr(new BioStream(_bio));
02619       _status_entry._status_code = 200;
02620       _state = S_start_direct_file_read;
02621 
02622       // Get the file size.
02623       FILE *fp = NULL;
02624       BIO_get_fp(_bio->get_bio(), &fp);
02625       if (fp != NULL) {
02626         if (fseek(fp, 0, SEEK_END) == 0) {
02627           _file_size = ftell(fp);
02628           _got_file_size = true;
02629           fseek(fp, 0, SEEK_SET);
02630         }
02631       }
02632 
02633     } else {
02634       // Couldn't read the file.
02635       OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
02636       _status_entry._status_code = SC_no_connection;
02637       _state = S_failure;
02638     }
02639 
02640   } else {
02641     // We're reading a normal network URL.
02642     if (_state == S_failure || (_state < S_read_header && _state != S_ready)) {
02643       if (downloader_cat.is_debug()) {
02644         downloader_cat.debug()
02645           << _NOTIFY_HTTP_CHANNEL_ID 
02646           << "resetting to clear previous request.\n";
02647       }
02648       reset_to_new();
02649       
02650     } else if (TrueClock::get_global_ptr()->get_short_time() - _last_run_time >= _idle_timeout) {
02651       if (downloader_cat.is_debug()) {
02652         downloader_cat.debug()
02653           << _NOTIFY_HTTP_CHANNEL_ID 
02654           << "resetting old connection: " 
02655           << TrueClock::get_global_ptr()->get_short_time() - _last_run_time
02656           << " s old.\n";
02657       }
02658       reset_to_new();
02659       
02660     } else if (_state == S_read_header) {
02661       // Roll one step forwards to start skipping past the previous
02662       // body.
02663       _state = S_begin_body;
02664     }
02665   }
02666 
02667   if (_method == HTTPEnum::M_connect) {
02668     _done_state = S_ready;
02669   } else {
02670     _done_state = S_read_header;
02671   }
02672 }
02673 
02674 ////////////////////////////////////////////////////////////////////
02675 //     Function: HTTPChannel::reconsider_proxy
02676 //       Access: Private
02677 //  Description: Reevaluates the flags and strings that are computed
02678 //               based on the particular proxy we are attempting to
02679 //               connect to.  This should be called when we initiate a
02680 //               request, and also whenever we change proxies while
02681 //               processing a request.
02682 ////////////////////////////////////////////////////////////////////
02683 void HTTPChannel::
02684 reconsider_proxy() {
02685   _proxy_tunnel_now = false;
02686   _proxy_serves_document = false;
02687   
02688   if (!_proxy.empty()) {
02689     // If the user insists we always tunnel through a proxy, or if
02690     // we're opening an SSL connection, or the user has explicitly
02691     // asked for a direct connection of some kind, or if we have a
02692     // SOCKS-style proxy; each of these demands a tunnel through the
02693     // proxy to speak directly to the http server.
02694     _proxy_tunnel_now =
02695       (get_proxy_tunnel() || _want_ssl ||
02696        _method == HTTPEnum::M_connect || _proxy.get_scheme() == "socks");
02697 
02698     // Otherwise (but we still have a proxy), then we ask the proxy to
02699     // hand us the document.
02700     _proxy_serves_document = !_proxy_tunnel_now;
02701   }
02702 
02703   make_header();
02704   make_request_text();
02705 
02706   if (_proxy_tunnel_now) {
02707     // Maybe we need to tunnel through the proxy to connect to the
02708     // server directly.
02709     ostringstream request;
02710     request 
02711       << "CONNECT " << _request.get_url().get_server_and_port()
02712       << " " << _client->get_http_version_string() << "\r\n";
02713     if (_client->get_http_version() >= HTTPEnum::HV_11) {
02714       request 
02715         << "Host: " << _request.get_url().get_server_and_port() << "\r\n";
02716     }
02717     _proxy_header = request.str();
02718     make_proxy_request_text();
02719 
02720   } else {
02721     _proxy_header = string();
02722     _proxy_request_text = string();
02723   }
02724 }
02725 
02726 
02727 ////////////////////////////////////////////////////////////////////
02728 //     Function: HTTPChannel::reset_for_new_request
02729 //       Access: Private
02730 //  Description: Resets the internal state variables in preparation
02731 //               for beginning a new request.
02732 ////////////////////////////////////////////////////////////////////
02733 void HTTPChannel::
02734 reset_for_new_request() {
02735   if (downloader_cat.is_spam()) {
02736     downloader_cat.spam()
02737       << _NOTIFY_HTTP_CHANNEL_ID 
02738       << "reset_for_new_request.\n";
02739   }
02740   
02741   reset_download_to();
02742   reset_body_stream();
02743 
02744   _last_status_code = 0;
02745   _status_entry = StatusEntry();
02746 
02747   _response_type = RT_none;
02748   _redirect_trail.clear();
02749   _bytes_downloaded = 0;
02750   _bytes_requested = 0;
02751 }
02752 
02753 ////////////////////////////////////////////////////////////////////
02754 //     Function: HTTPChannel::finished_body
02755 //       Access: Private
02756 //  Description: This is called by the body reading
02757 //               classes--ChunkedStreamBuf and IdentityStreamBuf--when
02758 //               they have finished reading the body.  It advances the
02759 //               state appropriately.
02760 //
02761 //               has_trailer should be set true if the body type has
02762 //               an associated trailer which should be read or
02763 //               skipped, or false if there is no trailer.
02764 ////////////////////////////////////////////////////////////////////
02765 void HTTPChannel::
02766 finished_body(bool has_trailer) {
02767   if (will_close_connection() && _download_dest == DD_none) {
02768     if (downloader_cat.is_debug()) {
02769       downloader_cat.debug()
02770         << _NOTIFY_HTTP_CHANNEL_ID 
02771         << "resetting to finish body; server would close anyway.\n";
02772     }
02773     reset_to_new();
02774 
02775   } else {
02776     if (has_trailer) {
02777       _state = HTTPChannel::S_read_body;
02778     } else {
02779       _state = HTTPChannel::S_read_trailer;
02780     }
02781   }
02782 }
02783 
02784 ////////////////////////////////////////////////////////////////////
02785 //     Function: HTTPChannel::open_download_file
02786 //       Access: Private
02787 //  Description: If a download has been requested, opens the file on
02788 //               disk (or prepares the RamFile or stream) and seeks
02789 //               within it to the appropriate _first_byte_delivered
02790 //               position, so that downloaded bytes will be written to
02791 //               the appropriate point within the file.  Returns true
02792 //               if the starting position is valid, false otherwise
02793 //               (in which case the state is set to S_failure).
02794 ////////////////////////////////////////////////////////////////////
02795 bool HTTPChannel::
02796 open_download_file() {
02797   _subdocument_resumes = (_subdocument_resumes && _first_byte_delivered != 0);
02798 
02799   if (_download_dest == DD_file) {
02800     VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
02801     _download_to_stream = vfs->open_write_file(_download_to_filename, false, !_subdocument_resumes);
02802     if (_download_to_stream == NULL) {
02803       downloader_cat.info()
02804         << _NOTIFY_HTTP_CHANNEL_ID 
02805         << "Could not open " << _download_to_filename << " for writing.\n";
02806       _status_entry._status_code = SC_download_open_error;
02807       _state = S_failure;
02808       return false;
02809     }
02810   }
02811 
02812   if (_subdocument_resumes) {
02813     if (_download_dest == DD_file) {
02814       // Windows doesn't complain if you try to seek past the end of
02815       // file--it happily appends enough zero bytes to make the
02816       // difference.  Blecch.  That means we need to get the file size
02817       // first to check it ourselves.
02818       _download_to_stream->seekp(0, ios::end);
02819       if (_first_byte_delivered > (size_t)_download_to_stream->tellp()) {
02820         downloader_cat.info()
02821           << _NOTIFY_HTTP_CHANNEL_ID 
02822           << "Invalid starting position of byte " << _first_byte_delivered
02823           << " within " << _download_to_filename << " (which has " 
02824           << _download_to_stream->tellp() << " bytes)\n";
02825         close_download_stream();
02826         _status_entry._status_code = SC_download_invalid_range;
02827         _state = S_failure;
02828         return false;
02829       }
02830       
02831       _download_to_stream->seekp(_first_byte_delivered);
02832       
02833     } else if (_download_dest == DD_ram) {
02834       if (_first_byte_delivered > _download_to_ramfile->_data.length()) {
02835         downloader_cat.info()
02836           << _NOTIFY_HTTP_CHANNEL_ID 
02837           << "Invalid starting position of byte " << _first_byte_delivered 
02838           << " within Ramfile (which has " 
02839           << _download_to_ramfile->_data.length() << " bytes)\n";
02840         close_download_stream();
02841         _status_entry._status_code = SC_download_invalid_range;
02842         _state = S_failure;
02843         return false;
02844       }
02845 
02846       if (_first_byte_delivered == 0) {
02847         _download_to_ramfile->_data = string();
02848       } else {
02849         _download_to_ramfile->_data = 
02850           _download_to_ramfile->_data.substr(0, _first_byte_delivered);
02851       }
02852     } else if (_download_dest == DD_stream) {
02853       // Windows doesn't complain if you try to seek past the end of
02854       // file--it happily appends enough zero bytes to make the
02855       // difference.  Blecch.  That means we need to get the file size
02856       // first to check it ourselves.
02857       _download_to_stream->seekp(0, ios::end);
02858       if (_first_byte_delivered > (size_t)_download_to_stream->tellp()) {
02859         downloader_cat.info()
02860           << _NOTIFY_HTTP_CHANNEL_ID 
02861           << "Invalid starting position of byte " << _first_byte_delivered
02862           << " within stream (which has " 
02863           << _download_to_stream->tellp() << " bytes)\n";
02864         close_download_stream();
02865         _status_entry._status_code = SC_download_invalid_range;
02866         _state = S_failure;
02867         return false;
02868       }
02869       
02870       _download_to_stream->seekp(_first_byte_delivered);
02871     }
02872 
02873   } else {
02874     // If _subdocument_resumes is false, we should be sure to reset to
02875     // the beginning of the file, regardless of the value of
02876     // _first_byte_delivered.
02877     if (_download_dest == DD_file || _download_dest == DD_stream) {
02878       _download_to_stream->seekp(0);
02879     } else if (_download_dest == DD_ram) {
02880       _download_to_ramfile->_data = string();
02881     }
02882   }
02883 
02884   return true;
02885 }
02886 
02887 
02888 ////////////////////////////////////////////////////////////////////
02889 //     Function: HTTPChannel::server_getline
02890 //       Access: Private
02891 //  Description: Reads a single line from the server's reply.  Returns
02892 //               true if the line is successfully retrieved, or false
02893 //               if a complete line has not yet been received or if
02894 //               the connection has been closed.
02895 ////////////////////////////////////////////////////////////////////
02896 bool HTTPChannel::
02897 server_getline(string &str) {
02898   nassertr(!_source.is_null(), false);
02899   int ch = (*_source)->get();
02900   while (!(*_source)->eof() && !(*_source)->fail()) {
02901     switch (ch) {
02902     case '\n':
02903       // end-of-line character, we're done.
02904       str = _working_get;
02905       _working_get = string();
02906       {
02907         // Trim trailing whitespace.  We're not required to do this per the
02908         // HTTP spec, but let's be generous.
02909         size_t p = str.length();
02910         while (p > 0 && isspace(str[p - 1])) {
02911           --p;
02912         }
02913         str = str.substr(0, p);
02914       }
02915       if (downloader_cat.is_debug()) {
02916         downloader_cat.debug() 
02917           << _NOTIFY_HTTP_CHANNEL_ID 
02918           << "recv: " << str << "\n";
02919       }
02920       return true;
02921 
02922     case '\r':
02923       // Ignore CR characters.
02924       break;
02925 
02926     default:
02927       _working_get += (char)ch;
02928     }
02929     ch = (*_source)->get();
02930   }
02931 
02932   check_socket();
02933   return false;
02934 }
02935 
02936 ////////////////////////////////////////////////////////////////////
02937 //     Function: HTTPChannel::server_getline_failsafe
02938 //       Access: Private
02939 //  Description: Reads a line from the server's reply.  If the server
02940 //               disconnects or times out before sending a reply,
02941 //               moves on to the next proxy server (or sets failure
02942 //               mode) and returns false; otherwise, returns true.
02943 ////////////////////////////////////////////////////////////////////
02944 bool HTTPChannel::
02945 server_getline_failsafe(string &str) {
02946   if (!server_getline(str)) {
02947     if (_bio.is_null()) {
02948       // Huh, the server hung up on us as soon as we tried to connect.
02949       if (_response_type == RT_hangup) {
02950         // This was our second immediate hangup in a row.  Give up.
02951         _status_entry._status_code = SC_lost_connection;
02952         _state = S_try_next_proxy;
02953         
02954       } else {
02955         // Try again, once.
02956         _response_type = RT_hangup;
02957       }
02958 
02959     } else {
02960       double elapsed =
02961         TrueClock::get_global_ptr()->get_short_time() -
02962         _sent_request_time;
02963       if (elapsed > get_http_timeout()) {
02964         // Time to give up.
02965         downloader_cat.info()
02966           << _NOTIFY_HTTP_CHANNEL_ID 
02967           << "Timeout waiting for "
02968           << _request.get_url().get_server_and_port() 
02969           << " in server_getline_failsafe (" << elapsed 
02970           << " seconds elapsed).\n";
02971         _status_entry._status_code = SC_timeout;
02972         _state = S_try_next_proxy;
02973       }
02974     }
02975     
02976     return false;
02977   }
02978   return true;
02979 }
02980 
02981 ////////////////////////////////////////////////////////////////////
02982 //     Function: HTTPChannel::server_get
02983 //       Access: Private
02984 //  Description: Reads a fixed number of bytes from the server's
02985 //               reply.  Returns true if the indicated number of bytes
02986 //               are successfully retrieved, or false if the complete
02987 //               set has not yet been received or if the connection
02988 //               has been closed.
02989 ////////////////////////////////////////////////////////////////////
02990 bool HTTPChannel::
02991 server_get(string &str, size_t num_bytes) {
02992   nassertr(!_source.is_null(), false);
02993   int ch = (*_source)->get();
02994   while (!(*_source)->eof() && !(*_source)->fail()) {
02995     _working_get += (char)ch;
02996     if (_working_get.length() >= num_bytes) {
02997       str = _working_get;
02998       _working_get = string();
02999       return true;
03000     }
03001 
03002     ch = (*_source)->get();
03003   }
03004 
03005   check_socket();
03006   return false;
03007 }
03008 
03009 ////////////////////////////////////////////////////////////////////
03010 //     Function: HTTPChannel::server_get_failsafe
03011 //       Access: Private
03012 //  Description: Reads a fixed number of bytes from the server.  If
03013 //               the server disconnects or times out before sending a
03014 //               reply, moves on to the next proxy server (or sets
03015 //               failure mode) and returns false; otherwise, returns
03016 //               true.
03017 ////////////////////////////////////////////////////////////////////
03018 bool HTTPChannel::
03019 server_get_failsafe(string &str, size_t num_bytes) {
03020   if (!server_get(str, num_bytes)) {
03021     if (_bio.is_null()) {
03022       // Huh, the server hung up on us as soon as we tried to connect.
03023       if (_response_type == RT_hangup) {
03024         // This was our second immediate hangup in a row.  Give up.
03025         _status_entry._status_code = SC_lost_connection;
03026         _state = S_try_next_proxy;
03027         
03028       } else {
03029         // Try again, once.
03030         _response_type = RT_hangup;
03031       }
03032       
03033     } else {
03034       double elapsed =
03035         TrueClock::get_global_ptr()->get_short_time() -
03036         _sent_request_time;
03037       if (elapsed > get_http_timeout()) {
03038         // Time to give up.
03039         downloader_cat.info()
03040           << _NOTIFY_HTTP_CHANNEL_ID 
03041           << "Timeout waiting for "
03042           << _request.get_url().get_server_and_port() 
03043           << " in server_get_failsafe (" << elapsed 
03044           << " seconds elapsed).\n";
03045         _status_entry._status_code = SC_timeout;
03046         _state = S_try_next_proxy;
03047       }
03048     }
03049     
03050     return false;
03051   }
03052   return true;
03053 }
03054 
03055 ////////////////////////////////////////////////////////////////////
03056 //     Function: HTTPChannel::server_send
03057 //       Access: Private
03058 //  Description: Sends a series of lines to the server.  Returns true
03059 //               if the buffer is fully sent, or false if some of it
03060 //               remains.  If this returns false, the function must be
03061 //               called again later, passing in the exact same string,
03062 //               until the return value is true.
03063 //
03064 //               If the secret flag is true, the data is not echoed to
03065 //               the log (even in spam mode).  This may be desirable
03066 //               if the data may contain binary data, or if it may
03067 //               contain passwords etc.
03068 ////////////////////////////////////////////////////////////////////
03069 bool HTTPChannel::
03070 server_send(const string &str, bool secret) {
03071   nassertr(str.length() > _sent_so_far, true);
03072 
03073   // Use the underlying BIO to write to the server, instead of the
03074   // BIOStream, which would insist on blocking (and might furthermore
03075   // delay the send due to collect-tcp mode being enabled).
03076   size_t bytes_to_send = str.length() - _sent_so_far;
03077   int write_count =
03078     BIO_write(*_bio, str.data() + _sent_so_far, bytes_to_send);
03079     
03080   if (write_count <= 0) {
03081     if (BIO_should_retry(*_bio)) {
03082       // Temporary failure: the pipe is full.  Wait till later.
03083       return false;
03084     }
03085     // Oops, the connection has been closed!
03086     if (downloader_cat.is_debug()) {
03087       downloader_cat.debug()
03088         << _NOTIFY_HTTP_CHANNEL_ID 
03089         << "Lost connection to server unexpectedly during write.\n";
03090     }
03091     reset_to_new();
03092     return false;
03093   }
03094 
03095   if (downloader_cat.is_spam()) {
03096     downloader_cat.spam()
03097       << _NOTIFY_HTTP_CHANNEL_ID 
03098       << "wrote " << write_count << " bytes to " << _bio << "\n";
03099   }
03100   
03101 #ifndef NDEBUG
03102   if (!secret && downloader_cat.is_debug()) {
03103     show_send(str.substr(0, write_count));
03104   }
03105 #endif
03106   
03107   if (write_count < (int)bytes_to_send) {
03108     _sent_so_far += write_count;
03109     return false;
03110   }
03111 
03112   // Buffer completely sent.
03113   _sent_so_far = 0;
03114   return true;
03115 }
03116 
03117 ////////////////////////////////////////////////////////////////////
03118 //     Function: HTTPChannel::parse_http_response
03119 //       Access: Private
03120 //  Description: Parses the first line sent back from an HTTP server
03121 //               or proxy and stores the result in _status_code and
03122 //               _http_version, etc.  Returns true on success, false
03123 //               on invalid response.
03124 ////////////////////////////////////////////////////////////////////
03125 bool HTTPChannel::
03126 parse_http_response(const string &line) {
03127   // The first line back should include the HTTP version and the
03128   // result code.
03129   if (line.length() < 5 || line.substr(0, 5) != string("HTTP/")) {
03130     // Not an HTTP response.
03131     _status_entry._status_code = SC_non_http_response;
03132     if (_response_type == RT_non_http) {
03133       // This was our second non-HTTP response in a row.  Give up.
03134       _state = S_try_next_proxy;
03135 
03136     } else {
03137       // Maybe we were just in some bad state.  Drop the connection
03138       // and try again, once.
03139       if (downloader_cat.is_debug()) {
03140         downloader_cat.debug()
03141           << _NOTIFY_HTTP_CHANNEL_ID 
03142           << "got non-HTTP response, resetting.\n";
03143       }
03144       reset_to_new();
03145       _response_type = RT_non_http;
03146     }
03147     return false;
03148   }
03149 
03150   // Split out the first line into its three components.
03151   size_t p = 5;
03152   while (p < line.length() && !isspace(line[p])) {
03153     p++;
03154   }
03155   _http_version_string = line.substr(0, p);
03156   _http_version = HTTPClient::parse_http_version_string(_http_version_string);
03157 
03158   while (p < line.length() && isspace(line[p])) {
03159     p++;
03160   }
03161   size_t q = p;
03162   while (q < line.length() && !isspace(line[q])) {
03163     q++;
03164   }
03165   string status_code = line.substr(p, q - p);
03166   _status_entry._status_code = atoi(status_code.c_str());
03167 
03168   while (q < line.length() && isspace(line[q])) {
03169     q++;
03170   }
03171   _status_entry._status_string = line.substr(q, line.length() - q);
03172 
03173   return true;
03174 }
03175 
03176 ////////////////////////////////////////////////////////////////////
03177 //     Function: HTTPChannel::parse_http_header
03178 //       Access: Private
03179 //  Description: Reads the series of header lines from the server and
03180 //               stores them in _headers.  Returns true if there is
03181 //               more to read, false when done.
03182 ////////////////////////////////////////////////////////////////////
03183 bool HTTPChannel::
03184 parse_http_header() {
03185   string line;
03186   if (!server_getline(line)) {
03187     return true;
03188   }
03189 
03190   while (!line.empty()) {
03191     if (isspace(line[0])) {
03192       // If the line begins with a space, that continues the previous
03193       // field.
03194       size_t p = 0;
03195       while (p < line.length() && isspace(line[p])) {
03196         p++;
03197       }
03198       _current_field_value += line.substr(p - 1);
03199 
03200     } else {
03201       // If the line does not begin with a space, that defines a new
03202       // field.
03203       if (!_current_field_name.empty()) {
03204         store_header_field(_current_field_name, _current_field_value);
03205         _current_field_value = string();
03206       }
03207 
03208       size_t colon = line.find(':');
03209       if (colon != string::npos) {
03210         _current_field_name = downcase(line.substr(0, colon));
03211         size_t p = colon + 1;
03212         while (p < line.length() && isspace(line[p])) {
03213           p++;
03214         }
03215         _current_field_value = line.substr(p);
03216       }
03217     }
03218 
03219     if (!server_getline(line)) {
03220       return true;
03221     }
03222   }
03223 
03224   // After reading an empty line, we're done with the headers.
03225   if (!_current_field_name.empty()) {
03226     store_header_field(_current_field_name, _current_field_value);
03227     _current_field_value = string();
03228   }
03229 
03230   return false;
03231 }
03232 
03233 ////////////////////////////////////////////////////////////////////
03234 //     Function: HTTPChannel::parse_content_range
03235 //       Access: Private
03236 //  Description: Interprets the "Content-Range" header in the reply,
03237 //               and fills in _first_byte_delivered and
03238 //               _last_byte_delivered appropriately if the header
03239 //               response can be understood.
03240 ////////////////////////////////////////////////////////////////////
03241 bool HTTPChannel::
03242 parse_content_range(const string &content_range) {
03243   // First, get the units indication.
03244   size_t p = 0;
03245   while (p < content_range.length() && !isspace(content_range[p])) {
03246     p++;
03247   }
03248 
03249   string units = content_range.substr(0, p);
03250   while (p < content_range.length() && isspace(content_range[p])) {
03251     p++;
03252   }
03253 
03254   if (units == "bytes") {
03255     const char *c_str = content_range.c_str();
03256     char *endptr;
03257     if (p < content_range.length() && isdigit(content_range[p])) {
03258       long first_byte = strtol(c_str + p, &endptr, 10);
03259       p = endptr - c_str;
03260       if (p < content_range.length() && content_range[p] == '-') {
03261         p++;
03262         if (p < content_range.length() && isdigit(content_range[p])) {
03263           long last_byte = strtol(c_str + p, &endptr, 10);
03264           p = endptr - c_str;
03265           
03266           if (last_byte >= first_byte) {
03267             _first_byte_delivered = first_byte;
03268             _last_byte_delivered = last_byte;
03269             return true;
03270           }
03271         }
03272       }
03273     }
03274   }
03275     
03276   // Invalid or unhandled response.
03277   return false;
03278 }
03279 
03280 
03281 ////////////////////////////////////////////////////////////////////
03282 //     Function: HTTPChannel::check_socket
03283 //       Access: Private
03284 //  Description: Checks whether the connection to the server has been
03285 //               closed after a failed read.  If it has, issues a
03286 //               warning and calls reset_to_new().
03287 ////////////////////////////////////////////////////////////////////
03288 void HTTPChannel::
03289 check_socket() {
03290   nassertv(!_source.is_null());
03291   if ((*_source)->is_closed()) {
03292     if (downloader_cat.is_debug()) {
03293       downloader_cat.debug()
03294         << _NOTIFY_HTTP_CHANNEL_ID 
03295         << "Lost connection to server unexpectedly during read.\n";
03296     }
03297     reset_to_new();
03298   }
03299 }
03300 
03301 /*
03302    Certificate verify error codes:
03303 
03304 0 X509_V_OK: ok
03305 
03306     the operation was successful.
03307 
03308 2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate
03309 
03310     the issuer certificate could not be found: this occurs if the
03311     issuer certificate of an untrusted certificate cannot be found.
03312 
03313 3 X509_V_ERR_UNABLE_TO_GET_CRL unable to get certificate CRL
03314 
03315     the CRL of a certificate could not be found. Unused.
03316 
03317 4 X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: unable to decrypt
03318 certificate's signature
03319 
03320     the certificate signature could not be decrypted. This means that
03321     the actual signature value could not be determined rather than it
03322     not matching the expected value, this is only meaningful for RSA
03323     keys.
03324 
03325 5 X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: unable to decrypt CRL's signature
03326 
03327     the CRL signature could not be decrypted: this means that the
03328     actual signature value could not be determined rather than it not
03329     matching the expected value. Unused.
03330 
03331 6 X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: unable to decode
03332 issuer public key
03333 
03334     the public key in the certificate SubjectPublicKeyInfo could not
03335     be read.
03336 
03337 7 X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure
03338 
03339     the signature of the certificate is invalid.
03340 
03341 8 X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure
03342 
03343     the signature of the certificate is invalid. Unused.
03344 
03345 9 X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid
03346 
03347     the certificate is not yet valid: the notBefore date is after the
03348     current time.
03349 
03350 10 X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired
03351 
03352     the certificate has expired: that is the notAfter date is before
03353     the current time.
03354 
03355 11 X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid
03356 
03357     the CRL is not yet valid. Unused.
03358 
03359 12 X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired
03360 
03361     the CRL has expired. Unused.
03362 
03363 13 X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: format error in
03364 certificate's notBefore field
03365 
03366     the certificate notBefore field contains an invalid time.
03367 
03368 14 X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: format error in
03369 certificate's notAfter field
03370 
03371     the certificate notAfter field contains an invalid time.
03372 
03373 15 X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: format error in CRL's
03374 lastUpdate field
03375 
03376     the CRL lastUpdate field contains an invalid time. Unused.
03377 
03378 16 X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: format error in CRL's
03379 nextUpdate field
03380 
03381     the CRL nextUpdate field contains an invalid time. Unused.
03382 
03383 17 X509_V_ERR_OUT_OF_MEM: out of memory
03384 
03385     an error occurred trying to allocate memory. This should never
03386     happen.
03387 
03388 18 X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self signed certificate
03389 
03390     the passed certificate is self signed and the same certificate
03391     cannot be found in the list of trusted certificates.
03392 
03393 19 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: self signed certificate in
03394 certificate chain
03395 
03396     the certificate chain could be built up using the untrusted
03397     certificates but the root could not be found locally.
03398 
03399 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local
03400 issuer certificate
03401 
03402     the issuer certificate of a locally looked up certificate could
03403     not be found. This normally means the list of trusted certificates
03404     is not complete.
03405 
03406 21 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the
03407 first certificate
03408 
03409     no signatures could be verified because the chain contains only
03410     one certificate and it is not self signed.
03411 
03412 22 X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long
03413 
03414     the certificate chain length is greater than the supplied maximum
03415     depth. Unused.
03416 
03417 23 X509_V_ERR_CERT_REVOKED: certificate revoked
03418 
03419     the certificate has been revoked. Unused.
03420 
03421 24 X509_V_ERR_INVALID_CA: invalid CA certificate
03422 
03423     a CA certificate is invalid. Either it is not a CA or its
03424     extensions are not consistent with the supplied purpose.
03425 
03426 25 X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded
03427 
03428     the basicConstraints pathlength parameter has been exceeded.
03429 
03430 26 X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose
03431 
03432     the supplied certificate cannot be used for the specified purpose.
03433 
03434 27 X509_V_ERR_CERT_UNTRUSTED: certificate not trusted
03435 
03436     the root CA is not marked as trusted for the specified purpose.
03437 
03438 28 X509_V_ERR_CERT_REJECTED: certificate rejected
03439 
03440     the root CA is marked to reject the specified purpose.
03441 
03442 29 X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch
03443 
03444     the current candidate issuer certificate was rejected because its
03445     subject name did not match the issuer name of the current
03446     certificate. Only displayed when the -issuer_checks option is set.
03447 
03448 30 X509_V_ERR_AKID_SKID_MISMATCH: authority and subject key identifier
03449 mismatch
03450 
03451     the current candidate issuer certificate was rejected because its
03452     subject key identifier was present and did not match the authority
03453     key identifier current certificate. Only displayed when the
03454     -issuer_checks option is set.
03455 
03456 31 X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: authority and issuer serial
03457 number mismatch
03458 
03459     the current candidate issuer certificate was rejected because its
03460     issuer name and serial number was present and did not match the
03461     authority key identifier of the current certificate. Only
03462     displayed when the -issuer_checks option is set.
03463 
03464 32 X509_V_ERR_KEYUSAGE_NO_CERTSIGN:key usage does not include
03465 certificate signing
03466 
03467     the current candidate issuer certificate was rejected because its
03468     keyUsage extension does not permit certificate signing.
03469 
03470 50 X509_V_ERR_APPLICATION_VERIFICATION: application verification failure
03471 
03472     an application specific error. Unused.
03473 
03474 */
03475 
03476 ////////////////////////////////////////////////////////////////////
03477 //     Function: HTTPChannel::check_preapproved_server_certificate
03478 //       Access: Private
03479 //  Description: Checks to see if the indicated certificate is on the
03480 //               pre-approved list for the current server.
03481 //
03482 //               If the full cert itself (including its key) is on the
03483 //               pre-approved list, sets both cert_preapproved and
03484 //               cert_name_preapproved to true.
03485 //
03486 //               If the full cert is not on the pre-approved list, but
03487 //               its name matches a name on the pre-approved list,
03488 //               sets cert_name_preapproved to true, and
03489 //               cert_preapproved to false.
03490 //
03491 //               Otherwise, sets both values to false.  This doesn't
03492 //               mean the cert is necessarily invalid, just that it
03493 //               wasn't on the pre-approved list (which is usually
03494 //               empty anyway).
03495 ////////////////////////////////////////////////////////////////////
03496 void HTTPChannel::
03497 check_preapproved_server_certificate(X509 *cert, bool &cert_preapproved, 
03498                                      bool &cert_name_preapproved) const {
03499   return _client->check_preapproved_server_certificate(_request.get_url(),
03500                                                        cert, cert_preapproved,
03501                                                        cert_name_preapproved);
03502 }
03503 
03504 ////////////////////////////////////////////////////////////////////
03505 //     Function: HTTPChannel::validate_server_name
03506 //       Access: Private
03507 //  Description: Returns true if the name in the cert matches the
03508 //               hostname of the server, false otherwise.
03509 ////////////////////////////////////////////////////////////////////
03510 bool HTTPChannel::
03511 validate_server_name(X509 *cert) {
03512   string hostname = _request.get_url().get_server();
03513 
03514   vector_string cert_names;
03515 
03516   // According to RFC 2818, we should check the DNS name(s) in the
03517   // subjectAltName extension first, if that extension exists.
03518   STACK_OF(GENERAL_NAME) *subject_alt_names =
03519     (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
03520   if (subject_alt_names != NULL) {
03521     int num_alts = sk_GENERAL_NAME_num(subject_alt_names);
03522     for (int i = 0; i < num_alts; ++i) {
03523       // Get the ith alt name.
03524       const GENERAL_NAME *alt_name = 
03525         sk_GENERAL_NAME_value(subject_alt_names, i);
03526       
03527       if (alt_name->type == GEN_DNS) {
03528         char *buffer = NULL;
03529         int len = ASN1_STRING_to_UTF8((unsigned char**)&buffer,
03530                                       alt_name->d.ia5);
03531         if (len > 0) {
03532           cert_names.push_back(string(buffer, len));
03533         }
03534         if (buffer != NULL) {
03535           OPENSSL_free(buffer);
03536         }
03537       }
03538     }
03539   }
03540 
03541   if (cert_names.empty()) {
03542     // If there were no DNS names, use the common name instead.
03543   
03544     X509_NAME *xname = X509_get_subject_name(cert);
03545     if (xname != NULL) {
03546       string common_name = get_x509_name_component(xname, NID_commonName);
03547       cert_names.push_back(common_name);
03548     }
03549   }
03550 
03551   if (cert_names.empty()) {
03552     downloader_cat.info()
03553       << _NOTIFY_HTTP_CHANNEL_ID 
03554       << "Server certificate from " << hostname
03555       << " provides no name.\n";
03556     return false;
03557   }
03558 
03559   if (downloader_cat.is_debug()) {
03560     downloader_cat.debug()
03561       << _NOTIFY_HTTP_CHANNEL_ID 
03562       << "Server certificate from " << hostname
03563       << " provides name(s):";
03564     vector_string::const_iterator si;
03565     for (si = cert_names.begin(); si != cert_names.end(); ++si) {
03566       const string &cert_name = (*si);
03567       downloader_cat.debug(false)
03568         << " " << cert_name;
03569     }
03570     downloader_cat.debug(false)
03571       << "\n";
03572   }
03573 
03574   // Now validate the names we found.  If any of them matches, the
03575   // cert matches.
03576   vector_string::const_iterator si;
03577   for (si = cert_names.begin(); si != cert_names.end(); ++si) {
03578     const string &cert_name = (*si);
03579 
03580     if (match_cert_name(cert_name, hostname)) {
03581       return true;
03582     }
03583   }
03584 
03585   downloader_cat.info()
03586     << _NOTIFY_HTTP_CHANNEL_ID 
03587     << "Server certificate from " << hostname
03588     << " provides wrong name(s):";
03589   for (si = cert_names.begin(); si != cert_names.end(); ++si) {
03590     const string &cert_name = (*si);
03591     downloader_cat.info(false)
03592       << " " << cert_name;
03593   }
03594   downloader_cat.info(false)
03595     << "\n";
03596 
03597   return false;
03598 }
03599 
03600 ////////////////////////////////////////////////////////////////////
03601 //     Function: HTTPChannel::match_cert_name
03602 //       Access: Private, Static
03603 //  Description: Returns true if this particular name from the
03604 //               certificate matches the indicated hostname, false
03605 //               otherwise.
03606 ////////////////////////////////////////////////////////////////////
03607 bool HTTPChannel::
03608 match_cert_name(const string &cert_name, const string &hostname) {
03609   // We use GlobPattern to match the name.  This isn't quite
03610   // consistent with RFC2818, since it also accepts additional
03611   // wildcard characters like "?" and "[]", but I think it's close
03612   // enough.
03613 
03614   GlobPattern pattern(cert_name);
03615   pattern.set_case_sensitive(false);
03616   pattern.set_nomatch_chars(".");
03617   return pattern.matches(hostname);
03618 }
03619     
03620 ////////////////////////////////////////////////////////////////////
03621 //     Function: HTTPChannel::get_x509_name_component
03622 //       Access: Private, Static
03623 //  Description: Returns the indicated component of the X509 name as a
03624 //               string, if defined, or empty string if it is not.
03625 ////////////////////////////////////////////////////////////////////
03626 string HTTPChannel::
03627 get_x509_name_component(X509_NAME *name, int nid) {
03628   ASN1_OBJECT *obj = OBJ_nid2obj(nid);
03629 
03630   if (obj == NULL) {
03631     // Unknown nid.  See openssl/objects.h.
03632     return string();
03633   }
03634 
03635   int i = X509_NAME_get_index_by_OBJ(name, obj, -1);
03636   if (i < 0) {
03637     return string();
03638   }
03639 
03640   ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
03641   return string((char *)data->data, data->length);  
03642 }
03643 
03644 ////////////////////////////////////////////////////////////////////
03645 //     Function: HTTPChannel::make_header
03646 //       Access: Private
03647 //  Description: Formats the appropriate GET or POST (or whatever)
03648 //               request to send to the server, based on the current
03649 //               _method, _document_spec, _body, and _proxy settings.
03650 ////////////////////////////////////////////////////////////////////
03651 void HTTPChannel::
03652 make_header() {
03653   _proxy_auth = _client->select_auth(_proxy, true, _proxy_realm);
03654   _proxy_username = string();
03655   if (_proxy_auth != (HTTPAuthorization *)NULL) {
03656     _proxy_realm = _proxy_auth->get_realm();
03657     _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
03658   }
03659 
03660   if (_method == HTTPEnum::M_connect) {
03661     // This method doesn't require an HTTP header at all; we'll just
03662     // open a plain connection.  (Except when we're using a proxy; but
03663     // in that case, it's the proxy_header we'll need, not the regular
03664     // HTTP header.)
03665     _header = string();
03666     return;
03667   }
03668 
03669   _www_auth = _client->select_auth(_request.get_url(), false, _www_realm);
03670   _www_username = string();
03671   if (_www_auth != (HTTPAuthorization *)NULL) {
03672     _www_realm = _www_auth->get_realm();
03673     _www_username = _client->select_username(_request.get_url(), false, _www_realm);
03674   }
03675 
03676   string request_path;
03677   if (_proxy_serves_document) {
03678     // If we'll be asking the proxy for the document, we need its full
03679     // URL--but we omit the username, which is information just for us.
03680     URLSpec url_no_username = _request.get_url();
03681     url_no_username.set_username(string());
03682     request_path = url_no_username.get_url();
03683 
03684   } else {
03685     // If we'll be asking the server directly for the document, we
03686     // just want its path relative to the server.
03687     request_path = _request.get_url().get_path_and_query();
03688   }
03689 
03690   // HTTP syntax always requires something in the request path.  If it
03691   // is empty, put in a star as a placeholder (OPTIONS, for instance,
03692   // uses this).
03693   if (request_path.empty()) {
03694     request_path = "*";
03695   }
03696 
03697   ostringstream stream;
03698 
03699   stream 
03700     << _method << " " << request_path << " " 
03701     << _client->get_http_version_string() << "\r\n";
03702 
03703   if (_client->get_http_version() >= HTTPEnum::HV_11) {
03704     
03705     stream 
03706       << "Host: " << _request.get_url().get_server();
03707     if (!_request.get_url().is_default_port()) {
03708       // It appears that some servers (notably gstatic.com) might
03709       // return a 404 if you include an explicit port number in with
03710       // the Host: header, even if it is the default port.  So, don't
03711       // include the port number unless we need to.
03712       stream << ":" << _request.get_url().get_port();
03713     }
03714     stream << "\r\n";
03715     if (!get_persistent_connection()) {
03716       stream
03717         << "Connection: close\r\n";
03718     }
03719   }
03720 
03721   if (_last_byte_requested != 0) {
03722     stream 
03723       << "Range: bytes=" << _first_byte_requested << "-" 
03724       << _last_byte_requested << "\r\n";
03725 
03726   } else if (_first_byte_requested != 0) {
03727     stream 
03728       << "Range: bytes=" << _first_byte_requested << "-\r\n";
03729   }
03730 
03731   switch (_request.get_request_mode()) {
03732   case DocumentSpec::RM_any:
03733     // No particular request; give us any document that matches the
03734     // URL.  
03735     if (_first_byte_requested != 0) {
03736       // Unless we're requesting a subrange, in which case if the
03737       // exact document matches, retrieve the subrange indicated;
03738       // otherwise, retrieve the entire document.
03739       if (_request.has_tag()) {
03740         stream
03741           << "If-Range: " << _request.get_tag().get_string() << "\r\n";
03742       } else if (_request.has_date()) {
03743         stream
03744           << "If-Range: " << _request.get_date().get_string() << "\r\n";
03745       }
03746     }
03747     break;
03748 
03749   case DocumentSpec::RM_equal:
03750     // Give us only this particular version of the document, or
03751     // nothing.
03752     if (_request.has_tag()) {
03753       stream
03754         << "If-Match: " << _request.get_tag().get_string() << "\r\n";
03755     }
03756     if (_request.has_date()) {
03757       stream
03758         << "If-Unmodified-Since: " << _request.get_date().get_string()
03759         << "\r\n";
03760     }
03761     break;
03762 
03763   case DocumentSpec::RM_newer:
03764     // Give us anything newer than this document, or nothing.
03765     if (_request.has_tag()) {
03766       stream
03767         << "If-None-Match: " << _request.get_tag().get_string() << "\r\n";
03768     }
03769     if (_request.has_date()) {
03770       stream
03771         << "If-Modified-Since: " << _request.get_date().get_string()
03772         << "\r\n";
03773     }
03774     break;
03775 
03776   case DocumentSpec::RM_equal_or_newer:
03777     // Just don't give us anything older.
03778     if (_request.has_date()) {
03779       // This is a little unreliable: we ask for any document that's
03780       // been modified since one second before our last-modified-date.
03781       // Who knows whether the server will honor this properly.
03782       stream
03783         << "If-Modified-Since: " << (_request.get_date() - 1).get_string()
03784         << "\r\n";
03785     }
03786     break;
03787   }
03788 
03789   switch (_request.get_cache_control()) {
03790   case DocumentSpec::CC_allow_cache:
03791     // Normal, caching behavior.
03792     break;
03793 
03794   case DocumentSpec::CC_revalidate:
03795     // Request the server to revalidate its cache before returning it.
03796     stream
03797       << "Cache-Control: max-age=0\r\n";
03798     break;
03799 
03800   case DocumentSpec::CC_no_cache:
03801     // Request the server to get a fresh copy regardless of its cache.
03802     stream
03803       << "Cache-Control: no-cache\r\n"
03804       << "Pragma: no-cache\r\n";
03805     break;
03806   }
03807 
03808   _client->send_cookies(stream, _request.get_url());
03809 
03810   if (!_body.empty()) {
03811     stream
03812       << "Content-Type: application/x-www-form-urlencoded\r\n"
03813       << "Content-Length: " << _body.length() << "\r\n";
03814   }
03815 
03816   _header = stream.str();
03817 }
03818 
03819 ////////////////////////////////////////////////////////////////////
03820 //     Function: HTTPChannel::make_proxy_request_text
03821 //       Access: Private
03822 //  Description: Builds the _proxy_request_text string.  This is a
03823 //               special request that will be sent directly to the
03824 //               proxy prior to the request tailored for the server.
03825 //               Generally this is used to open a tunnelling
03826 //               connection for https-over-proxy.
03827 ////////////////////////////////////////////////////////////////////
03828 void HTTPChannel::
03829 make_proxy_request_text() {
03830   _proxy_request_text = _proxy_header;
03831 
03832   if (_proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
03833     _proxy_request_text += "Proxy-Authorization: ";
03834     _proxy_request_text += 
03835       _proxy_auth->generate(HTTPEnum::M_connect, _request.get_url().get_server_and_port(),
03836                             _proxy_username, _body);
03837     _proxy_request_text += "\r\n";
03838   }
03839     
03840   _proxy_request_text += "\r\n";
03841 }
03842 
03843 ////////////////////////////////////////////////////////////////////
03844 //     Function: HTTPChannel::make_request_text
03845 //       Access: Private
03846 //  Description: Builds the _request_text string.  This is the
03847 //               specific request that will be sent to the server this
03848 //               pass, based on the current header and body.
03849 ////////////////////////////////////////////////////////////////////
03850 void HTTPChannel::
03851 make_request_text() {
03852   _request_text = _header;
03853 
03854   if (_proxy_serves_document &&
03855       _proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
03856     _request_text += "Proxy-Authorization: ";
03857     _request_text += 
03858       _proxy_auth->generate(_method, _request.get_url().get_url(), _proxy_username, _body);
03859     _request_text += "\r\n";
03860   }
03861 
03862   if (_www_auth != (HTTPAuthorization *)NULL && !_www_username.empty()) {
03863     string authorization = 
03864     _request_text += "Authorization: ";
03865     _request_text +=
03866       _www_auth->generate(_method, _request.get_url().get_path_and_query(), _www_username, _body);
03867     _request_text += "\r\n";
03868   }
03869 
03870   _request_text += _send_extra_headers;
03871   _request_text += "\r\n";
03872   _request_text += _body;
03873 }
03874   
03875 ////////////////////////////////////////////////////////////////////
03876 //     Function: HTTPChannel::reset_url
03877 //       Access: Private
03878 //  Description: Redirects the next connection to the indicated URL
03879 //               (from the previous URL).  This resets the socket if
03880 //               necessary when we are about to switch servers.
03881 ////////////////////////////////////////////////////////////////////
03882 void HTTPChannel::
03883 reset_url(const URLSpec &old_url, const URLSpec &new_url) {
03884   // If we change between http and https, we have to reset the
03885   // connection regardless of proxy.  Otherwise, we have to drop the
03886   // connection if the server or port changes, unless we're
03887   // communicating through a proxy.
03888 
03889   if (new_url.get_scheme() != old_url.get_scheme() ||
03890       (_proxy.empty() && (new_url.get_server() != old_url.get_server() || 
03891                           new_url.get_port() != old_url.get_port()))) {
03892     if (downloader_cat.is_debug()) {
03893       downloader_cat.debug()
03894         << _NOTIFY_HTTP_CHANNEL_ID 
03895         << "resetting for new server " 
03896         << new_url.get_server_and_port() << "\n";
03897     }
03898     reset_to_new();
03899   }
03900 }
03901 
03902 ////////////////////////////////////////////////////////////////////
03903 //     Function: HTTPChannel::store_header_field
03904 //       Access: Private
03905 //  Description: Stores a single name: value pair in the header list,
03906 //               or appends the value to the end of the existing
03907 //               value, if the header has been repeated.
03908 ////////////////////////////////////////////////////////////////////
03909 void HTTPChannel::
03910 store_header_field(const string &field_name, const string &field_value) {
03911   pair<Headers::iterator, bool> insert_result =
03912     _headers.insert(Headers::value_type(field_name, field_value));
03913 
03914   if (!insert_result.second) {
03915     // It didn't insert; thus, the field already existed.  Append the
03916     // new value.
03917     Headers::iterator hi = insert_result.first;
03918     (*hi).second += ", ";
03919     (*hi).second += field_value;
03920   }
03921 
03922   if (field_name == "set-cookie") {
03923     _client->set_cookie(HTTPCookie(field_value, _request.get_url()));
03924   }
03925 }
03926 
03927 #ifndef NDEBUG
03928 ////////////////////////////////////////////////////////////////////
03929 //     Function: HTTPChannel::show_send
03930 //       Access: Private, Static
03931 //  Description: Writes the outgoing message, one line at a time, to
03932 //               the debugging log.
03933 ////////////////////////////////////////////////////////////////////
03934 void HTTPChannel::
03935 show_send(const string &message) {
03936   size_t start = 0;
03937   size_t newline = message.find('\n', start);
03938   while (newline != string::npos) {
03939     // Assume every \n is preceded by a \r.
03940     downloader_cat.debug()
03941       << "send: " << message.substr(start, newline - start - 1) << "\n";
03942     start = newline + 1;
03943     newline = message.find('\n', start);
03944   }
03945 
03946   if (start < message.length()) {
03947     downloader_cat.debug()
03948       << "send: " << message.substr(start) << " (no newline)\n";
03949   }
03950 }
03951 #endif   // NDEBUG
03952 
03953 ////////////////////////////////////////////////////////////////////
03954 //     Function: HTTPChannel::reset_download_to
03955 //       Access: Private
03956 //  Description: Resets the indication of how the document will be
03957 //               downloaded.  This must be re-specified after each
03958 //               get_document() (or related) call.
03959 ////////////////////////////////////////////////////////////////////
03960 void HTTPChannel::
03961 reset_download_to() {
03962   _started_download = false;
03963   close_download_stream();
03964   _download_dest = DD_none;
03965 }
03966 
03967 ////////////////////////////////////////////////////////////////////
03968 //     Function: HTTPChannel::close_download_stream
03969 //       Access: Private
03970 //  Description: Ensures the file opened for receiving the download
03971 //               has been correctly closed.
03972 ////////////////////////////////////////////////////////////////////
03973 void HTTPChannel::
03974 close_download_stream() {
03975   if (_download_to_stream != NULL) {
03976     _download_to_stream->flush();
03977     if (_download_dest == DD_file) {
03978       VirtualFileSystem::close_write_file(_download_to_stream);
03979     }
03980   }
03981   _download_to_ramfile = (Ramfile *)NULL;
03982   _download_to_stream = NULL;
03983 }
03984 
03985 
03986 ////////////////////////////////////////////////////////////////////
03987 //     Function: HTTPChannel::reset_to_new
03988 //       Access: Private
03989 //  Description: Closes the connection and resets the state to S_new.
03990 ////////////////////////////////////////////////////////////////////
03991 void HTTPChannel::
03992 reset_to_new() {
03993   if (downloader_cat.is_spam()) {
03994     downloader_cat.spam()
03995       << _NOTIFY_HTTP_CHANNEL_ID 
03996       << "reset_to_new.\n";
03997   }
03998   
03999   close_connection();
04000   _state = S_new;
04001 }
04002 
04003 ////////////////////////////////////////////////////////////////////
04004 //     Function: HTTPChannel::reset_body_stream
04005 //       Access: Private
04006 //  Description: Clears the _body_stream pointer, if it is set.
04007 ////////////////////////////////////////////////////////////////////
04008 void HTTPChannel::
04009 reset_body_stream() {
04010   if (_owns_body_stream) {
04011     if (_body_stream != (ISocketStream *)NULL) {
04012       close_read_body(_body_stream);
04013       nassertv(_body_stream == (ISocketStream *)NULL && !_owns_body_stream);
04014     }
04015   } else {
04016     _body_stream = NULL;
04017   }
04018 }
04019 
04020 
04021 ////////////////////////////////////////////////////////////////////
04022 //     Function: HTTPChannel::close_connection
04023 //       Access: Private
04024 //  Description: Closes the connection but leaves the _state
04025 //               unchanged.
04026 ////////////////////////////////////////////////////////////////////
04027 void HTTPChannel::
04028 close_connection() {
04029   reset_body_stream();
04030   _source.clear();
04031   _bio.clear();
04032   _working_get = string();
04033   _sent_so_far = 0;
04034   _read_index++;
04035 }
04036 
04037 ////////////////////////////////////////////////////////////////////
04038 //     Function: HTTPChannel::more_useful_status_code
04039 //       Access: Private, Static
04040 //  Description: Returns true if status code a is a more useful value
04041 //               (that is, it represents a more-nearly successfully
04042 //               connection attempt, or contains more information)
04043 //               than b, or false otherwise.
04044 ////////////////////////////////////////////////////////////////////
04045 bool HTTPChannel::
04046 more_useful_status_code(int a, int b) {
04047   if (a >= 100 && b >= 100) {
04048     // Both represent HTTP responses.  Responses from a server (<
04049     // 1000) are better than those from a proxy; we take advantage of
04050     // the fact that we have already added 1000 to proxy responses.
04051     // Except for 407, so let's fix that now.
04052     if (a == 407) { 
04053       a += 1000;
04054     }
04055     if (b == 407) { 
04056       b += 1000;
04057     }
04058 
04059     // Now just check the series.
04060     int series_a = (a / 100);
04061     int series_b = (b / 100);
04062 
04063     // In general, a lower series is a closer success.
04064     return (series_a < series_b);
04065   }
04066 
04067   if (a < 100 && b < 100) {
04068     // Both represent non-HTTP responses.  Here a larger number is
04069     // better.
04070     return (a > b);
04071   }
04072 
04073   if (a < 100) {
04074     // a is a non-HTTP response, while b is an HTTP response.  HTTP is
04075     // generally, better, unless we exceeded SC_http_error_watermark.
04076     return (a > SC_http_error_watermark);
04077   }
04078 
04079   // Exactly the opposite case as above.
04080   return (b < SC_http_error_watermark);
04081 }
04082 
04083 
04084 ////////////////////////////////////////////////////////////////////
04085 //     Function: HTTPChannel::State output operator
04086 //  Description: 
04087 ////////////////////////////////////////////////////////////////////
04088 ostream &
04089 operator << (ostream &out, HTTPChannel::State state) {
04090 #ifdef NDEBUG
04091   return out << (int)state;
04092 #else
04093   switch (state) {
04094   case HTTPChannel::S_new:
04095     return out << "new";
04096 
04097   case HTTPChannel::S_try_next_proxy:
04098     return out << "try_next_proxy";
04099 
04100   case HTTPChannel::S_connecting:
04101     return out << "connecting";
04102 
04103   case HTTPChannel::S_connecting_wait:
04104     return out << "connecting_wait";
04105 
04106   case HTTPChannel::S_http_proxy_ready:
04107     return out << "http_proxy_ready";
04108 
04109   case HTTPChannel::S_http_proxy_request_sent:
04110     return out << "http_proxy_request_sent";
04111 
04112   case HTTPChannel::S_http_proxy_reading_header:
04113     return out << "http_proxy_reading_header";
04114 
04115   case HTTPChannel::S_socks_proxy_greet:
04116     return out << "socks_proxy_greet";
04117 
04118   case HTTPChannel::S_socks_proxy_greet_reply:
04119     return out << "socks_proxy_greet_reply";
04120 
04121   case HTTPChannel::S_socks_proxy_connect:
04122     return out << "socks_proxy_connect";
04123 
04124   case HTTPChannel::S_socks_proxy_connect_reply:
04125     return out << "socks_proxy_connect_reply";
04126 
04127   case HTTPChannel::S_setup_ssl:
04128     return out << "setup_ssl";
04129 
04130   case HTTPChannel::S_ssl_handshake:
04131     return out << "ssl_handshake";
04132 
04133   case HTTPChannel::S_ready:
04134     return out << "ready";
04135 
04136   case HTTPChannel::S_request_sent:
04137     return out << "request_sent";
04138 
04139   case HTTPChannel::S_reading_header:
04140     return out << "reading_header";
04141 
04142   case HTTPChannel::S_start_direct_file_read:
04143     return out << "start_direct_file_read";
04144 
04145   case HTTPChannel::S_read_header:
04146     return out << "read_header";
04147 
04148   case HTTPChannel::S_begin_body:
04149     return out << "begin_body";
04150 
04151   case HTTPChannel::S_reading_body:
04152     return out << "reading_body";
04153 
04154   case HTTPChannel::S_read_body:
04155     return out << "read_body";
04156 
04157   case HTTPChannel::S_read_trailer:
04158     return out << "read_trailer";
04159 
04160   case HTTPChannel::S_failure:
04161     return out << "failure";
04162   }
04163 
04164   return out << "invalid state(" << (int)state << ")";
04165 #endif  // NDEBUG
04166 }
04167 
04168 #endif  // HAVE_OPENSSL
 All Classes Functions Variables Enumerations