/* * The matching process is defined as "each and every UUID * specified in the "search pattern" must be present in the * "target pattern". Here "search pattern" is the set of UUIDs * specified by the service discovery client and "target pattern" * is the set of UUIDs present in a service record. * * Return 1 if each and every UUID in the search * pattern exists in the target pattern, 0 if the * match succeeds and -1 on error. */ static int sdp_match_uuid(sdp_list_t *search, sdp_list_t *pattern) { /* * The target is a sorted list, so we need not look * at all elements to confirm existence of an element * from the search pattern */ int patlen = sdp_list_len(pattern); if (patlen < sdp_list_len(search)) return -1; for (; search; search = search->next) { uuid_t *uuid128; void *data = search->data; sdp_list_t *list; if (data == NULL) return -1; // create 128-bit form of the search UUID uuid128 = sdp_uuid_to_uuid128((uuid_t *)data); list = sdp_list_find(pattern, uuid128, sdp_uuid128_cmp); bt_free(uuid128); if (!list) return 0; } return 1; }
/* * Extract attribute identifiers from the request PDU. * Clients could request a subset of attributes (by id) * from a service record, instead of the whole set. The * requested identifiers are present in the PDU form of * the request */ static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, sdp_buf_t *buf) { sdp_buf_t pdu; if (!rec) return SDP_INVALID_RECORD_HANDLE; if (seq) { SDPDBG("Entries in attr seq : %d", sdp_list_len(seq)); } else { SDPDBG("NULL attribute descriptor"); } if (seq == NULL) { SDPDBG("Attribute sequence is NULL"); return 0; } sdp_gen_record_pdu(rec, &pdu); for (; seq; seq = seq->next) { struct attrid *aid = seq->data; SDPDBG("AttrDataType : %d", aid->dtd); if (aid->dtd == SDP_UINT16) { uint16_t attr = bt_get_unaligned((uint16_t *)&aid->uint16); sdp_data_t *a = (sdp_data_t *)sdp_data_get(rec, attr); if (a) sdp_append_to_pdu(buf, a); } else if (aid->dtd == SDP_UINT32) { uint32_t range = bt_get_unaligned((uint32_t *)&aid->uint32); uint16_t attr; uint16_t low = (0xffff0000 & range) >> 16; uint16_t high = 0x0000ffff & range; sdp_data_t *data; SDPDBG("attr range : 0x%x", range); SDPDBG("Low id : 0x%x", low); SDPDBG("High id : 0x%x", high); if (low == 0x0000 && high == 0xffff && pdu.data_size <= buf->buf_size) { /* copy it */ memcpy(buf->data, pdu.data, pdu.data_size); buf->data_size = pdu.data_size; break; } /* (else) sub-range of attributes */ for (attr = low; attr < high; attr++) { data = sdp_data_get(rec, attr); if (data) sdp_append_to_pdu(buf, data); } data = sdp_data_get(rec, high); if (data) sdp_append_to_pdu(buf, data); } else {
/* * 100% taken from bluez-utils (sdptool) */ static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto) { sdp_data_t *seq = NULL; void *dtds[10], *values[10]; void **seqDTDs, **seqs; int i, seqlen; sdp_list_t *p; seqlen = sdp_list_len(proto); seqDTDs = (void **)malloc(seqlen * sizeof(void *)); seqs = (void **)malloc(seqlen * sizeof(void *)); for (i = 0, p = proto; p; p = p->next, i++) { sdp_list_t *elt = (sdp_list_t *)p->data; sdp_data_t *s; int pslen = 0; for (; elt && pslen < sizeof(dtds); elt = elt->next, pslen++) { sdp_data_t *d = (sdp_data_t *)elt->data; dtds[pslen] = &d->dtd; switch (d->dtd) { case SDP_UUID16: values[pslen] = &((uuid_t *)d)->value.uuid16; break; case SDP_UUID32: values[pslen] = &((uuid_t *)d)->value.uuid32; break; case SDP_UUID128: values[pslen] = &((uuid_t *)d)->value.uuid128; break; case SDP_UINT8: values[pslen] = &d->val.uint8; break; case SDP_UINT16: values[pslen] = &d->val.uint16; break; case SDP_SEQ8: case SDP_SEQ16: case SDP_SEQ32: values[pslen] = d; break; // FIXME: more } } s = sdp_seq_alloc(dtds, values, pslen); if (s) { seqDTDs[i] = &s->dtd; seqs[i] = s; } } seq = sdp_seq_alloc(seqDTDs, seqs, seqlen); free(seqDTDs); free(seqs); return seq; }
/* * Extract attribute identifiers from the request PDU. * Clients could request a subset of attributes (by id) * from a service record, instead of the whole set. The * requested identifiers are present in the PDU form of * the request */ static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, uint8_t dtd, sdp_buf_t *buf) { if (!rec) return SDP_INVALID_RECORD_HANDLE; #ifdef SDP_DEBUG if (seq) SDPDBG("Entries in attr seq : %d\n", sdp_list_len(seq)); else SDPDBG("NULL attribute descriptor\n"); SDPDBG("AttrDataType : %d\n", dtd); #endif if (seq == NULL) { SDPDBG("Attribute sequence is NULL\n"); return 0; } if (dtd == SDP_UINT16) for (; seq; seq = seq->next) { uint16_t attr = sdp_get_unaligned((uint16_t *)seq->data); sdp_data_t *a = (sdp_data_t *)sdp_data_get(rec, attr); if (a) sdp_append_to_pdu(buf, a); } else if (dtd == SDP_UINT32) { sdp_buf_t pdu; sdp_gen_record_pdu(rec, &pdu); for (; seq; seq = seq->next) { uint32_t range = sdp_get_unaligned((uint32_t *)seq->data); uint16_t attr; uint16_t low = (0xffff0000 & range) >> 16; uint16_t high = 0x0000ffff & range; SDPDBG("attr range : 0x%x\n", range); SDPDBG("Low id : 0x%x\n", low); SDPDBG("High id : 0x%x\n", high); if (low == 0x0000 && high == 0xffff && pdu.data_size <= buf->buf_size) { /* copy it */ memcpy(buf->data, pdu.data, pdu.data_size); buf->data_size = pdu.data_size; break; } /* (else) sub-range of attributes */ for (attr = low; attr <= high; attr++) { sdp_data_t *a = (sdp_data_t *)sdp_data_get(rec, attr); if (a) sdp_append_to_pdu(buf, a); } } free(pdu.data); } else {