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 |