1 /*
2 * Copyright (c) 2023 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 "vpn_monitor.h"
17
18 #include <cstddef>
19 #include <string>
20
21 #include <napi/native_common.h>
22 #include <uv.h>
23
24 #include "module_template.h"
25 #include "napi_utils.h"
26 #include "netmanager_ext_log.h"
27 #include "networkvpn_client.h"
28
29 namespace OHOS {
30 namespace NetManagerStandard {
31 namespace {
32 constexpr const char *CONNECT = "connect";
33 constexpr int32_t PARAM_JUST_OPTIONS = 1;
34 constexpr int32_t PARAM_OPTIONS_AND_CALLBACK = 2;
35
EventConnectCallback(uv_work_t * work,int status)36 void EventConnectCallback(uv_work_t *work, int status)
37 {
38 if (work == nullptr) {
39 NETMANAGER_EXT_LOGE("work is nullptr");
40 return;
41 }
42 auto workWrapper = reinterpret_cast<UvWorkWrapper *>(work->data);
43 if (workWrapper == nullptr) {
44 NETMANAGER_EXT_LOGE("workWrapper is nullptr");
45 delete work;
46 return;
47 }
48 bool *data = reinterpret_cast<bool *>(workWrapper->data);
49 if (data == nullptr) {
50 NETMANAGER_EXT_LOGE("isConnected is nullptr");
51 delete workWrapper;
52 delete work;
53 return;
54 }
55
56 napi_env env = workWrapper->env;
57 napi_handle_scope scope = NapiUtils::OpenScope(env);
58 napi_value isConnected = NapiUtils::GetBoolean(env, *data);
59 napi_value result = NapiUtils::CreateObject(env);
60 NapiUtils::SetNamedProperty(env, result, "isConnected", isConnected);
61 workWrapper->manager->Emit(CONNECT, std::make_pair(NapiUtils::GetUndefined(env), result));
62 NapiUtils::CloseScope(env, scope);
63 delete data;
64 delete workWrapper;
65 delete work;
66 }
67
CheckParamType(napi_env env,napi_value * params,size_t paramsCount)68 bool CheckParamType(napi_env env, napi_value *params, size_t paramsCount)
69 {
70 switch (paramsCount) {
71 case PARAM_JUST_OPTIONS:
72 return (NapiUtils::GetValueType(env, params[0]) == napi_string);
73 case PARAM_OPTIONS_AND_CALLBACK:
74 return ((NapiUtils::GetValueType(env, params[0]) == napi_string) &&
75 (NapiUtils::GetValueType(env, params[1]) == napi_function));
76 default:
77 return false;
78 }
79 }
80 } // namespace
81
OnVpnStateChanged(const bool & isConnected)82 void VpnEventCallback::OnVpnStateChanged(const bool &isConnected)
83 {
84 auto manager = VpnMonitor::GetInstance().GetManager();
85 bool *data = new bool(isConnected);
86 manager->EmitByUv(CONNECT, reinterpret_cast<void *>(data), EventConnectCallback);
87 }
88
GetInstance()89 VpnMonitor &VpnMonitor::GetInstance()
90 {
91 static VpnMonitor instance;
92 return instance;
93 }
94
On(napi_env env,napi_callback_info info)95 napi_value VpnMonitor::On(napi_env env, napi_callback_info info)
96 {
97 if (!ParseParams(env, info)) {
98 NETMANAGER_EXT_LOGE("parse failed");
99 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
100 return NapiUtils::GetUndefined(env);
101 }
102 Register(env);
103 return NapiUtils::GetUndefined(env);
104 }
105
Off(napi_env env,napi_callback_info info)106 napi_value VpnMonitor::Off(napi_env env, napi_callback_info info)
107 {
108 if (!ParseParams(env, info)) {
109 NETMANAGER_EXT_LOGE("parse failed");
110 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
111 return NapiUtils::GetUndefined(env);
112 }
113 Unregister(env);
114 return NapiUtils::GetUndefined(env);
115 }
116
ParseParams(napi_env env,napi_callback_info info)117 bool VpnMonitor::ParseParams(napi_env env, napi_callback_info info)
118 {
119 napi_value jsObject = nullptr;
120 size_t paramsCount = MAX_PARAM_NUM;
121 napi_value params[MAX_PARAM_NUM] = {nullptr};
122 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, ¶msCount, params, &jsObject, nullptr), false);
123
124 if (!CheckParamType(env, params, paramsCount)) {
125 return false;
126 }
127 if (!UnwrapManager(env, jsObject)) {
128 return false;
129 }
130 const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
131 if (CONNECT != event) {
132 NETMANAGER_EXT_LOGE("%{public}s event is error", event.c_str());
133 return false;
134 }
135 if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
136 callback_ = params[1];
137 }
138 return true;
139 }
140
UnwrapManager(napi_env env,napi_value jsObject)141 bool VpnMonitor::UnwrapManager(napi_env env, napi_value jsObject)
142 {
143 NAPI_CALL_BASE(env, napi_unwrap(env, jsObject, reinterpret_cast<void **>(&manager_)), false);
144 if (manager_ == nullptr) {
145 return false;
146 }
147 return true;
148 }
149
Register(napi_env env)150 void VpnMonitor::Register(napi_env env)
151 {
152 auto vpnClient = reinterpret_cast<NetworkVpnClient *>(manager_->GetData());
153 if (vpnClient == nullptr) {
154 NETMANAGER_EXT_LOGE("vpnClient is nullptr");
155 return;
156 }
157 manager_->AddListener(env, CONNECT, callback_, false, false);
158
159 if (eventCallback_ != nullptr) {
160 vpnClient->UnregisterVpnEvent(eventCallback_);
161 }
162 eventCallback_ = new (std::nothrow) VpnEventCallback();
163 if (nullptr == eventCallback_) {
164 NETMANAGER_EXT_LOGE("eventCallback_ is nullptr");
165 return;
166 }
167 vpnClient->RegisterVpnEvent(eventCallback_);
168 }
169
Unregister(napi_env env)170 void VpnMonitor::Unregister(napi_env env)
171 {
172 auto vpnClient = reinterpret_cast<NetworkVpnClient *>(manager_->GetData());
173 if (vpnClient == nullptr) {
174 NETMANAGER_EXT_LOGE("vpnClient is nullptr");
175 return;
176 }
177 manager_->DeleteListener(CONNECT);
178 vpnClient->UnregisterVpnEvent(eventCallback_);
179 }
180 } // namespace NetManagerStandard
181 } // namespace OHOS