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