1 /*
2 * Copyright (c) 2021-2022 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 "event_manager.h"
17
18 #include <map>
19 #include <algorithm>
20 #include "netstack_log.h"
21 #include "napi_utils.h"
22
23 namespace OHOS::NetStack {
24 static constexpr const int CALLBACK_PARAM_NUM = 1;
25 static constexpr const int ASYNC_CALLBACK_PARAM_NUM = 2;
26 static constexpr const char *ON_HEADER_RECEIVE = "headerReceive";
27 static constexpr const char *ON_HEADERS_RECEIVE = "headersReceive";
28
EventManager()29 EventManager::EventManager() : data_(nullptr), eventRef_(nullptr), isDestroy_(false) {}
30
~EventManager()31 EventManager::~EventManager()
32 {
33 NETSTACK_LOGD("EventManager is destructed by the destructor");
34 }
35
AddListener(napi_env env,const std::string & type,napi_value callback,bool once,bool asyncCallback)36 void EventManager::AddListener(napi_env env, const std::string &type, napi_value callback, bool once,
37 bool asyncCallback)
38 {
39 std::lock_guard lock(mutexForListenersAndEmitByUv_);
40 auto it = std::remove_if(listeners_.begin(), listeners_.end(),
41 [type](const EventListener &listener) -> bool { return listener.MatchType(type); });
42 if (it != listeners_.end()) {
43 listeners_.erase(it, listeners_.end());
44 }
45
46 listeners_.emplace_back(EventListener(env, type, callback, once, asyncCallback));
47 }
48
DeleteListener(const std::string & type,napi_value callback)49 void EventManager::DeleteListener(const std::string &type, napi_value callback)
50 {
51 std::lock_guard lock(mutexForListenersAndEmitByUv_);
52 auto it =
53 std::remove_if(listeners_.begin(), listeners_.end(), [type, callback](const EventListener &listener) -> bool {
54 return listener.Match(type, callback);
55 });
56 listeners_.erase(it, listeners_.end());
57 }
58
Emit(const std::string & type,const std::pair<napi_value,napi_value> & argv)59 void EventManager::Emit(const std::string &type, const std::pair<napi_value, napi_value> &argv)
60 {
61 std::lock_guard lock(mutexForEmitAndEmitByUv_);
62 std::for_each(listeners_.begin(), listeners_.end(), [type, argv](const EventListener &listener) {
63 if (listener.IsAsyncCallback()) {
64 /* AsyncCallback(BusinessError error, T data) */
65 napi_value arg[ASYNC_CALLBACK_PARAM_NUM] = {argv.first, argv.second};
66 listener.Emit(type, ASYNC_CALLBACK_PARAM_NUM, arg);
67 } else {
68 /* Callback(T data) */
69 napi_value arg[CALLBACK_PARAM_NUM] = {argv.second};
70 listener.Emit(type, CALLBACK_PARAM_NUM, arg);
71 }
72 });
73
74 auto it = std::remove_if(listeners_.begin(), listeners_.end(),
75 [type](const EventListener &listener) -> bool { return listener.MatchOnce(type); });
76 listeners_.erase(it, listeners_.end());
77 }
78
SetData(void * data)79 void EventManager::SetData(void *data)
80 {
81 std::lock_guard<std::mutex> lock(dataMutex_);
82 data_ = data;
83 }
84
GetData()85 void *EventManager::GetData()
86 {
87 std::lock_guard<std::mutex> lock(dataMutex_);
88 return data_;
89 }
90
SetQueueData(void * data)91 void EventManager::SetQueueData(void *data)
92 {
93 std::lock_guard<std::mutex> lock(dataQueueMutex_);
94 dataQueue_.push(data);
95 }
96
GetQueueData()97 void *EventManager::GetQueueData()
98 {
99 std::lock_guard<std::mutex> lock(dataQueueMutex_);
100 if (!dataQueue_.empty()) {
101 return dataQueue_.front();
102 }
103 NETSTACK_LOGE("eventManager data queue is empty");
104 return nullptr;
105 }
106
PopQueueData()107 void EventManager::PopQueueData()
108 {
109 std::lock_guard<std::mutex> lock(dataQueueMutex_);
110 if (!dataQueue_.empty()) {
111 dataQueue_.pop();
112 }
113 }
114
EmitByUv(const std::string & type,void * data,void (Handler)(uv_work_t *,int status))115 void EventManager::EmitByUv(const std::string &type, void *data, void(Handler)(uv_work_t *, int status))
116 {
117 std::lock_guard lock1(mutexForEmitAndEmitByUv_);
118 std::lock_guard lock2(mutexForListenersAndEmitByUv_);
119 if (!EventManager::IsManagerValid(this)) {
120 return;
121 }
122 bool foundHeader = std::find_if(listeners_.begin(), listeners_.end(), [](const EventListener &listener) {
123 return listener.MatchType(ON_HEADER_RECEIVE);
124 }) != listeners_.end();
125 bool foundHeaders = std::find_if(listeners_.begin(), listeners_.end(), [](const EventListener &listener) {
126 return listener.MatchType(ON_HEADERS_RECEIVE);
127 }) != listeners_.end();
128 if (!foundHeader && !foundHeaders) {
129 if (type == ON_HEADER_RECEIVE || type == ON_HEADERS_RECEIVE) {
130 auto tempMap = static_cast<std::map<std::string, std::string> *>(data);
131 delete tempMap;
132 }
133 } else if (foundHeader && !foundHeaders) {
134 if (type == ON_HEADERS_RECEIVE) {
135 auto tempMap = static_cast<std::map<std::string, std::string> *>(data);
136 delete tempMap;
137 }
138 } else if (!foundHeader) {
139 if (type == ON_HEADER_RECEIVE) {
140 auto tempMap = static_cast<std::map<std::string, std::string> *>(data);
141 delete tempMap;
142 }
143 }
144
145 std::for_each(listeners_.begin(), listeners_.end(), [type, data, Handler, this](const EventListener &listener) {
146 if (listener.MatchType(type)) {
147 auto workWrapper = new UvWorkWrapper(data, listener.GetEnv(), type, this);
148 listener.EmitByUv(type, workWrapper, Handler);
149 }
150 });
151 }
152
HasEventListener(const std::string & type)153 bool EventManager::HasEventListener(const std::string &type)
154 {
155 std::lock_guard lock(mutexForListenersAndEmitByUv_);
156 return std::any_of(listeners_.begin(), listeners_.end(),
157 [&type](const EventListener &listener) -> bool { return listener.MatchType(type); });
158 }
159
DeleteListener(const std::string & type)160 void EventManager::DeleteListener(const std::string &type)
161 {
162 std::lock_guard lock(mutexForListenersAndEmitByUv_);
163 auto it = std::remove_if(listeners_.begin(), listeners_.end(),
164 [type](const EventListener &listener) -> bool { return listener.MatchType(type); });
165 listeners_.erase(it, listeners_.end());
166 }
167
168 std::unordered_set<EventManager *> EventManager::validManager_;
169 std::mutex EventManager::mutexForManager_;
170
SetInvalid(EventManager * manager)171 void EventManager::SetInvalid(EventManager *manager)
172 {
173 std::lock_guard lock(mutexForManager_);
174 auto pos = validManager_.find(manager);
175 if (pos == validManager_.end()) {
176 NETSTACK_LOGE("The manager is not in the unordered_set");
177 return;
178 }
179 validManager_.erase(pos);
180 delete manager;
181 manager = nullptr;
182 }
183
IsManagerValid(EventManager * manager)184 bool EventManager::IsManagerValid(EventManager *manager)
185 {
186 std::lock_guard lock(mutexForManager_);
187 return validManager_.find(manager) != validManager_.end();
188 }
189
SetValid(EventManager * manager)190 void EventManager::SetValid(EventManager *manager)
191 {
192 std::lock_guard lock(mutexForManager_);
193 validManager_.emplace(manager);
194 }
195
CreateEventReference(napi_env env,napi_value value)196 void EventManager::CreateEventReference(napi_env env, napi_value value)
197 {
198 if (env != nullptr && value != nullptr) {
199 eventRef_ = NapiUtils::CreateReference(env, value);
200 }
201 }
202
DeleteEventReference(napi_env env)203 void EventManager::DeleteEventReference(napi_env env)
204 {
205 if (env != nullptr && eventRef_ != nullptr) {
206 NapiUtils::DeleteReference(env, eventRef_);
207 }
208 }
209
SetEventDestroy(bool flag)210 void EventManager::SetEventDestroy(bool flag)
211 {
212 isDestroy_.store(flag);
213 }
214
IsEventDestroy()215 bool EventManager::IsEventDestroy()
216 {
217 return isDestroy_.load();
218 }
219
GetWebSocketTextData()220 const std::string &EventManager::GetWebSocketTextData()
221 {
222 return webSocketTextData_;
223 }
224
AppendWebSocketTextData(void * data,size_t length)225 void EventManager::AppendWebSocketTextData(void *data, size_t length)
226 {
227 webSocketTextData_.append(reinterpret_cast<char *>(data), length);
228 }
229
GetWebSocketBinaryData()230 const std::string &EventManager::GetWebSocketBinaryData()
231 {
232 return webSocketBinaryData_;
233 }
234
AppendWebSocketBinaryData(void * data,size_t length)235 void EventManager::AppendWebSocketBinaryData(void *data, size_t length)
236 {
237 webSocketBinaryData_.append(reinterpret_cast<char *>(data), length);
238 }
239
ClearWebSocketTextData()240 void EventManager::ClearWebSocketTextData()
241 {
242 webSocketTextData_.clear();
243 }
244
ClearWebSocketBinaryData()245 void EventManager::ClearWebSocketBinaryData()
246 {
247 webSocketBinaryData_.clear();
248 }
249
UvWorkWrapper(void * theData,napi_env theEnv,std::string eventType,EventManager * eventManager)250 UvWorkWrapper::UvWorkWrapper(void *theData, napi_env theEnv, std::string eventType, EventManager *eventManager)
251 : data(theData), env(theEnv), type(std::move(eventType)), manager(eventManager)
252 {
253 }
254 } // namespace OHOS::NetStack
255