00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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>
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
00043
00044
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
00077 _nonblocking = false;
00078
00079
00080
00081
00082
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
00121
00122
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
00138
00139
00140
00141
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
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
00210
00211
00212
00213
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
00226
00227
00228
00229
00230
00231
00232 bool HTTPChannel::
00233 will_close_connection() const {
00234 if (get_http_version() < HTTPEnum::HV_11) {
00235
00236 return true;
00237 }
00238
00239 string connection = get_header_value("Connection");
00240 if (downcase(connection) == "close") {
00241
00242 return true;
00243 }
00244
00245 if (connection.empty() && !get_persistent_connection()) {
00246
00247 return true;
00248 }
00249
00250
00251 return false;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
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
00285
00286
00287
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
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
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
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
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
00372
00373
00374
00375
00376
00377
00378
00379 if (_state == _done_state) {
00380 return reached_done_state();
00381 }
00382
00383 bool repeat_later;
00384 do {
00385
00386
00387
00388 if (_bio.is_null() && _state != S_try_next_proxy) {
00389 if (_connect_count > http_max_connect_count) {
00390
00391
00392
00393
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
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
00435
00436
00437
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
00536 return reached_done_state();
00537 }
00538 thread_consider_yield();
00539 } while (!repeat_later || _bio.is_null());
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 thread_yield();
00551 return true;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
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
00585
00586
00587 _state = S_reading_body;
00588 _read_index++;
00589 result = new IChunkedStream(_source, this);
00590
00591 } else {
00592
00593
00594
00595
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
00610
00611
00612
00613
00614
00615
00616
00617 void HTTPChannel::
00618 close_read_body(istream *stream) const {
00619 if (stream != (istream *)NULL) {
00620
00621
00622
00623
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
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
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
00678
00679 return true;
00680 }
00681
00682
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
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
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
00735
00736 return true;
00737 }
00738
00739
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
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
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
00795
00796 return true;
00797 }
00798
00799
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
00812
00813
00814
00815
00816
00817
00818
00819
00820
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
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
00844
00845
00846
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
00861
00862
00863
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
00891
00892
00893
00894
00895
00896 bool HTTPChannel::
00897 reached_done_state() {
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 if (_state == S_failure) {
00908
00909
00910
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
00950 _status_list.clear();
00951
00952 if (_download_dest == DD_none) {
00953
00954 return false;
00955
00956 } else {
00957
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
00983
00984
00985
00986
00987
00988
00989
00990 bool HTTPChannel::
00991 run_try_next_proxy() {
00992 if (_proxy_next_index < _proxies.size()) {
00993
00994
00995 _status_list.push_back(_status_entry);
00996 _status_entry = StatusEntry();
00997
00998
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
01010 _state = S_failure;
01011 return false;
01012 }
01013
01014
01015
01016
01017
01018
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
01065
01066
01067
01068
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
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
01095
01096 tv.tv_sec = (int)_connect_timeout;
01097 tv.tv_usec = (int)((_connect_timeout - tv.tv_sec) * 1000000.0);
01098 } else {
01099
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
01109 _status_entry._status_code = SC_internal_error;
01110 _state = S_try_next_proxy;
01111 return false;
01112 }
01113
01114 if (errcode == 0) {
01115
01116 if (get_blocking_connect() ||
01117 (TrueClock::get_global_ptr()->get_short_time() -
01118 _started_connecting_time > get_connect_timeout())) {
01119
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
01134 _state = S_connecting;
01135 return false;
01136 }
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 bool HTTPChannel::
01147 run_http_proxy_ready() {
01148
01149 nassertr(!_proxy_request_text.empty(), false);
01150 if (!server_send(_proxy_request_text, false)) {
01151 return true;
01152 }
01153
01154
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
01162
01163
01164
01165
01166
01167
01168
01169 bool HTTPChannel::
01170 run_http_proxy_request_sent() {
01171
01172 string line;
01173 if (!server_getline_failsafe(line)) {
01174 return true;
01175 }
01176
01177
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
01199
01200
01201
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
01211
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
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
01232 _state = S_begin_body;
01233 return false;
01234 }
01235 }
01236 }
01237
01238 if (!is_valid()) {
01239
01240
01241
01242
01243
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
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
01266
01267
01268
01269
01270
01271 bool HTTPChannel::
01272 run_socks_proxy_greet() {
01273 static const char socks_greeting[] = {
01274 0x05,
01275 0x01,
01276 0x00,
01277
01278
01279
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
01289 _state = S_socks_proxy_greet_reply;
01290 return false;
01291 }
01292
01293
01294
01295
01296
01297
01298
01299 bool HTTPChannel::
01300 run_socks_proxy_greet_reply() {
01301 string reply;
01302
01303
01304 if (!server_get_failsafe(reply, 2)) {
01305 return true;
01306 }
01307
01308 if (reply[0] != 0x05) {
01309
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
01329
01330 _state = S_socks_proxy_connect;
01331 return false;
01332 }
01333
01334
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
01346
01347
01348
01349
01350 bool HTTPChannel::
01351 run_socks_proxy_connect() {
01352 static const char socks_connect[] = {
01353 0x05,
01354 0x01,
01355 0x00,
01356 0x03,
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
01388
01389
01390
01391
01392 bool HTTPChannel::
01393 run_socks_proxy_connect_reply() {
01394 string reply;
01395
01396
01397 if (!server_get_failsafe(reply, 2)) {
01398 return true;
01399 }
01400
01401 if (reply[0] != 0x05) {
01402
01403 downloader_cat.info()
01404 << _NOTIFY_HTTP_CHANNEL_ID
01405 << "Rejecting Socks version " << (int)reply[0] << "\n";
01406 close_connection();
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
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430 switch (reply[1]) {
01431 case 0x03:
01432 case 0x04:
01433 case 0x05:
01434 case 0x06:
01435
01436
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();
01445 _state = S_try_next_proxy;
01446 return false;
01447 }
01448
01449
01450 _working_get = reply;
01451 if (!server_get_failsafe(reply, 5)) {
01452 return true;
01453 }
01454
01455
01456 int total_bytes = 6;
01457
01458 switch (reply[3]) {
01459 case 0x01:
01460 total_bytes += 4;
01461 break;
01462
01463 case 0x03:
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
01477
01478 _working_get = reply;
01479 if (!server_get_failsafe(reply, total_bytes)) {
01480 return true;
01481 }
01482
01483 if (downloader_cat.is_debug()) {
01484
01485 string connect_host;
01486
01487 switch (reply[3]) {
01488 case 0x01:
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:
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
01525
01526
01527
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
01539
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
01565
01566
01567
01568
01569
01570
01571
01572
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
01607
01608 _started_connecting_time =
01609 TrueClock::get_global_ptr()->get_short_time();
01610
01611 return false;
01612 }
01613
01614
01615
01616
01617
01618
01619
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
01630 return true;
01631 }
01632
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
01642
01643
01644 if (!_cipher_list.empty()) {
01645
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
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
01690
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
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
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
01777
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
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803 bool HTTPChannel::
01804 run_ready() {
01805
01806 if (!_request_text.empty()) {
01807 if (!server_send(_request_text, false)) {
01808 return true;
01809 }
01810 }
01811
01812
01813 _state = S_request_sent;
01814 _sent_request_time = TrueClock::get_global_ptr()->get_short_time();
01815 return false;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824 bool HTTPChannel::
01825 run_request_sent() {
01826
01827 string line;
01828 if (!server_getline_failsafe(line)) {
01829 return true;
01830 }
01831
01832
01833 while (line.empty()) {
01834 if (!server_getline_failsafe(line)) {
01835 return true;
01836 }
01837 }
01838
01839 if (!parse_http_response(line)) {
01840
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
01855
01856
01857
01858
01859
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
01870 _status_entry._status_code = SC_lost_connection;
01871 _state = S_try_next_proxy;
01872
01873 } else {
01874
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
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
01899
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
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
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
01959
01960
01961 if (_server_response_has_no_body) {
01962
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
01981
01982 _file_size = _last_byte_delivered - _first_byte_delivered + 1;
01983 _got_file_size = true;
01984 }
01985 _redirect = get_header_value("Location");
01986
01987
01988
01989
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
02005
02006 close_connection();
02007 }
02008
02009
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
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
02025 _state = S_begin_body;
02026 return false;
02027 }
02028 }
02029 }
02030
02031 if (get_status_code() == 401 && last_status != 401) {
02032
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
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
02054
02055
02056
02057
02058
02059
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
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
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
02103
02104
02105
02106
02107
02108
02109 _state = S_try_next_proxy;
02110 return false;
02111 }
02112
02113
02114 return false;
02115 }
02116
02117
02118
02119
02120
02121
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
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150 bool HTTPChannel::
02151 run_read_header() {
02152 _state = S_begin_body;
02153 return false;
02154 }
02155
02156
02157
02158
02159
02160
02161
02162 bool HTTPChannel::
02163 run_begin_body() {
02164 if (will_close_connection()) {
02165
02166
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
02178 _state = S_read_trailer;
02179
02180 } else if (get_file_size() > (int)_skip_body_size) {
02181
02182
02183
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
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224 bool HTTPChannel::
02225 run_reading_body() {
02226 if (will_close_connection()) {
02227
02228
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
02239 if (_body_stream == NULL || !_owns_body_stream) {
02240
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
02263 return true;
02264 }
02265
02266 reset_body_stream();
02267
02268
02269 nassertr(_state != S_reading_body, false);
02270 return false;
02271 }
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287 bool HTTPChannel::
02288 run_read_body() {
02289 if (will_close_connection()) {
02290
02291
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
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
02318
02319
02320
02321
02322
02323 bool HTTPChannel::
02324 run_read_trailer() {
02325 if (will_close_connection()) {
02326
02327
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
02343
02344
02345
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
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
02394 reset_body_stream();
02395 close_download_stream();
02396 _started_download = false;
02397 return false;
02398 } else {
02399
02400 return true;
02401 }
02402 }
02403
02404
02405
02406
02407
02408
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
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
02446 reset_body_stream();
02447 close_download_stream();
02448 _started_download = false;
02449 return false;
02450 } else {
02451
02452 return true;
02453 }
02454 }
02455
02456
02457
02458
02459
02460
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
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
02509 reset_body_stream();
02510 close_download_stream();
02511 _started_download = false;
02512 return false;
02513 } else {
02514
02515 return true;
02516 }
02517 }
02518
02519
02520
02521
02522
02523
02524
02525
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
02541
02542 nonblocking = true;
02543 #endif
02544
02545
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
02553
02554
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
02570
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
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
02600
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
02610 if (_request.get_url().get_scheme() == "file") {
02611
02612
02613
02614 reset_to_new();
02615 _bio = new BioPtr(_request.get_url());
02616 if (_bio->get_bio() != NULL) {
02617
02618 _source = new BioStreamPtr(new BioStream(_bio));
02619 _status_entry._status_code = 200;
02620 _state = S_start_direct_file_read;
02621
02622
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
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
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
02662
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
02676
02677
02678
02679
02680
02681
02682
02683 void HTTPChannel::
02684 reconsider_proxy() {
02685 _proxy_tunnel_now = false;
02686 _proxy_serves_document = false;
02687
02688 if (!_proxy.empty()) {
02689
02690
02691
02692
02693
02694 _proxy_tunnel_now =
02695 (get_proxy_tunnel() || _want_ssl ||
02696 _method == HTTPEnum::M_connect || _proxy.get_scheme() == "socks");
02697
02698
02699
02700 _proxy_serves_document = !_proxy_tunnel_now;
02701 }
02702
02703 make_header();
02704 make_request_text();
02705
02706 if (_proxy_tunnel_now) {
02707
02708
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
02729
02730
02731
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
02755
02756
02757
02758
02759
02760
02761
02762
02763
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
02786
02787
02788
02789
02790
02791
02792
02793
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
02815
02816
02817
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
02854
02855
02856
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
02875
02876
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
02890
02891
02892
02893
02894
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
02904 str = _working_get;
02905 _working_get = string();
02906 {
02907
02908
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
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
02938
02939
02940
02941
02942
02943
02944 bool HTTPChannel::
02945 server_getline_failsafe(string &str) {
02946 if (!server_getline(str)) {
02947 if (_bio.is_null()) {
02948
02949 if (_response_type == RT_hangup) {
02950
02951 _status_entry._status_code = SC_lost_connection;
02952 _state = S_try_next_proxy;
02953
02954 } else {
02955
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
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
02983
02984
02985
02986
02987
02988
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
03011
03012
03013
03014
03015
03016
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
03023 if (_response_type == RT_hangup) {
03024
03025 _status_entry._status_code = SC_lost_connection;
03026 _state = S_try_next_proxy;
03027
03028 } else {
03029
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
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
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069 bool HTTPChannel::
03070 server_send(const string &str, bool secret) {
03071 nassertr(str.length() > _sent_so_far, true);
03072
03073
03074
03075
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
03083 return false;
03084 }
03085
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
03113 _sent_so_far = 0;
03114 return true;
03115 }
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125 bool HTTPChannel::
03126 parse_http_response(const string &line) {
03127
03128
03129 if (line.length() < 5 || line.substr(0, 5) != string("HTTP/")) {
03130
03131 _status_entry._status_code = SC_non_http_response;
03132 if (_response_type == RT_non_http) {
03133
03134 _state = S_try_next_proxy;
03135
03136 } else {
03137
03138
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
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
03178
03179
03180
03181
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
03193
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
03202
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
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
03235
03236
03237
03238
03239
03240
03241 bool HTTPChannel::
03242 parse_content_range(const string &content_range) {
03243
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
03277 return false;
03278 }
03279
03280
03281
03282
03283
03284
03285
03286
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
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
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
03506
03507
03508
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
03517
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
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
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
03575
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
03602
03603
03604
03605
03606
03607 bool HTTPChannel::
03608 match_cert_name(const string &cert_name, const string &hostname) {
03609
03610
03611
03612
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
03622
03623
03624
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
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
03646
03647
03648
03649
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
03662
03663
03664
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
03679
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
03686
03687 request_path = _request.get_url().get_path_and_query();
03688 }
03689
03690
03691
03692
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
03709
03710
03711
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
03734
03735 if (_first_byte_requested != 0) {
03736
03737
03738
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
03751
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
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
03778 if (_request.has_date()) {
03779
03780
03781
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
03792 break;
03793
03794 case DocumentSpec::CC_revalidate:
03795
03796 stream
03797 << "Cache-Control: max-age=0\r\n";
03798 break;
03799
03800 case DocumentSpec::CC_no_cache:
03801
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
03821
03822
03823
03824
03825
03826
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
03845
03846
03847
03848
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
03877
03878
03879
03880
03881
03882 void HTTPChannel::
03883 reset_url(const URLSpec &old_url, const URLSpec &new_url) {
03884
03885
03886
03887
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
03904
03905
03906
03907
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
03916
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
03930
03931
03932
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
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
03955
03956
03957
03958
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
03969
03970
03971
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
03988
03989
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
04005
04006
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
04023
04024
04025
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
04039
04040
04041
04042
04043
04044
04045 bool HTTPChannel::
04046 more_useful_status_code(int a, int b) {
04047 if (a >= 100 && b >= 100) {
04048
04049
04050
04051
04052 if (a == 407) {
04053 a += 1000;
04054 }
04055 if (b == 407) {
04056 b += 1000;
04057 }
04058
04059
04060 int series_a = (a / 100);
04061 int series_b = (b / 100);
04062
04063
04064 return (series_a < series_b);
04065 }
04066
04067 if (a < 100 && b < 100) {
04068
04069
04070 return (a > b);
04071 }
04072
04073 if (a < 100) {
04074
04075
04076 return (a > SC_http_error_watermark);
04077 }
04078
04079
04080 return (b < SC_http_error_watermark);
04081 }
04082
04083
04084
04085
04086
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