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