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

📄 dbus-database.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  Nokia Corporation *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <errno.h>#include <stdlib.h>#include <string.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <glib.h>#include <dbus/dbus.h>#include "dbus.h"#include "dbus-helper.h"#include "hcid.h"#include "sdpd.h"#include "sdp-xml.h"#include "manager.h"#include "adapter.h"#include "dbus-hci.h"#include "dbus-common.h"#include "dbus-error.h"#include "error.h"#include "dbus-service.h"#include "dbus-security.h"#include "dbus-database.h"static int sdp_server_enable = 0;static GSList *records = NULL;struct record_data {	uint32_t handle;	char *sender;};static struct record_data *find_record(uint32_t handle, const char *sender){	GSList *list;	for (list = records; list; list = list->next) {		struct record_data *data = list->data;		if (handle == data->handle && !strcmp(sender, data->sender))			return data;	}	return NULL;}static void exit_callback(const char *name, void *user_data){	struct record_data *user_record = user_data;	records = g_slist_remove(records, user_record);	if (sdp_server_enable)		remove_record_from_server(user_record->handle);	else		unregister_sdp_record(user_record->handle);	if (user_record->sender)		g_free(user_record->sender);	g_free(user_record);}static DBusHandlerResult add_service_record(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	DBusMessageIter iter, array;	const char *sender;	struct record_data *user_record;	sdp_record_t *sdp_record;	const uint8_t *record;	int scanned, len = -1;	dbus_message_iter_init(msg, &iter);	dbus_message_iter_recurse(&iter, &array);	dbus_message_iter_get_fixed_array(&array, &record, &len);	if (len <= 0)		return error_invalid_arguments(conn, msg, NULL);	user_record = g_new0(struct record_data, 1);	if (sdp_server_enable) {		sdp_record = sdp_extract_pdu(record, &scanned);		if (!sdp_record) {			error("Parsing of service record failed");			g_free(user_record);			return error_failed_errno(conn, msg, EIO);		}		if (scanned != len) {			error("Size mismatch of service record");			g_free(user_record);			sdp_record_free(sdp_record);			return error_failed_errno(conn, msg, EIO);		}		if (add_record_to_server(sdp_record) < 0) {			error("Failed to register service record");			g_free(user_record);			sdp_record_free(sdp_record);			return error_failed_errno(conn, msg, EIO);		}		user_record->handle = sdp_record->handle;	} else {		uint32_t size = len;		if (register_sdp_binary((uint8_t *) record, size,						&user_record->handle) < 0) {			error("Failed to register service record");			g_free(user_record);			return error_failed_errno(conn, msg, errno);		}	}	sender = dbus_message_get_sender(msg);	user_record->sender = g_strdup(sender);	records = g_slist_append(records, user_record);	name_listener_add(conn, sender, exit_callback, user_record);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &user_record->handle,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult add_service_record_from_xml(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	const char *sender, *record;	struct record_data *user_record;	sdp_record_t *sdp_record;	if (dbus_message_get_args(msg, NULL,			DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	user_record = g_new0(struct record_data, 1);	sdp_record = sdp_xml_parse_record(record, strlen(record));	if (!sdp_record) {		error("Parsing of XML service record failed");		g_free(user_record);		return error_failed_errno(conn, msg, EIO);	}	if (sdp_server_enable) {		if (add_record_to_server(sdp_record) < 0) {			error("Failed to register service record");			g_free(user_record);			sdp_record_free(sdp_record);			return error_failed_errno(conn, msg, EIO);		}		user_record->handle = sdp_record->handle;	} else {		if (register_sdp_record(sdp_record) < 0) {			error("Failed to register service record");			g_free(user_record);			sdp_record_free(sdp_record);			return error_failed_errno(conn, msg, EIO);		}		user_record->handle = sdp_record->handle;		sdp_record_free(sdp_record);	}	sender = dbus_message_get_sender(msg);	user_record->sender = g_strdup(sender);	records = g_slist_append(records, user_record);	name_listener_add(conn, sender, exit_callback, user_record);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &user_record->handle,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult update_record(DBusConnection *conn, DBusMessage *msg,				dbus_uint32_t handle, sdp_record_t *sdp_record){	int err;	if (sdp_server_enable) {		if (remove_record_from_server(handle) < 0) {			sdp_record_free(sdp_record);			return error_not_available(conn, msg);		}		sdp_record->handle = handle;		err = add_record_to_server(sdp_record);		if (err < 0) {			sdp_record_free(sdp_record);			error("Failed to update the service record");			return error_failed_errno(conn, msg, EIO);		}	} else {		sdp_data_t *d = sdp_data_alloc(SDP_UINT32, &handle);		sdp_attr_replace(sdp_record, SDP_ATTR_RECORD_HANDLE, d);		err = update_sdp_record(handle, sdp_record);		sdp_record_free(sdp_record);		if (err < 0) {			error("Failed to update the service record");			return error_failed_errno(conn, msg, EIO);		}	}	return send_message_and_unref(conn,			dbus_message_new_method_return(msg));}static DBusHandlerResult update_service_record(DBusConnection *conn,						DBusMessage *msg, void *data){	struct record_data *user_record;	DBusMessageIter iter, array;	sdp_record_t *sdp_record;	dbus_uint32_t handle;	const uint8_t *bin_record;	int scanned, size = -1;	dbus_message_iter_init(msg, &iter);	dbus_message_iter_get_basic(&iter, &handle);	dbus_message_iter_next(&iter);	dbus_message_iter_recurse(&iter, &array);	dbus_message_iter_get_fixed_array(&array, &bin_record, &size);	if (size <= 0)		return error_invalid_arguments(conn, msg, NULL);	user_record = find_record(handle, dbus_message_get_sender(msg));	if (!user_record)		return error_not_available(conn, msg);	sdp_record = sdp_extract_pdu(bin_record, &scanned);	if (!sdp_record) {		error("Parsing of service record failed");		return error_invalid_arguments(conn, msg, NULL);	}	if (scanned != size) {		error("Size mismatch of service record");		sdp_record_free(sdp_record);		return error_invalid_arguments(conn, msg, NULL);	}	return update_record(conn, msg, handle, sdp_record);}static DBusHandlerResult update_service_record_from_xml(DBusConnection *conn,						DBusMessage *msg, void *data){	const char *record;	struct record_data *user_record;	sdp_record_t *sdp_record;	dbus_uint32_t handle;	int len;	if (dbus_message_get_args(msg, NULL,			DBUS_TYPE_UINT32, &handle,			DBUS_TYPE_STRING, &record,			DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	len = (record ? strlen(record) : 0);	if (len == 0)		return error_invalid_arguments(conn, msg, NULL);	user_record = find_record(handle, dbus_message_get_sender(msg));	if (!user_record)		return error_not_available(conn, msg);	sdp_record = sdp_xml_parse_record(record, len);	if (!sdp_record) {		error("Parsing of XML service record failed");		sdp_record_free(sdp_record);		return error_failed_errno(conn, msg, EIO);	}	return update_record(conn, msg, handle, sdp_record);}static DBusHandlerResult remove_service_record(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	dbus_uint32_t handle;	const char *sender;	struct record_data *user_record;	if (dbus_message_get_args(msg, NULL,			DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	sender = dbus_message_get_sender(msg);	user_record = find_record(handle, sender);	if (!user_record)		return error_not_available(conn, msg);	name_listener_remove(conn, sender, exit_callback, user_record);	records = g_slist_remove(records, user_record);	if (sdp_server_enable)		remove_record_from_server(handle);	else		unregister_sdp_record(handle);	if (user_record->sender)		g_free(user_record->sender);	g_free(user_record);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	return send_message_and_unref(conn, reply);}static DBusHandlerResult register_service(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	const char *sender, *ident, *name, *desc;	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ident,			DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &desc,						DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	sender = dbus_message_get_sender(msg);	if (service_register(conn, sender, ident, name, desc) < 0)		return error_failed_errno(conn, msg, EIO);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	return send_message_and_unref(conn, reply);}static DBusHandlerResult unregister_service(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	const char *sender, *ident;	struct service *service;	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ident,						DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	sender = dbus_message_get_sender(msg);	service = search_service(conn, ident);	if (!service)		return error_service_does_not_exist(conn, msg);	if (!service->external || strcmp(sender, service->bus_name))		return error_not_authorized(conn, msg);	if (service_unregister(conn, service) < 0)		return error_failed_errno(conn, msg, EIO);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	return send_message_and_unref(conn, reply);}static DBusHandlerResult request_authorization(DBusConnection *conn,						DBusMessage *msg, void *data){	const char *sender, *address, *path;	struct service *service;	bdaddr_t bdaddr;	gboolean trusted;	int adapter_id;	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,			DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	sender = dbus_message_get_sender(msg);	service = search_service(conn, sender);	if (!service) {		debug("Got RequestAuthorization from non-service owner %s",				sender);		return error_not_authorized(conn, msg);	}	str2ba(address, &bdaddr);	adapter_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);	if (adapter_id < 0)		return error_not_connected(conn, msg);	hci_devba(adapter_id, &bdaddr);	trusted = read_trust(&bdaddr, address, GLOBAL_TRUST);	if (!trusted)		trusted = read_trust(BDADDR_ANY, address, service->ident);	if (trusted) {		DBusMessage *reply;		reply = dbus_message_new_method_return(msg);		if (!reply)			return DBUS_HANDLER_RESULT_NEED_MEMORY;		return send_message_and_unref(conn, reply);	}	return handle_authorize_request(conn, msg, service, address, path);}static DBusHandlerResult cancel_authorization_request(DBusConnection *conn,						DBusMessage *msg, void *data){	const char *sender, *address, *path;	struct service *service;	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,			DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) == FALSE)		return error_invalid_arguments(conn, msg, NULL);	sender = dbus_message_get_sender(msg);	service = search_service(conn, sender);	if (!service)		return error_not_authorized(conn, msg);	return cancel_authorize_request(conn, msg, service, address, path);}static DBusMethodVTable database_methods[] = {	{ "AddServiceRecord",			add_service_record,		"ay",	"u"	},		{ "AddServiceRecordFromXML",		add_service_record_from_xml,	"s",	"u"	},	{ "UpdateServiceRecord",		update_service_record,		"uay",	""	},	{ "UpdateServiceRecordFromXML",		update_service_record_from_xml,	"us",	""	},	{ "RemoveServiceRecord",		remove_service_record,		"u",	""	},	{ "RegisterService",			register_service,		"sss",	""	},	{ "UnregisterService",			unregister_service,		"s",	""	},	{ "RequestAuthorization",		request_authorization,		"ss",	""	},	{ "CancelAuthorizationRequest",		cancel_authorization_request,	"ss",	""	},	{ NULL, NULL, NULL, NULL }};dbus_bool_t database_init(DBusConnection *conn, const char *path){	return dbus_connection_register_interface(conn, path,							DATABASE_INTERFACE,							database_methods,							NULL, NULL);}DBusHandlerResult database_message(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMethodVTable *current;	for (current = database_methods;			current->name && current->message_function; current++) {		if (!dbus_message_is_method_call(msg, DATABASE_INTERFACE,								current->name))			continue;		if (dbus_message_has_signature(msg, current->signature)) {			debug("%s: %s.%s()", dbus_message_get_path(msg),					DATABASE_INTERFACE, current->name);			return current->message_function(conn, msg, data);		}	}	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;}void set_sdp_server_enable(void){	sdp_server_enable = 1;}

⌨️ 快捷键说明

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