• 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 
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