| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // NOTE: lifted from src/platform/update_engine and tweaked for cashew |
| 6 // TODO(vlaviano): see http_fetcher.h |
| 7 |
| 8 #ifndef SRC_LIBCURL_HTTP_FETCHER_H_ |
| 9 #define SRC_LIBCURL_HTTP_FETCHER_H_ |
| 10 |
| 11 #include <curl/curl.h> |
| 12 #include <glib.h> |
| 13 |
| 14 #include <map> |
| 15 #include <string> |
| 16 |
| 17 #include <base/basictypes.h> // NOLINT |
| 18 |
| 19 #include "src/http_fetcher.h" |
| 20 |
| 21 // This is a concrete implementation of HttpFetcher that uses libcurl to do the |
| 22 // http work. |
| 23 |
| 24 namespace cashew { |
| 25 |
| 26 class LibcurlHttpFetcher : public HttpFetcher { |
| 27 public: |
| 28 static const int kMaxRedirects = 10; |
| 29 |
| 30 LibcurlHttpFetcher() |
| 31 : curl_multi_handle_(NULL), |
| 32 curl_handle_(NULL), |
| 33 timeout_source_(NULL), |
| 34 transfer_in_progress_(false), |
| 35 retry_count_(0), |
| 36 retry_seconds_(60), |
| 37 idle_seconds_(1) {} |
| 38 |
| 39 // Cleans up all internal state. Does not notify delegate |
| 40 ~LibcurlHttpFetcher(); |
| 41 |
| 42 // Begins the transfer if it hasn't already begun. |
| 43 virtual void BeginTransfer(const std::string& url); |
| 44 |
| 45 // If the transfer is in progress, aborts the transfer early. |
| 46 // The transfer cannot be resumed. |
| 47 virtual void TerminateTransfer(); |
| 48 |
| 49 // Suspend the transfer by calling curl_easy_pause(CURLPAUSE_ALL). |
| 50 virtual void Pause(); |
| 51 |
| 52 // Resume the transfer by calling curl_easy_pause(CURLPAUSE_CONT). |
| 53 virtual void Unpause(); |
| 54 |
| 55 // Libcurl sometimes asks to be called back after some time while |
| 56 // leaving that time unspecified. In that case, we pick a reasonable |
| 57 // default of one second, but it can be overridden here. This is |
| 58 // primarily useful for testing. |
| 59 // From http://curl.haxx.se/libcurl/c/curl_multi_timeout.html: |
| 60 // if libcurl returns a -1 timeout here, it just means that libcurl |
| 61 // currently has no stored timeout value. You must not wait too long |
| 62 // (more than a few seconds perhaps) before you call |
| 63 // curl_multi_perform() again. |
| 64 void set_idle_seconds(int seconds) { idle_seconds_ = seconds; } |
| 65 |
| 66 // Sets the retry timeout. Useful for testing. |
| 67 void set_retry_seconds(int seconds) { retry_seconds_ = seconds; } |
| 68 |
| 69 private: |
| 70 // Resumes a transfer where it left off. This will use the |
| 71 // HTTP Range: header to make a new connection from where the last |
| 72 // left off. |
| 73 virtual void ResumeTransfer(const std::string& url); |
| 74 |
| 75 // These two methods are for glib main loop callbacks. They are called |
| 76 // when either a file descriptor is ready for work or when a timer |
| 77 // has fired. The static versions are shims for libcurl which has a C API. |
| 78 bool FDCallback(GIOChannel *source, GIOCondition condition); |
| 79 static gboolean StaticFDCallback(GIOChannel *source, |
| 80 GIOCondition condition, |
| 81 gpointer data) { |
| 82 return reinterpret_cast<LibcurlHttpFetcher*>(data)->FDCallback(source, |
| 83 condition); |
| 84 } |
| 85 gboolean TimeoutCallback(); |
| 86 static gboolean StaticTimeoutCallback(gpointer data) { |
| 87 return reinterpret_cast<LibcurlHttpFetcher*>(data)->TimeoutCallback(); |
| 88 } |
| 89 |
| 90 gboolean RetryTimeoutCallback(); |
| 91 static gboolean StaticRetryTimeoutCallback(void* arg) { |
| 92 return static_cast<LibcurlHttpFetcher*>(arg)->RetryTimeoutCallback(); |
| 93 } |
| 94 |
| 95 // Calls into curl_multi_perform to let libcurl do its work. Returns after |
| 96 // curl_multi_perform is finished, which may actually be after more than |
| 97 // one call to curl_multi_perform. This method will set up the glib run |
| 98 // loop with sources for future work that libcurl will do. |
| 99 // This method will not block. |
| 100 // Returns true if we should resume immediately after this call. |
| 101 void CurlPerformOnce(); |
| 102 |
| 103 // Sets up glib main loop sources as needed by libcurl. This is generally |
| 104 // the file descriptor of the socket and a timer in case nothing happens |
| 105 // on the fds. |
| 106 void SetupMainloopSources(); |
| 107 |
| 108 // Callback called by libcurl when new data has arrived on the transfer |
| 109 size_t LibcurlWrite(void *ptr, size_t size, size_t nmemb); |
| 110 static size_t StaticLibcurlWrite(void *ptr, size_t size, |
| 111 size_t nmemb, void *stream) { |
| 112 return reinterpret_cast<LibcurlHttpFetcher*>(stream)-> |
| 113 LibcurlWrite(ptr, size, nmemb); |
| 114 } |
| 115 |
| 116 // Cleans up the following if they are non-null: |
| 117 // curl(m) handles, io_channels_, timeout_source_. |
| 118 void CleanUp(); |
| 119 |
| 120 // Handles for the libcurl library |
| 121 CURLM *curl_multi_handle_; |
| 122 CURL *curl_handle_; |
| 123 |
| 124 // a list of all file descriptors that we're waiting on from the |
| 125 // glib main loop |
| 126 typedef std::map<int, std::pair<GIOChannel*, guint> > IOChannels; |
| 127 IOChannels io_channels_; |
| 128 |
| 129 // if non-NULL, a timer we're waiting on. glib main loop will call us back |
| 130 // when it fires. |
| 131 GSource* timeout_source_; |
| 132 |
| 133 bool transfer_in_progress_; |
| 134 |
| 135 // The transfer size. -1 if not known. |
| 136 off_t transfer_size_; |
| 137 |
| 138 // How many bytes have been downloaded and sent to the delegate. |
| 139 off_t bytes_downloaded_; |
| 140 |
| 141 // If we resumed an earlier transfer, data offset that we used for the |
| 142 // new connection. 0 otherwise. |
| 143 off_t resume_offset_; |
| 144 |
| 145 // Number of resumes performed. |
| 146 int retry_count_; |
| 147 |
| 148 // Seconds to wait before retrying a resume. |
| 149 int retry_seconds_; |
| 150 |
| 151 // Seconds to wait before asking libcurl to "perform". |
| 152 int idle_seconds_; |
| 153 |
| 154 DISALLOW_COPY_AND_ASSIGN(LibcurlHttpFetcher); |
| 155 }; |
| 156 |
| 157 } // namespace cashew |
| 158 |
| 159 #endif // SRC_LIBCURL_HTTP_FETCHER_H_ |
| OLD | NEW |