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

📄 sdp.c

📁 linux下的蓝牙协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2001-2002  Nokia Corporation *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com> *  Copyright (C) 2002-2004  Marcel Holtmann <marcel@holtmann.org> *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation; * *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. *  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY *  CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *  ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,  *  COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS  *  SOFTWARE IS DISCLAIMED. * * *  $Id: sdp.c,v 1.7 2004/07/22 18:08:49 holtmann Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <malloc.h>#include <sys/un.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/l2cap.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <bluetooth/sdp_internal.h>#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB"static uint128_t *bluetooth_base_uuid = NULL;/* Message structure. */struct tupla {	int index;	char *str;};static struct tupla Protocol[] = {	{ SDP_UUID,     "SDP"     },	{ RFCOMM_UUID,  "RFCOMM"  },	{ TCS_BIN_UUID, "TCS-BIN" },	{ L2CAP_UUID,   "L2CAP"   },	{ IP_UUID,      "IP"      },	{ UDP_UUID,     "UDP"     },	{ TCP_UUID,     "TCP"     },	{ TCS_AT_UUID,  "TCS-AT"  },	{ OBEX_UUID,    "OBEX"    },	{ FTP_UUID,     "FTP"     },	{ HTTP_UUID,    "HTTP"    },	{ WSP_UUID,     "WSP"     },	{ BNEP_UUID,    "BNEP"    },	{ HIDP_UUID,    "HIDP"    },	{ CMTP_UUID,    "CMTP"    },	{ 0 }};static struct tupla ServiceClass[] = {	{ SDP_SERVER_SVCLASS_ID,        "SDP Server" },	{ BROWSE_GRP_DESC_SVCLASS_ID,   "Browse Group Descriptor" },	{ PUBLIC_BROWSE_GROUP,          "Public Browse Group" },	{ SERIAL_PORT_SVCLASS_ID,       "Serial Port" },	{ LAN_ACCESS_SVCLASS_ID,        "LAN Access Using PPP" },	{ DIALUP_NET_SVCLASS_ID,        "Dialup Networking" },	{ IRMC_SYNC_SVCLASS_ID,	        "IrMCSync" },	{ OBEX_OBJPUSH_SVCLASS_ID,      "OBEX Object Push" },	{ OBEX_FILETRANS_SVCLASS_ID,    "OBEX File Transfer" },	{ IRMC_SYNC_CMD_SVCLASS_ID,     "IrMCSync Command" },	{ HEADSET_SVCLASS_ID,           "Headset" },	{ CORDLESS_TELEPHONY_SVCLASS_ID,"Cordless Telephony" },	{ INTERCOM_SVCLASS_ID,          "Intercom" },	{ FAX_SVCLASS_ID,               "Fax" },	{ HEADSET_AGW_SVCLASS_ID,       "Headset Audio Gateway" },	{ PNP_INFO_SVCLASS_ID,          "PnP Information" },	{ GENERIC_NETWORKING_SVCLASS_ID,"Generic Networking" },	{ GENERIC_FILETRANS_SVCLASS_ID, "Generic File Transfer" },	{ GENERIC_AUDIO_SVCLASS_ID,     "Generic Audio" },	{ GENERIC_TELEPHONY_SVCLASS_ID, "Generic Telephony" },	{ PANU_SVCLASS_ID,              "PAN user" },	{ NAP_SVCLASS_ID,               "Network access point" },	{ GN_SVCLASS_ID,                "PAN group network" },	{ HID_SVCLASS_ID,               "Human Interface Device" },	{ CIP_SVCLASS_ID,               "Common ISDN Access" },	{ 0 }};static struct tupla Profile[] = {	{ SERIAL_PORT_PROFILE_ID,        "Serial Port" },	{ LAN_ACCESS_PROFILE_ID,         "LAN Access Using PPP" },	{ DIALUP_NET_PROFILE_ID,         "Dialup Networking" },	{ IRMC_SYNC_PROFILE_ID,          "IrMCSync" },	{ OBEX_OBJPUSH_PROFILE_ID,       "OBEX Object Push" },	{ OBEX_FILETRANS_PROFILE_ID,     "OBEX File Transfer" },	{ IRMC_SYNC_CMD_PROFILE_ID,      "IrMCSync Command" },	{ HEADSET_PROFILE_ID,            "Headset" },	{ CORDLESS_TELEPHONY_PROFILE_ID, "Cordless Telephony" },	{ INTERCOM_PROFILE_ID,           "Intercom" },	{ FAX_PROFILE_ID,                "Fax" },	{ HEADSET_AGW_PROFILE_ID,        "Headset Audio Gateway" },	{ PANU_PROFILE_ID,               "PAN user" },	{ NAP_PROFILE_ID,                "PAN access point" },	{ GN_PROFILE_ID,                 "PAN group network" },	{ HID_SVCLASS_ID,                "Human Interface Device" },	{ CIP_SVCLASS_ID,                "Common ISDN Access" },	{ 0 }};static char *string_lookup(struct tupla *pt0, int index){	struct tupla *pt;	for (pt = pt0; pt->index; pt++)		if (pt->index == index) 			return pt->str;	return "";}/* * Prints into a string the Protocol UUID * coping a maximum of n characters. */static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n) {	char *str2;	if (!uuid) {		snprintf(str, n, "NULL");		return -2;	}	switch (uuid->type) {	case SDP_UUID16:		str2 = string_lookup(message, uuid->value.uuid16);		snprintf(str, n, str2);		break;	case SDP_UUID32:		snprintf(str, n, "Error: This is uuid32");		return -3;	case SDP_UUID128:		snprintf(str, n, "Error: This is uuid128");		return -4;	default:		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);		return -1;	}	return 0;}int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n){	return uuid2str(Protocol, uuid, str, n);}int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n){	return uuid2str(ServiceClass, uuid, str, n);}int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n){	return uuid2str(Profile, uuid, str, n);}/* * convert the UUID to string, copying a maximum of n characters. */int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n){	if (!uuid) {		snprintf(str, n, "NULL");		return -2;	}	switch (uuid->type) {	case SDP_UUID16:		snprintf(str, n, "%.4x", uuid->value.uuid16);		break;	case SDP_UUID32:		snprintf(str, n, "%.8x", uuid->value.uuid32);		break;	case SDP_UUID128:{		unsigned int   data0;		unsigned short data1;		unsigned short data2;		unsigned short data3;		unsigned int   data4;		unsigned short data5;		memcpy(&data0, &uuid->value.uuid128.data[0], 4);		memcpy(&data1, &uuid->value.uuid128.data[4], 2);		memcpy(&data2, &uuid->value.uuid128.data[6], 2);		memcpy(&data3, &uuid->value.uuid128.data[8], 2);		memcpy(&data4, &uuid->value.uuid128.data[10], 4);		memcpy(&data5, &uuid->value.uuid128.data[14], 2);		snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", 				ntohl(data0), ntohs(data1), 				ntohs(data2), ntohs(data3), 				ntohl(data4), ntohs(data5));		}		break;	default:		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);		return -1;	// Enum type of UUID not set	}	return 0;}#ifdef SDP_DEBUG/* * Function prints the UUID in hex as per defined syntax - * * 4bytes-2bytes-2bytes-2bytes-6bytes * * There is some ugly code, including hardcoding, but * that is just the way it is converting 16 and 32 bit * UUIDs to 128 bit as defined in the SDP doc */void sdp_uuid_print(const uuid_t *uuid){	if (uuid == NULL) {		SDPERR("Null passed to print UUID\n");		return;	}	if (uuid->type == SDP_UUID16) {		SDPDBG("  uint16_t : 0x%.4x\n", uuid->value.uuid16);	} else if (uuid->type == SDP_UUID32) {		SDPDBG("  uint32_t : 0x%.8x\n", uuid->value.uuid32);	} else if (uuid->type == SDP_UUID128) {		unsigned int data0;		unsigned short data1;		unsigned short data2;		unsigned short data3;		unsigned int data4;		unsigned short data5;		memcpy(&data0, &uuid->value.uuid128.data[0], 4);		memcpy(&data1, &uuid->value.uuid128.data[4], 2);		memcpy(&data2, &uuid->value.uuid128.data[6], 2);		memcpy(&data3, &uuid->value.uuid128.data[8], 2);		memcpy(&data4, &uuid->value.uuid128.data[10], 4);		memcpy(&data5, &uuid->value.uuid128.data[14], 2);		SDPDBG("  uint128_t : 0x%.8x-", ntohl(data0));		SDPDBG("%.4x-", ntohs(data1));		SDPDBG("%.4x-", ntohs(data2));		SDPDBG("%.4x-", ntohs(data3));		SDPDBG("%.8x", ntohl(data4));		SDPDBG("%.4x\n", ntohs(data5));	} else		SDPERR("Enum type of UUID not set\n");}#endifsdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value){	sdp_data_t *seq;	int len = 0;	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));	if (!d)		return NULL;	memset(d, 0, sizeof(sdp_data_t));	d->dtd = dtd;	d->unitSize = sizeof(uint8_t);	switch (dtd) {	case SDP_DATA_NIL:		break;	case SDP_UINT8:		d->val.uint8 = *(uint8_t *)value;		d->unitSize += sizeof(uint8_t);		break;	case SDP_INT8:	case SDP_BOOL:		d->val.int8 = *(int8_t *)value;		d->unitSize += sizeof(int8_t);		break;	case SDP_UINT16:		d->val.uint16 = sdp_get_unaligned((uint16_t *)value);		d->unitSize += sizeof(uint16_t);		break;	case SDP_INT16:		d->val.int16 = sdp_get_unaligned((int16_t *)value);		d->unitSize += sizeof(int16_t);		break;	case SDP_UINT32:		d->val.uint32 = sdp_get_unaligned((uint32_t *)value);		d->unitSize += sizeof(uint32_t);		break;	case SDP_INT32:		d->val.int32 = sdp_get_unaligned((int32_t *)value);		d->unitSize += sizeof(int32_t);		break;	case SDP_INT64:		d->val.int64 = sdp_get_unaligned((int64_t *)value);		d->unitSize += sizeof(int64_t);		break;	case SDP_UINT64:		d->val.uint64 = sdp_get_unaligned((uint64_t *)value);		d->unitSize += sizeof(uint64_t);		break;	case SDP_UINT128:		memcpy(&d->val.uint128.data, value, sizeof(uint128_t));		d->unitSize += sizeof(uint128_t);		break;	case SDP_INT128:		memcpy(&d->val.int128.data, value, sizeof(uint128_t));		d->unitSize += sizeof(uint128_t);		break;	case SDP_UUID16:		sdp_uuid16_create(&d->val.uuid, sdp_get_unaligned((uint16_t *)value));		d->unitSize += sizeof(uint16_t);		break;	case SDP_UUID32:		sdp_uuid32_create(&d->val.uuid, sdp_get_unaligned((uint32_t *)value));		d->unitSize += sizeof(uint32_t);		break;	case SDP_UUID128:		sdp_uuid128_create(&d->val.uuid, value);		d->unitSize += sizeof(uint128_t);		break;	case SDP_URL_STR8:	case SDP_TEXT_STR8:	case SDP_URL_STR16:	case SDP_TEXT_STR16:		if (!value)			goto out_error;		len = strlen(value);		d->unitSize += len;		if (len <= USHRT_MAX) {			d->val.str = (char *)malloc(len + 1);			if (!d->val.str)				goto out_error;			strcpy(d->val.str, value);			if (len <= UCHAR_MAX) {				d->unitSize += sizeof(uint8_t);				if (dtd != SDP_URL_STR8 && dtd != SDP_TEXT_STR8) {					if (dtd == SDP_URL_STR16)						dtd = SDP_URL_STR8;					else						dtd = SDP_TEXT_STR8;				}			} else {				d->unitSize += sizeof(uint16_t);				if (dtd == SDP_TEXT_STR8)					dtd = SDP_TEXT_STR16;				else					dtd = SDP_URL_STR16;			}		} else {			SDPERR("Strings of size > USHRT_MAX not supported\n");			goto out_error;		}		break;	case SDP_URL_STR32:	case SDP_TEXT_STR32:		SDPERR("Strings of size > USHRT_MAX not supported\n");		break;	case SDP_ALT8:	case SDP_ALT16:	case SDP_ALT32:	case SDP_SEQ8:	case SDP_SEQ16:	case SDP_SEQ32:		if (dtd == SDP_ALT8 || dtd == SDP_SEQ8)			d->unitSize += sizeof(uint8_t);		else if (dtd == SDP_ALT16 || dtd == SDP_SEQ16)			d->unitSize += sizeof(uint16_t);		else if (dtd == SDP_ALT32 || dtd == SDP_SEQ32)			d->unitSize += sizeof(uint32_t);		seq = (sdp_data_t *)value;		d->val.dataseq = seq;		for (; seq; seq = seq->next)			d->unitSize += seq->unitSize;		break;	default:		goto out_error;	}	return d;out_error:	free(d);	return NULL;}sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *d){	if (seq) {		sdp_data_t *p;		for (p = seq; p->next; p = p->next);		p->next = d;	} else		seq = d;	d->next = NULL;	return seq;}sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len){	sdp_data_t *curr = NULL, *seq = NULL;	int i;	for (i = 0; i < len; i++) {		sdp_data_t *data;		uint8_t dtd = *(uint8_t *)dtds[i];		if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32)			data = (sdp_data_t *)values[i];		else			data = sdp_data_alloc(dtd, values[i]);		if (!data)			return NULL;		if (curr)			curr->next = data;		else			seq = data;		curr = data;	}	return sdp_data_alloc(SDP_SEQ8, seq);}int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d){	sdp_data_t *p = sdp_data_get(rec, attr);	if (p)		return -1;	d->attrId = attr;	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func);	return 0;}void sdp_attr_remove(sdp_record_t *rec, uint16_t attr){	sdp_data_t *d = sdp_data_get(rec, attr);	if (d)		rec->attrlist = sdp_list_remove(rec->attrlist, d);}void sdp_set_seq_len(char *ptr, int length){	uint8_t dtd = *(uint8_t *)ptr++;	switch (dtd) {	case SDP_SEQ8:	case SDP_ALT8:	case SDP_TEXT_STR8:	case SDP_URL_STR8:		*(uint8_t *)ptr = (uint8_t)length;		break;	case SDP_SEQ16:	case SDP_ALT16:	case SDP_TEXT_STR16:	case SDP_URL_STR16:		sdp_put_unaligned(htons(length), (uint16_t *)ptr);		break;	case SDP_SEQ32:	case SDP_ALT32:	case SDP_TEXT_STR32:	case SDP_URL_STR32:		sdp_put_unaligned(htons(length), (uint32_t *)ptr);		break;	}}int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd){	int orig = buf->data_size;	uint8_t *p = buf->data + buf->data_size;	*p++ = dtd;	buf->data_size += sizeof(uint8_t);	switch (dtd) {	case SDP_SEQ8:	case SDP_TEXT_STR8:	case SDP_URL_STR8:	case SDP_ALT8:		buf->data_size += sizeof(uint8_t);		break;	case SDP_SEQ16:	case SDP_TEXT_STR16:	case SDP_URL_STR16:	case SDP_ALT16:		buf->data_size += sizeof(uint16_t);		break;	case SDP_SEQ32:	case SDP_TEXT_STR32:	case SDP_URL_STR32:	case SDP_ALT32:		buf->data_size += sizeof(uint32_t);		break;	}	return buf->data_size - orig;}void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr){	uint8_t *p = buf->data;	// data type for attr	*p++ = SDP_UINT16;	buf->data_size = sizeof(uint8_t);	sdp_put_unaligned(htons(attr), (uint16_t *)p);	p += sizeof(uint16_t);	buf->data_size += sizeof(uint16_t);}

⌨️ 快捷键说明

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