⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdp.c

📁 linux下的蓝牙协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
}#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 char *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(sdp_get_unaligned((uint16_t *)buf));		scanned += sizeof(uint16_t);		break;	case SDP_SEQ32:	case SDP_ALT32:		*size = ntohl(sdp_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, char *buf, int size){	int 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, char *buf, int size){	fd_set readFds;	struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 };	FD_SET(session->sock, &readFds);	SDPDBG("Waiting for response\n");	if (0 == select(session->sock + 1, &readFds, NULL, NULL, &timeout)) {		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, char *reqbuf, char *rspbuf, int reqsize, int *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) {		sdp_data_t *uuid = seq->val.dataseq;		sdp_data_t *pVnum = seq->val.dataseq->next;		if (uuid && pVnum) {			profDesc = (sdp_profile_desc_t *)malloc(sizeof(sdp_profile_desc_t));			profDesc->uuid = uuid->val.uuid;			profDesc->version = pVnum->val.uint16;#ifdef SDP_DEBUG			sdp_uuid_print(&profDesc->uuid);			SDPDBG("Vnum : 0x%04x\n", profDesc->version);#endif			*profDescSeq = sdp_list_append(*profDescSeq, profDesc);		}	}	return 0;}int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16){	sdp_data_t *d, *curr;	*u16 = NULL;	d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST);	if (d == NULL) {		errno = ENODATA;		return -1;	}	for (curr = d->val.dataseq; curr; curr = curr->next)		*u16 = sdp_list_append(*u16, &curr->val.uint16);	return 0;}/* flexible extraction of basic attributes - Jean II *//* How do we expect caller to extract predefined data sequences? */int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value){	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);	if (sdpdata)		/* Verify that it is what the caller expects */		if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 ||		sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 ||		sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 ||		sdpdata->dtd == SDP_INT32) {			*value = sdpdata->val.uint32;			return 0;		}	errno = EINVAL;	return -1;}int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, int valuelen){	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);	if (sdpdata)		/* Verify that it is what the caller expects */		if (sdpdata->dtd == SDP_TEXT_STR8 || sdpdata->dtd == SDP_TEXT_STR16 || sdpdata->dtd == SDP_TEXT_STR32)			if (strlen(sdpdata->val.str) < valuelen) {				strcpy(value, sdpdata->val.str);				return 0;			}	errno = EINVAL;	return -1;}#define get_basic_attr(attrID, pAttrValue, fieldName)		\	sdp_data_t *data = sdp_data_get(rec, attrID);		\	if (data) {						\		*pAttrValue = data->val.fieldName;		\		return 0;					\	}							\	errno = EINVAL;						\	return -1;int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid){	get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid);}int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid){	get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid);}int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState){	get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32);}int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail){	get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8);}int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo){	get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32);}int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState){	get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32);}/* * NOTE that none of the setXXX() functions below will * actually update the SDP server, unless the * {register, update}sdp_record_t() function is invoked. */int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *value){	sdp_data_t *d = sdp_data_alloc(dtd, value);	if (d) {		sdp_attr_replace(rec, attr, d);		return 0;	}	return -1;}/* * Set the information attributes of the service * pointed to by rec. The attributes are * service name, description and provider name */void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc){	if (name)		sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY, SDP_TEXT_STR8, (void *)name);	if (prov)		sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY, SDP_TEXT_STR8, (void *)prov);	if (desc)		sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY, SDP_TEXT_STR8, (void *)desc);}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];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -