1 /*
2 * Copyright (c) 2022-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 "monitor.h"
17
18 #include <cstddef>
19 #include <utility>
20
21 #include <napi/native_api.h>
22 #include <napi/native_common.h>
23 #include <securec.h>
24 #include <uv.h>
25
26 #include "module_template.h"
27 #include "napi_utils.h"
28 #include "netstack_log.h"
29 #include "tls_socket.h"
30
31 namespace OHOS {
32 namespace NetStack {
33 namespace TlsSocket {
34 namespace {
35 constexpr int PARAM_OPTION = 1;
36 constexpr int PARAM_OPTION_CALLBACK = 2;
37 constexpr std::string_view EVENT_MESSAGE = "message";
38 constexpr std::string_view EVENT_CONNECT = "connect";
39 constexpr std::string_view EVENT_CLOSE = "close";
40 constexpr std::string_view EVENT_ERROR = "error";
41 constexpr std::initializer_list<std::string_view> EVENTS = {EVENT_MESSAGE, EVENT_CONNECT, EVENT_CLOSE, EVENT_ERROR};
42
43 constexpr const char *PROPERTY_ADDRESS = "address";
44 constexpr const char *PROPERTY_FAMILY = "family";
45 constexpr const char *PROPERTY_PORT = "port";
46 constexpr const char *PROPERTY_SIZE = "size";
47 constexpr const char *ON_MESSAGE = "message";
48 constexpr const char *ON_REMOTE_INFO = "remoteInfo";
49
ParserNullBranch(const std::string &errMessage, uv_work_t *&work, UvWorkWrapper *&workWrapper)50 void ParserNullBranch(const std::string &errMessage, uv_work_t *&work, UvWorkWrapper *&workWrapper)
51 {
52 NETSTACK_LOGE("%{public}s", errMessage.c_str());
53 if (workWrapper != nullptr) {
54 delete workWrapper;
55 workWrapper = nullptr;
56 }
57
58 if (work != nullptr) {
59 delete work;
60 work = nullptr;
61 }
62 }
63
SetPropertyForWorkWrapper(UvWorkWrapper *workWrapper, Monitor::MessageRecvParma *messageRecvParma, napi_value arrayBuffer, napi_value remoteInfo, napi_value obj)64 void SetPropertyForWorkWrapper(UvWorkWrapper *workWrapper, Monitor::MessageRecvParma *messageRecvParma,
65 napi_value arrayBuffer, napi_value remoteInfo, napi_value obj)
66 {
67 napi_value message = nullptr;
68 napi_create_typedarray(workWrapper->env, napi_uint8_array, messageRecvParma->data_.size(), arrayBuffer, 0,
69 &message);
70 napi_value address = NapiUtils::CreateStringUtf8(workWrapper->env, messageRecvParma->remoteInfo_.GetAddress());
71 napi_value family = NapiUtils::CreateStringUtf8(workWrapper->env, messageRecvParma->remoteInfo_.GetFamily());
72 napi_value port = NapiUtils::CreateInt32(workWrapper->env, messageRecvParma->remoteInfo_.GetPort());
73 napi_value size = NapiUtils::CreateInt32(workWrapper->env, messageRecvParma->remoteInfo_.GetSize());
74 NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_ADDRESS, address);
75 NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_FAMILY, family);
76 NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_PORT, port);
77 NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_SIZE, size);
78 NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_MESSAGE, message);
79 NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_REMOTE_INFO, remoteInfo);
80 }
81
EventMessageCallback(uv_work_t *work, int status)82 void EventMessageCallback(uv_work_t *work, int status)
83 {
84 (void)status;
85 if (work == nullptr) {
86 NETSTACK_LOGE("work is nullptr");
87 return;
88 }
89 auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
90 auto eventManager = reinterpret_cast<EventManager *>(workWrapper->data);
91 auto messageRecvParam = reinterpret_cast<Monitor::MessageRecvParma *>(eventManager->GetQueueData());
92 if (!messageRecvParam) {
93 NETSTACK_LOGE("messageRecvParam is nullptr");
94 return;
95 }
96
97 napi_env env = workWrapper->env;
98 auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
99 std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
100
101 napi_value obj = NapiUtils::CreateObject(workWrapper->env);
102 napi_value remoteInfo = NapiUtils::CreateObject(workWrapper->env);
103 void *data = nullptr;
104 napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(workWrapper->env, messageRecvParam->data_.size(), &data);
105 if (data != nullptr && NapiUtils::ValueIsArrayBuffer(env, arrayBuffer) &&
106 memcpy_s(data, messageRecvParam->data_.size(), messageRecvParam->data_.c_str(),
107 messageRecvParam->data_.size()) != EOK) {
108 delete messageRecvParam;
109 ParserNullBranch("", work, workWrapper);
110 return;
111 }
112 SetPropertyForWorkWrapper(workWrapper, messageRecvParam, arrayBuffer, remoteInfo, obj);
113
114 if (workWrapper->manager == nullptr || !EventManager::IsManagerValid(workWrapper->manager)) {
115 delete messageRecvParam;
116 ParserNullBranch("manager is invalid", work, workWrapper);
117 return;
118 }
119 workWrapper->manager->Emit(workWrapper->type, std::make_pair(NapiUtils::GetUndefined(workWrapper->env), obj));
120 delete messageRecvParam;
121 ParserNullBranch("event message callback success", work, workWrapper);
122 }
123
EventConnectCloseCallback(uv_work_t *work, int status)124 void EventConnectCloseCallback(uv_work_t *work, int status)
125 {
126 (void)status;
127 if (work == nullptr) {
128 NETSTACK_LOGE("work is nullptr");
129 return;
130 }
131 auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
132 if (workWrapper == nullptr) {
133 NETSTACK_LOGE("workWrapper is nullptr");
134 delete work;
135 return;
136 }
137 if (workWrapper->manager == nullptr) {
138 NETSTACK_LOGE("manager is nullptr");
139 delete workWrapper;
140 delete work;
141 return;
142 }
143 napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
144 std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env),
145 NapiUtils::GetUndefined(workWrapper->env)};
146 workWrapper->manager->Emit(workWrapper->type, arg);
147 NapiUtils::CloseScope(workWrapper->env, scope);
148 delete workWrapper;
149 delete work;
150 }
151
EventErrorCallback(uv_work_t *work, int status)152 void EventErrorCallback(uv_work_t *work, int status)
153 {
154 (void)status;
155 if (work == nullptr) {
156 NETSTACK_LOGE("work is nullptr");
157 return;
158 }
159 auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
160 if (workWrapper == nullptr) {
161 NETSTACK_LOGE("workWrapper is nullptr");
162 delete work;
163 return;
164 }
165 std::shared_ptr<Monitor::ErrorRecvParma> errorRecvParma(static_cast<Monitor::ErrorRecvParma *>(workWrapper->data));
166 if (errorRecvParma == nullptr) {
167 NETSTACK_LOGE("monitor is nullptr");
168 delete workWrapper;
169 delete work;
170 return;
171 }
172 if (workWrapper->manager == nullptr) {
173 NETSTACK_LOGE("manager is nullptr");
174 delete workWrapper;
175 delete work;
176 return;
177 }
178 napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
179 napi_value obj = NapiUtils::CreateObject(workWrapper->env);
180 napi_value errorNumber = NapiUtils::CreateInt32(workWrapper->env, errorRecvParma->errorNumber_);
181 napi_value errorString = NapiUtils::CreateStringUtf8(workWrapper->env, errorRecvParma->errorString_);
182 NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorNumber", errorNumber);
183 NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorString", errorString);
184 std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
185 workWrapper->manager->Emit(workWrapper->type, arg);
186 NapiUtils::CloseScope(workWrapper->env, scope);
187 delete workWrapper;
188 delete work;
189 }
190 } // namespace
191
Monitor()192 Monitor::Monitor() {}
193
~Monitor()194 Monitor::~Monitor() {}
195
ParserEventForOn(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket, EventManager *manager)196 void Monitor::ParserEventForOn(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket,
197 EventManager *manager)
198 {
199 if (event == EVENT_MESSAGE) {
200 tlsSocket->OnMessage([this, manager](auto data, auto remoteInfo) {
201 MessageRecvParma *messageRecvParma = new MessageRecvParma();
202 messageRecvParma->data_ = data;
203 messageRecvParma->remoteInfo_ = remoteInfo;
204 if (EventManager::IsManagerValid(manager)) {
205 manager->SetQueueData(reinterpret_cast<void *>(messageRecvParma));
206 manager->EmitByUv(std::string(EVENT_MESSAGE), reinterpret_cast<void *>(manager), EventMessageCallback);
207 }
208 });
209 }
210 if (event == EVENT_CLOSE) {
211 tlsSocket->OnClose([this, manager]() {
212 if (EventManager::IsManagerValid(manager)) {
213 manager->EmitByUv(std::string(EVENT_CLOSE), nullptr, EventConnectCloseCallback);
214 }
215 });
216 }
217 if (event == EVENT_CONNECT) {
218 tlsSocket->OnConnect([this, manager]() {
219 if (EventManager::IsManagerValid(manager)) {
220 manager->EmitByUv(std::string(EVENT_CONNECT), nullptr, EventConnectCloseCallback);
221 }
222 });
223 }
224 if (event == EVENT_ERROR) {
225 tlsSocket->OnError([this, manager](auto errorNumber, auto errorString) {
226 ErrorRecvParma *errorRecvParma = new ErrorRecvParma();
227 errorRecvParma->errorNumber_ = errorNumber;
228 errorRecvParma->errorString_ = errorString;
229 if (EventManager::IsManagerValid(manager)) {
230 manager->EmitByUv(std::string(EVENT_ERROR), static_cast<void *>(errorRecvParma), EventErrorCallback);
231 }
232 });
233 }
234 }
235
On(napi_env env, napi_callback_info info)236 napi_value Monitor::On(napi_env env, napi_callback_info info)
237 {
238 napi_value thisVal = nullptr;
239 size_t paramsCount = MAX_PARAM_NUM;
240 napi_value params[MAX_PARAM_NUM] = {nullptr};
241 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
242 if (paramsCount == PARAM_OPTION) {
243 return NapiUtils::GetUndefined(env);
244 }
245 if (paramsCount != PARAM_OPTION_CALLBACK) {
246 if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
247 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
248 }
249 if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
250 return NapiUtils::GetUndefined(env);
251 }
252 }
253 EventManager *manager = nullptr;
254 napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager));
255 if (manager == nullptr) {
256 NETSTACK_LOGE("manager is nullptr");
257 return NapiUtils::GetUndefined(env);
258 }
259 auto tlsSocket = reinterpret_cast<std::shared_ptr<TLSSocket> *>(manager->GetData());
260 if (tlsSocket == nullptr) {
261 NETSTACK_LOGE("tlsSocket is null");
262 return NapiUtils::GetUndefined(env);
263 }
264
265 const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
266 if (std::find(EVENTS.begin(), EVENTS.end(), event) == EVENTS.end()) {
267 NETSTACK_LOGE("Incorrect listening event %{public}s", event.c_str());
268 return NapiUtils::GetUndefined(env);
269 }
270 manager->AddListener(env, event, params[1], false, false);
271 auto shared = *tlsSocket;
272 if (!shared) {
273 return NapiUtils::GetUndefined(env);
274 }
275 ParserEventForOn(event, shared, manager);
276 return NapiUtils::GetUndefined(env);
277 }
278
ParserEventForOff(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket)279 void Monitor::ParserEventForOff(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket)
280 {
281 if (event == EVENT_MESSAGE) {
282 tlsSocket->OffMessage();
283 }
284 if (event == EVENT_CLOSE) {
285 tlsSocket->OffClose();
286 }
287 if (event == EVENT_CONNECT) {
288 tlsSocket->OffConnect();
289 }
290 if (event == EVENT_ERROR) {
291 tlsSocket->OffError();
292 }
293 }
294
Off(napi_env env, napi_callback_info info)295 napi_value Monitor::Off(napi_env env, napi_callback_info info)
296 {
297 napi_value thisVal = nullptr;
298 size_t paramsCount = MAX_PARAM_NUM;
299 napi_value params[MAX_PARAM_NUM] = {nullptr};
300 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
301 if (paramsCount == PARAM_OPTION) {
302 return NapiUtils::GetUndefined(env);
303 }
304
305 if (paramsCount != PARAM_OPTION_CALLBACK) {
306 if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
307 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
308 }
309 if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
310 return NapiUtils::GetUndefined(env);
311 }
312 }
313 EventManager *manager = nullptr;
314 napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager));
315 if (manager == nullptr) {
316 NETSTACK_LOGE("manager is nullptr");
317 return NapiUtils::GetUndefined(env);
318 }
319 auto tlsSocket = reinterpret_cast<std::shared_ptr<TLSSocket> *>(manager->GetData());
320 if (tlsSocket == nullptr) {
321 NETSTACK_LOGE("tlsSocket is null");
322 return NapiUtils::GetUndefined(env);
323 }
324
325 auto shared = *tlsSocket;
326 if (!shared) {
327 return NapiUtils::GetUndefined(env);
328 }
329 const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
330 manager->DeleteListener(event);
331 ParserEventForOff(event, shared);
332 return NapiUtils::GetUndefined(env);
333 }
334 } // namespace TlsSocket
335 } // namespace NetStack
336 } // namespace OHOS
337