1/* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#ifndef WEBRTC_BASE_HTTPCLIENT_H__ 12#define WEBRTC_BASE_HTTPCLIENT_H__ 13 14#include "webrtc/base/common.h" 15#include "webrtc/base/httpbase.h" 16#include "webrtc/base/nethelpers.h" 17#include "webrtc/base/proxyinfo.h" 18#include "webrtc/base/scoped_ptr.h" 19#include "webrtc/base/sigslot.h" 20#include "webrtc/base/socketaddress.h" 21#include "webrtc/base/socketpool.h" 22 23namespace rtc { 24 25////////////////////////////////////////////////////////////////////// 26// Client-specific http utilities 27////////////////////////////////////////////////////////////////////// 28 29// Write cache-relevant response headers to output stream. If size is non-null, 30// it contains the length of the output in bytes. output may be null if only 31// the length is desired. 32bool HttpWriteCacheHeaders(const HttpResponseData* response, 33 StreamInterface* output, size_t* size); 34// Read cached headers from a stream, and them merge them into the response 35// object using the specified combine operation. 36bool HttpReadCacheHeaders(StreamInterface* input, 37 HttpResponseData* response, 38 HttpData::HeaderCombine combine); 39 40////////////////////////////////////////////////////////////////////// 41// HttpClient 42// Implements an HTTP 1.1 client. 43////////////////////////////////////////////////////////////////////// 44 45class DiskCache; 46class HttpClient; 47class IPNetPool; 48 49class SignalThread; 50// What to do: Define STRICT_HTTP_ERROR=1 in your makefile. Use HttpError in 51// your code (HttpErrorType should only be used for code that is shared 52// with groups which have not yet migrated). 53#if STRICT_HTTP_ERROR 54typedef HttpError HttpErrorType; 55#else // !STRICT_HTTP_ERROR 56typedef int HttpErrorType; 57#endif // !STRICT_HTTP_ERROR 58 59class HttpClient : private IHttpNotify, public sigslot::has_slots<> { 60public: 61 // If HttpRequestData and HttpResponseData objects are provided, they must 62 // be freed by the caller. Otherwise, an internal object is allocated. 63 HttpClient(const std::string& agent, StreamPool* pool, 64 HttpTransaction* transaction = NULL); 65 ~HttpClient() override; 66 67 void set_pool(StreamPool* pool) { pool_ = pool; } 68 69 void set_agent(const std::string& agent) { agent_ = agent; } 70 const std::string& agent() const { return agent_; } 71 72 void set_proxy(const ProxyInfo& proxy) { proxy_ = proxy; } 73 const ProxyInfo& proxy() const { return proxy_; } 74 75 // Request retries occur when the connection closes before the beginning of 76 // an http response is received. In these cases, the http server may have 77 // timed out the keepalive connection before it received our request. Note 78 // that if a request document cannot be rewound, no retry is made. The 79 // default is 1. 80 void set_request_retries(size_t retries) { retries_ = retries; } 81 size_t request_retries() const { return retries_; } 82 83 enum RedirectAction { REDIRECT_DEFAULT, REDIRECT_ALWAYS, REDIRECT_NEVER }; 84 void set_redirect_action(RedirectAction action) { redirect_action_ = action; } 85 RedirectAction redirect_action() const { return redirect_action_; } 86 87 enum UriForm { URI_DEFAULT, URI_ABSOLUTE, URI_RELATIVE }; 88 void set_uri_form(UriForm form) { uri_form_ = form; } 89 UriForm uri_form() const { return uri_form_; } 90 91 void set_cache(DiskCache* cache) { ASSERT(!IsCacheActive()); cache_ = cache; } 92 bool cache_enabled() const { return (NULL != cache_); } 93 94 // reset clears the server, request, and response structures. It will also 95 // abort an active request. 96 void reset(); 97 98 void set_server(const SocketAddress& address); 99 const SocketAddress& server() const { return server_; } 100 101 // Note: in order for HttpClient to retry a POST in response to 102 // an authentication challenge, a redirect response, or socket disconnection, 103 // the request document must support 'replaying' by calling Rewind() on it. 104 HttpTransaction* transaction() { return transaction_; } 105 const HttpTransaction* transaction() const { return transaction_; } 106 HttpRequestData& request() { return transaction_->request; } 107 const HttpRequestData& request() const { return transaction_->request; } 108 HttpResponseData& response() { return transaction_->response; } 109 const HttpResponseData& response() const { return transaction_->response; } 110 111 // convenience methods 112 void prepare_get(const std::string& url); 113 void prepare_post(const std::string& url, const std::string& content_type, 114 StreamInterface* request_doc); 115 116 // Convert HttpClient to a pull-based I/O model. 117 StreamInterface* GetDocumentStream(); 118 119 // After you finish setting up your request, call start. 120 void start(); 121 122 // Signalled when the header has finished downloading, before the document 123 // content is processed. You may change the response document in response 124 // to this signal. The second parameter indicates whether this is an 125 // intermediate (false) or final (true) header. An intermediate header is 126 // one that generates another request, such as a redirect or authentication 127 // challenge. The third parameter indicates the length of the response 128 // document, or else SIZE_UNKNOWN. Note: Do NOT abort the request in response 129 // to this signal. 130 sigslot::signal3<HttpClient*,bool,size_t> SignalHeaderAvailable; 131 // Signalled when the current request finishes. On success, err is 0. 132 sigslot::signal2<HttpClient*,HttpErrorType> SignalHttpClientComplete; 133 134protected: 135 void connect(); 136 void release(); 137 138 bool ShouldRedirect(std::string* location) const; 139 140 bool BeginCacheFile(); 141 HttpError WriteCacheHeaders(const std::string& id); 142 void CompleteCacheFile(); 143 144 bool CheckCache(); 145 HttpError ReadCacheHeaders(const std::string& id, bool override); 146 HttpError ReadCacheBody(const std::string& id); 147 148 bool PrepareValidate(); 149 HttpError CompleteValidate(); 150 151 HttpError OnHeaderAvailable(bool ignore_data, bool chunked, size_t data_size); 152 153 void StartDNSLookup(); 154 void OnResolveResult(AsyncResolverInterface* resolver); 155 156 // IHttpNotify Interface 157 HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) override; 158 void onHttpComplete(HttpMode mode, HttpError err) override; 159 void onHttpClosed(HttpError err) override; 160 161private: 162 enum CacheState { CS_READY, CS_WRITING, CS_READING, CS_VALIDATING }; 163 bool IsCacheActive() const { return (cache_state_ > CS_READY); } 164 165 std::string agent_; 166 StreamPool* pool_; 167 HttpBase base_; 168 SocketAddress server_; 169 ProxyInfo proxy_; 170 HttpTransaction* transaction_; 171 bool free_transaction_; 172 size_t retries_, attempt_, redirects_; 173 RedirectAction redirect_action_; 174 UriForm uri_form_; 175 scoped_ptr<HttpAuthContext> context_; 176 DiskCache* cache_; 177 CacheState cache_state_; 178 AsyncResolverInterface* resolver_; 179}; 180 181////////////////////////////////////////////////////////////////////// 182// HttpClientDefault - Default implementation of HttpClient 183////////////////////////////////////////////////////////////////////// 184 185class HttpClientDefault : public ReuseSocketPool, public HttpClient { 186public: 187 HttpClientDefault(SocketFactory* factory, const std::string& agent, 188 HttpTransaction* transaction = NULL); 189}; 190 191////////////////////////////////////////////////////////////////////// 192 193} // namespace rtc 194 195#endif // WEBRTC_BASE_HTTPCLIENT_H__ 196