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