| 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 // NOTE: lifted from src/platform/update_engine and tweaked for cashew | 5 // NOTE: lifted from src/platform/update_engine and tweaked for cashew |
| 6 // TODO(vlaviano): see http_fetcher.h | 6 // TODO(vlaviano): see http_fetcher.h |
| 7 | 7 |
| 8 #include "src/libcurl_http_fetcher.h" | 8 #include "src/libcurl_http_fetcher.h" |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 DLOG(INFO) << "Unpause"; | 176 DLOG(INFO) << "Unpause"; |
| 177 CHECK(curl_handle_); | 177 CHECK(curl_handle_); |
| 178 CHECK(transfer_in_progress_); | 178 CHECK(transfer_in_progress_); |
| 179 CHECK_EQ(curl_easy_pause(curl_handle_, CURLPAUSE_CONT), CURLE_OK); | 179 CHECK_EQ(curl_easy_pause(curl_handle_, CURLPAUSE_CONT), CURLE_OK); |
| 180 } | 180 } |
| 181 | 181 |
| 182 // This method sets up callbacks with the glib main loop. | 182 // This method sets up callbacks with the glib main loop. |
| 183 void LibcurlHttpFetcher::SetupMainloopSources() { | 183 void LibcurlHttpFetcher::SetupMainloopSources() { |
| 184 fd_set fd_read; | 184 fd_set fd_read; |
| 185 fd_set fd_write; | 185 fd_set fd_write; |
| 186 fd_set fd_exec; | 186 fd_set fd_exc; |
| 187 | 187 |
| 188 FD_ZERO(&fd_read); | 188 FD_ZERO(&fd_read); |
| 189 FD_ZERO(&fd_write); | 189 FD_ZERO(&fd_write); |
| 190 FD_ZERO(&fd_exec); | 190 FD_ZERO(&fd_exc); |
| 191 | 191 |
| 192 int fd_max = 0; | 192 int fd_max = 0; |
| 193 | 193 |
| 194 // Ask libcurl for the set of file descriptors we should track on its | 194 // Ask libcurl for the set of file descriptors we should track on its |
| 195 // behalf. | 195 // behalf. |
| 196 CHECK_EQ(curl_multi_fdset(curl_multi_handle_, &fd_read, &fd_write, | 196 CHECK_EQ(curl_multi_fdset(curl_multi_handle_, &fd_read, &fd_write, |
| 197 &fd_exec, &fd_max), CURLM_OK); | 197 &fd_exc, &fd_max), CURLM_OK); |
| 198 | 198 |
| 199 // We should iterate through all file descriptors up to libcurl's fd_max or | 199 // We should iterate through all file descriptors up to libcurl's fd_max or |
| 200 // the highest one we're tracking, whichever is larger | 200 // the highest one we're tracking, whichever is larger. |
| 201 if (!io_channels_.empty()) | 201 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
| 202 fd_max = max(fd_max, io_channels_.rbegin()->first); | 202 if (!io_channels_[t].empty()) |
| 203 fd_max = max(fd_max, io_channels_[t].rbegin()->first); |
| 204 } |
| 203 | 205 |
| 204 // For each fd, if we're not tracking it, track it. If we are tracking it, | 206 // For each fd, if we're not tracking it, track it. If we are tracking it, but |
| 205 // but libcurl doesn't care about it anymore, stop tracking it. | 207 // libcurl doesn't care about it anymore, stop tracking it. After this loop, |
| 206 // After this loop, there should be exactly as many GIOChannel objects | 208 // there should be exactly as many GIOChannel objects in io_channels_[0|1] as |
| 207 // in io_channels_ as there are fds that we're tracking. | 209 // there are read/write fds that we're tracking. |
| 208 for (int i = 0; i <= fd_max; i++) { | 210 for (int fd = 0; fd <= fd_max; ++fd) { |
| 209 if (!(FD_ISSET(i, &fd_read) || FD_ISSET(i, &fd_write) || | 211 // Note that fd_exc is unused in the current version of libcurl so is_exc |
| 210 FD_ISSET(i, &fd_exec))) { | 212 // should always be false. |
| 211 // if we have an outstanding io_channel, remove it | 213 bool is_exc = FD_ISSET(fd, &fd_exc) != 0; |
| 212 if (io_channels_.find(i) != io_channels_.end()) { | 214 bool must_track[2] = { |
| 213 g_source_remove(io_channels_[i].second); | 215 is_exc || (FD_ISSET(fd, &fd_read) != 0), // track 0 -- read |
| 214 g_io_channel_unref(io_channels_[i].first); | 216 is_exc || (FD_ISSET(fd, &fd_write) != 0) // track 1 -- write |
| 215 io_channels_.erase(io_channels_.find(i)); | 217 }; |
| 218 |
| 219 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
| 220 bool tracked = io_channels_[t].find(fd) != io_channels_[t].end(); |
| 221 |
| 222 if (!must_track[t]) { |
| 223 // If we have an outstanding io_channel, remove it. |
| 224 if (tracked) { |
| 225 g_source_remove(io_channels_[t][fd].second); |
| 226 g_io_channel_unref(io_channels_[t][fd].first); |
| 227 io_channels_[t].erase(io_channels_[t].find(fd)); |
| 228 } |
| 229 continue; |
| 216 } | 230 } |
| 217 continue; | 231 |
| 218 } | 232 // If we are already tracking this fd, continue -- nothing to do. |
| 219 // If we are already tracking this fd, continue. | 233 if (tracked) |
| 220 if (io_channels_.find(i) != io_channels_.end()) | 234 continue; |
| 221 continue; | 235 |
| 222 // We must track a new fd | 236 // Set conditions appropriately -- read for track 0, write for track 1. |
| 223 GIOChannel *io_channel = g_io_channel_unix_new(i); | 237 GIOCondition condition = static_cast<GIOCondition>( |
| 224 guint tag = g_io_add_watch( | 238 ((t == 0) ? (G_IO_IN | G_IO_PRI) : G_IO_OUT) | G_IO_ERR | G_IO_HUP); |
| 225 io_channel, | 239 |
| 226 static_cast<GIOCondition>(G_IO_IN | G_IO_OUT | G_IO_PRI | | 240 // Track a new fd. |
| 227 G_IO_ERR | G_IO_HUP), | 241 GIOChannel* io_channel = g_io_channel_unix_new(fd); |
| 228 &StaticFDCallback, | 242 guint tag = |
| 229 this); | 243 g_io_add_watch(io_channel, condition, &StaticFDCallback, this); |
| 230 io_channels_[i] = make_pair(io_channel, tag); | 244 |
| 231 static int io_counter = 0; | 245 io_channels_[t][fd] = make_pair(io_channel, tag); |
| 232 io_counter++; | 246 static int io_counter = 0; |
| 233 if (io_counter % 50 == 0) { | 247 io_counter++; |
| 234 LOG(INFO) << "io_counter = " << io_counter; | 248 if (io_counter % 50 == 0) { |
| 249 LOG(INFO) << "io_counter = " << io_counter; |
| 250 } |
| 235 } | 251 } |
| 236 } | 252 } |
| 237 | 253 |
| 238 // Set up a timeout callback for libcurl. | 254 // Set up a timeout callback for libcurl. |
| 239 if (!timeout_source_) { | 255 if (!timeout_source_) { |
| 240 LOG(INFO) << "Setting up timeout source: " << idle_seconds_ << " seconds."; | 256 LOG(INFO) << "Setting up timeout source: " << idle_seconds_ << " seconds."; |
| 241 timeout_source_ = g_timeout_source_new_seconds(idle_seconds_); | 257 timeout_source_ = g_timeout_source_new_seconds(idle_seconds_); |
| 242 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this, NULL); | 258 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this, NULL); |
| 243 g_source_attach(timeout_source_, NULL); | 259 g_source_attach(timeout_source_, NULL); |
| 244 } | 260 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 271 CurlPerformOnce(); | 287 CurlPerformOnce(); |
| 272 return TRUE; | 288 return TRUE; |
| 273 } | 289 } |
| 274 | 290 |
| 275 void LibcurlHttpFetcher::CleanUp() { | 291 void LibcurlHttpFetcher::CleanUp() { |
| 276 if (timeout_source_) { | 292 if (timeout_source_) { |
| 277 g_source_destroy(timeout_source_); | 293 g_source_destroy(timeout_source_); |
| 278 timeout_source_ = NULL; | 294 timeout_source_ = NULL; |
| 279 } | 295 } |
| 280 | 296 |
| 281 for (IOChannels::iterator it = io_channels_.begin(); | 297 for (size_t t = 0; t < arraysize(io_channels_); ++t) { |
| 282 it != io_channels_.end(); ++it) { | 298 for (IOChannels::iterator it = io_channels_[t].begin(); |
| 283 g_source_remove(it->second.second); | 299 it != io_channels_[t].end(); ++it) { |
| 284 g_io_channel_unref(it->second.first); | 300 g_source_remove(it->second.second); |
| 301 g_io_channel_unref(it->second.first); |
| 302 } |
| 303 io_channels_[t].clear(); |
| 285 } | 304 } |
| 286 io_channels_.clear(); | |
| 287 | 305 |
| 288 if (curl_handle_) { | 306 if (curl_handle_) { |
| 289 if (curl_multi_handle_) { | 307 if (curl_multi_handle_) { |
| 290 CHECK_EQ(curl_multi_remove_handle(curl_multi_handle_, curl_handle_), | 308 CHECK_EQ(curl_multi_remove_handle(curl_multi_handle_, curl_handle_), |
| 291 CURLM_OK); | 309 CURLM_OK); |
| 292 } | 310 } |
| 293 curl_easy_cleanup(curl_handle_); | 311 curl_easy_cleanup(curl_handle_); |
| 294 curl_handle_ = NULL; | 312 curl_handle_ = NULL; |
| 295 } | 313 } |
| 296 if (curl_multi_handle_) { | 314 if (curl_multi_handle_) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 307 &http_response_code); | 325 &http_response_code); |
| 308 if (result == CURLE_OK) { | 326 if (result == CURLE_OK) { |
| 309 http_response_code_ = static_cast<int>(http_response_code); | 327 http_response_code_ = static_cast<int>(http_response_code); |
| 310 } else { | 328 } else { |
| 311 DLOG(WARNING) << "GetHttpResponseCode: curl_easy_getinfo failed: " | 329 DLOG(WARNING) << "GetHttpResponseCode: curl_easy_getinfo failed: " |
| 312 << curl_easy_strerror(result); | 330 << curl_easy_strerror(result); |
| 313 } | 331 } |
| 314 } | 332 } |
| 315 | 333 |
| 316 } // namespace cashew | 334 } // namespace cashew |
| OLD | NEW |