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> |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 void LibcurlHttpFetcher::Unpause() { | 221 void LibcurlHttpFetcher::Unpause() { |
222 CHECK(curl_handle_); | 222 CHECK(curl_handle_); |
223 CHECK(transfer_in_progress_); | 223 CHECK(transfer_in_progress_); |
224 CHECK_EQ(curl_easy_pause(curl_handle_, CURLPAUSE_CONT), CURLE_OK); | 224 CHECK_EQ(curl_easy_pause(curl_handle_, CURLPAUSE_CONT), CURLE_OK); |
225 } | 225 } |
226 | 226 |
227 // This method sets up callbacks with the glib main loop. | 227 // This method sets up callbacks with the glib main loop. |
228 void LibcurlHttpFetcher::SetupMainloopSources() { | 228 void LibcurlHttpFetcher::SetupMainloopSources() { |
229 fd_set fd_read; | 229 fd_set fd_read; |
230 fd_set fd_write; | 230 fd_set fd_write; |
231 fd_set fd_exec; | 231 fd_set fd_exc; |
232 | 232 |
233 FD_ZERO(&fd_read); | 233 FD_ZERO(&fd_read); |
234 FD_ZERO(&fd_write); | 234 FD_ZERO(&fd_write); |
235 FD_ZERO(&fd_exec); | 235 FD_ZERO(&fd_exc); |
236 | 236 |
237 int fd_max = 0; | 237 int fd_max = 0; |
238 | 238 |
239 // Ask libcurl for the set of file descriptors we should track on its | 239 // Ask libcurl for the set of file descriptors we should track on its |
240 // behalf. | 240 // behalf. |
241 CHECK_EQ(curl_multi_fdset(curl_multi_handle_, &fd_read, &fd_write, | 241 CHECK_EQ(curl_multi_fdset(curl_multi_handle_, &fd_read, &fd_write, |
242 &fd_exec, &fd_max), CURLM_OK); | 242 &fd_exc, &fd_max), CURLM_OK); |
243 | 243 |
244 // We should iterate through all file descriptors up to libcurl's fd_max or | 244 // We should iterate through all file descriptors up to libcurl's fd_max or |
245 // the highest one we're tracking, whichever is larger | 245 // the highest one we're tracking, whichever is larger. |
246 if (!io_channels_.empty()) | 246 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
247 fd_max = max(fd_max, io_channels_.rbegin()->first); | 247 if (!io_channels_[t].empty()) |
| 248 fd_max = max(fd_max, io_channels_[t].rbegin()->first); |
| 249 } |
248 | 250 |
249 // For each fd, if we're not tracking it, track it. If we are tracking it, | 251 // For each fd, if we're not tracking it, track it. If we are tracking it, but |
250 // but libcurl doesn't care about it anymore, stop tracking it. | 252 // libcurl doesn't care about it anymore, stop tracking it. After this loop, |
251 // After this loop, there should be exactly as many GIOChannel objects | 253 // there should be exactly as many GIOChannel objects in io_channels_[0|1] as |
252 // in io_channels_ as there are fds that we're tracking. | 254 // there are read/write fds that we're tracking. |
253 for (int i = 0; i <= fd_max; i++) { | 255 for (int fd = 0; fd <= fd_max; ++fd) { |
254 if (!(FD_ISSET(i, &fd_read) || FD_ISSET(i, &fd_write) || | 256 // Note that fd_exc is unused in the current version of libcurl so is_exc |
255 FD_ISSET(i, &fd_exec))) { | 257 // should always be false. |
256 // if we have an outstanding io_channel, remove it | 258 bool is_exc = FD_ISSET(fd, &fd_exc) != 0; |
257 if (io_channels_.find(i) != io_channels_.end()) { | 259 bool must_track[2] = { |
258 g_source_remove(io_channels_[i].second); | 260 is_exc || (FD_ISSET(fd, &fd_read) != 0), // track 0 -- read |
259 g_io_channel_unref(io_channels_[i].first); | 261 is_exc || (FD_ISSET(fd, &fd_write) != 0) // track 1 -- write |
260 io_channels_.erase(io_channels_.find(i)); | 262 }; |
| 263 |
| 264 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
| 265 bool tracked = io_channels_[t].find(fd) != io_channels_[t].end(); |
| 266 |
| 267 if (!must_track[t]) { |
| 268 // If we have an outstanding io_channel, remove it. |
| 269 if (tracked) { |
| 270 g_source_remove(io_channels_[t][fd].second); |
| 271 g_io_channel_unref(io_channels_[t][fd].first); |
| 272 io_channels_[t].erase(io_channels_[t].find(fd)); |
| 273 } |
| 274 continue; |
261 } | 275 } |
262 continue; | 276 |
263 } | 277 // If we are already tracking this fd, continue -- nothing to do. |
264 // If we are already tracking this fd, continue. | 278 if (tracked) |
265 if (io_channels_.find(i) != io_channels_.end()) | 279 continue; |
266 continue; | 280 |
267 // We must track a new fd | 281 // Set conditions appropriately -- read for track 0, write for track 1. |
268 GIOChannel *io_channel = g_io_channel_unix_new(i); | 282 GIOCondition condition = static_cast<GIOCondition>( |
269 guint tag = g_io_add_watch( | 283 ((t == 0) ? (G_IO_IN | G_IO_PRI) : G_IO_OUT) | G_IO_ERR | G_IO_HUP); |
270 io_channel, | 284 |
271 static_cast<GIOCondition>(G_IO_IN | G_IO_OUT | G_IO_PRI | | 285 // Track a new fd. |
272 G_IO_ERR | G_IO_HUP), | 286 GIOChannel* io_channel = g_io_channel_unix_new(fd); |
273 &StaticFDCallback, | 287 guint tag = |
274 this); | 288 g_io_add_watch(io_channel, condition, &StaticFDCallback, this); |
275 io_channels_[i] = make_pair(io_channel, tag); | 289 |
276 static int io_counter = 0; | 290 io_channels_[t][fd] = make_pair(io_channel, tag); |
277 io_counter++; | 291 static int io_counter = 0; |
278 if (io_counter % 50 == 0) { | 292 io_counter++; |
279 LOG(INFO) << "io_counter = " << io_counter; | 293 if (io_counter % 50 == 0) { |
| 294 LOG(INFO) << "io_counter = " << io_counter; |
| 295 } |
280 } | 296 } |
281 } | 297 } |
282 | 298 |
283 // Set up a timeout callback for libcurl. | 299 // Set up a timeout callback for libcurl. |
284 if (!timeout_source_) { | 300 if (!timeout_source_) { |
285 LOG(INFO) << "Setting up timeout source: " << idle_seconds_ << " seconds."; | 301 LOG(INFO) << "Setting up timeout source: " << idle_seconds_ << " seconds."; |
286 timeout_source_ = g_timeout_source_new_seconds(idle_seconds_); | 302 timeout_source_ = g_timeout_source_new_seconds(idle_seconds_); |
287 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this, NULL); | 303 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this, NULL); |
288 g_source_attach(timeout_source_, NULL); | 304 g_source_attach(timeout_source_, NULL); |
289 } | 305 } |
(...skipping 24 matching lines...) Expand all Loading... |
314 CurlPerformOnce(); | 330 CurlPerformOnce(); |
315 return TRUE; | 331 return TRUE; |
316 } | 332 } |
317 | 333 |
318 void LibcurlHttpFetcher::CleanUp() { | 334 void LibcurlHttpFetcher::CleanUp() { |
319 if (timeout_source_) { | 335 if (timeout_source_) { |
320 g_source_destroy(timeout_source_); | 336 g_source_destroy(timeout_source_); |
321 timeout_source_ = NULL; | 337 timeout_source_ = NULL; |
322 } | 338 } |
323 | 339 |
324 for (IOChannels::iterator it = io_channels_.begin(); | 340 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
325 it != io_channels_.end(); ++it) { | 341 for (IOChannels::iterator it = io_channels_[t].begin(); |
326 g_source_remove(it->second.second); | 342 it != io_channels_[t].end(); ++it) { |
327 g_io_channel_unref(it->second.first); | 343 g_source_remove(it->second.second); |
| 344 g_io_channel_unref(it->second.first); |
| 345 } |
| 346 io_channels_[t].clear(); |
328 } | 347 } |
329 io_channels_.clear(); | |
330 | 348 |
331 if (curl_handle_) { | 349 if (curl_handle_) { |
332 if (curl_multi_handle_) { | 350 if (curl_multi_handle_) { |
333 CHECK_EQ(curl_multi_remove_handle(curl_multi_handle_, curl_handle_), | 351 CHECK_EQ(curl_multi_remove_handle(curl_multi_handle_, curl_handle_), |
334 CURLM_OK); | 352 CURLM_OK); |
335 } | 353 } |
336 curl_easy_cleanup(curl_handle_); | 354 curl_easy_cleanup(curl_handle_); |
337 curl_handle_ = NULL; | 355 curl_handle_ = NULL; |
338 } | 356 } |
339 if (curl_multi_handle_) { | 357 if (curl_multi_handle_) { |
340 CHECK_EQ(curl_multi_cleanup(curl_multi_handle_), CURLM_OK); | 358 CHECK_EQ(curl_multi_cleanup(curl_multi_handle_), CURLM_OK); |
341 curl_multi_handle_ = NULL; | 359 curl_multi_handle_ = NULL; |
342 } | 360 } |
343 transfer_in_progress_ = false; | 361 transfer_in_progress_ = false; |
344 } | 362 } |
345 | 363 |
346 void LibcurlHttpFetcher::GetHttpResponseCode() { | 364 void LibcurlHttpFetcher::GetHttpResponseCode() { |
347 long http_response_code = 0; | 365 long http_response_code = 0; |
348 if (curl_easy_getinfo(curl_handle_, | 366 if (curl_easy_getinfo(curl_handle_, |
349 CURLINFO_RESPONSE_CODE, | 367 CURLINFO_RESPONSE_CODE, |
350 &http_response_code) == CURLE_OK) { | 368 &http_response_code) == CURLE_OK) { |
351 http_response_code_ = static_cast<int>(http_response_code); | 369 http_response_code_ = static_cast<int>(http_response_code); |
352 } | 370 } |
353 } | 371 } |
354 | 372 |
355 } // namespace chromeos_update_engine | 373 } // namespace chromeos_update_engine |
OLD | NEW |