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