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