| 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 |