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 #ifndef COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H 17 #define COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H 18 19 #include <atomic> 20 #include <condition_variable> 21 #include <functional> 22 #include <mutex> 23 #include <queue> 24 #include <thread> 25 #include <utility> 26 #include <vector> 27 #include <set> 28 #ifdef HTTP_MULTIPATH_CERT_ENABLE 29 #include <openssl/ssl.h> 30 #endif 31 32 #include "curl/curl.h" 33 #include "napi/native_api.h" 34 #include "request_context.h" 35 36 namespace OHOS::NetStack::Http { 37 class HttpResponseCacheExec final { 38 public: 39 HttpResponseCacheExec() = default; 40 41 ~HttpResponseCacheExec() = default; 42 43 static bool ExecFlush(BaseContext *context); 44 45 static napi_value FlushCallback(BaseContext *context); 46 47 static bool ExecDelete(BaseContext *context); 48 49 static napi_value DeleteCallback(BaseContext *context); 50 }; 51 52 class HttpExec final { 53 public: 54 HttpExec() = default; 55 56 ~HttpExec() = default; 57 58 static bool RequestWithoutCache(RequestContext *context); 59 60 static bool ExecRequest(RequestContext *context); 61 62 static napi_value BuildRequestCallback(RequestContext *context); 63 64 static napi_value RequestCallback(RequestContext *context); 65 66 static napi_value RequestInStreamCallback(RequestContext *context); 67 68 static std::string MakeUrl(const std::string &url, std::string param, const std::string &extraParam); 69 70 static bool MethodForGet(const std::string &method); 71 72 static bool MethodForPost(const std::string &method); 73 74 static bool EncodeUrlParam(std::string &str); 75 76 static bool ParseHostAndPortFromUrl(const std::string &url, std::string &host, uint16_t &port); 77 78 #if !HAS_NETMANAGER_BASE 79 static bool Initialize(); 80 81 static bool IsInitialized(); 82 83 static void DeInitialize(); 84 #endif 85 86 static void AsyncRunRequest(RequestContext *context); 87 88 private: 89 static bool SetOption(CURL *curl, RequestContext *context, struct curl_slist *requestHeader); 90 91 static bool SetOtherOption(CURL *curl, RequestContext *context); 92 93 static bool SetRequestOption(void *curl, RequestContext *context); 94 95 static bool SetSSLCertOption(CURL *curl, RequestContext *context); 96 97 static bool SetServerSSLCertOption(CURL *curl, OHOS::NetStack::Http::RequestContext *context); 98 99 static bool SetDnsOption(CURL *curl, RequestContext *context); 100 101 static bool SetDnsResolvOption(CURL *curl, RequestContext *context); 102 103 static bool SetCertPinnerOption(CURL *curl, RequestContext *context); 104 105 static size_t OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData); 106 107 static size_t OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData); 108 109 static struct curl_slist *MakeHeaders(const std::vector<std::string> &vec); 110 111 static napi_value MakeResponseHeader(napi_env env, void *ctx); 112 113 static bool IsUnReserved(unsigned char in); 114 115 static bool ProcByExpectDataType(napi_value object, RequestContext *context); 116 117 static bool AddCurlHandle(CURL *handle, RequestContext *context); 118 119 #if HAS_NETMANAGER_BASE 120 static void HandleCurlData(CURLMsg *msg, RequestContext *context); 121 #else 122 static void HandleCurlData(CURLMsg *msg); 123 #endif 124 125 static bool GetCurlDataFromHandle(CURL *handle, RequestContext *context, CURLMSG curlMsg, CURLcode result); 126 127 static double GetTimingFromCurl(CURL *handle, CURLINFO info); 128 129 static void CacheCurlPerformanceTiming(CURL *handle, RequestContext *context); 130 131 static curl_off_t GetSizeFromCurl(CURL *handle, RequestContext *context); 132 133 #if !HAS_NETMANAGER_BASE 134 static void RunThread(); 135 136 static void SendRequest(); 137 138 static void ReadResponse(); 139 #endif 140 141 static void GetGlobalHttpProxyInfo(std::string &host, int32_t &port, std::string &exclusions); 142 143 static void GetHttpProxyInfo(RequestContext *context, std::string &host, int32_t &port, std::string &exclusions); 144 145 static void OnDataReceive(napi_env env, napi_status status, void *data); 146 147 static void OnDataProgress(napi_env env, napi_status status, void *data); 148 149 static void OnDataUploadProgress(napi_env env, napi_status status, void *data); 150 151 static int ProgressCallback(void *userData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, 152 curl_off_t ulnow); 153 154 static bool SetMultiPartOption(void *curl, RequestContext *context); 155 156 static void SetFormDataOption(MultiFormData &multiFormData, curl_mimepart *part, 157 void *curl, RequestContext *context); 158 159 #if !HAS_NETMANAGER_BASE 160 static void AddRequestInfo(); 161 #endif 162 163 static CURLcode SslCtxFunction(void *curl, void *ssl_ctx, void *parm); 164 165 struct RequestInfo { 166 RequestInfo() = delete; 167 ~RequestInfo() = default; 168 RequestInfoRequestInfo169 RequestInfo(RequestContext *c, CURL *h) 170 { 171 context = c; 172 handle = h; 173 } 174 175 RequestContext *context; 176 CURL *handle; 177 178 bool operator<(const RequestInfo &info) const 179 { 180 return context->options.GetPriority() < info.context->options.GetPriority(); 181 } 182 183 bool operator>(const RequestInfo &info) const 184 { 185 return context->options.GetPriority() > info.context->options.GetPriority(); 186 } 187 }; 188 189 #if !HAS_NETMANAGER_BASE 190 struct StaticVariable { StaticVariableStaticVariable191 StaticVariable() : curlMulti(nullptr), initialized(false), runThread(true) {} 192 ~StaticVariableStaticVariable193 ~StaticVariable() 194 { 195 if (HttpExec::IsInitialized()) { 196 HttpExec::DeInitialize(); 197 } 198 } 199 200 std::mutex curlMultiMutex; 201 std::mutex mutexForInitialize; 202 CURLM *curlMulti; 203 std::map<CURL *, RequestContext *> contextMap; 204 std::thread workThread; 205 std::condition_variable conditionVariable; 206 std::priority_queue<RequestInfo> infoQueue; 207 208 #ifndef MAC_PLATFORM 209 std::atomic_bool initialized; 210 std::atomic_bool runThread; 211 #else 212 bool initialized; 213 bool runThread; 214 #endif 215 }; 216 static StaticVariable staticVariable_; 217 #endif 218 }; 219 } // namespace OHOS::NetStack::Http 220 221 #endif /* COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H */ 222