• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *&param, 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