1 /*
2 * Copyright (c) 2021-2024 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 "module_template.h"
17
18 #include <algorithm>
19 #include <functional>
20 #include <initializer_list>
21 #include <memory>
22 #include <new>
23 #include <string>
24
25 #include "event_manager.h"
26 #include "netstack_log.h"
27
28 namespace OHOS::NetStack::ModuleTemplate {
29 static constexpr const int EVENT_PARAM_NUM = 2;
30 static constexpr const char *INTERFACE_LOCAL_SOCKET = "LocalSocket";
31 static constexpr const char *INTERFACE_TLS_SOCKET = "TLSSocket";
32 static constexpr const char *INTERFACE_WEB_SOCKET = "WebSocket";
33 static constexpr const char *INTERFACE_HTTP_REQUEST = "OHOS_NET_HTTP_HttpRequest";
34
OnManagerWrapper(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events,bool asyncCallback)35 napi_value OnManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
36 bool asyncCallback)
37 {
38 napi_value thisVal = nullptr;
39 size_t paramsCount = MAX_PARAM_NUM;
40 napi_value params[MAX_PARAM_NUM] = {nullptr};
41 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
42
43 if (paramsCount != EVENT_PARAM_NUM || NapiUtils::GetValueType(env, params[0]) != napi_string ||
44 NapiUtils::GetValueType(env, params[1]) != napi_function) {
45 NETSTACK_LOGE("on off once interface para: [string, function]");
46 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
47 return NapiUtils::GetUndefined(env);
48 }
49
50 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
51 if (std::find(events.begin(), events.end(), event) == events.end()) {
52 return NapiUtils::GetUndefined(env);
53 }
54
55 EventManagerWrapper *wrapper = nullptr;
56 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
57 if (napiRet != napi_ok) {
58 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
59 return NapiUtils::GetUndefined(env);
60 }
61 if (wrapper == nullptr) {
62 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
63 return NapiUtils::GetUndefined(env);
64 }
65 auto manager = wrapper->sharedManager;
66 if (manager == nullptr) {
67 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
68 return NapiUtils::GetUndefined(env);
69 }
70 if (manager != nullptr) {
71 manager->AddListener(env, event, params[1], false, asyncCallback);
72 }
73
74 return NapiUtils::GetUndefined(env);
75 }
76
OnceManagerWrapper(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events,bool asyncCallback)77 napi_value OnceManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
78 bool asyncCallback)
79 {
80 napi_value thisVal = nullptr;
81 size_t paramsCount = MAX_PARAM_NUM;
82 napi_value params[MAX_PARAM_NUM] = {nullptr};
83 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
84
85 if (paramsCount != EVENT_PARAM_NUM || NapiUtils::GetValueType(env, params[0]) != napi_string ||
86 NapiUtils::GetValueType(env, params[1]) != napi_function) {
87 NETSTACK_LOGE("on off once interface para: [string, function]");
88 return NapiUtils::GetUndefined(env);
89 }
90
91 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
92 if (std::find(events.begin(), events.end(), event) == events.end()) {
93 return NapiUtils::GetUndefined(env);
94 }
95
96 EventManagerWrapper *wrapper = nullptr;
97 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
98 if (napiRet != napi_ok) {
99 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
100 return NapiUtils::GetUndefined(env);
101 }
102 if (wrapper == nullptr) {
103 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
104 return NapiUtils::GetUndefined(env);
105 }
106 auto manager = wrapper->sharedManager;
107 if (manager != nullptr) {
108 manager->AddListener(env, event, params[1], true, asyncCallback);
109 }
110
111 return NapiUtils::GetUndefined(env);
112 }
113
OffManagerWrapper(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events)114 napi_value OffManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events)
115 {
116 napi_value thisVal = nullptr;
117 size_t paramsCount = MAX_PARAM_NUM;
118 napi_value params[MAX_PARAM_NUM] = {nullptr};
119 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
120
121 if ((paramsCount != 1 && paramsCount != EVENT_PARAM_NUM) ||
122 NapiUtils::GetValueType(env, params[0]) != napi_string) {
123 NETSTACK_LOGE("on off once interface para: [string, function?]");
124 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
125 return NapiUtils::GetUndefined(env);
126 }
127
128 if (paramsCount == EVENT_PARAM_NUM && NapiUtils::GetValueType(env, params[1]) != napi_function) {
129 NETSTACK_LOGE("on off once interface para: [string, function]");
130 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
131 return NapiUtils::GetUndefined(env);
132 }
133
134 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
135 if (std::find(events.begin(), events.end(), event) == events.end()) {
136 return NapiUtils::GetUndefined(env);
137 }
138
139 EventManagerWrapper *wrapper = nullptr;
140 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
141 if (napiRet != napi_ok) {
142 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
143 return NapiUtils::GetUndefined(env);
144 }
145 if (wrapper == nullptr) {
146 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
147 return NapiUtils::GetUndefined(env);
148 }
149 auto manager = wrapper->sharedManager;
150 if (manager == nullptr) {
151 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
152 return NapiUtils::GetUndefined(env);
153 }
154 if (manager != nullptr) {
155 if (paramsCount == EVENT_PARAM_NUM) {
156 manager->DeleteListener(event, params[1]);
157 } else {
158 manager->DeleteListener(event);
159 }
160 }
161
162 return NapiUtils::GetUndefined(env);
163 }
164
OnSharedManager(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events,bool asyncCallback)165 napi_value OnSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
166 bool asyncCallback)
167 {
168 napi_value thisVal = nullptr;
169 size_t paramsCount = MAX_PARAM_NUM;
170 napi_value params[MAX_PARAM_NUM] = {nullptr};
171 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
172
173 if (paramsCount != EVENT_PARAM_NUM || NapiUtils::GetValueType(env, params[0]) != napi_string ||
174 NapiUtils::GetValueType(env, params[1]) != napi_function) {
175 NETSTACK_LOGE("on off once interface para: [string, function]");
176 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
177 return NapiUtils::GetUndefined(env);
178 }
179
180 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
181 if (std::find(events.begin(), events.end(), event) == events.end()) {
182 return NapiUtils::GetUndefined(env);
183 }
184
185 std::shared_ptr<EventManager> *sharedManager = nullptr;
186 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
187 if (napiRet != napi_ok) {
188 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
189 return NapiUtils::GetUndefined(env);
190 }
191 if (sharedManager == nullptr) {
192 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
193 return NapiUtils::GetUndefined(env);
194 }
195 auto manager = *sharedManager;
196 if (manager == nullptr) {
197 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
198 return NapiUtils::GetUndefined(env);
199 }
200 if (manager != nullptr) {
201 manager->AddListener(env, event, params[1], false, asyncCallback);
202 }
203
204 return NapiUtils::GetUndefined(env);
205 }
206
OnceSharedManager(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events,bool asyncCallback)207 napi_value OnceSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
208 bool asyncCallback)
209 {
210 napi_value thisVal = nullptr;
211 size_t paramsCount = MAX_PARAM_NUM;
212 napi_value params[MAX_PARAM_NUM] = {nullptr};
213 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
214
215 if (paramsCount != EVENT_PARAM_NUM || NapiUtils::GetValueType(env, params[0]) != napi_string ||
216 NapiUtils::GetValueType(env, params[1]) != napi_function) {
217 NETSTACK_LOGE("on off once interface para: [string, function]");
218 return NapiUtils::GetUndefined(env);
219 }
220
221 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
222 if (std::find(events.begin(), events.end(), event) == events.end()) {
223 return NapiUtils::GetUndefined(env);
224 }
225
226 std::shared_ptr<EventManager> *sharedManager = nullptr;
227 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
228 if (napiRet != napi_ok) {
229 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
230 return NapiUtils::GetUndefined(env);
231 }
232 if (sharedManager == nullptr) {
233 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
234 return NapiUtils::GetUndefined(env);
235 }
236 auto manager = *sharedManager;
237 if (manager != nullptr) {
238 manager->AddListener(env, event, params[1], true, asyncCallback);
239 }
240
241 return NapiUtils::GetUndefined(env);
242 }
243
OffSharedManager(napi_env env,napi_callback_info info,const std::initializer_list<std::string> & events)244 napi_value OffSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events)
245 {
246 napi_value thisVal = nullptr;
247 size_t paramsCount = MAX_PARAM_NUM;
248 napi_value params[MAX_PARAM_NUM] = {nullptr};
249 NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr));
250
251 if ((paramsCount != 1 && paramsCount != EVENT_PARAM_NUM) ||
252 NapiUtils::GetValueType(env, params[0]) != napi_string) {
253 NETSTACK_LOGE("on off once interface para: [string, function?]");
254 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
255 return NapiUtils::GetUndefined(env);
256 }
257
258 if (paramsCount == EVENT_PARAM_NUM && NapiUtils::GetValueType(env, params[1]) != napi_function) {
259 NETSTACK_LOGE("on off once interface para: [string, function]");
260 napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
261 return NapiUtils::GetUndefined(env);
262 }
263
264 std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
265 if (std::find(events.begin(), events.end(), event) == events.end()) {
266 return NapiUtils::GetUndefined(env);
267 }
268
269 std::shared_ptr<EventManager> *sharedManager = nullptr;
270 auto napiRet = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
271 if (napiRet != napi_ok) {
272 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
273 return NapiUtils::GetUndefined(env);
274 }
275 if (sharedManager == nullptr) {
276 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
277 return NapiUtils::GetUndefined(env);
278 }
279 auto manager = *sharedManager;
280 if (manager == nullptr) {
281 NETSTACK_LOGE("get event manager in napi_unwrap failed, napiRet is %{public}d", napiRet);
282 return NapiUtils::GetUndefined(env);
283 }
284 if (manager != nullptr) {
285 if (paramsCount == EVENT_PARAM_NUM) {
286 manager->DeleteListener(event, params[1]);
287 } else {
288 manager->DeleteListener(event);
289 }
290 }
291
292 return NapiUtils::GetUndefined(env);
293 }
294
DefineClass(napi_env env,napi_value exports,const std::initializer_list<napi_property_descriptor> & properties,const std::string & className)295 void DefineClass(napi_env env, napi_value exports, const std::initializer_list<napi_property_descriptor> &properties,
296 const std::string &className)
297 {
298 auto constructor = [](napi_env env, napi_callback_info info) -> napi_value {
299 napi_value thisVal = nullptr;
300 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr));
301
302 return thisVal;
303 };
304
305 napi_value jsConstructor = nullptr;
306
307 napi_property_descriptor descriptors[properties.size()];
308 std::copy(properties.begin(), properties.end(), descriptors);
309
310 NAPI_CALL_RETURN_VOID(env, napi_define_class(env, className.c_str(), NAPI_AUTO_LENGTH, constructor, nullptr,
311 properties.size(), descriptors, &jsConstructor));
312 (void)exports;
313 auto global = NapiUtils::GetGlobal(env);
314 NapiUtils::SetNamedProperty(env, global, className, jsConstructor);
315 }
316
NewInstanceWithManagerWrapper(napi_env env,napi_callback_info info,const std::string & className,Finalizer finalizer)317 napi_value NewInstanceWithManagerWrapper(napi_env env, napi_callback_info info, const std::string &className,
318 Finalizer finalizer)
319 {
320 NETSTACK_LOGD("create new instance for %{public}s", className.c_str());
321 napi_value thisVal = nullptr;
322 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr));
323
324 auto global = NapiUtils::GetGlobal(env);
325 napi_value jsConstructor = NapiUtils::GetNamedProperty(env, global, className);
326 if (NapiUtils::GetValueType(env, jsConstructor) == napi_undefined) {
327 return nullptr;
328 }
329
330 napi_value result = nullptr;
331 NAPI_CALL(env, napi_new_instance(env, jsConstructor, 0, nullptr, &result));
332
333 auto wrapper = new EventManagerWrapper;
334 auto manager = std::make_shared<EventManager>();
335 wrapper->sharedManager = manager;
336 if (className == INTERFACE_HTTP_REQUEST || className == INTERFACE_LOCAL_SOCKET ||
337 className == INTERFACE_TLS_SOCKET || className == INTERFACE_WEB_SOCKET) {
338 NETSTACK_LOGD("create reference for %{public}s", className.c_str());
339 manager->CreateEventReference(env, thisVal);
340 }
341 napi_wrap(env, result, reinterpret_cast<void *>(wrapper), finalizer, nullptr, nullptr);
342
343 return result;
344 }
345
NewInstanceWithSharedManager(napi_env env,napi_callback_info info,const std::string & className,Finalizer finalizer)346 napi_value NewInstanceWithSharedManager(napi_env env, napi_callback_info info, const std::string &className,
347 Finalizer finalizer)
348 {
349 NETSTACK_LOGD("create new instance for %{public}s", className.c_str());
350 napi_value thisVal = nullptr;
351 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr));
352
353 auto global = NapiUtils::GetGlobal(env);
354 napi_value jsConstructor = NapiUtils::GetNamedProperty(env, global, className);
355 if (NapiUtils::GetValueType(env, jsConstructor) == napi_undefined) {
356 return nullptr;
357 }
358
359 napi_value result = nullptr;
360 NAPI_CALL(env, napi_new_instance(env, jsConstructor, 0, nullptr, &result));
361
362 auto sharedManager = new (std::nothrow) std::shared_ptr<EventManager>();
363 if (sharedManager == nullptr) {
364 return result;
365 }
366 auto manager = std::make_shared<EventManager>();
367 *sharedManager = manager;
368 if (className == INTERFACE_HTTP_REQUEST || className == INTERFACE_LOCAL_SOCKET ||
369 className == INTERFACE_TLS_SOCKET || className == INTERFACE_WEB_SOCKET) {
370 NETSTACK_LOGD("create reference for %{public}s", className.c_str());
371 manager->CreateEventReference(env, thisVal);
372 }
373 napi_wrap(env, result, reinterpret_cast<void *>(sharedManager), finalizer, nullptr, nullptr);
374
375 return result;
376 }
377
NewInstanceNoManager(napi_env env,napi_callback_info info,const std::string & name,Finalizer finalizer)378 napi_value NewInstanceNoManager(napi_env env, napi_callback_info info, const std::string &name, Finalizer finalizer)
379 {
380 napi_value thisVal = nullptr;
381 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr));
382 (void)thisVal;
383 auto global = NapiUtils::GetGlobal(env);
384 napi_value jsConstructor = NapiUtils::GetNamedProperty(env, global, name);
385 if (NapiUtils::GetValueType(env, jsConstructor) == napi_undefined) {
386 return nullptr;
387 }
388
389 napi_value result = nullptr;
390 NAPI_CALL(env, napi_new_instance(env, jsConstructor, 0, nullptr, &result));
391
392 return result;
393 }
394 } // namespace OHOS::NetStack::ModuleTemplate
395