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