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