00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "httpChannel.h"
00020 #include "httpClient.h"
00021 #include "bioStream.h"
00022 #include "chunkedStream.h"
00023 #include "identityStream.h"
00024 #include "config_downloader.h"
00025 #include "clockObject.h"
00026 #include "buffer.h"
00027
00028 #ifdef HAVE_SSL
00029 #ifdef REPORT_OPENSSL_ERRORS
00030 #include <openssl/err.h>
00031 #endif
00032
00033 TypeHandle HTTPChannel::_type_handle;
00034
00035
00036
00037
00038
00039
00040 HTTPChannel::
00041 HTTPChannel(HTTPClient *client) :
00042 _client(client)
00043 {
00044 _persistent_connection = false;
00045 _connect_timeout = connect_timeout;
00046 _http_timeout = http_timeout;
00047 _blocking_connect = false;
00048 _download_throttle = false;
00049 _max_bytes_per_second = downloader_byte_rate;
00050 _seconds_per_update = downloader_frequency;
00051 _max_updates_per_second = 1.0f / _seconds_per_update;
00052 _bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
00053 _nonblocking = false;
00054 _want_ssl = false;
00055 _proxy_serves_document = false;
00056 _first_byte = 0;
00057 _last_byte = 0;
00058 _read_index = 0;
00059 _file_size = 0;
00060 _bytes_downloaded = 0;
00061 _bytes_requested = 0;
00062 _status_code = 0;
00063 _status_string = string();
00064 _response_type = RT_none;
00065 _proxy = _client->get_proxy();
00066 _http_version = _client->get_http_version();
00067 _http_version_string = _client->get_http_version_string();
00068 _state = S_new;
00069 _done_state = S_new;
00070 _started_download = false;
00071 _sent_so_far = 0;
00072 _proxy_tunnel = false;
00073 _body_stream = NULL;
00074 _sbio = NULL;
00075 _last_status_code = 0;
00076 _last_run_time = 0.0f;
00077 _download_to_ramfile = NULL;
00078 }
00079
00080
00081
00082
00083
00084
00085 HTTPChannel::
00086 ~HTTPChannel() {
00087 close_connection();
00088 reset_download_to();
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 VirtualFileSystem *HTTPChannel::
00098 get_file_system() const {
00099 return NULL;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 Filename HTTPChannel::
00109 get_filename() const {
00110 return Filename();
00111 }
00112
00113
00114
00115
00116
00117
00118
00119 bool HTTPChannel::
00120 is_regular_file() const {
00121 return is_valid();
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 bool HTTPChannel::
00133 will_close_connection() const {
00134 if (get_http_version() < HTTPEnum::HV_11) {
00135
00136 return true;
00137 }
00138
00139 string connection = get_header_value("Connection");
00140 if (downcase(connection) == "close") {
00141
00142 return true;
00143 }
00144
00145
00146 return false;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 istream *HTTPChannel::
00159 open_read_file() const {
00160 return ((HTTPChannel *)this)->read_body();
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 string HTTPChannel::
00171 get_header_value(const string &key) const {
00172 Headers::const_iterator hi = _headers.find(downcase(key));
00173 if (hi != _headers.end()) {
00174 return (*hi).second;
00175 }
00176 return string();
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 void HTTPChannel::
00186 write_headers(ostream &out) const {
00187 Headers::const_iterator hi;
00188 for (hi = _headers.begin(); hi != _headers.end(); ++hi) {
00189 out << (*hi).first << ": " << (*hi).second << "\n";
00190 }
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 bool HTTPChannel::
00207 run() {
00208 if (_state == _done_state || _state == S_failure) {
00209 clear_extra_headers();
00210 if (!reached_done_state()) {
00211 return false;
00212 }
00213 }
00214
00215 if (_started_download) {
00216 if (_nonblocking && _download_throttle) {
00217 double now = ClockObject::get_global_clock()->get_real_time();
00218 double elapsed = now - _last_run_time;
00219 if (elapsed < _seconds_per_update) {
00220
00221 return true;
00222 }
00223 int num_potential_updates = (int)(elapsed / _seconds_per_update);
00224 _last_run_time = now;
00225 _bytes_requested += _bytes_per_update * num_potential_updates;
00226 if (downloader_cat.is_spam()) {
00227 downloader_cat.spam()
00228 << "elapsed = " << elapsed << " num_potential_updates = "
00229 << num_potential_updates << " bytes_requested = "
00230 << _bytes_requested << "\n";
00231 }
00232 }
00233 switch (_download_dest) {
00234 case DD_none:
00235 return false;
00236
00237 case DD_file:
00238 return run_download_to_file();
00239
00240 case DD_ram:
00241 return run_download_to_ram();
00242 }
00243 }
00244
00245 if (downloader_cat.is_spam()) {
00246 downloader_cat.spam()
00247 << "begin run(), _state = " << (int)_state << ", _done_state = "
00248 << (int)_done_state << "\n";
00249 }
00250
00251 if (_state == _done_state) {
00252 return reached_done_state();
00253 }
00254
00255 bool repeat_later;
00256 do {
00257 if (_bio.is_null()) {
00258 if (_connect_count > http_max_connect_count) {
00259
00260
00261
00262
00263 downloader_cat.warning()
00264 << "Too many lost connections, giving up.\n";
00265 _state = S_failure;
00266 return false;
00267 }
00268
00269
00270 _proxy = _client->get_proxy();
00271
00272 if (_proxy.empty()) {
00273 _bio = new BioPtr(_request.get_url());
00274 } else {
00275 _bio = new BioPtr(_proxy);
00276 }
00277 _source = new BioStreamPtr(new BioStream(_bio));
00278 if (_nonblocking) {
00279 BIO_set_nbio(*_bio, 1);
00280 }
00281
00282 if (_connect_count > 0) {
00283 downloader_cat.info()
00284 << "Reconnecting to " << _bio->get_server_name() << ":"
00285 << _bio->get_port() << "\n";
00286 }
00287
00288 _state = S_connecting;
00289 _started_connecting_time =
00290 ClockObject::get_global_clock()->get_real_time();
00291 _connect_count++;
00292 }
00293
00294 if (downloader_cat.is_spam()) {
00295 downloader_cat.spam()
00296 << "continue run(), _state = " << (int)_state << "\n";
00297 }
00298
00299 switch (_state) {
00300 case S_connecting:
00301 repeat_later = run_connecting();
00302 break;
00303
00304 case S_connecting_wait:
00305 repeat_later = run_connecting_wait();
00306 break;
00307
00308 case S_proxy_ready:
00309 repeat_later = run_proxy_ready();
00310 break;
00311
00312 case S_proxy_request_sent:
00313 repeat_later = run_proxy_request_sent();
00314 break;
00315
00316 case S_proxy_reading_header:
00317 repeat_later = run_proxy_reading_header();
00318 break;
00319
00320 case S_setup_ssl:
00321 repeat_later = run_setup_ssl();
00322 break;
00323
00324 case S_ssl_handshake:
00325 repeat_later = run_ssl_handshake();
00326 break;
00327
00328 case S_ready:
00329 repeat_later = run_ready();
00330 break;
00331
00332 case S_request_sent:
00333 repeat_later = run_request_sent();
00334 break;
00335
00336 case S_reading_header:
00337 repeat_later = run_reading_header();
00338 break;
00339
00340 case S_read_header:
00341 repeat_later = run_read_header();
00342 break;
00343
00344 case S_begin_body:
00345 repeat_later = run_begin_body();
00346 break;
00347
00348 case S_reading_body:
00349 repeat_later = run_reading_body();
00350 break;
00351
00352 case S_read_body:
00353 repeat_later = run_read_body();
00354 break;
00355
00356 case S_read_trailer:
00357 repeat_later = run_read_trailer();
00358 break;
00359
00360 default:
00361 downloader_cat.warning()
00362 << "Unhandled state " << (int)_state << "\n";
00363 return false;
00364 }
00365
00366 if (_state == _done_state || _state == S_failure) {
00367 clear_extra_headers();
00368
00369 return reached_done_state();
00370 }
00371 } while (!repeat_later || _bio.is_null());
00372
00373 if (downloader_cat.is_spam()) {
00374 downloader_cat.spam()
00375 << "later run(), _state = " << (int)_state
00376 << ", _done_state = " << (int)_done_state << "\n";
00377 }
00378 return true;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 ISocketStream *HTTPChannel::
00394 read_body() {
00395 if ((_state != S_read_header && _state != S_begin_body) || _source.is_null()) {
00396 return NULL;
00397 }
00398
00399 string transfer_coding = downcase(get_header_value("Transfer-Encoding"));
00400 string content_length = get_header_value("Content-Length");
00401
00402 ISocketStream *result;
00403 if (transfer_coding == "chunked") {
00404
00405
00406
00407 _file_size = 0;
00408 _state = S_reading_body;
00409 _read_index++;
00410 result = new IChunkedStream(_source, (HTTPChannel *)this);
00411
00412 } else {
00413
00414
00415
00416
00417 _state = S_reading_body;
00418 _read_index++;
00419 result = new IIdentityStream(_source, (HTTPChannel *)this,
00420 !content_length.empty(), _file_size);
00421 }
00422
00423 return result;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 bool HTTPChannel::
00461 download_to_file(const Filename &filename, bool subdocument_resumes) {
00462 reset_download_to();
00463 _download_to_filename = filename;
00464 _download_to_filename.set_binary();
00465 _download_to_file.close();
00466 _download_to_file.clear();
00467
00468 _subdocument_resumes = (subdocument_resumes && _first_byte != 0);
00469
00470 if (!_download_to_filename.open_write(_download_to_file, !_subdocument_resumes)) {
00471 downloader_cat.info()
00472 << "Could not open " << _download_to_filename << " for writing.\n";
00473 return false;
00474 }
00475
00476 _download_dest = DD_file;
00477 if (!reset_download_position()) {
00478 reset_download_to();
00479 return false;
00480 }
00481
00482 if (_nonblocking) {
00483
00484
00485 return true;
00486 }
00487
00488
00489 run();
00490 return is_download_complete();
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 bool HTTPChannel::
00525 download_to_ram(Ramfile *ramfile, bool subdocument_resumes) {
00526 nassertr(ramfile != (Ramfile *)NULL, false);
00527 reset_download_to();
00528 ramfile->_pos = 0;
00529 _download_to_ramfile = ramfile;
00530 _download_dest = DD_ram;
00531 _subdocument_resumes = (subdocument_resumes && _first_byte != 0);
00532
00533 if (!reset_download_position()) {
00534 reset_download_to();
00535 return false;
00536 }
00537
00538 if (_nonblocking) {
00539
00540
00541 return true;
00542 }
00543
00544
00545 run();
00546 return is_download_complete();
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 SocketStream *HTTPChannel::
00562 get_connection() {
00563 if (!is_connection_ready()) {
00564 return NULL;
00565 }
00566
00567 BioStream *stream = _source->get_stream();
00568 _source->set_stream(NULL);
00569
00570
00571 reset_to_new();
00572
00573 return stream;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582 string HTTPChannel::
00583 downcase(const string &s) {
00584 string result;
00585 result.reserve(s.size());
00586 string::const_iterator p;
00587 for (p = s.begin(); p != s.end(); ++p) {
00588 result += tolower(*p);
00589 }
00590 return result;
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600 bool HTTPChannel::
00601 reached_done_state() {
00602 if (downloader_cat.is_spam()) {
00603 downloader_cat.spam()
00604 << "terminating run(), _state = " << (int)_state
00605 << ", _done_state = " << (int)_done_state << "\n";
00606 }
00607
00608 if (_state == S_failure || _download_dest == DD_none) {
00609
00610 return false;
00611
00612 } else {
00613
00614 _body_stream = read_body();
00615 if (_body_stream == (ISocketStream *)NULL) {
00616 if (downloader_cat.is_debug()) {
00617 downloader_cat.debug()
00618 << "Unable to download body.\n";
00619 }
00620 return false;
00621 } else {
00622 _started_download = true;
00623 _last_run_time = ClockObject::get_global_clock()->get_real_time();
00624 return true;
00625 }
00626 }
00627 }
00628
00629
00630
00631
00632
00633
00634
00635 bool HTTPChannel::
00636 run_connecting() {
00637 _status_code = 0;
00638 _status_string = string();
00639 if (BIO_do_connect(*_bio) <= 0) {
00640 if (BIO_should_retry(*_bio)) {
00641 _state = S_connecting_wait;
00642 return false;
00643 }
00644 downloader_cat.info()
00645 << "Could not connect to " << _bio->get_server_name() << ":"
00646 << _bio->get_port() << "\n";
00647 #ifdef REPORT_OPENSSL_ERRORS
00648 ERR_print_errors_fp(stderr);
00649 #endif
00650 _state = S_failure;
00651 return false;
00652 }
00653
00654 if (downloader_cat.is_debug()) {
00655 downloader_cat.debug()
00656 << "Connected to " << _bio->get_server_name() << ":"
00657 << _bio->get_port() << "\n";
00658 }
00659
00660 if (!_proxy.empty()) {
00661 _state = S_proxy_ready;
00662
00663 } else {
00664 _state = _want_ssl ? S_setup_ssl : S_ready;
00665 }
00666 return false;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676 bool HTTPChannel::
00677 run_connecting_wait() {
00678 int fd = -1;
00679 BIO_get_fd(*_bio, &fd);
00680 if (fd < 0) {
00681 downloader_cat.warning()
00682 << "nonblocking socket BIO has no file descriptor.\n";
00683 _state = S_failure;
00684 return false;
00685 }
00686
00687 if (downloader_cat.is_debug()) {
00688 downloader_cat.debug()
00689 << "waiting to connect to " << _request.get_url().get_server_and_port() << ".\n";
00690 }
00691 fd_set wset;
00692 FD_ZERO(&wset);
00693 FD_SET(fd, &wset);
00694 struct timeval tv;
00695 if (get_blocking_connect()) {
00696
00697
00698 tv.tv_sec = (int)_connect_timeout;
00699 tv.tv_usec = (int)((_connect_timeout - tv.tv_sec) * 1000000.0);
00700 } else {
00701
00702 tv.tv_sec = 0;
00703 tv.tv_usec = 0;
00704 }
00705 int errcode = select(fd + 1, NULL, &wset, NULL, &tv);
00706 if (errcode < 0) {
00707 downloader_cat.warning()
00708 << "Error in select.\n";
00709 _state = S_failure;
00710 return false;
00711 }
00712
00713 if (errcode == 0) {
00714
00715 if (get_blocking_connect() ||
00716 (ClockObject::get_global_clock()->get_real_time() -
00717 _started_connecting_time > get_connect_timeout())) {
00718
00719 downloader_cat.info()
00720 << "Timeout connecting to "
00721 << _request.get_url().get_server_and_port() << ".\n";
00722 _state = S_failure;
00723 return false;
00724 }
00725 return true;
00726 }
00727
00728
00729 _state = S_connecting;
00730 return false;
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 bool HTTPChannel::
00747 run_proxy_ready() {
00748
00749 if (!_proxy_request_text.empty()) {
00750 if (!http_send(_proxy_request_text)) {
00751 return true;
00752 }
00753
00754
00755 _state = S_proxy_request_sent;
00756
00757 } else {
00758 _state = S_ready;
00759 }
00760 return false;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 bool HTTPChannel::
00773 run_proxy_request_sent() {
00774
00775 string line;
00776 if (!http_getline(line)) {
00777 if (_bio.is_null()) {
00778
00779 if (_response_type == RT_hangup) {
00780
00781 _state = S_failure;
00782
00783 } else {
00784
00785 _response_type = RT_hangup;
00786 }
00787 }
00788 return true;
00789 }
00790
00791 if (!parse_http_response(line)) {
00792 return false;
00793 }
00794
00795 _state = S_proxy_reading_header;
00796 _current_field_name = string();
00797 _current_field_value = string();
00798 _headers.clear();
00799 _file_size = 0;
00800 return false;
00801 }
00802
00803
00804
00805
00806
00807
00808
00809 bool HTTPChannel::
00810 run_proxy_reading_header() {
00811 if (parse_http_header()) {
00812 return true;
00813 }
00814
00815 _redirect = get_header_value("Location");
00816
00817
00818
00819 _server_response_has_no_body =
00820 (get_status_code() / 100 == 1 ||
00821 get_status_code() == 204 ||
00822 get_status_code() == 304);
00823
00824 int last_status = _last_status_code;
00825 _last_status_code = get_status_code();
00826
00827 if (get_status_code() == 407 && last_status != 407 && !_proxy.empty()) {
00828
00829 string authenticate_request = get_header_value("Proxy-Authenticate");
00830 _proxy_auth = _client->generate_auth(_proxy, true, authenticate_request);
00831 if (_proxy_auth != (HTTPAuthorization *)NULL) {
00832 _proxy_realm = _proxy_auth->get_realm();
00833 _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
00834 if (!_proxy_username.empty()) {
00835 make_proxy_request_text();
00836
00837
00838 _state = S_begin_body;
00839 return false;
00840 }
00841 }
00842 }
00843
00844 if (!is_valid()) {
00845
00846
00847
00848
00849
00850 if (get_status_code() != 407) {
00851 _status_code += 1000;
00852 }
00853
00854 _state = S_failure;
00855 return false;
00856 }
00857
00858
00859 _proxy_tunnel = true;
00860 make_request_text();
00861
00862 _state = _want_ssl ? S_setup_ssl : S_ready;
00863 return false;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 bool HTTPChannel::
00873 run_setup_ssl() {
00874 _sbio = BIO_new_ssl(_client->get_ssl_ctx(), true);
00875 BIO_push(_sbio, *_bio);
00876
00877 if (downloader_cat.is_debug()) {
00878 downloader_cat.debug()
00879 << "performing SSL handshake\n";
00880 }
00881 _state = S_ssl_handshake;
00882 return false;
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892 bool HTTPChannel::
00893 run_ssl_handshake() {
00894 if (BIO_do_handshake(_sbio) <= 0) {
00895 if (BIO_should_retry(_sbio)) {
00896 return true;
00897 }
00898 downloader_cat.info()
00899 << "Could not establish SSL handshake with "
00900 << _request.get_url().get_server_and_port() << "\n";
00901 #ifdef REPORT_OPENSSL_ERRORS
00902 ERR_print_errors_fp(stderr);
00903 #endif
00904
00905
00906 _state = S_failure;
00907 return false;
00908 }
00909
00910 SSL *ssl;
00911 BIO_get_ssl(_sbio, &ssl);
00912 nassertr(ssl != (SSL *)NULL, false);
00913
00914 if (!_nonblocking) {
00915 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
00916 }
00917
00918
00919
00920 _bio->set_bio(_sbio);
00921 _sbio = NULL;
00922
00923
00924 long verify_result = SSL_get_verify_result(ssl);
00925 if (verify_result == X509_V_ERR_CERT_HAS_EXPIRED) {
00926 downloader_cat.info()
00927 << "Expired certificate from " << _request.get_url().get_server_and_port() << "\n";
00928 if (_client->get_verify_ssl() == HTTPClient::VS_normal) {
00929 _state = S_failure;
00930 return false;
00931 }
00932
00933 } else if (verify_result == X509_V_ERR_CERT_NOT_YET_VALID) {
00934 downloader_cat.info()
00935 << "Premature certificate from " << _request.get_url().get_server_and_port() << "\n";
00936 if (_client->get_verify_ssl() == HTTPClient::VS_normal) {
00937 _state = S_failure;
00938 return false;
00939 }
00940
00941 } else if (verify_result != X509_V_OK) {
00942 downloader_cat.info()
00943 << "Unable to verify identity of " << _request.get_url().get_server_and_port()
00944 << ", verify error code " << verify_result << "\n";
00945 if (_client->get_verify_ssl() != HTTPClient::VS_no_verify) {
00946 _state = S_failure;
00947 return false;
00948 }
00949 }
00950
00951 X509 *cert = SSL_get_peer_certificate(ssl);
00952 if (cert == (X509 *)NULL) {
00953 downloader_cat.info()
00954 << "No certificate was presented by server.\n";
00955 if (_client->get_verify_ssl() != HTTPClient::VS_no_verify ||
00956 !_client->_expected_servers.empty()) {
00957 _state = S_failure;
00958 return false;
00959 }
00960
00961 } else {
00962 if (downloader_cat.is_debug()) {
00963 downloader_cat.debug()
00964 << "Received certificate from server:\n" << flush;
00965 X509_print_fp(stderr, cert);
00966 fflush(stderr);
00967 }
00968
00969 X509_NAME *subject = X509_get_subject_name(cert);
00970
00971 if (downloader_cat.is_debug()) {
00972 string org_name = get_x509_name_component(subject, NID_organizationName);
00973 string org_unit_name = get_x509_name_component(subject, NID_organizationalUnitName);
00974 string common_name = get_x509_name_component(subject, NID_commonName);
00975
00976 downloader_cat.debug()
00977 << "Server is " << common_name << " from " << org_unit_name
00978 << " / " << org_name << "\n";
00979 }
00980
00981 if (_client->get_verify_ssl() != HTTPClient::VS_no_verify) {
00982
00983
00984 if (!verify_server(subject)) {
00985 downloader_cat.info()
00986 << "Server does not match any expected server.\n";
00987 _state = S_failure;
00988 return false;
00989 }
00990 }
00991
00992 X509_free(cert);
00993 }
00994
00995 _state = S_ready;
00996 return false;
00997 }
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 bool HTTPChannel::
01012 run_ready() {
01013
01014 if (!_request_text.empty()) {
01015 if (!http_send(_request_text)) {
01016 return true;
01017 }
01018 }
01019
01020
01021 _state = S_request_sent;
01022 _sent_request_time = ClockObject::get_global_clock()->get_real_time();
01023 return false;
01024 }
01025
01026
01027
01028
01029
01030
01031
01032 bool HTTPChannel::
01033 run_request_sent() {
01034
01035 string line;
01036 if (!http_getline(line)) {
01037 if (_bio.is_null()) {
01038
01039 if (_response_type == RT_hangup) {
01040
01041 _state = S_failure;
01042
01043 } else {
01044
01045 _response_type = RT_hangup;
01046 }
01047
01048 } else if (ClockObject::get_global_clock()->get_real_time() -
01049 _sent_request_time > get_http_timeout()) {
01050
01051 downloader_cat.info()
01052 << "Timeout waiting for " << _request.get_url().get_server_and_port() << ".\n";
01053 _state = S_failure;
01054 }
01055
01056 return true;
01057 }
01058
01059 if (!parse_http_response(line)) {
01060
01061 return false;
01062 }
01063
01064 _state = S_reading_header;
01065 _current_field_name = string();
01066 _current_field_value = string();
01067 _headers.clear();
01068 _file_size = 0;
01069 return false;
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 bool HTTPChannel::
01081 run_reading_header() {
01082 if (parse_http_header()) {
01083 if (_bio.is_null()) {
01084 downloader_cat.info()
01085 << "Connection lost while reading HTTP response.\n";
01086 if (_response_type == RT_http_hangup) {
01087
01088 _state = S_failure;
01089
01090 } else {
01091
01092 _response_type = RT_http_hangup;
01093 }
01094
01095 } else if (ClockObject::get_global_clock()->get_real_time() -
01096 _sent_request_time > get_http_timeout()) {
01097
01098 downloader_cat.info()
01099 << "Timeout waiting for " << _request.get_url().get_server_and_port() << ".\n";
01100 _state = S_failure;
01101 }
01102 return true;
01103 }
01104 _response_type = RT_http_complete;
01105
01106
01107
01108 clear_extra_headers();
01109
01110 _server_response_has_no_body =
01111 (get_status_code() / 100 == 1 ||
01112 get_status_code() == 204 ||
01113 get_status_code() == 304 ||
01114 _method == HTTPEnum::M_head);
01115
01116
01117 if (get_status_code() == 206) {
01118 string content_range = get_header_value("Content-Range");
01119 if (content_range.empty()) {
01120 downloader_cat.warning()
01121 << "Got 206 response without Content-Range header!\n";
01122 _state = S_failure;
01123 return false;
01124
01125 } else {
01126 if (!parse_content_range(content_range)) {
01127 downloader_cat.warning()
01128 << "Couldn't parse Content-Range: " << content_range << "\n";
01129 _state = S_failure;
01130 return false;
01131 }
01132 }
01133
01134 } else {
01135 _first_byte = 0;
01136 _last_byte = 0;
01137 }
01138
01139
01140 _document_spec = DocumentSpec(_request.get_url());
01141 string tag = get_header_value("ETag");
01142 if (!tag.empty()) {
01143 _document_spec.set_tag(HTTPEntityTag(tag));
01144 }
01145 string date = get_header_value("Last-Modified");
01146 if (!date.empty()) {
01147 _document_spec.set_date(HTTPDate(date));
01148 }
01149
01150
01151
01152 if (!reset_download_position()) {
01153 _state = S_failure;
01154 return false;
01155 }
01156
01157 _file_size = 0;
01158 string content_length = get_header_value("Content-Length");
01159 if (!content_length.empty()) {
01160 _file_size = atoi(content_length.c_str());
01161
01162 } else if (get_status_code() == 206) {
01163
01164
01165 _file_size = _last_byte - _first_byte + 1;
01166 }
01167 _redirect = get_header_value("Location");
01168
01169
01170
01171 if (_redirect.has_path() && !_redirect.has_authority()) {
01172 _redirect.set_scheme(_document_spec.get_url().get_scheme());
01173 _redirect.set_authority(_document_spec.get_url().get_authority());
01174 }
01175
01176 _state = S_read_header;
01177
01178 if (_server_response_has_no_body && will_close_connection()) {
01179
01180
01181 close_connection();
01182 }
01183
01184
01185 int last_status = _last_status_code;
01186 _last_status_code = get_status_code();
01187
01188 if (get_status_code() == 407 && last_status != 407 && !_proxy.empty()) {
01189
01190 string authenticate_request = get_header_value("Proxy-Authenticate");
01191 _proxy_auth =
01192 _client->generate_auth(_proxy, true, authenticate_request);
01193 if (_proxy_auth != (HTTPAuthorization *)NULL) {
01194 _proxy_realm = _proxy_auth->get_realm();
01195 _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
01196 if (!_proxy_username.empty()) {
01197 make_request_text();
01198
01199
01200 _state = S_begin_body;
01201 return false;
01202 }
01203 }
01204 }
01205
01206 if (get_status_code() == 401 && last_status != 401) {
01207
01208 string authenticate_request = get_header_value("WWW-Authenticate");
01209 _www_auth = _client->generate_auth(_request.get_url(), false, authenticate_request);
01210 if (_www_auth != (HTTPAuthorization *)NULL) {
01211 _www_realm = _www_auth->get_realm();
01212 _www_username = _client->select_username(_request.get_url(), false, _www_realm);
01213 if (!_www_username.empty()) {
01214 make_request_text();
01215
01216
01217 _state = S_begin_body;
01218 return false;
01219 }
01220 }
01221 }
01222
01223 if ((get_status_code() / 100) == 3 && get_status_code() != 305) {
01224
01225 if (!get_redirect().empty() && (_method == HTTPEnum::M_get ||
01226 _method == HTTPEnum::M_head)) {
01227
01228 URLSpec new_url = get_redirect();
01229 if (!_redirect_trail.insert(new_url).second) {
01230 downloader_cat.warning()
01231 << "cycle detected in redirect to " << new_url << "\n";
01232
01233 } else {
01234 if (downloader_cat.is_debug()) {
01235 downloader_cat.debug()
01236 << "following redirect to " << new_url << "\n";
01237 }
01238 if (_request.get_url().has_username()) {
01239 new_url.set_username(_request.get_url().get_username());
01240 }
01241 reset_url(_request.get_url(), new_url);
01242 _request.set_url(new_url);
01243 make_header();
01244 make_request_text();
01245
01246
01247 _state = S_begin_body;
01248 return false;
01249 }
01250 }
01251 }
01252
01253 return false;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 bool HTTPChannel::
01275 run_read_header() {
01276 _state = S_begin_body;
01277 return false;
01278 }
01279
01280
01281
01282
01283
01284
01285
01286 bool HTTPChannel::
01287 run_begin_body() {
01288 if (will_close_connection()) {
01289
01290
01291 reset_to_new();
01292 return false;
01293 }
01294
01295 if (_server_response_has_no_body) {
01296
01297 _state = S_read_trailer;
01298
01299 } else if (_file_size > 8192) {
01300
01301
01302
01303
01304 if (downloader_cat.is_debug()) {
01305 downloader_cat.debug()
01306 << "Dropping connection rather than skipping past " << _file_size
01307 << " bytes.\n";
01308 }
01309 reset_to_new();
01310
01311 } else {
01312 nassertr(_body_stream == NULL, false);
01313 _body_stream = read_body();
01314 if (_body_stream == (ISocketStream *)NULL) {
01315 if (downloader_cat.is_debug()) {
01316 downloader_cat.debug()
01317 << "Unable to skip body.\n";
01318 }
01319 reset_to_new();
01320
01321 } else {
01322 _state = S_reading_body;
01323 }
01324 }
01325
01326 return false;
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 bool HTTPChannel::
01342 run_reading_body() {
01343 if (will_close_connection()) {
01344
01345
01346 reset_to_new();
01347 return false;
01348 }
01349
01350
01351 if (_body_stream == NULL) {
01352
01353 reset_to_new();
01354 return false;
01355 }
01356
01357 string line;
01358 getline(*_body_stream, line);
01359 while (!_body_stream->fail() && !_body_stream->eof()) {
01360 if (downloader_cat.is_spam()) {
01361 downloader_cat.spam() << "skip: " << line << "\n";
01362 }
01363 getline(*_body_stream, line);
01364 }
01365
01366 if (!_body_stream->is_closed()) {
01367
01368 return true;
01369 }
01370
01371 delete _body_stream;
01372 _body_stream = NULL;
01373
01374
01375 nassertr(_state != S_reading_body, false);
01376 return false;
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 bool HTTPChannel::
01394 run_read_body() {
01395 if (will_close_connection()) {
01396
01397
01398 reset_to_new();
01399 return false;
01400 }
01401
01402
01403 string line;
01404 if (!http_getline(line)) {
01405 return true;
01406 }
01407 while (!line.empty()) {
01408 if (!http_getline(line)) {
01409 return true;
01410 }
01411 }
01412
01413 _state = S_read_trailer;
01414 return false;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424 bool HTTPChannel::
01425 run_read_trailer() {
01426 if (will_close_connection()) {
01427
01428
01429 reset_to_new();
01430 return false;
01431 }
01432
01433 if (!_proxy.empty() && !_proxy_tunnel) {
01434 _state = S_proxy_ready;
01435 } else {
01436 _state = S_ready;
01437 }
01438 return false;
01439 }
01440
01441
01442
01443
01444
01445
01446
01447 bool HTTPChannel::
01448 run_download_to_file() {
01449 nassertr(_body_stream != (ISocketStream *)NULL, false);
01450
01451 bool do_throttle = _nonblocking && _download_throttle;
01452 int count = 0;
01453
01454 int ch = _body_stream->get();
01455 nassertr(_body_stream != (ISocketStream *)NULL, false);
01456 while (!_body_stream->eof() && !_body_stream->fail()) {
01457 _download_to_file.put(ch);
01458 _bytes_downloaded++;
01459 if (do_throttle && (++count >= _bytes_per_update)) {
01460
01461 return true;
01462 }
01463
01464 ch = _body_stream->get();
01465 nassertr(_body_stream != (ISocketStream *)NULL, false);
01466 }
01467
01468 if (_download_to_file.fail()) {
01469 downloader_cat.warning()
01470 << "Error writing to " << _download_to_filename << "\n";
01471 _state = S_failure;
01472 _download_to_file.close();
01473 return false;
01474 }
01475
01476 if (_body_stream->is_closed()) {
01477
01478 _download_to_file.close();
01479 return false;
01480 } else {
01481
01482 return true;
01483 }
01484 }
01485
01486
01487
01488
01489
01490
01491
01492 bool HTTPChannel::
01493 run_download_to_ram() {
01494 nassertr(_body_stream != (ISocketStream *)NULL, false);
01495 nassertr(_download_to_ramfile != (Ramfile *)NULL, false);
01496
01497 bool do_throttle = _nonblocking && _download_throttle;
01498 int count = 0;
01499
01500 int ch = _body_stream->get();
01501 nassertr(_body_stream != (ISocketStream *)NULL, false);
01502 while (!_body_stream->eof() && !_body_stream->fail()) {
01503 _download_to_ramfile->_data += (char)ch;
01504 _bytes_downloaded++;
01505 if (do_throttle && (++count >= _bytes_per_update)) {
01506
01507 return true;
01508 }
01509
01510 ch = _body_stream->get();
01511 nassertr(_body_stream != (ISocketStream *)NULL, false);
01512 }
01513
01514 if (_body_stream->is_closed()) {
01515
01516 return false;
01517 } else {
01518
01519 return true;
01520 }
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531 void HTTPChannel::
01532 begin_request(HTTPEnum::Method method, const DocumentSpec &url,
01533 const string &body, bool nonblocking,
01534 size_t first_byte, size_t last_byte) {
01535 reset_for_new_request();
01536
01537
01538
01539 if (_proxy != _client->get_proxy()) {
01540 _proxy = _client->get_proxy();
01541 reset_to_new();
01542 }
01543
01544 if (_nonblocking != nonblocking) {
01545 _nonblocking = nonblocking;
01546 reset_to_new();
01547 }
01548
01549 reset_url(_request.get_url(), url.get_url());
01550 _request = url;
01551 _document_spec = DocumentSpec();
01552 _method = method;
01553 _body = body;
01554
01555
01556
01557 _want_ssl = (_request.get_url().get_scheme() == "https");
01558
01559
01560
01561
01562 _proxy_serves_document = (!_proxy.empty() && !_want_ssl);
01563
01564 _first_byte = first_byte;
01565 _last_byte = last_byte;
01566 _connect_count = 0;
01567
01568 make_header();
01569 make_request_text();
01570
01571 if (!_proxy.empty() && (_want_ssl || _method == HTTPEnum::M_connect)) {
01572
01573
01574
01575 ostringstream request;
01576 request
01577 << "CONNECT " << _request.get_url().get_server_and_port()
01578 << " " << _client->get_http_version_string() << "\r\n";
01579 if (_client->get_http_version() >= HTTPEnum::HV_11) {
01580 request
01581 << "Host: " << _request.get_url().get_server() << "\r\n";
01582 }
01583 _proxy_header = request.str();
01584 make_proxy_request_text();
01585
01586 } else {
01587 _proxy_header = string();
01588 _proxy_request_text = string();
01589 }
01590
01591
01592 if (_state == S_failure || (_state < S_read_header && _state != S_ready)) {
01593 reset_to_new();
01594
01595 } else if (_state == S_read_header) {
01596
01597
01598 _state = S_begin_body;
01599 }
01600
01601 _done_state = (_method == HTTPEnum::M_connect) ? S_ready : S_read_header;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610 void HTTPChannel::
01611 reset_for_new_request() {
01612 reset_download_to();
01613 _last_status_code = 0;
01614 _response_type = RT_none;
01615 _redirect_trail.clear();
01616 _bytes_downloaded = 0;
01617 _bytes_requested = 0;
01618 }
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 void HTTPChannel::
01633 finished_body(bool has_trailer) {
01634 if (will_close_connection() && _download_dest == DD_none) {
01635 reset_to_new();
01636
01637 } else {
01638 if (has_trailer) {
01639 _state = HTTPChannel::S_read_body;
01640 } else {
01641 _state = HTTPChannel::S_read_trailer;
01642 }
01643 }
01644 }
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 bool HTTPChannel::
01656 reset_download_position() {
01657 if (_subdocument_resumes) {
01658 if (_download_dest == DD_file) {
01659
01660
01661
01662
01663 _download_to_file.seekp(0, ios::end);
01664 if (_first_byte > (size_t)_download_to_file.tellp()) {
01665 downloader_cat.info()
01666 << "Invalid starting position of byte " << _first_byte << " within "
01667 << _download_to_filename << " (which has "
01668 << _download_to_file.tellp() << " bytes)\n";
01669 _download_to_file.close();
01670 return false;
01671 }
01672
01673 _download_to_file.seekp(_first_byte);
01674
01675 } else if (_download_dest == DD_ram) {
01676 if (_first_byte > _download_to_ramfile->_data.length()) {
01677 downloader_cat.info()
01678 << "Invalid starting position of byte " << _first_byte
01679 << " within Ramfile (which has "
01680 << _download_to_ramfile->_data.length() << " bytes)\n";
01681 return false;
01682 }
01683
01684 if (_first_byte == 0) {
01685 _download_to_ramfile->_data = string();
01686 } else {
01687 _download_to_ramfile->_data =
01688 _download_to_ramfile->_data.substr(0, _first_byte);
01689 }
01690 }
01691
01692 } else {
01693
01694
01695
01696 if (_download_dest == DD_file) {
01697 _download_to_file.seekp(0);
01698 } else if (_download_dest == DD_ram) {
01699 _download_to_ramfile->_data = string();
01700 }
01701 }
01702
01703 return true;
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 bool HTTPChannel::
01716 http_getline(string &str) {
01717 nassertr(!_source.is_null(), false);
01718 int ch = (*_source)->get();
01719 while (!(*_source)->eof() && !(*_source)->fail()) {
01720 switch (ch) {
01721 case '\n':
01722
01723 str = _working_getline;
01724 _working_getline = string();
01725 {
01726
01727
01728 size_t p = str.length();
01729 while (p > 0 && isspace(str[p - 1])) {
01730 --p;
01731 }
01732 str = str.substr(0, p);
01733 }
01734 if (downloader_cat.is_spam()) {
01735 downloader_cat.spam() << "recv: " << str << "\n";
01736 }
01737 return true;
01738
01739 case '\r':
01740
01741 break;
01742
01743 default:
01744 _working_getline += (char)ch;
01745 }
01746 ch = (*_source)->get();
01747 }
01748
01749 check_socket();
01750 return false;
01751 }
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762 bool HTTPChannel::
01763 http_send(const string &str) {
01764 nassertr(str.length() > _sent_so_far, true);
01765
01766
01767
01768
01769 size_t bytes_to_send = str.length() - _sent_so_far;
01770 int write_count =
01771 BIO_write(*_bio, str.data() + _sent_so_far, bytes_to_send);
01772
01773 if (write_count <= 0) {
01774 if (BIO_should_retry(*_bio)) {
01775
01776 return false;
01777 }
01778
01779 if (downloader_cat.is_debug()) {
01780 downloader_cat.debug()
01781 << "Lost connection to server unexpectedly during write.\n";
01782 }
01783 reset_to_new();
01784 return false;
01785 }
01786
01787 #ifndef NDEBUG
01788 if (downloader_cat.is_spam()) {
01789 show_send(str.substr(0, write_count));
01790 }
01791 #endif
01792
01793 if (write_count < (int)bytes_to_send) {
01794 _sent_so_far += write_count;
01795 return false;
01796 }
01797
01798
01799 _sent_so_far = 0;
01800 return true;
01801 }
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 bool HTTPChannel::
01812 parse_http_response(const string &line) {
01813
01814
01815 if (line.length() < 5 || line.substr(0, 5) != string("HTTP/")) {
01816
01817 _status_code = 0;
01818 _status_string = "Not an HTTP response";
01819 if (_response_type == RT_non_http) {
01820
01821 _state = S_failure;
01822
01823 } else {
01824
01825
01826 reset_to_new();
01827 _response_type = RT_non_http;
01828 }
01829 return false;
01830 }
01831
01832
01833 size_t p = 5;
01834 while (p < line.length() && !isspace(line[p])) {
01835 p++;
01836 }
01837 _http_version_string = line.substr(0, p);
01838 _http_version = HTTPClient::parse_http_version_string(_http_version_string);
01839
01840 while (p < line.length() && isspace(line[p])) {
01841 p++;
01842 }
01843 size_t q = p;
01844 while (q < line.length() && !isspace(line[q])) {
01845 q++;
01846 }
01847 string status_code = line.substr(p, q - p);
01848 _status_code = atoi(status_code.c_str());
01849
01850 while (q < line.length() && isspace(line[q])) {
01851 q++;
01852 }
01853 _status_string = line.substr(q, line.length() - q);
01854
01855 return true;
01856 }
01857
01858
01859
01860
01861
01862
01863
01864
01865 bool HTTPChannel::
01866 parse_http_header() {
01867 string line;
01868 if (!http_getline(line)) {
01869 return true;
01870 }
01871
01872 while (!line.empty()) {
01873 if (isspace(line[0])) {
01874
01875
01876 size_t p = 0;
01877 while (p < line.length() && isspace(line[p])) {
01878 p++;
01879 }
01880 _current_field_value += line.substr(p - 1);
01881
01882 } else {
01883
01884
01885 if (!_current_field_name.empty()) {
01886 store_header_field(_current_field_name, _current_field_value);
01887 _current_field_value = string();
01888 }
01889
01890 size_t colon = line.find(':');
01891 if (colon != string::npos) {
01892 _current_field_name = downcase(line.substr(0, colon));
01893 size_t p = colon + 1;
01894 while (p < line.length() && isspace(line[p])) {
01895 p++;
01896 }
01897 _current_field_value = line.substr(p);
01898 }
01899 }
01900
01901 if (!http_getline(line)) {
01902 return true;
01903 }
01904 }
01905
01906
01907 if (!_current_field_name.empty()) {
01908 store_header_field(_current_field_name, _current_field_value);
01909 _current_field_value = string();
01910 }
01911
01912 return false;
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922 bool HTTPChannel::
01923 parse_content_range(const string &content_range) {
01924
01925 size_t p = 0;
01926 while (p < content_range.length() && !isspace(content_range[p])) {
01927 p++;
01928 }
01929
01930 string units = content_range.substr(0, p);
01931 while (p < content_range.length() && isspace(content_range[p])) {
01932 p++;
01933 }
01934
01935 if (units == "bytes") {
01936 const char *c_str = content_range.c_str();
01937 char *endptr;
01938 if (p < content_range.length() && isdigit(content_range[p])) {
01939 long first_byte = strtol(c_str + p, &endptr, 10);
01940 p = endptr - c_str;
01941 if (p < content_range.length() && content_range[p] == '-') {
01942 p++;
01943 if (p < content_range.length() && isdigit(content_range[p])) {
01944 long last_byte = strtol(c_str + p, &endptr, 10);
01945 p = endptr - c_str;
01946
01947 if (last_byte >= first_byte) {
01948 _first_byte = first_byte;
01949 _last_byte = last_byte;
01950 return true;
01951 }
01952 }
01953 }
01954 }
01955 }
01956
01957
01958 return false;
01959 }
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969 void HTTPChannel::
01970 check_socket() {
01971 nassertv(!_source.is_null());
01972 if ((*_source)->is_closed()) {
01973 if (downloader_cat.is_debug()) {
01974 downloader_cat.debug()
01975 << "Lost connection to server unexpectedly during read.\n";
01976 }
01977 reset_to_new();
01978 }
01979 }
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989 bool HTTPChannel::
01990 verify_server(X509_NAME *subject) const {
01991 if (_client->_expected_servers.empty()) {
01992 if (downloader_cat.is_debug()) {
01993 downloader_cat.debug()
01994 << "No expected servers on list; allowing any https connection.\n";
01995 }
01996 return true;
01997 }
01998
01999 if (downloader_cat.is_debug()) {
02000 downloader_cat.debug() << "checking server: " << flush;
02001 X509_NAME_print_ex_fp(stderr, subject, 0, 0);
02002 fflush(stderr);
02003 downloader_cat.debug(false) << "\n";
02004 }
02005
02006 HTTPClient::ExpectedServers::const_iterator ei;
02007 for (ei = _client->_expected_servers.begin();
02008 ei != _client->_expected_servers.end();
02009 ++ei) {
02010 X509_NAME *expected_name = (*ei);
02011 if (x509_name_subset(expected_name, subject)) {
02012 if (downloader_cat.is_debug()) {
02013 downloader_cat.debug()
02014 << "Match found!\n";
02015 }
02016 return true;
02017 }
02018 }
02019
02020
02021 if (downloader_cat.is_debug()) {
02022 downloader_cat.debug()
02023 << "No match found against any of the following expected servers:\n";
02024
02025 for (ei = _client->_expected_servers.begin();
02026 ei != _client->_expected_servers.end();
02027 ++ei) {
02028 X509_NAME *expected_name = (*ei);
02029 X509_NAME_print_ex_fp(stderr, expected_name, 0, 0);
02030 fputs("\n", stderr);
02031 }
02032 fflush(stderr);
02033 }
02034
02035 return false;
02036 }
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 string HTTPChannel::
02220 get_x509_name_component(X509_NAME *name, int nid) {
02221 ASN1_OBJECT *obj = OBJ_nid2obj(nid);
02222
02223 if (obj == NULL) {
02224
02225 return string();
02226 }
02227
02228 int i = X509_NAME_get_index_by_OBJ(name, obj, -1);
02229 if (i < 0) {
02230 return string();
02231 }
02232
02233 ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
02234 return string((char *)data->data, data->length);
02235 }
02236
02237
02238
02239
02240
02241
02242
02243
02244 bool HTTPChannel::
02245 x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
02246 int count_a = X509_NAME_entry_count(name_a);
02247 for (int ai = 0; ai < count_a; ai++) {
02248 X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai);
02249
02250 int bi = X509_NAME_get_index_by_OBJ(name_b, na->object, -1);
02251 if (bi < 0) {
02252
02253 return false;
02254 }
02255
02256 X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi);
02257 if (na->value->length != nb->value->length ||
02258 memcmp(na->value->data, nb->value->data, na->value->length) != 0) {
02259
02260 return false;
02261 }
02262 }
02263 return true;
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
02273 void HTTPChannel::
02274 make_header() {
02275 _proxy_auth = _client->select_auth(_proxy, true, _proxy_realm);
02276 _proxy_username = string();
02277 if (_proxy_auth != (HTTPAuthorization *)NULL) {
02278 _proxy_realm = _proxy_auth->get_realm();
02279 _proxy_username = _client->select_username(_proxy, true, _proxy_realm);
02280 }
02281
02282 if (_method == HTTPEnum::M_connect) {
02283
02284
02285
02286
02287 _header = string();
02288 return;
02289 }
02290
02291 _www_auth = _client->select_auth(_request.get_url(), false, _www_realm);
02292 _www_username = string();
02293 if (_www_auth != (HTTPAuthorization *)NULL) {
02294 _www_realm = _www_auth->get_realm();
02295 _www_username = _client->select_username(_request.get_url(), false, _www_realm);
02296 }
02297
02298 string request_path;
02299 if (_proxy_serves_document) {
02300
02301
02302 URLSpec url_no_username = _request.get_url();
02303 url_no_username.set_username(string());
02304 request_path = url_no_username.get_url();
02305
02306 } else {
02307
02308
02309 request_path = _request.get_url().get_path();
02310 }
02311
02312
02313
02314
02315 if (request_path.empty()) {
02316 request_path = "*";
02317 }
02318
02319 ostringstream stream;
02320
02321 stream
02322 << _method << " " << request_path << " "
02323 << _client->get_http_version_string() << "\r\n";
02324
02325 if (_client->get_http_version() >= HTTPEnum::HV_11) {
02326 stream
02327 << "Host: " << _request.get_url().get_server() << "\r\n";
02328 if (!get_persistent_connection()) {
02329 stream
02330 << "Connection: close\r\n";
02331 }
02332 }
02333
02334 if (_last_byte != 0) {
02335 stream
02336 << "Range: bytes=" << _first_byte << "-" << _last_byte << "\r\n";
02337
02338 } else if (_first_byte != 0) {
02339 stream
02340 << "Range: bytes=" << _first_byte << "-\r\n";
02341 }
02342
02343 switch (_request.get_request_mode()) {
02344 case DocumentSpec::RM_any:
02345
02346
02347 if (_first_byte != 0) {
02348
02349
02350
02351 if (_request.has_tag()) {
02352 stream
02353 << "If-Range: " << _request.get_tag().get_string() << "\r\n";
02354 } else if (_request.has_date()) {
02355 stream
02356 << "If-Range: " << _request.get_date().get_string() << "\r\n";
02357 }
02358 }
02359 break;
02360
02361 case DocumentSpec::RM_equal:
02362
02363
02364 if (_request.has_tag()) {
02365 stream
02366 << "If-Match: " << _request.get_tag().get_string() << "\r\n";
02367 }
02368 if (_request.has_date()) {
02369 stream
02370 << "If-Unmodified-Since: " << _request.get_date().get_string()
02371 << "\r\n";
02372 }
02373 break;
02374
02375 case DocumentSpec::RM_newer:
02376
02377 if (_request.has_tag()) {
02378 stream
02379 << "If-None-Match: " << _request.get_tag().get_string() << "\r\n";
02380 }
02381 if (_request.has_date()) {
02382 stream
02383 << "If-Modified-Since: " << _request.get_date().get_string()
02384 << "\r\n";
02385 }
02386 break;
02387
02388 case DocumentSpec::RM_equal_or_newer:
02389
02390 if (_request.has_date()) {
02391
02392
02393
02394 stream
02395 << "If-Modified-Since: " << (_request.get_date() - 1).get_string()
02396 << "\r\n";
02397 }
02398 break;
02399 }
02400
02401 switch (_request.get_cache_control()) {
02402 case DocumentSpec::CC_allow_cache:
02403
02404 break;
02405
02406 case DocumentSpec::CC_revalidate:
02407
02408 stream
02409 << "Cache-Control: max-age=0\r\n";
02410 break;
02411
02412 case DocumentSpec::CC_no_cache:
02413
02414 stream
02415 << "Cache-Control: no-cache\r\n"
02416 << "Pragma: no-cache\r\n";
02417 break;
02418 }
02419
02420 if (!_body.empty()) {
02421 stream
02422 << "Content-Type: application/x-www-form-urlencoded\r\n"
02423 << "Content-Length: " << _body.length() << "\r\n";
02424 }
02425
02426 _header = stream.str();
02427 }
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438 void HTTPChannel::
02439 make_proxy_request_text() {
02440 _proxy_request_text = _proxy_header;
02441
02442 if (_proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
02443 _proxy_request_text += "Proxy-Authorization: ";
02444 _proxy_request_text +=
02445 _proxy_auth->generate(HTTPEnum::M_connect, _request.get_url().get_server_and_port(),
02446 _proxy_username, _body);
02447 _proxy_request_text += "\r\n";
02448 }
02449
02450 _proxy_request_text += "\r\n";
02451 }
02452
02453
02454
02455
02456
02457
02458
02459
02460 void HTTPChannel::
02461 make_request_text() {
02462 _request_text = _header;
02463
02464 if (!_proxy.empty() && !_proxy_tunnel &&
02465 _proxy_auth != (HTTPAuthorization *)NULL && !_proxy_username.empty()) {
02466 _request_text += "Proxy-Authorization: ";
02467 _request_text +=
02468 _proxy_auth->generate(_method, _request.get_url().get_url(), _proxy_username, _body);
02469 _request_text += "\r\n";
02470 }
02471
02472 if (_www_auth != (HTTPAuthorization *)NULL && !_www_username.empty()) {
02473 string authorization =
02474 _request_text += "Authorization: ";
02475 _request_text +=
02476 _www_auth->generate(_method, _request.get_url().get_path(), _www_username, _body);
02477 _request_text += "\r\n";
02478 }
02479
02480 _request_text += _send_extra_headers;
02481 _request_text += "\r\n";
02482 _request_text += _body;
02483 }
02484
02485
02486
02487
02488
02489
02490
02491
02492 void HTTPChannel::
02493 reset_url(const URLSpec &old_url, const URLSpec &new_url) {
02494
02495
02496
02497
02498
02499 if (new_url.get_scheme() != old_url.get_scheme() ||
02500 (_proxy.empty() && (new_url.get_server() != old_url.get_server() ||
02501 new_url.get_port() != old_url.get_port()))) {
02502 reset_to_new();
02503 }
02504 }
02505
02506
02507
02508
02509
02510
02511
02512
02513 void HTTPChannel::
02514 store_header_field(const string &field_name, const string &field_value) {
02515 pair<Headers::iterator, bool> insert_result =
02516 _headers.insert(Headers::value_type(field_name, field_value));
02517
02518 if (!insert_result.second) {
02519
02520
02521 Headers::iterator hi = insert_result.first;
02522 (*hi).second += ", ";
02523 (*hi).second += field_value;
02524 }
02525 }
02526
02527 #ifndef NDEBUG
02528
02529
02530
02531
02532
02533
02534 void HTTPChannel::
02535 show_send(const string &message) {
02536 size_t start = 0;
02537 size_t newline = message.find('\n', start);
02538 while (newline != string::npos) {
02539
02540 downloader_cat.spam()
02541 << "send: " << message.substr(start, newline - start - 1) << "\n";
02542 start = newline + 1;
02543 newline = message.find('\n', start);
02544 }
02545
02546 if (start < message.length()) {
02547 downloader_cat.spam()
02548 << "send: " << message.substr(start) << " (no newline)\n";
02549 }
02550 }
02551 #endif // NDEBUG
02552
02553
02554
02555
02556
02557
02558
02559
02560 void HTTPChannel::
02561 reset_download_to() {
02562 _started_download = false;
02563 _download_to_file.close();
02564 _download_to_ramfile = (Ramfile *)NULL;
02565 _download_dest = DD_none;
02566 }
02567
02568
02569
02570
02571
02572
02573 void HTTPChannel::
02574 reset_to_new() {
02575 close_connection();
02576 _state = S_new;
02577 }
02578
02579
02580
02581
02582
02583
02584
02585 void HTTPChannel::
02586 close_connection() {
02587 if (_body_stream != (ISocketStream *)NULL) {
02588 delete _body_stream;
02589 _body_stream = (ISocketStream *)NULL;
02590 }
02591 _source.clear();
02592 _bio.clear();
02593 _working_getline = string();
02594 _sent_so_far = 0;
02595 _proxy_tunnel = false;
02596 _read_index++;
02597 }
02598
02599 #endif // HAVE_SSL