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 #include "napi_link_enhance_server.h"
16
17 #include "napi_link_enhance_error_code.h"
18 #include "napi_link_enhance_utils.h"
19 #include "softbus_error_code.h"
20 #include "softbus_connection.h"
21
22 namespace Communication {
23 namespace OHOS::Softbus {
24
25 thread_local napi_ref NapiLinkEnhanceServer::consRef_ = nullptr;
26
27 std::unordered_map<std::string, NapiLinkEnhanceServer *> NapiLinkEnhanceServer::enhanceServerMap_;
28 std::mutex NapiLinkEnhanceServer::serverMapMutex_;
29
CheckCreateServerParams(napi_env env,napi_callback_info info,napi_value & outResult)30 static napi_status CheckCreateServerParams(napi_env env, napi_callback_info info, napi_value &outResult)
31 {
32 size_t argc = ARGS_SIZE_ONE;
33 napi_value argv[ARGS_SIZE_ONE] = { 0 };
34
35 NAPI_SOFTBUS_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
36 NAPI_SOFTBUS_RETURN_IF(
37 argc != ARGS_SIZE_ONE, "expect 1 args", napi_invalid_arg);
38
39 std::string name {};
40 if (!ParseString(env, name, argv[ARGS_SIZE_ZERO])) {
41 COMM_LOGE(COMM_SDK, "expect string");
42 return napi_string_expected;
43 }
44 if (name.length() == 0) {
45 COMM_LOGE(COMM_SDK, "invalid name");
46 return napi_invalid_arg;
47 }
48 napi_value constructor = nullptr;
49 if (NapiLinkEnhanceServer::consRef_ == nullptr) {
50 return napi_string_expected;
51 }
52 NAPI_SOFTBUS_CALL_RETURN(napi_get_reference_value(env, NapiLinkEnhanceServer::consRef_, &constructor));
53 NAPI_SOFTBUS_CALL_RETURN(napi_new_instance(env, constructor, argc, argv, &outResult));
54 return napi_ok;
55 }
56
Create(napi_env env,napi_callback_info info)57 napi_value NapiLinkEnhanceServer::Create(napi_env env, napi_callback_info info)
58 {
59 if (!CheckAccessToken()) {
60 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
61 return NapiGetUndefinedRet(env);
62 }
63 napi_value result;
64 auto status = CheckCreateServerParams(env, info, result);
65 if (status != napi_ok) {
66 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
67 return NapiGetUndefinedRet(env);
68 }
69 return result;
70 }
71
DefineJSClass(napi_env env)72 void NapiLinkEnhanceServer::DefineJSClass(napi_env env)
73 {
74 napi_property_descriptor serverDesc[] = {
75 DECLARE_NAPI_FUNCTION("start", Start),
76 DECLARE_NAPI_FUNCTION("stop", Stop),
77 DECLARE_NAPI_FUNCTION("close", Close),
78 DECLARE_NAPI_FUNCTION("on", On),
79 DECLARE_NAPI_FUNCTION("off", Off),
80 };
81
82 napi_value constructor = nullptr;
83 napi_define_class(env, "Server", NAPI_AUTO_LENGTH, Constructor, nullptr,
84 sizeof(serverDesc) / sizeof(serverDesc[0]), serverDesc, &constructor);
85 napi_create_reference(env, constructor, 1, &consRef_);
86 }
87
Constructor(napi_env env,napi_callback_info info)88 napi_value NapiLinkEnhanceServer::Constructor(napi_env env, napi_callback_info info)
89 {
90 napi_value thisVar = nullptr;
91
92 size_t argc = ARGS_SIZE_ONE;
93 napi_value argv[ARGS_SIZE_ONE] = {0};
94
95 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
96 if (argc != ARGS_SIZE_ONE) {
97 COMM_LOGE(COMM_SDK, "expect one args");
98 return NapiGetUndefinedRet(env);
99 }
100 std::string name = "";
101 if (!ParseString(env, name, argv[PARAM0])) {
102 COMM_LOGE(COMM_SDK, "Parse name failed ");
103 return NapiGetUndefinedRet(env);
104 }
105 {
106 std::lock_guard<std::mutex> guard(serverMapMutex_);
107 if (enhanceServerMap_.find(name) != enhanceServerMap_.end()) {
108 HandleSyncErr(env, LINK_ENHANCE_DUPLICATE_SERVER_NAME);
109 return NapiGetUndefinedRet(env);
110 }
111 }
112 NapiLinkEnhanceServer* enhanceServer = new NapiLinkEnhanceServer(name);
113 if (enhanceServer == nullptr) {
114 COMM_LOGE(COMM_SDK, "new enhanceServer failed");
115 return NapiGetUndefinedRet(env);
116 }
117 auto status = napi_wrap(
118 env, thisVar, enhanceServer,
119 [](napi_env env, void* data, void* hint) {
120 NapiLinkEnhanceServer* server = static_cast<NapiLinkEnhanceServer*>(data);
121 if (server) {
122 delete server;
123 server = nullptr;
124 }
125 },
126 nullptr,
127 nullptr);
128 if (status != napi_ok) {
129 COMM_LOGE(COMM_SDK, "napi_wrap failed");
130 delete enhanceServer;
131 enhanceServer = nullptr;
132 return thisVar;
133 }
134 enhanceServer->env_ = env;
135 {
136 std::lock_guard<std::mutex> guard(serverMapMutex_);
137 enhanceServerMap_[name] = enhanceServer;
138 }
139
140 return thisVar;
141 }
142
NapiGetEnhanceServer(napi_env env,napi_value thisVar)143 static NapiLinkEnhanceServer *NapiGetEnhanceServer(napi_env env, napi_value thisVar)
144 {
145 NapiLinkEnhanceServer *enhanceServer = nullptr;
146 auto status = napi_unwrap(env, thisVar, (void **)&enhanceServer);
147 if (status != napi_ok) {
148 return nullptr;
149 }
150 return enhanceServer;
151 }
152
NapiGetEnhanceServer(napi_env env,napi_callback_info info)153 static NapiLinkEnhanceServer *NapiGetEnhanceServer(napi_env env, napi_callback_info info)
154 {
155 size_t argc = 0;
156 napi_value thisVar = nullptr;
157 if (napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr) != napi_ok) {
158 return nullptr;
159 }
160 return NapiGetEnhanceServer(env, thisVar);
161 }
162
CheckAccessTokenAndParams(napi_env env,napi_callback_info info,std::string & funcName)163 static bool CheckAccessTokenAndParams(napi_env env, napi_callback_info info, std::string &funcName)
164 {
165 if (!CheckAccessToken()) {
166 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
167 return false;
168 }
169 size_t argc = ARGS_SIZE_TWO;
170 napi_value args[ARGS_SIZE_TWO];
171 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
172 if (status != napi_ok || argc != ARGS_SIZE_TWO) {
173 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
174 return false;
175 }
176 napi_valuetype valueType = napi_null;
177 napi_typeof(env, args[PARAM1], &valueType);
178 if (valueType != napi_function) {
179 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
180 return false;
181 }
182
183 size_t typeLen = 0;
184 status = napi_get_value_string_utf8(env, args[ARGS_SIZE_ZERO], nullptr, -1, &typeLen);
185 if (status != napi_ok || typeLen >= ARGS_TYPE_MAX_LEN) {
186 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
187 return false;
188 }
189 char type[ARGS_TYPE_MAX_LEN];
190 status = napi_get_value_string_utf8(env, args[ARGS_SIZE_ZERO], type, sizeof(type), &typeLen);
191 if (status != napi_ok) {
192 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
193 return false;
194 }
195 funcName = type;
196 return true;
197 }
198
On(napi_env env,napi_callback_info info)199 napi_value NapiLinkEnhanceServer::On(napi_env env, napi_callback_info info)
200 {
201 std::string funcName = "";
202 if (!CheckAccessTokenAndParams(env, info, funcName)) {
203 return NapiGetUndefinedRet(env);
204 }
205 NapiLinkEnhanceServer *enhanceServer = NapiGetEnhanceServer(env, info);
206 size_t argc = ARGS_SIZE_TWO;
207 napi_value args[ARGS_SIZE_TWO];
208 napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
209 if (status != napi_ok || argc != ARGS_SIZE_TWO || enhanceServer == nullptr) {
210 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
211 return NapiGetUndefinedRet(env);
212 }
213
214 if (strcmp(funcName.c_str(), "connectionAccepted") == 0) {
215 COMM_LOGE(COMM_SDK, "register connectionAccepted");
216 if (enhanceServer->acceptConnectRef_ != nullptr) {
217 napi_delete_reference(env, enhanceServer->acceptConnectRef_);
218 }
219 napi_create_reference(env, args[ARGS_SIZE_ONE], 1, &(enhanceServer->acceptConnectRef_));
220 enhanceServer->SetAcceptedEnable(true);
221 } else if (strcmp(funcName.c_str(), "serverStopped") == 0) {
222 COMM_LOGE(COMM_SDK, "register serverStopped");
223 if (enhanceServer->serverStopRef_ != nullptr) {
224 napi_delete_reference(env, enhanceServer->serverStopRef_);
225 }
226 napi_create_reference(env, args[ARGS_SIZE_ONE], 1, &(enhanceServer->serverStopRef_));
227 enhanceServer->SetStopEnable(true);
228 } else {
229 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
230 return NapiGetUndefinedRet(env);
231 }
232 return NapiGetUndefinedRet(env);
233 }
234
Off(napi_env env,napi_callback_info info)235 napi_value NapiLinkEnhanceServer::Off(napi_env env, napi_callback_info info)
236 {
237 std::string funcName = "";
238 if (!CheckAccessTokenAndParams(env, info, funcName)) {
239 return NapiGetUndefinedRet(env);
240 }
241
242 NapiLinkEnhanceServer *enhanceServer = NapiGetEnhanceServer(env, info);
243 if (enhanceServer == nullptr) {
244 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
245 return NapiGetUndefinedRet(env);
246 }
247 if (strcmp(funcName.c_str(), "onAcceptConnect") == 0) {
248 if (enhanceServer->acceptConnectRef_ != nullptr) {
249 napi_delete_reference(env, enhanceServer->acceptConnectRef_);
250 }
251 enhanceServer->acceptConnectRef_ = nullptr;
252 enhanceServer->SetAcceptedEnable(false);
253 } else if (strcmp(funcName.c_str(), "serverStopped") == 0) {
254 if (enhanceServer->serverStopRef_ != nullptr) {
255 napi_delete_reference(env, enhanceServer->serverStopRef_);
256 }
257 enhanceServer->serverStopRef_ = nullptr;
258 enhanceServer->SetStopEnable(false);
259 } else {
260 HandleSyncErr(env, LINK_ENHANCE_PARAMETER_INVALID);
261 return NapiGetUndefinedRet(env);
262 }
263 return NapiGetUndefinedRet(env);
264 }
265
Start(napi_env env,napi_callback_info info)266 napi_value NapiLinkEnhanceServer::Start(napi_env env, napi_callback_info info)
267 {
268 if (!CheckAccessToken()) {
269 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
270 return NapiGetUndefinedRet(env);
271 }
272 size_t argc = 0;
273 napi_status status = napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
274 if (status != napi_ok || argc > ARGS_SIZE_ZERO) {
275 HandleSyncErr(env, LINK_ENHANCE_INTERVAL_ERR);
276 return NapiGetUndefinedRet(env);
277 }
278 NapiLinkEnhanceServer *enhanceServer = NapiGetEnhanceServer(env, info);
279 if (enhanceServer == nullptr) {
280 HandleSyncErr(env, LINK_ENHANCE_INTERVAL_ERR);
281 return NapiGetUndefinedRet(env);
282 }
283 int32_t ret = GeneralCreateServer(PKG_NAME.c_str(), enhanceServer->name_.c_str());
284 if (ret != 0) {
285 COMM_LOGE(COMM_SDK, "create server failed, ret=%{public}d", ret);
286 int32_t errCode = ConvertToJsErrcode(ret);
287 HandleSyncErr(env, errCode);
288 }
289 return NapiGetUndefinedRet(env);
290 }
291
Stop(napi_env env,napi_callback_info info)292 napi_value NapiLinkEnhanceServer::Stop(napi_env env, napi_callback_info info)
293 {
294 if (!CheckAccessToken()) {
295 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
296 return NapiGetUndefinedRet(env);
297 }
298 size_t argc = 0;
299 napi_status status = napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
300 if (status != napi_ok || argc > ARGS_SIZE_ZERO) {
301 COMM_LOGE(COMM_SDK, "no needed arguments");
302 return NapiGetUndefinedRet(env);
303 }
304 NapiLinkEnhanceServer *enhanceServer = NapiGetEnhanceServer(env, info);
305 if (enhanceServer == nullptr) {
306 COMM_LOGE(COMM_SDK, "get server failed");
307 return NapiGetUndefinedRet(env);
308 }
309 enhanceServer->lock_.lock();
310 enhanceServer->isAcceptedEnable_ = false;
311 enhanceServer->isStopEnable_ = false;
312 enhanceServer->lock_.unlock();
313
314 int32_t ret = GeneralRemoveServer(PKG_NAME.c_str(), enhanceServer->name_.c_str());
315 if (ret != 0) {
316 COMM_LOGE(COMM_SDK, "remove server failed, ret=%{public}d", ret);
317 if (ConvertToJsErrcode(ret) == LINK_ENHANCE_PERMISSION_DENIED) {
318 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
319 }
320 }
321 return NapiGetUndefinedRet(env);
322 }
323
Close(napi_env env,napi_callback_info info)324 napi_value NapiLinkEnhanceServer::Close(napi_env env, napi_callback_info info)
325 {
326 COMM_LOGI(COMM_SDK, "enter");
327 if (!CheckAccessToken()) {
328 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
329 return NapiGetUndefinedRet(env);
330 }
331 size_t argc = 0;
332 napi_status status = napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
333 if (status != napi_ok || argc > ARGS_SIZE_ZERO) {
334 COMM_LOGE(COMM_SDK, "no needed arguments");
335 return NapiGetUndefinedRet(env);
336 }
337 NapiLinkEnhanceServer *enhanceServer = NapiGetEnhanceServer(env, info);
338 if (enhanceServer == nullptr) {
339 COMM_LOGE(COMM_SDK, "get server failed");
340 return NapiGetUndefinedRet(env);
341 }
342 int32_t ret = GeneralRemoveServer(PKG_NAME.c_str(), enhanceServer->name_.c_str());
343 if (ret != 0) {
344 COMM_LOGE(COMM_SDK, "remove server failed, ret=%{public}d", ret);
345 if (ConvertToJsErrcode(ret) == LINK_ENHANCE_PERMISSION_DENIED) {
346 HandleSyncErr(env, LINK_ENHANCE_PERMISSION_DENIED);
347 }
348 }
349 enhanceServer->lock_.lock();
350 enhanceServer->isAcceptedEnable_ = false;
351 enhanceServer->isStopEnable_ = false;
352 enhanceServer->lock_.unlock();
353 if (enhanceServer->acceptConnectRef_ != nullptr) {
354 napi_delete_reference(env, enhanceServer->acceptConnectRef_);
355 enhanceServer->acceptConnectRef_ = nullptr;
356 }
357 if (enhanceServer->serverStopRef_ != nullptr) {
358 napi_delete_reference(env, enhanceServer->serverStopRef_);
359 enhanceServer->serverStopRef_ = nullptr;
360 }
361 {
362 std::lock_guard<std::mutex> guard(serverMapMutex_);
363 if (enhanceServerMap_.find(enhanceServer->name_) != enhanceServerMap_.end()) {
364 enhanceServerMap_.erase(enhanceServer->name_);
365 }
366 }
367 return NapiGetUndefinedRet(env);
368 }
369
IsAcceptedEnable()370 bool NapiLinkEnhanceServer::IsAcceptedEnable()
371 {
372 this->lock_.lock();
373 bool isEnable = this->isAcceptedEnable_;
374 this->lock_.unlock();
375 return isEnable;
376 }
377
IsStopEnable()378 bool NapiLinkEnhanceServer::IsStopEnable()
379 {
380 this->lock_.lock();
381 bool isEnable = this->isStopEnable_;
382 this->lock_.unlock();
383 return isEnable;
384 }
385 } // namespace SoftBus
386 } // namespace Communication