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 "websocket_module.h"
17 
18 #include "constant.h"
19 #include "netstack_log.h"
20 #include "module_template.h"
21 #include "netstack_common_utils.h"
22 #include "websocket_async_work.h"
23 
24 namespace OHOS::NetStack::Websocket {
25 static bool g_appIsAtomicService = false;
26 static std::once_flag g_isAtomicServiceFlag;
27 static std::string g_appBundleName;
28 
InitWebSocketModule(napi_env env,napi_value exports)29 napi_value WebSocketModule::InitWebSocketModule(napi_env env, napi_value exports)
30 {
31     DefineWebSocketClass(env, exports);
32     InitWebSocketProperties(env, exports);
33     NapiUtils::SetEnvValid(env);
34     napi_add_env_cleanup_hook(env, NapiUtils::HookForEnvCleanup, env);
35     std::call_once(g_isAtomicServiceFlag, []() {
36         g_appIsAtomicService = CommonUtils::IsAtomicService(g_appBundleName);
37         NETSTACK_LOGI("IsAtomicService  bundleName is %{public}s, isAtomicService is %{public}d",
38                       g_appBundleName.c_str(), g_appIsAtomicService);
39     });
40     return exports;
41 }
42 
CreateWebSocket(napi_env env,napi_callback_info info)43 napi_value WebSocketModule::CreateWebSocket(napi_env env, napi_callback_info info)
44 {
45     return ModuleTemplate::NewInstanceWithSharedManager(env, info, INTERFACE_WEB_SOCKET, FinalizeWebSocketInstance);
46 }
47 
DefineWebSocketClass(napi_env env,napi_value exports)48 void WebSocketModule::DefineWebSocketClass(napi_env env, napi_value exports)
49 {
50     std::initializer_list<napi_property_descriptor> properties = {
51         DECLARE_NAPI_FUNCTION(WebSocket::FUNCTION_CONNECT, WebSocket::Connect),
52         DECLARE_NAPI_FUNCTION(WebSocket::FUNCTION_SEND, WebSocket::Send),
53         DECLARE_NAPI_FUNCTION(WebSocket::FUNCTION_CLOSE, WebSocket::Close),
54         DECLARE_NAPI_FUNCTION(WebSocket::FUNCTION_ON, WebSocket::On),
55         DECLARE_NAPI_FUNCTION(WebSocket::FUNCTION_OFF, WebSocket::Off),
56     };
57     ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_WEB_SOCKET);
58 }
59 
InitWebSocketProperties(napi_env env,napi_value exports)60 void WebSocketModule::InitWebSocketProperties(napi_env env, napi_value exports)
61 {
62     std::initializer_list<napi_property_descriptor> properties = {
63         DECLARE_NAPI_FUNCTION(FUNCTION_CREATE_WEB_SOCKET, CreateWebSocket),
64     };
65     NapiUtils::DefineProperties(env, exports, properties);
66 }
67 
FinalizeWebSocketInstance(napi_env env,void * data,void * hint)68 void WebSocketModule::FinalizeWebSocketInstance(napi_env env, void *data, void *hint)
69 {
70     NETSTACK_LOGI("websocket handle is finalized");
71     auto sharedManager = reinterpret_cast<std::shared_ptr<EventManager> *>(data);
72     delete sharedManager;
73 }
74 
Connect(napi_env env,napi_callback_info info)75 napi_value WebSocketModule::WebSocket::Connect(napi_env env, napi_callback_info info)
76 {
77     return ModuleTemplate::InterfaceWithSharedManager<ConnectContext>(
78         env, info, "WebSocketConnect",
79         [](napi_env, napi_value, ConnectContext *context) -> bool {
80             context->SetAtomicService(g_appIsAtomicService);
81             context->SetBundleName(g_appBundleName);
82             return true;
83         },
84         WebSocketAsyncWork::ExecConnect, WebSocketAsyncWork::ConnectCallback);
85 }
86 
Send(napi_env env,napi_callback_info info)87 napi_value WebSocketModule::WebSocket::Send(napi_env env, napi_callback_info info)
88 {
89     return ModuleTemplate::InterfaceWithSharedManager<SendContext>(
90         env, info, "WebSocketSend", nullptr, WebSocketAsyncWork::ExecSend, WebSocketAsyncWork::SendCallback);
91 }
92 
Close(napi_env env,napi_callback_info info)93 napi_value WebSocketModule::WebSocket::Close(napi_env env, napi_callback_info info)
94 {
95     return ModuleTemplate::InterfaceWithSharedManager<CloseContext>(
96         env, info, "WebSocketClose", nullptr, WebSocketAsyncWork::ExecClose, WebSocketAsyncWork::CloseCallback);
97 }
98 
On(napi_env env,napi_callback_info info)99 napi_value WebSocketModule::WebSocket::On(napi_env env, napi_callback_info info)
100 {
101     ModuleTemplate::OnSharedManager(env, info,
102                                     {EventName::EVENT_OPEN, EventName::EVENT_MESSAGE, EventName::EVENT_CLOSE}, true);
103     return ModuleTemplate::OnSharedManager(
104         env, info, {EventName::EVENT_ERROR, EventName::EVENT_HEADER_RECEIVE, EventName::EVENT_DATA_END}, false);
105 }
106 
Off(napi_env env,napi_callback_info info)107 napi_value WebSocketModule::WebSocket::Off(napi_env env, napi_callback_info info)
108 {
109     return ModuleTemplate::OffSharedManager(env, info,
110                                             {EventName::EVENT_OPEN, EventName::EVENT_MESSAGE, EventName::EVENT_CLOSE,
111                                              EventName::EVENT_ERROR, EventName::EVENT_DATA_END,
112                                              EventName::EVENT_HEADER_RECEIVE});
113 }
114 
115 static napi_module g_websocketModule = {
116     .nm_version = 1,
117     .nm_flags = 0,
118     .nm_filename = nullptr,
119     .nm_register_func = WebSocketModule::InitWebSocketModule,
120     .nm_modname = "net.webSocket",
121     .nm_priv = nullptr,
122     .reserved = {nullptr},
123 };
124 
RegisterWebSocketModule(void)125 extern "C" __attribute__((constructor)) void RegisterWebSocketModule(void)
126 {
127     napi_module_register(&g_websocketModule);
128 }
129 } // namespace OHOS::NetStack::Websocket
130