1 /*
2 * Copyright (c) 2025 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 <algorithm>
17 #include "napi/native_node_api.h"
18 #include "eap_event_mgr.h"
19 namespace OHOS {
20 namespace NetManagerStandard {
21
22 static constexpr int32_t REGISTERINFO_MAX_NUM = 16;
23 static constexpr int32_t WIFI_DEVICE_SA_ID = 1120;
24 static constexpr int32_t COMM_ETHERNET_MANAGER_SYS_ABILITY_ID = 1157;
25 static constexpr uint32_t INVALID_REF_COUNT = 0xff;
26 static constexpr const char *EAP_BUFFER = "eapBuffer";
27 static constexpr const char *EAP_BUFFERLEN = "bufferLen";
28 static constexpr const char *EAP_MSGID = "msgId";
29 static std::shared_mutex g_regInfoMutex;
30
OnEapSupplicantPostback(NetType netType,const sptr<EapData> & eapData)31 int32_t NetEapPostBackCallback::OnEapSupplicantPostback(NetType netType, const sptr<EapData> &eapData)
32 {
33 if (eapData == nullptr) {
34 NETMANAGER_EXT_LOGE("%{public}s eapData is nullptr.", __func__);
35 return NETMANAGER_ERR_LOCAL_PTR_NULL;
36 }
37 if (eapData->eapCode < EAP_CODE_MIN || eapData->eapCode > EAP_CODE_MAX) {
38 NETMANAGER_EXT_LOGE("eapCode %{public}d invalid.", eapData->eapCode);
39 return NETMANAGER_ERR_PARAMETER_ERROR;
40 }
41 if (eapData->eapBuffer.size() == 0) {
42 NETMANAGER_EXT_LOGE("%{public}s eapBuffer size is 0. %{public}s", __func__, eapData->PrintLogInfo().c_str());
43 return NETMANAGER_ERR_PARAMETER_ERROR;
44 }
45 NETMANAGER_EXT_LOGI("%{public}s: eapCode:%{public}d, eapType:%{public}d, buffsize:%{public}zu", __func__,
46 eapData->eapCode, eapData->eapType, eapData->eapBuffer.size());
47 uint32_t composeParam = (eapData->eapCode << 8) | eapData->eapType;
48 return CheckAndNotifyApp(netType, composeParam, eapData);
49 }
50
CreateResult(const napi_env & env,const sptr<EapData> & eapData)51 napi_value NetEapPostBackCallback::CreateResult(const napi_env& env, const sptr<EapData> &eapData)
52 {
53 napi_value obj = NapiUtils::CreateObject(env);
54 if (NapiUtils::GetValueType(env, obj) != napi_object) {
55 return NapiUtils::GetUndefined(env);
56 }
57
58 NapiUtils::SetVectorUint8Property(env, obj, EAP_BUFFER, eapData->eapBuffer);
59 NapiUtils::SetUint32Property(env, obj, EAP_BUFFERLEN, eapData->bufferLen);
60 NapiUtils::SetUint32Property(env, obj, EAP_MSGID, eapData->msgId);
61 return obj;
62 }
63
CheckAndNotifyApp(NetType netType,const int32_t key,const sptr<EapData> & eapData)64 bool NetEapPostBackCallback::CheckAndNotifyApp(NetType netType, const int32_t key, const sptr<EapData> &eapData)
65 {
66 std::shared_lock<std::shared_mutex> lock(g_regInfoMutex);
67 auto regInfo = EapEventMgr::GetInstance().GetRegisterInfoMap();
68 auto netTypeIter = regInfo.find(netType);
69 if (netTypeIter == regInfo.end()) {
70 NETMANAGER_EXT_LOGE("%{public}s, netType %{public}d not find register info.", __func__, netType);
71 return false;
72 }
73 auto it = netTypeIter->second.find(key);
74 if (it == netTypeIter->second.end()) {
75 NETMANAGER_EXT_LOGE("%{public}s, not find register info.", __func__);
76 return false;
77 }
78 for (auto& each : it->second) {
79 auto func = [this, env = each.m_regEnv, eapData] () -> napi_value { return this->CreateResult(env, eapData); };
80 std::shared_ptr<AsyncEventData> asyncEvent =
81 std::make_shared<AsyncEventData>(each.m_regEnv, each.m_regHandlerRef, func);
82 asyncEvent->Init(key, netType, eapData->msgId);
83 EventNotify(asyncEvent);
84 }
85 return true;
86 }
87
SendTask(const std::shared_ptr<AsyncEventData> & asyncEvent)88 void NetEapPostBackCallback::SendTask(const std::shared_ptr<AsyncEventData> &asyncEvent)
89 {
90 napi_value handler = nullptr;
91 napi_value jsEvent = nullptr;
92 napi_value undefine;
93 uint32_t refCount = INVALID_REF_COUNT;
94 napi_status res;
95 bool unrefRef = false;
96 bool find = false;
97 InitScope(asyncEvent);
98 auto regInfo = EapEventMgr::GetInstance().GetRegisterInfoMap();
99 auto it = regInfo[asyncEvent->netType_].find(asyncEvent->key_);
100 if (it == regInfo[asyncEvent->netType_].end()) {
101 NETMANAGER_EXT_LOGE("%{public}s, event has been unregistered.", __func__);
102 EndSendTask(asyncEvent, unrefRef, refCount);
103 return;
104 }
105 for (auto& each : it->second) {
106 if (each.m_regEnv == asyncEvent->env_ && each.m_regHandlerRef == asyncEvent->callbackRef_) {
107 find = true;
108 break;
109 }
110 }
111 if (find == false) {
112 NETMANAGER_EXT_LOGE("%{public}s, NOT find the event.", __func__);
113 EndSendTask(asyncEvent, unrefRef, refCount);
114 return;
115 }
116 res = napi_reference_ref(asyncEvent->env_, asyncEvent->callbackRef_, &refCount);
117 NETMANAGER_EXT_LOGI("%{public}s, res: %{public}d, callbackRef: %{private}p, refCount: %{public}d",
118 __func__, res, asyncEvent->callbackRef_, refCount);
119 if (res != napi_ok || refCount <= 1) {
120 EndSendTask(asyncEvent, unrefRef, refCount);
121 return;
122 }
123 unrefRef = true;
124 res = napi_get_reference_value(asyncEvent->env_, asyncEvent->callbackRef_, &handler);
125 if (res != napi_ok || handler == nullptr) {
126 NETMANAGER_EXT_LOGE("%{public}s, handler is nullptr or res: %{public}d!", __func__, res);
127 EndSendTask(asyncEvent, unrefRef, refCount);
128 return;
129 }
130 napi_get_undefined(asyncEvent->env_, &undefine);
131 jsEvent = asyncEvent->packResult_();
132 if (napi_call_function(asyncEvent->env_, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
133 NETMANAGER_EXT_LOGE("%{public}s, Report event to Js failed", __func__);
134 EndSendTask(asyncEvent, unrefRef, refCount);
135 return;
136 }
137 }
138
InitScope(const std::shared_ptr<AsyncEventData> & asyncEvent)139 void NetEapPostBackCallback::InitScope(const std::shared_ptr<AsyncEventData> &asyncEvent)
140 {
141 napi_open_handle_scope(asyncEvent->env_, &scope_);
142 if (scope_ == nullptr) {
143 NETMANAGER_EXT_LOGE("napi_send_event, scope is nullptr");
144 EndSendTask(asyncEvent, false, INVALID_REF_COUNT);
145 }
146 }
147
EndSendTask(const std::shared_ptr<AsyncEventData> & asyncEvent,bool unrefRef,uint32_t refCount)148 void NetEapPostBackCallback::EndSendTask(const std::shared_ptr<AsyncEventData> &asyncEvent,
149 bool unrefRef, uint32_t refCount)
150 {
151 napi_close_handle_scope(asyncEvent->env_, scope_);
152 if (unrefRef) {
153 napi_reference_unref(asyncEvent->env_, asyncEvent->callbackRef_, &refCount);
154 }
155 }
156
EventNotify(const std::shared_ptr<AsyncEventData> & asyncEvent)157 void NetEapPostBackCallback::EventNotify(const std::shared_ptr<AsyncEventData> &asyncEvent)
158 {
159 if (asyncEvent == nullptr) {
160 NETMANAGER_EXT_LOGE("asyncEvent is null!");
161 return;
162 }
163 NETMANAGER_EXT_LOGI("Enter eap postback event notify, msgId: %{public}d", asyncEvent->msgId_);
164 auto sendTask = std::bind(&NetEapPostBackCallback::SendTask, this, asyncEvent);
165 if (napi_status::napi_ok != napi_send_event(asyncEvent->env_, sendTask, napi_eprio_immediate)) {
166 NETMANAGER_EXT_LOGE("%{public}s, Failed to SendEvent", __func__);
167 }
168 }
169
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)170 void NetManagerNapiAbilityStatusChange::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
171 {
172 NETMANAGER_EXT_LOGI("NetManagerNapiAbilityStatusChange OnAddSystemAbility systemAbilityId:%{public}d",
173 systemAbilityId);
174 std::vector<std::string> event;
175 switch (systemAbilityId) {
176 case WIFI_DEVICE_SA_ID:
177 case COMM_ETHERNET_MANAGER_SYS_ABILITY_ID: {
178 EapEventMgr::GetInstance().RegCustomEapHandler(NetType::WLAN0, RegTriggerMode::SA_LAUNCH);
179 break;
180 }
181 default:
182 NETMANAGER_EXT_LOGI("OnAddSystemAbility unhandled sysabilityId:%{public}d", systemAbilityId);
183 return;
184 }
185 }
186
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)187 void NetManagerNapiAbilityStatusChange::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
188 {
189 NETMANAGER_EXT_LOGI("NetManagerNapiAbilityStatusChange OnRemoveSystemAbility systemAbilityId:%{public}d",
190 systemAbilityId);
191 }
192
GetInstance()193 EapEventMgr &EapEventMgr::GetInstance()
194 {
195 static EapEventMgr instance;
196 return instance;
197 }
198
EapEventMgr()199 EapEventMgr::EapEventMgr():eapPostBackCallback_(sptr<NetEapPostBackCallback>::MakeSptr())
200 {
201 auto samgrProxy = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
202 if (samgrProxy == nullptr) {
203 NETMANAGER_EXT_LOGE("samgrProxy is nullptr!");
204 return;
205 }
206 sptr<NetManagerNapiAbilityStatusChange> mSaStatusListener = sptr<NetManagerNapiAbilityStatusChange>::MakeSptr();
207
208 int32_t retWifiSa = samgrProxy->SubscribeSystemAbility((int32_t)WIFI_DEVICE_SA_ID, mSaStatusListener);
209 int32_t retNetManagerSa = samgrProxy->SubscribeSystemAbility(
210 (int32_t)COMM_ETHERNET_MANAGER_SYS_ABILITY_ID, mSaStatusListener);
211 NETMANAGER_EXT_LOGI("EventRegister, SubscribeSystemAbility return retWifiSa:%{public}d, \
212 retNetManagerSa:%{public}d!", retWifiSa, retNetManagerSa);
213 }
214
RegCustomEapHandler(napi_env env,NetType netType,uint32_t eapCode,uint32_t eapType,napi_value handler)215 int32_t EapEventMgr::RegCustomEapHandler(napi_env env, NetType netType, uint32_t eapCode, uint32_t eapType,
216 napi_value handler)
217 {
218 NETMANAGER_EXT_LOGI("%{public}s enter, netType:%{public}d, eapCode:%{public}d, eapType:%{public}d", __func__,
219 static_cast<int>(netType), eapCode, eapType);
220 uint32_t composeParam = (eapCode << 8) | eapType;
221 napi_ref handlerRef = nullptr;
222 napi_create_reference(env, handler, 1, &handlerRef);
223 RegObj regObj(env, handlerRef);
224
225 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
226 auto netTypeMapIter = eventRegisterInfo_.find(netType);
227 if (netTypeMapIter == eventRegisterInfo_.end()) {
228 NETMANAGER_EXT_LOGI("%{public}s, new netType!", __func__);
229 TypeMapRegObj mapObj;
230 mapObj[composeParam] = std::vector<RegObj>{regObj};
231 eventRegisterInfo_[netType] = mapObj;
232 } else {
233 NETMANAGER_EXT_LOGI("%{public}s, exist netType!", __func__);
234 TypeMapRegObj mapObj = netTypeMapIter->second;
235 auto iter = mapObj.find(composeParam);
236 if (iter == mapObj.end()) {
237 NETMANAGER_EXT_LOGI("%{public}s, new eapCode:%{public}d, eapType:%{public}d!", __func__,
238 eapCode, eapType);
239 if (mapObj.size() > REGISTERINFO_MAX_NUM) {
240 NETMANAGER_EXT_LOGE("%{public}s, RegisterInfo Exceeding the maximum value!", __func__);
241 return EAP_ERRCODE_INTERNAL_ERROR;
242 }
243 mapObj[composeParam] = std::vector<RegObj>{regObj};
244 eventRegisterInfo_[netType] = mapObj;
245 } else {
246 auto vecIter = std::find_if(iter->second.begin(), iter->second.end(),
247 [®Obj] (const RegObj &obj) { return regObj.m_regEnv == obj.m_regEnv;});
248 if (vecIter != iter->second.end()) {
249 NETMANAGER_EXT_LOGE("%{public}s, eapCode:%{public}d, eapType:%{public}d callback is registered!",
250 __func__, eapCode, eapType);
251 return EAP_ERRCODE_SUCCESS;
252 }
253 iter->second.emplace_back(regObj);
254 NETMANAGER_EXT_LOGI("%{public}s, eapCode:%{public}d, eapType:%{public}d callback size:%{public}zu!",
255 __func__, eapCode, eapType, iter->second.size());
256 }
257 }
258 guard.unlock();
259 return RegCustomEapHandler(netType, RegTriggerMode::USER_REGISTER);
260 }
261
RegCustomEapHandler(NetType netType,RegTriggerMode triggerMode)262 int32_t EapEventMgr::RegCustomEapHandler(NetType netType, RegTriggerMode triggerMode)
263 {
264 std::string regCmd;
265 {
266 std::shared_lock<std::shared_mutex> guard(g_regInfoMutex);
267 auto mNetTypeValueIter = eventRegisterInfo_.find(netType);
268 if (mNetTypeValueIter == eventRegisterInfo_.end()) {
269 NETMANAGER_EXT_LOGE("%{public}s eventRegisterInfo_ not have eapType:%{public}d", __func__, netType);
270 return EAP_ERRCODE_INTERNAL_ERROR;
271 }
272 regCmd += std::to_string(static_cast<int>(netType));
273 regCmd += ":";
274 regCmd += std::to_string(mNetTypeValueIter->second.size());
275 for (auto &iter : mNetTypeValueIter->second) {
276 regCmd += ":";
277 regCmd += std::to_string(iter.first);
278 }
279 }
280 NETMANAGER_EXT_LOGI("%{public}s enter, triggreMode:%{public}d, netType:%{public}d, regCmd:%{public}s", __func__,
281 static_cast<int>(triggerMode), static_cast<int>(netType), regCmd.c_str());
282 return DelayedSingleton<EthernetClient>::GetInstance()->RegCustomEapHandler(netType, regCmd,
283 eapPostBackCallback_);
284 }
285
UnRegCustomEapHandler(napi_env env,NetType netType,uint32_t eapCode,uint32_t eapType,napi_value handler)286 int32_t EapEventMgr::UnRegCustomEapHandler(napi_env env, NetType netType, uint32_t eapCode, uint32_t eapType,
287 napi_value handler)
288 {
289 NETMANAGER_EXT_LOGI("%{public}s enter, netType:%{public}d, eapCode:%{public}d, eapType:%{public}d", __func__,
290 static_cast<int>(netType), eapCode, eapType);
291 uint32_t composeParam = (eapCode << 8) | eapType;
292 napi_ref handlerRef = nullptr;
293 napi_create_reference(env, handler, 1, &handlerRef);
294 RegObj regObj(env, handlerRef);
295 bool needUnregister = false;
296 {
297 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
298 auto netTypeMapIter = eventRegisterInfo_.find(netType);
299 if (netTypeMapIter == eventRegisterInfo_.end()) {
300 NETMANAGER_EXT_LOGE("%{public}s, not netType %{public}d handler", __func__, netType);
301 return EAP_ERRCODE_INTERNAL_ERROR;
302 }
303 TypeMapRegObj& mapObj = netTypeMapIter->second;
304 auto mapObjIter = mapObj.find(composeParam);
305 if (mapObjIter == mapObj.end()) {
306 NETMANAGER_EXT_LOGE("%{public}s, not composeParam %{public}d handler", __func__, composeParam);
307 return EAP_ERRCODE_INTERNAL_ERROR;
308 }
309 auto new_end = std::remove_if(mapObjIter->second.begin(), mapObjIter->second.end(),
310 [env](const RegObj& obj) { return obj.m_regEnv == env; });
311 mapObjIter->second.erase(new_end, mapObjIter->second.end());
312 // if have no callbacks, supplicant unregister this eap code and type
313 if (mapObjIter->second.size() == 0) {
314 mapObj.erase(mapObjIter);
315 needUnregister = true;
316 }
317 }
318 if (needUnregister) {
319 NETMANAGER_EXT_LOGI("%{public}s, eapCode:%{public}d, eapType:%{public}d", __func__, eapCode, eapType);
320 return UnRegCustomEapHandler(netType);
321 }
322 return true;
323 }
324
UnRegCustomEapHandler(NetType netType)325 int32_t EapEventMgr::UnRegCustomEapHandler(NetType netType)
326 {
327 return RegCustomEapHandler(netType, RegTriggerMode::UNREGISTER);
328 }
329
ReplyCustomEapData(CustomResult result,const sptr<EapData> & eapData)330 int32_t EapEventMgr::ReplyCustomEapData(CustomResult result, const sptr<EapData> &eapData)
331 {
332 return DelayedSingleton<EthernetClient>::GetInstance()->ReplyCustomEapData(static_cast<int>(result),
333 eapData);
334 }
335
GetRegisterInfoMap()336 std::map<NetType, TypeMapRegObj> EapEventMgr::GetRegisterInfoMap()
337 {
338 return eventRegisterInfo_;
339 }
340 } // namespace NetManagerStandard
341 } // namespace OHOS