| Andrew de los Reyes | 819fef2 | 2010-12-17 11:33:58 -0800 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 
|  | 2 | // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 | // found in the LICENSE file. | 
|  | 4 |  | 
|  | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__ | 
|  | 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__ | 
|  | 7 |  | 
|  | 8 | #include <deque> | 
|  | 9 | #include <utility> | 
|  | 10 | #include <vector> | 
|  | 11 |  | 
| Chris Masone | d903c3b | 2011-05-12 15:35:46 -0700 | [diff] [blame] | 12 | #include <base/memory/scoped_ptr.h> | 
| Andrew de los Reyes | 819fef2 | 2010-12-17 11:33:58 -0800 | [diff] [blame] | 13 |  | 
|  | 14 | #include "update_engine/http_fetcher.h" | 
|  | 15 |  | 
|  | 16 | // This class is a simple wrapper around an HttpFetcher. The client | 
|  | 17 | // specifies a vector of byte ranges. MultiRangeHTTPFetcher will fetch bytes | 
|  | 18 | // from those offsets, using the same bash fetcher for all ranges. Thus, the | 
|  | 19 | // fetcher must support beginning a transfter after one has stopped. Pass -1 | 
|  | 20 | // as a length to specify unlimited length. It really only would make sense | 
|  | 21 | // for the last range specified to have unlimited length, tho it is legal for | 
|  | 22 | // other entries to have unlimited length. | 
|  | 23 |  | 
|  | 24 | // There are three states a MultiRangeHTTPFetcher object will be in: | 
|  | 25 | // - Stopped (start state) | 
|  | 26 | // - Downloading | 
|  | 27 | // - Pending transfer ended | 
|  | 28 | // Various functions below that might change state indicate possible | 
|  | 29 | // state changes. | 
|  | 30 |  | 
|  | 31 | namespace chromeos_update_engine { | 
|  | 32 |  | 
|  | 33 | class MultiRangeHTTPFetcher : public HttpFetcher, public HttpFetcherDelegate { | 
|  | 34 | public: | 
|  | 35 | // Takes ownership of the passed in fetcher. | 
|  | 36 | explicit MultiRangeHTTPFetcher(HttpFetcher* base_fetcher) | 
|  | 37 | : HttpFetcher(base_fetcher->proxy_resolver()), | 
|  | 38 | base_fetcher_(base_fetcher), | 
|  | 39 | base_fetcher_active_(false), | 
|  | 40 | pending_transfer_ended_(false), | 
|  | 41 | terminating_(false), | 
|  | 42 | current_index_(0), | 
|  | 43 | bytes_received_this_range_(0) {} | 
|  | 44 | ~MultiRangeHTTPFetcher() {} | 
|  | 45 |  | 
|  | 46 | void ClearRanges() { ranges_.clear(); } | 
|  | 47 |  | 
|  | 48 | void AddRange(off_t offset, off_t size) { | 
|  | 49 | ranges_.push_back(std::make_pair(offset, size)); | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | virtual void SetOffset(off_t offset) {}  // for now, doesn't support this | 
|  | 53 |  | 
|  | 54 | // Begins the transfer to the specified URL. | 
|  | 55 | // State change: Stopped -> Downloading | 
|  | 56 | // (corner case: Stopped -> Stopped for an empty request) | 
|  | 57 | virtual void BeginTransfer(const std::string& url); | 
|  | 58 |  | 
|  | 59 | // State change: Downloading -> Pending transfer ended | 
|  | 60 | virtual void TerminateTransfer(); | 
|  | 61 |  | 
|  | 62 | virtual void Pause() { base_fetcher_->Pause(); } | 
|  | 63 |  | 
|  | 64 | virtual void Unpause() { base_fetcher_->Unpause(); } | 
|  | 65 |  | 
|  | 66 | // These functions are overloaded in LibcurlHttp fetcher for testing purposes. | 
|  | 67 | virtual void set_idle_seconds(int seconds) { | 
|  | 68 | base_fetcher_->set_idle_seconds(seconds); | 
|  | 69 | } | 
|  | 70 | virtual void set_retry_seconds(int seconds) { | 
|  | 71 | base_fetcher_->set_retry_seconds(seconds); | 
|  | 72 | } | 
|  | 73 | virtual void SetConnectionAsExpensive(bool is_expensive) { | 
|  | 74 | base_fetcher_->SetConnectionAsExpensive(is_expensive); | 
|  | 75 | } | 
|  | 76 | virtual void SetBuildType(bool is_official) { | 
|  | 77 | base_fetcher_->SetBuildType(is_official); | 
|  | 78 | } | 
|  | 79 | virtual void SetProxies(const std::deque<std::string>& proxies) { | 
|  | 80 | base_fetcher_->SetProxies(proxies); | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | private: | 
|  | 84 | // pair<offset, length>: | 
|  | 85 | typedef std::vector<std::pair<off_t, off_t> > RangesVect; | 
|  | 86 |  | 
|  | 87 | // State change: Stopped or Downloading -> Downloading | 
|  | 88 | void StartTransfer(); | 
|  | 89 |  | 
|  | 90 | // State change: Downloading -> Downloading or Pending transfer ended | 
|  | 91 | virtual void ReceivedBytes(HttpFetcher* fetcher, | 
|  | 92 | const char* bytes, | 
|  | 93 | int length); | 
|  | 94 |  | 
|  | 95 | // State change: Pending transfer ended -> Stopped | 
|  | 96 | void TransferEnded(HttpFetcher* fetcher, bool successful); | 
|  | 97 | // These two call TransferEnded(): | 
|  | 98 | virtual void TransferComplete(HttpFetcher* fetcher, bool successful); | 
|  | 99 | virtual void TransferTerminated(HttpFetcher* fetcher); | 
|  | 100 |  | 
|  | 101 | void Reset(); | 
|  | 102 |  | 
|  | 103 | scoped_ptr<HttpFetcher> base_fetcher_; | 
|  | 104 |  | 
|  | 105 | // If true, do not send any more data or TransferComplete to the delegate. | 
|  | 106 | bool base_fetcher_active_; | 
|  | 107 |  | 
|  | 108 | // If true, the next fetcher needs to be started when TransferTerminated is | 
|  | 109 | // received from the current fetcher. | 
|  | 110 | bool pending_transfer_ended_; | 
|  | 111 |  | 
|  | 112 | // True if we are waiting for base fetcher to terminate b/c we are | 
|  | 113 | // ourselves terminating. | 
|  | 114 | bool terminating_; | 
|  | 115 |  | 
|  | 116 | RangesVect ranges_; | 
|  | 117 |  | 
|  | 118 | RangesVect::size_type current_index_;  // index into ranges_ | 
|  | 119 | off_t bytes_received_this_range_; | 
|  | 120 |  | 
|  | 121 | DISALLOW_COPY_AND_ASSIGN(MultiRangeHTTPFetcher); | 
|  | 122 | }; | 
|  | 123 |  | 
|  | 124 | }  // namespace chromeos_update_engine | 
|  | 125 |  | 
|  | 126 | #endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__ |