blob: f4ee9b7a1456fbe0cf4c20be21e8939037a04bbe [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 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
adlr@google.comc98a7ed2009-12-04 18:54:03 +00005#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_H__
rspangler@google.com49fdf182009-10-10 00:57:34 +00007
Andrew de los Reyes45168102010-11-22 11:13:50 -08008#include <deque>
rspangler@google.com49fdf182009-10-10 00:57:34 +00009#include <string>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000010#include <vector>
Andrew de los Reyes45168102010-11-22 11:13:50 -080011
12#include <base/basictypes.h>
13#include <base/logging.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000014#include <glib.h>
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -080015#include <google/protobuf/stubs/common.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080016
17#include "update_engine/proxy_resolver.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000018
19// This class is a simple wrapper around an HTTP library (libcurl). We can
20// easily mock out this interface for testing.
21
22// Implementations of this class should use asynchronous i/o. They can access
23// the glib main loop to request callbacks when timers or file descriptors
24// change.
25
26namespace chromeos_update_engine {
27
28class HttpFetcherDelegate;
29
30class HttpFetcher {
31 public:
Andrew de los Reyes45168102010-11-22 11:13:50 -080032 // |proxy_resolver| is the resolver that will be consulted for proxy
33 // settings. It may be null, in which case direct connections will
34 // be used. Does not take ownership of the resolver.
35 explicit HttpFetcher(ProxyResolver* proxy_resolver)
Darin Petkovcb466212010-08-26 09:40:11 -070036 : post_data_set_(false),
37 http_response_code_(0),
Andrew de los Reyes45168102010-11-22 11:13:50 -080038 delegate_(NULL),
39 proxies_(1, kNoProxy),
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -080040 proxy_resolver_(proxy_resolver),
41 no_resolver_idle_id_(0),
42 callback_(NULL) {}
43 virtual ~HttpFetcher();
Darin Petkovcb466212010-08-26 09:40:11 -070044
45 void set_delegate(HttpFetcherDelegate* delegate) { delegate_ = delegate; }
46 HttpFetcherDelegate* delegate() const { return delegate_; }
47 int http_response_code() const { return http_response_code_; }
rspangler@google.com49fdf182009-10-10 00:57:34 +000048
49 // Optional: Post data to the server. The HttpFetcher should make a copy
50 // of this data and upload it via HTTP POST during the transfer.
Andrew de los Reyes45168102010-11-22 11:13:50 -080051 void SetPostData(const void* data, size_t size);
52
53 // Proxy methods to set the proxies, then to pop them off.
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -080054 // Returns true on success.
55 bool ResolveProxiesForUrl(const std::string& url,
56 google::protobuf::Closure* callback);
Andrew de los Reyes45168102010-11-22 11:13:50 -080057
58 void SetProxies(const std::deque<std::string>& proxies) {
59 proxies_ = proxies;
rspangler@google.com49fdf182009-10-10 00:57:34 +000060 }
Andrew de los Reyes45168102010-11-22 11:13:50 -080061 const std::string& GetCurrentProxy() const {
62 return proxies_.front();
63 }
64 bool HasProxy() const { return !proxies_.empty(); }
65 void PopProxy() { proxies_.pop_front(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +000066
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070067 // Downloading should resume from this offset
68 virtual void SetOffset(off_t offset) = 0;
69
Darin Petkov9ce452b2010-11-17 14:33:28 -080070 // Begins the transfer to the specified URL. This fetcher instance should not
71 // be destroyed until either TransferComplete, or TransferTerminated is
72 // called.
rspangler@google.com49fdf182009-10-10 00:57:34 +000073 virtual void BeginTransfer(const std::string& url) = 0;
74
Darin Petkov9ce452b2010-11-17 14:33:28 -080075 // Aborts the transfer. The transfer may not abort right away -- delegate's
76 // TransferTerminated() will be called when the transfer is actually done.
rspangler@google.com49fdf182009-10-10 00:57:34 +000077 virtual void TerminateTransfer() = 0;
78
79 // If data is coming in too quickly, you can call Pause() to pause the
80 // transfer. The delegate will not have ReceivedBytes() called while
81 // an HttpFetcher is paused.
82 virtual void Pause() = 0;
83
84 // Used to unpause an HttpFetcher and let the bytes stream in again.
85 // If a delegate is set, ReceivedBytes() may be called on it before
86 // Unpause() returns
87 virtual void Unpause() = 0;
88
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070089 // These two function are overloaded in LibcurlHttp fetcher to speed
90 // testing.
91 virtual void set_idle_seconds(int seconds) {}
92 virtual void set_retry_seconds(int seconds) {}
93
Andrew de los Reyes819fef22010-12-17 11:33:58 -080094 ProxyResolver* proxy_resolver() const { return proxy_resolver_; }
95
96 // These are used for testing:
97 virtual void SetConnectionAsExpensive(bool is_expensive) {}
98 virtual void SetBuildType(bool is_official) {}
99
rspangler@google.com49fdf182009-10-10 00:57:34 +0000100 protected:
101 // The URL we're actively fetching from
102 std::string url_;
103
104 // POST data for the transfer, and whether or not it was ever set
105 bool post_data_set_;
106 std::vector<char> post_data_;
107
Darin Petkovcb466212010-08-26 09:40:11 -0700108 // The server's HTTP response code from the last transfer. This
109 // field should be set to 0 when a new transfer is initiated, and
110 // set to the response code when the transfer is complete.
111 int http_response_code_;
112
rspangler@google.com49fdf182009-10-10 00:57:34 +0000113 // The delegate; may be NULL.
114 HttpFetcherDelegate* delegate_;
Andrew de los Reyes45168102010-11-22 11:13:50 -0800115
116 // Proxy servers
117 std::deque<std::string> proxies_;
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800118
Andrew de los Reyes45168102010-11-22 11:13:50 -0800119 ProxyResolver* const proxy_resolver_;
120
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800121 // The ID of the idle callback, used when we have no proxy resolver.
122 guint no_resolver_idle_id_;
123
124 // Callback for when we are resolving proxies
125 google::protobuf::Closure* callback_;
126
rspangler@google.com49fdf182009-10-10 00:57:34 +0000127 private:
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800128 // Callback from the proxy resolver
129 void ProxiesResolved(const std::deque<std::string>& proxies);
130 static void StaticProxiesResolved(const std::deque<std::string>& proxies,
131 void* data) {
132 reinterpret_cast<HttpFetcher*>(data)->ProxiesResolved(proxies);
133 }
134
rspangler@google.com49fdf182009-10-10 00:57:34 +0000135 DISALLOW_COPY_AND_ASSIGN(HttpFetcher);
136};
137
138// Interface for delegates
139class HttpFetcherDelegate {
140 public:
Andrew de los Reyes34e41a12010-10-26 20:07:58 -0700141 // Called every time bytes are received.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000142 virtual void ReceivedBytes(HttpFetcher* fetcher,
143 const char* bytes,
144 int length) = 0;
145
Andrew de los Reyes34e41a12010-10-26 20:07:58 -0700146 // Called if the fetcher seeks to a particular offset.
147 virtual void SeekToOffset(off_t offset) {}
148
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800149 // When a transfer has completed, exactly one of these two methods will be
150 // called. TransferTerminated is called when the transfer has been aborted
151 // through TerminateTransfer. TransferComplete is called in all other
152 // situations. It's OK to destroy the |fetcher| object in this callback.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000153 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) = 0;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800154 virtual void TransferTerminated(HttpFetcher* fetcher) {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000155};
156
157} // namespace chromeos_update_engine
158
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000159#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_H__