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