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