• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
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 #include "constant.h"
17 #include "curl/curl.h"
18 #include "netstack_common_utils.h"
19 #include "netstack_log.h"
20 
21 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
22 #include <netinet/tcp.h>
23 #endif
24 #include "http_request_options.h"
25 #include "secure_char.h"
26 
27 namespace OHOS::NetStack::Http {
28 static constexpr const uint32_t MIN_PRIORITY = 1;
29 static constexpr const uint32_t MAX_PRIORITY = 1000;
30 
31 static constexpr const int64_t MIN_RESUM_NUMBER = 1;
32 static constexpr const int64_t MAX_RESUM_NUMBER = 4294967296;
33 
HttpRequestOptions()34 HttpRequestOptions::HttpRequestOptions()
35     : method_(HttpConstant::HTTP_METHOD_GET),
36       readTimeout_(HttpConstant::DEFAULT_READ_TIMEOUT),
37       maxLimit_(HttpConstant::DEFAULT_MAX_LIMIT),
38       connectTimeout_(HttpConstant::DEFAULT_CONNECT_TIMEOUT),
39       usingProtocol_(HttpProtocol::HTTP_NONE),
40       dataType_(HttpDataType::NO_DATA_TYPE),
41       priority_(MIN_PRIORITY),
42       usingHttpProxyType_(UsingHttpProxyType::USE_DEFAULT),
43       httpProxyPort_(0),
44       resumeFromNumber_(0),
45       resumeToNumber_(0)
46 {
47 }
48 
SetUrl(const std::string & url)49 void HttpRequestOptions::SetUrl(const std::string &url)
50 {
51     url_ = url;
52 }
53 
SetMethod(const std::string & method)54 void HttpRequestOptions::SetMethod(const std::string &method)
55 {
56     method_ = method;
57 }
58 
SetBody(const void * data,size_t length)59 void HttpRequestOptions::SetBody(const void *data, size_t length)
60 {
61     body_.append(static_cast<const char *>(data), length);
62 }
63 
SetHeader(const std::string & key,const std::string & val)64 void HttpRequestOptions::SetHeader(const std::string &key, const std::string &val)
65 {
66     header_[key] = val;
67 }
68 
SetReadTimeout(uint32_t readTimeout)69 void HttpRequestOptions::SetReadTimeout(uint32_t readTimeout)
70 {
71     readTimeout_ = readTimeout;
72     tcpOption_.SetTcpUserTimeout(readTimeout);
73 }
74 
SetMaxLimit(uint32_t maxLimit)75 void HttpRequestOptions::SetMaxLimit(uint32_t maxLimit)
76 {
77     if (maxLimit > HttpConstant::MAX_LIMIT) {
78         NETSTACK_LOGD("maxLimit setting exceeds the maximum limit, use max limit");
79         maxLimit_ = HttpConstant::MAX_LIMIT;
80         return;
81     }
82     maxLimit_ = maxLimit;
83 }
84 
SetConnectTimeout(uint32_t connectTimeout)85 void HttpRequestOptions::SetConnectTimeout(uint32_t connectTimeout)
86 {
87     connectTimeout_ = connectTimeout;
88 }
89 
GetUrl() const90 const std::string &HttpRequestOptions::GetUrl() const
91 {
92     return url_;
93 }
94 
GetMethod() const95 const std::string &HttpRequestOptions::GetMethod() const
96 {
97     return method_;
98 }
99 
GetBody() const100 const std::string &HttpRequestOptions::GetBody() const
101 {
102     return body_;
103 }
104 
GetHeader() const105 const std::map<std::string, std::string> &HttpRequestOptions::GetHeader() const
106 {
107     return header_;
108 }
109 
GetReadTimeout() const110 uint32_t HttpRequestOptions::GetReadTimeout() const
111 {
112     return readTimeout_;
113 }
114 
GetMaxLimit() const115 uint32_t HttpRequestOptions::GetMaxLimit() const
116 {
117     return maxLimit_;
118 }
119 
GetConnectTimeout() const120 uint32_t HttpRequestOptions::GetConnectTimeout() const
121 {
122     return connectTimeout_;
123 }
124 
SetUsingProtocol(HttpProtocol httpProtocol)125 void HttpRequestOptions::SetUsingProtocol(HttpProtocol httpProtocol)
126 {
127     usingProtocol_ = httpProtocol;
128 }
129 
GetHttpVersion() const130 uint32_t HttpRequestOptions::GetHttpVersion() const
131 {
132     if (usingProtocol_ == HttpProtocol::HTTP3) {
133         NETSTACK_LOGD("CURL_HTTP_VERSION_3");
134         return CURL_HTTP_VERSION_3;
135     }
136     if (usingProtocol_ == HttpProtocol::HTTP2) {
137         NETSTACK_LOGD("CURL_HTTP_VERSION_2_0");
138         return CURL_HTTP_VERSION_2_0;
139     }
140     if (usingProtocol_ == HttpProtocol::HTTP1_1) {
141         NETSTACK_LOGD("CURL_HTTP_VERSION_1_1");
142         return CURL_HTTP_VERSION_1_1;
143     }
144     return CURL_HTTP_VERSION_NONE;
145 }
146 
SetRequestTime(const std::string & time)147 void HttpRequestOptions::SetRequestTime(const std::string &time)
148 {
149     requestTime_ = time;
150 }
151 
GetRequestTime() const152 const std::string &HttpRequestOptions::GetRequestTime() const
153 {
154     return requestTime_;
155 }
156 
SetHttpDataType(HttpDataType dataType)157 void HttpRequestOptions::SetHttpDataType(HttpDataType dataType)
158 {
159     if (dataType != HttpDataType::STRING && dataType != HttpDataType::ARRAY_BUFFER &&
160         dataType != HttpDataType::OBJECT) {
161         return;
162     }
163     dataType_ = dataType;
164 }
165 
GetHttpDataType() const166 HttpDataType HttpRequestOptions::GetHttpDataType() const
167 {
168     return dataType_;
169 }
170 
SetPriority(uint32_t priority)171 void HttpRequestOptions::SetPriority(uint32_t priority)
172 {
173     if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) {
174         return;
175     }
176     priority_ = priority;
177 }
178 
GetPriority() const179 uint32_t HttpRequestOptions::GetPriority() const
180 {
181     return priority_;
182 }
183 
SetCanSkipCertVerifyFlag(bool canCertVerify)184 void HttpRequestOptions::SetCanSkipCertVerifyFlag(bool canCertVerify)
185 {
186     canSkipCertVerify_ = canCertVerify;
187 }
188 
GetCanSkipCertVerifyFlag() const189 bool HttpRequestOptions::GetCanSkipCertVerifyFlag() const
190 {
191     return canSkipCertVerify_;
192 }
SetUsingHttpProxyType(UsingHttpProxyType type)193 void HttpRequestOptions::SetUsingHttpProxyType(UsingHttpProxyType type)
194 {
195     usingHttpProxyType_ = type;
196 }
197 
GetUsingHttpProxyType() const198 UsingHttpProxyType HttpRequestOptions::GetUsingHttpProxyType() const
199 {
200     return usingHttpProxyType_;
201 }
202 
SetSpecifiedHttpProxy(const std::string & host,int32_t port,const std::string & exclusionList)203 void HttpRequestOptions::SetSpecifiedHttpProxy(const std::string &host, int32_t port, const std::string &exclusionList)
204 {
205     httpProxyHost_ = host;
206     httpProxyPort_ = port;
207     httpProxyExclusions_ = exclusionList;
208 }
209 
GetSpecifiedHttpProxy(std::string & host,int32_t & port,std::string & exclusionList)210 void HttpRequestOptions::GetSpecifiedHttpProxy(std::string &host, int32_t &port, std::string &exclusionList)
211 {
212     host = httpProxyHost_;
213     port = httpProxyPort_;
214     exclusionList = httpProxyExclusions_;
215 }
216 
SetClientCert(std::string & cert,std::string & certType,std::string & key,Secure::SecureChar & keyPasswd)217 void HttpRequestOptions::SetClientCert(
218     std::string &cert, std::string &certType, std::string &key, Secure::SecureChar &keyPasswd)
219 {
220     cert_ = cert;
221     certType_ = certType;
222     key_ = key;
223     keyPasswd_ = keyPasswd;
224 }
225 
AddMultiFormData(const MultiFormData & multiFormData)226 void HttpRequestOptions::AddMultiFormData(const MultiFormData &multiFormData)
227 {
228     multiFormDataList_.push_back(multiFormData);
229 }
230 
GetClientCert(std::string & cert,std::string & certType,std::string & key,Secure::SecureChar & keyPasswd)231 void HttpRequestOptions::GetClientCert(
232     std::string &cert, std::string &certType, std::string &key, Secure::SecureChar &keyPasswd)
233 {
234     cert = cert_;
235     certType = certType_;
236     key = key_;
237     keyPasswd = keyPasswd_;
238 }
239 
SetCaPath(const std::string & path)240 void HttpRequestOptions::SetCaPath(const std::string &path)
241 {
242     if (path.empty()) {
243         return;
244     }
245 
246     caPath_ = path;
247 }
248 
GetCaPath() const249 const std::string &HttpRequestOptions::GetCaPath() const
250 {
251     return caPath_;
252 }
253 
SetCaData(const std::string & caData)254 void HttpRequestOptions::SetCaData(const std::string &caData)
255 {
256     if (caData.empty()) {
257         return;
258     }
259 
260     caData_ = caData;
261 }
262 
GetCaData() const263 const std::string &HttpRequestOptions::GetCaData() const
264 {
265     return caData_;
266 }
267 
SetTlsOption(const TlsOption & tlsOption)268 void HttpRequestOptions::SetTlsOption(const TlsOption &tlsOption)
269 {
270     tlsOption_.tlsVersionMax = tlsOption.tlsVersionMax;
271     tlsOption_.tlsVersionMin = tlsOption.tlsVersionMin;
272     tlsOption_.cipherSuite = tlsOption.cipherSuite;
273 }
274 
GetTlsOption() const275 const TlsOption HttpRequestOptions::GetTlsOption() const
276 {
277     return tlsOption_;
278 }
279 
GetTCPOption() const280 const HttpRequestOptions::TcpConfiguration HttpRequestOptions::GetTCPOption() const
281 {
282     return tcpOption_;
283 }
284 
SetServerAuthentication(const ServerAuthentication & serverAuthentication)285 void HttpRequestOptions::SetServerAuthentication(const ServerAuthentication &serverAuthentication)
286 {
287     serverAuthentication_.authenticationType = serverAuthentication.authenticationType;
288     serverAuthentication_.credential.password = serverAuthentication.credential.password;
289     serverAuthentication_.credential.username = serverAuthentication.credential.username;
290 }
291 
GetServerAuthentication() const292 const ServerAuthentication HttpRequestOptions::GetServerAuthentication() const
293 {
294     return serverAuthentication_;
295 }
296 
SetDohUrl(const std::string & dohUrl)297 void HttpRequestOptions::SetDohUrl(const std::string &dohUrl)
298 {
299     if (dohUrl.empty()) {
300         return;
301     }
302     dohUrl_ = dohUrl;
303 }
304 
GetDohUrl() const305 const std::string &HttpRequestOptions::GetDohUrl() const
306 {
307     return dohUrl_;
308 }
309 
SetRangeNumber(int64_t resumeFromNumber,int64_t resumeToNumber)310 void HttpRequestOptions::SetRangeNumber(int64_t resumeFromNumber, int64_t resumeToNumber)
311 {
312     if (resumeFromNumber >= MIN_RESUM_NUMBER && resumeFromNumber <= MAX_RESUM_NUMBER) {
313         resumeFromNumber_ = resumeFromNumber;
314     }
315     if (resumeToNumber >= MIN_RESUM_NUMBER && resumeToNumber <= MAX_RESUM_NUMBER) {
316         resumeToNumber_ = resumeToNumber;
317     }
318 }
319 
GetRangeString() const320 std::string HttpRequestOptions::GetRangeString() const
321 {
322     bool isSetFrom = resumeFromNumber_ >= MIN_RESUM_NUMBER;
323     bool isSetTo = resumeToNumber_ >= MIN_RESUM_NUMBER;
324     if (!isSetTo && !isSetFrom) {
325         return "";
326     } else if (!isSetTo && isSetFrom) {
327         return std::to_string(resumeFromNumber_) + '-';
328     } else if (isSetTo && !isSetFrom) {
329         return '-' + std::to_string(resumeToNumber_);
330     } else if (resumeToNumber_ <= resumeFromNumber_) {
331         return "";
332     } else {
333         return std::to_string(resumeFromNumber_) + '-' + std::to_string(resumeToNumber_);
334     }
335 }
336 
GetDnsServers() const337 const std::vector<std::string> &HttpRequestOptions::GetDnsServers() const
338 {
339     return dnsServers_;
340 }
341 
SetDnsServers(const std::vector<std::string> & dnsServers)342 void HttpRequestOptions::SetDnsServers(const std::vector<std::string> &dnsServers)
343 {
344     dnsServers_ = dnsServers;
345 }
346 
GetMultiPartDataList()347 std::vector<MultiFormData> HttpRequestOptions::GetMultiPartDataList()
348 {
349     return multiFormDataList_;
350 }
351 
SetCertificatePinning(std::string certPIN)352 void HttpRequestOptions::SetCertificatePinning(std::string certPIN)
353 {
354     certificatePinning_ = std::move(certPIN);
355 }
356 
GetCertificatePinning() const357 std::string HttpRequestOptions::GetCertificatePinning() const
358 {
359     return certificatePinning_;
360 }
361 
SetAddressFamily(std::string addressFamily)362 void HttpRequestOptions::SetAddressFamily(std::string addressFamily)
363 {
364     addressFamily_ = std::move(addressFamily);
365 }
366 
GetAddressFamily() const367 std::string HttpRequestOptions::GetAddressFamily() const
368 {
369     return addressFamily_;
370 }
371 
SetOptionToSocket(int sock)372 bool HttpRequestOptions::TcpConfiguration::SetOptionToSocket(int sock)
373 {
374 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(IOS_PLATFORM)
375     int proto = -1;
376     auto len = static_cast<socklen_t>(sizeof(proto));
377     /*
378     https://man7.org/linux/man-pages/man2/getsockopt.2.html
379     RETURN VALUE         top
380         On success, zero is returned for the standard options.  On error,
381         -1 is returned, and errno is set to indicate the error.
382 
383         Netfilter allows the programmer to define custom socket options
384         with associated handlers; for such options, the return value on
385         success is the value returned by the handler.
386     */
387     auto res = getsockopt(sock, SOL_SOCKET, SO_PROTOCOL, &proto, &len);
388     if (res != 0 || proto != IPPROTO_TCP) {
389         return false;
390     }
391     if (setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &userTimeout_, sizeof(userTimeout_)) != 0) {
392         NETSTACK_LOGE("set TCP_USER_TIMEOUT failed, errno = %{public}d userTimeout = %{public}d sock = %{public}d",
393             errno, userTimeout_, sock);
394         return false;
395     }
396 
397     int keepAlive_ = 1;
398     /*
399     https://man7.org/linux/man-pages/man7/socket.7.html
400     SO_KEEPALIVE
401         Enable sending of keep-alive messages on connection-
402         oriented sockets.  Expects an integer boolean flag.
403 
404     https://man7.org/linux/man-pages/man3/setsockopt.3p.html
405     RETURN VALUE         top
406         Upon successful completion, setsockopt() shall return 0.
407         Otherwise, -1 shall be returned and errno set to indicate the
408         error.
409     */
410     if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive_, sizeof(keepAlive_)) != 0) {
411         NETSTACK_LOGE("set SO_KEEPALIVE failed, errno = %{public}d sock = %{public}d", errno, sock);
412         return false;
413     }
414     if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &keepIdle_, sizeof(keepIdle_)) != 0) {
415         NETSTACK_LOGE("set TCP_KEEPIDLE failed, errno = %{public}d keepIdle = %{public}d sock = %{public}d",
416             errno, keepIdle_, sock);
417         return false;
418     }
419     if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &keepCnt_, sizeof(keepCnt_)) != 0) {
420         NETSTACK_LOGE("set TCP_KEEPCNT failed, errno = %{public}d keepCnt = %{public}d sock = %{public}d",
421             errno, keepCnt_, sock);
422         return false;
423     }
424     if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &keepInterval_, sizeof(keepInterval_)) != 0) {
425         NETSTACK_LOGE("set TCP_KEEPINTVL failed, errno = %{public}d keepInterval = %{public}d sock = %{public}d",
426             errno, keepInterval_, sock);
427         return false;
428     }
429 #endif
430     return true;
431 }
432 
SetTcpUserTimeout(const uint32_t & timeout)433 void HttpRequestOptions::TcpConfiguration::SetTcpUserTimeout(const uint32_t &timeout)
434 {
435     userTimeout_ = timeout;
436 }
437 } // namespace OHOS::NetStack::Http