blob: ae25f45b3ceb250094835ebb25df730382b07e57 [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) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -080045 ~MultiRangeHttpFetcher() {}
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
58 virtual void SetOffset(off_t offset) {} // for now, doesn't support this
59
Gilad Arnolde4ad2502011-12-29 17:08:54 -080060 virtual void SetLength(size_t length) {} // unsupported
61 virtual void UnsetLength() {}
62
Andrew de los Reyes819fef22010-12-17 11:33:58 -080063 // Begins the transfer to the specified URL.
64 // State change: Stopped -> Downloading
65 // (corner case: Stopped -> Stopped for an empty request)
66 virtual void BeginTransfer(const std::string& url);
67
68 // State change: Downloading -> Pending transfer ended
69 virtual void TerminateTransfer();
70
71 virtual void Pause() { base_fetcher_->Pause(); }
72
73 virtual void Unpause() { base_fetcher_->Unpause(); }
74
75 // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
76 virtual void set_idle_seconds(int seconds) {
77 base_fetcher_->set_idle_seconds(seconds);
78 }
79 virtual void set_retry_seconds(int seconds) {
80 base_fetcher_->set_retry_seconds(seconds);
81 }
Andrew de los Reyes819fef22010-12-17 11:33:58 -080082 virtual void SetProxies(const std::deque<std::string>& proxies) {
83 base_fetcher_->SetProxies(proxies);
84 }
85
Gilad Arnold48085ba2011-11-16 09:36:08 -080086 inline virtual size_t GetBytesDownloaded() {
87 return base_fetcher_->GetBytesDownloaded();
88 }
89
David Zeuthen34135a92013-08-06 11:16:16 -070090 virtual void set_low_speed_limit(int low_speed_bps, int low_speed_sec) {
91 base_fetcher_->set_low_speed_limit(low_speed_bps, low_speed_sec);
92 }
93
94 virtual void set_connect_timeout(int connect_timeout_seconds) {
95 base_fetcher_->set_connect_timeout(connect_timeout_seconds);
96 }
97
98 virtual void set_max_retry_count(int max_retry_count) {
99 base_fetcher_->set_max_retry_count(max_retry_count);
100 }
101
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800102 private:
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800103 // A range object defining the offset and length of a download chunk. Zero
104 // length indicates an unspecified end offset (note that it is impossible to
105 // request a zero-length range in HTTP).
106 class Range {
107 public:
108 Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700109 explicit Range(off_t offset) : offset_(offset), length_(0) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800110
111 inline off_t offset() const { return offset_; }
112 inline size_t length() const { return length_; }
113
114 inline bool HasLength() const { return (length_ > 0); }
115
116 std::string ToString() const;
117
118 private:
119 off_t offset_;
120 size_t length_;
121 };
122
123 typedef std::vector<Range> RangesVect;
Jay Srinivasan43488792012-06-19 00:25:31 -0700124
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800125 // State change: Stopped or Downloading -> Downloading
126 void StartTransfer();
127
Jay Srinivasan43488792012-06-19 00:25:31 -0700128 // State change: Downloading -> Downloading or Pending transfer ended
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800129 virtual void ReceivedBytes(HttpFetcher* fetcher,
130 const char* bytes,
131 int length);
132
133 // State change: Pending transfer ended -> Stopped
134 void TransferEnded(HttpFetcher* fetcher, bool successful);
135 // These two call TransferEnded():
136 virtual void TransferComplete(HttpFetcher* fetcher, bool successful);
137 virtual void TransferTerminated(HttpFetcher* fetcher);
138
139 void Reset();
140
Ben Chan02f7c1d2014-10-18 15:18:02 -0700141 std::unique_ptr<HttpFetcher> base_fetcher_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800142
143 // If true, do not send any more data or TransferComplete to the delegate.
144 bool base_fetcher_active_;
145
146 // If true, the next fetcher needs to be started when TransferTerminated is
147 // received from the current fetcher.
148 bool pending_transfer_ended_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700149
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800150 // True if we are waiting for base fetcher to terminate b/c we are
151 // ourselves terminating.
152 bool terminating_;
153
154 RangesVect ranges_;
155
156 RangesVect::size_type current_index_; // index into ranges_
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800157 size_t bytes_received_this_range_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800158
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800159 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800160};
161
162} // namespace chromeos_update_engine
163
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700164#endif // UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_