1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2009 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#ifndef UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_
1839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#define UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_
1949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
204516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes#include <deque>
2149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <string>
22c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include <vector>
234516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes
244906c1c6dac2ef7916bfa7193cc9324e99b4d223Alex Vakulenko#include <base/callback.h>
254516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes#include <base/logging.h>
2605735a1879a553153458aae0a25fa5d42e3e408fBen Chan#include <base/macros.h>
273f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop.h>
284516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes
2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/http_common.h"
304516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes#include "update_engine/proxy_resolver.h"
3149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// This class is a simple wrapper around an HTTP library (libcurl). We can
3349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// easily mock out this interface for testing.
3449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// Implementations of this class should use asynchronous i/o. They can access
3660ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo// the MessageLoop to request callbacks when timers or file descriptors change.
3749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comnamespace chromeos_update_engine {
3949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
4049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass HttpFetcherDelegate;
4149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
4249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass HttpFetcher {
4349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com public:
444516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  // |proxy_resolver| is the resolver that will be consulted for proxy
454516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  // settings. It may be null, in which case direct connections will
464516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  // be used. Does not take ownership of the resolver.
476f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo  explicit HttpFetcher(ProxyResolver* proxy_resolver)
48cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov      : post_data_set_(false),
49cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov        http_response_code_(0),
5088b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko        delegate_(nullptr),
514516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes        proxies_(1, kNoProxy),
52f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes        proxy_resolver_(proxy_resolver),
53c1c17b4ed6a3896b6343e737fd89682fa0c8436bAlex Deymo        callback_(nullptr) {}
54f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes  virtual ~HttpFetcher();
55cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov
56cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  void set_delegate(HttpFetcherDelegate* delegate) { delegate_ = delegate; }
57cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  HttpFetcherDelegate* delegate() const { return delegate_; }
58cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  int http_response_code() const { return http_response_code_; }
5949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
6049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Optional: Post data to the server. The HttpFetcher should make a copy
619dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold  // of this data and upload it via HTTP POST during the transfer. The type of
629dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold  // the data is necessary for properly setting the Content-Type HTTP header.
639dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold  void SetPostData(const void* data, size_t size, HttpContentType type);
649dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold
659dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold  // Same without a specified Content-Type.
664516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  void SetPostData(const void* data, size_t size);
674516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes
684516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  // Proxy methods to set the proxies, then to pop them off.
69e5f6f2571d43eb65e0b27dd8d50f2c1f0b3fe30fDaniel Erat  void ResolveProxiesForUrl(const std::string& url,
7060ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo                            const base::Closure& callback);
714348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
724516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  void SetProxies(const std::deque<std::string>& proxies) {
734516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes    proxies_ = proxies;
7449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  }
754516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  const std::string& GetCurrentProxy() const {
764516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes    return proxies_.front();
774516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  }
784516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  bool HasProxy() const { return !proxies_.empty(); }
794516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  void PopProxy() { proxies_.pop_front(); }
8049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
813fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  // Downloading should resume from this offset
823fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  virtual void SetOffset(off_t offset) = 0;
833fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes
84e4ad2508de4d69d7a90d3ce441efe2c82c55bd1dGilad Arnold  // Set/unset the length of the range to be downloaded.
85e4ad2508de4d69d7a90d3ce441efe2c82c55bd1dGilad Arnold  virtual void SetLength(size_t length) = 0;
86e4ad2508de4d69d7a90d3ce441efe2c82c55bd1dGilad Arnold  virtual void UnsetLength() = 0;
87e4ad2508de4d69d7a90d3ce441efe2c82c55bd1dGilad Arnold
889ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  // Begins the transfer to the specified URL. This fetcher instance should not
899ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  // be destroyed until either TransferComplete, or TransferTerminated is
909ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  // called.
9149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void BeginTransfer(const std::string& url) = 0;
9249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
939ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  // Aborts the transfer. The transfer may not abort right away -- delegate's
949ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  // TransferTerminated() will be called when the transfer is actually done.
9549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void TerminateTransfer() = 0;
9649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
976f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo  // Add or update a custom header to be sent with every request. If the same
986f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo  // |header_name| is passed twice, the second |header_value| would override the
996f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo  // previous value.
1006f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo  virtual void SetHeader(const std::string& header_name,
1016f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo                         const std::string& header_value) = 0;
1026f10c5f7c550b1bd6df1d9a04b5e75e03f943639Alex Deymo
10349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // If data is coming in too quickly, you can call Pause() to pause the
10449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // transfer. The delegate will not have ReceivedBytes() called while
10549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // an HttpFetcher is paused.
10649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void Pause() = 0;
10749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
10849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Used to unpause an HttpFetcher and let the bytes stream in again.
10949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // If a delegate is set, ReceivedBytes() may be called on it before
11049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Unpause() returns
11149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void Unpause() = 0;
11249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
1133fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  // These two function are overloaded in LibcurlHttp fetcher to speed
1143fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  // testing.
1153fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  virtual void set_idle_seconds(int seconds) {}
1163fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes  virtual void set_retry_seconds(int seconds) {}
1173fd5d30433509859bfdcc0b650e242981410c6a7Andrew de los Reyes
11834135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // Sets the values used to time out the connection if the transfer
11934135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // rate is less than |low_speed_bps| bytes/sec for more than
12034135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // |low_speed_sec| seconds.
12134135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  virtual void set_low_speed_limit(int low_speed_bps, int low_speed_sec) = 0;
12234135a9f24c72137aa85378b57e7698162c687f2David Zeuthen
12334135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // Sets the connect timeout, e.g. the maximum amount of time willing
12434135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // to wait for establishing a connection to the server.
12534135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  virtual void set_connect_timeout(int connect_timeout_seconds) = 0;
12634135a9f24c72137aa85378b57e7698162c687f2David Zeuthen
12734135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  // Sets the number of allowed retries.
12834135a9f24c72137aa85378b57e7698162c687f2David Zeuthen  virtual void set_max_retry_count(int max_retry_count) = 0;
12934135a9f24c72137aa85378b57e7698162c687f2David Zeuthen
13048085ba58516e94f045d3ab7e26c8f36e6a6936fGilad Arnold  // Get the total number of bytes downloaded by fetcher.
13148085ba58516e94f045d3ab7e26c8f36e6a6936fGilad Arnold  virtual size_t GetBytesDownloaded() = 0;
13248085ba58516e94f045d3ab7e26c8f36e6a6936fGilad Arnold
133819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes  ProxyResolver* proxy_resolver() const { return proxy_resolver_; }
134819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes
13549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com protected:
13671f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  // Cancels a proxy resolution in progress. The callback passed to
13771f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  // ResolveProxiesForUrl() will not be called. Returns whether there was a
13871f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  // pending proxy resolution to be canceled.
13971f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  bool CancelProxyResolution();
14071f6762c7e04774439c8011a5032bea6f182276fAlex Deymo
14149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // The URL we're actively fetching from
14249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  std::string url_;
14349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
14449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // POST data for the transfer, and whether or not it was ever set
14549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  bool post_data_set_;
1463f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob post_data_;
1479dd1e7c6bbc605c2150800f763c596ff0a4ad1c1Gilad Arnold  HttpContentType post_content_type_;
14849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
149cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  // The server's HTTP response code from the last transfer. This
150cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  // field should be set to 0 when a new transfer is initiated, and
151cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  // set to the response code when the transfer is complete.
152cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov  int http_response_code_;
153cb466212cccca21dfe0dcd01afbbb06e005309e2Darin Petkov
15488b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  // The delegate; may be null.
15549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  HttpFetcherDelegate* delegate_;
1564516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes
1574516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  // Proxy servers
1584516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  std::deque<std::string> proxies_;
159f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes
1604516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes  ProxyResolver* const proxy_resolver_;
1614516810fe41a39c0c55d2095679898787259ae38Andrew de los Reyes
162f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes  // The ID of the idle callback, used when we have no proxy resolver.
1633f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::MessageLoop::TaskId no_resolver_idle_id_{
1643f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko      brillo::MessageLoop::kTaskIdNull};
165f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes
166f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes  // Callback for when we are resolving proxies
16760ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  std::unique_ptr<base::Closure> callback_;
168f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes
16949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com private:
170f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes  // Callback from the proxy resolver
171f3ed8e7d4ad456a3c841d8a530f308b6fcb2a4ccAndrew de los Reyes  void ProxiesResolved(const std::deque<std::string>& proxies);
1724348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
17360ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  // Callback used to run the proxy resolver callback when there is no
17460ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  // |proxy_resolver_|.
17560ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  void NoProxyResolverCallback();
17660ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo
17771f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  // Stores the ongoing proxy request id if there is one, otherwise
17871f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  // kProxyRequestIdNull.
17971f6762c7e04774439c8011a5032bea6f182276fAlex Deymo  ProxyRequestId proxy_request_{kProxyRequestIdNull};
18071f6762c7e04774439c8011a5032bea6f182276fAlex Deymo
18149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  DISALLOW_COPY_AND_ASSIGN(HttpFetcher);
18249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com};
18349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
18449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// Interface for delegates
18549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass HttpFetcherDelegate {
18649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com public:
187e89487039d0eca8130d822cabf75a729609509e0Alex Deymo  virtual ~HttpFetcherDelegate() = default;
188e89487039d0eca8130d822cabf75a729609509e0Alex Deymo
18934e41a1b50ccd06f5b3dad7a1ab1d467c7e8e00eAndrew de los Reyes  // Called every time bytes are received.
19049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void ReceivedBytes(HttpFetcher* fetcher,
191f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                             const void* bytes,
192f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                             size_t length) = 0;
19349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
19434e41a1b50ccd06f5b3dad7a1ab1d467c7e8e00eAndrew de los Reyes  // Called if the fetcher seeks to a particular offset.
19534e41a1b50ccd06f5b3dad7a1ab1d467c7e8e00eAndrew de los Reyes  virtual void SeekToOffset(off_t offset) {}
19634e41a1b50ccd06f5b3dad7a1ab1d467c7e8e00eAndrew de los Reyes
197819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes  // When a transfer has completed, exactly one of these two methods will be
198819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes  // called. TransferTerminated is called when the transfer has been aborted
199819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes  // through TerminateTransfer. TransferComplete is called in all other
200819fef2e0fa08984cf31e848e704442c500ea4f9Andrew de los Reyes  // situations. It's OK to destroy the |fetcher| object in this callback.
20149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void TransferComplete(HttpFetcher* fetcher, bool successful) = 0;
2029ce452b6acd95899e9adb17c2935012625163dc6Darin Petkov  virtual void TransferTerminated(HttpFetcher* fetcher) {}
20349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com};
20449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
20549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com}  // namespace chromeos_update_engine
20649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
20739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#endif  // UPDATE_ENGINE_COMMON_HTTP_FETCHER_H_
208