• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramsCount, 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, &paramsCount, 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