[GTK][WPE] Fix non-unified builds after r250857
[WebKit-https.git] / Source / WebCore / platform / network / curl / CurlContext.h
1 /*
2  * Copyright (C) 2013 Apple Inc.  All rights reserved.
3  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "CurlProxySettings.h"
30 #include "CurlSSLHandle.h"
31
32 #include <wtf/Lock.h>
33 #include <wtf/NeverDestroyed.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Seconds.h>
36 #include <wtf/Threading.h>
37 #include <wtf/URL.h>
38
39 #if OS(WINDOWS)
40 #include <windows.h>
41 #include <winsock2.h>
42 #endif
43
44 #include <curl/curl.h>
45
46 namespace WebCore {
47
48 // Values taken from http://www.browserscope.org/ following
49 // the rule "Do What Every Other Modern Browser Is Doing".
50 const long CurlDefaultMaxConnects { -1 }; // -1 : Does not set CURLMOPT_MAXCONNECTS
51 const long CurlDefaultMaxTotalConnections { 17 };
52 const long CurlDefaultMaxHostConnections { 6 };
53
54 // CurlGlobal --------------------------------------------
55 // to make the initialization of libcurl happen before other initialization of CurlContext
56
57 class CurlGlobal {
58 protected:
59     CurlGlobal()
60     {
61         curl_global_init(CURL_GLOBAL_ALL);
62     }
63     
64     virtual ~CurlGlobal()
65     {
66         curl_global_cleanup();
67     }
68 };
69
70 // CurlShareHandle --------------------------------------------
71
72 class CurlShareHandle {
73     WTF_MAKE_NONCOPYABLE(CurlShareHandle);
74
75 public:
76     CurlShareHandle();
77     ~CurlShareHandle();
78
79     CURLSH* handle() const { return m_shareHandle; }
80
81 private:
82     static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
83     static void unlockCallback(CURL*, curl_lock_data, void*);
84     static Lock* mutexFor(curl_lock_data);
85
86     CURLSH* m_shareHandle { nullptr };
87 };
88
89 // CurlContext --------------------------------------------
90
91 class CurlRequestScheduler;
92
93 class CurlContext : public CurlGlobal {
94     WTF_MAKE_NONCOPYABLE(CurlContext);
95     friend NeverDestroyed<CurlContext>;
96 public:
97     WEBCORE_EXPORT static CurlContext& singleton();
98
99     virtual ~CurlContext();
100
101     const CurlShareHandle& shareHandle() { return m_shareHandle; }
102
103     CurlRequestScheduler& scheduler() { return *m_scheduler; }
104
105     // Proxy
106     const CurlProxySettings& proxySettings() const { return m_proxySettings; }
107     void setProxySettings(CurlProxySettings&& settings) { m_proxySettings = WTFMove(settings); }
108     void setProxyUserPass(const String& user, const String& password) { m_proxySettings.setUserPass(user, password); }
109     void setDefaultProxyAuthMethod() { m_proxySettings.setDefaultAuthMethod(); }
110     void setProxyAuthMethod(long authMethod) { m_proxySettings.setAuthMethod(authMethod); }
111
112     // SSL
113     CurlSSLHandle& sslHandle() { return m_sslHandle; }
114
115     // HTTP/2
116     bool isHttp2Enabled() const;
117
118     // Timeout
119     Seconds dnsCacheTimeout() const { return m_dnsCacheTimeout; }
120     Seconds connectTimeout() const { return m_connectTimeout; }
121     Seconds defaultTimeoutInterval() const { return m_defaultTimeoutInterval; }
122
123 #ifndef NDEBUG
124     FILE* getLogFile() const { return m_logFile; }
125     bool isVerbose() const { return m_verbose; }
126 #endif
127
128 private:
129     CurlContext();
130     void initShareHandle();
131
132     CurlProxySettings m_proxySettings;
133     CurlShareHandle m_shareHandle;
134     CurlSSLHandle m_sslHandle;
135     std::unique_ptr<CurlRequestScheduler> m_scheduler;
136
137     Seconds m_dnsCacheTimeout { Seconds::fromMinutes(5) };
138     Seconds m_connectTimeout { 30.0 };
139     Seconds m_defaultTimeoutInterval { 60.0 };
140
141 #ifndef NDEBUG
142     FILE* m_logFile { nullptr };
143     bool m_verbose { false };
144 #endif
145 };
146
147 // CurlMultiHandle --------------------------------------------
148
149 class CurlMultiHandle {
150     WTF_MAKE_FAST_ALLOCATED;
151     WTF_MAKE_NONCOPYABLE(CurlMultiHandle);
152
153 public:
154     CurlMultiHandle();
155     ~CurlMultiHandle();
156
157     void setMaxConnects(long);
158     void setMaxTotalConnections(long);
159     void setMaxHostConnections(long);
160
161     CURLMcode addHandle(CURL*);
162     CURLMcode removeHandle(CURL*);
163
164     CURLMcode getFdSet(fd_set&, fd_set&, fd_set&, int&);
165     CURLMcode perform(int&);
166     CURLMsg* readInfo(int&);
167
168 private:
169     CURLM* m_multiHandle { nullptr };
170 };
171
172 // CurlSList -------------------------------------------------
173
174 class CurlSList {
175 public:
176     CurlSList() { }
177     ~CurlSList() { clear(); }
178
179     operator struct curl_slist** () { return &m_list; }
180
181     const struct curl_slist* head() const { return m_list; }
182     bool isEmpty() const { return !m_list; }
183     void clear()
184     {
185         if (m_list) {
186             curl_slist_free_all(m_list);
187             m_list = nullptr;
188         }
189     }
190
191     void append(const char* str) { m_list = curl_slist_append(m_list, str); }
192     void append(const String& str) { append(str.latin1().data()); }
193
194 private:
195     struct curl_slist* m_list { nullptr };
196 };
197
198 // CurlHandle -------------------------------------------------
199
200 class CertificateInfo;
201 class CurlSSLVerifier;
202 class HTTPHeaderMap;
203 class NetworkLoadMetrics;
204
205 class CurlHandle {
206     WTF_MAKE_FAST_ALLOCATED;
207     WTF_MAKE_NONCOPYABLE(CurlHandle);
208
209 public:
210     enum class VerifyPeer {
211         Disable = 0L,
212         Enable = 1L
213     };
214
215     enum class VerifyHost {
216         LooseNameCheck = 0,
217         StrictNameCheck = 2
218     };
219
220     CurlHandle();
221     virtual ~CurlHandle();
222
223     CURL* handle() const { return m_handle; }
224     const URL& url() const { return m_url; }
225
226     CURLcode perform();
227     CURLcode pause(int);
228
229     static const String errorDescription(CURLcode);
230
231     void enableShareHandle();
232
233     void setUrl(const URL&);
234     void enableSSLForHost(const String&);
235
236     void appendRequestHeaders(const HTTPHeaderMap&);
237     void appendRequestHeader(const String& name, const String& value);
238     void appendRequestHeader(const String& name);
239     void removeRequestHeader(const String& name);
240
241     void enableHttp();
242     void enableHttpGetRequest();
243     void enableHttpHeadRequest();
244     void enableHttpPostRequest();
245     void setPostFields(const char*, long);
246     void setPostFieldLarge(curl_off_t);
247     void enableHttpPutRequest();
248     void setInFileSizeLarge(curl_off_t);
249     void setHttpCustomRequest(const String&);
250
251     void enableConnectionOnly();
252
253     void enableAcceptEncoding();
254     void enableAllowedProtocols();
255
256     void setHttpAuthUserPass(const String&, const String&, long authType = CURLAUTH_ANY);
257
258     void disableServerTrustEvaluation();
259     void setCACertPath(const char*);
260     void setSslVerifyPeer(VerifyPeer);
261     void setSslVerifyHost(VerifyHost);
262     void setSslCert(const char*);
263     void setSslCertType(const char*);
264     void setSslKeyPassword(const char*);
265     void setSslCipherList(const char*);
266
267     void enableProxyIfExists();
268
269     void setDnsCacheTimeout(Seconds);
270     void setConnectTimeout(Seconds);
271     void setTimeout(Seconds);
272
273     // Callback function
274     void setHeaderCallbackFunction(curl_write_callback, void*);
275     void setWriteCallbackFunction(curl_write_callback, void*);
276     void setReadCallbackFunction(curl_read_callback, void*);
277     void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
278     void setDebugCallbackFunction(curl_debug_callback, void*);
279
280     // Status
281     Optional<String> getProxyUrl();
282     Optional<long> getResponseCode();
283     Optional<long> getHttpConnectCode();
284     Optional<long long> getContentLength();
285     Optional<long> getHttpAuthAvail();
286     Optional<long> getProxyAuthAvail();
287     Optional<long> getHttpVersion();
288     Optional<NetworkLoadMetrics> getNetworkLoadMetrics(const WTF::Seconds& domainLookupStart);
289     void addExtraNetworkLoadMetrics(NetworkLoadMetrics&);
290
291     int sslErrors() const;
292     Optional<CertificateInfo> certificateInfo() const;
293
294     static long long maxCurlOffT();
295
296 #ifndef NDEBUG
297     void enableVerboseIfUsed();
298     void enableStdErrIfUsed();
299 #endif
300
301 private:
302     void enableRequestHeaders();
303     static int expectedSizeOfCurlOffT();
304
305     static CURLcode willSetupSslCtxCallback(CURL*, void* sslCtx, void* userData);
306     CURLcode willSetupSslCtx(void* sslCtx);
307
308     CURL* m_handle { nullptr };
309     char m_errorBuffer[CURL_ERROR_SIZE] { };
310
311     URL m_url;
312     CurlSList m_requestHeaders;
313     std::unique_ptr<CurlSSLVerifier> m_sslVerifier;
314 };
315
316 class CurlSocketHandle : public CurlHandle {
317     WTF_MAKE_NONCOPYABLE(CurlSocketHandle);
318
319 public:
320     struct WaitResult {
321         bool readable { false };
322         bool writable { false };
323     };
324
325     CurlSocketHandle(const URL&, Function<void(CURLcode)>&& errorHandler);
326
327     bool connect();
328     size_t send(const uint8_t*, size_t);
329     Optional<size_t> receive(uint8_t*, size_t);
330     Optional<WaitResult> wait(const Seconds& timeout, bool alsoWaitForWrite);
331
332 private:
333     Function<void(CURLcode)> m_errorHandler;
334 };
335
336 } // namespace WebCore