1 /*
2 * Copyright (C) 2021 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 "sdp_client.h"
17
18 #include <string.h>
19
20 #include "allocator.h"
21
22 #include "sdp_client_parse.h"
23 #include "sdp_connect.h"
24 #include "sdp_util.h"
25
26 #include "bt_endian.h"
27 #include "log.h"
28 #include "packet.h"
29
30 #define SDP_UUID_ATTRIBUTE_LENGTH 17
31 #define SDP_SEARCH_LENGTH 5
32 #define SDP_ATTRIBUTE_LENGTH 15
33 #define SDP_SEARCH_ATTRIBUTE_LENGTH 20
34 #define SDP_BROWSE_LENGTH 8
35
36 /**
37 * @brief The function is used to initialize sdp client.
38 *
39 */
SdpInitializeClient()40 void SdpInitializeClient()
41 {
42 SdpCreateConnectList();
43 SdpCreateRequestList();
44 }
45
46 /**
47 * @brief The function is used to finalize sdp client.
48 *
49 */
SdpFinalizeClient()50 void SdpFinalizeClient()
51 {
52 SdpDestroyConnectList();
53 SdpDestroyRequestList();
54 }
55
SdpBuildPacket(const uint8_t * buffer,uint16_t length)56 static Packet *SdpBuildPacket(const uint8_t *buffer, uint16_t length)
57 {
58 Packet *packet = NULL;
59
60 packet = PacketMalloc(0, 0, length);
61 PacketPayloadWrite(packet, buffer, 0, length);
62
63 return packet;
64 }
65
SdpBuildAttributeList(SdpAttributeIdList attributeIdList,uint8_t * buffer,uint16_t offset)66 static uint16_t SdpBuildAttributeList(SdpAttributeIdList attributeIdList, uint8_t *buffer, uint16_t offset)
67 {
68 if (attributeIdList.type == SDP_TYPE_RANGE) {
69 uint8_t idRange[] = {0x35, 0x05, 0x0A, 0x00, 0x00, 0x00, 0x00};
70 uint16_t pos = 1;
71 /// Range of Attribute IDs (All Attribute: 0x0000 - 0xffff)
72 pos += SDP_UINT16_LENGTH;
73 *(uint16_t *)(idRange + pos) = H2BE_16(attributeIdList.attributeIdRange.start);
74 pos += SDP_UINT16_LENGTH;
75 *(uint16_t *)(idRange + pos) = H2BE_16(attributeIdList.attributeIdRange.end);
76 pos += SDP_UINT16_LENGTH;
77 if (memcpy_s(buffer + offset, pos, idRange, pos) != EOK) {
78 LOG_ERROR("[%{public}s][%{public}d] memcpy_s failed", __FUNCTION__, __LINE__);
79 return offset;
80 }
81 offset += pos;
82 } else {
83 if (attributeIdList.attributeIdList.attributeIdNumber > SDP_ATTRIBUTE_ID_LIST_MAX_COUNT) {
84 attributeIdList.attributeIdList.attributeIdNumber = SDP_ATTRIBUTE_ID_LIST_MAX_COUNT;
85 }
86 /// Data Element Sequence uint8 (0x35)
87 buffer[offset] = (DE_TYPE_DES << SDP_DESCRIPTOR_SIZE_BIT) | DE_SIZE_VAR_8;
88 offset++;
89 /// Data Element Var Size
90 buffer[offset] = attributeIdList.attributeIdList.attributeIdNumber * (SDP_UINT16_LENGTH + 1);
91 offset++;
92 /// Each Attribute ID
93 for (int i = 0; i < attributeIdList.attributeIdList.attributeIdNumber; i++) {
94 /// Data Element Unsigned Integer 2 bytes (0x09)
95 buffer[offset] = (DE_TYPE_UINT << SDP_DESCRIPTOR_SIZE_BIT) | DE_SIZE_16;
96 offset++;
97 /// Data Value 16-bit unsigned integer
98 *(uint16_t *)(buffer + offset) = H2BE_16(attributeIdList.attributeIdList.attributeId[i]);
99 offset += SDP_UINT16_LENGTH;
100 }
101 }
102
103 return offset;
104 }
105
SdpCreateSearchRequest(const BtUuid * uuidArray,uint16_t uuidNum,uint8_t * buffer)106 static uint16_t SdpCreateSearchRequest(const BtUuid *uuidArray, uint16_t uuidNum, uint8_t *buffer)
107 {
108 uint16_t offset = 0;
109
110 // Data Element: Sequence uint8 (0x35)
111 buffer[offset] = (DE_TYPE_DES << SDP_DESCRIPTOR_SIZE_BIT) | DE_SIZE_VAR_8;
112 offset += SDP_UINT16_LENGTH;
113 /// ServiceSearchPattern (min 1, max 12)
114 for (int i = 0; i < uuidNum; i++) {
115 offset = SdpAddAttributeForUuid(buffer, offset, &uuidArray[i]);
116 }
117 /// ParameterLength
118 buffer[1] = offset - SDP_UINT16_LENGTH;
119 /// MaximumServiceRecordCount - uint16_t (0x0001 - 0xFFFF)
120 *(uint16_t *)(buffer + offset) = H2BE_16(SDP_MAX_RECORD_HANDLE_COUNT);
121 offset += SDP_UINT16_LENGTH;
122
123 return offset;
124 }
125
SdpCreateAttributeRequest(uint32_t handle,SdpAttributeIdList attributeIdList,uint8_t * buffer)126 static uint16_t SdpCreateAttributeRequest(uint32_t handle, SdpAttributeIdList attributeIdList, uint8_t *buffer)
127 {
128 uint16_t offset = 0;
129
130 /// ServiceRecordHandle
131 *(uint32_t *)(buffer + offset) = H2BE_32(handle);
132 offset += SDP_SERVICE_RECORD_HANDLE_BYTE;
133 /// MaximumAttributeByteCount - uint16_t (0x0001 - 0xFFFF)
134 *(uint16_t *)(buffer + offset) = H2BE_16(SDP_MAX_ATTRIBUTE_BYTE_COUNT);
135 offset += SDP_UINT16_LENGTH;
136 /// AttributeIDList
137 offset = SdpBuildAttributeList(attributeIdList, buffer, offset);
138
139 return offset;
140 }
141
SdpCreateSearchAttributeRequest(const BtUuid * uuidArray,uint16_t uuidNum,SdpAttributeIdList attributeIdList,uint8_t * buffer)142 static uint16_t SdpCreateSearchAttributeRequest(
143 const BtUuid *uuidArray, uint16_t uuidNum, SdpAttributeIdList attributeIdList, uint8_t *buffer)
144 {
145 uint16_t offset = 0;
146
147 // Data Element: Sequence uint8 (0x35)
148 buffer[offset] = (DE_TYPE_DES << SDP_DESCRIPTOR_SIZE_BIT) | DE_SIZE_VAR_8;
149 offset += SDP_UINT16_LENGTH;
150 /// ServiceSearchPattern (min 1, max 12)
151 for (int i = 0; i < uuidNum; i++) {
152 offset = SdpAddAttributeForUuid(buffer, offset, &uuidArray[i]);
153 }
154 /// ParameterLength
155 buffer[1] = offset - SDP_UINT16_LENGTH;
156 /// MaximumAttributeByteCount - uint16_t (0x0001 - 0xFFFF)
157 *(uint16_t *)(buffer + offset) = H2BE_16(SDP_MAX_ATTRIBUTE_BYTE_COUNT);
158 offset += SDP_UINT16_LENGTH;
159 /// AttributeIDList
160 offset = SdpBuildAttributeList(attributeIdList, buffer, offset);
161
162 return offset;
163 }
164
SdpCreateServiceBrowseRequest(uint8_t * buffer)165 static uint16_t SdpCreateServiceBrowseRequest(uint8_t *buffer)
166 {
167 uint16_t length;
168 BtUuid uuid;
169
170 uuid.type = BT_UUID_16;
171 uuid.uuid16 = SDP_PUBLIC_BROWSE_GROUP_ROOT_UUID;
172 length = SdpCreateSearchRequest(&uuid, 1, buffer);
173
174 return length;
175 }
176
SdpServiceSearch(const BtAddr * addr,const SdpUuid * uuidArray,void * context,void (* serviceSearchCb)(const BtAddr * addr,const uint32_t * handleArray,uint16_t handleNum,void * context))177 int SdpServiceSearch(const BtAddr *addr, const SdpUuid *uuidArray, void *context,
178 void (*serviceSearchCb)(const BtAddr *addr, const uint32_t *handleArray, uint16_t handleNum, void *context))
179 {
180 LOG_INFO("[%{public}s][%{public}d] uuidNum = [%hu]", __FUNCTION__, __LINE__, uuidArray->uuidNum);
181 SdpClientRequest *request = NULL;
182 uint8_t *buffer = NULL;
183 uint16_t length;
184 int ret;
185
186 if (SdpGetEnableState() == false) {
187 return BT_BAD_STATUS;
188 }
189
190 /// Create service search request
191 request = MEM_MALLOC.alloc(sizeof(SdpClientRequest));
192 (void)memset_s(request, sizeof(SdpClientRequest), 0, sizeof(SdpClientRequest));
193 buffer = MEM_MALLOC.alloc(uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH + SDP_SEARCH_LENGTH);
194 (void)memset_s(buffer,
195 (uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH + SDP_SEARCH_LENGTH),
196 0,
197 (uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH + SDP_SEARCH_LENGTH));
198
199 length = SdpCreateSearchRequest(uuidArray->uuid, uuidArray->uuidNum, buffer);
200 if (length == 0) {
201 LOG_ERROR("[%{public}s][%{public}d] Create search request failed", __FUNCTION__, __LINE__);
202 return BT_BAD_PARAM;
203 }
204
205 (void)memcpy_s(&request->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
206 request->pduId = SDP_SERVICE_SEARCH_REQUEST;
207 request->transactionId = SdpGetTransactionId();
208 request->resentFlag = false;
209 request->packetState = SDP_PACKET_WAIT;
210 request->packet = SdpBuildPacket(buffer, length);
211 request->assemblePacket = NULL;
212 request->callback.ServiceSearchCb = serviceSearchCb;
213 request->context = context;
214
215 ret = SdpClientConnect(request);
216 MEM_MALLOC.free(buffer);
217
218 return ret;
219 }
220
SdpServiceAttribute(const BtAddr * addr,uint32_t handle,SdpAttributeIdList attributeIdList,void * context,void (* serviceAttributeCb)(const BtAddr * addr,const SdpService * service,void * context))221 int SdpServiceAttribute(const BtAddr *addr, uint32_t handle, SdpAttributeIdList attributeIdList, void *context,
222 void (*serviceAttributeCb)(const BtAddr *addr, const SdpService *service, void *context))
223 {
224 LOG_INFO("[%{public}s][%{public}d] handle = [%08x], type = [%u]", __FUNCTION__, __LINE__, handle, attributeIdList.type);
225 uint16_t length;
226 uint8_t *buffer = NULL;
227 SdpClientRequest *request = NULL;
228 int ret;
229
230 if (SdpGetEnableState() == false) {
231 return BT_BAD_STATUS;
232 }
233
234 request = MEM_MALLOC.alloc(sizeof(SdpClientRequest));
235 (void)memset_s(request, sizeof(SdpClientRequest), 0, sizeof(SdpClientRequest));
236 /// Create service attribute request
237 buffer = MEM_MALLOC.alloc(sizeof(SdpAttributeIdList) + SDP_ATTRIBUTE_LENGTH);
238 (void)memset_s(buffer,
239 (sizeof(SdpAttributeIdList) + SDP_ATTRIBUTE_LENGTH),
240 0,
241 (sizeof(SdpAttributeIdList) + SDP_ATTRIBUTE_LENGTH));
242
243 length = SdpCreateAttributeRequest(handle, attributeIdList, buffer);
244 if (length == 0) {
245 LOG_ERROR("[%{public}s][%{public}d] Create attribute request failed", __FUNCTION__, __LINE__);
246 return BT_BAD_PARAM;
247 }
248
249 (void)memcpy_s(&request->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
250 request->pduId = SDP_SERVICE_ATTRIBUTE_REQUEST;
251 request->transactionId = SdpGetTransactionId();
252 request->resentFlag = false;
253 request->packetState = SDP_PACKET_WAIT;
254 request->packet = SdpBuildPacket(buffer, length);
255 request->assemblePacket = NULL;
256 request->callback.ServiceAttributeCb = serviceAttributeCb;
257 request->context = context;
258
259 ret = SdpClientConnect(request);
260 MEM_MALLOC.free(buffer);
261
262 return ret;
263 }
264
SdpServiceSearchAttribute(const BtAddr * addr,const SdpUuid * uuidArray,SdpAttributeIdList attributeIdList,void * context,void (* searchAttributeCb)(const BtAddr * addr,const SdpService * serviceArray,uint16_t serviceNum,void * context))265 int SdpServiceSearchAttribute(const BtAddr *addr, const SdpUuid *uuidArray, SdpAttributeIdList attributeIdList,
266 void *context,
267 void (*searchAttributeCb)(const BtAddr *addr, const SdpService *serviceArray, uint16_t serviceNum, void *context))
268 {
269 LOG_INFO("[%{public}s][%{public}d] uuidNum = [%hu], type = [%u]", __FUNCTION__, __LINE__, uuidArray->uuidNum, attributeIdList.type);
270 uint16_t length;
271 uint8_t *buffer = NULL;
272 SdpClientRequest *request = NULL;
273 int ret;
274
275 if (SdpGetEnableState() == false) {
276 return BT_BAD_STATUS;
277 }
278
279 /// Create service search attribute request
280 request = MEM_MALLOC.alloc(sizeof(SdpClientRequest));
281 (void)memset_s(request, sizeof(SdpClientRequest), 0, sizeof(SdpClientRequest));
282 buffer = MEM_MALLOC.alloc(
283 sizeof(SdpAttributeIdList) + (uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH) + SDP_SEARCH_ATTRIBUTE_LENGTH);
284 (void)memset_s(buffer,
285 (sizeof(SdpAttributeIdList) + (uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH) + SDP_SEARCH_ATTRIBUTE_LENGTH),
286 0,
287 (sizeof(SdpAttributeIdList) + (uuidArray->uuidNum * SDP_UUID_ATTRIBUTE_LENGTH) + SDP_SEARCH_ATTRIBUTE_LENGTH));
288
289 length = SdpCreateSearchAttributeRequest(uuidArray->uuid, uuidArray->uuidNum, attributeIdList, buffer);
290 if (length == 0) {
291 LOG_ERROR("[%{public}s][%{public}d] Create search attribute request failed", __FUNCTION__, __LINE__);
292 return BT_BAD_PARAM;
293 }
294
295 (void)memcpy_s(&request->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
296 request->pduId = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
297 request->transactionId = SdpGetTransactionId();
298 request->resentFlag = false;
299 request->packetState = SDP_PACKET_WAIT;
300 request->packet = SdpBuildPacket(buffer, length);
301 request->assemblePacket = NULL;
302 request->callback.ServiceSearchAttributeCb = searchAttributeCb;
303 request->context = context;
304
305 ret = SdpClientConnect(request);
306 MEM_MALLOC.free(buffer);
307
308 return ret;
309 }
310
SdpServiceBrowse(const BtAddr * addr,void * context,void (* serviceBrowseCb)(const BtAddr * addr,const uint32_t * handleArray,uint16_t handleNum,void * context))311 int SdpServiceBrowse(const BtAddr *addr, void *context,
312 void (*serviceBrowseCb)(const BtAddr *addr, const uint32_t *handleArray, uint16_t handleNum, void *context))
313 {
314 SdpClientRequest *request = NULL;
315 uint8_t *buffer = NULL;
316 uint16_t length;
317 int ret;
318
319 if (SdpGetEnableState() == false) {
320 return BT_BAD_STATUS;
321 }
322
323 /// Create service search request
324 request = MEM_MALLOC.alloc(sizeof(SdpClientRequest));
325 (void)memset_s(request, sizeof(SdpClientRequest), 0, sizeof(SdpClientRequest));
326
327 buffer = MEM_MALLOC.alloc(SDP_BROWSE_LENGTH);
328 (void)memset_s(buffer, SDP_BROWSE_LENGTH, 0, SDP_BROWSE_LENGTH);
329
330 length = SdpCreateServiceBrowseRequest(buffer);
331 if (length == 0) {
332 LOG_ERROR("[%{public}s][%{public}d] Setup search request failed", __FUNCTION__, __LINE__);
333 return BT_BAD_PARAM;
334 }
335
336 (void)memcpy_s(&request->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
337 request->pduId = SDP_SERVICE_SEARCH_REQUEST;
338 request->transactionId = SdpGetTransactionId();
339 request->resentFlag = false;
340 request->packetState = SDP_PACKET_WAIT;
341 request->packet = SdpBuildPacket(buffer, length);
342 request->assemblePacket = NULL;
343 request->callback.ServiceSearchCb = serviceBrowseCb;
344 request->context = context;
345
346 ret = SdpClientConnect(request);
347 MEM_MALLOC.free(buffer);
348
349 return ret;
350 }