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

📄 dbus-sdp.c

📁 实现bluez蓝牙profile需要的库
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (err) {		if (ctxt->call) {			get_record_data_call_cb(ctxt->call, NULL, err);			get_record_data_free(ctxt->call);		} else			error_failed(ctxt->conn, ctxt->rq, err);		transaction_context_free(ctxt, FALSE);	}	return TRUE;}static void remote_svc_rec_completed_cb(uint8_t type, uint16_t err,			uint8_t *rsp, size_t size, void *udata){	struct transaction_context *ctxt = udata;	sdp_record_t *rec = NULL;	DBusMessage *reply;	DBusMessageIter iter, array_iter;	const char *src, *dst;	int scanned;	if (!ctxt)		return;	if (err == 0xffff) {		/* Check for protocol error or I/O error */		int sdp_err = sdp_get_error(ctxt->session);		if (sdp_err < 0) {			error("search failed: Invalid session!");			error_failed(ctxt->conn, ctxt->rq, EINVAL);			goto failed;		}		error("search failed: %s (%d)", strerror(sdp_err), sdp_err);		error_failed(ctxt->conn, ctxt->rq, sdp_err);		goto failed;	}	if (type == SDP_ERROR_RSP) {		error_sdp_failed(ctxt->conn, ctxt->rq, err);		goto failed;	}	/* check response PDU ID */	if (type != SDP_SVC_ATTR_RSP) {		error("SDP error: %s (%d)", strerror(EPROTO), EPROTO);		error_failed(ctxt->conn, ctxt->rq, EPROTO);		goto failed;	}	dbus_message_get_args(ctxt->rq, NULL,			DBUS_TYPE_STRING, &dst,			DBUS_TYPE_INVALID);	src = get_address_from_message(ctxt->conn, ctxt->rq);	reply = dbus_message_new_method_return(ctxt->rq);	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_TYPE_BYTE_AS_STRING, &array_iter);	rec = sdp_extract_pdu(rsp, &scanned);	if (rec == NULL) {		error("SVC REC is null");		goto done;	}	sdp_store_record(src, dst, rec->handle, rsp, size);	sdp_record_free(rec);	dbus_message_iter_append_fixed_array(&array_iter,			DBUS_TYPE_BYTE, &rsp, size);done:	dbus_message_iter_close_container(&iter, &array_iter);	send_message_and_unref(ctxt->conn, reply);failed:	transaction_context_free(ctxt, TRUE);}static void remote_svc_rec_completed_xml_cb(uint8_t type, uint16_t err,						uint8_t *rsp, size_t size,						void *udata){	struct transaction_context *ctxt = udata;	sdp_record_t *rec = NULL;	DBusMessage *reply;	const char *src, *dst;	int scanned;	sdp_buf_t result;	if (!ctxt)		return;	if (err == 0xffff) {		/* Check for protocol error or I/O error */		int sdp_err = sdp_get_error(ctxt->session);		if (sdp_err < 0) {			error("search failed: Invalid session!");			error_failed(ctxt->conn, ctxt->rq, EINVAL);			goto failed;		}		error("search failed: %s (%d)", strerror(sdp_err), sdp_err);		error_failed(ctxt->conn, ctxt->rq, sdp_err);		goto failed;	}	if (type == SDP_ERROR_RSP) {		error_sdp_failed(ctxt->conn, ctxt->rq, err);		goto failed;	}	/* check response PDU ID */	if (type != SDP_SVC_ATTR_RSP) {		error("SDP error: %s (%d)", strerror(EPROTO), EPROTO);		error_failed(ctxt->conn, ctxt->rq, EPROTO);		goto failed;	}	dbus_message_get_args(ctxt->rq, NULL,			DBUS_TYPE_STRING, &dst,			DBUS_TYPE_INVALID);	src = get_address_from_message(ctxt->conn, ctxt->rq);	reply = dbus_message_new_method_return(ctxt->rq);		rec = sdp_extract_pdu(rsp, &scanned);	if (rec == NULL) {		error("SVC REC is null");		goto done;	}	sdp_store_record(src, dst, rec->handle, rsp, size);	memset(&result, 0, sizeof(sdp_buf_t));	convert_sdp_record_to_xml(rec, &result, append_and_grow_string);	sdp_record_free(rec);	if (result.data) {		dbus_message_append_args(reply,				DBUS_TYPE_STRING, &result.data,				DBUS_TYPE_INVALID);		free(result.data);	}done:	send_message_and_unref(ctxt->conn, reply);failed:	transaction_context_free(ctxt, TRUE);}static void remote_svc_handles_completed_cb(uint8_t type, uint16_t err,			uint8_t *rsp, size_t size, void *udata){	struct transaction_context *ctxt = udata;	DBusMessage *reply;	DBusMessageIter iter, array_iter;	uint8_t *pdata;	int csrc, tsrc;	if (!ctxt)		return;	if (err == 0xffff) {		/* Check for protocol error or I/O error */		int sdp_err = sdp_get_error(ctxt->session);		if (sdp_err < 0) {			error("search failed: Invalid session!");			error_failed(ctxt->conn, ctxt->rq, EINVAL);			goto failed;		}		error("search failed: %s (%d)", strerror(sdp_err), sdp_err);		error_failed(ctxt->conn, ctxt->rq, sdp_err);		goto failed;	}	if (type == SDP_ERROR_RSP) {		error_sdp_failed(ctxt->conn, ctxt->rq, err);		goto failed;	}	/* check response PDU ID */	if (type != SDP_SVC_SEARCH_RSP) {		error("SDP error: %s (%d)", strerror(EPROTO), EPROTO);		error_failed(ctxt->conn, ctxt->rq, EPROTO);		goto failed;	}	reply = dbus_message_new_method_return(ctxt->rq);	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,				DBUS_TYPE_UINT32_AS_STRING, &array_iter);	pdata = rsp;	tsrc = ntohs(bt_get_unaligned((uint16_t *) pdata));	if (tsrc <= 0)		goto done;	pdata += sizeof(uint16_t);	csrc = ntohs(bt_get_unaligned((uint16_t *) pdata));	if (csrc <= 0)		goto done;	pdata += sizeof(uint16_t);	do {		uint32_t handle = ntohl(bt_get_unaligned((uint32_t*)pdata));		pdata += sizeof(uint32_t);		dbus_message_iter_append_basic(&array_iter,						DBUS_TYPE_UINT32, &handle);	} while (--tsrc);done:	dbus_message_iter_close_container(&iter, &array_iter);	send_message_and_unref(ctxt->conn, reply);failed:	transaction_context_free(ctxt, TRUE);}static const char *extract_service_class(sdp_data_t *d){	sdp_data_t *seq;	uuid_t *uuid;	static char uuid_str[37];	/* Expected sequence of UUID16 */	if (d->attrId != SDP_ATTR_SVCLASS_ID_LIST || d->dtd != SDP_SEQ8)		return NULL;	if (!d->val.dataseq)		return NULL;	seq = d->val.dataseq;	if (!SDP_IS_UUID(seq->dtd))		return NULL;	uuid = &seq->val.uuid;	if (uuid->type != SDP_UUID16)		return NULL;	sprintf(uuid_str, "0000%04x-0000-1000-8000-00805f9b34fb",							uuid->value.uuid16);	return uuid_str;}static int service_search_attr(struct transaction_context *ctxt, uint16_t uuid){	sdp_list_t *attrids, *search;	uint32_t range = 0x0000ffff;	int ret = 0;	sdp_uuid16_create(&ctxt->uuid, uuid);	search = sdp_list_append(0, &ctxt->uuid);	attrids = sdp_list_append(NULL, &range);	/*	 * Create/send the search request and set the	 * callback to indicate the request completion	 */	if (sdp_service_search_attr_async(ctxt->session, search,				SDP_ATTR_REQ_RANGE, attrids) < 0)		ret = -sdp_get_error(ctxt->session);	sdp_list_free(search, NULL);	sdp_list_free(attrids, NULL);	return ret;}static void remote_svc_identifiers_completed_cb(uint8_t type, uint16_t err,			uint8_t *rsp, size_t size, void *udata){	struct transaction_context *ctxt = udata;	const char *src, *dst, *puuid;	const char *devid_uuid = "00001200-0000-1000-8000-00805f9b34fb";	char **identifiers;	DBusMessage *reply;	GSList *l = NULL;	int scanned, extracted = 0, len = 0, recsize = 0;	uint8_t dtd = 0;	if (!ctxt)		return;	if (err == 0xffff) {		/* Check for protocol error or I/O error */		int sdp_err = sdp_get_error(ctxt->session);		if (sdp_err < 0) {			error("search failed: Invalid session!");			error_failed(ctxt->conn, ctxt->rq, EINVAL);			goto failed;		}		error("search failed: %s (%d)", strerror(sdp_err), sdp_err);		error_failed(ctxt->conn, ctxt->rq, sdp_err);		goto failed;	}	if (type == SDP_ERROR_RSP) {		error_sdp_failed(ctxt->conn, ctxt->rq, err);		goto failed;	}	/* Check response PDU ID */	if (type != SDP_SVC_SEARCH_ATTR_RSP) {		error("SDP error: %s (%d)", strerror(EPROTO), EPROTO);		error_failed(ctxt->conn, ctxt->rq, EPROTO);		goto failed;	}	src = get_address_from_message(ctxt->conn, ctxt->rq);	dbus_message_get_args(ctxt->rq, NULL,			DBUS_TYPE_STRING, &dst,			DBUS_TYPE_INVALID);	scanned = sdp_extract_seqtype(rsp, &dtd, &len);	rsp += scanned;	for (; extracted < len; rsp += recsize, extracted += recsize) {		sdp_record_t *rec;		sdp_data_t *d;		recsize = 0;		rec = sdp_extract_pdu(rsp, &recsize);		if (!rec)			break;		sdp_store_record(src, dst, rec->handle, rsp, recsize);		d = sdp_data_get(rec, SDP_ATTR_SVCLASS_ID_LIST);		if (!d) {			sdp_record_free(rec);			continue;		}		puuid = extract_service_class(d);		sdp_record_free(rec);		if (!puuid)			continue;		/* Ignore repeated identifiers */		l = g_slist_find_custom(ctxt->identifiers,				puuid, (GCompareFunc) strcmp);		if (l)			continue;		ctxt->identifiers = g_slist_append(ctxt->identifiers,							g_strdup(puuid));	}	/* If public browse response is empty: search for L2CAP */	if (!ctxt->identifiers && ctxt->uuid.value.uuid16 == PUBLIC_BROWSE_GROUP)		if (service_search_attr(ctxt, L2CAP_UUID) == 0)			return; /* Wait the response */	/* Request DeviceID if it was not returned previously */	l = g_slist_find_custom(ctxt->identifiers,			devid_uuid, (GCompareFunc) strcmp);	if (!l && ctxt->uuid.value.uuid16 != PNP_INFO_SVCLASS_ID)		if (service_search_attr(ctxt, PNP_INFO_SVCLASS_ID) == 0)			return; /* Wait the response */	reply = dbus_message_new_method_return(ctxt->rq);	identifiers = g_new(char *, g_slist_length(ctxt->identifiers));	for (l = ctxt->identifiers, len = 0; l; l = l->next, len++)		identifiers[len] = l->data;	dbus_message_append_args(reply,			DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,			&identifiers, len,			DBUS_TYPE_INVALID);	send_message_and_unref(ctxt->conn, reply);	if (len)		dbus_connection_emit_signal(ctxt->conn,				dbus_message_get_path(ctxt->rq),				ADAPTER_INTERFACE,				"RemoteIdentifiersUpdated",				DBUS_TYPE_STRING, &dst,				DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,				&identifiers, len,				DBUS_TYPE_INVALID);	if (identifiers)		g_free(identifiers);failed:	transaction_context_free(ctxt, TRUE);}static gboolean sdp_client_connect_cb(GIOChannel *chan,					GIOCondition cond, void *udata){	struct pending_connect *c = udata;	struct transaction_context *ctxt = NULL;	int sdp_err, err = 0, sk;	socklen_t len;	sk = g_io_channel_unix_get_fd(chan);	len = sizeof(err);	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {		error("getsockopt(): %s (%d)", strerror(errno), errno);		err = errno;		goto failed;	}	if (err != 0) {		error("connect(): %s (%d)", strerror(err), err);		goto failed;	}	ctxt = g_new0(struct transaction_context, 1);	ctxt->conn = dbus_connection_ref(c->conn);	ctxt->rq = dbus_message_ref(c->rq);	ctxt->session = c->session;	if (c->call)		ctxt->call = c->call;	/* set the complete transaction callback and send the search request */	sdp_err = c->conn_cb(ctxt);	if (sdp_err < 0) {		err = -sdp_err;		error("search failed: %s (%d)", strerror(err), err);		goto failed;	}	/* set the callback responsible for update the transaction data */	ctxt->io_id = g_io_add_watch(chan,				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,				search_process_cb, ctxt);	ctxt->io = g_io_channel_ref(chan);	goto done;failed:	if (c->call)		get_record_data_call_cb(c->call, NULL, err);	else		error_connection_attempt_failed(c->conn, c->rq, err);	if (c->call)		get_record_data_free(c->call);	if (ctxt)		transaction_context_free(ctxt, FALSE);	else		sdp_close(c->session);done:	pending_connects = g_slist_remove(pending_connects, c);	pending_connect_free(c);	return FALSE;}static struct pending_connect *connect_request(DBusConnection *conn,					DBusMessage *msg,					uint16_t dev_id,					const char *dst,					connect_cb_t *cb, int *err){	struct pending_connect *c;	bdaddr_t srcba, dstba;	GIOChannel *chan;

⌨️ 快捷键说明

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