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