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