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 |