📄 sdp.c
字号:
else SDPDBG("NULL value\n"); SDPDBG("=====================================\n");}void sdp_print_service_attr(sdp_list_t *svcAttrList){ SDPDBG("Printing service attr list %p\n", svcAttrList); sdp_list_foreach(svcAttrList, attr_print_func, NULL); SDPDBG("Printed service attr list %p\n", svcAttrList);}#endifsdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned){ int extracted = 0, seqlen = 0; uint8_t dtd; uint16_t attr; sdp_record_t *rec = sdp_record_alloc(); const uint8_t *p = buf; *scanned = sdp_extract_seqtype(buf, &dtd, &seqlen); p += *scanned; rec->attrlist = NULL; while (extracted < seqlen) { int n = sizeof(uint8_t), attrlen = 0; sdp_data_t *data = NULL; SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, extracted); dtd = *(uint8_t *) p; attr = ntohs(bt_get_unaligned((uint16_t *) (p + n))); n += sizeof(uint16_t); SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr); data = sdp_extract_attr(p + n, &attrlen, rec); SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen); n += attrlen; if (data == NULL) { SDPDBG("Terminating extraction of attributes"); break; } if (attr == SDP_ATTR_RECORD_HANDLE) rec->handle = data->val.uint32; extracted += n; p += n; sdp_attr_replace(rec, attr, data); SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d", seqlen, extracted); }#ifdef SDP_DEBUG SDPDBG("Successful extracting of Svc Rec attributes\n"); sdp_print_service_attr(rec->attrlist);#endif *scanned += seqlen; return rec;}#ifdef SDP_DEBUGstatic void print_dataseq(sdp_data_t *p){ sdp_data_t *d; for (d = p; d; d = d->next) sdp_data_print(d);}#endifvoid sdp_record_print(const sdp_record_t *rec){ sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); if (d) printf("Service Name: %s\n", d->val.str); d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY); if (d) printf("Service Description: %s\n", d->val.str); d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY); if (d) printf("Service Provider: %s\n", d->val.str);}#ifdef SDP_DEBUGvoid sdp_data_print(sdp_data_t *d){ switch (d->dtd) { case SDP_DATA_NIL: SDPDBG("NIL\n"); break; case SDP_BOOL: case SDP_UINT8: case SDP_UINT16: case SDP_UINT32: case SDP_UINT64: case SDP_UINT128: case SDP_INT8: case SDP_INT16: case SDP_INT32: case SDP_INT64: case SDP_INT128: SDPDBG("Integer : 0x%x\n", d->val.uint32); break; case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: SDPDBG("UUID\n"); sdp_uuid_print(&d->val.uuid); break; case SDP_TEXT_STR8: case SDP_TEXT_STR16: case SDP_TEXT_STR32: SDPDBG("Text : %s\n", d->val.str); break; case SDP_URL_STR8: case SDP_URL_STR16: case SDP_URL_STR32: SDPDBG("URL : %s\n", d->val.str); break; case SDP_SEQ8: case SDP_SEQ16: case SDP_SEQ32: print_dataseq(d->val.dataseq); break; case SDP_ALT8: case SDP_ALT16: case SDP_ALT32: SDPDBG("Data Sequence Alternates\n"); print_dataseq(d->val.dataseq); break; }}#endifsdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId){ if (rec->attrlist) { sdp_data_t sdpTemplate; sdp_list_t *p; sdpTemplate.attrId = attrId; p = sdp_list_find(rec->attrlist, &sdpTemplate, sdp_attrid_comp_func); if (p) return (sdp_data_t *)p->data; } return 0;}/* * Extract the sequence type and its length, and return offset into buf * or 0 on failure. */int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *size){ uint8_t dtd = *(uint8_t *) buf; int scanned = sizeof(uint8_t); buf += sizeof(uint8_t); *dtdp = dtd; switch (dtd) { case SDP_SEQ8: case SDP_ALT8: *size = *(uint8_t *) buf; scanned += sizeof(uint8_t); break; case SDP_SEQ16: case SDP_ALT16: *size = ntohs(bt_get_unaligned((uint16_t *) buf)); scanned += sizeof(uint16_t); break; case SDP_SEQ32: case SDP_ALT32: *size = ntohl(bt_get_unaligned((uint32_t *) buf)); scanned += sizeof(uint32_t); break; default: SDPERR("Unknown sequence type, aborting\n"); return 0; } return scanned;}int sdp_send_req(sdp_session_t *session, uint8_t *buf, uint32_t size){ uint32_t sent = 0; while (sent < size) { int n = send(session->sock, buf + sent, size - sent, 0); if (n < 0) return -1; sent += n; } return 0;}int sdp_read_rsp(sdp_session_t *session, uint8_t *buf, uint32_t size){ fd_set readFds; struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 }; FD_ZERO(&readFds); FD_SET(session->sock, &readFds); SDPDBG("Waiting for response\n"); if (select(session->sock + 1, &readFds, NULL, NULL, &timeout) == 0) { SDPERR("Client timed out\n"); errno = ETIMEDOUT; return -1; } return recv(session->sock, buf, size, 0);}/* * generic send request, wait for response method. */int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *reqbuf, uint8_t *rspbuf, uint32_t reqsize, uint32_t *rspsize){ int n; sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)reqbuf; sdp_pdu_hdr_t *rsphdr = (sdp_pdu_hdr_t *)rspbuf; SDPDBG(""); if (0 > sdp_send_req(session, reqbuf, reqsize)) { SDPERR("Error sending data:%s", strerror(errno)); return -1; } n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); if (0 > n) return -1; SDPDBG("Read : %d\n", n); if (n == 0 || reqhdr->tid != rsphdr->tid) { errno = EPROTO; return -1; } *rspsize = n; return 0;}/* * singly-linked lists (after openobex implementation) */sdp_list_t *sdp_list_append(sdp_list_t *p, void *d){ sdp_list_t *q, *n = (sdp_list_t *)malloc(sizeof(sdp_list_t)); if (!n) return 0; n->data = d; n->next = 0; if (!p) return n; for (q = p; q->next; q = q->next); q->next = n; return p;}sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d){ sdp_list_t *p, *q; for (q = 0, p = list; p; q = p, p = p->next) if (p->data == d) { if (q) q->next = p->next; else list = p->next; free(p); break; } return list;}sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *d, sdp_comp_func_t f){ sdp_list_t *q, *p, *n; n = (sdp_list_t *)malloc(sizeof(sdp_list_t)); if (!n) return 0; n->data = d; for (q = 0, p = list; p; q = p, p = p->next) if (f(p->data, d) >= 0) break; // insert between q and p; if !q insert at head if (q) q->next = n; else list = n; n->next = p; return list;}/* * Every element of the list points to things which need * to be free()'d. This method frees the list's contents */void sdp_list_free(sdp_list_t *list, sdp_free_func_t f){ sdp_list_t *next; while (list) { next = list->next; if (f) f(list->data); free(list); list = next; }}static inline int __find_port(sdp_data_t *seq, int proto){ if (!seq || !seq->next) return 0; if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) { seq = seq->next; switch (seq->dtd) { case SDP_UINT8: return seq->val.uint8; case SDP_UINT16: return seq->val.uint16; } } return 0;}int sdp_get_proto_port(const sdp_list_t *list, int proto){ if (proto != L2CAP_UUID && proto != RFCOMM_UUID) { errno = EINVAL; return -1; } for (; list; list = list->next) { sdp_list_t *p; for (p = list->data; p; p = p->next) { sdp_data_t *seq = (sdp_data_t *) p->data; int port = __find_port(seq, proto); if (port) return port; } } return 0;}sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto){ for (; list; list = list->next) { sdp_list_t *p; for (p = list->data; p; p = p->next) { sdp_data_t *seq = (sdp_data_t *) p->data; if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) return seq->next; } } return NULL;}int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap){ sdp_data_t *pdlist, *curr; sdp_list_t *ap = 0; pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST); if (pdlist == NULL) { errno = ENODATA; return -1; } SDPDBG("AP type : 0%x\n", pdlist->dtd); for (; pdlist; pdlist = pdlist->next) { sdp_list_t *pds = 0; for (curr = pdlist->val.dataseq; curr; curr = curr->next) pds = sdp_list_append(pds, curr->val.dataseq); ap = sdp_list_append(ap, pds); } *pap = ap; return 0;}int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap){ sdp_data_t *pdlist, *curr; sdp_list_t *ap = 0; pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); if (pdlist == NULL) { errno = ENODATA; return -1; } SDPDBG("AP type : 0%x\n", pdlist->dtd); pdlist = pdlist->val.dataseq; for (; pdlist; pdlist = pdlist->next) { sdp_list_t *pds = 0; for (curr = pdlist->val.dataseq; curr; curr = curr->next) pds = sdp_list_append(pds, curr->val.dataseq); ap = sdp_list_append(ap, pds); } *pap = ap; return 0;}int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp){ sdp_data_t *sdpdata = sdp_data_get(rec, attr); *seqp = NULL; if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) { sdp_data_t *d; for (d = sdpdata->val.dataseq; d; d = d->next) { uuid_t *u = (uuid_t *)malloc(sizeof(uuid_t)); memset((char *)u, 0, sizeof(uuid_t)); if (d->dtd >= SDP_UUID16 && d->dtd <= SDP_UUID128) { *u = d->val.uuid; *seqp = sdp_list_append(*seqp, u); } else goto fail; } return 0; }fail: sdp_list_free(*seqp, free); errno = EINVAL; return -1;}int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq){ int status = 0, i, len; void **dtds, **values; uint8_t uuid16 = SDP_UUID16; uint8_t uuid32 = SDP_UUID32; uint8_t uuid128 = SDP_UUID128; sdp_list_t *p; len = sdp_list_len(seq); if (!seq || len == 0) return -1; dtds = (void **)malloc(len * sizeof(void *)); values = (void **)malloc(len * sizeof(void *)); for (p = seq, i = 0; i < len; i++, p = p->next) { uuid_t *uuid = (uuid_t *)p->data; if (uuid) switch (uuid->type) { case SDP_UUID16: dtds[i] = &uuid16; values[i] = &uuid->value.uuid16; break; case SDP_UUID32: dtds[i] = &uuid32; values[i] = &uuid->value.uuid32; break; case SDP_UUID128: dtds[i] = &uuid128; values[i] = &uuid->value.uuid128; break; default: status = -1; break; } else { status = -1; break; } } if (status == 0) { sdp_data_t *data = sdp_seq_alloc(dtds, values, len); sdp_attr_replace(rec, aid, data); sdp_pattern_add_uuidseq(rec, seq); } free(dtds); free(values); return status;}int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq){ sdp_lang_attr_t *lang; sdp_data_t *sdpdata, *curr_data; *langSeq = NULL; sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST); if (sdpdata == NULL) { errno = ENODATA; return -1; } curr_data = sdpdata->val.dataseq; while (curr_data) { sdp_data_t *pCode = curr_data; sdp_data_t *pEncoding = pCode->next; sdp_data_t *pOffset = pEncoding->next; if (pCode && pEncoding && pOffset) { lang = (sdp_lang_attr_t *)malloc(sizeof(sdp_lang_attr_t)); lang->code_ISO639 = pCode->val.uint16; lang->encoding = pEncoding->val.uint16; lang->base_offset = pOffset->val.uint16; SDPDBG("code_ISO639 : 0x%02x\n", lang->code_ISO639); SDPDBG("encoding : 0x%02x\n", lang->encoding); SDPDBG("base_offfset : 0x%02x\n", lang->base_offset); *langSeq = sdp_list_append(*langSeq, lang); } curr_data = pOffset->next; } return 0;}int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq){ sdp_profile_desc_t *profDesc; sdp_data_t *sdpdata, *seq; *profDescSeq = NULL; sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST); if (!sdpdata || !sdpdata->val.dataseq) { errno = ENODATA; return -1; } for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) { uuid_t *uuid = NULL; uint16_t version = 0x100; if (SDP_IS_UUID(seq->dtd)) { uuid = &seq->val.uuid; } else { sdp_data_t *puuid = seq->val.dataseq; sdp_data_t *pVnum = seq->val.dataseq->next; if (puuid && pVnum) { uuid = &puuid->val.uuid; version = pVnum->val.uint16; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -