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
16 #include "gatt_server_profile.h"
17 #include "att.h"
18 #include "bt_def.h"
19 #include "gatt_connection_manager.h"
20 #include "gatt_service_base.h"
21 #include "log.h"
22
23 namespace OHOS {
24 namespace bluetooth {
25 struct GattServerProfile::impl {
26 class GattConnectionObserverImplement;
implOHOS::bluetooth::GattServerProfile::impl27 impl(GattServerProfileCallback *pServerCallbackFunc, utility::Dispatcher *dispatcher, uint16_t maxMtu,
28 GattServerProfile &profile)
29 : requestList_(),
30 connectionCallBack_(std::make_unique<GattConnectionObserverImplement>(profile)),
31 pServerCallBack_(pServerCallbackFunc),
32 dispatcher_(dispatcher),
33 db_(),
34 mtu_(maxMtu)
35 {}
36 std::map<uint16_t, uint16_t> mtuInfo_ = {};
37 std::list<std::pair<uint16_t, GattResponesInfor>> requestList_ = {};
38 std::list<std::pair<uint16_t, GattResponesInfor>> responseList_ = {};
39 std::list<std::pair<uint16_t, DeviceInfo>> devList_ = {};
40 std::unique_ptr<GattConnectionObserverImplement> connectionCallBack_ = {};
41 GattServerProfileCallback *pServerCallBack_ = nullptr;
42 utility::Dispatcher *dispatcher_ = nullptr;
43 GattDatabase db_ = {};
44 uint16_t mtu_ = 0;
45 GattServerProfile *profile_ = nullptr;
46 int connectionObserverId_ = 0;
47 BT_DISALLOW_COPY_AND_ASSIGN(impl);
48
49 static void ReceiveData(uint16_t connectHandle, uint16_t event, void *eventData, Buffer *buffer, void *context);
50 static void ReceiveResponseResult(uint16_t connectHandle, int result, void *context);
51 void ReceiveResponseResultPostTask(uint16_t connectHandle, int result);
52 void RegisterCallbackToATT();
53 static void DeregisterCallbackToATT();
54 void RegisterCallbackToConnectManager();
55 void DeregisterCallbackToConnectManager();
56 void AddResponseList();
57 void SplitReadByTypeReqMessage(uint16_t connectHandle, AttEventData *data);
58 void ExchangeMTUResponse(uint16_t connectHandle, uint16_t mtu);
59 void DiscoverAllPrimaryServiceResponsePostTask(uint16_t connectHandle, AttEventData *data);
60 void DiscoverAllPrimaryServiceResponse(uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle);
61 void DiscoverCharacteristicResponsePostTask(uint16_t connectHandle, AttEventData *data);
62 void DiscoverCharacteristicResponse(uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle);
63 void DiscoverPrimaryServiceByUuidResponsePostTask(uint16_t connectHandle, Buffer *value, AttEventData *data);
64 void DiscoverPrimaryServiceByUuidResponse(
65 uint16_t connectHandle, Buffer *value, uint16_t startHandle, uint16_t endHandle);
66 void FindIncludedServiceResponsePostTask(uint16_t connectHandle, AttEventData *data);
67 void FindIncludedServiceResponse(uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle);
68 void DiscoverAllCharacteristicDescriptorResponsePostTask(uint16_t connectHandle, AttEventData *data);
69 void DiscoverAllCharacteristicDescriptorResponse(uint16_t connectHandle, uint16_t attHandle, uint16_t endHandle);
70 void ReadValueResponsePostTask(uint16_t connectHandle, uint16_t attHandle);
71 void ReadValueResponse(uint16_t connectHandle, uint16_t attHandle);
72 void ReadUsingCharacteristicByUuidResponsePostTask(uint16_t connectHandle, AttEventData *data);
73 void ReadUsingCharacteristicByUuidResponseStep1(
74 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, Uuid uuid);
75 RetVal ReadUsingCharacteristicByUuidResponseStep2(uint16_t connectHandle, uint16_t startHandle, uint16_t num,
76 AttReadByTypeRspDataList *list, Uuid uuid, uint8_t *offset);
77 void ReadBlobValueResponsePostTask(uint16_t connectHandle, AttEventData *data);
78 void ReadBlobValueResponse(uint16_t connectHandle, uint16_t attHandle, uint16_t offset);
79 void ReadMultipleCharacteristicValueResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value);
80 void ReadMultipleCharacteristicValueResponse(uint16_t connectHandle, Buffer *value);
81 void WriteValueResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value);
82 void WriteValueResponse(uint16_t connectHandle, uint16_t attHandle, Buffer *value);
83 void WriteWithoutResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value);
84 void WriteWithoutResponse(uint16_t connectHandle, uint16_t attHandle, Buffer *value);
85 void WriteLongCharacteristicValueResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value);
86 void WriteLongCharacteristicValueResponse(
87 uint16_t connectHandle, uint16_t attHandle, uint16_t offset, Buffer *value);
88 void ExecuteWriteResponsePostTask(uint16_t connectHandle, AttEventData *data);
89 void ExecuteWriteResponse(uint16_t connectHandle, bool flag);
90 void HandleValueConfirmationResponsePostTask(uint16_t connectHandle, int ret);
91 void HandleValueConfirmationResponse(uint16_t connectHandle, int ret);
92 void SendAttReadByTypeResponse(
93 uint16_t connectHandle, uint16_t handle, uint8_t len, AttReadByTypeRspDataList *value, uint16_t num);
94 static bool CheckAttHandleParameter(
95 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, uint8_t requestId);
96 static bool CheckUuidType(uint16_t connectHandle, Uuid *uuid, AttEventData *data);
97 bool FindServiceEndingHandle(uint16_t attHandle);
98 bool FindServiceByHandle(uint16_t attHandle, Uuid uuid);
99 bool FindCharacteristicDeclarationByHandle(uint16_t attHandle, Uuid uuid);
100 bool FindCharacteristicValueByUuid(uint16_t attHandle, Uuid uuid);
101 bool FindCharacteristicDescriptorByUuid(uint16_t attHandle, Uuid uuid);
102 Buffer *AssembleServicePackage(uint16_t attHandle);
103 Buffer *AssembleCharacteristicPackage(uint16_t attHandle);
104 Buffer *AssembleDescriptorPackage(uint16_t connectHandle, uint16_t attHandle);
105 static void AssembleAttReadByGroupTypeRspPackage(
106 AttReadGoupAttributeData *list, const GattDatabase::Service &service, uint8_t num);
107 void AssembleAttReadByTypeRspSvcPackage(
108 AttReadByTypeRspDataList *list, uint16_t attHandle, uint8_t num, uint8_t *offset);
109 void AssembleAttReadByTypeRspCharacteristicPackage(
110 AttReadByTypeRspDataList *list, uint16_t attHandle, uint8_t num, uint8_t *offset);
111 bool AssembleAttReadByTypeRspDescPackage(
112 AttReadByTypeRspDataList *list, uint16_t connectHandle, uint16_t attHandle, uint8_t num, uint8_t *offset);
113 void AssembleAttFindInforRspSvcPackage(AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len);
114 void AssembleAttFindInforRspCharacteristicPackage(
115 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len);
116 void AssembleAttFindInforRspCharacteristicValPackage(
117 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len);
118 void AssembleAttFindInforRspDescPackage(AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len);
119 static void AssembleDataPackage(uint8_t *dest, uint8_t destMax, uint8_t *offset, uint8_t *src, uint8_t size);
120 static void AssembleDataPackage(uint8_t *dest, uint8_t *offset, uint8_t src);
121 static void FreeDataPackage(AttReadByTypeRspDataList *list, uint8_t num);
122 bool CharacteristicPropertyIsReadable(uint16_t attHandle);
123 bool DescriptorPropertyIsReadable(uint16_t attHandle);
124 bool CharacteristicPropertyIsWritable(uint16_t attHandle);
125 bool DescriptorPropertyIsWritable(uint16_t attHandle);
126 AttError WriteDescriptorProcess(uint16_t connectHandle, uint16_t attHandle, Buffer *value);
127 uint16_t GetMtuInformation(uint16_t connectHandle);
128 void SetMtuInformation(uint16_t connectHandle, uint16_t mtu);
129 std::list<std::pair<uint16_t, GattResponesInfor>>::iterator FindIteratorByResponesInfor(
130 uint16_t handle, ResponesType respType);
131 void DeleteList(uint16_t connectHandle);
132 void AddDeviceList(uint16_t connectHandle, GattDevice device);
133 void AddCccdValue(uint16_t connectHandle, uint16_t attHandle, uint16_t value);
134 void DeleteCccdValue(uint16_t connectHandle);
135 uint16_t GetCccdValue(uint16_t connectHandle, uint16_t attHandle);
136 };
137 /**
138 * @brief A constructor used to create <pServerCallbackFunc> <dispatcher> and <maxMtu> instance..
139 *
140 * @since 6.0
141 */
GattServerProfile(GattServerProfileCallback * pServerCallbackFunc,utility::Dispatcher * dispatcher,uint16_t maxMtu)142 GattServerProfile::GattServerProfile(
143 GattServerProfileCallback *pServerCallbackFunc, utility::Dispatcher *dispatcher, uint16_t maxMtu)
144 : pimpl(new (std::nothrow)GattServerProfile::impl(pServerCallbackFunc, dispatcher, maxMtu, *this))
145 {
146 if (pimpl == nullptr) {
147 LOG_ERROR("GattServerProfile get pimpl error");
148 return;
149 }
150 pimpl->RegisterCallbackToConnectManager();
151 }
152 /**
153 * @brief A destructor used to delete the <pServerCallbackFunc> <dispatcher> and <maxMtu> instance.
154 *
155 * @since 6.0
156 */
~GattServerProfile()157 GattServerProfile::~GattServerProfile()
158 {
159 pimpl->DeregisterCallbackToConnectManager();
160 }
161 /**
162 * @brief Enable gatt server profile.
163 *
164 * @since 6.0
165 */
Enable() const166 void GattServerProfile::Enable() const
167 {
168 pimpl->requestList_.clear();
169 pimpl->responseList_.clear();
170 pimpl->mtuInfo_.clear();
171 pimpl->RegisterCallbackToATT();
172 }
173 /**
174 * @brief Disable gatt server profile.
175 *
176 * @since 6.0
177 */
Disable() const178 void GattServerProfile::Disable() const
179 {
180 pimpl->DeregisterCallbackToATT();
181 pimpl->db_.RemoveAllServices();
182 }
183 /**
184 * @brief Register callback function to ATT.
185 *
186 * @since 6.0
187 */
RegisterCallbackToATT()188 void GattServerProfile::impl::RegisterCallbackToATT()
189 {
190 LOG_INFO("%{public}s", __FUNCTION__);
191 attCallback attDataCallback = GattServerProfile::impl::ReceiveData;
192 attSendDataCallback attReqCallback = GattServerProfile::impl::ReceiveResponseResult;
193
194 ATT_ServerDataRegister(attDataCallback, this);
195 ATT_ServerSendDataRegister(attReqCallback, this);
196 }
197 /**
198 * @brief Unregister callback function to att.
199 *
200 * @since 6.0
201 */
DeregisterCallbackToATT()202 void GattServerProfile::impl::DeregisterCallbackToATT()
203 {
204 LOG_INFO("%{public}s", __FUNCTION__);
205 ATT_ServerDataDeregister();
206 ATT_ServerSendDataDeRegister();
207 }
208 /**
209 * @brief Add iter to the response list.
210 *
211 * @since 6.0
212 */
AddResponseList(void)213 void GattServerProfile::impl::AddResponseList(void)
214 {
215 auto iter = requestList_.begin();
216 responseList_.emplace_back(*iter);
217 LOG_INFO("%{public}s: server responseList size: %{public}zu", __FUNCTION__, responseList_.size());
218 }
219 /**
220 * @brief This sub-procedure is used by the server to process split read by type request message.
221 *
222 * @param connectHandle Indicates identify a connection.
223 * @param data Indicates att data.
224 * @since 6.0
225 */
SplitReadByTypeReqMessage(uint16_t connectHandle,AttEventData * data)226 void GattServerProfile::impl::SplitReadByTypeReqMessage(uint16_t connectHandle, AttEventData *data)
227 {
228 switch (data->attReadByTypeRequest.readHandleRangeUuid.uuid->uuid16) {
229 case UUID_INCLUDE_SERVICE:
230 FindIncludedServiceResponsePostTask(connectHandle, data);
231 break;
232 case UUID_CHARACTERISTIC:
233 DiscoverCharacteristicResponsePostTask(connectHandle, data);
234 break;
235 default:
236 ReadUsingCharacteristicByUuidResponsePostTask(connectHandle, data);
237 break;
238 }
239 }
240 /**
241 * @brief This sub-procedure is used by the server to process received data from att.
242 *
243 * @param connectHandle Indicates identify a connection.
244 * @param event Indicates client callback event id.
245 * @param eventData Indicates att data.
246 * @param buffer Indicates att data.
247 * @param context Indicates client callback function.
248 * @since 6.0
249 */
ReceiveData(uint16_t connectHandle,uint16_t event,void * eventData,Buffer * buffer,void * context)250 void GattServerProfile::impl::ReceiveData(
251 uint16_t connectHandle, uint16_t event, void *eventData, Buffer *buffer, void *context)
252 {
253 LOG_INFO("GattServerProfile::%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
254 if (eventData == nullptr) {
255 return;
256 }
257
258 auto object = static_cast<GattServerProfile::impl *>(context);
259 switch (event) {
260 case ATT_EXCHANGE_MTU_REQUEST_ID:
261 object->ExchangeMTUResponse(connectHandle, ((AttEventData *)eventData)->attExchangeMtuRequest.mtuSize);
262 break;
263 case ATT_FIND_INFORMATION_REQUEST_ID:
264 object->DiscoverAllCharacteristicDescriptorResponsePostTask(connectHandle, ((AttEventData *)eventData));
265 break;
266 case ATT_FIND_BY_TYPE_VALUE_REQUEST_ID:
267 object->DiscoverPrimaryServiceByUuidResponsePostTask(connectHandle, buffer, (AttEventData *)eventData);
268 break;
269 case ATT_READ_BY_TYPE_REQUEST_ID:
270 object->SplitReadByTypeReqMessage(connectHandle, (AttEventData *)eventData);
271 break;
272 case ATT_READ_REQUEST_ID:
273 object->ReadValueResponsePostTask(
274 connectHandle, ((AttEventData *)eventData)->attReadRequest.readHandle.attHandle);
275 break;
276 case ATT_READ_BLOB_REQUEST_ID:
277 object->ReadBlobValueResponsePostTask(connectHandle, (AttEventData *)eventData);
278 break;
279 case ATT_READ_MULTIPLE_REQUEST_ID:
280 object->ReadMultipleCharacteristicValueResponsePostTask(connectHandle, (AttEventData *)eventData, buffer);
281 break;
282 case ATT_READ_BY_GROUP_TYPE_REQUEST_ID:
283 object->DiscoverAllPrimaryServiceResponsePostTask(connectHandle, (AttEventData *)eventData);
284 break;
285 case ATT_WRITE_REQUEST_ID:
286 object->WriteValueResponsePostTask(connectHandle, (AttEventData *)eventData, buffer);
287 break;
288 case ATT_WRITE_COMMAND_ID:
289 object->WriteWithoutResponsePostTask(connectHandle, (AttEventData *)eventData, buffer);
290 break;
291 case ATT_PREPARE_WRITE_REQUEST_ID:
292 object->WriteLongCharacteristicValueResponsePostTask(connectHandle, (AttEventData *)eventData, buffer);
293 break;
294 case ATT_EXECUTE_WRITE_REQUEST_ID:
295 object->ExecuteWriteResponsePostTask(connectHandle, (AttEventData *)eventData);
296 break;
297 case ATT_HANDLE_VALUE_CONFIRMATION_ID:
298 object->HandleValueConfirmationResponsePostTask(connectHandle, GATT_SUCCESS);
299 break;
300 case ATT_TRANSACTION_TIME_OUT_ID:
301 object->HandleValueConfirmationResponsePostTask(connectHandle, GATT_FAILURE);
302 break;
303 default:
304 AttError errorData = {*(uint8_t *)eventData, 0, ATT_REQUEST_NOT_SUPPORTED};
305 ATT_ErrorResponse(connectHandle, &errorData);
306 LOG_INFO("%{public}s: ATT_REQUEST_NOT_FOUND", __FUNCTION__);
307 break;
308 }
309 }
310 /**
311 * @brief This sub-procedure is used by the server to process received att response result.
312 *
313 * @param connectHandle Indicates identify a connection.
314 * @param result Indicates Response result.
315 * @param context Indicates server callback function.
316 * @since 6.0
317 */
ReceiveResponseResult(uint16_t connectHandle,int result,void * context)318 void GattServerProfile::impl::ReceiveResponseResult(uint16_t connectHandle, int result, void *context)
319 {
320 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
321 auto object = static_cast<GattServerProfile::impl *>(context);
322 object->dispatcher_->PostTask(std::bind(&impl::ReceiveResponseResultPostTask, object, connectHandle, result));
323 }
324
ReceiveResponseResultPostTask(uint16_t connectHandle,int result)325 void GattServerProfile::impl::ReceiveResponseResultPostTask(uint16_t connectHandle, int result)
326 {
327 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
328 auto iter = requestList_.begin();
329 if (iter != requestList_.end()) {
330 if (!result) {
331 switch (iter->second.respType_) {
332 case EXCHANGE_MTU:
333 SetMtuInformation(connectHandle, iter->second.value_);
334 pServerCallBack_->OnExchangeMtuEvent(connectHandle, iter->second.value_);
335 break;
336 case SEND_INDICATION:
337 case READ_LONG_CHARACTERISTIC_VALUE:
338 AddResponseList();
339 break;
340 default:
341 break;
342 }
343 }
344 requestList_.erase(iter);
345 }
346 }
347 /**
348 * @brief This sub-procedure is used by the server to set the ATT_MTU to the maximum possible value.
349 *
350 * @param connectHandle Indicates identify a connection.
351 * @param mtu Indicates att bearer transmission unit.
352 * @since 6.0
353 */
ExchangeMTUResponse(uint16_t connectHandle,uint16_t mtu)354 void GattServerProfile::impl::ExchangeMTUResponse(uint16_t connectHandle, uint16_t mtu)
355 {
356 LOG_INFO("%{public}s", __FUNCTION__);
357 AttError errorData = {READ_BY_GROUP_TYPE_REQUEST, 0, ATT_REQUEST_NOT_SUPPORTED};
358
359 if (mtu < GATT_DEFAULT_MTU) {
360 ATT_ErrorResponse(connectHandle, &errorData);
361 return;
362 } else if (mtu > mtu_) {
363 mtu = mtu_;
364 }
365 requestList_.emplace_back(connectHandle, GattResponesInfor(EXCHANGE_MTU, mtu));
366 ATT_ExchangeMTUResponse(connectHandle, mtu_);
367 }
368 /**
369 * @brief This sub-procedure is used by the servert to respond that discover all primary services.
370 *
371 * @param connectHandle Indicates identify a connection.
372 * @param data Indicates att data.
373 * @since 6.0
374 */
DiscoverAllPrimaryServiceResponsePostTask(uint16_t connectHandle,AttEventData * data)375 void GattServerProfile::impl::DiscoverAllPrimaryServiceResponsePostTask(uint16_t connectHandle, AttEventData *data)
376 {
377 LOG_INFO("%{public}s", __FUNCTION__);
378 uint16_t startHandle = data->attReadByGroupTypeRequest.readGroupRequest.handleRange.startHandle,
379 endHandle = data->attReadByGroupTypeRequest.readGroupRequest.handleRange.endHandle;
380 dispatcher_->PostTask(
381 std::bind(&impl::DiscoverAllPrimaryServiceResponse, this, connectHandle, startHandle, endHandle));
382 }
383
DiscoverAllPrimaryServiceResponse(uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle)384 void GattServerProfile::impl::DiscoverAllPrimaryServiceResponse(
385 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle)
386 {
387 LOG_INFO("%{public}s", __FUNCTION__);
388 uint8_t dataLen = 0;
389 uint16_t groupSize = 0;
390 uint16_t preUuidLen = 0;
391 uint16_t serviceNum = 0;
392 AttError errorData = {READ_BY_GROUP_TYPE_REQUEST, startHandle, 0};
393 AttReadGoupAttributeData serviceList[GATT_VALUE_LEN_MAX] = {{0, 0, nullptr}};
394 auto service = db_.GetServices().begin();
395
396 if (CheckAttHandleParameter(connectHandle, startHandle, endHandle, READ_BY_GROUP_TYPE_REQUEST)) {
397 return;
398 }
399 for (; service != db_.GetServices().end(); service++) {
400 if (startHandle <= service->second.handle_ && service->second.isPrimary_) {
401 uint16_t uuidLen = service->second.uuid_.GetUuidType();
402 if (uuidLen != UUID_16BIT_LEN) {
403 uuidLen = UUID_128BIT_LEN;
404 }
405 if (preUuidLen != 0 && preUuidLen != uuidLen) {
406 break;
407 }
408 preUuidLen = uuidLen;
409 dataLen = sizeof(startHandle) + sizeof(endHandle) + uuidLen;
410 groupSize = groupSize + dataLen;
411 if (groupSize <= GetMtuInformation(connectHandle) - sizeof(groupSize)) {
412 AssembleAttReadByGroupTypeRspPackage(serviceList, service->second, serviceNum);
413 serviceNum++;
414 } else {
415 break;
416 }
417 }
418 }
419 if (serviceNum) {
420 ATT_ReadByGroupTypeResponse(connectHandle, dataLen, serviceList, serviceNum);
421 for (int i = 0; i < serviceNum; i++) {
422 free(serviceList[i].attributeValue);
423 }
424 } else {
425 errorData.errorCode = ATT_ATTRIBUTE_NOT_FOUND;
426 ATT_ErrorResponse(connectHandle, &errorData);
427 }
428 }
429 /**
430 * @brief This sub-procedure is used by the server to respond that discover all primary services by uuid.
431 *
432 * @param connectHandle Indicates identify a connection.
433 * @param value Indicates att data.
434 * @param data Indicates att handle infor.
435 * @since 6.0
436 */
DiscoverPrimaryServiceByUuidResponsePostTask(uint16_t connectHandle,Buffer * value,AttEventData * data)437 void GattServerProfile::impl::DiscoverPrimaryServiceByUuidResponsePostTask(
438 uint16_t connectHandle, Buffer *value, AttEventData *data)
439 {
440 Buffer *attData = BufferRefMalloc(value);
441 uint16_t startHandle = data->attFindByTypeValueRequest.findByTypeValueRequest.handleRange.startHandle;
442 uint16_t endHandle = data->attFindByTypeValueRequest.findByTypeValueRequest.handleRange.endHandle;
443
444 dispatcher_->PostTask(
445 std::bind(&impl::DiscoverPrimaryServiceByUuidResponse, this, connectHandle, attData, startHandle, endHandle));
446 }
447
DiscoverPrimaryServiceByUuidResponse(uint16_t connectHandle,Buffer * value,uint16_t startHandle,uint16_t endHandle)448 void GattServerProfile::impl::DiscoverPrimaryServiceByUuidResponse(
449 uint16_t connectHandle, Buffer *value, uint16_t startHandle, uint16_t endHandle)
450 {
451 LOG_INFO("%{public}s", __FUNCTION__);
452 Uuid uuid;
453 uint16_t listNum = 0;
454 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
455 AttHandleInfo handleInfoList[GATT_VALUE_LEN_MAX] = {{0, 0}};
456 AttError errorData = {FIND_BY_TYPE_VALUE_REQUEST, startHandle, ATT_ATTRIBUTE_NOT_FOUND};
457 auto service = db_.GetServices().begin();
458
459 if (CheckAttHandleParameter(connectHandle, startHandle, endHandle, FIND_BY_TYPE_VALUE_REQUEST)) {
460 return;
461 }
462 (void)memcpy_s(uuid128Bit, UUID_128BIT_LEN, BufferPtr(value), BufferGetSize(value));
463 if (BufferGetSize(value) == UUID_16BIT_LEN) {
464 uuid = Uuid::ConvertFrom16Bits((uuid128Bit[0] | (uuid128Bit[1] << BIT_8)));
465 } else if (BufferGetSize(value) == UUID_128BIT_LEN) {
466 uuid = Uuid::ConvertFromBytesLE(uuid128Bit, UUID_128BIT_LEN);
467 } else {
468 goto ATT_ERROR_RESPONSE;
469 }
470 for (; service != db_.GetServices().end(); service++) {
471 if (startHandle <= service->second.handle_ && service->second.uuid_.operator==(uuid) &&
472 service->second.isPrimary_) {
473 handleInfoList->attHandle = service->second.handle_;
474 handleInfoList->groupEndHandle = service->second.endHandle_;
475 if ((uint16_t)((listNum + sizeof(uint8_t)) * (sizeof(startHandle) + sizeof(endHandle))) >
476 GetMtuInformation(connectHandle) - 1) {
477 break;
478 }
479 listNum++;
480 }
481 }
482 if (listNum) {
483 ATT_FindByTypeValueResponse(connectHandle, handleInfoList, listNum);
484 } else {
485 ATT_ERROR_RESPONSE:
486 ATT_ErrorResponse(connectHandle, &errorData);
487 }
488 BufferFree(value);
489 }
490 /**
491 * @brief This sub-procedure is used by the server to respond that find include 16bit uuid services.
492 *
493 * @param connectHandle Indicates identify a connection.
494 * @param data Indicates att data.
495 * @since 6.0
496 */
FindIncludedServiceResponsePostTask(uint16_t connectHandle,AttEventData * data)497 void GattServerProfile::impl::FindIncludedServiceResponsePostTask(uint16_t connectHandle, AttEventData *data)
498 {
499 uint16_t startHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.startHandle;
500 uint16_t endHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.endHandle;
501
502 dispatcher_->PostTask(std::bind(&impl::FindIncludedServiceResponse, this, connectHandle, startHandle, endHandle));
503 }
504
FindIncludedServiceResponse(uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle)505 void GattServerProfile::impl::FindIncludedServiceResponse(
506 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle)
507 {
508 LOG_INFO("%{public}s", __FUNCTION__);
509 uint8_t offset = 0;
510 AttReadByTypeRspDataList valueList[GATT_VALUE_LEN_MAX] = {{{0}, nullptr}};
511 AttError errorData = {READ_BY_TYPE_REQUEST, startHandle, 0};
512
513 if (CheckAttHandleParameter(connectHandle, startHandle, endHandle, READ_BY_TYPE_REQUEST)) {
514 return;
515 }
516 for (; startHandle <= endHandle; startHandle++) {
517 auto isvc = db_.GetIncludeService(startHandle);
518 if (isvc != nullptr) {
519 uint8_t len = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t);
520 valueList[0].attHandle.attHandle = isvc->handle_;
521 valueList[0].attributeValue = (uint8_t *)malloc(len);
522 if (valueList[0].attributeValue == nullptr) {
523 LOG_ERROR("%{public}s, malloc fail", __FUNCTION__);
524 return;
525 }
526 AssembleDataPackage(
527 valueList[0].attributeValue, len, &offset, (uint8_t *)&(isvc->startHandle_), sizeof(uint16_t));
528 AssembleDataPackage(
529 valueList[0].attributeValue, len, &offset, (uint8_t *)&(isvc->endHandle_), sizeof(uint16_t));
530 if (isvc->uuid_.GetUuidType() == UUID_16BIT_LEN) {
531 uint16_t uuid16bit = isvc->uuid_.ConvertTo16Bits();
532 AssembleDataPackage(
533 valueList[0].attributeValue, len, &offset, (uint8_t *)&(uuid16bit), sizeof(uint16_t));
534 len = len + UUID_16BIT_LEN;
535 }
536 ATT_ReadByTypeResponse(connectHandle, len, valueList, sizeof(uint8_t));
537 free(valueList[0].attributeValue);
538 return;
539 }
540 if (FindServiceEndingHandle(startHandle)) {
541 break;
542 }
543 }
544 errorData.errorCode = ATT_ATTRIBUTE_NOT_FOUND;
545 ATT_ErrorResponse(connectHandle, &errorData);
546 }
547 /**
548 * @brief This sub-procedure is used by the server to respond that discover all characteristics.
549 *
550 * @param connectHandle Indicates identify a connection.
551 * @param data Indicates att data.
552 * @since 6.0
553 */
DiscoverCharacteristicResponsePostTask(uint16_t connectHandle,AttEventData * data)554 void GattServerProfile::impl::DiscoverCharacteristicResponsePostTask(uint16_t connectHandle, AttEventData *data)
555 {
556 uint16_t startHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.startHandle;
557 uint16_t endHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.endHandle;
558
559 dispatcher_->PostTask(
560 std::bind(&impl::DiscoverCharacteristicResponse, this, connectHandle, startHandle, endHandle));
561 }
562
DiscoverCharacteristicResponse(uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle)563 void GattServerProfile::impl::DiscoverCharacteristicResponse(
564 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle)
565 {
566 LOG_INFO("%{public}s", __FUNCTION__);
567 uint8_t dataLen = 0;
568 uint16_t groupSize = 0;
569 uint16_t valueNum = 0;
570 uint16_t preUuidLen = 0;
571 AttReadByTypeRspDataList valueList[GATT_VALUE_LEN_MAX] = {{{0}, nullptr}};
572
573 if (CheckAttHandleParameter(connectHandle, startHandle, endHandle, READ_BY_TYPE_REQUEST)) {
574 return;
575 }
576 for (; startHandle <= endHandle; startHandle++) {
577 uint8_t offset = 0;
578 auto characteristic = db_.GetCharacteristic(startHandle + MIN_ATTRIBUTE_HANDLE);
579 if (characteristic != nullptr) {
580 uint16_t uuidLen = characteristic->uuid_.GetUuidType();
581 if (uuidLen != UUID_16BIT_LEN) {
582 uuidLen = UUID_128BIT_LEN;
583 }
584 if (preUuidLen != 0 && preUuidLen != uuidLen) {
585 break;
586 }
587 preUuidLen = uuidLen;
588 dataLen = sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint16_t) + uuidLen;
589 groupSize = groupSize + dataLen;
590 if (characteristic->valueHandle_ <= endHandle &&
591 groupSize <= GetMtuInformation(connectHandle) - sizeof(groupSize)) {
592 AssembleAttReadByTypeRspCharacteristicPackage(
593 valueList, startHandle + MIN_ATTRIBUTE_HANDLE, valueNum, &offset);
594 valueNum++;
595 } else {
596 break;
597 }
598 } else if (FindServiceEndingHandle(startHandle)) {
599 break;
600 }
601 }
602 SendAttReadByTypeResponse(connectHandle, startHandle, dataLen, valueList, valueNum);
603 }
604 /**
605 * @brief This sub-procedure is used by the server to respond that discover all characteristic descriptors.
606 *
607 * @param connectHandle Indicates identify a connection.
608 * @param data Indicates att data.
609 * @since 6.0
610 */
DiscoverAllCharacteristicDescriptorResponsePostTask(uint16_t connectHandle,AttEventData * data)611 void GattServerProfile::impl::DiscoverAllCharacteristicDescriptorResponsePostTask(
612 uint16_t connectHandle, AttEventData *data)
613 {
614 uint16_t startHandle = data->attFindInformationRequest.findInformationRequest.startHandle;
615 uint16_t endHandle = data->attFindInformationRequest.findInformationRequest.endHandle;
616
617 dispatcher_->PostTask(
618 std::bind(&impl::DiscoverAllCharacteristicDescriptorResponse, this, connectHandle, startHandle, endHandle));
619 }
620
DiscoverAllCharacteristicDescriptorResponse(uint16_t connectHandle,uint16_t attHandle,uint16_t endHandle)621 void GattServerProfile::impl::DiscoverAllCharacteristicDescriptorResponse(
622 uint16_t connectHandle, uint16_t attHandle, uint16_t endHandle)
623 {
624 LOG_INFO("%{public}s", __FUNCTION__);
625 uint16_t pairNum = 0;
626 uint16_t uuidLen = 0;
627 uint16_t groupSize = 0;
628 uint16_t preUuidLen = 0;
629 AttHandleUuid handleUUIDPairs[GATT_VALUE_LEN_MAX] = {{0, {0, {0}}}};
630 AttError errorData = {FIND_INFORMATION_REQUEST, attHandle, ATT_ATTRIBUTE_NOT_FOUND};
631
632 if (CheckAttHandleParameter(connectHandle, attHandle, endHandle, FIND_INFORMATION_REQUEST)) {
633 return;
634 }
635 for (; attHandle <= endHandle; attHandle++) {
636 if (db_.GetService(attHandle) != nullptr) {
637 AssembleAttFindInforRspSvcPackage(handleUUIDPairs, attHandle, pairNum, &uuidLen);
638 } else if (db_.GetDescriptor(attHandle) != nullptr) {
639 AssembleAttFindInforRspDescPackage(handleUUIDPairs, attHandle, pairNum, &uuidLen);
640 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
641 AssembleAttFindInforRspCharacteristicValPackage(handleUUIDPairs, attHandle, pairNum, &uuidLen);
642 } else if (db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE) != nullptr) {
643 AssembleAttFindInforRspCharacteristicPackage(handleUUIDPairs, attHandle, pairNum, &uuidLen);
644 } else {
645 if (FindServiceEndingHandle(attHandle)) {
646 break;
647 }
648 continue;
649 }
650 if (preUuidLen != 0 && preUuidLen != uuidLen) {
651 break;
652 }
653 preUuidLen = uuidLen;
654 groupSize = groupSize + sizeof(uint16_t) + uuidLen;
655 if (groupSize <= GetMtuInformation(connectHandle) - sizeof(groupSize)) {
656 pairNum++;
657 } else {
658 break;
659 }
660 }
661
662 if (pairNum) {
663 ATT_FindInformationResponse(connectHandle, handleUUIDPairs->uuid.type, handleUUIDPairs, pairNum);
664 } else {
665 ATT_ErrorResponse(connectHandle, &errorData);
666 }
667 }
668 /**
669 * @brief This sub-procedure is used to respond that read value.
670 *
671 * @param connectHandle Indicates identify a connection.
672 * @param attHandle Indicates attribute handle.
673 * @since 6.0
674 */
ReadValueResponsePostTask(uint16_t connectHandle,uint16_t attHandle)675 void GattServerProfile::impl::ReadValueResponsePostTask(uint16_t connectHandle, uint16_t attHandle)
676 {
677 dispatcher_->PostTask(std::bind(&impl::ReadValueResponse, this, connectHandle, attHandle));
678 }
679
ReadValueResponse(uint16_t connectHandle,uint16_t attHandle)680 void GattServerProfile::impl::ReadValueResponse(uint16_t connectHandle, uint16_t attHandle)
681 {
682 LOG_INFO("%{public}s", __FUNCTION__);
683 Buffer *value = nullptr;
684 AttError errorData = {READ_REQUEST, attHandle, 0};
685
686 if (db_.GetService(attHandle) != nullptr) {
687 value = AssembleServicePackage(attHandle);
688 if (value != nullptr) {
689 ATT_ReadResponse(connectHandle, value);
690 BufferFree(value);
691 } else {
692 errorData.errorCode = ATT_INVALID_HANDLE;
693 }
694 } else if (db_.GetDescriptor(attHandle) != nullptr) {
695 if (DescriptorPropertyIsReadable(attHandle)) {
696 value = AssembleDescriptorPackage(connectHandle, attHandle);
697 if (value != nullptr) {
698 ATT_ReadResponse(connectHandle, value);
699 BufferFree(value);
700 } else {
701 pServerCallBack_->OnDescriptorReadEvent(connectHandle, attHandle);
702 }
703 } else {
704 errorData.errorCode = ATT_READ_NOT_PERMITTED;
705 }
706 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
707 if (CharacteristicPropertyIsReadable(attHandle)) {
708 pServerCallBack_->OnReadCharacteristicValueEvent(connectHandle, attHandle);
709 } else {
710 errorData.errorCode = ATT_READ_NOT_PERMITTED;
711 }
712 } else if (db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE) != nullptr) {
713 value = AssembleCharacteristicPackage(attHandle + MIN_ATTRIBUTE_HANDLE);
714 if (value != nullptr) {
715 ATT_ReadResponse(connectHandle, value);
716 BufferFree(value);
717 } else {
718 errorData.errorCode = ATT_INVALID_HANDLE;
719 }
720 } else {
721 errorData.errorCode = ATT_INVALID_HANDLE;
722 }
723 if (errorData.errorCode) {
724 ATT_ErrorResponse(connectHandle, &errorData);
725 }
726 }
727 /**
728 * @brief This sub-procedure is used to respond that read a characteristic value by uuid.
729 *
730 * @param connectHandle Indicates identify a connection.
731 * @param data Indicates att data.
732 * @since 6.0
733 */
ReadUsingCharacteristicByUuidResponsePostTask(uint16_t connectHandle,AttEventData * data)734 void GattServerProfile::impl::ReadUsingCharacteristicByUuidResponsePostTask(uint16_t connectHandle, AttEventData *data)
735 {
736 Uuid uuid;
737 uint16_t startHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.startHandle;
738 uint16_t endHandle = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.endHandle;
739 if (CheckUuidType(connectHandle, &uuid, data)) {
740 return;
741 }
742 dispatcher_->PostTask(std::bind(
743 &impl::ReadUsingCharacteristicByUuidResponseStep1, this, connectHandle, startHandle, endHandle, uuid));
744 }
745
ReadUsingCharacteristicByUuidResponseStep1(uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle,Uuid uuid)746 void GattServerProfile::impl::ReadUsingCharacteristicByUuidResponseStep1(
747 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, Uuid uuid)
748 {
749 LOG_INFO("%{public}s", __FUNCTION__);
750 uint8_t dataLen = 0;
751 uint8_t preDataLen = 0;
752 uint16_t groupSize = 0;
753 uint16_t valueNum = 0;
754 AttReadByTypeRspDataList valueList[GATT_VALUE_LEN_MAX] = {{{0}, nullptr}};
755
756 if (CheckAttHandleParameter(connectHandle, startHandle, endHandle, READ_BY_TYPE_REQUEST)) {
757 return;
758 }
759 for (; startHandle <= endHandle; startHandle++) {
760 uint8_t offset = 0;
761 RetVal ret =
762 ReadUsingCharacteristicByUuidResponseStep2(connectHandle, startHandle, valueNum, valueList, uuid, &offset);
763 if (ret == RET_RETURN) {
764 return;
765 } else if (ret == RET_BREAK) {
766 break;
767 } else if (ret == RET_CONTINUE) {
768 continue;
769 }
770 groupSize = groupSize + offset;
771 dataLen = offset + sizeof(uint16_t);
772 if (preDataLen == 0 ||
773 (preDataLen == dataLen && groupSize <= GetMtuInformation(connectHandle) - sizeof(groupSize))) {
774 valueNum++;
775 preDataLen = dataLen;
776 } else {
777 dataLen = preDataLen;
778 break;
779 }
780 }
781
782 SendAttReadByTypeResponse(connectHandle, startHandle, dataLen, valueList, valueNum);
783 }
784
ReadUsingCharacteristicByUuidResponseStep2(uint16_t connectHandle,uint16_t startHandle,uint16_t num,AttReadByTypeRspDataList * list,Uuid uuid,uint8_t * offset)785 RetVal GattServerProfile::impl::ReadUsingCharacteristicByUuidResponseStep2(uint16_t connectHandle, uint16_t startHandle,
786 uint16_t num, AttReadByTypeRspDataList *list, Uuid uuid, uint8_t *offset)
787 {
788 RetVal ret = RET_NORMAL;
789 AttError errorData = {READ_BY_TYPE_REQUEST, startHandle, ATT_READ_NOT_PERMITTED};
790
791 if (FindServiceByHandle(startHandle, uuid)) {
792 AssembleAttReadByTypeRspSvcPackage(list, startHandle, num, offset);
793 } else if (FindCharacteristicDescriptorByUuid(startHandle, uuid)) {
794 if (DescriptorPropertyIsReadable(startHandle)) {
795 if (AssembleAttReadByTypeRspDescPackage(list, connectHandle, startHandle, num, offset)) {
796 pServerCallBack_->OnReadUsingCharacteristicUuidEvent(connectHandle, startHandle);
797 ret = RET_RETURN;
798 }
799 } else {
800 ATT_ErrorResponse(connectHandle, &errorData);
801 ret = RET_RETURN;
802 }
803 } else if (FindCharacteristicValueByUuid(startHandle, uuid)) {
804 if (CharacteristicPropertyIsReadable(startHandle)) {
805 pServerCallBack_->OnReadUsingCharacteristicUuidEvent(connectHandle, startHandle);
806 } else {
807 ATT_ErrorResponse(connectHandle, &errorData);
808 }
809 ret = RET_RETURN;
810 } else if (FindCharacteristicDeclarationByHandle(startHandle, uuid)) {
811 AssembleAttReadByTypeRspCharacteristicPackage(list, startHandle + MIN_ATTRIBUTE_HANDLE, num, offset);
812 } else {
813 if (FindServiceEndingHandle(startHandle)) {
814 ret = RET_BREAK;
815 } else {
816 ret = RET_CONTINUE;
817 }
818 }
819
820 return ret;
821 }
822 /**
823 * @brief This sub-procedure is used to respond that read long characteristic value.
824 *
825 * @param connectHandle Indicates identify a connection.
826 * @param data Indicates att data.
827 * @since 6.0
828 */
ReadBlobValueResponsePostTask(uint16_t connectHandle,AttEventData * data)829 void GattServerProfile::impl::ReadBlobValueResponsePostTask(uint16_t connectHandle, AttEventData *data)
830 {
831 uint16_t attHandle = data->attReadBlobRequest.readBlob.attHandle;
832 uint16_t offset = data->attReadBlobRequest.readBlob.offset;
833 dispatcher_->PostTask(std::bind(&impl::ReadBlobValueResponse, this, connectHandle, attHandle, offset));
834 }
835
ReadBlobValueResponse(uint16_t connectHandle,uint16_t attHandle,uint16_t offset)836 void GattServerProfile::impl::ReadBlobValueResponse(uint16_t connectHandle, uint16_t attHandle, uint16_t offset)
837 {
838 LOG_INFO("%{public}s", __FUNCTION__);
839 Buffer *buffer = nullptr;
840 uint16_t bufSize = GetMtuInformation(connectHandle) - sizeof(uint8_t);
841 AttError errorData = {READ_BLOB_REQUEST, attHandle, 0};
842
843 auto iter = FindIteratorByResponesInfor(connectHandle, READ_LONG_CHARACTERISTIC_VALUE);
844 if (iter != responseList_.end()) {
845 uint16_t len = iter->second.value_;
846 if (len < offset) {
847 errorData.errorCode = ATT_INVALID_OFFSET;
848 } else {
849 if (len < bufSize + offset) {
850 bufSize = len - offset;
851 } else {
852 requestList_.emplace_back(connectHandle,
853 GattResponesInfor(READ_LONG_CHARACTERISTIC_VALUE, iter->second.value_, iter->second.data_));
854 }
855 buffer = GattServiceBase::BuildBuffer(iter->second.data_->get(), (size_t)offset, (size_t)bufSize);
856 responseList_.erase(iter);
857 }
858 } else if (offset != 0x00) {
859 errorData.errorCode = ATT_INVALID_OFFSET;
860 } else {
861 if (db_.GetService(attHandle) != nullptr) {
862 buffer = AssembleServicePackage(attHandle);
863 } else if (db_.GetDescriptor(attHandle) != nullptr) {
864 if (!DescriptorPropertyIsReadable(attHandle)) {
865 errorData.errorCode = ATT_READ_NOT_PERMITTED;
866 }
867 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
868 if (!CharacteristicPropertyIsReadable(attHandle)) {
869 errorData.errorCode = ATT_READ_NOT_PERMITTED;
870 }
871 } else if (db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE) != nullptr) {
872 buffer = AssembleCharacteristicPackage(attHandle + MIN_ATTRIBUTE_HANDLE);
873 } else {
874 errorData.errorCode = ATT_INVALID_HANDLE;
875 }
876 }
877 if (errorData.errorCode) {
878 ATT_ErrorResponse(connectHandle, &errorData);
879 } else if (buffer != nullptr) {
880 ATT_ReadBlobResponse(connectHandle, buffer);
881 BufferFree(buffer);
882 } else {
883 pServerCallBack_->ReadBlobValueEvent(connectHandle, attHandle);
884 }
885 }
886 /**
887 * @brief This sub-procedure is used to respond that read multiple characteristic values.
888 *
889 * @param connectHandle Indicates identify a connection.
890 * @since 6.0
891 */
ReadMultipleCharacteristicValueResponsePostTask(uint16_t connectHandle,AttEventData * data,Buffer * value)892 void GattServerProfile::impl::ReadMultipleCharacteristicValueResponsePostTask(
893 uint16_t connectHandle, AttEventData *data, Buffer *value)
894 {
895 Buffer *attData = BufferRefMalloc(value);
896 dispatcher_->PostTask(std::bind(&impl::ReadMultipleCharacteristicValueResponse, this, connectHandle, attData));
897 }
898
ReadMultipleCharacteristicValueResponse(uint16_t connectHandle,Buffer * value)899 void GattServerProfile::impl::ReadMultipleCharacteristicValueResponse(uint16_t connectHandle, Buffer *value)
900 {
901 auto dataPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), BufferGetSize(value));
902 pServerCallBack_->OnMultipleCharacteristicValueEvent(connectHandle, dataPtr, BufferGetSize(value));
903 }
904 /**
905 * @brief This sub-procedure is used to respond that write values.
906 *
907 * @param connectHandle Indicates identify a connection.
908 * @param data Indicates att data.
909 * @param value Indicates value of the schedule settings.
910 * @since 6.0
911 */
WriteValueResponsePostTask(uint16_t connectHandle,AttEventData * data,Buffer * value)912 void GattServerProfile::impl::WriteValueResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value)
913 {
914 Buffer *attData = BufferRefMalloc(value);
915 uint16_t attHandle = data->attWriteRequest.writeRequest.attHandle;
916
917 dispatcher_->PostTask(std::bind(&impl::WriteValueResponse, this, connectHandle, attHandle, attData));
918 }
919
WriteValueResponse(uint16_t connectHandle,uint16_t attHandle,Buffer * value)920 void GattServerProfile::impl::WriteValueResponse(uint16_t connectHandle, uint16_t attHandle, Buffer *value)
921 {
922 LOG_INFO("%{public}s", __FUNCTION__);
923 AttError errorData = {WRITE_REQUEST, attHandle, 0};
924
925 if (db_.GetService(attHandle) != nullptr) {
926 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
927 } else if (db_.GetDescriptor(attHandle) != nullptr) {
928 if (DescriptorPropertyIsWritable(attHandle)) {
929 errorData = WriteDescriptorProcess(connectHandle, attHandle, value);
930 } else {
931 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
932 }
933 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
934 if (CharacteristicPropertyIsWritable(attHandle)) {
935 auto cccPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), BufferGetSize(value));
936 pServerCallBack_->OnWriteCharacteristicValueEvent(connectHandle, attHandle, cccPtr, BufferGetSize(value));
937 } else {
938 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
939 }
940 } else if (db_.GetCharacteristic(MIN_ATTRIBUTE_HANDLE + attHandle) != nullptr) {
941 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
942 } else {
943 errorData.errorCode = ATT_INVALID_HANDLE;
944 }
945
946 if (errorData.errorCode) {
947 ATT_ErrorResponse(connectHandle, &errorData);
948 }
949 BufferFree(value);
950 }
951 /**
952 * @brief This sub-procedure is used to respond that write without response.
953 *
954 * @param connectHandle Indicates identify a connection.
955 * @param data Indicates att data.
956 * @param value Indicates value of the schedule settings.
957 * @since 6.0
958 */
WriteWithoutResponsePostTask(uint16_t connectHandle,AttEventData * data,Buffer * value)959 void GattServerProfile::impl::WriteWithoutResponsePostTask(uint16_t connectHandle, AttEventData *data, Buffer *value)
960 {
961 Buffer *attData = BufferRefMalloc(value);
962 uint16_t attHandle = data->attWriteCommand.writeCommand.attHandle;
963
964 dispatcher_->PostTask(std::bind(&impl::WriteWithoutResponse, this, connectHandle, attHandle, attData));
965 }
966
WriteWithoutResponse(uint16_t connectHandle,uint16_t attHandle,Buffer * value)967 void GattServerProfile::impl::WriteWithoutResponse(uint16_t connectHandle, uint16_t attHandle, Buffer *value)
968 {
969 LOG_INFO("%{public}s", __FUNCTION__);
970 if (db_.GetDescriptor(attHandle) != nullptr) {
971 if (DescriptorPropertyIsWritable(attHandle)) {
972 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), BufferGetSize(value));
973 pServerCallBack_->OnWriteWithoutResponseEvent(connectHandle, attHandle, sharedPtr, BufferGetSize(value));
974 }
975 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
976 if (db_.GetCharacteristic(attHandle)->properties_ & CHARACTERISTIC_PROPERTIE_WRITE_WITHOUT_RESPONSE) {
977 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), BufferGetSize(value));
978 pServerCallBack_->OnWriteWithoutResponseEvent(connectHandle, attHandle, sharedPtr, BufferGetSize(value));
979 }
980 }
981 BufferFree(value);
982 }
983 /**
984 * @brief This sub-procedure is used to respond that write long characteristic values.
985 *
986 * @param connectHandle Indicates identify a connection.
987 * @param data Indicates att data.
988 * @param value Indicates value of the schedule settings.
989 * @since 6.0
990 */
WriteLongCharacteristicValueResponsePostTask(uint16_t connectHandle,AttEventData * data,Buffer * value)991 void GattServerProfile::impl::WriteLongCharacteristicValueResponsePostTask(
992 uint16_t connectHandle, AttEventData *data, Buffer *value)
993 {
994 Buffer *attData = BufferRefMalloc(value);
995 uint16_t attHandle = data->attPrepareWriteResponse.prepareWrite.handleValue.attHandle;
996 uint16_t offset = data->attPrepareWriteResponse.prepareWrite.offset;
997
998 dispatcher_->PostTask(
999 std::bind(&impl::WriteLongCharacteristicValueResponse, this, connectHandle, attHandle, offset, attData));
1000 }
1001
WriteLongCharacteristicValueResponse(uint16_t connectHandle,uint16_t attHandle,uint16_t offset,Buffer * value)1002 void GattServerProfile::impl::WriteLongCharacteristicValueResponse(
1003 uint16_t connectHandle, uint16_t attHandle, uint16_t offset, Buffer *value)
1004 {
1005 LOG_INFO("%{public}s", __FUNCTION__);
1006 size_t len = BufferGetSize(value);
1007 AttError errorData = {PREPARE_WRITE_REQUEST, attHandle, 0};
1008
1009 if (db_.GetService(attHandle) != nullptr) {
1010 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
1011 } else if (db_.GetDescriptor(attHandle) != nullptr) {
1012 if (DescriptorPropertyIsWritable(attHandle)) {
1013 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), len);
1014 pServerCallBack_->OnPrepareWriteValueEvent(connectHandle, attHandle, offset, sharedPtr, len);
1015 } else {
1016 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
1017 }
1018 } else if (db_.GetCharacteristic(attHandle) != nullptr) {
1019 if (CharacteristicPropertyIsWritable(attHandle)) {
1020 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), len);
1021 pServerCallBack_->OnPrepareWriteValueEvent(connectHandle, attHandle, offset, sharedPtr, len);
1022 } else {
1023 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
1024 }
1025 } else if (db_.GetCharacteristic(MIN_ATTRIBUTE_HANDLE + attHandle) != nullptr) {
1026 errorData.errorCode = ATT_WRITE_NOT_PERMITTED;
1027 } else {
1028 errorData.errorCode = ATT_INVALID_HANDLE;
1029 }
1030
1031 if (errorData.errorCode) {
1032 ATT_ErrorResponse(connectHandle, &errorData);
1033 }
1034 }
1035 /**
1036 * @brief This sub-procedure is used to respond that execute write values.
1037 *
1038 * @param connectHandle Indicates identify a connection.
1039 * @param data Indicates att data.
1040 * @since 6.0
1041 */
ExecuteWriteResponsePostTask(uint16_t connectHandle,AttEventData * data)1042 void GattServerProfile::impl::ExecuteWriteResponsePostTask(uint16_t connectHandle, AttEventData *data)
1043 {
1044 bool flag = data->attExecuteWriteRequest.excuteWrite.flag;
1045 dispatcher_->PostTask(std::bind(&impl::ExecuteWriteResponse, this, connectHandle, flag));
1046 }
1047
ExecuteWriteResponse(uint16_t connectHandle,bool flag)1048 void GattServerProfile::impl::ExecuteWriteResponse(uint16_t connectHandle, bool flag)
1049 {
1050 LOG_INFO("%{public}s", __FUNCTION__);
1051 pServerCallBack_->OnExecuteWriteValueEvent(connectHandle, flag);
1052 }
1053 /**
1054 * @brief The Attribute Protocol Handle Value Indication is used to perform this subprocedure.
1055 *
1056 * @param connectHandle Indicates identify a connection.
1057 * @param ret Indicates result of respond.
1058 * @since 6.0
1059 */
HandleValueConfirmationResponsePostTask(uint16_t connectHandle,int ret)1060 void GattServerProfile::impl::HandleValueConfirmationResponsePostTask(uint16_t connectHandle, int ret)
1061 {
1062 dispatcher_->PostTask(std::bind(&impl::HandleValueConfirmationResponse, this, connectHandle, ret));
1063 }
1064
HandleValueConfirmationResponse(uint16_t connectHandle,int ret)1065 void GattServerProfile::impl::HandleValueConfirmationResponse(uint16_t connectHandle, int ret)
1066 {
1067 LOG_INFO("%{public}s", __FUNCTION__);
1068 auto attResp = FindIteratorByResponesInfor(connectHandle, SEND_INDICATION);
1069 if (attResp == responseList_.end()) {
1070 return;
1071 }
1072 pServerCallBack_->OnIndicationEvent(connectHandle, attResp->second.value_, ret);
1073 }
1074 /**
1075 * @brief This sub-procedure is used to Send Att ReadByTypeResponse.
1076 *
1077 * @param connectHandle Indicates identify a connection.
1078 * @param handle Indicates handle of error response.
1079 * @param len Indicates value length.
1080 * @param value Indicates send value.
1081 * @param num Indicates handle value pair.
1082 * @since 6.0
1083 */
SendAttReadByTypeResponse(uint16_t connectHandle,uint16_t handle,uint8_t len,AttReadByTypeRspDataList * value,uint16_t num)1084 void GattServerProfile::impl::SendAttReadByTypeResponse(
1085 uint16_t connectHandle, uint16_t handle, uint8_t len, AttReadByTypeRspDataList *value, uint16_t num)
1086 {
1087 LOG_INFO("%{public}s", __FUNCTION__);
1088 AttError errorData = {READ_BY_TYPE_REQUEST, handle, ATT_ATTRIBUTE_NOT_FOUND};
1089
1090 if (num) {
1091 ATT_ReadByTypeResponse(connectHandle, len, value, num);
1092 FreeDataPackage(value, num);
1093 } else {
1094 ATT_ErrorResponse(connectHandle, &errorData);
1095 }
1096 }
1097 /**
1098 * @brief Check the correctness of the attribute handle.
1099 *
1100 * @param connectHandle Indicates identify a connection.
1101 * @param startHandle Indicates attribute start handle.
1102 * @param endHandle Indicates attribute end handle.
1103 * @param requestId Indicates send request type.
1104 * @return Returns true if the parameter is invalid. Returns false if the parameter is valid.
1105 * @since 6.0
1106 */
CheckAttHandleParameter(uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle,uint8_t requestId)1107 bool GattServerProfile::impl::CheckAttHandleParameter(
1108 uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, uint8_t requestId)
1109 {
1110 bool result = false;
1111 AttError errorData = {requestId, startHandle, ATT_INVALID_HANDLE};
1112
1113 if (startHandle == INVALID_ATTRIBUTE_HANDLE || startHandle > endHandle) {
1114 ATT_ErrorResponse(connectHandle, &errorData);
1115 result = true;
1116 }
1117
1118 return result;
1119 }
1120 /**
1121 * @brief Check the correctness of the uuid type.
1122 *
1123 * @param connectHandle Indicates identify a connection.
1124 * @param uuid Indicates uuid of expectation.
1125 * @param data Indicates attribute data.
1126 * @return Returns true if the uuid parameter is invalid. Returns false if the parameter is valid.
1127 * @since 6.0
1128 */
CheckUuidType(uint16_t connectHandle,Uuid * uuid,AttEventData * data)1129 bool GattServerProfile::impl::CheckUuidType(uint16_t connectHandle, Uuid *uuid, AttEventData *data)
1130 {
1131 bool result = false;
1132 AttError errorData;
1133
1134 if (data->attReadByTypeRequest.readHandleRangeUuid.uuid->type == BT_UUID_16) {
1135 *uuid = Uuid::ConvertFrom16Bits(data->attReadByTypeRequest.readHandleRangeUuid.uuid->uuid16);
1136 } else if (data->attReadByTypeRequest.readHandleRangeUuid.uuid->type == BT_UUID_128) {
1137 *uuid = Uuid::ConvertFromBytesLE(data->attReadByTypeRequest.readHandleRangeUuid.uuid->uuid128, UUID_128BIT_LEN);
1138 } else {
1139 errorData.reqOpcode = READ_BY_TYPE_REQUEST;
1140 errorData.errorCode = ATT_ATTRIBUTE_NOT_FOUND;
1141 errorData.attHandleInError = data->attReadByTypeRequest.readHandleRangeUuid.handleRange.startHandle;
1142 ATT_ErrorResponse(connectHandle, &errorData);
1143 result = true;
1144 }
1145
1146 return result;
1147 }
1148 /**
1149 * @brief Check if the handle is an end handle.
1150 *
1151 * @param attHandle Indicates attribute start handle.
1152 * @return Returns true if the attHandle is ending handle.
1153 * @since 6.0
1154 */
FindServiceEndingHandle(uint16_t attHandle)1155 bool GattServerProfile::impl::FindServiceEndingHandle(uint16_t attHandle)
1156 {
1157 bool result = false;
1158
1159 if (db_.GetServices().begin() == db_.GetServices().end() ||
1160 attHandle > db_.GetServices().rbegin()->second.endHandle_ || attHandle == MAX_ATTRIBUTE_HANDLE) {
1161 result = true;
1162 }
1163
1164 return result;
1165 }
1166 /**
1167 * @brief Confirm through the handle that the handle belongs to a service handle.
1168 *
1169 * @param attHandle Indicates attribute start handle.
1170 * @param uuid Indicates 0x2800–UUID for «PrimaryService» OR 0x2801 for «Secondary Service».
1171 * @return Returns true if the handle belongs to a service handle.
1172 * @since 6.0
1173 */
FindServiceByHandle(uint16_t attHandle,Uuid uuid)1174 bool GattServerProfile::impl::FindServiceByHandle(uint16_t attHandle, Uuid uuid)
1175 {
1176 bool ret = false;
1177 if (db_.GetService(attHandle) != nullptr && uuid.operator==(Uuid::ConvertFrom16Bits(UUID_PRIMARY_SERVICE))) {
1178 ret = true;
1179 }
1180 return ret;
1181 }
1182 /**
1183 * @brief Confirm through the handle that the handle belongs to a characteristic declaration handle.
1184 *
1185 * @param attHandle Indicates attribute start handle.
1186 * @param uuid Indicates 0x2803–UUID for «Characteristic».
1187 * @return Returns true if the handle belongs to a characteristic declaration handle.
1188 * @since 6.0
1189 */
FindCharacteristicDeclarationByHandle(uint16_t attHandle,Uuid uuid)1190 bool GattServerProfile::impl::FindCharacteristicDeclarationByHandle(uint16_t attHandle, Uuid uuid)
1191 {
1192 bool ret = false;
1193 if (db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE) != nullptr &&
1194 uuid.operator==(Uuid::ConvertFrom16Bits(UUID_CHARACTERISTIC))) {
1195 ret = true;
1196 }
1197 return ret;
1198 }
1199 /**
1200 * @brief Confirm through the handle that the handle belongs to a characteristic value handle.
1201 *
1202 * @param attHandle Indicates attribute start handle.
1203 * @param uuid Indicates 16-bit Bluetooth UUID or 128-bit UUID for characteristic value.
1204 * @return Returns true if the uuid belongs to a characteristic value.
1205 * @since 6.0
1206 */
FindCharacteristicValueByUuid(uint16_t attHandle,Uuid uuid)1207 bool GattServerProfile::impl::FindCharacteristicValueByUuid(uint16_t attHandle, Uuid uuid)
1208 {
1209 bool ret = false;
1210 if (db_.GetDescriptor(attHandle) == nullptr && db_.GetCharacteristic(attHandle) != nullptr &&
1211 db_.GetCharacteristic(attHandle)->uuid_.operator==(uuid)) {
1212 ret = true;
1213 }
1214 return ret;
1215 }
1216 /**
1217 * @brief Confirm through the handle that the handle belongs to a service handle.
1218 *
1219 * @param attHandle Indicates attribute start handle.
1220 * @param uuid Indicates 16-bit Bluetooth UUID or 128-bit UUID for characteristic descriptor
1221 * @return Returns true if the uuid belongs to a characteristic descriptor.
1222 * @since 6.0
1223 */
FindCharacteristicDescriptorByUuid(uint16_t attHandle,Uuid uuid)1224 bool GattServerProfile::impl::FindCharacteristicDescriptorByUuid(uint16_t attHandle, Uuid uuid)
1225 {
1226 bool ret = false;
1227 if (db_.GetDescriptor(attHandle) != nullptr && db_.GetDescriptor(attHandle)->uuid_.operator==(uuid)) {
1228 ret = true;
1229 }
1230 return ret;
1231 }
1232 /**
1233 * @brief Assemble service data package.
1234 *
1235 * @param attHandle Indicates attribute handle.
1236 * @return Returns attribute value buffer.
1237 * @since 6.0
1238 */
AssembleServicePackage(uint16_t attHandle)1239 Buffer *GattServerProfile::impl::AssembleServicePackage(uint16_t attHandle)
1240 {
1241 if (db_.GetService(attHandle) == nullptr) {
1242 HILOGE("null pointer");
1243 return nullptr;
1244 }
1245 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1246 Buffer *value = BufferMalloc(db_.GetService(attHandle)->uuid_.GetUuidType());
1247 if (db_.GetService(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1248 uint16_t uuid16Bit = db_.GetService(attHandle)->uuid_.ConvertTo16Bits();
1249 if (memcpy_s(BufferPtr(value), BufferGetSize(value), &uuid16Bit, UUID_16BIT_LEN) != EOK) {
1250 LOG_ERROR("%{public}s: memcpy_s uuid16Bit fail", __FUNCTION__);
1251 BufferFree(value);
1252 value = nullptr;
1253 }
1254 } else if (db_.GetService(attHandle)->uuid_.GetUuidType() == UUID_128BIT_LEN) {
1255 db_.GetService(attHandle)->uuid_.ConvertToBytesLE(uuid128Bit, UUID_128BIT_LEN);
1256 if (memcpy_s(BufferPtr(value), BufferGetSize(value), uuid128Bit, UUID_128BIT_LEN) != EOK) {
1257 LOG_ERROR("%{public}s: memcpy_s uuid128Bit fail", __FUNCTION__);
1258 BufferFree(value);
1259 value = nullptr;
1260 }
1261 } else {
1262 BufferFree(value);
1263 value = nullptr;
1264 }
1265 return value;
1266 }
1267 /**
1268 * @brief Assemble service data package.
1269 *
1270 * @param attHandle Indicates attribute handle.
1271 * @return Returns attribute value buffer.
1272 * @since 6.0
1273 */
AssembleCharacteristicPackage(uint16_t attHandle)1274 Buffer *GattServerProfile::impl::AssembleCharacteristicPackage(uint16_t attHandle)
1275 {
1276 Buffer *value = nullptr;
1277 uint8_t offset = 0;
1278
1279 if (db_.GetCharacteristic(attHandle) != nullptr) {
1280 uint8_t properties = db_.GetCharacteristic(attHandle)->properties_;
1281 uint16_t valueHandle = db_.GetCharacteristic(attHandle)->valueHandle_;
1282 value =
1283 BufferMalloc(sizeof(uint8_t) + sizeof(uint16_t) + db_.GetCharacteristic(attHandle)->uuid_.GetUuidType());
1284 AssembleDataPackage((uint8_t *)BufferPtr(value), &offset, properties);
1285 AssembleDataPackage(
1286 (uint8_t *)BufferPtr(value), BufferGetSize(value), &offset, (uint8_t *)&valueHandle, sizeof(uint16_t));
1287 if (db_.GetCharacteristic(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1288 uint16_t uuid16Bit = db_.GetCharacteristic(attHandle)->uuid_.ConvertTo16Bits();
1289 AssembleDataPackage(
1290 (uint8_t *)BufferPtr(value), BufferGetSize(value), &offset, (uint8_t *)&uuid16Bit, UUID_16BIT_LEN);
1291 } else if (db_.GetCharacteristic(attHandle)->uuid_.GetUuidType() == UUID_128BIT_LEN) {
1292 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1293 db_.GetCharacteristic(attHandle)->uuid_.ConvertToBytesLE(uuid128Bit, UUID_128BIT_LEN);
1294 AssembleDataPackage(
1295 (uint8_t *)BufferPtr(value), BufferGetSize(value), &offset, uuid128Bit, UUID_128BIT_LEN);
1296 } else {
1297 BufferFree(value);
1298 value = nullptr;
1299 }
1300 }
1301
1302 return value;
1303 }
1304 /**
1305 * @brief Assemble client characteristic configuration descriptor data package.
1306 *
1307 * @param attHandle Indicates attribute handle.
1308 * @return Returns attribute value buffer.
1309 * @since 6.0
1310 */
AssembleDescriptorPackage(uint16_t connectHandle,uint16_t attHandle)1311 Buffer *GattServerProfile::impl::AssembleDescriptorPackage(uint16_t connectHandle, uint16_t attHandle)
1312 {
1313 Uuid uuid = Uuid::ConvertFrom16Bits(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION);
1314 if (db_.GetDescriptor(attHandle) != nullptr &&
1315 db_.GetDescriptor(attHandle)->uuid_.operator==(uuid)) {
1316 uint8_t data[2] = {0};
1317 uint16_t val = GetCccdValue(connectHandle, attHandle);
1318 (void)memcpy_s(data, sizeof(uint16_t), &val, sizeof(uint16_t));
1319 return GattServiceBase::BuildBuffer(data, sizeof(uint16_t));
1320 }
1321 return nullptr;
1322 }
1323 /**
1324 * @brief Assemble AttReadByGroupTypeRsp Package.
1325 *
1326 * @param list Indicates AttReadGroupAttributeData list.
1327 * @param service Indicates Services found.
1328 * @param num Indicates list offset.
1329 * @since 6.0
1330 */
AssembleAttReadByGroupTypeRspPackage(AttReadGoupAttributeData * list,const GattDatabase::Service & service,uint8_t num)1331 void GattServerProfile::impl::AssembleAttReadByGroupTypeRspPackage(
1332 AttReadGoupAttributeData *list, const GattDatabase::Service &service, uint8_t num)
1333 {
1334 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1335
1336 list[num].attHandle = service.handle_;
1337 list[num].groupEndHandle = service.endHandle_;
1338
1339 if (service.uuid_.GetUuidType() == UUID_16BIT_LEN) {
1340 list[num].attributeValue = (uint8_t *)malloc(UUID_16BIT_LEN);
1341 uint16_t uuid16Bit = service.uuid_.ConvertTo16Bits();
1342 (void)memcpy_s(list[num].attributeValue, UUID_16BIT_LEN, &uuid16Bit, UUID_16BIT_LEN);
1343 } else {
1344 list[num].attributeValue = (uint8_t *)malloc(UUID_128BIT_LEN);
1345 service.uuid_.ConvertToBytesLE(uuid128Bit, UUID_128BIT_LEN);
1346 (void)memcpy_s(list[num].attributeValue, UUID_128BIT_LEN, &uuid128Bit, UUID_128BIT_LEN);
1347 }
1348 }
1349 /**
1350 * @brief Assemble AttReadByTypeRspSvc Package.
1351 *
1352 * @param list Indicates AttReadByTypeRspDataList list.
1353 * @param attHandle Indicates attribute handle.
1354 * @param num Indicates list offset.
1355 * @since 6.0
1356 */
AssembleAttReadByTypeRspSvcPackage(AttReadByTypeRspDataList * list,uint16_t attHandle,uint8_t num,uint8_t * offset)1357 void GattServerProfile::impl::AssembleAttReadByTypeRspSvcPackage(
1358 AttReadByTypeRspDataList *list, uint16_t attHandle, uint8_t num, uint8_t *offset)
1359 {
1360 if (db_.GetService(attHandle) == nullptr) {
1361 HILOGE("null pointer");
1362 return;
1363 }
1364 list[num].attHandle.attHandle = db_.GetService(attHandle)->handle_;
1365 if (db_.GetService(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1366 uint16_t uuid16Bit = db_.GetService(attHandle)->uuid_.ConvertTo16Bits();
1367 list[num].attributeValue = (uint8_t *)malloc(UUID_16BIT_LEN);
1368 AssembleDataPackage(list[num].attributeValue, UUID_16BIT_LEN, offset, (uint8_t *)&uuid16Bit, UUID_16BIT_LEN);
1369 } else {
1370 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1371 db_.GetService(attHandle)->uuid_.ConvertToBytesLE(uuid128Bit, UUID_128BIT_LEN);
1372 list[num].attributeValue = (uint8_t *)malloc(UUID_128BIT_LEN);
1373 AssembleDataPackage(list[num].attributeValue, UUID_128BIT_LEN, offset, uuid128Bit, UUID_128BIT_LEN);
1374 }
1375 }
1376
1377 /**
1378 * @brief Assemble AttReadByTypeRspCharacteris Package.
1379 *
1380 * @param list Indicates AttReadByTypeRspDataList list.
1381 * @param attHandle Indicates attribute handle.
1382 * @param num Indicates list offset.
1383 * @since 6.0
1384 */
AssembleAttReadByTypeRspCharacteristicPackage(AttReadByTypeRspDataList * list,uint16_t attHandle,uint8_t num,uint8_t * offset)1385 void GattServerProfile::impl::AssembleAttReadByTypeRspCharacteristicPackage(
1386 AttReadByTypeRspDataList *list, uint16_t attHandle, uint8_t num, uint8_t *offset)
1387 {
1388 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1389 uint8_t len = sizeof(uint8_t) + sizeof(uint16_t) + UUID_128BIT_LEN;
1390
1391 if (db_.GetCharacteristic(attHandle) == nullptr) {
1392 return;
1393 }
1394 list[num].attHandle.attHandle = db_.GetCharacteristic(attHandle)->handle_;
1395 list[num].attributeValue = (uint8_t *)malloc(len);
1396 AssembleDataPackage(list[num].attributeValue, offset, db_.GetCharacteristic(attHandle)->properties_);
1397 AssembleDataPackage(list[num].attributeValue,
1398 len,
1399 offset,
1400 (uint8_t *)&db_.GetCharacteristic(attHandle)->valueHandle_,
1401 sizeof(uint16_t));
1402 if (db_.GetCharacteristic(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1403 uint16_t uuid16Bit = db_.GetCharacteristic(attHandle)->uuid_.ConvertTo16Bits();
1404 AssembleDataPackage(list[num].attributeValue, len, offset, (uint8_t *)&uuid16Bit, UUID_16BIT_LEN);
1405 } else {
1406 db_.GetCharacteristic(attHandle)->uuid_.ConvertToBytesLE(uuid128Bit, UUID_128BIT_LEN);
1407 AssembleDataPackage(list[num].attributeValue, len, offset, uuid128Bit, UUID_128BIT_LEN);
1408 }
1409 }
1410 /**
1411 * @brief Assemble AttReadByTypeRspDesc Package.
1412 *
1413 * @param list Indicates AttReadByTypeRspDataList list.
1414 * @param connectHandle Indicates identify a connection.
1415 * @param attHandle Indicates attribute handle.
1416 * @param num Indicates list offset.
1417 * @return Returns true if descriptor is not CCCD.
1418 * @since 6.0
1419 */
AssembleAttReadByTypeRspDescPackage(AttReadByTypeRspDataList * list,uint16_t connectHandle,uint16_t attHandle,uint8_t num,uint8_t * offset)1420 bool GattServerProfile::impl::AssembleAttReadByTypeRspDescPackage(
1421 AttReadByTypeRspDataList *list, uint16_t connectHandle, uint16_t attHandle, uint8_t num, uint8_t *offset)
1422 {
1423 bool ret = true;
1424 Uuid uuid = Uuid::ConvertFrom16Bits(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION);
1425 if (db_.GetDescriptor(attHandle) != nullptr) {
1426 list[num].attHandle.attHandle = db_.GetDescriptor(attHandle)->handle_;
1427 if (db_.GetDescriptor(attHandle)->uuid_.operator==(uuid)) {
1428 uint16_t val = GetCccdValue(connectHandle, attHandle);
1429 list[num].attributeValue = (uint8_t *)malloc(sizeof(val));
1430 AssembleDataPackage(list[num].attributeValue, sizeof(val), offset, (uint8_t *)&val, sizeof(val));
1431 ret = false;
1432 }
1433 }
1434
1435 return ret;
1436 }
1437 /**
1438 * @brief Assemble AttFindInforRspSvc Package.
1439 *
1440 * @param pairs Indicates AttHandleUuid pairs.
1441 * @param attHandle Indicates attribute handle.
1442 * @param num Indicates list offset.
1443 * @since 6.0
1444 */
AssembleAttFindInforRspSvcPackage(AttHandleUuid * pairs,uint16_t attHandle,uint8_t num,uint16_t * len)1445 void GattServerProfile::impl::AssembleAttFindInforRspSvcPackage(
1446 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len)
1447 {
1448 if (db_.GetService(attHandle) == nullptr) {
1449 HILOGE("null pointer");
1450 return;
1451 }
1452 pairs[num].attHandle = db_.GetService(attHandle)->handle_;
1453 if (db_.GetService(attHandle)->isPrimary_) {
1454 pairs[num].uuid.uuid16 = UUID_PRIMARY_SERVICE;
1455 } else {
1456 pairs[num].uuid.uuid16 = UUID_SECONDARY_SERVICE;
1457 }
1458 pairs[num].uuid.type = UUID_16BIT_FORMAT;
1459 *len = UUID_16BIT_LEN;
1460 }
1461 /**
1462 * @brief Assemble AttFindInforRspCharacteris Package.
1463 *
1464 * @param pairs Indicates AttHandleUuid pairs.
1465 * @param attHandle Indicates attribute handle.
1466 * @param num Indicates list offset.
1467 * @since 6.0
1468 */
AssembleAttFindInforRspCharacteristicPackage(AttHandleUuid * pairs,uint16_t attHandle,uint8_t num,uint16_t * len)1469 void GattServerProfile::impl::AssembleAttFindInforRspCharacteristicPackage(
1470 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len)
1471 {
1472 if (db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE) != nullptr) {
1473 pairs[num].attHandle = db_.GetCharacteristic(attHandle + MIN_ATTRIBUTE_HANDLE)->handle_;
1474 pairs[num].uuid.uuid16 = UUID_CHARACTERISTIC;
1475 pairs[num].uuid.type = UUID_16BIT_FORMAT;
1476 *len = UUID_16BIT_LEN;
1477 }
1478 }
1479 /**
1480 * @brief Assemble AttFindInforRspCharacterisVal Package.
1481 *
1482 * @param pairs Indicates AttHandleUuid pairs.
1483 * @param attHandle Indicates attribute handle.
1484 * @param num Indicates list offset.
1485 * @since 6.0
1486 */
AssembleAttFindInforRspCharacteristicValPackage(AttHandleUuid * pairs,uint16_t attHandle,uint8_t num,uint16_t * len)1487 void GattServerProfile::impl::AssembleAttFindInforRspCharacteristicValPackage(
1488 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len)
1489 {
1490 if (db_.GetCharacteristic(attHandle) == nullptr) {
1491 return;
1492 }
1493 pairs[num].attHandle = db_.GetCharacteristic(attHandle)->valueHandle_;
1494 if (db_.GetCharacteristic(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1495 pairs[num].uuid.uuid16 = db_.GetCharacteristic(attHandle)->uuid_.ConvertTo16Bits();
1496 pairs[num].uuid.type = UUID_16BIT_FORMAT;
1497 *len = UUID_16BIT_LEN;
1498 } else {
1499 db_.GetCharacteristic(attHandle)->uuid_.ConvertToBytesLE(pairs[num].uuid.uuid128, UUID_128BIT_LEN);
1500 pairs[num].uuid.type = UUID_128BIT_FORMAT;
1501 *len = UUID_128BIT_LEN;
1502 }
1503 }
1504 /**
1505 * @brief Assemble AttFindInforRspDesc Package.
1506 *
1507 * @param pairs Indicates AttHandleUuid pairs.
1508 * @param attHandle Indicates attribute handle.
1509 * @param num Indicates list offset.
1510 * @since 6.0
1511 */
AssembleAttFindInforRspDescPackage(AttHandleUuid * pairs,uint16_t attHandle,uint8_t num,uint16_t * len)1512 void GattServerProfile::impl::AssembleAttFindInforRspDescPackage(
1513 AttHandleUuid *pairs, uint16_t attHandle, uint8_t num, uint16_t *len)
1514 {
1515 if (db_.GetDescriptor(attHandle) != nullptr) {
1516 pairs[num].attHandle = db_.GetDescriptor(attHandle)->handle_;
1517 if (db_.GetDescriptor(attHandle)->uuid_.GetUuidType() == UUID_16BIT_LEN) {
1518 pairs[num].uuid.uuid16 = db_.GetDescriptor(attHandle)->uuid_.ConvertTo16Bits();
1519 pairs[num].uuid.type = UUID_16BIT_FORMAT;
1520 *len = UUID_16BIT_LEN;
1521 } else {
1522 db_.GetDescriptor(attHandle)->uuid_.ConvertToBytesLE(pairs[num].uuid.uuid128, UUID_128BIT_LEN);
1523 pairs[num].uuid.type = UUID_128BIT_FORMAT;
1524 *len = UUID_128BIT_LEN;
1525 }
1526 }
1527 }
1528 /**
1529 * @brief Assemble att data package.
1530 *
1531 * @param dest Indicates destination address.
1532 * @param destMax -The maximum length of destination buffer.
1533 * @param offset Indicates address offset.
1534 * @param src Indicates source address.
1535 * @param size Indicates data size.
1536 * @since 6.0
1537 */
AssembleDataPackage(uint8_t * dest,uint8_t destMax,uint8_t * offset,uint8_t * src,uint8_t size)1538 void GattServerProfile::impl::AssembleDataPackage(
1539 uint8_t *dest, uint8_t destMax, uint8_t *offset, uint8_t *src, uint8_t size)
1540 {
1541 if (memcpy_s((dest + *offset), destMax, src, size) != EOK) {
1542 return;
1543 }
1544 *offset = *offset + size;
1545 }
1546 /**
1547 * @brief Assemble att data package.
1548 *
1549 * @param dest Indicates destination address.
1550 * @param offset Indicates address offset.
1551 * @param src Indicates source address.
1552 * @since 6.0
1553 */
AssembleDataPackage(uint8_t * dest,uint8_t * offset,uint8_t src)1554 void GattServerProfile::impl::AssembleDataPackage(uint8_t *dest, uint8_t *offset, uint8_t src)
1555 {
1556 *(dest + *offset) = src;
1557 *offset = *offset + 1;
1558 }
1559
FreeDataPackage(AttReadByTypeRspDataList * list,uint8_t num)1560 void GattServerProfile::impl::FreeDataPackage(AttReadByTypeRspDataList *list, uint8_t num)
1561 {
1562 for (int i = 0; i < num; i++) {
1563 free(list[i].attributeValue);
1564 }
1565 }
1566 /**
1567 * @brief Get properties of Characteristic and value.
1568 *
1569 * @param attHandle Indicates attribute handle.
1570 * @return Returns true if characteristic is readable
1571 * @since 6.0
1572 */
CharacteristicPropertyIsReadable(uint16_t attHandle)1573 bool GattServerProfile::impl::CharacteristicPropertyIsReadable(uint16_t attHandle)
1574 {
1575 if ((db_.GetCharacteristic(attHandle) != nullptr) &&
1576 (db_.GetCharacteristic(attHandle)->properties_ & CHARACTERISTIC_PROPERTIE_READ) &&
1577 (db_.GetValueByHandle(attHandle).value().get().permissions_ &
1578 static_cast<int>(GattPermissionService::READABLE))) {
1579 return true;
1580 } else {
1581 return false;
1582 }
1583 }
1584 /**
1585 * @brief Get properties of descriptor and value.
1586 *
1587 * @param attHandle Indicates attribute handle.
1588 * @return Returns true if descriptor is readable
1589 * @since 6.0
1590 */
DescriptorPropertyIsReadable(uint16_t attHandle)1591 bool GattServerProfile::impl::DescriptorPropertyIsReadable(uint16_t attHandle)
1592 {
1593 if ((db_.GetDescriptor(attHandle) != nullptr) &&
1594 (db_.GetDescriptor(attHandle)->permissions_ & static_cast<int>(GattPermissionService::READABLE))) {
1595 return true;
1596 } else {
1597 return false;
1598 }
1599 }
1600 /**
1601 * @brief Get properties of Characteristic and value.
1602 *
1603 * @param attHandle Indicates attribute handle.
1604 * @return Returns true if characteristic is writable
1605 * @since 6.0
1606 */
CharacteristicPropertyIsWritable(uint16_t attHandle)1607 bool GattServerProfile::impl::CharacteristicPropertyIsWritable(uint16_t attHandle)
1608 {
1609 if ((db_.GetCharacteristic(attHandle) != nullptr) &&
1610 (db_.GetCharacteristic(attHandle)->properties_ & CHARACTERISTIC_PROPERTIE_WRITE) &&
1611 (db_.GetValueByHandle(attHandle).value().get().permissions_ &
1612 static_cast<int>(GattPermissionService::WRITEABLE))) {
1613 return true;
1614 } else {
1615 return false;
1616 }
1617 }
1618 /**
1619 * @brief Get properties of descriptor and value.
1620 *
1621 * @param attHandle Indicates attribute handle.
1622 * @return Returns true if descriptor is writable
1623 * @since 6.0
1624 */
DescriptorPropertyIsWritable(uint16_t attHandle)1625 bool GattServerProfile::impl::DescriptorPropertyIsWritable(uint16_t attHandle)
1626 {
1627 if ((db_.GetDescriptor(attHandle) != nullptr) &&
1628 (db_.GetDescriptor(attHandle)->permissions_ & static_cast<int>(GattPermissionService::WRITEABLE))) {
1629 return true;
1630 } else {
1631 return false;
1632 }
1633 }
1634 /**
1635 * @brief This sub-procedure is used to respond that write descriptor values.
1636 *
1637 * @param connectHandle Indicates identify a connection.
1638 * @param attHandle Indicates descriptor handle.
1639 * @param value Indicates value of the schedule settings.
1640 * @since 6.0
1641 */
WriteDescriptorProcess(uint16_t connectHandle,uint16_t attHandle,Buffer * value)1642 AttError GattServerProfile::impl::WriteDescriptorProcess(uint16_t connectHandle, uint16_t attHandle, Buffer *value)
1643 {
1644 uint16_t cccVal = 0;
1645 AttError errorData = {WRITE_REQUEST, attHandle, 0};
1646 Uuid uuid = Uuid::ConvertFrom16Bits(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION);
1647
1648 if (db_.GetDescriptor(attHandle) != nullptr &&
1649 db_.GetDescriptor(attHandle)->uuid_.operator==(uuid)) {
1650 if (BufferGetSize(value) > sizeof(uint16_t)) {
1651 errorData.errorCode = ATT_ATTRIBUTE_NOT_LONG;
1652 } else {
1653 if (memcpy_s(&cccVal, sizeof(uint16_t), BufferPtr(value), BufferGetSize(value)) != EOK) {
1654 LOG_ERROR("%{public}s: memcpy_s fail", __FUNCTION__);
1655 errorData.errorCode = ATT_UNLIKELY_ERROR;
1656 return errorData;
1657 }
1658 AddCccdValue(connectHandle, attHandle, cccVal);
1659 ATT_WriteResponse(connectHandle);
1660 }
1661 } else {
1662 auto descPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(value), BufferGetSize(value));
1663 pServerCallBack_->OnDescriptorWriteEvent(connectHandle, attHandle, descPtr, BufferGetSize(value));
1664 }
1665
1666 return errorData;
1667 }
1668 /**
1669 * @brief Get att mtu size.
1670 *
1671 * @param connectHandle Indicates identify a connection.
1672 * @return Returns mtu size.
1673 * @since 6.0
1674 */
GetMtuInformation(uint16_t connectHandle)1675 uint16_t GattServerProfile::impl::GetMtuInformation(uint16_t connectHandle)
1676 {
1677 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1678 uint16_t mtu = GATT_DEFAULT_MTU;
1679 auto it = mtuInfo_.find(connectHandle);
1680 if (it != mtuInfo_.end()) {
1681 mtu = it->second;
1682 }
1683
1684 return mtu;
1685 }
1686 /**
1687 * @brief Save att mtu size.
1688 *
1689 * @param connectHandle Indicates identify a connection.
1690 * @param mtu Indicates mtu size.
1691 * @since 6.0
1692 */
SetMtuInformation(uint16_t connectHandle,uint16_t mtu)1693 void GattServerProfile::impl::SetMtuInformation(uint16_t connectHandle, uint16_t mtu)
1694 {
1695 LOG_INFO("%{public}s: connectHandle is %hu, mtu is %hu.", __FUNCTION__, connectHandle, mtu);
1696 auto it = mtuInfo_.find(connectHandle);
1697 if (it == mtuInfo_.end()) {
1698 mtuInfo_.emplace(connectHandle, mtu);
1699 } else {
1700 it->second = mtu;
1701 }
1702 }
1703 /**
1704 * @brief Delete list of request and response when gatt is disconnected.
1705 *
1706 * @param connectHandle Indicates identify a connection.
1707 * @since 6.0
1708 */
DeleteList(uint16_t connectHandle)1709 void GattServerProfile::impl::DeleteList(uint16_t connectHandle)
1710 {
1711 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1712 auto reqList = requestList_.begin();
1713 while (reqList != requestList_.end()) {
1714 if (connectHandle == reqList->first) {
1715 requestList_.erase(reqList++);
1716 } else {
1717 reqList++;
1718 }
1719 }
1720
1721 auto respList = responseList_.begin();
1722 while (respList != responseList_.end()) {
1723 if (connectHandle == respList->first) {
1724 responseList_.erase(respList++);
1725 } else {
1726 respList++;
1727 }
1728 }
1729 }
1730 /**
1731 * @brief Add new device to list.
1732 *
1733 * @param connectHandle Indicates identify a connection.
1734 * @param device Indicates new device.
1735 * @since 6.0
1736 */
AddDeviceList(uint16_t connectHandle,GattDevice device)1737 void GattServerProfile::impl::AddDeviceList(uint16_t connectHandle, GattDevice device)
1738 {
1739 LOG_INFO("%{public}s: entry", __FUNCTION__);
1740 for (auto iter = devList_.begin(); iter != devList_.end(); iter++) {
1741 if (iter->second.device_.addr_.operator==(device.addr_) &&
1742 iter->second.device_.transport_ == device.transport_) {
1743 iter->first = connectHandle;
1744 LOG_INFO("%{public}s: Device already exists", __FUNCTION__);
1745 return;
1746 }
1747 }
1748 devList_.emplace_back(connectHandle, DeviceInfo(device));
1749 }
1750 /**
1751 * @brief Set cccd value to list.
1752 *
1753 * @param connectHandle Indicates identify a connection.
1754 * @param attHandle Indicates cccd handle.
1755 * @param value Indicates cccd value.
1756 * @since 6.0
1757 */
AddCccdValue(uint16_t connectHandle,uint16_t attHandle,uint16_t value)1758 void GattServerProfile::impl::AddCccdValue(uint16_t connectHandle, uint16_t attHandle, uint16_t value)
1759 {
1760 LOG_INFO("%{public}s: connectHandle is %hu, attHandle is %hu, value is %hu.",
1761 __FUNCTION__, connectHandle, attHandle, value);
1762 auto iter = devList_.begin();
1763 for (; iter != devList_.end(); iter++) {
1764 if (connectHandle == iter->first) {
1765 break;
1766 }
1767 }
1768 if (iter == devList_.end()) {
1769 LOG_INFO("%{public}s: Device does not exist", __FUNCTION__);
1770 return;
1771 }
1772 for (uint8_t num = 0; num < GATT_CCCD_NUM_MAX; num++) {
1773 if (iter->second.cccd_[num].valHandle_ == attHandle) {
1774 iter->second.cccd_[num].value_ = value;
1775 LOG_INFO("cccd valid handle: %hu, value: %hu", attHandle, value);
1776 return;
1777 } else if (iter->second.cccd_[num].valHandle_ == INVALID_ATTRIBUTE_HANDLE) {
1778 iter->second.cccd_[num].valHandle_ = attHandle;
1779 iter->second.cccd_[num].value_ = value;
1780 LOG_INFO("cccd invalid handle: %hu, value: %hu", attHandle, value);
1781 return;
1782 } else {
1783 LOG_ERROR("%{public}s: CCCD does not exist", __FUNCTION__);
1784 }
1785 }
1786 }
1787 /**
1788 * @brief Get cccd value from list.
1789 *
1790 * @param connectHandle Indicates identify a connection.
1791 * @since 6.0
1792 */
DeleteCccdValue(uint16_t connectHandle)1793 void GattServerProfile::impl::DeleteCccdValue(uint16_t connectHandle)
1794 {
1795 for (auto iter = devList_.begin(); iter != devList_.end(); iter++) {
1796 if (connectHandle == iter->first) {
1797 for (uint8_t num = 0; num < GATT_CCCD_NUM_MAX; num++) {
1798 iter->second.cccd_[num].valHandle_ = INVALID_ATTRIBUTE_HANDLE;
1799 iter->second.cccd_[num].value_ = 0x00;
1800 }
1801 }
1802 }
1803 }
1804 /**
1805 * @brief Get cccd value from list.
1806 *
1807 * @param connectHandle Indicates identify a connection.
1808 * @param attHandle Indicates cccd handle.
1809 * @since 6.0
1810 */
GetCccdValue(uint16_t connectHandle,uint16_t attHandle)1811 uint16_t GattServerProfile::impl::GetCccdValue(uint16_t connectHandle, uint16_t attHandle)
1812 {
1813 uint16_t ret = 0;
1814
1815 for (auto iter = devList_.begin(); iter != devList_.end(); iter++) {
1816 if (connectHandle == iter->first) {
1817 for (uint8_t num = 0; num < GATT_CCCD_NUM_MAX; num++) {
1818 if (iter->second.cccd_[num].valHandle_ == attHandle) {
1819 ret = iter->second.cccd_[num].value_;
1820 }
1821 }
1822 }
1823 }
1824 LOG_INFO("%{public}s: connectHandle is %hu, attHandle is %hu, CCCvalue is %hu.",
1825 __FUNCTION__, connectHandle, attHandle, ret);
1826 return ret;
1827 }
1828 /**
1829 * @brief Indicates connect or disconnect.
1830 *
1831 * @since 6.0
1832 */
1833 class GattServerProfile::impl::GattConnectionObserverImplement : public GattConnectionObserver {
1834 public:
OnConnect(const GattDevice & device,uint16_t connectionHandle,int ret)1835 void OnConnect(const GattDevice &device, uint16_t connectionHandle, int ret) override
1836 {
1837 LOG_INFO("%{public}s: gatt_server connect ret is %{public}d", __FUNCTION__, ret);
1838 if (ret == GATT_SUCCESS) {
1839 this->serverProfile_.pimpl->dispatcher_->PostTask(
1840 std::bind(&impl::AddDeviceList, serverProfile_.pimpl.get(), connectionHandle, device));
1841 }
1842 }
1843
OnDisconnect(const GattDevice & device,uint16_t connectionHandle,int ret)1844 void OnDisconnect(const GattDevice &device, uint16_t connectionHandle, int ret) override
1845 {
1846 LOG_INFO("%{public}s: gatt_server connect ret is %{public}d", __FUNCTION__, ret);
1847 if (device.isEncryption_ == false) {
1848 this->serverProfile_.pimpl->dispatcher_->PostTask(
1849 std::bind(&impl::DeleteCccdValue, serverProfile_.pimpl.get(), connectionHandle));
1850 }
1851 this->serverProfile_.pimpl->dispatcher_->PostTask(
1852 std::bind(&impl::DeleteList, serverProfile_.pimpl.get(), connectionHandle));
1853 this->serverProfile_.pimpl->dispatcher_->PostTask(
1854 std::bind(&impl::SetMtuInformation, serverProfile_.pimpl.get(), connectionHandle, GATT_DEFAULT_MTU));
1855 }
1856
GattConnectionObserverImplement(GattServerProfile & serverProfile)1857 GattConnectionObserverImplement(GattServerProfile &serverProfile) : serverProfile_(serverProfile)
1858 {}
~GattConnectionObserverImplement()1859 ~GattConnectionObserverImplement()
1860 {}
1861
1862 private:
1863 GattServerProfile &serverProfile_;
1864 };
1865 /**
1866 * @brief Register callback to ConnectManager.
1867 *
1868 * @since 6.0
1869 */
RegisterCallbackToConnectManager()1870 void GattServerProfile::impl::RegisterCallbackToConnectManager()
1871 {
1872 LOG_INFO("%{public}s", __FUNCTION__);
1873 connectionObserverId_ = GattConnectionManager::GetInstance().RegisterObserver(*connectionCallBack_);
1874 if (connectionObserverId_ < 0) {
1875 LOG_ERROR("%{public}s: GATT_profile register callback to ConnectManager failed", __FUNCTION__);
1876 }
1877 }
1878 /**
1879 * @brief Unregister callback to ConnectManager.
1880 *
1881 * @since 6.0
1882 */
DeregisterCallbackToConnectManager()1883 void GattServerProfile::impl::DeregisterCallbackToConnectManager()
1884 {
1885 LOG_INFO("%{public}s", __FUNCTION__);
1886 GattConnectionManager::GetInstance().DeregisterObserver(connectionObserverId_);
1887 }
1888
FindIteratorByResponesInfor(uint16_t handle,ResponesType respType)1889 std::list<std::pair<uint16_t, GattResponesInfor>>::iterator GattServerProfile::impl::FindIteratorByResponesInfor(
1890 uint16_t handle, ResponesType respType)
1891 {
1892 std::list<std::pair<uint16_t, GattResponesInfor>>::iterator iter;
1893 for (iter = responseList_.begin(); iter != responseList_.end(); iter++) {
1894 if (handle == iter->first && respType == iter->second.respType_) {
1895 break;
1896 }
1897 }
1898 return iter;
1899 }
1900
1901 /**
1902 * @brief This sub-procedure is used to add services.
1903 *
1904 * @param service Indicates service list.
1905 * @since 6.0
1906 */
AddService(Service & service) const1907 int GattServerProfile::AddService(Service &service) const
1908 {
1909 int result = pimpl->db_.AddService(service);
1910 return result;
1911 }
1912 /**
1913 * @brief Check service from data base.
1914 *
1915 * @param service Indicates service list
1916 * @since 6.0
1917 */
CheckLegalityOfServiceDefinition(Service & service) const1918 int GattServerProfile::CheckLegalityOfServiceDefinition(Service &service) const
1919 {
1920 return pimpl->db_.CheckLegalityOfServiceDefinition(service);
1921 }
1922 /**
1923 * @brief This sub-procedure is used to remove services.
1924 *
1925 * @param serviceHandle Indicates service handle.
1926 * @since 6.0
1927 */
RemoveService(uint16_t serviceHandle) const1928 int GattServerProfile::RemoveService(uint16_t serviceHandle) const
1929 {
1930 int result = pimpl->db_.DeleteService(serviceHandle);
1931 return result;
1932 }
1933
GetDBHash() const1934 const std::string GattServerProfile::GetDBHash() const
1935 {
1936 return std::string();
1937 }
1938 /**
1939 * @brief This sub-procedure is used to get service from data base.
1940 *
1941 * @param serviceHandle Indicates service handle.
1942 * @since 6.0
1943 */
GetService(uint16_t serviceHandle) const1944 const GattDatabase::Service *GattServerProfile::GetService(uint16_t serviceHandle) const
1945 {
1946 return pimpl->db_.GetService(serviceHandle);
1947 }
1948 /**
1949 * @brief This sub-procedure is used to get service from data base.
1950 *
1951 * @param serviceHandle Indicates service handle.
1952 * @since 6.0
1953 */
GetServices() const1954 const std::map<uint16_t, GattDatabase::Service> &GattServerProfile::GetServices() const
1955 {
1956 return pimpl->db_.GetServices();
1957 }
1958 /**
1959 * @brief This sub-procedure is used to get service characteristic from data base.
1960 *
1961 * @param valueHandle Indicates value handle.
1962 * @since 6.0
1963 */
GetCharacteristic(uint16_t valueHandle) const1964 GattDatabase::Characteristic *GattServerProfile::GetCharacteristic(uint16_t valueHandle) const
1965 {
1966 return pimpl->db_.GetCharacteristic(valueHandle);
1967 }
1968 /**
1969 * @brief This sub-procedure is used to get service descriptor from data base.
1970 *
1971 * @param valueHandle Indicates value handle.
1972 * @since 6.0
1973 */
GetDescriptor(uint16_t valueHandle) const1974 const GattDatabase::Descriptor *GattServerProfile::GetDescriptor(uint16_t valueHandle) const
1975 {
1976 return pimpl->db_.GetDescriptor(valueHandle);
1977 }
1978 /**
1979 * @brief This sub-procedure is used to set value .
1980 *
1981 * @since 6.0
1982 */
SetAttributeValue(uint16_t valueHandle,GattDatabase::AttributeValue & value) const1983 void GattServerProfile::SetAttributeValue(uint16_t valueHandle, GattDatabase::AttributeValue &value) const
1984 {
1985 pimpl->db_.SetValueByHandle(valueHandle, value);
1986 }
1987 /**
1988 * @brief This sub-procedure is used to respond that write values.
1989 *
1990 * @param connectHandle Indicates identify a connection.
1991 * @param data Indicates att data.
1992 * @param value Indicates value of the schedule settings.
1993 * @since 6.0
1994 */
GetAttributeValue(uint16_t handle) const1995 Buffer *GattServerProfile::GetAttributeValue(uint16_t handle) const
1996 {
1997 auto entity = pimpl->db_.GetValueByHandle(handle);
1998 if (entity.has_value()) {
1999 auto &value = entity.value().get();
2000 return GattServiceBase::BuildBuffer(value.value_.value_.get(), value.value_.length_);
2001 }
2002
2003 return nullptr;
2004 }
2005 /**
2006 * @brief This sub-procedure is used to get attribute.
2007 *
2008 * @since 6.0
2009 */
GetAttributeEntity(uint16_t handle) const2010 const std::optional<std::reference_wrapper<GattDatabase::AttributeEntity>> GattServerProfile::GetAttributeEntity(
2011 uint16_t handle) const
2012 {
2013 return pimpl->db_.GetValueByHandle(handle);
2014 }
2015 /**
2016 * @brief This sub-procedure is used to send notification.
2017 *
2018 * @param connectHandle Indicates identify a connection.
2019 * @param handle Indicates value handle.
2020 * @param value Indicates value of the schedule settings.
2021 * @since 6.0
2022 */
SendNotification(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const2023 void GattServerProfile::SendNotification(
2024 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
2025 {
2026 LOG_INFO("%{public}s: connectHandle is %hu, handle is is %hu.", __FUNCTION__, connectHandle, handle);
2027 if (pimpl->GetCccdValue(connectHandle, handle + MIN_ATTRIBUTE_HANDLE) == GATT_NOTIFICATION_VALUE) {
2028 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
2029 if (buffer != nullptr) {
2030 ATT_HandleValueNotification(connectHandle, handle, buffer);
2031 BufferFree(buffer);
2032 }
2033 } else {
2034 LOG_ERROR("%{public}s: GATT_NOTIFICATION_VALUE is invalid", __FUNCTION__);
2035 }
2036 }
2037 /**
2038 * @brief This sub-procedure is used to send indication.
2039 *
2040 * @param connectHandle Indicates identify a connection.
2041 * @param handle Indicates value handle.
2042 * @param value Indicates value of the schedule settings.
2043 * @param len Indicates size of value.
2044 * @since 6.0
2045 */
SendIndication(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const2046 void GattServerProfile::SendIndication(
2047 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
2048 {
2049 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
2050 if (pimpl->GetCccdValue(connectHandle, handle + MIN_ATTRIBUTE_HANDLE) == GATT_INDICATION_VALUE) {
2051 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
2052 if (buffer != nullptr) {
2053 pimpl->requestList_.emplace_back(connectHandle, GattResponesInfor(SEND_INDICATION, handle));
2054 ATT_HandleValueIndication(connectHandle, handle, buffer);
2055 BufferFree(buffer);
2056 }
2057 } else {
2058 LOG_ERROR("%{public}s: GATT_INDICATION_VALUE is invalid", __FUNCTION__);
2059 pimpl->pServerCallBack_->OnIndicationEvent(connectHandle, handle, GATT_FAILURE);
2060 }
2061 }
2062 /**
2063 * @brief This sub-procedure is used to send read characteristic value response.
2064 *
2065 * @param connectHandle Indicates identify a connection.
2066 * @param handle Indicates value handle.
2067 * @param value Indicates value of the schedule settings.
2068 * @param len Indicates size of value.
2069 * @param result Indicates send status.
2070 * @since 6.0
2071 */
SendReadCharacteristicValueResp(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len,int result) const2072 void GattServerProfile::SendReadCharacteristicValueResp(
2073 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len, int result) const
2074 {
2075 return SendReadDescriptorResp(connectHandle, handle, value, len, result);
2076 }
2077 /**
2078 * @brief This sub-procedure is used to send read using characteristic value response.
2079 *
2080 * @param connectHandle Indicates identify a connection.
2081 * @param handle Indicates value handle.
2082 * @param value Indicates value of the schedule settings.
2083 * @param len Indicates size of value.
2084 * @param result Indicates send status.
2085 * @since 6.0
2086 */
SendReadUsingCharacteristicValueResp(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len,int result) const2087 void GattServerProfile::SendReadUsingCharacteristicValueResp(
2088 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len, int result) const
2089 {
2090 LOG_INFO("%{public}s: connectHandle is %hu, result is %{public}d.", __FUNCTION__, connectHandle, result);
2091 AttReadByTypeRspDataList valueList[GATT_VALUE_LEN_MAX] = {{{0}, nullptr}};
2092 AttError errorData = {READ_REQUEST, handle, 0};
2093
2094 if (result == GATT_SUCCESS) {
2095 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
2096 if (buffer != nullptr) {
2097 valueList->attHandle.attHandle = handle;
2098 valueList->attributeValue = (uint8_t *)BufferPtr(buffer);
2099 ATT_ReadByTypeResponse(connectHandle, len + sizeof(handle), valueList, sizeof(uint8_t));
2100 BufferFree(buffer);
2101 }
2102 } else {
2103 errorData.errorCode = ConvertResponseErrorCode(result);
2104 ATT_ErrorResponse(connectHandle, &errorData);
2105 }
2106 }
2107 /**
2108 * @brief This sub-procedure is used to send read blob value response.
2109 *
2110 * @param connectHandle Indicates identify a connection.
2111 * @param handle Indicates value handle.
2112 * @param value Indicates value of the schedule settings.
2113 * @param len Indicates size of value.
2114 * @param result Indicates send status.
2115 * @since 6.0
2116 */
SendReadBlobValueResp(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len,int result) const2117 void GattServerProfile::SendReadBlobValueResp(
2118 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len, int result) const
2119 {
2120 LOG_INFO("%{public}s: connectHandle is %hu, result is %{public}d.", __FUNCTION__, connectHandle, result);
2121 AttError errorData = {READ_BLOB_REQUEST, handle, 0};
2122
2123 if (result == GATT_SUCCESS) {
2124 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
2125 if (buffer != nullptr) {
2126 ATT_ReadBlobResponse(connectHandle, buffer);
2127 BufferFree(buffer);
2128 }
2129 } else {
2130 errorData.errorCode = ConvertResponseErrorCode(result);
2131 ATT_ErrorResponse(connectHandle, &errorData);
2132 }
2133 }
2134 /**
2135 * @brief This sub-procedure is used to send write characteristic value response.
2136 *
2137 * @param connectHandle Indicates identify a connection.
2138 * @param handle Indicates value handle.
2139 * @param result Indicates send status.
2140 * @since 6.0
2141 */
SendWriteCharacteristicValueResp(uint16_t connectHandle,uint16_t handle,int result) const2142 void GattServerProfile::SendWriteCharacteristicValueResp(
2143 uint16_t connectHandle, uint16_t handle, int result) const
2144 {
2145 LOG_INFO("%{public}s: connectHandle is %hu, result is %{public}d.", __FUNCTION__, connectHandle, result);
2146 AttError errorData = {WRITE_REQUEST, handle, 0};
2147 if (result == GATT_SUCCESS) {
2148 ATT_WriteResponse(connectHandle);
2149 } else {
2150 errorData.errorCode = ConvertResponseErrorCode(result);
2151 ATT_ErrorResponse(connectHandle, &errorData);
2152 }
2153 }
2154 /**
2155 * @brief This sub-procedure is used to send read descriptor response.
2156 *
2157 * @param connectHandle Indicates identify a connection.
2158 * @param handle Indicates value handle.
2159 * @param value Indicates value of the schedule settings.
2160 * @param result Indicates send status.
2161 * @since 6.0
2162 */
SendReadDescriptorResp(uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len,int result) const2163 void GattServerProfile::SendReadDescriptorResp(
2164 uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len, int result) const
2165 {
2166 LOG_INFO("%{public}s: connectHandle is %hu, result is %{public}d.", __FUNCTION__, connectHandle, result);
2167 Buffer *buffer = nullptr;
2168 AttError errorData = {READ_REQUEST, handle, 0};
2169 uint16_t bufSize = pimpl->GetMtuInformation(connectHandle) - sizeof(uint8_t);
2170
2171 if (result == GATT_SUCCESS) {
2172 if (len > bufSize) {
2173 pimpl->requestList_.emplace_back(
2174 connectHandle, GattResponesInfor(READ_LONG_CHARACTERISTIC_VALUE, len, value));
2175 len = bufSize;
2176 }
2177 buffer = GattServiceBase::BuildBuffer(value->get(), len);
2178 if (buffer != nullptr) {
2179 ATT_ReadResponse(connectHandle, buffer);
2180 BufferFree(buffer);
2181 }
2182 } else {
2183 errorData.errorCode = ConvertResponseErrorCode(result);
2184 ATT_ErrorResponse(connectHandle, &errorData);
2185 }
2186 }
2187 /**
2188 * @brief This sub-procedure is used to send write descriptor response.
2189 *
2190 * @param connectHandle Indicates identify a connection.
2191 * @param handle Indicates value handle.
2192 * @param result Indicates send status.
2193 * @since 6.0
2194 */
SendWriteDescriptorResp(uint16_t connectHandle,uint16_t handle,int result) const2195 void GattServerProfile::SendWriteDescriptorResp(uint16_t connectHandle, uint16_t handle, int result) const
2196 {
2197 AttError errorData = {WRITE_REQUEST, handle, 0};
2198 if (result == GATT_SUCCESS) {
2199 ATT_WriteResponse(connectHandle);
2200 } else {
2201 errorData.errorCode = ConvertResponseErrorCode(result);
2202 ATT_ErrorResponse(connectHandle, &errorData);
2203 }
2204 }
2205 /**
2206 * @brief This sub-procedure is used to send prepare write value response.
2207 *
2208 * @param connectHandle Indicates identify a connection.
2209 * @param handle Indicates value handle.
2210 * @param value Indicates value of the schedule settings.
2211 * @param len Indicates size of value.
2212 * @param result Indicates send status.
2213 * @since 6.0
2214 */
SendPrepareWriteValueResp(PrepareWriteParam param,const GattValue & value,size_t len,int result) const2215 void GattServerProfile::SendPrepareWriteValueResp(
2216 PrepareWriteParam param, const GattValue &value, size_t len, int result) const
2217 {
2218 LOG_INFO("%{public}s: connectHandle is %hu, offset is %hu, result is %{public}d.",
2219 __FUNCTION__,
2220 param.connectHandle_,
2221 param.offset_,
2222 result);
2223 AttError errorData = {READ_BLOB_REQUEST, param.handle_, 0};
2224 AttReadBlobReqPrepareWriteValue attReadBlobObj = {param.handle_, param.offset_};
2225
2226 if (result == GATT_SUCCESS) {
2227 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
2228 if (buffer != nullptr) {
2229 ATT_PrepareWriteResponse(param.connectHandle_, attReadBlobObj, buffer);
2230 BufferFree(buffer);
2231 }
2232 } else {
2233 errorData.errorCode = ConvertResponseErrorCode(result);
2234 ATT_ErrorResponse(param.connectHandle_, &errorData);
2235 }
2236 }
2237 /**
2238 * @brief This sub-procedure is used to send execute write response.
2239 *
2240 * @param connectHandle Indicates identify a connection.
2241 * @since 6.0
2242 */
SendExecuteWriteValueResp(uint16_t connectHandle)2243 void GattServerProfile::SendExecuteWriteValueResp(uint16_t connectHandle)
2244 {
2245 LOG_INFO("%{public}s: connectHandle is %hu", __FUNCTION__, connectHandle);
2246 ATT_ExecuteWriteResponse(connectHandle);
2247 }
2248 /**
2249 * @brief Convert the att error code to the service layer error code.
2250 *
2251 * @param errorCode Indicates gatt service's error code.
2252 * @return Returns att error code.
2253 * @since 6.0
2254 */
ConvertResponseErrorCode(int errorCode)2255 int GattServerProfile::ConvertResponseErrorCode(int errorCode)
2256 {
2257 int ret;
2258
2259 switch ((GattStatus)errorCode) {
2260 case INVALID_HANDLE:
2261 ret = ATT_INVALID_HANDLE;
2262 break;
2263 case INVALID_OFFSET:
2264 ret = ATT_INVALID_OFFSET;
2265 break;
2266 case HANDLE_NOT_FOUND:
2267 ret = ATT_ATTRIBUTE_NOT_FOUND;
2268 break;
2269 case READ_NOT_PERMITTED:
2270 ret = ATT_READ_NOT_PERMITTED;
2271 break;
2272 case WRITE_NOT_PERMITTED:
2273 ret = ATT_WRITE_NOT_PERMITTED;
2274 break;
2275 case INSUFFICIENT_ENCRYPTION:
2276 ret = ATT_INSUFFICIENT_ENCRYPTION;
2277 break;
2278 case INSUFFICIENT_AUTHENTICATION:
2279 ret = ATT_INSUFFICIENT_AUTHENTICATION;
2280 break;
2281 case INSUFFICIENT_AUTHORIZATION:
2282 ret = ATT_INSUFFICIENT_AUTHORIZATION;
2283 break;
2284 case INSUFFICIENT_ENCRYPTION_KEY_SIZE:
2285 ret = ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE;
2286 break;
2287 case PREPARE_QUEUE_FULL:
2288 ret = ATT_PREPARE_QUEUE_FULL;
2289 break;
2290 case ATTRIBUTE_NOT_LONG:
2291 ret = ATT_ATTRIBUTE_NOT_LONG;
2292 break;
2293 case INVALID_ATTRIBUTE_VALUE_LENGTH:
2294 ret = ATT_INVALID_ATTRIBUTE_VALUE_LENGTH;
2295 break;
2296 case WRITE_REQUEST_REJECTED:
2297 ret = ATT_WRITE_REQUEST_REJECTED;
2298 break;
2299 default:
2300 ret = ATT_REQUEST_NOT_SUPPORTED;
2301 LOG_ERROR("%{public}s: Error code of error response is invalid. ErrorCode = %{public}d",
2302 __FUNCTION__, errorCode);
2303 break;
2304 }
2305
2306 return ret;
2307 }
2308 } // namespace bluetooth
2309 } // namespace OHOS
2310