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 |