blob: 7fa5f098155fd846b82378889532e742b2f2b0b4 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#ifndef UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_
18#define UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_
rspangler@google.com49fdf182009-10-10 00:57:34 +000019
Andrew de los Reyes45168102010-11-22 11:13:50 -080020#include <deque>
Amin Hassani0cd9d772018-07-31 23:55:43 -070021#include <memory>
rspangler@google.com49fdf182009-10-10 00:57:34 +000022#include <string>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000023#include <vector>
Andrew de los Reyes45168102010-11-22 11:13:50 -080024
Alex Vakulenko4906c1c2014-08-21 13:17:44 -070025#include <base/callback.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080026#include <base/logging.h>
Ben Chan05735a12014-09-03 07:48:22 -070027#include <base/macros.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070028#include <brillo/message_loops/message_loop.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080029
Alex Deymo39910dc2015-11-09 17:04:30 -080030#include "update_engine/common/http_common.h"
Amin Hassaniec7bc112020-10-29 16:47:58 -070031#include "update_engine/common/metrics_constants.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070032#include "update_engine/common/proxy_resolver.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000033
34// This class is a simple wrapper around an HTTP library (libcurl). We can
35// easily mock out this interface for testing.
36
37// Implementations of this class should use asynchronous i/o. They can access
Alex Deymo60ca1a72015-06-18 18:19:15 -070038// the MessageLoop to request callbacks when timers or file descriptors change.
rspangler@google.com49fdf182009-10-10 00:57:34 +000039
40namespace chromeos_update_engine {
41
42class HttpFetcherDelegate;
43
44class HttpFetcher {
45 public:
Andrew de los Reyes45168102010-11-22 11:13:50 -080046 // |proxy_resolver| is the resolver that will be consulted for proxy
47 // settings. It may be null, in which case direct connections will
48 // be used. Does not take ownership of the resolver.
Alex Deymo6f10c5f2016-03-03 22:35:43 -080049 explicit HttpFetcher(ProxyResolver* proxy_resolver)
Darin Petkovcb466212010-08-26 09:40:11 -070050 : post_data_set_(false),
51 http_response_code_(0),
Alex Vakulenko88b591f2014-08-28 16:48:57 -070052 delegate_(nullptr),
Andrew de los Reyes45168102010-11-22 11:13:50 -080053 proxies_(1, kNoProxy),
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -080054 proxy_resolver_(proxy_resolver),
Alex Deymoc1c17b42015-11-23 03:53:15 -030055 callback_(nullptr) {}
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -080056 virtual ~HttpFetcher();
Darin Petkovcb466212010-08-26 09:40:11 -070057
58 void set_delegate(HttpFetcherDelegate* delegate) { delegate_ = delegate; }
59 HttpFetcherDelegate* delegate() const { return delegate_; }
60 int http_response_code() const { return http_response_code_; }
rspangler@google.com49fdf182009-10-10 00:57:34 +000061
Amin Hassanid3d84212019-08-17 00:27:44 -070062 // 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.
66 ErrorCode GetAuxiliaryErrorCode() const { return auxiliary_error_code_; }
67
rspangler@google.com49fdf182009-10-10 00:57:34 +000068 // Optional: Post data to the server. The HttpFetcher should make a copy
Gilad Arnold9dd1e7c2012-02-16 12:13:36 -080069 // 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.
Andrew de los Reyes45168102010-11-22 11:13:50 -080074 void SetPostData(const void* data, size_t size);
75
76 // Proxy methods to set the proxies, then to pop them off.
Daniel Erate5f6f252017-04-20 12:09:58 -060077 void ResolveProxiesForUrl(const std::string& url,
Alex Deymo60ca1a72015-06-18 18:19:15 -070078 const base::Closure& callback);
Jay Srinivasan43488792012-06-19 00:25:31 -070079
Andrew de los Reyes45168102010-11-22 11:13:50 -080080 void SetProxies(const std::deque<std::string>& proxies) {
81 proxies_ = proxies;
rspangler@google.com49fdf182009-10-10 00:57:34 +000082 }
Amin Hassanib2689592019-01-13 17:04:28 -080083 const std::string& GetCurrentProxy() const { return proxies_.front(); }
Andrew de los Reyes45168102010-11-22 11:13:50 -080084 bool HasProxy() const { return !proxies_.empty(); }
85 void PopProxy() { proxies_.pop_front(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +000086
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070087 // Downloading should resume from this offset
88 virtual void SetOffset(off_t offset) = 0;
89
Gilad Arnolde4ad2502011-12-29 17:08:54 -080090 // Set/unset the length of the range to be downloaded.
91 virtual void SetLength(size_t length) = 0;
92 virtual void UnsetLength() = 0;
93
Darin Petkov9ce452b2010-11-17 14:33:28 -080094 // Begins the transfer to the specified URL. This fetcher instance should not
95 // be destroyed until either TransferComplete, or TransferTerminated is
96 // called.
rspangler@google.com49fdf182009-10-10 00:57:34 +000097 virtual void BeginTransfer(const std::string& url) = 0;
98
Darin Petkov9ce452b2010-11-17 14:33:28 -080099 // Aborts the transfer. The transfer may not abort right away -- delegate's
100 // TransferTerminated() will be called when the transfer is actually done.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000101 virtual void TerminateTransfer() = 0;
102
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800103 // Add or update a custom header to be sent with every request. If the same
104 // |header_name| is passed twice, the second |header_value| would override the
105 // previous value.
106 virtual void SetHeader(const std::string& header_name,
107 const std::string& header_value) = 0;
108
Jae Hoon Kim0ae8fe12019-06-26 14:32:50 -0700109 // Only used for testing.
110 // If |header_name| is set, the value will be set into |header_value|.
111 // On success the boolean true will be returned, hoewever on failture to find
112 // the |header_name| in the header the return value will be false. The state
113 // in which |header_value| is left in for failures is an empty string.
114 virtual bool GetHeader(const std::string& header_name,
115 std::string* header_value) const = 0;
116
rspangler@google.com49fdf182009-10-10 00:57:34 +0000117 // If data is coming in too quickly, you can call Pause() to pause the
118 // transfer. The delegate will not have ReceivedBytes() called while
119 // an HttpFetcher is paused.
120 virtual void Pause() = 0;
121
122 // Used to unpause an HttpFetcher and let the bytes stream in again.
123 // If a delegate is set, ReceivedBytes() may be called on it before
124 // Unpause() returns
125 virtual void Unpause() = 0;
126
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700127 // These two function are overloaded in LibcurlHttp fetcher to speed
128 // testing.
129 virtual void set_idle_seconds(int seconds) {}
130 virtual void set_retry_seconds(int seconds) {}
131
David Zeuthen34135a92013-08-06 11:16:16 -0700132 // Sets the values used to time out the connection if the transfer
133 // rate is less than |low_speed_bps| bytes/sec for more than
134 // |low_speed_sec| seconds.
135 virtual void set_low_speed_limit(int low_speed_bps, int low_speed_sec) = 0;
136
137 // Sets the connect timeout, e.g. the maximum amount of time willing
138 // to wait for establishing a connection to the server.
139 virtual void set_connect_timeout(int connect_timeout_seconds) = 0;
140
141 // Sets the number of allowed retries.
142 virtual void set_max_retry_count(int max_retry_count) = 0;
143
Gilad Arnold48085ba2011-11-16 09:36:08 -0800144 // Get the total number of bytes downloaded by fetcher.
145 virtual size_t GetBytesDownloaded() = 0;
146
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800147 ProxyResolver* proxy_resolver() const { return proxy_resolver_; }
148
rspangler@google.com49fdf182009-10-10 00:57:34 +0000149 protected:
Alex Deymo71f67622017-02-03 21:30:24 -0800150 // Cancels a proxy resolution in progress. The callback passed to
151 // ResolveProxiesForUrl() will not be called. Returns whether there was a
152 // pending proxy resolution to be canceled.
153 bool CancelProxyResolution();
154
rspangler@google.com49fdf182009-10-10 00:57:34 +0000155 // The URL we're actively fetching from
156 std::string url_;
157
158 // POST data for the transfer, and whether or not it was ever set
159 bool post_data_set_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700160 brillo::Blob post_data_;
Gilad Arnold9dd1e7c2012-02-16 12:13:36 -0800161 HttpContentType post_content_type_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000162
Darin Petkovcb466212010-08-26 09:40:11 -0700163 // The server's HTTP response code from the last transfer. This
164 // field should be set to 0 when a new transfer is initiated, and
165 // set to the response code when the transfer is complete.
166 int http_response_code_;
167
Amin Hassanid3d84212019-08-17 00:27:44 -0700168 // Set when there is an error that can't be expressed in the form of
169 // |http_response_code_|.
170 ErrorCode auxiliary_error_code_{ErrorCode::kSuccess};
171
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700172 // The delegate; may be null.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000173 HttpFetcherDelegate* delegate_;
Andrew de los Reyes45168102010-11-22 11:13:50 -0800174
175 // Proxy servers
176 std::deque<std::string> proxies_;
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800177
Andrew de los Reyes45168102010-11-22 11:13:50 -0800178 ProxyResolver* const proxy_resolver_;
179
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800180 // The ID of the idle callback, used when we have no proxy resolver.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700181 brillo::MessageLoop::TaskId no_resolver_idle_id_{
182 brillo::MessageLoop::kTaskIdNull};
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800183
184 // Callback for when we are resolving proxies
Alex Deymo60ca1a72015-06-18 18:19:15 -0700185 std::unique_ptr<base::Closure> callback_;
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800186
rspangler@google.com49fdf182009-10-10 00:57:34 +0000187 private:
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800188 // Callback from the proxy resolver
189 void ProxiesResolved(const std::deque<std::string>& proxies);
Jay Srinivasan43488792012-06-19 00:25:31 -0700190
Alex Deymo60ca1a72015-06-18 18:19:15 -0700191 // Callback used to run the proxy resolver callback when there is no
192 // |proxy_resolver_|.
193 void NoProxyResolverCallback();
194
Alex Deymo71f67622017-02-03 21:30:24 -0800195 // Stores the ongoing proxy request id if there is one, otherwise
196 // kProxyRequestIdNull.
197 ProxyRequestId proxy_request_{kProxyRequestIdNull};
198
rspangler@google.com49fdf182009-10-10 00:57:34 +0000199 DISALLOW_COPY_AND_ASSIGN(HttpFetcher);
200};
201
202// Interface for delegates
203class HttpFetcherDelegate {
204 public:
Alex Deymoe8948702014-11-11 21:44:45 -0800205 virtual ~HttpFetcherDelegate() = default;
206
Amin Hassani0cd9d772018-07-31 23:55:43 -0700207 // Called every time bytes are received. Returns false if this call causes the
208 // transfer be terminated or completed otherwise it returns true.
209 virtual bool ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800210 const void* bytes,
211 size_t length) = 0;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000212
Andrew de los Reyes34e41a12010-10-26 20:07:58 -0700213 // Called if the fetcher seeks to a particular offset.
214 virtual void SeekToOffset(off_t offset) {}
215
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800216 // When a transfer has completed, exactly one of these two methods will be
217 // called. TransferTerminated is called when the transfer has been aborted
218 // through TerminateTransfer. TransferComplete is called in all other
219 // situations. It's OK to destroy the |fetcher| object in this callback.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000220 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) = 0;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800221 virtual void TransferTerminated(HttpFetcher* fetcher) {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000222};
223
224} // namespace chromeos_update_engine
225
Alex Deymo39910dc2015-11-09 17:04:30 -0800226#endif // UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_