blob: 5251bfe69e65d0e552c0a1c0993d2e3c899c64a2 [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
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 Masoned903c3b2011-05-12 15:35:46 -070012#include <base/memory/scoped_ptr.h>
Andrew de los Reyes819fef22010-12-17 11:33:58 -080013
14#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
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
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 SetBuildType(bool is_official) {
83 base_fetcher_->SetBuildType(is_official);
84 }
85 virtual void SetProxies(const std::deque<std::string>& proxies) {
86 base_fetcher_->SetProxies(proxies);
87 }
88
Gilad Arnold48085ba2011-11-16 09:36:08 -080089 inline virtual size_t GetBytesDownloaded() {
90 return base_fetcher_->GetBytesDownloaded();
91 }
92
Andrew de los Reyes819fef22010-12-17 11:33:58 -080093 private:
Gilad Arnolde4ad2502011-12-29 17:08:54 -080094 // A range object defining the offset and length of a download chunk. Zero
95 // length indicates an unspecified end offset (note that it is impossible to
96 // request a zero-length range in HTTP).
97 class Range {
98 public:
99 Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
100 Range(off_t offset) : offset_(offset), length_(0) {}
101
102 inline off_t offset() const { return offset_; }
103 inline size_t length() const { return length_; }
104
105 inline bool HasLength() const { return (length_ > 0); }
106
107 std::string ToString() const;
108
109 private:
110 off_t offset_;
111 size_t length_;
112 };
113
114 typedef std::vector<Range> RangesVect;
Jay Srinivasan43488792012-06-19 00:25:31 -0700115
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800116 // State change: Stopped or Downloading -> Downloading
117 void StartTransfer();
118
Jay Srinivasan43488792012-06-19 00:25:31 -0700119 // State change: Downloading -> Downloading or Pending transfer ended
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800120 virtual void ReceivedBytes(HttpFetcher* fetcher,
121 const char* bytes,
122 int length);
123
124 // State change: Pending transfer ended -> Stopped
125 void TransferEnded(HttpFetcher* fetcher, bool successful);
126 // These two call TransferEnded():
127 virtual void TransferComplete(HttpFetcher* fetcher, bool successful);
128 virtual void TransferTerminated(HttpFetcher* fetcher);
129
130 void Reset();
131
132 scoped_ptr<HttpFetcher> base_fetcher_;
133
134 // If true, do not send any more data or TransferComplete to the delegate.
135 bool base_fetcher_active_;
136
137 // If true, the next fetcher needs to be started when TransferTerminated is
138 // received from the current fetcher.
139 bool pending_transfer_ended_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700140
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800141 // True if we are waiting for base fetcher to terminate b/c we are
142 // ourselves terminating.
143 bool terminating_;
144
145 RangesVect ranges_;
146
147 RangesVect::size_type current_index_; // index into ranges_
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800148 size_t bytes_received_this_range_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800149
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800150 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800151};
152
153} // namespace chromeos_update_engine
154
155#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__