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