Chromium Code Reviews| 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 if (!HasProxy()) { | |
| 64 LOG(ERROR) << "Missing proxy."; | |
| 
 
petkov
2010/11/19 05:37:15
This is a really unexpected case, right? If you en
 
adlr
2010/11/20 02:52:29
good call. changed to CHECK
 
 | |
| 65 } else { | |
| 66 LOG(INFO) << "Using proxy: " << CurrentProxy(); | |
| 67 if (CurrentProxy() == kNoProxy) { | |
| 68 CHECK_EQ(curl_easy_setopt(curl_handle_, | |
| 69 CURLOPT_PROXY, | |
| 70 ""), CURLE_OK); | |
| 71 } else { | |
| 72 CHECK_EQ(curl_easy_setopt(curl_handle_, | |
| 73 CURLOPT_PROXY, | |
| 74 CurrentProxy().c_str()), CURLE_OK); | |
| 75 // Curl seems to require us to set the protocol | |
| 76 curl_proxytype type; | |
| 77 if (ChromeProxyResolver::GetProxyType(CurrentProxy(), &type)) { | |
| 78 LOG(INFO) << "Set proxtype to: " << type; | |
| 
 
petkov
2010/11/19 05:37:15
Set proxy type?
 
adlr
2010/11/20 02:52:29
removed this line; was kinda redundant
 
 | |
| 79 CHECK_EQ(curl_easy_setopt(curl_handle_, | |
| 80 CURLOPT_PROXYTYPE, | |
| 81 type), CURLE_OK); | |
| 82 } | |
| 83 } | |
| 84 } | |
| 85 | |
| 62 if (post_data_set_) { | 86 if (post_data_set_) { | 
| 63 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POST, 1), CURLE_OK); | 87 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POST, 1), CURLE_OK); | 
| 64 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDS, | 88 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDS, | 
| 65 &post_data_[0]), | 89 &post_data_[0]), | 
| 66 CURLE_OK); | 90 CURLE_OK); | 
| 67 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDSIZE, | 91 CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_POSTFIELDSIZE, | 
| 68 post_data_.size()), | 92 post_data_.size()), | 
| 69 CURLE_OK); | 93 CURLE_OK); | 
| 70 } | 94 } | 
| 71 | 95 | 
| (...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); | 150 CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK); | 
| 127 transfer_in_progress_ = true; | 151 transfer_in_progress_ = true; | 
| 128 } | 152 } | 
| 129 | 153 | 
| 130 // Begins the transfer, which must not have already been started. | 154 // Begins the transfer, which must not have already been started. | 
| 131 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { | 155 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) { | 
| 132 transfer_size_ = -1; | 156 transfer_size_ = -1; | 
| 133 resume_offset_ = 0; | 157 resume_offset_ = 0; | 
| 134 retry_count_ = 0; | 158 retry_count_ = 0; | 
| 135 http_response_code_ = 0; | 159 http_response_code_ = 0; | 
| 160 ResolveProxiesForUrl(url); | |
| 136 ResumeTransfer(url); | 161 ResumeTransfer(url); | 
| 137 CurlPerformOnce(); | 162 CurlPerformOnce(); | 
| 138 } | 163 } | 
| 139 | 164 | 
| 140 void LibcurlHttpFetcher::ForceTransferTermination() { | 165 void LibcurlHttpFetcher::ForceTransferTermination() { | 
| 141 CleanUp(); | 166 CleanUp(); | 
| 142 if (delegate_) { | 167 if (delegate_) { | 
| 143 // Note that after the callback returns this object may be destroyed. | 168 // Note that after the callback returns this object may be destroyed. | 
| 144 delegate_->TransferTerminated(this); | 169 delegate_->TransferTerminated(this); | 
| 145 } | 170 } | 
| (...skipping 25 matching lines...) Expand all Loading... | |
| 171 GetHttpResponseCode(); | 196 GetHttpResponseCode(); | 
| 172 if (http_response_code_) { | 197 if (http_response_code_) { | 
| 173 LOG(INFO) << "HTTP response code: " << http_response_code_; | 198 LOG(INFO) << "HTTP response code: " << http_response_code_; | 
| 174 } else { | 199 } else { | 
| 175 LOG(ERROR) << "Unable to get http response code."; | 200 LOG(ERROR) << "Unable to get http response code."; | 
| 176 } | 201 } | 
| 177 | 202 | 
| 178 // we're done! | 203 // we're done! | 
| 179 CleanUp(); | 204 CleanUp(); | 
| 180 | 205 | 
| 206 if (!sent_byte_ && | |
| 207 (http_response_code_ < 200 || http_response_code_ >= 300)) { | |
| 208 // The transfer completed w/ error and we didn't get any bytes. | |
| 209 // If we have another proxy to try, try that. | |
| 210 | |
| 211 PopProxy(); // Delete the proxy we just gave up on. | |
| 212 | |
| 213 if (HasProxy()) { | |
| 214 // We have another proxy. Retry immediately. | |
| 215 g_timeout_add_seconds(0, | |
| 
 
petkov
2010/11/19 05:37:15
g_idle_add?
 
adlr
2010/11/20 02:52:29
Done.
 
 | |
| 216 &LibcurlHttpFetcher::StaticRetryTimeoutCallback, | |
| 217 this); | |
| 218 } else { | |
| 219 // Out of proxies. Give up. | |
| 220 if (delegate_) | |
| 221 delegate_->TransferComplete(this, false); // success | |
| 222 } | |
| 223 return; | |
| 224 } | |
| 225 | |
| 181 if ((transfer_size_ >= 0) && (bytes_downloaded_ < transfer_size_)) { | 226 if ((transfer_size_ >= 0) && (bytes_downloaded_ < transfer_size_)) { | 
| 182 // Need to restart transfer | 227 // Need to restart transfer | 
| 183 retry_count_++; | 228 retry_count_++; | 
| 184 LOG(INFO) << "Restarting transfer b/c we finished, had downloaded " | 229 LOG(INFO) << "Restarting transfer b/c we finished, had downloaded " | 
| 185 << bytes_downloaded_ << " bytes, but transfer_size_ is " | 230 << bytes_downloaded_ << " bytes, but transfer_size_ is " | 
| 186 << transfer_size_ << ". retry_count: " << retry_count_; | 231 << transfer_size_ << ". retry_count: " << retry_count_; | 
| 187 if (retry_count_ > kMaxRetriesCount) { | 232 if (retry_count_ > kMaxRetriesCount) { | 
| 188 if (delegate_) | 233 if (delegate_) | 
| 189 delegate_->TransferComplete(this, false); // success | 234 delegate_->TransferComplete(this, false); // success | 
| 190 } else { | 235 } else { | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 201 delegate_->TransferComplete(this, success); | 246 delegate_->TransferComplete(this, success); | 
| 202 } | 247 } | 
| 203 } | 248 } | 
| 204 } else { | 249 } else { | 
| 205 // set up callback | 250 // set up callback | 
| 206 SetupMainloopSources(); | 251 SetupMainloopSources(); | 
| 207 } | 252 } | 
| 208 } | 253 } | 
| 209 | 254 | 
| 210 size_t LibcurlHttpFetcher::LibcurlWrite(void *ptr, size_t size, size_t nmemb) { | 255 size_t LibcurlHttpFetcher::LibcurlWrite(void *ptr, size_t size, size_t nmemb) { | 
| 256 sent_byte_ = true; | |
| 
 
petkov
2010/11/19 05:37:15
are you sure size > 0?
 
adlr
2010/11/20 02:52:29
hadn't considered that. Should we even call anyone
 
 | |
| 211 GetHttpResponseCode(); | 257 GetHttpResponseCode(); | 
| 212 { | 258 { | 
| 213 double transfer_size_double; | 259 double transfer_size_double; | 
| 214 CHECK_EQ(curl_easy_getinfo(curl_handle_, | 260 CHECK_EQ(curl_easy_getinfo(curl_handle_, | 
| 215 CURLINFO_CONTENT_LENGTH_DOWNLOAD, | 261 CURLINFO_CONTENT_LENGTH_DOWNLOAD, | 
| 216 &transfer_size_double), CURLE_OK); | 262 &transfer_size_double), CURLE_OK); | 
| 217 off_t new_transfer_size = static_cast<off_t>(transfer_size_double); | 263 off_t new_transfer_size = static_cast<off_t>(transfer_size_double); | 
| 218 if (new_transfer_size > 0) { | 264 if (new_transfer_size > 0) { | 
| 219 transfer_size_ = resume_offset_ + new_transfer_size; | 265 transfer_size_ = resume_offset_ + new_transfer_size; | 
| 220 } | 266 } | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 void LibcurlHttpFetcher::GetHttpResponseCode() { | 425 void LibcurlHttpFetcher::GetHttpResponseCode() { | 
| 380 long http_response_code = 0; | 426 long http_response_code = 0; | 
| 381 if (curl_easy_getinfo(curl_handle_, | 427 if (curl_easy_getinfo(curl_handle_, | 
| 382 CURLINFO_RESPONSE_CODE, | 428 CURLINFO_RESPONSE_CODE, | 
| 383 &http_response_code) == CURLE_OK) { | 429 &http_response_code) == CURLE_OK) { | 
| 384 http_response_code_ = static_cast<int>(http_response_code); | 430 http_response_code_ = static_cast<int>(http_response_code); | 
| 385 } | 431 } | 
| 386 } | 432 } | 
| 387 | 433 | 
| 388 } // namespace chromeos_update_engine | 434 } // namespace chromeos_update_engine | 
| OLD | NEW |