1 /*
2 * Copyright (C) 2025 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 "napi_link_enhance_utils.h"
17
18 #include <regex>
19 #include "napi_link_enhance_error_code.h"
20 #include "securec.h"
21 #include "softbus_access_token_adapter.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_error_code.h"
24
25 namespace Communication {
26 namespace OHOS::Softbus {
27 using namespace std;
28 static std::map<int32_t, std::string> napiErrMsgMap {
29 {LINK_ENHANCE_PERMISSION_DENIED, "Permission denied."},
30 {LINK_ENHANCE_CONNECT_TIMEOUT, "Connect timeout."},
31 {LINK_ENHANCE_CONNECT_PEER_NOT_START_SERVICE, "Peer server is not started."},
32 {LINK_ENHANCE_SERVERS_EXCEEDS, "The number of servers exceeds the limit."},
33 {LINK_ENHANCE_DUPLICATE_SERVER_NAME, "Duplicate server name."},
34 {LINK_ENHANCE_CONNECTIONS_EXCEEDS, "The number of connection exceeds the limit."},
35 {LINK_ENHANCE_CONNECTION_NOT_READY, "Connection is not ready."},
36 {LINK_ENHANCE_PARAMETER_INVALID, "Invalid parameter."},
37 {LINK_ENHANCE_INTERVAL_ERR, "Internal error."},
38 };
39
DoInJsMainThread(napi_env env,std::function<void (void)> func)40 int32_t DoInJsMainThread(napi_env env, std::function<void(void)> func)
41 {
42 if (napi_send_event(env, func, napi_eprio_high) != napi_ok) {
43 COMM_LOGE(COMM_SDK, "Failed to SendEvent");
44 return -1;
45 }
46 return 0;
47 }
48
ParseString(napi_env env,string & param,napi_value args)49 bool ParseString(napi_env env, string ¶m, napi_value args)
50 {
51 napi_valuetype valuetype;
52 napi_typeof(env, args, &valuetype);
53
54 if (valuetype != napi_string) {
55 COMM_LOGE(COMM_SDK, "Wrong argument type(%{public}d). String expected.", valuetype);
56 return false;
57 }
58 size_t size = 0;
59 if (napi_get_value_string_utf8(env, args, nullptr, 0, &size) != napi_ok) {
60 COMM_LOGE(COMM_SDK, "can not get string size");
61 return false;
62 }
63 param.reserve(size + 1);
64 param.resize(size);
65 if (napi_get_value_string_utf8(env, args, param.data(), (size + 1), &size) != napi_ok) {
66 COMM_LOGE(COMM_SDK, "can not get string value");
67 return false;
68 }
69 return true;
70 }
71
ParseInt32(napi_env env,int32_t & param,napi_value args)72 bool ParseInt32(napi_env env, int32_t ¶m, napi_value args)
73 {
74 napi_valuetype valuetype;
75 napi_typeof(env, args, &valuetype);
76 if (valuetype != napi_number) {
77 COMM_LOGE(COMM_SDK, "Wrong argument type(%{public}d). Int32 expected.", valuetype);
78 return false;
79 }
80 if (napi_get_value_int32(env, args, ¶m) != napi_ok) {
81 COMM_LOGE(COMM_SDK, "napi_get_value_int32 failed");
82 return false;
83 }
84 return true;
85 }
86
ParseUInt32(napi_env env,uint32_t & param,napi_value args)87 bool ParseUInt32(napi_env env, uint32_t ¶m, napi_value args)
88 {
89 napi_valuetype valuetype;
90 napi_typeof(env, args, &valuetype);
91 if (valuetype != napi_number) {
92 COMM_LOGE(COMM_SDK, "Wrong argument type(%{public}d). Int32 expected.", valuetype);
93 return false;
94 }
95 if (napi_get_value_uint32(env, args, ¶m) != napi_ok) {
96 COMM_LOGE(COMM_SDK, "napi_get_value_uint32 failed");
97 return false;
98 }
99 return true;
100 }
101
NapiGetUndefinedRet(napi_env env)102 napi_value NapiGetUndefinedRet(napi_env env)
103 {
104 napi_value ret = nullptr;
105 napi_get_undefined(env, &ret);
106 return ret;
107 }
108
NapiGetStringRet(napi_env env,std::string string)109 napi_value NapiGetStringRet(napi_env env, std::string string)
110 {
111 napi_value result = nullptr;
112 napi_create_string_utf8(env, string.c_str(), string.size(), &result);
113 return result;
114 }
115
NapiGetInt32Ret(napi_env env,int32_t res)116 napi_value NapiGetInt32Ret(napi_env env, int32_t res)
117 {
118 napi_value ret = nullptr;
119 napi_create_int32(env, res, &ret);
120 return ret;
121 }
122
SetNamedPropertyByInteger(napi_env env,napi_value dstObj,int32_t objName,const char * propName)123 void SetNamedPropertyByInteger(napi_env env, napi_value dstObj, int32_t objName, const char *propName)
124 {
125 napi_value prop = nullptr;
126 if (napi_create_int32(env, objName, &prop) == napi_ok) {
127 napi_set_named_property(env, dstObj, propName, prop);
128 }
129 }
130
ConnectionStateTypeInit(napi_env env)131 napi_value ConnectionStateTypeInit(napi_env env)
132 {
133 napi_value connectionStateTypeObj = nullptr;
134 napi_create_object(env, &connectionStateTypeObj);
135 SetNamedPropertyByInteger(
136 env, connectionStateTypeObj, static_cast<int32_t>(ConnectionState::STATE_DISCONNECTED), "STATE_DISCONNECTED");
137 SetNamedPropertyByInteger(
138 env, connectionStateTypeObj, static_cast<int32_t>(ConnectionState::STATE_CONNECTED), "STATE_CONNECTED");
139 return connectionStateTypeObj;
140 }
141
PropertyInit(napi_env env,napi_value exports)142 napi_value PropertyInit(napi_env env, napi_value exports)
143 {
144 napi_value connectionStateTypeObj = ConnectionStateTypeInit(env);
145
146 napi_property_descriptor exportFuncs[] = {
147 DECLARE_NAPI_PROPERTY("ConnectionState", connectionStateTypeObj),
148 };
149
150 napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
151
152 return exports;
153 }
154
NapiCallFunction(napi_env env,napi_ref callbackRef,napi_value * argv,size_t argc)155 void NapiCallFunction(napi_env env, napi_ref callbackRef, napi_value *argv, size_t argc)
156 {
157 napi_value undefined = nullptr;
158 napi_value callRet = nullptr;
159 napi_value callback = nullptr;
160 if (callbackRef == nullptr) {
161 COMM_LOGE(COMM_SDK, "callbackRef is nullptr");
162 return;
163 }
164 auto status = napi_get_reference_value(env, callbackRef, &callback);
165 if (status != napi_ok) {
166 COMM_LOGE(COMM_SDK, "napi_get_reference_value failed, status: %{public}d", status);
167 return;
168 }
169
170 status = napi_call_function(env, undefined, callback, argc, argv, &callRet);
171 if (status != napi_ok) {
172 COMM_LOGE(COMM_SDK, "napi_call_function failed, status: %{public}d", status);
173 }
174
175 // Check whether the JS application triggers an exception in callback. If it is, clear it.
176 bool isExist = false;
177 status = napi_is_exception_pending(env, &isExist);
178 COMM_LOGD(COMM_SDK, "napi_is_exception_pending status: %{public}d, isExist: %{public}d", status, isExist);
179 if (isExist) {
180 COMM_LOGE(COMM_SDK, "Clear JS application's exception");
181 napi_value exception = nullptr;
182 status = napi_get_and_clear_last_exception(env, &exception);
183 COMM_LOGD(
184 COMM_SDK, "napi_get_and_clear_last_exception status: %{public}d", status);
185 }
186 }
187
ConvertToJsErrcode(int32_t err)188 int32_t ConvertToJsErrcode(int32_t err)
189 {
190 switch (err) {
191 case SOFTBUS_ACCESS_TOKEN_DENIED:
192 return LINK_ENHANCE_PERMISSION_DENIED;
193 case SOFTBUS_CONN_GENERAL_CREATE_CLIENT_MAX:
194 return LINK_ENHANCE_CONNECTIONS_EXCEEDS;
195 case SOFTBUS_CONN_GENERAL_CONNECT_TIMEOUT:
196 return LINK_ENHANCE_CONNECT_TIMEOUT;
197 case SOFTBUS_CONN_GENERAL_SERVER_NOT_OPENED:
198 return LINK_ENHANCE_CONNECT_PEER_NOT_START_SERVICE;
199 case SOFTBUS_CONN_GENERAL_DUPLICATE_SERVER:
200 return LINK_ENHANCE_DUPLICATE_SERVER_NAME;
201 case SOFTBUS_CONN_GENERAL_CONNECTION_NOT_READY:
202 return LINK_ENHANCE_CONNECTION_NOT_READY;
203 case SOFTBUS_INVALID_PARAM:
204 return LINK_ENHANCE_PARAMETER_INVALID;
205 case SOFTBUS_CONN_GENERAL_CREATE_SERVER_MAX:
206 return LINK_ENHANCE_SERVERS_EXCEEDS;
207 default:
208 return LINK_ENHANCE_INTERVAL_ERR;
209 }
210 }
211
HandleSyncErr(const napi_env & env,int32_t errCode)212 void HandleSyncErr(const napi_env &env, int32_t errCode)
213 {
214 if (errCode == SOFTBUS_OK) {
215 return;
216 }
217 std::string errMsg = "";
218 auto iter = napiErrMsgMap.find(errCode);
219 if (iter != napiErrMsgMap.end()) {
220 errMsg = iter->second;
221 }
222
223 if (errMsg != "") {
224 napi_throw_error(env, std::to_string(errCode).c_str(), errMsg.c_str());
225 }
226 }
227
CheckAccessToken(void)228 bool CheckAccessToken(void)
229 {
230 bool isAccessToken = SoftBusCheckIsAccess();
231 if (!isAccessToken) {
232 COMM_LOGW(COMM_SDK, "no access token");
233 }
234 return isAccessToken;
235 }
236 } // namespace Softbus
237 } // namespace Communication
238