blob: 1cdeb7b21293fc2a18933544bb4abd9dabfe3db1 [file] [log] [blame]
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001// 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
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
6#define UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
Andrew de los Reyes819fef22010-12-17 11:33:58 -08007
8#include <deque>
Ben Chan02f7c1d2014-10-18 15:18:02 -07009#include <memory>
Alex Vakulenkod2779df2014-06-16 13:19:00 -070010#include <string>
Andrew de los Reyes819fef22010-12-17 11:33:58 -080011#include <utility>
12#include <vector>
13
Andrew de los Reyes819fef22010-12-17 11:33:58 -080014#include "update_engine/http_fetcher.h"
15
16// This class is a simple wrapper around an HttpFetcher. The client
Gilad Arnold9bedeb52011-11-17 16:19:57 -080017// specifies a vector of byte ranges. MultiRangeHttpFetcher will fetch bytes
Andrew de los Reyes819fef22010-12-17 11:33:58 -080018// from those offsets, using the same bash fetcher for all ranges. Thus, the
Alex Vakulenko072359c2014-07-18 11:41:07 -070019// fetcher must support beginning a transfer after one has stopped. Pass -1
Andrew de los Reyes819fef22010-12-17 11:33:58 -080020// 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
Gilad Arnold9bedeb52011-11-17 16:19:57 -080024// There are three states a MultiRangeHttpFetcher object will be in:
Andrew de los Reyes819fef22010-12-17 11:33:58 -080025// - Stopped (start state)
26// - Downloading
27// - Pending transfer ended
28// Various functions below that might change state indicate possible
29// state changes.
30
31namespace chromeos_update_engine {
32
Gilad Arnold9bedeb52011-11-17 16:19:57 -080033class MultiRangeHttpFetcher : public HttpFetcher, public HttpFetcherDelegate {
Andrew de los Reyes819fef22010-12-17 11:33:58 -080034 public:
35 // Takes ownership of the passed in fetcher.
Gilad Arnold9bedeb52011-11-17 16:19:57 -080036 explicit MultiRangeHttpFetcher(HttpFetcher* base_fetcher)
Jay Srinivasan43488792012-06-19 00:25:31 -070037 : HttpFetcher(base_fetcher->proxy_resolver(),
38 base_fetcher->GetSystemState()),
Andrew de los Reyes819fef22010-12-17 11:33:58 -080039 base_fetcher_(base_fetcher),
40 base_fetcher_active_(false),
41 pending_transfer_ended_(false),
42 terminating_(false),
43 current_index_(0),
44 bytes_received_this_range_(0) {}
Alex Deymo610277e2014-11-11 21:18:11 -080045 ~MultiRangeHttpFetcher() override {}
Andrew de los Reyes819fef22010-12-17 11:33:58 -080046
47 void ClearRanges() { ranges_.clear(); }
48
Gilad Arnolde4ad2502011-12-29 17:08:54 -080049 void AddRange(off_t offset, size_t size) {
Mike Frysinger0f9547d2012-02-16 12:11:37 -050050 CHECK_GT(size, static_cast<size_t>(0));
Gilad Arnolde4ad2502011-12-29 17:08:54 -080051 ranges_.push_back(Range(offset, size));
52 }
53
54 void AddRange(off_t offset) {
55 ranges_.push_back(Range(offset));
Andrew de los Reyes819fef22010-12-17 11:33:58 -080056 }
57
Alex Deymo610277e2014-11-11 21:18:11 -080058 // HttpFetcher overrides.
59 void SetOffset(off_t offset) override {} // for now, doesn't support this
Andrew de los Reyes819fef22010-12-17 11:33:58 -080060
Alex Deymo610277e2014-11-11 21:18:11 -080061 void SetLength(size_t length) override {} // unsupported
62 void UnsetLength() override {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -080063
Andrew de los Reyes819fef22010-12-17 11:33:58 -080064 // Begins the transfer to the specified URL.
65 // State change: Stopped -> Downloading
66 // (corner case: Stopped -> Stopped for an empty request)
Alex Deymo610277e2014-11-11 21:18:11 -080067 void BeginTransfer(const std::string& url) override;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080068
69 // State change: Downloading -> Pending transfer ended
Alex Deymo610277e2014-11-11 21:18:11 -080070 void TerminateTransfer() override;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080071
Alex Deymo610277e2014-11-11 21:18:11 -080072 void Pause() override { base_fetcher_->Pause(); }
Andrew de los Reyes819fef22010-12-17 11:33:58 -080073
Alex Deymo610277e2014-11-11 21:18:11 -080074 void Unpause() override { base_fetcher_->Unpause(); }
Andrew de los Reyes819fef22010-12-17 11:33:58 -080075
76 // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
Alex Deymo610277e2014-11-11 21:18:11 -080077 void set_idle_seconds(int seconds) override {
Andrew de los Reyes819fef22010-12-17 11:33:58 -080078 base_fetcher_->set_idle_seconds(seconds);
79 }
Alex Deymo610277e2014-11-11 21:18:11 -080080 void set_retry_seconds(int seconds) override {
Andrew de los Reyes819fef22010-12-17 11:33:58 -080081 base_fetcher_->set_retry_seconds(seconds);
82 }
Alex Deymo610277e2014-11-11 21:18:11 -080083 // TODO(deymo): Determine if this method should be virtual in HttpFetcher so
84 // this call is sent to the base_fetcher_.
Andrew de los Reyes819fef22010-12-17 11:33:58 -080085 virtual void SetProxies(const std::deque<std::string>& proxies) {
86 base_fetcher_->SetProxies(proxies);
87 }
88
Alex Deymo610277e2014-11-11 21:18:11 -080089 inline size_t GetBytesDownloaded() override {
Gilad Arnold48085ba2011-11-16 09:36:08 -080090 return base_fetcher_->GetBytesDownloaded();
91 }
92
Alex Deymo610277e2014-11-11 21:18:11 -080093 void set_low_speed_limit(int low_speed_bps, int low_speed_sec) override {
David Zeuthen34135a92013-08-06 11:16:16 -070094 base_fetcher_->set_low_speed_limit(low_speed_bps, low_speed_sec);
95 }
96
Alex Deymo610277e2014-11-11 21:18:11 -080097 void set_connect_timeout(int connect_timeout_seconds) override {
David Zeuthen34135a92013-08-06 11:16:16 -070098 base_fetcher_->set_connect_timeout(connect_timeout_seconds);
99 }
100
Alex Deymo610277e2014-11-11 21:18:11 -0800101 void set_max_retry_count(int max_retry_count) override {
David Zeuthen34135a92013-08-06 11:16:16 -0700102 base_fetcher_->set_max_retry_count(max_retry_count);
103 }
104
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800105 private:
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800106 // A range object defining the offset and length of a download chunk. Zero
107 // length indicates an unspecified end offset (note that it is impossible to
108 // request a zero-length range in HTTP).
109 class Range {
110 public:
111 Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700112 explicit Range(off_t offset) : offset_(offset), length_(0) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800113
114 inline off_t offset() const { return offset_; }
115 inline size_t length() const { return length_; }
116
117 inline bool HasLength() const { return (length_ > 0); }
118
119 std::string ToString() const;
120
121 private:
122 off_t offset_;
123 size_t length_;
124 };
125
126 typedef std::vector<Range> RangesVect;
Jay Srinivasan43488792012-06-19 00:25:31 -0700127
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800128 // State change: Stopped or Downloading -> Downloading
129 void StartTransfer();
130
Alex Deymo610277e2014-11-11 21:18:11 -0800131 // HttpFetcherDelegate overrides.
Jay Srinivasan43488792012-06-19 00:25:31 -0700132 // State change: Downloading -> Downloading or Pending transfer ended
Alex Deymo610277e2014-11-11 21:18:11 -0800133 void ReceivedBytes(HttpFetcher* fetcher,
134 const char* bytes,
135 int length) override;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800136
137 // State change: Pending transfer ended -> Stopped
138 void TransferEnded(HttpFetcher* fetcher, bool successful);
139 // These two call TransferEnded():
Alex Deymo610277e2014-11-11 21:18:11 -0800140 void TransferComplete(HttpFetcher* fetcher, bool successful) override;
141 void TransferTerminated(HttpFetcher* fetcher) override;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800142
143 void Reset();
144
Ben Chan02f7c1d2014-10-18 15:18:02 -0700145 std::unique_ptr<HttpFetcher> base_fetcher_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800146
147 // If true, do not send any more data or TransferComplete to the delegate.
148 bool base_fetcher_active_;
149
150 // If true, the next fetcher needs to be started when TransferTerminated is
151 // received from the current fetcher.
152 bool pending_transfer_ended_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700153
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800154 // True if we are waiting for base fetcher to terminate b/c we are
155 // ourselves terminating.
156 bool terminating_;
157
158 RangesVect ranges_;
159
160 RangesVect::size_type current_index_; // index into ranges_
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800161 size_t bytes_received_this_range_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800162
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800163 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800164};
165
166} // namespace chromeos_update_engine
167
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700168#endif // UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_