• 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 "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