• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_cj_socket_spp_client"
17 #endif
18 
19 #include "bluetooth_spp_client_impl.h"
20 
21 #include "bluetooth_errorcode.h"
22 #include "bluetooth_host.h"
23 #include "cj_lambda.h"
24 #include "datetime_ex.h"
25 #include "napi_bluetooth_utils.h"
26 #include "securec.h"
27 
28 namespace OHOS {
29 namespace Bluetooth {
30 std::map<int, std::shared_ptr<SppClientImpl>> SppClientImpl::clientMap;
31 int SppClientImpl::count = 0;
32 const int SOCKET_BUFFER_SIZE = 1024;
33 
SppConnect(std::string deviceId,SppOption sppOption,int32_t * errCode)34 int32_t SppClientImpl::SppConnect(std::string deviceId, SppOption sppOption, int32_t* errCode)
35 {
36     HILOGD("enter");
37     std::shared_ptr<BluetoothRemoteDevice> device_ = std::make_shared<BluetoothRemoteDevice>(deviceId, 0);
38     std::shared_ptr<ClientSocket> client_ =
39         std::make_shared<ClientSocket>(*device_, UUID::FromString(sppOption.uuid_), sppOption.type_, sppOption.secure_);
40     int errorCode = client_->Connect(SPP_SOCKET_PSM_VALUE);
41     if (errorCode != BtStatus::BT_SUCCESS) {
42         HILOGE("SppConnect failed");
43         *errCode = errorCode;
44         return -1;
45     }
46     std::shared_ptr<SppClientImpl> client = std::make_shared<SppClientImpl>();
47     client->device_ = device_;
48     client->id_ = SppClientImpl::count++;
49     client->client_ = client_;
50     clientMap.insert(std::make_pair(client->id_, client));
51     HILOGD("SppConnect execute back successfully");
52     return client->id_;
53 }
54 
SppCloseClientSocket(int32_t socket)55 int32_t SppClientImpl::SppCloseClientSocket(int32_t socket)
56 {
57     HILOGD("enter");
58     std::shared_ptr<SppClientImpl> client = nullptr;
59     bool isOK = false;
60 
61     if (clientMap[socket]) {
62         client = clientMap[socket];
63     } else {
64         HILOGE("invalid socket.");
65         return BT_ERR_INVALID_PARAM;
66     }
67 
68     if (client->client_) {
69         client->client_->Close();
70         isOK = true;
71     }
72     clientMap.erase(socket);
73     return isOK ? 0 : BT_ERR_INVALID_PARAM;
74 }
75 
SppWrite(int32_t clientSocket,CArrUI8 data)76 int32_t SppClientImpl::SppWrite(int32_t clientSocket, CArrUI8 data)
77 {
78     HILOGD("enter");
79     BluetoothHost* host = &BluetoothHost::GetDefaultHost();
80     auto prohibitedTime = host->GetRefusePolicyProhibitedTime();
81     if (prohibitedTime < 0 || prohibitedTime > GetSecondsSince1970ToNow()) {
82         HILOGE("socket refuse because of Refuse Policy");
83         return BT_ERR_INVALID_PARAM;
84     }
85     auto client = clientMap[clientSocket];
86     if (client == nullptr) {
87         HILOGE("client is nullptr.");
88         return BT_ERR_INVALID_PARAM;
89     }
90     if (client->client_ == nullptr) {
91         HILOGE("client_ is nullptr.");
92         return BT_ERR_INVALID_PARAM;
93     }
94     std::shared_ptr<OutputStream> outputStream = client->client_->GetOutputStream();
95     size_t totalSize = static_cast<size_t>(data.size);
96     bool isOK = false;
97     while (totalSize) {
98         int result = outputStream->Write(data.head, totalSize);
99         if (result <= 0) {
100             HILOGE("outputStream.Write failed, ret = %{public}d", result);
101             return BT_ERR_SPP_IO;
102         }
103         totalSize = totalSize - static_cast<size_t>(result);
104         data.head += static_cast<size_t>(result);
105         isOK = true;
106     }
107     return isOK ? 0 : BT_ERR_INVALID_PARAM;
108 }
109 
On(std::string type,int32_t clientSocket,int64_t cbId)110 int32_t SppClientImpl::On(std::string type, int32_t clientSocket, int64_t cbId)
111 {
112     HILOGD("enter");
113     std::shared_ptr<CjBluetoothCallbackInfo> callbackInfo = std::make_shared<BufferCallbackInfo>();
114     callbackInfo->callback_ = cbId;
115     std::shared_ptr<SppClientImpl> client = SppClientImpl::clientMap[clientSocket];
116     if (client == nullptr) {
117         HILOGE("client is nullptr.");
118         return BT_ERR_INVALID_PARAM;
119     }
120     if (client->sppReadFlag) {
121         HILOGE("client is reading... please off first");
122         return BT_ERR_INVALID_PARAM;
123     }
124     client->sppReadFlag = true;
125     client->callbackInfos_[type] = callbackInfo;
126     client->thread_ = std::make_shared<std::thread>(SppClientImpl::SppRead, clientSocket);
127     client->thread_->detach();
128     return 0;
129 }
130 
Off(std::string type,int32_t clientSocket,int64_t cbId)131 int32_t SppClientImpl::Off(std::string type, int32_t clientSocket, int64_t cbId)
132 {
133     HILOGD("enter");
134     std::shared_ptr<SppClientImpl> client = SppClientImpl::clientMap[clientSocket];
135     if (client == nullptr) {
136         HILOGE("client is nullptr.");
137         return BT_ERR_INVALID_PARAM;
138     }
139     client->callbackInfos_[type] = nullptr;
140     client->sppReadFlag = false;
141     return 0;
142 }
143 
SppRead(int id)144 void SppClientImpl::SppRead(int id)
145 {
146     auto client = clientMap[id];
147     if (client == nullptr || !client->sppReadFlag || client->callbackInfos_[REGISTER_SPP_READ_TYPE] == nullptr) {
148         HILOGE("thread start failed.");
149         return;
150     }
151     std::shared_ptr<InputStream> inputStream = client->client_->GetInputStream();
152     uint8_t buf[SOCKET_BUFFER_SIZE];
153 
154     while (true) {
155         HILOGD("thread start.");
156         (void)memset_s(buf, SOCKET_BUFFER_SIZE, 0, SOCKET_BUFFER_SIZE);
157         int ret = inputStream->Read(buf, sizeof(buf));
158         if (ret <= 0) {
159             HILOGE("inputStream.Read failed, ret = %{public}d", ret);
160             return;
161         } else {
162             if (client == nullptr || !client->sppReadFlag || !client->callbackInfos_[REGISTER_SPP_READ_TYPE]) {
163                 HILOGE("failed");
164                 return;
165             }
166             std::shared_ptr<BufferCallbackInfo> callbackInfo =
167                 std::static_pointer_cast<BufferCallbackInfo>(client->callbackInfos_[REGISTER_SPP_READ_TYPE]);
168             if (callbackInfo == nullptr) {
169                 HILOGE("callbackInfo nullptr");
170                 return;
171             }
172 
173             CArrUI8 buffer {};
174             buffer.head = static_cast<uint8_t*>(malloc(sizeof(uint8_t) * ret));
175             if (buffer.head == nullptr) {
176                 HILOGE("malloc failed!");
177                 return;
178             }
179             buffer.size = ret;
180             if (memcpy_s(buffer.head, ret, buf, ret) != EOK) {
181                 HILOGE("memcpy_s failed!");
182                 free(buffer.head);
183                 return;
184             }
185 
186             auto cFunc = reinterpret_cast<void (*)(CArrUI8)>(callbackInfo->callback_);
187             std::function<void(CArrUI8)> func = CJLambda::Create(cFunc);
188             func(buffer);
189             free(buffer.head);
190         }
191     }
192     return;
193 }
194 
GetDeviceId(int32_t clientSocket,int32_t * errCode)195 std::string SppClientImpl::GetDeviceId(int32_t clientSocket, int32_t* errCode)
196 {
197     HILOGD("enter");
198     auto client = clientMap[clientSocket];
199     if (client == nullptr) {
200         *errCode = BT_ERR_INVALID_PARAM;
201         return std::string();
202     }
203     if (client->client_ == nullptr) {
204         *errCode = BT_ERR_INVALID_PARAM;
205         return std::string();
206     }
207     BluetoothRemoteDevice remoteDevice = client->client_->GetRemoteDevice();
208     std::string addr = remoteDevice.GetDeviceAddr();
209     return addr;
210 }
211 } // namespace Bluetooth
212 } // namespace OHOS