1 // 2 // Copyright (C) 2009 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_ 18 #define UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_ 19 20 #include <deque> 21 #include <string> 22 #include <vector> 23 24 #include <base/callback.h> 25 #include <base/logging.h> 26 #include <base/macros.h> 27 #include <brillo/message_loops/message_loop.h> 28 29 #include "update_engine/common/http_common.h" 30 #include "update_engine/proxy_resolver.h" 31 32 // This class is a simple wrapper around an HTTP library (libcurl). We can 33 // easily mock out this interface for testing. 34 35 // Implementations of this class should use asynchronous i/o. They can access 36 // the MessageLoop to request callbacks when timers or file descriptors change. 37 38 namespace chromeos_update_engine { 39 40 class HttpFetcherDelegate; 41 42 class HttpFetcher { 43 public: 44 // |proxy_resolver| is the resolver that will be consulted for proxy 45 // settings. It may be null, in which case direct connections will 46 // be used. Does not take ownership of the resolver. 47 explicit HttpFetcher(ProxyResolver* proxy_resolver) 48 : post_data_set_(false), 49 http_response_code_(0), 50 delegate_(nullptr), 51 proxies_(1, kNoProxy), 52 proxy_resolver_(proxy_resolver), 53 callback_(nullptr) {} 54 virtual ~HttpFetcher(); 55 56 void set_delegate(HttpFetcherDelegate* delegate) { delegate_ = delegate; } 57 HttpFetcherDelegate* delegate() const { return delegate_; } 58 int http_response_code() const { return http_response_code_; } 59 60 // Optional: Post data to the server. The HttpFetcher should make a copy 61 // of this data and upload it via HTTP POST during the transfer. The type of 62 // the data is necessary for properly setting the Content-Type HTTP header. 63 void SetPostData(const void* data, size_t size, HttpContentType type); 64 65 // Same without a specified Content-Type. 66 void SetPostData(const void* data, size_t size); 67 68 // Proxy methods to set the proxies, then to pop them off. 69 // Returns true on success. 70 bool ResolveProxiesForUrl(const std::string& url, 71 const base::Closure& callback); 72 73 void SetProxies(const std::deque<std::string>& proxies) { 74 proxies_ = proxies; 75 } 76 const std::string& GetCurrentProxy() const { 77 return proxies_.front(); 78 } 79 bool HasProxy() const { return !proxies_.empty(); } 80 void PopProxy() { proxies_.pop_front(); } 81 82 // Downloading should resume from this offset 83 virtual void SetOffset(off_t offset) = 0; 84 85 // Set/unset the length of the range to be downloaded. 86 virtual void SetLength(size_t length) = 0; 87 virtual void UnsetLength() = 0; 88 89 // Begins the transfer to the specified URL. This fetcher instance should not 90 // be destroyed until either TransferComplete, or TransferTerminated is 91 // called. 92 virtual void BeginTransfer(const std::string& url) = 0; 93 94 // Aborts the transfer. The transfer may not abort right away -- delegate's 95 // TransferTerminated() will be called when the transfer is actually done. 96 virtual void TerminateTransfer() = 0; 97 98 // Add or update a custom header to be sent with every request. If the same 99 // |header_name| is passed twice, the second |header_value| would override the 100 // previous value. 101 virtual void SetHeader(const std::string& header_name, 102 const std::string& header_value) = 0; 103 104 // If data is coming in too quickly, you can call Pause() to pause the 105 // transfer. The delegate will not have ReceivedBytes() called while 106 // an HttpFetcher is paused. 107 virtual void Pause() = 0; 108 109 // Used to unpause an HttpFetcher and let the bytes stream in again. 110 // If a delegate is set, ReceivedBytes() may be called on it before 111 // Unpause() returns 112 virtual void Unpause() = 0; 113 114 // These two function are overloaded in LibcurlHttp fetcher to speed 115 // testing. 116 virtual void set_idle_seconds(int seconds) {} 117 virtual void set_retry_seconds(int seconds) {} 118 119 // Sets the values used to time out the connection if the transfer 120 // rate is less than |low_speed_bps| bytes/sec for more than 121 // |low_speed_sec| seconds. 122 virtual void set_low_speed_limit(int low_speed_bps, int low_speed_sec) = 0; 123 124 // Sets the connect timeout, e.g. the maximum amount of time willing 125 // to wait for establishing a connection to the server. 126 virtual void set_connect_timeout(int connect_timeout_seconds) = 0; 127 128 // Sets the number of allowed retries. 129 virtual void set_max_retry_count(int max_retry_count) = 0; 130 131 // Get the total number of bytes downloaded by fetcher. 132 virtual size_t GetBytesDownloaded() = 0; 133 134 ProxyResolver* proxy_resolver() const { return proxy_resolver_; } 135 136 protected: 137 // The URL we're actively fetching from 138 std::string url_; 139 140 // POST data for the transfer, and whether or not it was ever set 141 bool post_data_set_; 142 brillo::Blob post_data_; 143 HttpContentType post_content_type_; 144 145 // The server's HTTP response code from the last transfer. This 146 // field should be set to 0 when a new transfer is initiated, and 147 // set to the response code when the transfer is complete. 148 int http_response_code_; 149 150 // The delegate; may be null. 151 HttpFetcherDelegate* delegate_; 152 153 // Proxy servers 154 std::deque<std::string> proxies_; 155 156 ProxyResolver* const proxy_resolver_; 157 158 // The ID of the idle callback, used when we have no proxy resolver. 159 brillo::MessageLoop::TaskId no_resolver_idle_id_{ 160 brillo::MessageLoop::kTaskIdNull}; 161 162 // Callback for when we are resolving proxies 163 std::unique_ptr<base::Closure> callback_; 164 165 private: 166 // Callback from the proxy resolver 167 void ProxiesResolved(const std::deque<std::string>& proxies); 168 static void StaticProxiesResolved(const std::deque<std::string>& proxies, 169 void* data) { 170 reinterpret_cast<HttpFetcher*>(data)->ProxiesResolved(proxies); 171 } 172 173 // Callback used to run the proxy resolver callback when there is no 174 // |proxy_resolver_|. 175 void NoProxyResolverCallback(); 176 177 DISALLOW_COPY_AND_ASSIGN(HttpFetcher); 178 }; 179 180 // Interface for delegates 181 class HttpFetcherDelegate { 182 public: 183 virtual ~HttpFetcherDelegate() = default; 184 185 // Called every time bytes are received. 186 virtual void ReceivedBytes(HttpFetcher* fetcher, 187 const void* bytes, 188 size_t length) = 0; 189 190 // Called if the fetcher seeks to a particular offset. 191 virtual void SeekToOffset(off_t offset) {} 192 193 // When a transfer has completed, exactly one of these two methods will be 194 // called. TransferTerminated is called when the transfer has been aborted 195 // through TerminateTransfer. TransferComplete is called in all other 196 // situations. It's OK to destroy the |fetcher| object in this callback. 197 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) = 0; 198 virtual void TransferTerminated(HttpFetcher* fetcher) {} 199 }; 200 201 } // namespace chromeos_update_engine 202 203 #endif // UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_ 204