blob: 342588a09619386a4a1bc36645ef6b8b60baf8f7 [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
48 void AddRange(off_t offset, off_t size) {
49 ranges_.push_back(std::make_pair(offset, size));
50 }
51
52 virtual void SetOffset(off_t offset) {} // for now, doesn't support this
53
54 // Begins the transfer to the specified URL.
55 // State change: Stopped -> Downloading
56 // (corner case: Stopped -> Stopped for an empty request)
57 virtual void BeginTransfer(const std::string& url);
58
59 // State change: Downloading -> Pending transfer ended
60 virtual void TerminateTransfer();
61
62 virtual void Pause() { base_fetcher_->Pause(); }
63
64 virtual void Unpause() { base_fetcher_->Unpause(); }
65
66 // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
67 virtual void set_idle_seconds(int seconds) {
68 base_fetcher_->set_idle_seconds(seconds);
69 }
70 virtual void set_retry_seconds(int seconds) {
71 base_fetcher_->set_retry_seconds(seconds);
72 }
73 virtual void SetConnectionAsExpensive(bool is_expensive) {
74 base_fetcher_->SetConnectionAsExpensive(is_expensive);
75 }
76 virtual void SetBuildType(bool is_official) {
77 base_fetcher_->SetBuildType(is_official);
78 }
79 virtual void SetProxies(const std::deque<std::string>& proxies) {
80 base_fetcher_->SetProxies(proxies);
81 }
82
Gilad Arnold48085ba2011-11-16 09:36:08 -080083 inline virtual size_t GetBytesDownloaded() {
84 return base_fetcher_->GetBytesDownloaded();
85 }
86
Andrew de los Reyes819fef22010-12-17 11:33:58 -080087 private:
88 // pair<offset, length>:
89 typedef std::vector<std::pair<off_t, off_t> > RangesVect;
90
91 // State change: Stopped or Downloading -> Downloading
92 void StartTransfer();
93
94// State change: Downloading -> Downloading or Pending transfer ended
95 virtual void ReceivedBytes(HttpFetcher* fetcher,
96 const char* bytes,
97 int length);
98
99 // State change: Pending transfer ended -> Stopped
100 void TransferEnded(HttpFetcher* fetcher, bool successful);
101 // These two call TransferEnded():
102 virtual void TransferComplete(HttpFetcher* fetcher, bool successful);
103 virtual void TransferTerminated(HttpFetcher* fetcher);
104
105 void Reset();
106
107 scoped_ptr<HttpFetcher> base_fetcher_;
108
109 // If true, do not send any more data or TransferComplete to the delegate.
110 bool base_fetcher_active_;
111
112 // If true, the next fetcher needs to be started when TransferTerminated is
113 // received from the current fetcher.
114 bool pending_transfer_ended_;
115
116 // True if we are waiting for base fetcher to terminate b/c we are
117 // ourselves terminating.
118 bool terminating_;
119
120 RangesVect ranges_;
121
122 RangesVect::size_type current_index_; // index into ranges_
123 off_t bytes_received_this_range_;
124
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800125 DISALLOW_COPY_AND_ASSIGN(MultiRangeHttpFetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800126};
127
128} // namespace chromeos_update_engine
129
130#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MULTI_RANGE_HTTP_FETCHER_H__