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