1 /*
2  * Copyright (C) 2021 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 "delivery_callback.h"
17 
18 #include <uv.h>
19 
20 #include "napi_util.h"
21 #include "telephony_log_wrapper.h"
22 
23 namespace OHOS {
24 namespace Telephony {
25 static constexpr const char *PDU = "pdu";
26 static const int32_t CALLBACK_VALUE_LEN = 2;
27 
DeliveryCallback(bool hasCallback,napi_env env,napi_ref thisVarRef,napi_ref callbackRef)28 DeliveryCallback::DeliveryCallback(bool hasCallback, napi_env env, napi_ref thisVarRef, napi_ref callbackRef)
29     : hasCallback_(hasCallback), env_(env), thisVarRef_(thisVarRef), callbackRef_(callbackRef)
30 {}
31 
~DeliveryCallback()32 DeliveryCallback::~DeliveryCallback()
33 {
34     env_ = nullptr;
35     thisVarRef_ = nullptr;
36     callbackRef_ = nullptr;
37 }
38 
GetCallbackValues(napi_env & env,const std::string & pdu,napi_value * values,uint32_t len)39 void GetCallbackValues(napi_env &env, const std::string &pdu, napi_value *values, uint32_t len)
40 {
41     if (len < CALLBACK_VALUE_LEN) {
42         TELEPHONY_LOGE("callback values len invalid");
43         return;
44     }
45     if (!pdu.empty()) {
46         values[0] = NapiUtil::CreateUndefined(env);
47         napi_create_object(env, &values[1]);
48         napi_value arrayValue = nullptr;
49         napi_create_array(env, &arrayValue);
50         for (uint32_t i = 0; i < static_cast<uint32_t>(pdu.size()); ++i) {
51             napi_value element = nullptr;
52             int32_t intValue = pdu[i];
53             napi_create_int32(env, intValue, &element);
54             napi_set_element(env, arrayValue, i, element);
55         }
56         napi_set_named_property(env, values[1], PDU, arrayValue);
57     } else {
58         values[0] = NapiUtil::CreateErrorMessage(env, "invalid delivery report");
59         values[1] = NapiUtil::CreateUndefined(env);
60     }
61 }
62 
CompleteSmsDeliveryWork(uv_work_t * work,int status)63 void CompleteSmsDeliveryWork(uv_work_t *work, int status)
64 {
65     TELEPHONY_LOGI("CompleteSmsDeliveryWork start");
66     if (work == nullptr) {
67         TELEPHONY_LOGE("CompleteSmsDeliveryWork work is nullptr");
68         return;
69     }
70     std::unique_ptr<DeliveryCallbackContext> pContext(static_cast<DeliveryCallbackContext *>(work->data));
71     if (pContext == nullptr) {
72         TELEPHONY_LOGE("CompleteSmsDeliveryWork pContext is nullptr!");
73         delete work;
74         work = nullptr;
75         return;
76     }
77     napi_env env_ = pContext->env;
78     napi_ref thisVarRef_ = pContext->thisVarRef;
79     napi_ref callbackRef_ = pContext->callbackRef;
80     std::string pduStr_ = pContext->pduStr;
81     napi_handle_scope scope = nullptr;
82     napi_open_handle_scope(env_, &scope);
83     if (scope == nullptr) {
84         TELEPHONY_LOGE("scope is nullptr");
85         delete work;
86         work = nullptr;
87         return;
88     }
89     napi_value callbackFunc = nullptr;
90     napi_get_reference_value(env_, callbackRef_, &callbackFunc);
91     napi_value callbackValues[CALLBACK_VALUE_LEN] = { 0 };
92     GetCallbackValues(env_, pduStr_, callbackValues, CALLBACK_VALUE_LEN);
93     napi_value callbackResult = nullptr;
94     napi_value thisVar = nullptr;
95     size_t argc = sizeof(callbackValues) / sizeof(callbackValues[0]);
96     napi_get_reference_value(env_, thisVarRef_, &thisVar);
97     napi_call_function(env_, thisVar, callbackFunc, argc, callbackValues, &callbackResult);
98     napi_delete_reference(env_, thisVarRef_);
99     napi_delete_reference(env_, callbackRef_);
100     napi_close_handle_scope(env_, scope);
101     delete work;
102     work = nullptr;
103     TELEPHONY_LOGI("CompleteSmsDeliveryWork end");
104 }
105 
OnSmsDeliveryResult(const std::u16string & pdu)106 void DeliveryCallback::OnSmsDeliveryResult(const std::u16string &pdu)
107 {
108     TELEPHONY_LOGI("OnSmsDeliveryResult start");
109     if (hasCallback_) {
110         uv_work_t *work = new uv_work_t;
111         if (work == nullptr) {
112             TELEPHONY_LOGE("OnSmsDeliveryResult work is nullptr!");
113             return;
114         }
115         uv_loop_s *loop = nullptr;
116         napi_get_uv_event_loop(env_, &loop);
117         DeliveryCallbackContext *pContext = std::make_unique<DeliveryCallbackContext>().release();
118         if (pContext == nullptr) {
119             TELEPHONY_LOGE("OnSmsDeliveryResult pContext is nullptr!");
120             delete work;
121             work = nullptr;
122             return;
123         }
124         pContext->env = env_;
125         pContext->thisVarRef = thisVarRef_;
126         pContext->callbackRef = callbackRef_;
127         pContext->pduStr = NapiUtil::ToUtf8(pdu);
128         work->data = static_cast<void *>(pContext);
129         int32_t errCode = uv_queue_work_with_qos(
130             loop, work, [](uv_work_t *work) {},
131             [](uv_work_t *work, int status) { CompleteSmsDeliveryWork(work, status); }, uv_qos_default);
132         if (errCode != 0) {
133             TELEPHONY_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", errCode);
134             pContext->env = nullptr;
135             pContext->thisVarRef = nullptr;
136             pContext->callbackRef = nullptr;
137             delete pContext;
138             pContext = nullptr;
139             delete work;
140             work = nullptr;
141         }
142     }
143 }
144 } // namespace Telephony
145 } // namespace OHOS