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