| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // Helpers | 30 // Helpers |
| 31 ////////////////////////////////////////////////////////////////////// | 31 ////////////////////////////////////////////////////////////////////// |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 const size_t kCacheHeader = 0; | 35 const size_t kCacheHeader = 0; |
| 36 const size_t kCacheBody = 1; | 36 const size_t kCacheBody = 1; |
| 37 | 37 |
| 38 // Convert decimal string to integer | 38 // Convert decimal string to integer |
| 39 bool HttpStringToUInt(const std::string& str, size_t* val) { | 39 bool HttpStringToUInt(const std::string& str, size_t* val) { |
| 40 ASSERT(NULL != val); | 40 RTC_DCHECK(NULL != val); |
| 41 char* eos = NULL; | 41 char* eos = NULL; |
| 42 *val = strtoul(str.c_str(), &eos, 10); | 42 *val = strtoul(str.c_str(), &eos, 10); |
| 43 return (*eos == '\0'); | 43 return (*eos == '\0'); |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool HttpShouldCache(const HttpTransaction& t) { | 46 bool HttpShouldCache(const HttpTransaction& t) { |
| 47 bool verb_allows_cache = (t.request.verb == HV_GET) | 47 bool verb_allows_cache = (t.request.verb == HV_GET) |
| 48 || (t.request.verb == HV_HEAD); | 48 || (t.request.verb == HV_HEAD); |
| 49 bool is_range_response = t.response.hasHeader(HH_CONTENT_RANGE, NULL); | 49 bool is_range_response = t.response.hasHeader(HH_CONTENT_RANGE, NULL); |
| 50 bool has_expires = t.response.hasHeader(HH_EXPIRES, NULL); | 50 bool has_expires = t.response.hasHeader(HH_EXPIRES, NULL); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 return base_.GetDocumentStream(); | 334 return base_.GetDocumentStream(); |
| 335 } | 335 } |
| 336 | 336 |
| 337 void HttpClient::start() { | 337 void HttpClient::start() { |
| 338 if (base_.mode() != HM_NONE) { | 338 if (base_.mode() != HM_NONE) { |
| 339 // call reset() to abort an in-progress request | 339 // call reset() to abort an in-progress request |
| 340 RTC_NOTREACHED(); | 340 RTC_NOTREACHED(); |
| 341 return; | 341 return; |
| 342 } | 342 } |
| 343 | 343 |
| 344 ASSERT(!IsCacheActive()); | 344 RTC_DCHECK(!IsCacheActive()); |
| 345 | 345 |
| 346 if (request().hasHeader(HH_TRANSFER_ENCODING, NULL)) { | 346 if (request().hasHeader(HH_TRANSFER_ENCODING, NULL)) { |
| 347 // Exact size must be known on the client. Instead of using chunked | 347 // Exact size must be known on the client. Instead of using chunked |
| 348 // encoding, wrap data with auto-caching file or memory stream. | 348 // encoding, wrap data with auto-caching file or memory stream. |
| 349 RTC_NOTREACHED(); | 349 RTC_NOTREACHED(); |
| 350 return; | 350 return; |
| 351 } | 351 } |
| 352 | 352 |
| 353 attempt_ = 0; | 353 attempt_ = 0; |
| 354 | 354 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 } | 396 } |
| 397 | 397 |
| 398 void HttpClient::connect() { | 398 void HttpClient::connect() { |
| 399 int stream_err; | 399 int stream_err; |
| 400 if (server_.IsUnresolvedIP()) { | 400 if (server_.IsUnresolvedIP()) { |
| 401 StartDNSLookup(); | 401 StartDNSLookup(); |
| 402 return; | 402 return; |
| 403 } | 403 } |
| 404 StreamInterface* stream = pool_->RequestConnectedStream(server_, &stream_err); | 404 StreamInterface* stream = pool_->RequestConnectedStream(server_, &stream_err); |
| 405 if (stream == NULL) { | 405 if (stream == NULL) { |
| 406 ASSERT(0 != stream_err); | 406 RTC_DCHECK(0 != stream_err); |
| 407 LOG(LS_ERROR) << "RequestConnectedStream error: " << stream_err; | 407 LOG(LS_ERROR) << "RequestConnectedStream error: " << stream_err; |
| 408 onHttpComplete(HM_CONNECT, HE_CONNECT_FAILED); | 408 onHttpComplete(HM_CONNECT, HE_CONNECT_FAILED); |
| 409 } else { | 409 } else { |
| 410 base_.attach(stream); | 410 base_.attach(stream); |
| 411 if (stream->GetState() == SS_OPEN) { | 411 if (stream->GetState() == SS_OPEN) { |
| 412 base_.send(&transaction_->request); | 412 base_.send(&transaction_->request); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 } | 415 } |
| 416 | 416 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 446 || !response().hasHeader(HH_LOCATION, location) | 446 || !response().hasHeader(HH_LOCATION, location) |
| 447 || (redirects_ >= kMaxRedirects)) | 447 || (redirects_ >= kMaxRedirects)) |
| 448 return false; | 448 return false; |
| 449 return (REDIRECT_ALWAYS == redirect_action_) | 449 return (REDIRECT_ALWAYS == redirect_action_) |
| 450 || (HC_SEE_OTHER == response().scode) | 450 || (HC_SEE_OTHER == response().scode) |
| 451 || (HV_HEAD == request().verb) | 451 || (HV_HEAD == request().verb) |
| 452 || (HV_GET == request().verb); | 452 || (HV_GET == request().verb); |
| 453 } | 453 } |
| 454 | 454 |
| 455 bool HttpClient::BeginCacheFile() { | 455 bool HttpClient::BeginCacheFile() { |
| 456 ASSERT(NULL != cache_); | 456 RTC_DCHECK(NULL != cache_); |
| 457 ASSERT(CS_READY == cache_state_); | 457 RTC_DCHECK(CS_READY == cache_state_); |
| 458 | 458 |
| 459 std::string id = GetCacheID(request()); | 459 std::string id = GetCacheID(request()); |
| 460 CacheLock lock(cache_, id, true); | 460 CacheLock lock(cache_, id, true); |
| 461 if (!lock.IsLocked()) { | 461 if (!lock.IsLocked()) { |
| 462 LOG_F(LS_WARNING) << "Couldn't lock cache"; | 462 LOG_F(LS_WARNING) << "Couldn't lock cache"; |
| 463 return false; | 463 return false; |
| 464 } | 464 } |
| 465 | 465 |
| 466 if (HE_NONE != WriteCacheHeaders(id)) { | 466 if (HE_NONE != WriteCacheHeaders(id)) { |
| 467 return false; | 467 return false; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 // Delete the tap and cache stream (which completes cache unlock) | 513 // Delete the tap and cache stream (which completes cache unlock) |
| 514 delete tap; | 514 delete tap; |
| 515 | 515 |
| 516 if (SR_SUCCESS != result) { | 516 if (SR_SUCCESS != result) { |
| 517 LOG(LS_ERROR) << "Cache file error: " << error; | 517 LOG(LS_ERROR) << "Cache file error: " << error; |
| 518 cache_->DeleteResource(GetCacheID(request())); | 518 cache_->DeleteResource(GetCacheID(request())); |
| 519 } | 519 } |
| 520 } | 520 } |
| 521 | 521 |
| 522 bool HttpClient::CheckCache() { | 522 bool HttpClient::CheckCache() { |
| 523 ASSERT(NULL != cache_); | 523 RTC_DCHECK(NULL != cache_); |
| 524 ASSERT(CS_READY == cache_state_); | 524 RTC_DCHECK(CS_READY == cache_state_); |
| 525 | 525 |
| 526 std::string id = GetCacheID(request()); | 526 std::string id = GetCacheID(request()); |
| 527 if (!cache_->HasResource(id)) { | 527 if (!cache_->HasResource(id)) { |
| 528 // No cache file available | 528 // No cache file available |
| 529 return false; | 529 return false; |
| 530 } | 530 } |
| 531 | 531 |
| 532 HttpError error = ReadCacheHeaders(id, true); | 532 HttpError error = ReadCacheHeaders(id, true); |
| 533 | 533 |
| 534 if (HE_NONE == error) { | 534 if (HE_NONE == error) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 response().document.get()); | 608 response().document.get()); |
| 609 if (SR_SUCCESS != result) { | 609 if (SR_SUCCESS != result) { |
| 610 error = HE_STREAM; | 610 error = HE_STREAM; |
| 611 } | 611 } |
| 612 } | 612 } |
| 613 | 613 |
| 614 return error; | 614 return error; |
| 615 } | 615 } |
| 616 | 616 |
| 617 bool HttpClient::PrepareValidate() { | 617 bool HttpClient::PrepareValidate() { |
| 618 ASSERT(CS_READY == cache_state_); | 618 RTC_DCHECK(CS_READY == cache_state_); |
| 619 // At this point, request() contains the pending request, and response() | 619 // At this point, request() contains the pending request, and response() |
| 620 // contains the cached response headers. Reformat the request to validate | 620 // contains the cached response headers. Reformat the request to validate |
| 621 // the cached content. | 621 // the cached content. |
| 622 HttpValidatorStrength vs_required = HttpRequestValidatorLevel(request()); | 622 HttpValidatorStrength vs_required = HttpRequestValidatorLevel(request()); |
| 623 HttpValidatorStrength vs_available = HttpResponseValidatorLevel(response()); | 623 HttpValidatorStrength vs_available = HttpResponseValidatorLevel(response()); |
| 624 if (vs_available < vs_required) { | 624 if (vs_available < vs_required) { |
| 625 return false; | 625 return false; |
| 626 } | 626 } |
| 627 std::string value; | 627 std::string value; |
| 628 if (response().hasHeader(HH_ETAG, &value)) { | 628 if (response().hasHeader(HH_ETAG, &value)) { |
| 629 request().addHeader(HH_IF_NONE_MATCH, value); | 629 request().addHeader(HH_IF_NONE_MATCH, value); |
| 630 } | 630 } |
| 631 if (response().hasHeader(HH_LAST_MODIFIED, &value)) { | 631 if (response().hasHeader(HH_LAST_MODIFIED, &value)) { |
| 632 request().addHeader(HH_IF_MODIFIED_SINCE, value); | 632 request().addHeader(HH_IF_MODIFIED_SINCE, value); |
| 633 } | 633 } |
| 634 response().clear(false); | 634 response().clear(false); |
| 635 cache_state_ = CS_VALIDATING; | 635 cache_state_ = CS_VALIDATING; |
| 636 return true; | 636 return true; |
| 637 } | 637 } |
| 638 | 638 |
| 639 HttpError HttpClient::CompleteValidate() { | 639 HttpError HttpClient::CompleteValidate() { |
| 640 ASSERT(CS_VALIDATING == cache_state_); | 640 RTC_DCHECK(CS_VALIDATING == cache_state_); |
| 641 | 641 |
| 642 std::string id = GetCacheID(request()); | 642 std::string id = GetCacheID(request()); |
| 643 | 643 |
| 644 // Merge cached headers with new headers | 644 // Merge cached headers with new headers |
| 645 HttpError error = ReadCacheHeaders(id, false); | 645 HttpError error = ReadCacheHeaders(id, false); |
| 646 if (HE_NONE != error) { | 646 if (HE_NONE != error) { |
| 647 // Rewrite merged headers to cache | 647 // Rewrite merged headers to cache |
| 648 CacheLock lock(cache_, id); | 648 CacheLock lock(cache_, id); |
| 649 error = WriteCacheHeaders(id); | 649 error = WriteCacheHeaders(id); |
| 650 } | 650 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 679 if (CS_VALIDATING == cache_state_) { | 679 if (CS_VALIDATING == cache_state_) { |
| 680 if (HC_NOT_MODIFIED == response().scode) { | 680 if (HC_NOT_MODIFIED == response().scode) { |
| 681 return CompleteValidate(); | 681 return CompleteValidate(); |
| 682 } | 682 } |
| 683 // Should we remove conditional headers from request? | 683 // Should we remove conditional headers from request? |
| 684 cache_state_ = CS_READY; | 684 cache_state_ = CS_READY; |
| 685 cache_->DeleteResource(GetCacheID(request())); | 685 cache_->DeleteResource(GetCacheID(request())); |
| 686 // Continue processing response as normal | 686 // Continue processing response as normal |
| 687 } | 687 } |
| 688 | 688 |
| 689 ASSERT(!IsCacheActive()); | 689 RTC_DCHECK(!IsCacheActive()); |
| 690 if ((request().verb == HV_HEAD) || !HttpCodeHasBody(response().scode)) { | 690 if ((request().verb == HV_HEAD) || !HttpCodeHasBody(response().scode)) { |
| 691 // HEAD requests and certain response codes contain no body | 691 // HEAD requests and certain response codes contain no body |
| 692 data_size = 0; | 692 data_size = 0; |
| 693 } | 693 } |
| 694 if (ShouldRedirect(NULL) | 694 if (ShouldRedirect(NULL) |
| 695 || ((HC_PROXY_AUTHENTICATION_REQUIRED == response().scode) | 695 || ((HC_PROXY_AUTHENTICATION_REQUIRED == response().scode) |
| 696 && (PROXY_HTTPS == proxy_.type))) { | 696 && (PROXY_HTTPS == proxy_.type))) { |
| 697 // We're going to issue another request, so ignore the incoming data. | 697 // We're going to issue another request, so ignore the incoming data. |
| 698 base_.set_ignore_data(true); | 698 base_.set_ignore_data(true); |
| 699 } | 699 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 Url<char> purl(location); | 750 Url<char> purl(location); |
| 751 set_server(SocketAddress(purl.host(), purl.port())); | 751 set_server(SocketAddress(purl.host(), purl.port())); |
| 752 request().path = purl.full_path(); | 752 request().path = purl.full_path(); |
| 753 if (response().scode == HC_SEE_OTHER) { | 753 if (response().scode == HC_SEE_OTHER) { |
| 754 request().verb = HV_GET; | 754 request().verb = HV_GET; |
| 755 request().clearHeader(HH_CONTENT_TYPE); | 755 request().clearHeader(HH_CONTENT_TYPE); |
| 756 request().clearHeader(HH_CONTENT_LENGTH); | 756 request().clearHeader(HH_CONTENT_LENGTH); |
| 757 request().document.reset(); | 757 request().document.reset(); |
| 758 } else if (request().document && !request().document->Rewind()) { | 758 } else if (request().document && !request().document->Rewind()) { |
| 759 // Unable to replay the request document. | 759 // Unable to replay the request document. |
| 760 ASSERT(REDIRECT_ALWAYS == redirect_action_); | 760 RTC_DCHECK(REDIRECT_ALWAYS == redirect_action_); |
| 761 err = HE_STREAM; | 761 err = HE_STREAM; |
| 762 } | 762 } |
| 763 if (err == HE_NONE) { | 763 if (err == HE_NONE) { |
| 764 ++redirects_; | 764 ++redirects_; |
| 765 context_.reset(); | 765 context_.reset(); |
| 766 response().clear(false); | 766 response().clear(false); |
| 767 release(); | 767 release(); |
| 768 start(); | 768 start(); |
| 769 return; | 769 return; |
| 770 } | 770 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 const std::string& agent, | 827 const std::string& agent, |
| 828 HttpTransaction* transaction) | 828 HttpTransaction* transaction) |
| 829 : ReuseSocketPool(factory ? factory : Thread::Current()->socketserver()), | 829 : ReuseSocketPool(factory ? factory : Thread::Current()->socketserver()), |
| 830 HttpClient(agent, NULL, transaction) { | 830 HttpClient(agent, NULL, transaction) { |
| 831 set_pool(this); | 831 set_pool(this); |
| 832 } | 832 } |
| 833 | 833 |
| 834 ////////////////////////////////////////////////////////////////////// | 834 ////////////////////////////////////////////////////////////////////// |
| 835 | 835 |
| 836 } // namespace rtc | 836 } // namespace rtc |
| OLD | NEW |