1 /* 2 * Copyright (c) 2021-2022 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 <mutex> 22 #include <thread> 23 #include <utility> 24 #include <vector> 25 #include <queue> 26 #include <functional> 27 28 #include "curl/curl.h" 29 #include "napi/native_api.h" 30 #include "request_context.h" 31 32 namespace OHOS::NetStack { 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 Request2Callback(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 size_t OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData); 84 85 static size_t OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData); 86 87 static struct curl_slist *MakeHeaders(const std::vector<std::string> &vec); 88 89 static napi_value MakeResponseHeader(RequestContext *context); 90 91 static void OnHeaderReceive(RequestContext *context, napi_value header); 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 static void HandleCurlData(CURLMsg *msg); 100 101 static bool GetCurlDataFromHandle(CURL *handle, RequestContext *context, CURLMSG curlMsg, CURLcode result); 102 103 static void RunThread(); 104 105 static void SendRequest(); 106 107 static void ReadResponse(); 108 109 static void GetGlobalHttpProxyInfo(std::string &host, int32_t &port, std::string &exclusions); 110 111 static void OnDataReceive(napi_env env, napi_status status, void *data); 112 113 static void OnDataProgress(napi_env env, napi_status status, void *data); 114 115 static void OnDataEnd(napi_env env, napi_status status, void *data); 116 117 static int ProgressCallback(void *userData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, 118 curl_off_t ulnow); 119 120 static void AddRequestInfo(); 121 122 struct RequestInfo { 123 RequestInfo() = delete; 124 ~RequestInfo() = default; 125 RequestInfoRequestInfo126 RequestInfo(RequestContext *c, CURL *h) 127 { 128 context = c; 129 handle = h; 130 } 131 132 RequestContext *context; 133 CURL *handle; 134 135 bool operator<(const RequestInfo &info) const 136 { 137 return context->options.GetPriority() < info.context->options.GetPriority(); 138 } 139 140 bool operator>(const RequestInfo &info) const 141 { 142 return context->options.GetPriority() > info.context->options.GetPriority(); 143 } 144 }; 145 146 struct StaticVariable { StaticVariableStaticVariable147 StaticVariable() : curlMulti(nullptr), initialized(false), runThread(true) {} 148 ~StaticVariableStaticVariable149 ~StaticVariable() 150 { 151 if (HttpExec::IsInitialized()) { 152 HttpExec::DeInitialize(); 153 } 154 } 155 156 std::mutex mutex; 157 std::mutex curlMultiMutex; 158 CURLM *curlMulti; 159 std::map<CURL *, RequestContext *> contextMap; 160 std::thread workThread; 161 std::condition_variable conditionVariable; 162 std::priority_queue<RequestInfo> infoQueue; 163 164 #ifndef MAC_PLATFORM 165 std::atomic_bool initialized; 166 std::atomic_bool runThread; 167 #else 168 bool initialized; 169 bool runThread; 170 #endif 171 }; 172 static StaticVariable staticVariable_; 173 }; 174 } // namespace OHOS::NetStack 175 176 #endif /* COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H */ 177