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