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

📄 server.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	ns = find_server(na->servers, dst_role);	if (!ns || ns->enable == FALSE) {		error("Server unavailable: %s (0x%x)", address, dst_role);		rsp = BNEP_CONN_NOT_ALLOWED;		goto reply;	}	if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0) {		rsp = BNEP_CONN_NOT_ALLOWED;		goto reply;	}	ba2str(&sa.l2_bdaddr, address);	if (setup) {		error("Connection rejected: Pending authorization");		rsp = BNEP_CONN_NOT_ALLOWED;		goto reply;	}	setup = setup_session_new(address, dst_role, src_role, sk, to->watch);	/* Wait authorization before reply success */	if (authorize_connection(ns, address) < 0) {		setup_session_free(setup);		setup = NULL;		rsp = BNEP_CONN_NOT_ALLOWED;		goto reply;	}	g_source_remove(to->id);	to->id = 0;	return TRUE;reply:	send_bnep_ctrl_rsp(sk, rsp);	return FALSE;}static void setup_destroy(void *user_data){	struct network_adapter *na = user_data;	struct timeout *to = na->to;	if (to->id)		g_source_remove(to->id);	g_free(to);}static gboolean timeout_cb(void *user_data){	struct timeout *to = user_data;	to->id = 0;	g_source_remove(to->watch);	return FALSE;}static void connect_event(GIOChannel *chan, int err, const bdaddr_t *src,				const bdaddr_t *dst, gpointer user_data){	struct network_adapter *na = user_data;	if (err < 0) {		error("accept(): %s(%d)", strerror(errno), errno);		return;	}	g_io_channel_set_close_on_unref(chan, TRUE);	/*	 * BNEP_SETUP_CONNECTION_REQUEST_MSG shall be received and	 * user shall authorize the incomming connection before	 * the time expires.	 */	na->to = g_malloc0(sizeof(struct timeout));	na->to->id = g_timeout_add_seconds(SETUP_TIMEOUT, timeout_cb, na->to);	na->to->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,				bnep_setup, na, setup_destroy);	g_io_channel_unref(chan);	return;}int server_init(DBusConnection *conn, const char *iface_prefix,		gboolean secure){	security = secure;	connection = dbus_connection_ref(conn);	prefix = iface_prefix;	if (bridge_create(BNEP_SVC_GN) < 0)		error("Can't create GN bridge");	return 0;}void server_exit(){	if (bridge_remove(BNEP_SVC_GN) < 0)		error("Can't remove GN bridge");	dbus_connection_unref(connection);	connection = NULL;}static uint32_t register_server_record(struct network_server *ns){	struct network_adapter *na = ns->na;	sdp_record_t *record;	record = server_record_new(ns->name, ns->id);	if (!record) {		error("Unable to allocate new service record");		return 0;	}	if (add_record_to_server(&na->src, record) < 0) {		error("Failed to register service record");		sdp_record_free(record);		return 0;	}	debug("register_server_record: got record id 0x%x", record->handle);	return record->handle;}static inline DBusMessage *failed(DBusMessage *msg, const char *description){	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",				description);}static inline DBusMessage *invalid_arguments(DBusMessage *msg,					const char *description){	return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",				description);}static DBusMessage *enable(DBusConnection *conn,			DBusMessage *msg, void *data){	struct network_server *ns = data;	DBusMessage *reply;	if (ns->enable)		return g_dbus_create_error(msg, ERROR_INTERFACE						".AlreadyExist",						"Server already enabled");	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	/* Add the service record */	ns->record_id = register_server_record(ns);	if (!ns->record_id) {		dbus_message_unref(reply);		return failed(msg, "Service record registration failed");	}	ns->enable = TRUE;	return reply;}static void kill_connection(void *data, void *udata){	const char *address = data;	bdaddr_t dst;	str2ba(address, &dst);	bnep_kill_connection(&dst);}static DBusMessage *disable(DBusConnection *conn,				DBusMessage *msg, void *data){	struct network_server *ns = data;	DBusMessage *reply;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	if (!ns->enable)		return failed(msg, "Not enabled");	/* Remove the service record */	if (ns->record_id) {		remove_record_from_server(ns->record_id);		ns->record_id = 0;	}	ns->enable = FALSE;	g_slist_foreach(ns->clients, (GFunc) kill_connection, NULL);	return reply;}static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,				const char *name, void *data){	struct network_server *ns = data;	DBusMessage *reply;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	if (!name || (strlen(name) == 0))		return invalid_arguments(msg, "Invalid name");	if (ns->name)		g_free(ns->name);	ns->name = g_strdup(name);	if (ns->enable && ns->record_id) {		uint32_t handle = register_server_record(ns);		if (!handle) {			dbus_message_unref(reply);			return failed(msg,				"Service record attribute update failed");		}		remove_record_from_server(ns->record_id);		ns->record_id = handle;	}	return reply;}static DBusMessage *get_properties(DBusConnection *conn,				DBusMessage *msg, void *data){	struct network_server *ns = data;	DBusMessage *reply;	DBusMessageIter iter;	DBusMessageIter dict;	const char *uuid;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);	dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &ns->name);	uuid = bnep_uuid(ns->id);	dict_append_entry(&dict, "Uuid", DBUS_TYPE_STRING, &uuid);	dict_append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &ns->enable);	dbus_message_iter_close_container(&iter, &dict);	return reply;}static DBusMessage *set_property(DBusConnection *conn,					DBusMessage *msg, void *data){	DBusMessageIter iter;	DBusMessageIter sub;	const char *property;	if (!dbus_message_iter_init(msg, &iter))		return invalid_arguments(msg, "Not a dict");	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)		return invalid_arguments(msg, "Key not a string");	dbus_message_iter_get_basic(&iter, &property);	dbus_message_iter_next(&iter);	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)		return invalid_arguments(msg, "Value not a variant");	dbus_message_iter_recurse(&iter, &sub);	if (g_str_equal("Name", property)) {		const char *name;		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)			return invalid_arguments(msg, "Value not string");		dbus_message_iter_get_basic(&sub, &name);		return set_name(conn, msg, name, data);	} else if (g_str_equal("Enabled", property)) {		gboolean enabled;		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)			return invalid_arguments(msg, "Value not boolean");		dbus_message_iter_get_basic(&sub, &enabled);		return enabled ? enable(conn, msg, data) :				disable(conn, msg, data);	}	return invalid_arguments(msg, "Property does not exist");}static void adapter_free(struct network_adapter *na){	if (na->io != NULL) {		g_io_channel_close(na->io);		g_io_channel_unref(na->io);	}	g_free(na->path);	g_free(na);}static void server_free(struct network_server *ns){	if (!ns)		return;	/* FIXME: Missing release/free all bnepX interfaces */	if (ns->record_id)		remove_record_from_server(ns->record_id);	if (ns->iface)		g_free(ns->iface);	if (ns->name)		g_free(ns->name);	if (ns->range)		g_free(ns->range);	if (ns->clients) {		g_slist_foreach(ns->clients, (GFunc) g_free, NULL);		g_slist_free(ns->clients);	}	g_free(ns);}static void path_unregister(void *data){	struct network_server *ns = data;	struct network_adapter *na = ns->na;	info("Unregistered interface %s on path %s",		ns->iface, na->path);	na->servers = g_slist_remove(na->servers, ns);	server_free(ns);	if (na->servers)		return;	adapters = g_slist_remove(adapters, na);	adapter_free(na);}static GDBusMethodTable server_methods[] = {	{ "SetProperty",	"sv",	"",	set_property },	{ "GetProperties",	"",	"a{sv}",get_properties },	{ }};static GDBusSignalTable server_signals[] = {	{ "PropertyChanged",		"sv"		},	{ }};static struct network_adapter *create_adapter(const char *path, bdaddr_t *src){	struct network_adapter *na;	int lm = 0;	if (security)		lm |= L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;	na = g_new0(struct network_adapter, 1);	na->path = g_strdup(path);	bacpy(&na->src, src);	na->io = bt_l2cap_listen(src, BNEP_PSM, BNEP_MTU, lm,			connect_event, na);	if (!na->io) {		adapter_free(na);		return NULL;	}	g_io_channel_set_close_on_unref(na->io, FALSE);	return na;}int server_register(const char *path, bdaddr_t *src, uint16_t id){	struct network_adapter *na;	struct network_server *ns;	na = find_adapter(adapters, path);	if (!na) {		na = create_adapter(path, src);		if (!na)			return -EINVAL;		adapters = g_slist_append(adapters, na);	}	ns = find_server(na->servers, id);	if (ns)		return 0;	ns = g_new0(struct network_server, 1);	switch (id) {	case BNEP_SVC_PANU:		ns->iface = g_strdup(NETWORK_PEER_INTERFACE);		ns->name = g_strdup("BlueZ PANU service");		break;	case BNEP_SVC_GN:		ns->iface = g_strdup(NETWORK_HUB_INTERFACE);		ns->name = g_strdup("BlueZ GN service");		break;	case BNEP_SVC_NAP:		ns->iface = g_strdup(NETWORK_ROUTER_INTERFACE);		ns->name = g_strdup("BlueZ NAP service");		break;	}	if (!g_dbus_register_interface(connection, path, ns->iface,					server_methods, server_signals, NULL,					ns, path_unregister)) {		error("D-Bus failed to register %s interface",				ns->iface);		server_free(ns);		return -1;	}	ns->id = id;	ns->na = na;	ns->record_id = register_server_record(ns);	ns->enable = TRUE;	na->servers = g_slist_append(na->servers, ns);	info("Registered interface %s on path %s", ns->iface, path);	return 0;}int server_unregister(const char *path, uint16_t id){	struct network_adapter *na;	struct network_server *ns;	na = find_adapter(adapters, path);	if (!na)		return -EINVAL;	ns = find_server(na->servers, id);	if (!ns)		return -EINVAL;	g_dbus_unregister_interface(connection, path, ns->iface);	return 0;}

⌨️ 快捷键说明

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