1 /*
2 * Copyright (C) 2023 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_bluetooth_error.h"
16 #include "napi_bluetooth_utils.h"
17 #include "napi_bluetooth_spp_server.h"
18 #include "bluetooth_errorcode.h"
19
20 namespace OHOS {
21 namespace Bluetooth {
22 const int num_20 = 20;
23 using namespace std;
24 int NapiSppServer::count = 0;
25 std::map<int, std::shared_ptr<NapiSppServer>> NapiSppServer::serverMap;
26
DefineSppFunctions(napi_env env,napi_value exports)27 void DefineSppFunctions(napi_env env, napi_value exports)
28 {
29 SppPropertyValueInit(env, exports);
30 napi_property_descriptor desc[] = {
31 DECLARE_NAPI_FUNCTION("sppListen", NapiSppServer::SppListen),
32 DECLARE_NAPI_FUNCTION("sppAccept", NapiSppServer::SppAccept),
33 DECLARE_NAPI_FUNCTION("sppConnect", NapiSppClient::SppConnect),
34 DECLARE_NAPI_FUNCTION("sppCloseServerSocket", NapiSppServer::SppCloseServerSocket),
35 DECLARE_NAPI_FUNCTION("sppCloseClientSocket", NapiSppClient::SppCloseClientSocket),
36 DECLARE_NAPI_FUNCTION("sppWrite", NapiSppClient::SppWrite),
37 #ifdef BLUETOOTH_API_SINCE_10
38 DECLARE_NAPI_FUNCTION("on", NapiSppServer::RegisterSocketObserver),
39 DECLARE_NAPI_FUNCTION("off", NapiSppServer::DeRegisterSocketObserver),
40 #endif
41 };
42 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
43 }
44
RegisterSocketObserver(napi_env env,napi_callback_info info)45 napi_value NapiSppServer::RegisterSocketObserver(napi_env env, napi_callback_info info)
46 {
47 return NapiSppClient::On(env, info);
48 }
49
DeRegisterSocketObserver(napi_env env,napi_callback_info info)50 napi_value NapiSppServer::DeRegisterSocketObserver(napi_env env, napi_callback_info info)
51 {
52 return NapiSppClient::Off(env, info);
53 }
54
SppTypeInit(napi_env env)55 napi_value SppTypeInit(napi_env env)
56 {
57 HILOGI("enter");
58 napi_value sppType = nullptr;
59 napi_create_object(env, &sppType);
60 SetNamedPropertyByInteger(env, sppType, SppType::SPP_RFCOMM, "SPP_RFCOMM");
61 return sppType;
62 }
63
SppPropertyValueInit(napi_env env,napi_value exports)64 void SppPropertyValueInit(napi_env env, napi_value exports)
65 {
66 napi_value sppTypeObj = SppTypeInit(env);
67 napi_property_descriptor exportFuncs[] = {
68 DECLARE_NAPI_PROPERTY("SppType", sppTypeObj),
69 };
70 napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
71 HILOGI("end");
72 }
73
CheckSppListenParams(napi_env env,napi_callback_info info,string & name,SppListenCallbackInfo * callbackInfo)74 static napi_status CheckSppListenParams(
75 napi_env env, napi_callback_info info, string &name, SppListenCallbackInfo *callbackInfo)
76 {
77 HILOGI("enter");
78 size_t argc = ARGS_SIZE_THREE;
79 napi_value argv[ARGS_SIZE_THREE] = {0};
80
81 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
82 NAPI_BT_RETURN_IF((argc != ARGS_SIZE_THREE && argc != ARGS_SIZE_THREE - CALLBACK_SIZE),
83 "Requires 2 or 3 arguments.", napi_invalid_arg);
84 NAPI_BT_RETURN_IF(!ParseString(env, name, argv[PARAM0]),
85 "Wrong argument type. String expected.", napi_invalid_arg);
86
87 callbackInfo->env_ = env;
88 callbackInfo->sppOption_ = GetSppOptionFromJS(env, argv[PARAM1]);
89 NAPI_BT_RETURN_IF((callbackInfo->sppOption_ == nullptr), "GetSppOptionFromJS faild.", napi_invalid_arg);
90 callbackInfo->name_ = name;
91
92 napi_value promise = nullptr;
93
94 if (argc == ARGS_SIZE_THREE) {
95 HILOGI("callback mode");
96 napi_valuetype valueType = napi_undefined;
97 NAPI_BT_CALL_RETURN(napi_typeof(env, argv[PARAM2], &valueType));
98 if (valueType != napi_function) {
99 HILOGE("Wrong argument type. Function expected.");
100 delete callbackInfo;
101 callbackInfo = nullptr;
102 return napi_invalid_arg;
103 }
104 napi_create_reference(env, argv[PARAM2], 1, &callbackInfo->callback_);
105 napi_get_undefined(env, &promise);
106 } else {
107 HILOGI("promise mode");
108 napi_create_promise(env, &callbackInfo->deferred_, &promise);
109 }
110 return napi_ok;
111 }
112
SppListen(napi_env env,napi_callback_info info)113 napi_value NapiSppServer::SppListen(napi_env env, napi_callback_info info)
114 {
115 HILOGI("enter");
116 string name;
117 SppListenCallbackInfo *callbackInfo = new SppListenCallbackInfo();
118 auto status = CheckSppListenParams(env, info, name, callbackInfo);
119 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
120
121 napi_value resource = nullptr;
122 napi_create_string_utf8(env, "SppListen", NAPI_AUTO_LENGTH, &resource);
123
124 napi_create_async_work(
125 env, nullptr, resource,
126 [](napi_env env, void* data) {
127 HILOGI("SppListen execute");
128 SppListenCallbackInfo* callbackInfo = static_cast<SppListenCallbackInfo*>(data);
129 callbackInfo->server_ = std::make_shared<ServerSocket>(callbackInfo->name_,
130 UUID::FromString(callbackInfo->sppOption_->uuid_), callbackInfo->sppOption_->type_,
131 callbackInfo->sppOption_->secure_);
132 int errorCode = callbackInfo->server_->Listen();
133 HILOGI("SppListen ServerSocket constructor end");
134 if (callbackInfo->server_ ->GetStringTag() != "") {
135 HILOGI("SppListen execute listen success");
136 callbackInfo->errorCode_ = CODE_SUCCESS;
137 } else {
138 HILOGI("SppListen execute listen failed");
139 callbackInfo->errorCode_ = errorCode;
140 }
141 },
142 [](napi_env env, napi_status status, void* data) {
143 HILOGI("SppListen execute back");
144 SppListenCallbackInfo* callbackInfo = static_cast<SppListenCallbackInfo*>(data);
145 napi_value result[ARGS_SIZE_TWO] = {0};
146 napi_value callback = 0;
147 napi_value undefined = 0;
148 napi_value callResult = 0;
149 napi_get_undefined(env, &undefined);
150
151 if (callbackInfo->errorCode_ == CODE_SUCCESS) {
152 HILOGI("SppListen execute back listen success");
153 std::shared_ptr<NapiSppServer> server = std::make_shared<NapiSppServer>();
154 server->id_ = NapiSppServer::count++;
155 napi_create_int32(env, server->id_, &result[PARAM1]);
156 server->server_ = callbackInfo->server_;
157 serverMap.insert(std::make_pair(server->id_, server));
158 } else {
159 HILOGI("SppListen execute back listen failed");
160 napi_get_undefined(env, &result[PARAM1]);
161 }
162
163 if (callbackInfo->callback_) {
164 HILOGI("SppListen execute back listen Callback mode success");
165 result[PARAM0] = GetCallbackErrorValue(callbackInfo->env_, callbackInfo->errorCode_);
166 napi_get_reference_value(env, callbackInfo->callback_, &callback);
167 napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &callResult);
168 napi_delete_reference(env, callbackInfo->callback_);
169 } else {
170 if (callbackInfo->errorCode_ == CODE_SUCCESS) {
171 HILOGI("SppListen execute back listen Promise mode success");
172 napi_resolve_deferred(env, callbackInfo->deferred_, result[PARAM1]);
173 } else {
174 HILOGI("SppListen execute back listen Promise mode failed");
175 napi_reject_deferred(env, callbackInfo->deferred_, result[PARAM1]);
176 }
177 }
178 napi_delete_async_work(env, callbackInfo->asyncWork_);
179 delete callbackInfo;
180 callbackInfo = nullptr;
181 },
182 static_cast<void*>(callbackInfo),
183 &callbackInfo->asyncWork_);
184
185 napi_queue_async_work(env, callbackInfo->asyncWork_);
186
187 return NapiGetUndefinedRet(env);
188 }
189
CheckSppAcceptParams(napi_env env,napi_callback_info info,int32_t & serverSocketNum,SppAcceptCallbackInfo * callbackInfo)190 static napi_status CheckSppAcceptParams(
191 napi_env env, napi_callback_info info, int32_t &serverSocketNum, SppAcceptCallbackInfo *callbackInfo)
192 {
193 HILOGI("enter");
194 size_t argc = ARGS_SIZE_TWO;
195 napi_value argv[ARGS_SIZE_TWO] = {0};
196
197 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
198 NAPI_BT_RETURN_IF((argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_TWO - CALLBACK_SIZE),
199 "Requires 1 or 2 arguments.", napi_invalid_arg);
200 NAPI_BT_RETURN_IF(!ParseInt32(env, serverSocketNum, argv[PARAM0]),
201 "Wrong argument type. int expected.", napi_invalid_arg);
202
203 std::shared_ptr<NapiSppServer> server = NapiSppServer::serverMap[serverSocketNum];
204 if (!server) {
205 HILOGE("server is null");
206 return napi_invalid_arg;
207 }
208 callbackInfo->env_ = env;
209 callbackInfo->server_ = server->server_;
210
211 napi_value promise = nullptr;
212
213 if (argc == ARGS_SIZE_TWO) {
214 HILOGI("callback mode");
215 napi_valuetype valueType = napi_undefined;
216 NAPI_BT_CALL_RETURN(napi_typeof(env, argv[PARAM1], &valueType));
217 if (valueType != napi_function) {
218 HILOGE("Wrong argument type. Function expected.");
219 delete callbackInfo;
220 callbackInfo = nullptr;
221 return napi_invalid_arg;
222 }
223 napi_create_reference(env, argv[PARAM1], 1, &callbackInfo->callback_);
224 napi_get_undefined(env, &promise);
225 } else {
226 HILOGI("promise mode");
227 napi_create_promise(env, &callbackInfo->deferred_, &promise);
228 }
229 return napi_ok;
230 }
231
SppAccept(napi_env env,napi_callback_info info)232 napi_value NapiSppServer::SppAccept(napi_env env, napi_callback_info info)
233 {
234 HILOGI("enter");
235 int32_t serverSocketNum = -1;
236 SppAcceptCallbackInfo *callbackInfo = new SppAcceptCallbackInfo();
237 auto status = CheckSppAcceptParams(env, info, serverSocketNum, callbackInfo);
238 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
239
240 napi_value resource = nullptr;
241 napi_create_string_utf8(env, "SppAccept", NAPI_AUTO_LENGTH, &resource);
242
243 napi_create_async_work(
244 env, nullptr, resource,
245 [](napi_env env, void* data) {
246 HILOGI("SppAccept execute");
247 SppAcceptCallbackInfo* callbackInfo = static_cast<SppAcceptCallbackInfo*>(data);
248 callbackInfo->client_ = callbackInfo->server_->Accept(num_20);
249 if (callbackInfo->client_ != nullptr) {
250 callbackInfo->errorCode_ = CODE_SUCCESS;
251 } else {
252 callbackInfo->errorCode_ = CODE_FAILED;
253 }
254 },
255 [](napi_env env, napi_status status, void* data) {
256 HILOGI("SppAccept execute back");
257 SppAcceptCallbackInfo* callbackInfo = static_cast<SppAcceptCallbackInfo*>(data);
258 napi_value result[ARGS_SIZE_TWO] = {0};
259 napi_value callback = 0;
260 napi_value undefined = 0;
261 napi_value callResult = 0;
262 napi_get_undefined(env, &undefined);
263
264 if (callbackInfo->errorCode_ == CODE_SUCCESS) {
265 std::shared_ptr<NapiSppClient> client = std::make_shared<NapiSppClient>();
266 client->id_ = NapiSppClient::count++;
267 napi_create_int32(env, client->id_, &result[PARAM1]);
268 client->client_ = callbackInfo->client_;
269 NapiSppClient::clientMap.insert(std::make_pair(client->id_, client));
270 } else {
271 napi_get_undefined(env, &result[PARAM1]);
272 }
273
274 if (callbackInfo->callback_) {
275 result[PARAM0] = GetCallbackErrorValue(callbackInfo->env_, callbackInfo->errorCode_);
276 napi_get_reference_value(env, callbackInfo->callback_, &callback);
277 napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &callResult);
278 napi_delete_reference(env, callbackInfo->callback_);
279 } else {
280 if (callbackInfo->errorCode_ == CODE_SUCCESS) {
281 napi_resolve_deferred(env, callbackInfo->deferred_, result[PARAM1]);
282 } else {
283 napi_reject_deferred(env, callbackInfo->deferred_, result[PARAM1]);
284 }
285 }
286 napi_delete_async_work(env, callbackInfo->asyncWork_);
287 delete callbackInfo;
288 callbackInfo = nullptr;
289 },
290 static_cast<void*>(callbackInfo),
291 &callbackInfo->asyncWork_);
292
293 napi_queue_async_work(env, callbackInfo->asyncWork_);
294
295 return NapiGetUndefinedRet(env);
296 }
297
CheckSppCloseServerSockeParams(napi_env env,napi_callback_info info,int & id)298 static napi_status CheckSppCloseServerSockeParams(napi_env env, napi_callback_info info, int &id)
299 {
300 HILOGI("enter");
301 size_t argc = ARGS_SIZE_ONE;
302 napi_value argv[ARGS_SIZE_ONE] = {0};
303 napi_value thisVar = nullptr;
304
305 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
306 NAPI_BT_RETURN_IF((argc != ARGS_SIZE_ONE), "Requires 1 arguments.", napi_invalid_arg);
307 NAPI_BT_RETURN_IF(!ParseInt32(env, id, argv[PARAM0]), "Wrong argument type. int expected.", napi_invalid_arg);
308 return napi_ok;
309 }
310
SppCloseServerSocket(napi_env env,napi_callback_info info)311 napi_value NapiSppServer::SppCloseServerSocket(napi_env env, napi_callback_info info)
312 {
313 HILOGI("enter");
314 int id = -1;
315 auto status = CheckSppCloseServerSockeParams(env, info, id);
316 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
317
318 bool isOK = false;
319
320 std::shared_ptr<NapiSppServer> server = nullptr;
321 std::shared_ptr<NapiSppClient> client = nullptr;
322
323 if (NapiSppClient::clientMap[id] != nullptr) {
324 client = NapiSppClient::clientMap[id];
325 if (client->client_) {
326 client->client_->Close();
327 NapiSppClient::clientMap.erase(id);
328 }
329 } else {
330 HILOGE("no such key in clientMap.");
331 }
332
333 if (serverMap[id] != nullptr) {
334 server = serverMap[id];
335 if (server->server_) {
336 server->server_->Close();
337 serverMap.erase(id);
338 isOK = true;
339 }
340 } else {
341 HILOGE("no such key in serverMap.");
342 }
343
344 return NapiGetBooleanRet(env, isOK);
345 }
346 } // namespace Bluetooth
347 } // namespace OHOS
348