OSDN Git Service

d5b2ec517ed174eea08b54a827c316802358badf
[android-x86/system-bt.git] / stack / sdp / sdp_discovery.cc
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 /******************************************************************************
20  *
21  *  this file contains SDP discovery functions
22  *
23  ******************************************************************************/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "btm_api.h"
32 #include "btu.h"
33 #include "hcidefs.h"
34 #include "hcimsgs.h"
35 #include "l2cdefs.h"
36 #include "log/log.h"
37 #include "sdp_api.h"
38 #include "sdpint.h"
39
40 #ifndef SDP_DEBUG_RAW
41 #define SDP_DEBUG_RAW false
42 #endif
43
44 /******************************************************************************/
45 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
46 /******************************************************************************/
47 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
48                                        uint8_t* p_reply_end);
49 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
50                                      uint8_t* p_reply_end);
51 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
52                                             uint8_t* p_reply_end);
53 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end);
54 static tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db,
55                                  const RawAddress& p_bda);
56 static uint8_t* add_attr(uint8_t* p, uint8_t* p_end, tSDP_DISCOVERY_DB* p_db,
57                          tSDP_DISC_REC* p_rec, uint16_t attr_id,
58                          tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level);
59
60 /* Safety check in case we go crazy */
61 #define MAX_NEST_LEVELS 5
62
63 /*******************************************************************************
64  *
65  * Function         sdpu_build_uuid_seq
66  *
67  * Description      This function builds a UUID sequence from the list of
68  *                  passed UUIDs. It is also passed the address of the output
69  *                  buffer.
70  *
71  * Returns          Pointer to next byte in the output buffer.
72  *
73  ******************************************************************************/
74 static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids,
75                                     tSDP_UUID* p_uuid_list) {
76   uint16_t xx;
77   uint8_t* p_len;
78
79   /* First thing is the data element header */
80   UINT8_TO_BE_STREAM(p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
81
82   /* Remember where the length goes. Leave space for it. */
83   p_len = p_out;
84   p_out += 1;
85
86   /* Now, loop through and put in all the UUID(s) */
87   for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
88     if (p_uuid_list->len == LEN_UUID_16) {
89       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
90       UINT16_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid16);
91     } else if (p_uuid_list->len == LEN_UUID_32) {
92       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
93       UINT32_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid32);
94     } else if (p_uuid_list->len == LEN_UUID_128) {
95       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
96       ARRAY_TO_BE_STREAM(p_out, p_uuid_list->uu.uuid128, p_uuid_list->len);
97     } else {
98       SDP_TRACE_ERROR("SDP: Passed UUID has invalid length %x",
99                       p_uuid_list->len);
100     }
101   }
102
103   /* Now, put in the length */
104   xx = (uint16_t)(p_out - p_len - 1);
105   UINT8_TO_BE_STREAM(p_len, xx);
106
107   return (p_out);
108 }
109
110 /*******************************************************************************
111  *
112  * Function         sdp_snd_service_search_req
113  *
114  * Description      Send a service search request to the SDP server.
115  *
116  * Returns          void
117  *
118  ******************************************************************************/
119 static void sdp_snd_service_search_req(tCONN_CB* p_ccb, uint8_t cont_len,
120                                        uint8_t* p_cont) {
121   uint8_t *p, *p_start, *p_param_len;
122   BT_HDR* p_cmd = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
123   uint16_t param_len;
124
125   /* Prepare the buffer for sending the packet to L2CAP */
126   p_cmd->offset = L2CAP_MIN_OFFSET;
127   p = p_start = (uint8_t*)(p_cmd + 1) + L2CAP_MIN_OFFSET;
128
129   /* Build a service search request packet */
130   UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_REQ);
131   UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
132   p_ccb->transaction_id++;
133
134   /* Skip the length, we need to add it at the end */
135   p_param_len = p;
136   p += 2;
137
138 /* Build the UID sequence. */
139 #if (SDP_BROWSE_PLUS == TRUE)
140   p = sdpu_build_uuid_seq(p, 1,
141                           &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
142 #else
143   p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
144                           p_ccb->p_db->uuid_filters);
145 #endif
146
147   /* Set max service record count */
148   UINT16_TO_BE_STREAM(p, sdp_cb.max_recs_per_search);
149
150   /* Set continuation state */
151   UINT8_TO_BE_STREAM(p, cont_len);
152
153   /* if this is not the first request */
154   if (cont_len && p_cont) {
155     memcpy(p, p_cont, cont_len);
156     p += cont_len;
157   }
158
159   /* Go back and put the parameter length into the buffer */
160   param_len = (uint16_t)(p - p_param_len - 2);
161   UINT16_TO_BE_STREAM(p_param_len, param_len);
162
163   p_ccb->disc_state = SDP_DISC_WAIT_HANDLES;
164
165   /* Set the length of the SDP data in the buffer */
166   p_cmd->len = (uint16_t)(p - p_start);
167
168 #if (SDP_DEBUG_RAW == TRUE)
169   SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d",
170                     cont_len, p_ccb->disc_state);
171 #endif
172
173   L2CA_DataWrite(p_ccb->connection_id, p_cmd);
174
175   /* Start inactivity timer */
176   alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
177                      sdp_conn_timer_timeout, p_ccb);
178 }
179
180 /*******************************************************************************
181  *
182  * Function         sdp_disc_connected
183  *
184  * Description      This function is called when an SDP discovery attempt is
185  *                  connected.
186  *
187  * Returns          void
188  *
189  ******************************************************************************/
190 void sdp_disc_connected(tCONN_CB* p_ccb) {
191   if (p_ccb->is_attr_search) {
192     p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
193
194     process_service_search_attr_rsp(p_ccb, NULL, NULL);
195   } else {
196     /* First step is to get a list of the handles from the server. */
197     /* We are not searching for a specific attribute, so we will   */
198     /* first search for the service, then get all attributes of it */
199
200     p_ccb->num_handles = 0;
201     sdp_snd_service_search_req(p_ccb, 0, NULL);
202   }
203 }
204
205 /*******************************************************************************
206  *
207  * Function         sdp_disc_server_rsp
208  *
209  * Description      This function is called when there is a response from
210  *                  the server.
211  *
212  * Returns          void
213  *
214  ******************************************************************************/
215 void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg) {
216   uint8_t *p, rsp_pdu;
217   bool invalid_pdu = true;
218
219 #if (SDP_DEBUG_RAW == TRUE)
220   SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d", p_ccb->disc_state);
221 #endif
222
223   /* stop inactivity timer when we receive a response */
224   alarm_cancel(p_ccb->sdp_conn_timer);
225
226   /* Got a reply!! Check what we got back */
227   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
228   uint8_t* p_end = p + p_msg->len;
229
230   BE_STREAM_TO_UINT8(rsp_pdu, p);
231
232   p_msg->len--;
233
234   switch (rsp_pdu) {
235     case SDP_PDU_SERVICE_SEARCH_RSP:
236       if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES) {
237         process_service_search_rsp(p_ccb, p, p_end);
238         invalid_pdu = false;
239       }
240       break;
241
242     case SDP_PDU_SERVICE_ATTR_RSP:
243       if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR) {
244         process_service_attr_rsp(p_ccb, p, p_end);
245         invalid_pdu = false;
246       }
247       break;
248
249     case SDP_PDU_SERVICE_SEARCH_ATTR_RSP:
250       if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR) {
251         process_service_search_attr_rsp(p_ccb, p, p_end);
252         invalid_pdu = false;
253       }
254       break;
255   }
256
257   if (invalid_pdu) {
258     SDP_TRACE_WARNING("SDP - Unexp. PDU: %d in state: %d", rsp_pdu,
259                       p_ccb->disc_state);
260     sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
261   }
262 }
263
264 /******************************************************************************
265  *
266  * Function         process_service_search_rsp
267  *
268  * Description      This function is called when there is a search response from
269  *                  the server.
270  *
271  * Returns          void
272  *
273  ******************************************************************************/
274 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
275                                        uint8_t* p_reply_end) {
276   uint16_t xx;
277   uint16_t total, cur_handles, orig;
278   uint8_t cont_len;
279
280   if (p_reply + 8 > p_reply_end) {
281     android_errorWriteLog(0x534e4554, "74249842");
282     sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
283     return;
284   }
285   /* Skip transaction, and param len */
286   p_reply += 4;
287   BE_STREAM_TO_UINT16(total, p_reply);
288   BE_STREAM_TO_UINT16(cur_handles, p_reply);
289
290   orig = p_ccb->num_handles;
291   p_ccb->num_handles += cur_handles;
292   if (p_ccb->num_handles == 0) {
293     SDP_TRACE_WARNING("SDP - Rcvd ServiceSearchRsp, no matches");
294     sdp_disconnect(p_ccb, SDP_NO_RECS_MATCH);
295     return;
296   }
297
298   /* Save the handles that match. We will can only process a certain number. */
299   if (total > sdp_cb.max_recs_per_search) total = sdp_cb.max_recs_per_search;
300   if (p_ccb->num_handles > sdp_cb.max_recs_per_search)
301     p_ccb->num_handles = sdp_cb.max_recs_per_search;
302
303   if (p_reply + ((p_ccb->num_handles - orig) * 4) + 1 > p_reply_end) {
304     android_errorWriteLog(0x534e4554, "74249842");
305     sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
306     return;
307   }
308
309   for (xx = orig; xx < p_ccb->num_handles; xx++)
310     BE_STREAM_TO_UINT32(p_ccb->handles[xx], p_reply);
311
312   BE_STREAM_TO_UINT8(cont_len, p_reply);
313   if (cont_len != 0) {
314     if (cont_len > SDP_MAX_CONTINUATION_LEN) {
315       sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
316       return;
317     }
318     if (p_reply + cont_len > p_reply_end) {
319       android_errorWriteLog(0x534e4554, "68161546");
320       sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
321       return;
322     }
323     /* stay in the same state */
324     sdp_snd_service_search_req(p_ccb, cont_len, p_reply);
325   } else {
326     /* change state */
327     p_ccb->disc_state = SDP_DISC_WAIT_ATTR;
328
329     /* Kick off the first attribute request */
330     process_service_attr_rsp(p_ccb, NULL, NULL);
331   }
332 }
333
334 /*******************************************************************************
335  *
336  * Function         sdp_copy_raw_data
337  *
338  * Description      copy the raw data
339  *
340  *
341  * Returns          void
342  *
343  ******************************************************************************/
344 #if (SDP_RAW_DATA_INCLUDED == TRUE)
345 static void sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) {
346   unsigned int cpy_len, rem_len;
347   uint32_t list_len;
348   uint8_t* p;
349   uint8_t type;
350
351 #if (SDP_DEBUG_RAW == TRUE)
352   uint8_t num_array[SDP_MAX_LIST_BYTE_COUNT];
353   uint32_t i;
354
355   for (i = 0; i < p_ccb->list_len; i++) {
356     snprintf((char*)&num_array[i * 2], sizeof(num_array) - i * 2, "%02X",
357              (uint8_t)(p_ccb->rsp_list[i]));
358   }
359   SDP_TRACE_WARNING("result :%s", num_array);
360 #endif
361
362   if (p_ccb->p_db->raw_data) {
363     cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
364     list_len = p_ccb->list_len;
365     p = &p_ccb->rsp_list[0];
366
367     if (offset) {
368       cpy_len -= 1;
369       type = *p++;
370       uint8_t* old_p = p;
371       p = sdpu_get_len_from_type(p, type, &list_len);
372       if ((int)cpy_len < (p - old_p)) {
373         SDP_TRACE_WARNING("%s: no bytes left for data", __func__);
374         return;
375       }
376       cpy_len -= (p - old_p);
377     }
378     if (list_len < cpy_len) {
379       cpy_len = list_len;
380     }
381     rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
382     if (cpy_len > rem_len) {
383       SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
384       cpy_len = rem_len;
385     }
386     SDP_TRACE_WARNING(
387         "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
388         "raw_used:%d raw_data:%p",
389         __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
390         p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
391     memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
392     p_ccb->p_db->raw_used += cpy_len;
393   }
394 }
395 #endif
396
397 /*******************************************************************************
398  *
399  * Function         process_service_attr_rsp
400  *
401  * Description      This function is called when there is a attribute response
402  *                  from the server.
403  *
404  * Returns          void
405  *
406  ******************************************************************************/
407 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
408                                      uint8_t* p_reply_end) {
409   uint8_t *p_start, *p_param_len;
410   uint16_t param_len, list_byte_count;
411   bool cont_request_needed = false;
412
413 #if (SDP_DEBUG_RAW == TRUE)
414   SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d",
415                     SDP_RAW_DATA_INCLUDED);
416 #endif
417   /* If p_reply is NULL, we were called after the records handles were read */
418   if (p_reply) {
419 #if (SDP_DEBUG_RAW == TRUE)
420     SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
421                       p_reply[2], p_reply[3]);
422 #endif
423     /* Skip transaction ID and length */
424     p_reply += 4;
425
426     BE_STREAM_TO_UINT16(list_byte_count, p_reply);
427 #if (SDP_DEBUG_RAW == TRUE)
428     SDP_TRACE_WARNING("list_byte_count:%d", list_byte_count);
429 #endif
430
431     /* Copy the response to the scratchpad. First, a safety check on the length
432      */
433     if ((p_ccb->list_len + list_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
434       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
435       return;
436     }
437
438 #if (SDP_DEBUG_RAW == TRUE)
439     SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
440                       list_byte_count);
441 #endif
442     if (p_ccb->rsp_list == NULL)
443       p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
444     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
445     p_ccb->list_len += list_byte_count;
446     p_reply += list_byte_count;
447 #if (SDP_DEBUG_RAW == TRUE)
448     SDP_TRACE_WARNING("list_len: %d(attr_rsp)", p_ccb->list_len);
449
450     /* Check if we need to request a continuation */
451     SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
452 #endif
453     if (*p_reply) {
454       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
455         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
456         return;
457       }
458       cont_request_needed = true;
459     } else {
460 #if (SDP_RAW_DATA_INCLUDED == TRUE)
461       SDP_TRACE_WARNING("process_service_attr_rsp");
462       sdp_copy_raw_data(p_ccb, false);
463 #endif
464
465       /* Save the response in the database. Stop on any error */
466       if (!save_attr_seq(p_ccb, &p_ccb->rsp_list[0],
467                          &p_ccb->rsp_list[p_ccb->list_len])) {
468         sdp_disconnect(p_ccb, SDP_DB_FULL);
469         return;
470       }
471       p_ccb->list_len = 0;
472       p_ccb->cur_handle++;
473     }
474   }
475
476   /* Now, ask for the next handle. Re-use the buffer we just got. */
477   if (p_ccb->cur_handle < p_ccb->num_handles) {
478     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
479     uint8_t* p;
480
481     p_msg->offset = L2CAP_MIN_OFFSET;
482     p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
483
484     /* Get all the attributes from the server */
485     UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_ATTR_REQ);
486     UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
487     p_ccb->transaction_id++;
488
489     /* Skip the length, we need to add it at the end */
490     p_param_len = p;
491     p += 2;
492
493     UINT32_TO_BE_STREAM(p, p_ccb->handles[p_ccb->cur_handle]);
494
495     /* Max attribute byte count */
496     UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
497
498     /* If no attribute filters, build a wildcard attribute sequence */
499     if (p_ccb->p_db->num_attr_filters)
500       p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
501                                 p_ccb->p_db->num_attr_filters);
502     else
503       p = sdpu_build_attrib_seq(p, NULL, 0);
504
505     /* Was this a continuation request ? */
506     if (cont_request_needed) {
507       if ((p_reply + *p_reply + 1) <= p_reply_end) {
508         memcpy(p, p_reply, *p_reply + 1);
509         p += *p_reply + 1;
510       } else {
511         android_errorWriteLog(0x534e4554, "68161546");
512       }
513     } else
514       UINT8_TO_BE_STREAM(p, 0);
515
516     /* Go back and put the parameter length into the buffer */
517     param_len = (uint16_t)(p - p_param_len - 2);
518     UINT16_TO_BE_STREAM(p_param_len, param_len);
519
520     /* Set the length of the SDP data in the buffer */
521     p_msg->len = (uint16_t)(p - p_start);
522
523     L2CA_DataWrite(p_ccb->connection_id, p_msg);
524
525     /* Start inactivity timer */
526     alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
527                        sdp_conn_timer_timeout, p_ccb);
528   } else {
529     sdp_disconnect(p_ccb, SDP_SUCCESS);
530     return;
531   }
532 }
533
534 /*******************************************************************************
535  *
536  * Function         process_service_search_attr_rsp
537  *
538  * Description      This function is called when there is a search attribute
539  *                  response from the server.
540  *
541  * Returns          void
542  *
543  ******************************************************************************/
544 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
545                                             uint8_t* p_reply_end) {
546   uint8_t *p, *p_start, *p_end, *p_param_len;
547   uint8_t type;
548   uint32_t seq_len;
549   uint16_t param_len, lists_byte_count = 0;
550   bool cont_request_needed = false;
551
552 #if (SDP_DEBUG_RAW == TRUE)
553   SDP_TRACE_WARNING("process_service_search_attr_rsp");
554 #endif
555   /* If p_reply is NULL, we were called for the initial read */
556   if (p_reply) {
557     if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) >
558         p_reply_end) {
559       android_errorWriteLog(0x534e4554, "79884292");
560       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
561       return;
562     }
563
564 #if (SDP_DEBUG_RAW == TRUE)
565     SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
566                       p_reply[2], p_reply[3]);
567 #endif
568     /* Skip transaction ID and length */
569     p_reply += 4;
570
571     BE_STREAM_TO_UINT16(lists_byte_count, p_reply);
572 #if (SDP_DEBUG_RAW == TRUE)
573     SDP_TRACE_WARNING("lists_byte_count:%d", lists_byte_count);
574 #endif
575
576     /* Copy the response to the scratchpad. First, a safety check on the length
577      */
578     if ((p_ccb->list_len + lists_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
579       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
580       return;
581     }
582
583 #if (SDP_DEBUG_RAW == TRUE)
584     SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
585                       lists_byte_count);
586 #endif
587
588     if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) {
589       android_errorWriteLog(0x534e4554, "79884292");
590       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
591       return;
592     }
593
594     if (p_ccb->rsp_list == NULL)
595       p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
596     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
597     p_ccb->list_len += lists_byte_count;
598     p_reply += lists_byte_count;
599 #if (SDP_DEBUG_RAW == TRUE)
600     SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)", p_ccb->list_len);
601
602     /* Check if we need to request a continuation */
603     SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
604 #endif
605     if (*p_reply) {
606       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
607         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
608         return;
609       }
610
611       cont_request_needed = true;
612     }
613   }
614
615 #if (SDP_DEBUG_RAW == TRUE)
616   SDP_TRACE_WARNING("cont_request_needed:%d", cont_request_needed);
617 #endif
618   /* If continuation request (or first time request) */
619   if ((cont_request_needed) || (!p_reply)) {
620     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
621     uint8_t* p;
622
623     p_msg->offset = L2CAP_MIN_OFFSET;
624     p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
625
626     /* Build a service search request packet */
627     UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_ATTR_REQ);
628     UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
629     p_ccb->transaction_id++;
630
631     /* Skip the length, we need to add it at the end */
632     p_param_len = p;
633     p += 2;
634
635 /* Build the UID sequence. */
636 #if (SDP_BROWSE_PLUS == TRUE)
637     p = sdpu_build_uuid_seq(p, 1,
638                             &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
639 #else
640     p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
641                             p_ccb->p_db->uuid_filters);
642 #endif
643
644     /* Max attribute byte count */
645     UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
646
647     /* If no attribute filters, build a wildcard attribute sequence */
648     if (p_ccb->p_db->num_attr_filters)
649       p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
650                                 p_ccb->p_db->num_attr_filters);
651     else
652       p = sdpu_build_attrib_seq(p, NULL, 0);
653
654     /* No continuation for first request */
655     if (p_reply) {
656       if ((p_reply + *p_reply + 1) <= p_reply_end) {
657         memcpy(p, p_reply, *p_reply + 1);
658         p += *p_reply + 1;
659       } else {
660         android_errorWriteLog(0x534e4554, "68161546");
661       }
662     } else
663       UINT8_TO_BE_STREAM(p, 0);
664
665     /* Go back and put the parameter length into the buffer */
666     param_len = p - p_param_len - 2;
667     UINT16_TO_BE_STREAM(p_param_len, param_len);
668
669     /* Set the length of the SDP data in the buffer */
670     p_msg->len = p - p_start;
671
672     L2CA_DataWrite(p_ccb->connection_id, p_msg);
673
674     /* Start inactivity timer */
675     alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
676                        sdp_conn_timer_timeout, p_ccb);
677
678     return;
679   }
680
681 /*******************************************************************/
682 /* We now have the full response, which is a sequence of sequences */
683 /*******************************************************************/
684
685 #if (SDP_RAW_DATA_INCLUDED == TRUE)
686   SDP_TRACE_WARNING("process_service_search_attr_rsp");
687   sdp_copy_raw_data(p_ccb, true);
688 #endif
689
690   p = &p_ccb->rsp_list[0];
691
692   /* The contents is a sequence of attribute sequences */
693   type = *p++;
694
695   if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
696     SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
697     return;
698   }
699   p = sdpu_get_len_from_type(p, type, &seq_len);
700
701   p_end = &p_ccb->rsp_list[p_ccb->list_len];
702
703   if ((p + seq_len) != p_end) {
704     sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
705     return;
706   }
707
708   while (p < p_end) {
709     p = save_attr_seq(p_ccb, p, &p_ccb->rsp_list[p_ccb->list_len]);
710     if (!p) {
711       sdp_disconnect(p_ccb, SDP_DB_FULL);
712       return;
713     }
714   }
715
716   /* Since we got everything we need, disconnect the call */
717   sdp_disconnect(p_ccb, SDP_SUCCESS);
718 }
719
720 /*******************************************************************************
721  *
722  * Function         save_attr_seq
723  *
724  * Description      This function is called when there is a response from
725  *                  the server.
726  *
727  * Returns          pointer to next byte or NULL if error
728  *
729  ******************************************************************************/
730 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end) {
731   uint32_t seq_len, attr_len;
732   uint16_t attr_id;
733   uint8_t type, *p_seq_end;
734   tSDP_DISC_REC* p_rec;
735
736   type = *p++;
737
738   if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
739     SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
740     return (NULL);
741   }
742
743   p = sdpu_get_len_from_type(p, type, &seq_len);
744   if ((p + seq_len) > p_msg_end) {
745     SDP_TRACE_WARNING("SDP - Bad len in attr_rsp %d", seq_len);
746     return (NULL);
747   }
748
749   /* Create a record */
750   p_rec = add_record(p_ccb->p_db, p_ccb->device_address);
751   if (!p_rec) {
752     SDP_TRACE_WARNING("SDP - DB full add_record");
753     return (NULL);
754   }
755
756   p_seq_end = p + seq_len;
757
758   while (p < p_seq_end) {
759     /* First get the attribute ID */
760     type = *p++;
761     p = sdpu_get_len_from_type(p, type, &attr_len);
762     if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) {
763       SDP_TRACE_WARNING("SDP - Bad type: 0x%02x or len: %d in attr_rsp", type,
764                         attr_len);
765       return (NULL);
766     }
767     BE_STREAM_TO_UINT16(attr_id, p);
768
769     /* Now, add the attribute value */
770     p = add_attr(p, p_seq_end, p_ccb->p_db, p_rec, attr_id, NULL, 0);
771
772     if (!p) {
773       SDP_TRACE_WARNING("SDP - DB full add_attr");
774       return (NULL);
775     }
776   }
777
778   return (p);
779 }
780
781 /*******************************************************************************
782  *
783  * Function         add_record
784  *
785  * Description      This function allocates space for a record from the DB.
786  *
787  * Returns          pointer to next byte in data stream
788  *
789  ******************************************************************************/
790 tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& p_bda) {
791   tSDP_DISC_REC* p_rec;
792
793   /* See if there is enough space in the database */
794   if (p_db->mem_free < sizeof(tSDP_DISC_REC)) return (NULL);
795
796   p_rec = (tSDP_DISC_REC*)p_db->p_free_mem;
797   p_db->p_free_mem += sizeof(tSDP_DISC_REC);
798   p_db->mem_free -= sizeof(tSDP_DISC_REC);
799
800   p_rec->p_first_attr = NULL;
801   p_rec->p_next_rec = NULL;
802
803   p_rec->remote_bd_addr = p_bda;
804
805   /* Add the record to the end of chain */
806   if (!p_db->p_first_rec)
807     p_db->p_first_rec = p_rec;
808   else {
809     tSDP_DISC_REC* p_rec1 = p_db->p_first_rec;
810
811     while (p_rec1->p_next_rec) p_rec1 = p_rec1->p_next_rec;
812
813     p_rec1->p_next_rec = p_rec;
814   }
815
816   return (p_rec);
817 }
818
819 #define SDP_ADDITIONAL_LIST_MASK 0x80
820 /*******************************************************************************
821  *
822  * Function         add_attr
823  *
824  * Description      This function allocates space for an attribute from the DB
825  *                  and copies the data into it.
826  *
827  * Returns          pointer to next byte in data stream
828  *
829  ******************************************************************************/
830 static uint8_t* add_attr(uint8_t* p, uint8_t* p_end, tSDP_DISCOVERY_DB* p_db,
831                          tSDP_DISC_REC* p_rec, uint16_t attr_id,
832                          tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level) {
833   tSDP_DISC_ATTR* p_attr;
834   uint32_t attr_len;
835   uint32_t total_len;
836   uint16_t attr_type;
837   uint16_t id;
838   uint8_t type;
839   uint8_t* p_attr_end;
840   uint8_t is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK;
841
842   nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);
843
844   type = *p++;
845   p = sdpu_get_len_from_type(p, type, &attr_len);
846
847   attr_len &= SDP_DISC_ATTR_LEN_MASK;
848   attr_type = (type >> 3) & 0x0f;
849
850   /* See if there is enough space in the database */
851   if (attr_len > 4)
852     total_len = attr_len - 4 + (uint16_t)sizeof(tSDP_DISC_ATTR);
853   else
854     total_len = sizeof(tSDP_DISC_ATTR);
855
856   p_attr_end = p + attr_len;
857   if (p_attr_end > p_end) {
858     android_errorWriteLog(0x534e4554, "115900043");
859     SDP_TRACE_WARNING("%s: SDP - Attribute length beyond p_end", __func__);
860     return NULL;
861   }
862
863   /* Ensure it is a multiple of 4 */
864   total_len = (total_len + 3) & ~3;
865
866   /* See if there is enough space in the database */
867   if (p_db->mem_free < total_len) return (NULL);
868
869   p_attr = (tSDP_DISC_ATTR*)p_db->p_free_mem;
870   p_attr->attr_id = attr_id;
871   p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
872   p_attr->p_next_attr = NULL;
873
874   /* Store the attribute value */
875   switch (attr_type) {
876     case UINT_DESC_TYPE:
877       if ((is_additional_list != 0) && (attr_len == 2)) {
878         BE_STREAM_TO_UINT16(id, p);
879         if (id != ATTR_ID_PROTOCOL_DESC_LIST)
880           p -= 2;
881         else {
882           /* Reserve the memory for the attribute now, as we need to add
883            * sub-attributes */
884           p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
885           p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
886           total_len = 0;
887
888           /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */
889           if (nest_level >= MAX_NEST_LEVELS) {
890             SDP_TRACE_ERROR("SDP - attr nesting too deep");
891             return p_attr_end;
892           }
893
894           /* Now, add the list entry */
895           p = add_attr(p, p_end, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST,
896                        p_attr, (uint8_t)(nest_level + 1));
897
898           break;
899         }
900       }
901     /* Case falls through */
902
903     case TWO_COMP_INT_DESC_TYPE:
904       switch (attr_len) {
905         case 1:
906           p_attr->attr_value.v.u8 = *p++;
907           break;
908         case 2:
909           BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
910           break;
911         case 4:
912           BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
913           break;
914         default:
915           BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
916           break;
917       }
918       break;
919
920     case UUID_DESC_TYPE:
921       switch (attr_len) {
922         case 2:
923           BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
924           break;
925         case 4:
926           BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
927           if (p_attr->attr_value.v.u32 < 0x10000) {
928             attr_len = 2;
929             p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
930             p_attr->attr_value.v.u16 = (uint16_t)p_attr->attr_value.v.u32;
931           }
932           break;
933         case 16:
934           /* See if we can compress his UUID down to 16 or 32bit UUIDs */
935           if (sdpu_is_base_uuid(p)) {
936             if ((p[0] == 0) && (p[1] == 0)) {
937               p_attr->attr_len_type =
938                   (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2;
939               p += 2;
940               BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
941               p += MAX_UUID_SIZE - 4;
942             } else {
943               p_attr->attr_len_type =
944                   (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4;
945               BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
946               p += MAX_UUID_SIZE - 4;
947             }
948           } else {
949             BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array,
950                                (int32_t)attr_len);
951           }
952           break;
953         default:
954           SDP_TRACE_WARNING("SDP - bad len in UUID attr: %d", attr_len);
955           return p_attr_end;
956       }
957       break;
958
959     case DATA_ELE_SEQ_DESC_TYPE:
960     case DATA_ELE_ALT_DESC_TYPE:
961       /* Reserve the memory for the attribute now, as we need to add
962        * sub-attributes */
963       p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
964       p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
965       total_len = 0;
966
967       /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */
968       if (nest_level >= MAX_NEST_LEVELS) {
969         SDP_TRACE_ERROR("SDP - attr nesting too deep");
970         return p_attr_end;
971       }
972       if (is_additional_list != 0 ||
973           attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS)
974         nest_level |= SDP_ADDITIONAL_LIST_MASK;
975       /* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */
976
977       while (p < p_attr_end) {
978         /* Now, add the list entry */
979         p = add_attr(p, p_end, p_db, p_rec, 0, p_attr,
980                      (uint8_t)(nest_level + 1));
981
982         if (!p) return (NULL);
983       }
984       break;
985
986     case TEXT_STR_DESC_TYPE:
987     case URL_DESC_TYPE:
988       BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
989       break;
990
991     case BOOLEAN_DESC_TYPE:
992       switch (attr_len) {
993         case 1:
994           p_attr->attr_value.v.u8 = *p++;
995           break;
996         default:
997           SDP_TRACE_WARNING("SDP - bad len in boolean attr: %d", attr_len);
998           return p_attr_end;
999       }
1000       break;
1001
1002     default: /* switch (attr_type) */
1003       break;
1004   }
1005
1006   p_db->p_free_mem += total_len;
1007   p_db->mem_free -= total_len;
1008
1009   /* Add the attribute to the end of the chain */
1010   if (!p_parent_attr) {
1011     if (!p_rec->p_first_attr)
1012       p_rec->p_first_attr = p_attr;
1013     else {
1014       tSDP_DISC_ATTR* p_attr1 = p_rec->p_first_attr;
1015
1016       while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
1017
1018       p_attr1->p_next_attr = p_attr;
1019     }
1020   } else {
1021     if (!p_parent_attr->attr_value.v.p_sub_attr) {
1022       p_parent_attr->attr_value.v.p_sub_attr = p_attr;
1023       /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch:0x%x(id:%d)",
1024           p_parent_attr, p_parent_attr->attr_id, p_attr, p_attr->attr_id); */
1025     } else {
1026       tSDP_DISC_ATTR* p_attr1 = p_parent_attr->attr_value.v.p_sub_attr;
1027       /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch1:0x%x(id:%d)",
1028           p_parent_attr, p_parent_attr->attr_id, p_attr1, p_attr1->attr_id); */
1029
1030       while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
1031
1032       p_attr1->p_next_attr = p_attr;
1033       /* SDP_TRACE_DEBUG ("new ch:0x%x(id:%d)", p_attr, p_attr->attr_id); */
1034     }
1035   }
1036
1037   return (p);
1038 }