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 #ifdef SUPPORT_SYSVPN
21 #include <utility>
22 #endif // SUPPORT_SYSVPN
23
24 #include <napi/native_common.h>
25 #include <uv.h>
26
27 #include "module_template.h"
28 #include "napi_utils.h"
29 #include "netmanager_ext_log.h"
30 #include "networkvpn_client.h"
31
32 namespace OHOS {
33 namespace NetManagerStandard {
34 namespace {
35 constexpr const char *CONNECT = "connect";
36 #ifdef SUPPORT_SYSVPN
37 constexpr const char *CONNECT_MULTI = "connectMulti";
38 #endif // SUPPORT_SYSVPN
39 constexpr int32_t PARAM_JUST_OPTIONS = 1;
40 constexpr int32_t PARAM_OPTIONS_AND_CALLBACK = 2;
41
42 #ifdef SUPPORT_SYSVPN
43 struct MultiVpnData {
44 bool isConnected;
45 std::string bundleName;
46 std::string vpnId;
47 };
48 #endif // SUPPORT_SYSVPN
49
EventConnectCallback(uv_work_t * work,int status)50 void EventConnectCallback(uv_work_t *work, int status)
51 {
52 if (work == nullptr) {
53 NETMANAGER_EXT_LOGE("work is nullptr");
54 return;
55 }
56 auto workWrapper = reinterpret_cast<UvWorkWrapper *>(work->data);
57 if (workWrapper == nullptr) {
58 NETMANAGER_EXT_LOGE("workWrapper is nullptr");
59 delete work;
60 return;
61 }
62 bool *data = reinterpret_cast<bool *>(workWrapper->data);
63 if (data == nullptr) {
64 NETMANAGER_EXT_LOGE("isConnected is nullptr");
65 delete workWrapper;
66 delete work;
67 return;
68 }
69
70 napi_env env = workWrapper->env;
71 napi_handle_scope scope = NapiUtils::OpenScope(env);
72 napi_value isConnected = NapiUtils::GetBoolean(env, *data);
73 napi_value result = NapiUtils::CreateObject(env);
74 NapiUtils::SetNamedProperty(env, result, "isConnected", isConnected);
75 workWrapper->manager->Emit(CONNECT, std::make_pair(NapiUtils::GetUndefined(env), result));
76 NapiUtils::CloseScope(env, scope);
77 delete data;
78 delete workWrapper;
79 delete work;
80 }
81
82 #ifdef SUPPORT_SYSVPN
EventConnectMultiCallback(uv_work_t * work,int status)83 void EventConnectMultiCallback(uv_work_t *work, int status)
84 {
85 if (work == nullptr) {
86 NETMANAGER_EXT_LOGE("work is nullptr");
87 return;
88 }
89 auto workWrapper = reinterpret_cast<UvWorkWrapper *>(work->data);
90 if (workWrapper == nullptr) {
91 NETMANAGER_EXT_LOGE("workWrapper is nullptr");
92 delete work;
93 return;
94 }
95 MultiVpnData *data = reinterpret_cast<MultiVpnData *>(workWrapper->data);
96 if (data == nullptr) {
97 NETMANAGER_EXT_LOGE("MultiVpnData is nullptr");
98 delete workWrapper;
99 delete work;
100 return;
101 }
102
103 napi_env env = workWrapper->env;
104 napi_handle_scope scope = NapiUtils::OpenScope(env);
105 napi_value obj = NapiUtils::CreateObject(env);
106 NapiUtils::SetBooleanProperty(env, obj, "isConnected", data->isConnected);
107 NapiUtils::SetStringPropertyUtf8(env, obj, "bundleName", data->bundleName);
108 NapiUtils::SetStringPropertyUtf8(env, obj, "vpnId", data->vpnId);
109 workWrapper->manager->Emit(CONNECT_MULTI, std::make_pair(NapiUtils::GetUndefined(env), obj));
110 NapiUtils::CloseScope(env, scope);
111 delete data;
112 delete workWrapper;
113 delete work;
114 }
115 #endif // SUPPORT_SYSVPN
116
CheckParamType(napi_env env,napi_value * params,size_t paramsCount)117 bool CheckParamType(napi_env env, napi_value *params, size_t paramsCount)
118 {
119 switch (paramsCount) {
120 case PARAM_JUST_OPTIONS:
121 return (NapiUtils::GetValueType(env, params[0]) == napi_string);
122 case PARAM_OPTIONS_AND_CALLBACK:
123 return ((NapiUtils::GetValueType(env, params[0]) == napi_string) &&
124 (NapiUtils::GetValueType(env, params[1]) == napi_function));
125 default:
126 return false;
127 }
128 }
129 } // namespace
130
OnVpnStateChanged(bool isConnected)131 int32_t VpnEventCallback::OnVpnStateChanged(bool isConnected)
132 {
133 auto manager = VpnMonitor::GetInstance().GetManager();
134 bool *data = new bool(isConnected);
135 manager->EmitByUv(CONNECT, reinterpret_cast<void *>(data), EventConnectCallback);
136 return ERR_OK;
137 }
138
OnMultiVpnStateChanged(bool isConnected,const std::string & bundleName,const std::string & vpnId)139 int32_t VpnEventCallback::OnMultiVpnStateChanged(bool isConnected, const std::string &bundleName,
140 const std::string &vpnId)
141 {
142 #ifdef SUPPORT_SYSVPN
143 auto manager = VpnMonitor::GetInstance().GetManager();
144 MultiVpnData *data = new MultiVpnData();
145 data->isConnected = isConnected;
146 data->bundleName = bundleName;
147 data->vpnId = vpnId;
148 manager->EmitByUv(CONNECT_MULTI, reinterpret_cast<void *>(data), EventConnectMultiCallback);
149 #endif // SUPPORT_SYSVPN
150 return ERR_OK;
151 }
152
VpnMonitor()153 VpnMonitor::VpnMonitor()
154 {
155 manager_ = std::make_shared<EventManager>();
156 }
157
158 VpnMonitor::~VpnMonitor() = default;
159
GetInstance()160 VpnMonitor &VpnMonitor::GetInstance()
161 {
162 static VpnMonitor instance;
163 return instance;
164 }
165
On(napi_env env,napi_callback_info info)166 napi_value VpnMonitor::On(napi_env env, napi_callback_info info)
167 {
168 #ifdef SUPPORT_SYSVPN
169 std::string event;
170 if (!ParseParams(env, info, event)) {
171 NETMANAGER_EXT_LOGE("parse failed");
172 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
173 return NapiUtils::GetUndefined(env);
174 }
175 Register(env, event);
176 #else
177 if (!ParseParams(env, info)) {
178 NETMANAGER_EXT_LOGE("parse failed");
179 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
180 return NapiUtils::GetUndefined(env);
181 }
182 Register(env);
183 #endif // SUPPORT_SYSVPN
184 return NapiUtils::GetUndefined(env);
185 }
186
Off(napi_env env,napi_callback_info info)187 napi_value VpnMonitor::Off(napi_env env, napi_callback_info info)
188 {
189 #ifdef SUPPORT_SYSVPN
190 std::string event;
191 if (!ParseParams(env, info, event)) {
192 NETMANAGER_EXT_LOGE("parse failed");
193 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
194 return NapiUtils::GetUndefined(env);
195 }
196 Unregister(env, event);
197 #else
198 if (!ParseParams(env, info)) {
199 NETMANAGER_EXT_LOGE("parse failed");
200 NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
201 return NapiUtils::GetUndefined(env);
202 }
203 Unregister(env);
204 #endif // SUPPORT_SYSVPN
205 return NapiUtils::GetUndefined(env);
206 }
207
208 #ifdef SUPPORT_SYSVPN
ParseParams(napi_env env,napi_callback_info info,std::string & event)209 bool VpnMonitor::ParseParams(napi_env env, napi_callback_info info, std::string &event)
210 {
211 napi_value jsObject = nullptr;
212 size_t paramsCount = MAX_PARAM_NUM;
213 napi_value params[MAX_PARAM_NUM] = {nullptr};
214 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, ¶msCount, params, &jsObject, nullptr), false);
215
216 if (!CheckParamType(env, params, paramsCount)) {
217 NETMANAGER_EXT_LOGE("CheckParamType failed");
218 return false;
219 }
220 if (manager_ == nullptr) {
221 NETMANAGER_EXT_LOGE("manager_ is nullptr");
222 return false;
223 }
224 const std::string eventType = NapiUtils::GetStringFromValueUtf8(env, params[0]);
225 if (CONNECT != eventType && CONNECT_MULTI != eventType) {
226 NETMANAGER_EXT_LOGE("%{public}s eventtyep is error", eventType.c_str());
227 return false;
228 }
229 event = eventType;
230 if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
231 callback_ = params[1];
232 }
233 return true;
234 }
235
Register(napi_env env,const std::string & event)236 void VpnMonitor::Register(napi_env env, const std::string &event)
237 {
238 if (manager_ == nullptr) {
239 NETMANAGER_EXT_LOGE("manager_ is nullptr");
240 return;
241 }
242 manager_->AddListener(env, event, callback_, false, false);
243 if (CONNECT == event) {
244 if (eventCallback_ != nullptr) {
245 NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
246 }
247 eventCallback_ = new (std::nothrow) VpnEventCallback();
248 if (nullptr == eventCallback_) {
249 NETMANAGER_EXT_LOGE("eventCallback_ is nullptr");
250 return;
251 }
252 NetworkVpnClient::GetInstance().RegisterVpnEvent(eventCallback_);
253 return;
254 }
255 if (CONNECT_MULTI == event) {
256 if (multiEventCallback_ != nullptr) {
257 NetworkVpnClient::GetInstance().UnregisterMultiVpnEvent(multiEventCallback_);
258 }
259 multiEventCallback_ = new (std::nothrow) VpnEventCallback();
260 if (nullptr == multiEventCallback_) {
261 NETMANAGER_EXT_LOGE("eventCallback_ is nullptr");
262 return;
263 }
264 NetworkVpnClient::GetInstance().RegisterMultiVpnEvent(multiEventCallback_);
265 return;
266 }
267 }
268
Unregister(napi_env env,const std::string & event)269 void VpnMonitor::Unregister(napi_env env, const std::string &event)
270 {
271 if (manager_ == nullptr) {
272 NETMANAGER_EXT_LOGE("manager_ is nullptr");
273 return;
274 }
275 manager_->DeleteListener(event);
276 if (CONNECT == event) {
277 NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
278 return;
279 }
280 if (CONNECT_MULTI == event) {
281 NetworkVpnClient::GetInstance().UnregisterMultiVpnEvent(multiEventCallback_);
282 return;
283 }
284 }
285 #endif // SUPPORT_SYSVPN
286
ParseParams(napi_env env,napi_callback_info info)287 bool VpnMonitor::ParseParams(napi_env env, napi_callback_info info)
288 {
289 napi_value jsObject = nullptr;
290 size_t paramsCount = MAX_PARAM_NUM;
291 napi_value params[MAX_PARAM_NUM] = {nullptr};
292 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, ¶msCount, params, &jsObject, nullptr), false);
293
294 if (!CheckParamType(env, params, paramsCount)) {
295 NETMANAGER_EXT_LOGE("CheckParamType failed");
296 return false;
297 }
298 if (manager_ == nullptr) {
299 NETMANAGER_EXT_LOGE("manager_ is nullptr");
300 return false;
301 }
302 const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
303 if (CONNECT != event) {
304 NETMANAGER_EXT_LOGE("%{public}s event is error", event.c_str());
305 return false;
306 }
307 if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
308 callback_ = params[1];
309 }
310 return true;
311 }
312
Register(napi_env env)313 void VpnMonitor::Register(napi_env env)
314 {
315 if (manager_ == nullptr) {
316 NETMANAGER_EXT_LOGE("manager_ is nullptr");
317 return;
318 }
319 manager_->AddListener(env, CONNECT, callback_, false, false);
320
321 if (eventCallback_ != nullptr) {
322 NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
323 }
324 eventCallback_ = new (std::nothrow) VpnEventCallback();
325 if (nullptr == eventCallback_) {
326 NETMANAGER_EXT_LOGE("eventCallback_ is nullptr");
327 return;
328 }
329 NetworkVpnClient::GetInstance().RegisterVpnEvent(eventCallback_);
330 }
331
Unregister(napi_env env)332 void VpnMonitor::Unregister(napi_env env)
333 {
334 if (manager_ == nullptr) {
335 NETMANAGER_EXT_LOGE("manager_ is nullptr");
336 return;
337 }
338 manager_->DeleteListener(CONNECT);
339 NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
340 }
341 } // namespace NetManagerStandard
342 } // namespace OHOS