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