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