| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "update_engine/libcurl_http_fetcher.h" | 5 #include "update_engine/libcurl_http_fetcher.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include <base/logging.h> | 10 #include <base/logging.h> |
| 11 | 11 |
| 12 #include "update_engine/chrome_proxy_resolver.h" | 12 #include "update_engine/chrome_proxy_resolver.h" |
| 13 #include "update_engine/dbus_interface.h" | 13 #include "update_engine/dbus_interface.h" |
| 14 #include "update_engine/flimflam_proxy.h" | 14 #include "update_engine/flimflam_proxy.h" |
| 15 #include "update_engine/utils.h" | 15 #include "update_engine/utils.h" |
| 16 | 16 |
| 17 using std::max; | 17 using std::max; |
| 18 using std::make_pair; | 18 using std::make_pair; |
| 19 using std::string; | 19 using std::string; |
| 20 | 20 |
| 21 // This is a concrete implementation of HttpFetcher that uses libcurl to do the | 21 // This is a concrete implementation of HttpFetcher that uses libcurl to do the |
| 22 // http work. | 22 // http work. |
| 23 | 23 |
| 24 namespace chromeos_update_engine { | 24 namespace chromeos_update_engine { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 const int kMaxRetriesCount = 20; | 27 const int kMaxRetriesCount = 20; |
| 28 const int kNoNetworkRetrySeconds = 30; |
| 28 const char kCACertificatesPath[] = "/usr/share/chromeos-ca-certificates"; | 29 const char kCACertificatesPath[] = "/usr/share/chromeos-ca-certificates"; |
| 29 } // namespace {} | 30 } // namespace {} |
| 30 | 31 |
| 31 LibcurlHttpFetcher::~LibcurlHttpFetcher() { | 32 LibcurlHttpFetcher::~LibcurlHttpFetcher() { |
| 32 LOG_IF(ERROR, transfer_in_progress_) | 33 LOG_IF(ERROR, transfer_in_progress_) |
| 33 << "Destroying the fetcher while a transfer is in progress."; | 34 << "Destroying the fetcher while a transfer is in progress."; |
| 34 CleanUp(); | 35 CleanUp(); |
| 35 } | 36 } |
| 36 | 37 |
| 37 // On error, returns false. | 38 // On error, returns false. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 | 146 |
| 146 CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK); | 147 CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK); |
| 147 transfer_in_progress_ = true; | 148 transfer_in_progress_ = true; |
| 148 } | 149 } |
| 149 | 150 |
| 150 // Begins the transfer, which must not have already been started. | 151 // Begins the transfer, which must not have already been started. |
| 151 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { | 152 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { |
| 152 transfer_size_ = -1; | 153 transfer_size_ = -1; |
| 153 resume_offset_ = 0; | 154 resume_offset_ = 0; |
| 154 retry_count_ = 0; | 155 retry_count_ = 0; |
| 156 no_network_retry_count_ = 0; |
| 155 http_response_code_ = 0; | 157 http_response_code_ = 0; |
| 156 ResolveProxiesForUrl(url); | 158 ResolveProxiesForUrl(url); |
| 157 ResumeTransfer(url); | 159 ResumeTransfer(url); |
| 158 CurlPerformOnce(); | 160 CurlPerformOnce(); |
| 159 } | 161 } |
| 160 | 162 |
| 161 void LibcurlHttpFetcher::ForceTransferTermination() { | 163 void LibcurlHttpFetcher::ForceTransferTermination() { |
| 162 CleanUp(); | 164 CleanUp(); |
| 163 if (delegate_) { | 165 if (delegate_) { |
| 164 // Note that after the callback returns this object may be destroyed. | 166 // Note that after the callback returns this object may be destroyed. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 185 retcode = curl_multi_perform(curl_multi_handle_, &running_handles); | 187 retcode = curl_multi_perform(curl_multi_handle_, &running_handles); |
| 186 if (terminate_requested_) { | 188 if (terminate_requested_) { |
| 187 ForceTransferTermination(); | 189 ForceTransferTermination(); |
| 188 return; | 190 return; |
| 189 } | 191 } |
| 190 } | 192 } |
| 191 if (0 == running_handles) { | 193 if (0 == running_handles) { |
| 192 GetHttpResponseCode(); | 194 GetHttpResponseCode(); |
| 193 if (http_response_code_) { | 195 if (http_response_code_) { |
| 194 LOG(INFO) << "HTTP response code: " << http_response_code_; | 196 LOG(INFO) << "HTTP response code: " << http_response_code_; |
| 197 no_network_retry_count_ = 0; |
| 195 } else { | 198 } else { |
| 196 LOG(ERROR) << "Unable to get http response code."; | 199 LOG(ERROR) << "Unable to get http response code."; |
| 197 } | 200 } |
| 198 | 201 |
| 199 // we're done! | 202 // we're done! |
| 200 CleanUp(); | 203 CleanUp(); |
| 201 | 204 |
| 205 // TODO(petkov): This temporary code tries to deal with the case where the |
| 206 // update engine performs an update check while the network is not ready |
| 207 // (e.g., right after resume). Longer term, we should check if the network |
| 208 // is online/offline and return an appropriate error code. |
| 209 if (!sent_byte_ && |
| 210 http_response_code_ == 0 && |
| 211 no_network_retry_count_ < no_network_max_retries_) { |
| 212 no_network_retry_count_++; |
| 213 g_timeout_add_seconds(kNoNetworkRetrySeconds, |
| 214 &LibcurlHttpFetcher::StaticRetryTimeoutCallback, |
| 215 this); |
| 216 LOG(INFO) << "No HTTP response, retry " << no_network_retry_count_; |
| 217 return; |
| 218 } |
| 219 |
| 202 if (!sent_byte_ && | 220 if (!sent_byte_ && |
| 203 (http_response_code_ < 200 || http_response_code_ >= 300)) { | 221 (http_response_code_ < 200 || http_response_code_ >= 300)) { |
| 204 // The transfer completed w/ error and we didn't get any bytes. | 222 // The transfer completed w/ error and we didn't get any bytes. |
| 205 // If we have another proxy to try, try that. | 223 // If we have another proxy to try, try that. |
| 206 | 224 |
| 207 PopProxy(); // Delete the proxy we just gave up on. | 225 PopProxy(); // Delete the proxy we just gave up on. |
| 208 | 226 |
| 209 if (HasProxy()) { | 227 if (HasProxy()) { |
| 210 // We have another proxy. Retry immediately. | 228 // We have another proxy. Retry immediately. |
| 211 g_idle_add(&LibcurlHttpFetcher::StaticRetryTimeoutCallback, this); | 229 g_idle_add(&LibcurlHttpFetcher::StaticRetryTimeoutCallback, this); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 void LibcurlHttpFetcher::GetHttpResponseCode() { | 439 void LibcurlHttpFetcher::GetHttpResponseCode() { |
| 422 long http_response_code = 0; | 440 long http_response_code = 0; |
| 423 if (curl_easy_getinfo(curl_handle_, | 441 if (curl_easy_getinfo(curl_handle_, |
| 424 CURLINFO_RESPONSE_CODE, | 442 CURLINFO_RESPONSE_CODE, |
| 425 &http_response_code) == CURLE_OK) { | 443 &http_response_code) == CURLE_OK) { |
| 426 http_response_code_ = static_cast<int>(http_response_code); | 444 http_response_code_ = static_cast<int>(http_response_code); |
| 427 } | 445 } |
| 428 } | 446 } |
| 429 | 447 |
| 430 } // namespace chromeos_update_engine | 448 } // namespace chromeos_update_engine |
| OLD | NEW |