| 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/dbus_interface.h" | 13 #include "update_engine/dbus_interface.h" |
| 13 #include "update_engine/flimflam_proxy.h" | 14 #include "update_engine/flimflam_proxy.h" |
| 14 #include "update_engine/utils.h" | 15 #include "update_engine/utils.h" |
| 15 | 16 |
| 16 using std::max; | 17 using std::max; |
| 17 using std::make_pair; | 18 using std::make_pair; |
| 18 using std::string; | 19 using std::string; |
| 19 | 20 |
| 20 // 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 |
| 21 // http work. | 22 // http work. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 52 void LibcurlHttpFetcher::ResumeTransfer(const std::string& url) { | 53 void LibcurlHttpFetcher::ResumeTransfer(const std::string& url) { |
| 53 LOG(INFO) << "Starting/Resuming transfer"; | 54 LOG(INFO) << "Starting/Resuming transfer"; |
| 54 CHECK(!transfer_in_progress_); | 55 CHECK(!transfer_in_progress_); |
| 55 url_ = url; | 56 url_ = url; |
| 56 curl_multi_handle_ = curl_multi_init(); | 57 curl_multi_handle_ = curl_multi_init(); |
| 57 CHECK(curl_multi_handle_); | 58 CHECK(curl_multi_handle_); |
| 58 | 59 |
| 59 curl_handle_ = curl_easy_init(); | 60 curl_handle_ = curl_easy_init(); |
| 60 CHECK(curl_handle_); | 61 CHECK(curl_handle_); |
| 61 | 62 |
| 63 CHECK(HasProxy()); |
| 64 LOG(INFO) << "Using proxy: " << CurrentProxy(); |
| 65 if (CurrentProxy() == kNoProxy) { |
| 66 CHECK_EQ(curl_easy_setopt(curl_handle_, |
| 67 CURLOPT_PROXY, |
| 68 ""), CURLE_OK); |
| 69 } else { |
| 70 CHECK_EQ(curl_easy_setopt(curl_handle_, |
| 71 CURLOPT_PROXY, |
| 72 CurrentProxy().c_str()), CURLE_OK); |
| 73 // Curl seems to require us to set the protocol |
| 74 curl_proxytype type; |
| 75 if (ChromeProxyResolver::GetProxyType(CurrentProxy(), &type)) { |
| 76 CHECK_EQ(curl_easy_setopt(curl_handle_, |
| 77 CURLOPT_PROXYTYPE, |
| 78 type), CURLE_OK); |
| 79 } |
| 80 } |
| 81 |
| 62 if (post_data_set_) { | 82 if (post_data_set_) { |
| 63 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POST, 1), CURLE_OK); | 83 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POST, 1), CURLE_OK); |
| 64 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDS, | 84 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDS, |
| 65 &post_data_[0]), | 85 &post_data_[0]), |
| 66 CURLE_OK); | 86 CURLE_OK); |
| 67 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDSIZE, | 87 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDSIZE, |
| 68 post_data_.size()), | 88 post_data_.size()), |
| 69 CURLE_OK); | 89 CURLE_OK); |
| 70 } | 90 } |
| 71 | 91 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK); | 146 CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK); |
| 127 transfer_in_progress_ = true; | 147 transfer_in_progress_ = true; |
| 128 } | 148 } |
| 129 | 149 |
| 130 // Begins the transfer, which must not have already been started. | 150 // Begins the transfer, which must not have already been started. |
| 131 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { | 151 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { |
| 132 transfer_size_ = -1; | 152 transfer_size_ = -1; |
| 133 resume_offset_ = 0; | 153 resume_offset_ = 0; |
| 134 retry_count_ = 0; | 154 retry_count_ = 0; |
| 135 http_response_code_ = 0; | 155 http_response_code_ = 0; |
| 156 ResolveProxiesForUrl(url); |
| 136 ResumeTransfer(url); | 157 ResumeTransfer(url); |
| 137 CurlPerformOnce(); | 158 CurlPerformOnce(); |
| 138 } | 159 } |
| 139 | 160 |
| 140 void LibcurlHttpFetcher::ForceTransferTermination() { | 161 void LibcurlHttpFetcher::ForceTransferTermination() { |
| 141 CleanUp(); | 162 CleanUp(); |
| 142 if (delegate_) { | 163 if (delegate_) { |
| 143 // Note that after the callback returns this object may be destroyed. | 164 // Note that after the callback returns this object may be destroyed. |
| 144 delegate_->TransferTerminated(this); | 165 delegate_->TransferTerminated(this); |
| 145 } | 166 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 171 GetHttpResponseCode(); | 192 GetHttpResponseCode(); |
| 172 if (http_response_code_) { | 193 if (http_response_code_) { |
| 173 LOG(INFO) << "HTTP response code: " << http_response_code_; | 194 LOG(INFO) << "HTTP response code: " << http_response_code_; |
| 174 } else { | 195 } else { |
| 175 LOG(ERROR) << "Unable to get http response code."; | 196 LOG(ERROR) << "Unable to get http response code."; |
| 176 } | 197 } |
| 177 | 198 |
| 178 // we're done! | 199 // we're done! |
| 179 CleanUp(); | 200 CleanUp(); |
| 180 | 201 |
| 202 if (!sent_byte_ && |
| 203 (http_response_code_ < 200 || http_response_code_ >= 300)) { |
| 204 // The transfer completed w/ error and we didn't get any bytes. |
| 205 // If we have another proxy to try, try that. |
| 206 |
| 207 PopProxy(); // Delete the proxy we just gave up on. |
| 208 |
| 209 if (HasProxy()) { |
| 210 // We have another proxy. Retry immediately. |
| 211 g_idle_add(&LibcurlHttpFetcher::StaticRetryTimeoutCallback, this); |
| 212 } else { |
| 213 // Out of proxies. Give up. |
| 214 if (delegate_) |
| 215 delegate_->TransferComplete(this, false); // success |
| 216 } |
| 217 return; |
| 218 } |
| 219 |
| 181 if ((transfer_size_ >= 0) && (bytes_downloaded_ < transfer_size_)) { | 220 if ((transfer_size_ >= 0) && (bytes_downloaded_ < transfer_size_)) { |
| 182 // Need to restart transfer | 221 // Need to restart transfer |
| 183 retry_count_++; | 222 retry_count_++; |
| 184 LOG(INFO) << "Restarting transfer b/c we finished, had downloaded " | 223 LOG(INFO) << "Restarting transfer b/c we finished, had downloaded " |
| 185 << bytes_downloaded_ << " bytes, but transfer_size_ is " | 224 << bytes_downloaded_ << " bytes, but transfer_size_ is " |
| 186 << transfer_size_ << ". retry_count: " << retry_count_; | 225 << transfer_size_ << ". retry_count: " << retry_count_; |
| 187 if (retry_count_ > kMaxRetriesCount) { | 226 if (retry_count_ > kMaxRetriesCount) { |
| 188 if (delegate_) | 227 if (delegate_) |
| 189 delegate_->TransferComplete(this, false); // success | 228 delegate_->TransferComplete(this, false); // success |
| 190 } else { | 229 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 201 delegate_->TransferComplete(this, success); | 240 delegate_->TransferComplete(this, success); |
| 202 } | 241 } |
| 203 } | 242 } |
| 204 } else { | 243 } else { |
| 205 // set up callback | 244 // set up callback |
| 206 SetupMainloopSources(); | 245 SetupMainloopSources(); |
| 207 } | 246 } |
| 208 } | 247 } |
| 209 | 248 |
| 210 size_t LibcurlHttpFetcher::LibcurlWrite(void *ptr, size_t size, size_t nmemb) { | 249 size_t LibcurlHttpFetcher::LibcurlWrite(void *ptr, size_t size, size_t nmemb) { |
| 250 if (size == 0) |
| 251 return 0; |
| 252 sent_byte_ = true; |
| 211 GetHttpResponseCode(); | 253 GetHttpResponseCode(); |
| 212 { | 254 { |
| 213 double transfer_size_double; | 255 double transfer_size_double; |
| 214 CHECK_EQ(curl_easy_getinfo(curl_handle_, | 256 CHECK_EQ(curl_easy_getinfo(curl_handle_, |
| 215 CURLINFO_CONTENT_LENGTH_DOWNLOAD, | 257 CURLINFO_CONTENT_LENGTH_DOWNLOAD, |
| 216 &transfer_size_double), CURLE_OK); | 258 &transfer_size_double), CURLE_OK); |
| 217 off_t new_transfer_size = static_cast<off_t>(transfer_size_double); | 259 off_t new_transfer_size = static_cast<off_t>(transfer_size_double); |
| 218 if (new_transfer_size > 0) { | 260 if (new_transfer_size > 0) { |
| 219 transfer_size_ = resume_offset_ + new_transfer_size; | 261 transfer_size_ = resume_offset_ + new_transfer_size; |
| 220 } | 262 } |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 void LibcurlHttpFetcher::GetHttpResponseCode() { | 421 void LibcurlHttpFetcher::GetHttpResponseCode() { |
| 380 long http_response_code = 0; | 422 long http_response_code = 0; |
| 381 if (curl_easy_getinfo(curl_handle_, | 423 if (curl_easy_getinfo(curl_handle_, |
| 382 CURLINFO_RESPONSE_CODE, | 424 CURLINFO_RESPONSE_CODE, |
| 383 &http_response_code) == CURLE_OK) { | 425 &http_response_code) == CURLE_OK) { |
| 384 http_response_code_ = static_cast<int>(http_response_code); | 426 http_response_code_ = static_cast<int>(http_response_code); |
| 385 } | 427 } |
| 386 } | 428 } |
| 387 | 429 |
| 388 } // namespace chromeos_update_engine | 430 } // namespace chromeos_update_engine |
| OLD | NEW |