| 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 |