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