OLD | NEW |
| (Empty) |
1 // Copyright 2007-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 // | |
17 // HttpClient provides a wrapper for WinHTTP and some helpers to make it | |
18 // easy to call it from c++. | |
19 | |
20 // Runtime requirements: WinHTTP 5.1 is now an operating-system component of | |
21 // the following systems: | |
22 // - Windows Vista | |
23 // - Windows Server 2003 family | |
24 // - Windows XP SP1 | |
25 // - Windows 2000 SP3 (except Datacenter Server) | |
26 // | |
27 // TODO(omaha): fix prototype of several methods to take size_t instead of int | |
28 // TODO(omaha): there are many overloads that do not have to be virtual. | |
29 // TODO(omaha): in the end HttpClient is just a c++ wrapper for WinHttp. Some | |
30 // refactoring may be needed, for example to provide access to | |
31 // the internal session and connection handles. It may make sense | |
32 // to reuse these handles, most likely the session handle. | |
33 // TODO(omaha): the idea of implementing the winhttp interface on top of | |
34 // wininet seems impractical now, as they may be subtle | |
35 // differences in behavior. The fallback on wininet when winhttp | |
36 // is not available could be better done by using the higher | |
37 // level urlmon functions, which perhaps we should do anyway, | |
38 // just in case winhttp is not working for some reason or bug. | |
39 // Since now we are not doing downloads in any of our long lived | |
40 // processes, the handle and memory leaks do not affect us much. | |
41 | |
42 #ifndef OMAHA_NET_HTTP_CLIENT_H__ | |
43 #define OMAHA_NET_HTTP_CLIENT_H__ | |
44 | |
45 #include <windows.h> | |
46 #include <atlstr.h> | |
47 | |
48 #if !defined(_WININET_) | |
49 #include <winhttp.h> // NOLINT | |
50 | |
51 // The following definitions are missing in winhttp.h | |
52 #define INTERNET_MAX_HOST_NAME_LENGTH 256 | |
53 #define INTERNET_MAX_USER_NAME_LENGTH 128 | |
54 #define INTERNET_MAX_PASSWORD_LENGTH 128 | |
55 #define INTERNET_MAX_PORT_NUMBER_LENGTH 5 | |
56 #define INTERNET_MAX_PORT_NUMBER_VALUE 65535 | |
57 #define INTERNET_MAX_PATH_LENGTH 2048 | |
58 #define INTERNET_MAX_SCHEME_LENGTH 32 | |
59 #define INTERNET_MAX_URL_LENGTH (INTERNET_MAX_SCHEME_LENGTH \ | |
60 + sizeof("://") \ | |
61 + INTERNET_MAX_PATH_LENGTH) | |
62 #endif | |
63 | |
64 // This is a definition we made up for convenience, just to be consistent with | |
65 // the other types of network access. | |
66 #define WINHTTP_ACCESS_TYPE_AUTO_DETECT 2 | |
67 | |
68 #include "base/basictypes.h" | |
69 #include "omaha/base/object_factory.h" | |
70 | |
71 namespace omaha { | |
72 | |
73 const TCHAR* const kHttpGetMethod = _T("GET"); | |
74 const TCHAR* const kHttpPostMethod = _T("POST"); | |
75 const TCHAR* const kHttpContentLengthHeader = _T("Content-Length"); | |
76 const TCHAR* const kHttpContentTypeHeader = _T("Content-Type"); | |
77 const TCHAR* const kHttpLastModifiedHeader = _T("Last-Modified"); | |
78 const TCHAR* const kHttpIfModifiedSinceHeader = _T("If-Modified-Since"); | |
79 const TCHAR* const kHttpPostTextContentType = | |
80 _T("application/x-www-form-urlencoded"); | |
81 const TCHAR* const kHttpPostRawContentType = _T("application/octet-stream"); | |
82 const TCHAR* const kHttpBinaryContentType =_T("binary"); | |
83 const TCHAR* const kHttpXmlContentType =_T("application/xml"); | |
84 | |
85 class HttpClient { | |
86 public: | |
87 enum HttpStack {WINHTTP, WININET}; | |
88 | |
89 // Use registry for network configuration info. | |
90 static const int kAccessTypeDefaultProxy = 0; | |
91 // Unconditional direct connection. | |
92 static const int kAccessTypeNoProxy = 1; | |
93 // Use the specified proxy server. | |
94 static const int kAccessTypeNamedProxy = 3; | |
95 | |
96 // GetFactory and DeleteFactory methods below are not thread safe. | |
97 // The caller must initialize and cleanup the factory before going | |
98 // multithreaded. | |
99 // | |
100 // Gets the singleton instance of the object factory. | |
101 typedef Factory<HttpClient, HttpStack> Factory; | |
102 static Factory& GetFactory(); | |
103 | |
104 // Cleans up the object factory. | |
105 static void DeleteFactory(); | |
106 | |
107 struct ProxyInfo { | |
108 uint32 access_type; | |
109 const TCHAR* proxy; | |
110 const TCHAR* proxy_bypass; | |
111 }; | |
112 | |
113 struct CurrentUserIEProxyConfig { | |
114 bool auto_detect; | |
115 const TCHAR* auto_config_url; | |
116 const TCHAR* proxy; | |
117 const TCHAR* proxy_bypass; | |
118 }; | |
119 | |
120 struct AutoProxyOptions { | |
121 uint32 flags; | |
122 uint32 auto_detect_flags; | |
123 const TCHAR* auto_config_url; | |
124 bool auto_logon_if_challenged; | |
125 }; | |
126 | |
127 virtual ~HttpClient() {} | |
128 | |
129 // Initializes the use of http functions by loading the corresponding http | |
130 // stack. | |
131 virtual HRESULT Initialize() = 0; | |
132 | |
133 // Adds one or more http request headers to the http request. | |
134 virtual HRESULT AddRequestHeaders(HINTERNET request, | |
135 const TCHAR* headers, | |
136 int length, | |
137 uint32 modifiers) = 0; | |
138 | |
139 // Determines whether WinHTTP is available. | |
140 virtual HRESULT CheckPlatform() = 0; | |
141 | |
142 // Closes an http handle. | |
143 virtual HRESULT Close(HINTERNET handle) = 0; | |
144 | |
145 // Specifies the initial server and port of an http request. | |
146 virtual HRESULT Connect(HINTERNET session_handle, | |
147 const TCHAR* server, | |
148 int port, | |
149 HINTERNET* connection_handle) = 0; | |
150 | |
151 // Breaks urls into component parts. | |
152 virtual HRESULT CrackUrl(const TCHAR* url, | |
153 uint32 flags, | |
154 CString* scheme, | |
155 CString* server, | |
156 int* port, | |
157 CString* url_path, | |
158 CString* extra_info) = 0; | |
159 | |
160 // Builds a url from component parts. | |
161 virtual HRESULT CreateUrl(const TCHAR* scheme, | |
162 const TCHAR* server, | |
163 int port, | |
164 const TCHAR* url_path, | |
165 const TCHAR* extra_info, | |
166 uint32 flags, | |
167 CString* url) = 0; | |
168 | |
169 | |
170 // Finds the url for the proxy auto-configuration (PAC) file. | |
171 // It reports the url of the PAC file but it does not download the file. | |
172 virtual HRESULT DetectAutoProxyConfigUrl(uint32 flags, | |
173 CString* auto_config_url) = 0; | |
174 | |
175 // Gets the proxy configuration from the registry. | |
176 virtual HRESULT GetDefaultProxyConfiguration(ProxyInfo* proxy_info) = 0; | |
177 | |
178 // Gets the Internet Explorer configuration for the current user. | |
179 virtual HRESULT GetIEProxyConfiguration( | |
180 CurrentUserIEProxyConfig* proxy_info) = 0; | |
181 | |
182 // Gets the proxy information for an url. This function implements the | |
183 // web proxy auto-discovery (WPAD) protocol for automatically configuring | |
184 // the proxy settings for an http request. The WPAD protocol downloads a | |
185 // proxy auto-configuration (PAC) file, which is a script that identifies | |
186 // the proxy server to use for a given target url. | |
187 virtual HRESULT GetProxyForUrl(HINTERNET session_handle, | |
188 const TCHAR* url, | |
189 const AutoProxyOptions* auto_proxy_options, | |
190 ProxyInfo* proxy_info) = 0; | |
191 | |
192 // Opens a new http session. The http session contains user specific state | |
193 // such as cookies, proxy, and authentication credentials. | |
194 virtual HRESULT Open(const TCHAR* user_agent, | |
195 uint32 access_type, | |
196 const TCHAR* proxy_name, | |
197 const TCHAR* proxy_bypass, | |
198 DWORD flags, | |
199 HINTERNET* session_handle) = 0; | |
200 | |
201 // Specifies the http request. | |
202 virtual HRESULT OpenRequest(HINTERNET connection_handle, | |
203 const TCHAR* verb, | |
204 const TCHAR* uri, | |
205 const TCHAR* version, | |
206 const TCHAR* referrer, | |
207 const TCHAR** accept_types, | |
208 uint32 flags, | |
209 HINTERNET* request_handle) = 0; | |
210 | |
211 // Returns the authorization schemes that are supported by the server or | |
212 // the proxy server. | |
213 virtual HRESULT QueryAuthSchemes(HINTERNET request_handle, | |
214 uint32* supported_schemes, | |
215 uint32* first_scheme, | |
216 uint32* auth_target) = 0; | |
217 | |
218 // Returns the amount of data, in bytes, available to be read. | |
219 virtual HRESULT QueryDataAvailable(HINTERNET request_handle, | |
220 DWORD* num_bytes) = 0; | |
221 | |
222 // Retrieves header information associated with the request. | |
223 virtual HRESULT QueryHeaders(HINTERNET request_handle, | |
224 uint32 info_level, | |
225 const TCHAR* name, | |
226 void* buffer, | |
227 DWORD* buffer_length, | |
228 DWORD* index) = 0; | |
229 | |
230 // Queries an internet option. | |
231 virtual HRESULT QueryOption(HINTERNET handle, | |
232 uint32 option, | |
233 void* buffer, | |
234 DWORD* buffer_length) = 0; | |
235 | |
236 // Reads response data. | |
237 virtual HRESULT ReadData(HINTERNET request_handle, | |
238 void* buffer, | |
239 DWORD buffer_length, | |
240 DWORD* bytes_read) = 0; | |
241 | |
242 // Waits to receive the response to an HTTP request. When ReceiveResponse | |
243 // completes successfully, the status code and response headers have been | |
244 // received. | |
245 virtual HRESULT ReceiveResponse(HINTERNET request_handle) = 0; | |
246 | |
247 // Sends the request to the server. It also allows to send optional data | |
248 // for POST requests. | |
249 virtual HRESULT SendRequest(HINTERNET request_handle, | |
250 const TCHAR* headers, | |
251 DWORD headers_length, | |
252 const void* optional_data, | |
253 DWORD optional_data_length, | |
254 DWORD content_length, | |
255 DWORD_PTR context) = 0; | |
256 | |
257 // Sets the authentication credentials. | |
258 virtual HRESULT SetCredentials(HINTERNET request_handle, | |
259 uint32 auth_targets, | |
260 uint32 auth_scheme, | |
261 const TCHAR* user_name, | |
262 const TCHAR* password) = 0; | |
263 | |
264 // Sets the proxy configuration in registry. | |
265 virtual HRESULT SetDefaultProxyConfiguration(const ProxyInfo& proxy_info) = 0; | |
266 | |
267 // Sets an internet option, either for the session or the request handle. | |
268 virtual HRESULT SetOption(HINTERNET handle, | |
269 uint32 option, | |
270 const void* buffer, | |
271 DWORD buffer_length) = 0; | |
272 | |
273 typedef void (__stdcall *StatusCallback)(HINTERNET handle, | |
274 uint32 context, | |
275 uint32 status, | |
276 void* status_information, | |
277 size_t status_info_length); | |
278 virtual StatusCallback SetStatusCallback(HINTERNET handle, | |
279 StatusCallback callback, | |
280 uint32 flags) = 0; | |
281 | |
282 // Sets timeout values for this http request. | |
283 virtual HRESULT SetTimeouts(HINTERNET handle, | |
284 int resolve_timeout_ms, | |
285 int connect_timeout_ms, | |
286 int send_timeout_ms, | |
287 int receive_timeout_ms) = 0; | |
288 | |
289 // Writes data to the server. | |
290 virtual HRESULT WriteData(HINTERNET request_handle, | |
291 const void* buffer, | |
292 DWORD bytes_to_write, | |
293 DWORD* bytes_written) = 0; | |
294 | |
295 // | |
296 // Http helpers. | |
297 // | |
298 // Builds one http header entry, with the following format: | |
299 // name: value\r\n | |
300 static CString BuildRequestHeader(const TCHAR* name, const TCHAR* value); | |
301 | |
302 enum StatusCodeClass { | |
303 STATUS_CODE_NOCODE = 0, | |
304 STATUS_CODE_INFORMATIONAL = 100, | |
305 STATUS_CODE_SUCCESSFUL = 200, | |
306 STATUS_CODE_REDIRECTION = 300, | |
307 STATUS_CODE_CLIENT_ERROR = 400, | |
308 STATUS_CODE_SERVER_ERROR = 500 | |
309 }; | |
310 // Returns the class of a status code, such as 100, 200... | |
311 static StatusCodeClass GetStatusCodeClass(int status_code); | |
312 | |
313 HRESULT QueryHeadersString(HINTERNET request_handle, | |
314 uint32 info_level, | |
315 const TCHAR* name, | |
316 CString* value, | |
317 DWORD* index); | |
318 HRESULT QueryHeadersInt(HINTERNET request_handle, | |
319 uint32 info_level, | |
320 const TCHAR* name, | |
321 int* value, | |
322 DWORD* index); | |
323 | |
324 HRESULT QueryOptionString(HINTERNET handle, uint32 option, CString* value); | |
325 HRESULT QueryOptionInt(HINTERNET handle, uint32 option, int* value); | |
326 | |
327 HRESULT SetOptionString(HINTERNET handle, uint32 option, const TCHAR* value); | |
328 HRESULT SetOptionInt(HINTERNET handle, uint32 option, int value); | |
329 | |
330 protected: | |
331 HttpClient() {} | |
332 | |
333 private: | |
334 static Factory* factory_; | |
335 DISALLOW_EVIL_CONSTRUCTORS(HttpClient); | |
336 }; | |
337 | |
338 // Creates an http client, depending on what is available on the platform. | |
339 // WinHttp is preferred over WinInet. | |
340 HttpClient* CreateHttpClient(); | |
341 | |
342 const HttpClient::StatusCallback kInvalidStatusCallback = | |
343 reinterpret_cast<HttpClient::StatusCallback>( | |
344 WINHTTP_INVALID_STATUS_CALLBACK); | |
345 | |
346 } // namespace omaha | |
347 | |
348 #endif // OMAHA_NET_HTTP_CLIENT_H__ | |
349 | |
OLD | NEW |