blob: 10829ccdd1b82ef97bb4e72f1745ec82f5f48b5b [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)
Andrew de los Reyes819fef22010-12-17 11:33:58 -080037 : 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) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -080044 ~MultiRangeHttpFetcher() {}
Andrew de los Reyes819fef22010-12-17 11:33:58 -080045
46 void ClearRanges() { ranges_.clear(); }
47
Gilad Arnolde4ad2502011-12-29 17:08:54 -080048 void AddRange(off_t offset, size_t size) {
Mike Frysinger0f9547d2012-02-16 12:11:37 -050049 CHECK_GT(size, static_cast<size_t>(0));
Gilad Arnolde4ad2502011-12-29 17:08:54 -080050 ranges_.push_back(Range(offset, size));
51 }
52
53 void AddRange(off_t offset) {
54 ranges_.push_back(Range(offset));
Andrew de los Reyes819fef22010-12-17 11:33:58 -080055 }
56
57 virtual void SetOffset(off_t offset) {} // for now, doesn't support this
58
Gilad Arnolde4ad2502011-12-29 17:08:54 -080059 virtual void SetLength(size_t length) {} // unsupported
60 virtual void UnsetLength() {}
61
Andrew de los Reyes819fef22010-12-17 11:33:58 -080062 // Begins the transfer to the specified URL.
63 // State change: Stopped -> Downloading
64 // (corner case: Stopped -> Stopped for an empty request)
65 virtual void BeginTransfer(const std::string& url);
66
67 // State change: Downloading -> Pending transfer ended
68 virtual void TerminateTransfer();
69
70 virtual void Pause() { base_fetcher_->Pause(); }
71
72 virtual void Unpause() { base_fetcher_->Unpause(); }
73
74 // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
75 virtual void set_idle_seconds(int seconds) {
76 base_fetcher_->set_idle_seconds(seconds);
77 }
78 virtual void set_retry_seconds(int seconds) {
79 base_fetcher_->set_retry_seconds(seconds);
80 }
81 virtual void SetConnectionAsExpensive(bool is_expensive) {
82 base_fetcher_->SetConnectionAsExpensive(is_expensive);
83 }
84 virtual void SetBuildType(bool is_official) {
85 base_fetcher_->SetBuildType(is_official);
86 }
87 virtual void SetProxies(const std::deque<std::string>& proxies) {
88 base_fetcher_->SetProxies(proxies);
89 }
90
Gilad Arnold48085ba2011-11-16 09:36:08 -080091 inline virtual size_t GetBytesDownloaded() {
92 return base_fetcher_->GetBytesDownloaded();
93 }
94
Andrew de los Reyes819fef22010-12-17 11:33:58 -080095 private:
Gilad Arnolde4ad2502011-12-29 17:08:54 -080096 // A range object defining the offset and length of a download chunk. Zero
97 // length indicates an unspecified end offset (note that it is impossible to
98 // request a zero-length range in HTTP).
99 class Range {
100 public:
101 Range(off_t offset, size_t length) : offset_(offset), length_(length) {}
102 Range(off_t offset) : offset_(offset), length_(0) {}
103
104 inline off_t offset() const { return offset_; }
105 inline size_t length() const { return length_; }
106
107 inline bool HasLength() const { return (length_ > 0); }
108
109 std::string ToString() const;
110
111 private:
112 off_t offset_;
113 size_t length_;
114 };
115
116 typedef std::vector<Range> RangesVect;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800117
118 // State change: Stopped or Downloading -> Downloading
119 void StartTransfer();
120
121// State change: Downloading -> Downloading or Pending transfer ended
122 virtual void ReceivedBytes(HttpFetcher* fetcher,
123 const char* bytes,
124 int length);
125
126 // State change: Pending transfer ended -> Stopped
127 void TransferEnded(HttpFetcher* fetcher, bool successful);
128 // These two call TransferEnded():
129 virtual void TransferComplete(HttpFetcher* fetcher, bool successful);
130 virtual void TransferTerminated(HttpFetcher* fetcher);
131
132 void Reset();
133
134 scoped_ptr<HttpFetcher> base_fetcher_;
135
136 // If true, do not send any more data or TransferComplete to the delegate.
137 bool base_fetcher_active_;
138
139 // If true, the next fetcher needs to be started when TransferTerminated is
140 // received from the current fetcher.
141 bool pending_transfer_ended_;
142
143 // True if we are waiting for base fetcher to terminate b/c we are
144 // ourselves terminating.
145 bool terminating_;
146
147 RangesVect ranges_;
148
149 RangesVect::size_type current_index_; // index into ranges_
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800150 size_t bytes_received_this_range_;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800151
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800152 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800153};
154
155} // namespace chromeos_update_engine
156
157#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__