blob: 800c7fd04c9682324db25693c4cef6dce805cfe9 [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
Alex Deymo759c2752014-03-17 21:09:36 -07005#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_
Andrew de los Reyes819fef22010-12-17 11:33:58 -08007
8#include <deque>
Alex Vakulenkod2779df2014-06-16 13:19:00 -07009#include <string>
Andrew de los Reyes819fef22010-12-17 11:33:58 -080010#include <utility>
11#include <vector>
12
Chris Masoned903c3b2011-05-12 15:35:46 -070013#include <base/memory/scoped_ptr.h>
Andrew de los Reyes819fef22010-12-17 11:33:58 -080014
15#include "update_engine/http_fetcher.h"
16
17// This class is a simple wrapper around an HttpFetcher. The client
Gilad Arnold9bedeb52011-11-17 16:19:57 -080018// specifies a vector of byte ranges. MultiRangeHttpFetcher will fetch bytes
Andrew de los Reyes819fef22010-12-17 11:33:58 -080019// from those offsets, using the same bash fetcher for all ranges. Thus, the
20// fetcher must support beginning a transfter after one has stopped. Pass -1
21// as a length to specify unlimited length. It really only would make sense
22// for the last range specified to have unlimited length, tho it is legal for
23// other entries to have unlimited length.
24
Gilad Arnold9bedeb52011-11-17 16:19:57 -080025// There are three states a MultiRangeHttpFetcher object will be in:
Andrew de los Reyes819fef22010-12-17 11:33:58 -080026// - Stopped (start state)
27// - Downloading
28// - Pending transfer ended
29// Various functions below that might change state indicate possible
30// state changes.
31
32namespace chromeos_update_engine {
33
Gilad Arnold9bedeb52011-11-17 16:19:57 -080034class MultiRangeHttpFetcher : public HttpFetcher, public HttpFetcherDelegate {
Andrew de los Reyes819fef22010-12-17 11:33:58 -080035 public:
36 // Takes ownership of the passed in fetcher.
Gilad Arnold9bedeb52011-11-17 16:19:57 -080037 explicit MultiRangeHttpFetcher(HttpFetcher* base_fetcher)
Jay Srinivasan43488792012-06-19 00:25:31 -070038 : HttpFetcher(base_fetcher->proxy_resolver(),
39 base_fetcher->GetSystemState()),
Andrew de los Reyes819fef22010-12-17 11:33:58 -080040 base_fetcher_(base_fetcher),
41 base_fetcher_active_(false),
42 pending_transfer_ended_(false),
43 terminating_(false),
44 current_index_(0),
45 bytes_received_this_range_(0) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -080046 ~MultiRangeHttpFetcher() {}
Andrew de los Reyes819fef22010-12-17 11:33:58 -080047
48 void ClearRanges() { ranges_.clear(); }
49
Gilad Arnolde4ad2502011-12-29 17:08:54 -080050 void AddRange(off_t offset, size_t size) {
Mike Frysinger0f9547d2012-02-16 12:11:37 -050051 CHECK_GT(size, static_cast<size_t>(0));
Gilad Arnolde4ad2502011-12-29 17:08:54 -080052 ranges_.push_back(Range(offset, size));
53 }
54
55 void AddRange(off_t offset) {
56 ranges_.push_back(Range(offset));
Andrew de los Reyes819fef22010-12-17 11:33:58 -080057 }
58
59 virtual void SetOffset(off_t offset) {} // for now, doesn't support this
60
Gilad Arnolde4ad2502011-12-29 17:08:54 -080061 virtual void SetLength(size_t length) {} // unsupported
62 virtual void UnsetLength() {}
63
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)
67 virtual void BeginTransfer(const std::string& url);
68
69 // State change: Downloading -> Pending transfer ended
70 virtual void TerminateTransfer();
71
72 virtual void Pause() { base_fetcher_->Pause(); }
73
74 virtual void Unpause() { base_fetcher_->Unpause(); }
75
76 // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
77 virtual void set_idle_seconds(int seconds) {
78 base_fetcher_->set_idle_seconds(seconds);
79 }
80 virtual void set_retry_seconds(int seconds) {
81 base_fetcher_->set_retry_seconds(seconds);
82 }
Andrew de los Reyes819fef22010-12-17 11:33:58 -080083 virtual void SetProxies(const std::deque<std::string>& proxies) {
84 base_fetcher_->SetProxies(proxies);
85 }
86
Gilad Arnold48085ba2011-11-16 09:36:08 -080087 inline virtual size_t GetBytesDownloaded() {
88 return base_fetcher_->GetBytesDownloaded();
89 }
90
David Zeuthen34135a92013-08-06 11:16:16 -070091 virtual void set_low_speed_limit(int low_speed_bps, int low_speed_sec) {
92 base_fetcher_->set_low_speed_limit(low_speed_bps, low_speed_sec);
93 }
94
95 virtual void set_connect_timeout(int connect_timeout_seconds) {
96 base_fetcher_->set_connect_timeout(connect_timeout_seconds);
97 }
98
99 virtual void set_max_retry_count(int max_retry_count) {
100 base_fetcher_->set_max_retry_count(max_retry_count);
101 }
102
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800103 private:
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800104 // A range object defining the offset and length of a download chunk. Zero
105 // length indicates an unspecified end offset (note that it is impossible to
106 // request a zero-length range in HTTP).
107 class Range {
108 public:
109 Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700110 explicit Range(off_t offset) : offset_(offset), length_(0) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800111
112 inline off_t offset() const { return offset_; }
113 inline size_t length() const { return length_; }
114
115 inline bool HasLength() const { return (length_ > 0); }
116
117 std::string ToString() const;
118
119 private:
120 off_t offset_;
121 size_t length_;
122 };
123
124 typedef std::vector<Range> RangesVect;
Jay Srinivasan43488792012-06-19 00:25:31 -0700125
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800126 // State change: Stopped or Downloading -> Downloading
127 void StartTransfer();
128
Jay Srinivasan43488792012-06-19 00:25:31 -0700129 // State change: Downloading -> Downloading or Pending transfer ended
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800130 virtual void ReceivedBytes(HttpFetcher* fetcher,
131 const char* bytes,
132 int length);
133
134 // State change: Pending transfer ended -> Stopped
135 void TransferEnded(HttpFetcher* fetcher, bool successful);
136 // These two call TransferEnded():
137 virtual void TransferComplete(HttpFetcher* fetcher, bool successful);
138 virtual void TransferTerminated(HttpFetcher* fetcher);
139
140 void Reset();
141
142 scoped_ptr<HttpFetcher> base_fetcher_;
143
144 // If true, do not send any more data or TransferComplete to the delegate.
145 bool base_fetcher_active_;
146
147 // If true, the next fetcher needs to be started when TransferTerminated is
148 // received from the current fetcher.
149 bool pending_transfer_ended_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700150
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800151 // True if we are waiting for base fetcher to terminate b/c we are
152 // ourselves terminating.
153 bool terminating_;
154
155 RangesVect ranges_;
156
157 RangesVect::size_type current_index_; // index into ranges_
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800158 size_t bytes_received_this_range_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800159
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800160 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800161};
162
163} // namespace chromeos_update_engine
164
Alex Deymo759c2752014-03-17 21:09:36 -0700165#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H_