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 "session_manager.h"
17
18 #include <uv.h>
19
20 #include "napi/native_node_api.h"
21 #include "node_api.h"
22
23 #include "client_helper.h"
24 #include "update_define.h"
25 #include "update_session.h"
26
27 using namespace std;
28
29 namespace OHOS::UpdateService {
SessionManager(napi_env env,napi_ref thisReference)30 SessionManager::SessionManager(napi_env env, napi_ref thisReference) : env_(env), thisReference_(thisReference)
31 {
32 ENGINE_LOGI("SessionManager constructor");
33 }
34
~SessionManager()35 SessionManager::~SessionManager()
36 {
37 ENGINE_LOGI("SessionManager destructor");
38 if (thisReference_ != nullptr) {
39 napi_delete_reference(env_, thisReference_);
40 thisReference_ = nullptr;
41 }
42 }
43
AddSession(std::shared_ptr<BaseSession> session)44 void SessionManager::AddSession(std::shared_ptr<BaseSession> session)
45 {
46 PARAM_CHECK(session != nullptr, return, "Invalid param");
47 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
48 sessions_.insert(make_pair(session->GetSessionId(), session));
49 }
50
RemoveSession(uint32_t sessionId)51 void SessionManager::RemoveSession(uint32_t sessionId)
52 {
53 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
54 sessions_.erase(sessionId);
55 }
56
GetFirstSessionId(uint32_t & sessionId)57 bool SessionManager::GetFirstSessionId(uint32_t &sessionId)
58 {
59 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
60 {
61 if (sessions_.empty()) {
62 return false;
63 }
64 sessionId = sessions_.begin()->second->GetSessionId();
65 return true;
66 }
67 }
68
GetNextSessionId(uint32_t & sessionId)69 bool SessionManager::GetNextSessionId(uint32_t &sessionId)
70 {
71 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
72 {
73 auto iter = sessions_.find(sessionId);
74 if (iter == sessions_.end()) {
75 return false;
76 }
77 iter++;
78 if (iter == sessions_.end()) {
79 return false;
80 }
81 sessionId = iter->second->GetSessionId();
82 }
83 return true;
84 }
85
ProcessUnsubscribe(const std::string & eventType,size_t argc,napi_value arg)86 int32_t SessionManager::ProcessUnsubscribe(const std::string &eventType, size_t argc, napi_value arg)
87 {
88 napi_handle_scope scope;
89 napi_status status = napi_open_handle_scope(env_, &scope);
90 PARAM_CHECK(status == napi_ok, return -1, "Error open handle");
91
92 uint32_t nextSessId = 0;
93 bool hasNext = GetFirstSessionId(nextSessId);
94 while (hasNext) {
95 uint32_t currSessId = nextSessId;
96 auto iter = sessions_.find(currSessId);
97 if (iter == sessions_.end()) {
98 break;
99 }
100 hasNext = GetNextSessionId(nextSessId);
101
102 auto listener = (std::shared_ptr<UpdateListener> &)(iter->second);
103 if (listener == nullptr) {
104 iter = sessions_.erase(iter);
105 continue;
106 }
107 if (listener->GetType() != SessionType::SESSION_SUBSCRIBE ||
108 eventType.compare(listener->GetEventType()) != 0) {
109 continue;
110 }
111 ENGINE_LOGI("ProcessUnsubscribe remove session");
112 if (argc == 1) {
113 listener->RemoveHandlerRef(env_);
114 RemoveSession(currSessId);
115 } else if (listener->CheckEqual(env_, arg, eventType)) {
116 listener->RemoveHandlerRef(env_);
117 RemoveSession(currSessId);
118 break;
119 }
120 }
121 napi_close_handle_scope(env_, scope);
122 return 0;
123 }
124
Unsubscribe(const EventClassifyInfo & eventClassifyInfo,napi_value handle)125 void SessionManager::Unsubscribe(const EventClassifyInfo &eventClassifyInfo, napi_value handle)
126 {
127 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
128 for (auto iter = sessions_.begin(); iter != sessions_.end();) {
129 if (iter->second == nullptr) {
130 iter = sessions_.erase(iter); // erase nullptr
131 continue;
132 }
133
134 if (iter->second->GetType() != SessionType::SESSION_SUBSCRIBE) {
135 ++iter;
136 continue;
137 }
138
139 auto listener = (std::shared_ptr<UpdateListener> &)(iter->second);
140 if (handle == nullptr && listener->IsSubscribeEvent(eventClassifyInfo)) {
141 ENGINE_LOGI("Unsubscribe, remove session %{public}d without handle", listener->GetSessionId());
142 listener->RemoveHandlerRef(env_);
143 iter = sessions_.erase(iter);
144 continue;
145 }
146
147 if (listener->IsSameListener(env_, eventClassifyInfo, handle)) {
148 ENGINE_LOGI("Unsubscribe, remove session %{public}d", listener->GetSessionId());
149 listener->RemoveHandlerRef(env_);
150 iter = sessions_.erase(iter);
151 continue;
152 }
153
154 ++iter;
155 }
156 }
157
FindSessionByHandle(napi_env env,const std::string & eventType,napi_value arg)158 BaseSession *SessionManager::FindSessionByHandle(napi_env env, const std::string &eventType, napi_value arg)
159 {
160 uint32_t nextSessId = 0;
161 bool hasNext = GetFirstSessionId(nextSessId);
162 while (hasNext) {
163 uint32_t currSessId = nextSessId;
164 auto iter = sessions_.find(currSessId);
165 if (iter == sessions_.end()) {
166 break;
167 }
168 hasNext = GetNextSessionId(nextSessId);
169
170 auto listener = (std::shared_ptr<UpdateListener> &)(iter->second);
171 if (listener == nullptr) {
172 iter = sessions_.erase(iter);
173 continue;
174 }
175 if (listener->GetType() != SessionType::SESSION_SUBSCRIBE) {
176 continue;
177 }
178 if ((eventType.compare(listener->GetEventType()) == 0) && listener->CheckEqual(env_, arg, eventType)) {
179 return listener.get();
180 }
181 }
182 return nullptr;
183 }
184
FindSessionByHandle(napi_env env,const EventClassifyInfo & eventClassifyInfo,napi_value arg)185 BaseSession *SessionManager::FindSessionByHandle(napi_env env, const EventClassifyInfo &eventClassifyInfo,
186 napi_value arg)
187 {
188 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
189 for (auto &iter : sessions_) {
190 if (iter.second == nullptr) {
191 continue;
192 }
193
194 if (iter.second->GetType() != SessionType::SESSION_SUBSCRIBE) {
195 continue;
196 }
197
198 auto listener = (std::shared_ptr<UpdateListener> &)(iter.second);
199 if (listener->IsSameListener(env, eventClassifyInfo, arg)) {
200 return listener.get();
201 }
202 }
203 return nullptr;
204 }
205
PublishToJS(const EventClassifyInfo & eventClassifyInfo,const EventInfo & eventInfo)206 void SessionManager::PublishToJS(const EventClassifyInfo &eventClassifyInfo, const EventInfo &eventInfo)
207 {
208 napi_handle_scope scope;
209 napi_status status = napi_open_handle_scope(env_, &scope);
210 PARAM_CHECK_NAPI_CALL(env_, status == napi_ok, return, "Error open_handle_scope");
211 napi_value thisVar = nullptr;
212 status = napi_get_reference_value(env_, thisReference_, &thisVar);
213 PARAM_CHECK_NAPI_CALL(env_, status == napi_ok, napi_close_handle_scope(env_, scope); return,
214 "Error get_reference");
215
216 std::lock_guard<std::recursive_mutex> guard(sessionMutex_);
217 for (auto &iter : sessions_) {
218 if (iter.second == nullptr) {
219 continue;
220 }
221
222 if (iter.second->GetType() != SessionType::SESSION_SUBSCRIBE) {
223 continue;
224 }
225
226 auto listener = (std::shared_ptr<UpdateListener> &)(iter.second);
227 if (!listener->IsSubscribeEvent(eventClassifyInfo)) {
228 continue;
229 }
230
231 listener->NotifyJS(env_, thisVar, eventInfo);
232 }
233 napi_close_handle_scope(env_, scope);
234 }
235
Emit(const EventClassifyInfo & eventClassifyInfo,const EventInfo & eventInfo)236 void SessionManager::Emit(const EventClassifyInfo &eventClassifyInfo, const EventInfo &eventInfo)
237 {
238 ENGINE_LOGI("SessionManager::Emit 0x%{public}x", CAST_INT(eventClassifyInfo.eventClassify));
239 auto task = [eventClassifyInfo, eventInfo, this]() { PublishToJS(eventClassifyInfo, eventInfo); };
240 if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_high)) {
241 ENGINE_LOGE("PublishToJS: Failed to SendEvent");
242 }
243 }
244 } // namespace OHOS::UpdateService