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