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 
VpnMonitor()89 VpnMonitor::VpnMonitor()
90 {
91     manager_ = new EventManager();
92 }
93 
~VpnMonitor()94 VpnMonitor::~VpnMonitor()
95 {
96     if (manager_ != nullptr) {
97         delete manager_;
98         manager_ = nullptr;
99     }
100 }
101 
GetInstance()102 VpnMonitor &VpnMonitor::GetInstance()
103 {
104     static VpnMonitor instance;
105     return instance;
106 }
107 
On(napi_env env,napi_callback_info info)108 napi_value VpnMonitor::On(napi_env env, napi_callback_info info)
109 {
110     if (!ParseParams(env, info)) {
111         NETMANAGER_EXT_LOGE("parse failed");
112         NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
113         return NapiUtils::GetUndefined(env);
114     }
115     Register(env);
116     return NapiUtils::GetUndefined(env);
117 }
118 
Off(napi_env env,napi_callback_info info)119 napi_value VpnMonitor::Off(napi_env env, napi_callback_info info)
120 {
121     if (!ParseParams(env, info)) {
122         NETMANAGER_EXT_LOGE("parse failed");
123         NAPI_CALL(env, napi_throw_error(env, "0", "parse failed"));
124         return NapiUtils::GetUndefined(env);
125     }
126     Unregister(env);
127     return NapiUtils::GetUndefined(env);
128 }
129 
ParseParams(napi_env env,napi_callback_info info)130 bool VpnMonitor::ParseParams(napi_env env, napi_callback_info info)
131 {
132     napi_value jsObject = nullptr;
133     size_t paramsCount = MAX_PARAM_NUM;
134     napi_value params[MAX_PARAM_NUM] = {nullptr};
135     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &paramsCount, params, &jsObject, nullptr), false);
136 
137     if (!CheckParamType(env, params, paramsCount)) {
138         NETMANAGER_EXT_LOGE("CheckParamType failed");
139         return false;
140     }
141     if (manager_ == nullptr) {
142         NETMANAGER_EXT_LOGE("manager_ is nullptr");
143         return false;
144     }
145     const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
146     if (CONNECT != event) {
147         NETMANAGER_EXT_LOGE("%{public}s event is error", event.c_str());
148         return false;
149     }
150     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
151         callback_ = params[1];
152     }
153     return true;
154 }
155 
Register(napi_env env)156 void VpnMonitor::Register(napi_env env)
157 {
158     if (manager_ == nullptr) {
159         NETMANAGER_EXT_LOGE("manager_ is nullptr");
160         return;
161     }
162     manager_->AddListener(env, CONNECT, callback_, false, false);
163 
164     if (eventCallback_ != nullptr) {
165         NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
166     }
167     eventCallback_ = new (std::nothrow) VpnEventCallback();
168     if (nullptr == eventCallback_) {
169         NETMANAGER_EXT_LOGE("eventCallback_ is nullptr");
170         return;
171     }
172     NetworkVpnClient::GetInstance().RegisterVpnEvent(eventCallback_);
173 }
174 
Unregister(napi_env env)175 void VpnMonitor::Unregister(napi_env env)
176 {
177     if (manager_ == nullptr) {
178         NETMANAGER_EXT_LOGE("manager_ is nullptr");
179         return;
180     }
181     manager_->DeleteListener(CONNECT);
182     NetworkVpnClient::GetInstance().UnregisterVpnEvent(eventCallback_);
183 }
184 } // namespace NetManagerStandard
185 } // namespace OHOS