1 /*
2 * Copyright (c) 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 <uv.h>
17 #include <functional>
18 #include "scan_callback.h"
19 #include "napi/native_node_api.h"
20 #include "napi_scan_utils.h"
21 #include "scan_log.h"
22
23 namespace OHOS::Scan {
ScanCallback(napi_env env,napi_ref ref)24 ScanCallback::ScanCallback(napi_env env, napi_ref ref) : env_(env), ref_(ref), callbackFunction_(nullptr)
25 {
26 }
27
ScanCallback(std::function<void (std::vector<ScanDeviceInfo> & infos)> callbackFunction)28 ScanCallback::ScanCallback(std::function<void(std::vector<ScanDeviceInfo> &infos)>
29 callbackFunction) : env_(nullptr), ref_(nullptr), callbackFunction_(callbackFunction)
30 {
31 }
32
~ScanCallback()33 ScanCallback::~ScanCallback()
34 {
35 std::lock_guard<std::mutex> autoLock(mutex_);
36 if (env_ == nullptr || ref_ == nullptr) {
37 return;
38 }
39 SCAN_HILOGI("callback has been destroyed");
40 Param *param = new (std::nothrow) Param;
41 if (param == nullptr) {
42 return;
43 }
44 param->env = env_;
45 param->callbackRef = ref_;
46 auto task = [param]() {
47 SCAN_HILOGI("napi_send_event ScanCallback DeleteReference");
48 if (param == nullptr) {
49 return;
50 }
51 napi_handle_scope scope = nullptr;
52 napi_open_handle_scope(param->env, &scope);
53 if (scope == nullptr) {
54 delete param;
55 return;
56 }
57 napi_ref callbackRef = param->callbackRef;
58 NapiScanUtils::DeleteReference(param->env, callbackRef);
59 napi_close_handle_scope(param->env, scope);
60 delete param;
61 };
62 if (napi_send_event(env_, task, napi_eprio_low) != napi_ok) {
63 SCAN_HILOGE("Failed to send event");
64 delete param;
65 }
66 }
67
InitialCallbackParam(napi_env & env_,napi_ref & ref_,std::mutex & mutex_)68 void CallbackParam::InitialCallbackParam(napi_env &env_, napi_ref &ref_, std::mutex &mutex_)
69 {
70 std::lock_guard<std::mutex> lock(mutex_);
71 this->env = env_;
72 this->ref = ref_;
73 this->mutexPtr = &mutex_;
74 }
75
SetCallbackParam(uint32_t & state,const ScanDeviceInfoTCP & deviceInfoTCP)76 void CallbackParam::SetCallbackParam(uint32_t &state, const ScanDeviceInfoTCP &deviceInfoTCP)
77 {
78 std::lock_guard<std::mutex> lock(*mutexPtr);
79 this->state = state;
80 this->deviceInfoTCP = deviceInfoTCP;
81 }
82
SetCallbackParam(uint32_t & state,const ScanDeviceInfo & deviceInfo)83 void CallbackParam::SetCallbackParam(uint32_t &state, const ScanDeviceInfo &deviceInfo)
84 {
85 std::lock_guard<std::mutex> lock(*mutexPtr);
86 this->state = state;
87 this->deviceInfo = deviceInfo;
88 }
89
SetCallbackSyncParam(uint32_t & state,const ScanDeviceInfoSync & deviceInfoSync)90 void CallbackParam::SetCallbackSyncParam(uint32_t &state, const ScanDeviceInfoSync &deviceInfoSync)
91 {
92 std::lock_guard<std::mutex> lock(*mutexPtr);
93 this->state = state;
94 this->deviceInfoSync = deviceInfoSync;
95 }
96
SetCallbackParam(bool & isGetSucc,int32_t & sizeRead)97 void CallbackParam::SetCallbackParam(bool &isGetSucc, int32_t &sizeRead)
98 {
99 std::lock_guard<std::mutex> lock(*mutexPtr);
100 this->isGetSucc = isGetSucc;
101 this->sizeRead = sizeRead;
102 }
103
SetCallbackParam(int32_t & scanVersion)104 void CallbackParam::SetCallbackParam(int32_t &scanVersion)
105 {
106 std::lock_guard<std::mutex> lock(*mutexPtr);
107 this->scanVersion = scanVersion;
108 }
109
SetCallbackParam(std::string & message)110 void CallbackParam::SetCallbackParam(std::string &message)
111 {
112 std::lock_guard<std::mutex> lock(*mutexPtr);
113 this->message = message;
114 }
115
SetCallbackContext(CallbackParam * & callBackParam,uv_work_function & uvWorkLambda,std::mutex & mutex_)116 void CallbackContext::SetCallbackContext(CallbackParam* &callBackParam,
117 uv_work_function &uvWorkLambda, std::mutex &mutex_)
118 {
119 std::lock_guard<std::mutex> lock(mutex_);
120 this->callBackParam = callBackParam;
121 this->uvWorkLambda = uvWorkLambda;
122 }
123
CreateCallbackParam(uv_work_t * & work,CallbackParam * & param,CallbackContext * & context,bool & flag)124 void ScanCallback::CreateCallbackParam(uv_work_t *&work, CallbackParam *¶m, CallbackContext *&context, bool &flag)
125 {
126 work = new (std::nothrow) uv_work_t;
127 CHECK_AND_CREATE(work, "Failed to create uv_work_t work", flag);
128 param = new (std::nothrow) CallbackParam;
129 CHECK_AND_CREATE(param, "Failed to create CallbackParam param", flag);
130 context = new (std::nothrow) CallbackContext;
131 CHECK_AND_CREATE(context, "Failed to create CallbackContext context", flag);
132 if (!flag) {
133 DELETE_AND_NULLIFY(work);
134 DELETE_AND_NULLIFY(param);
135 DELETE_AND_NULLIFY(context);
136 }
137 }
138
ExecuteUvQueueWork(CallbackContext * & context,uv_work_t * & work,uv_loop_s * & loop)139 bool ScanCallback::ExecuteUvQueueWork(CallbackContext* &context, uv_work_t* &work, uv_loop_s *&loop)
140 {
141 work->data = context;
142 int32_t retVal = uv_queue_work(
143 loop, work, [](uv_work_t *work) {},
144 [](uv_work_t *work, int statusInt) {
145 CallbackContext *context = static_cast<CallbackContext*>(work->data);
146 CallbackParam *cbParam = context->callBackParam;
147 napi_handle_scope scope = nullptr;
148 napi_open_handle_scope(cbParam->env, &scope);
149 if (scope != nullptr) {
150 auto uvWorkLambda = context->uvWorkLambda;
151 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
152 napi_value callbackFunc = NapiScanUtils::GetReference(cbParam->env, cbParam->ref);
153 napi_value callbackResult = nullptr;
154 uvWorkLambda(cbParam, callbackFunc, callbackResult);
155 SCAN_HILOGD("run napi call deviceInfo callback fun success");
156 napi_close_handle_scope(cbParam->env, scope);
157 }
158 DELETE_AND_NULLIFY(work);
159 DELETE_AND_NULLIFY(cbParam);
160 DELETE_AND_NULLIFY(context);
161 });
162 if (retVal != 0) {
163 SCAN_HILOGE("failed to get uv_queue_work.");
164 DELETE_AND_NULLIFY(work);
165 DELETE_AND_NULLIFY(context->callBackParam);
166 DELETE_AND_NULLIFY(context);
167 return false;
168 }
169 return true;
170 }
171
OnCallback(uint32_t state,const ScanDeviceInfoTCP & info)172 bool ScanCallback::OnCallback(uint32_t state, const ScanDeviceInfoTCP &info)
173 {
174 SCAN_HILOGD("Enter OnCallback::ScanDeviceInfoTCP");
175
176 INIT_CALLBACK_PARAMS;
177
178 if (!flag) {
179 SCAN_HILOGE("ScanCallback::OnCallback ScanDeviceInfoTCP error exit");
180 return false;
181 }
182
183 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
184 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
185 callbackValues[0] = ScannerInfoHelperTCP::MakeJsObject(cbParam->env, cbParam->deviceInfoTCP);
186 napi_call_function(cbParam->env, nullptr, callbackFunc,
187 NapiScanUtils::ARGC_ONE, callbackValues, &callbackResult);
188 };
189 param->InitialCallbackParam(env_, ref_, mutex_);
190 param->SetCallbackParam(state, info);
191 context->SetCallbackContext(param, uvWorkLambda, mutex_);
192
193 return ExecuteUvQueueWork(context, work, loop);
194 }
195
OnCallback(uint32_t state,const ScanDeviceInfo & info)196 bool ScanCallback::OnCallback(uint32_t state, const ScanDeviceInfo &info)
197 {
198 SCAN_HILOGD("Enter OnCallback::ScanDeviceInfo");
199
200 INIT_CALLBACK_PARAMS;
201
202 if (!flag) {
203 SCAN_HILOGE("ScanCallback::OnCallback ScanDeviceInfo error exit");
204 return false;
205 }
206
207 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
208 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
209 callbackValues[0] = ScannerInfoHelper::MakeJsObject(cbParam->env, cbParam->deviceInfo);
210 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiScanUtils::ARGC_ONE,
211 callbackValues, &callbackResult);
212 };
213 param->InitialCallbackParam(env_, ref_, mutex_);
214 param->SetCallbackParam(state, info);
215 context->SetCallbackContext(param, uvWorkLambda, mutex_);
216
217 return ExecuteUvQueueWork(context, work, loop);
218 }
219
OnCallbackSync(uint32_t state,const ScanDeviceInfoSync & info)220 bool ScanCallback::OnCallbackSync(uint32_t state, const ScanDeviceInfoSync &info)
221 {
222 SCAN_HILOGD("Enter OnCallback::ScanDeviceInfo");
223
224 INIT_CALLBACK_PARAMS;
225
226 if (!flag) {
227 SCAN_HILOGE("ScanCallback::OnCallback ScanDeviceInfo error exit");
228 return false;
229 }
230
231 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
232 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
233 callbackValues[0] = ScannerInfoSyncHelper::MakeJsObject(cbParam->env, cbParam->deviceInfoSync);
234 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiScanUtils::ARGC_ONE,
235 callbackValues, &callbackResult);
236 };
237 param->InitialCallbackParam(env_, ref_, mutex_);
238 param->SetCallbackSyncParam(state, info);
239 context->SetCallbackContext(param, uvWorkLambda, mutex_);
240
241 return ExecuteUvQueueWork(context, work, loop);
242 }
243
OnGetFrameResCallback(bool isGetSucc,int32_t sizeRead)244 bool ScanCallback::OnGetFrameResCallback(bool isGetSucc, int32_t sizeRead)
245 {
246 SCAN_HILOGD("Enter OnCallback::OnGetFrameResCallback");
247
248 INIT_CALLBACK_PARAMS;
249
250 if (!flag) {
251 SCAN_HILOGE("ScanCallback::OnCallback OnGetFrameResCallback error exit");
252 return false;
253 }
254
255 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
256 napi_value callbackValues[NapiScanUtils::ARGC_TWO] = { 0 };
257 callbackValues[0] = NapiScanUtils::CreateBoolean(cbParam->env, cbParam->isGetSucc);
258 callbackValues[1] = NapiScanUtils::CreateInt32(cbParam->env, cbParam->sizeRead);
259 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiScanUtils::ARGC_TWO,
260 callbackValues, &callbackResult);
261 };
262 param->InitialCallbackParam(env_, ref_, mutex_);
263 param->SetCallbackParam(isGetSucc, sizeRead);
264 context->SetCallbackContext(param, uvWorkLambda, mutex_);
265
266 return ExecuteUvQueueWork(context, work, loop);
267 }
268
OnScanInitCallback(int32_t & scanVersion)269 bool ScanCallback::OnScanInitCallback(int32_t &scanVersion)
270 {
271 SCAN_HILOGD("Enter OnCallback::OnScanInitCallback");
272
273 INIT_CALLBACK_PARAMS;
274
275 if (!flag) {
276 SCAN_HILOGE("ScanCallback::OnCallback OnScanInitCallback error exit");
277 return false;
278 }
279
280 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
281 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
282 callbackValues[0] = NapiScanUtils::CreateInt32(cbParam->env, cbParam->scanVersion);
283 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiScanUtils::ARGC_ONE,
284 callbackValues, &callbackResult);
285 };
286 param->InitialCallbackParam(env_, ref_, mutex_);
287 param->SetCallbackParam(scanVersion);
288 context->SetCallbackContext(param, uvWorkLambda, mutex_);
289
290 return ExecuteUvQueueWork(context, work, loop);
291 }
292
OnSendSearchMessage(std::string & message)293 bool ScanCallback::OnSendSearchMessage(std::string &message)
294 {
295 SCAN_HILOGD("Enter OnCallback::OnSendSearchMessage");
296
297 INIT_CALLBACK_PARAMS;
298
299 if (!flag) {
300 SCAN_HILOGE("ScanCallback::OnCallback OnSendSearchMessage error exit");
301 return false;
302 }
303
304 uv_work_function uvWorkLambda = [](CallbackParam* &cbParam, napi_value &callbackFunc, napi_value &callbackResult) {
305 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
306 callbackValues[0] = NapiScanUtils::CreateStringUtf8(cbParam->env, cbParam->message);
307 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiScanUtils::ARGC_ONE,
308 callbackValues, &callbackResult);
309 };
310 param->InitialCallbackParam(env_, ref_, mutex_);
311 param->SetCallbackParam(message);
312 context->SetCallbackContext(param, uvWorkLambda, mutex_);
313
314 return ExecuteUvQueueWork(context, work, loop);
315 }
316
OnGetDevicesList(std::vector<ScanDeviceInfo> & infos)317 bool ScanCallback::OnGetDevicesList(std::vector<ScanDeviceInfo> &infos)
318 {
319 SCAN_HILOGI("Enter OnGetDevicesList");
320 if (callbackFunction_ == nullptr) {
321 SCAN_HILOGE("callbackFunction_ is a nullptr");
322 return false;
323 }
324 callbackFunction_(infos);
325 return true;
326 }
327 } // namespace OHOS::Scan
328