📄 request.c
字号:
errno = EINVAL; return 0; } reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); if (!reqbuf || !rspbuf) { errno = ENOMEM; status = -1; goto end; } memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t)); reqhdr = (sdp_pdu_hdr_t *)reqbuf; reqhdr->pdu_id = SDP_SVC_ATTR_REQ; pdata = reqbuf + sizeof(sdp_pdu_hdr_t); reqsize = sizeof(sdp_pdu_hdr_t); // add the service record handle sdp_put_unaligned(htonl(handle), (uint32_t *)pdata); reqsize += sizeof(uint32_t); pdata += sizeof(uint32_t); // specify the response limit sdp_put_unaligned(htons(65535), (uint16_t *)pdata); reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); // get attr seq PDU form seqlen = gen_attridseq_pdu(pdata, attrids, reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32); if (seqlen == -1) { errno = EINVAL; status = -1; goto end; } pdata += seqlen; reqsize += seqlen; SDPDBG("Attr list length : %d\n", seqlen); // save before Continuation State _pdata = pdata; _reqsize = reqsize; do { // add NULL continuation state reqsize = _reqsize + copy_cstate(_pdata, cstate); // set the request header's param length reqhdr->tid = htons(sdp_gen_tid(session)); reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); if (status < 0) goto end; rsp_count = 0; rsphdr = (sdp_pdu_hdr_t *)rspbuf; if (rsphdr->pdu_id == SDP_ERROR_RSP) { SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id); status = -1; goto end; } pdata = rspbuf + sizeof(sdp_pdu_hdr_t); rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); attr_list_len += rsp_count; pdata += sizeof(uint16_t); // if continuation state set need to re-issue request before parsing cstate_len = *(uint8_t *)(pdata + rsp_count); SDPDBG("Response id : %d\n", rsphdr->pdu_id); SDPDBG("Attrlist byte count : %d\n", rsp_count); SDPDBG("sdp_cstate_t length : %d\n", cstate_len); /* * a split response: concatenate intermediate responses * and the last one (which has cstate_len == 0) */ if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { char *targetPtr = NULL; cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0; // build concatenated response buffer rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; memcpy(targetPtr, pdata, rsp_count); rsp_concat_buf.data_size += rsp_count; } } while (cstate); if (attr_list_len > 0) { int scanned = 0; if (rsp_concat_buf.data_size != 0) pdata = rsp_concat_buf.data; rec = sdp_extract_pdu(pdata, &scanned); if (!rec) status = -1; } end: if (reqbuf) free(reqbuf); if (rsp_concat_buf.data) free(rsp_concat_buf.data); if (rspbuf) free(rspbuf); return rec;}/* * This is a service search request combined with the service * attribute request. First a service class match is done and * for matching service, requested attributes are extracted * * INPUT : * * sdp_list_t *search * Singly linked list containing elements of the search * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16) * of the service to be searched * * AttributeSpecification attrSpec * Attribute identifiers are 16 bit unsigned integers specified * in one of 2 ways described below : * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers * They are the actual attribute identifiers in ascending order * * SDP_ATTR_REQ_RANGE - 32bit identifier range * The high-order 16bits is the start of range * the low-order 16bits are the end of range * 0x0000 to 0xFFFF gets all attributes * * sdp_list_t *attrids * Singly linked list containing attribute identifiers desired. * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) * * OUTPUT : * int return value * 0: * The request completed successfully. This does not * mean the requested services were found * -1: * On any error and sets errno * * sdp_list_t **rsp * This variable is set on a successful return to point to * service(s) found. Each element of this list is of type * sdp_record_t* (of the services which matched the search list) */int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrids, sdp_list_t **rsp){ int status = 0; int reqsize = 0, _reqsize; int rspsize = 0; int seqlen = 0, attr_list_len = 0; int rsp_count = 0, cstate_len = 0; char *pdata, *_pdata; char *reqbuf, *rspbuf; sdp_pdu_hdr_t *reqhdr, *rsphdr; uint8_t dataType; sdp_list_t *rec_list = NULL; sdp_buf_t rsp_concat_buf; sdp_cstate_t *cstate = NULL; if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) { errno = EINVAL; return -1; } reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); if (!reqbuf || !rspbuf) { errno = ENOMEM; status = -1; goto end; } memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t)); reqhdr = (sdp_pdu_hdr_t *)reqbuf; reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ; // generate PDU pdata = reqbuf + sizeof(sdp_pdu_hdr_t); reqsize = sizeof(sdp_pdu_hdr_t); // add service class IDs for search seqlen = gen_searchseq_pdu(pdata, search); SDPDBG("Data seq added : %d\n", seqlen); // now set the length and increment the pointer reqsize += seqlen; pdata += seqlen; sdp_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *)pdata); reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); // get attr seq PDU form seqlen = gen_attridseq_pdu(pdata, attrids, reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16: SDP_UINT32); if (seqlen == -1) { status = EINVAL; goto end; } pdata += seqlen; SDPDBG("Attr list length : %d\n", seqlen); reqsize += seqlen; *rsp = 0; // save before Continuation State _pdata = pdata; _reqsize = reqsize; do { reqhdr->tid = htons(sdp_gen_tid(session)); // add continuation state (can be null) reqsize = _reqsize + copy_cstate(_pdata, cstate); // set the request header's param length reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); rsphdr = (sdp_pdu_hdr_t *)rspbuf; status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); if (status < 0) { SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); goto end; } if (rsphdr->pdu_id == SDP_ERROR_RSP) { status = -1; goto end; } pdata = rspbuf + sizeof(sdp_pdu_hdr_t); rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); attr_list_len += rsp_count; pdata += sizeof(uint16_t); // pdata points to attribute list cstate_len = *(uint8_t *)(pdata + rsp_count); SDPDBG("Attrlist byte count : %d\n", attr_list_len); SDPDBG("Response byte count : %d\n", rsp_count); SDPDBG("Cstate length : %d\n", cstate_len); /* * This is a split response, need to concatenate intermediate * responses and the last one which will have cstate_len == 0 */ if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { char *targetPtr = NULL; cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0; // build concatenated response buffer rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; memcpy(targetPtr, pdata, rsp_count); rsp_concat_buf.data_size += rsp_count; } } while (cstate); if (attr_list_len > 0) { int scanned = 0; if (rsp_concat_buf.data_size != 0) pdata = rsp_concat_buf.data; /* * Response is a sequence of sequence(s) for one or * more data element sequence(s) representing services * for which attributes are returned */ scanned = sdp_extract_seqtype(pdata, &dataType, &seqlen); SDPDBG("Bytes scanned : %d\n", scanned); SDPDBG("Seq length : %d\n", seqlen); if (scanned && seqlen) { pdata += scanned; do { int recsize = 0; sdp_record_t *rec = sdp_extract_pdu(pdata, &recsize); if (rec == NULL) { SDPERR("SVC REC is null\n"); status = -1; goto end; } scanned += recsize; pdata += recsize; SDPDBG("Loc seq length : %d\n", recsize); SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle); SDPDBG("Bytes scanned : %d\n", scanned); SDPDBG("Attrlist byte count : %d\n", attr_list_len); rec_list = sdp_list_append(rec_list, rec); } while (scanned < attr_list_len); SDPDBG("Successful scan of service attr lists\n"); *rsp = rec_list; } } end: if (rsp_concat_buf.data) free(rsp_concat_buf.data); if (reqbuf) free(reqbuf); if (rspbuf) free(rspbuf); return status;}/* * Find devices in the piconet. */int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *found){ int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0); if (n < 0) { SDPERR("Inquiry failed:%s", strerror(errno)); return -1; } *found = n; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -