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

📄 dbus-service.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	write_trust(BDADDR_ANY, address, service->ident, TRUE);	dbus_connection_emit_signal(conn, service->object_path,					SERVICE_INTERFACE, "TrustAdded",					DBUS_TYPE_STRING, &address,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult list_trusted(DBusConnection *conn,                                        DBusMessage *msg, void *data){        struct service *service = data;        DBusMessage *reply;        GSList *trusts, *l;        char **addrs;        int len;        reply = dbus_message_new_method_return(msg);        if (!reply)                return DBUS_HANDLER_RESULT_NEED_MEMORY;        trusts = list_trusts(BDADDR_ANY, service->ident);        addrs = g_new(char *, g_slist_length(trusts));        for (l = trusts, len = 0; l; l = l->next, len++)                addrs[len] = l->data;        dbus_message_append_args(reply,                        DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,                        &addrs, len,                        DBUS_TYPE_INVALID);        g_free(addrs);        g_slist_foreach(trusts, (GFunc) g_free, NULL);        g_slist_free(trusts);        return send_message_and_unref(conn, reply);}static DBusHandlerResult is_trusted(DBusConnection *conn,					DBusMessage *msg, void *data){	struct service *service = data;	DBusMessage *reply;	const char *address;	dbus_bool_t trusted;	if (!dbus_message_get_args(msg, NULL,			DBUS_TYPE_STRING, &address,			DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(address) < 0)		return error_invalid_arguments(conn, msg, NULL);	trusted = read_trust(BDADDR_ANY, address, service->ident);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply,				DBUS_TYPE_BOOLEAN, &trusted,				DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult remove_trust(DBusConnection *conn,					DBusMessage *msg, void *data){	struct service *service = data;	DBusMessage *reply;	const char *address;	if (!dbus_message_get_args(msg, NULL,			DBUS_TYPE_STRING, &address,			DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(address) < 0)		return error_invalid_arguments(conn, msg, NULL);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	write_trust(BDADDR_ANY, address, service->ident, FALSE);	dbus_connection_emit_signal(conn, service->object_path,					SERVICE_INTERFACE, "TrustRemoved",					DBUS_TYPE_STRING, &address,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusMethodVTable service_methods[] = {	{ "GetInfo",		get_info,		"",	"a{sv}"	},	{ "GetIdentifier",	get_identifier,		"",	"s"	},	{ "GetName",		get_name,		"",	"s"	},	{ "GetDescription",	get_description,	"",	"s"	},	{ "GetBusName",		get_bus_name,		"",	"s"	},	{ "Start",		start,			"",	""	},	{ "Stop",		stop,			"",	""	},	{ "IsRunning",		is_running,		"",	"b"	},	{ "IsExternal",		is_external,		"",	"b"	},	{ "SetTrusted",		set_trusted,		"s",	""	},	{ "IsTrusted",		is_trusted,		"s",	"b"	},	{ "RemoveTrust",	remove_trust,		"s",	""	},	{ "ListTrusts",		list_trusted,		"",	"as"	},	{ NULL, NULL, NULL, NULL }};static DBusSignalVTable service_signals[] = {	{ "Started",		""	},	{ "Stopped",		""	},	{ "TrustAdded",		"s"	},	{ "TrustRemoved",	"s"	},	{ NULL, NULL }};static dbus_bool_t service_init(DBusConnection *conn, const char *path){	return dbus_connection_register_interface(conn, path, SERVICE_INTERFACE,							service_methods,							service_signals, NULL);}static int service_cmp_path(struct service *service, const char *path){	return strcmp(service->object_path, path);}static int service_cmp_ident(struct service *service, const char *ident){	return strcmp(service->ident, ident);}static int register_service(struct service *service){	char obj_path[PATH_MAX], *suffix;	DBusConnection *conn = get_dbus_connection();	int i;	if (g_slist_find_custom(services, service->ident,				(GCompareFunc) service_cmp_ident)			|| !strcmp(service->ident, GLOBAL_TRUST))		return -EADDRINUSE;	if (service->external) {		snprintf(obj_path, sizeof(obj_path) - 1,				"/org/bluez/external_%s", service->ident);	} else {		snprintf(obj_path, sizeof(obj_path) - 1,				"/org/bluez/service_%s", service->filename);		/* Don't include the .service part in the path */		suffix = strstr(obj_path, SERVICE_SUFFIX);		*suffix = '\0';	}	/* Make the path valid for D-Bus */	for (i = strlen("/org/bluez/"); obj_path[i]; i++) {		if (!isalnum(obj_path[i]))			obj_path[i] = '_';	}	if (g_slist_find_custom(services, obj_path,				(GCompareFunc) service_cmp_path))		return -EADDRINUSE;	debug("Registering service object: ident=%s, name=%s (%s)",			service->ident, service->name, obj_path);	if (!dbus_connection_create_object_path(conn, obj_path,						service, NULL)) {		error("D-Bus failed to register %s object", obj_path);		return -1;	}	if (!service_init(conn, obj_path)) {		error("Service init failed");		return -1;	}	service->object_path = g_strdup(obj_path);	services = g_slist_append(services, service);	dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE,					"ServiceAdded",					DBUS_TYPE_STRING, &service->object_path,					DBUS_TYPE_INVALID);	return 0;}static int unregister_service_for_connection(DBusConnection *connection,						struct service *service){	DBusConnection *conn = get_dbus_connection();	debug("Unregistering service object: %s", service->object_path);	if (!conn)		goto cleanup;	if (service->bus_name)		name_listener_remove(connection, service->bus_name,					(name_cb_t) service_exit, service);	dbus_connection_emit_signal(conn, service->object_path,					SERVICE_INTERFACE,					"Stopped", DBUS_TYPE_INVALID);	if (!dbus_connection_destroy_object_path(conn, service->object_path)) {		error("D-Bus failed to unregister %s object", service->object_path);		return -1;	}	dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE,					"ServiceRemoved",					DBUS_TYPE_STRING, &service->object_path,					DBUS_TYPE_INVALID);cleanup:	if (service->pid) {		if (service->startup_timer) {			abort_startup(service, conn, ECANCELED);			services = g_slist_remove(services, service);			removed = g_slist_append(removed, service);		} else if (!service->shutdown_timer)			stop_service(service, TRUE);	} else {		services = g_slist_remove(services, service);		service_free(service);	}	return 0;}static int unregister_service(struct service *service){	return unregister_service_for_connection(get_dbus_connection(), service);}void release_services(DBusConnection *conn){	debug("release_services");	g_slist_foreach(services, (GFunc) unregister_service, NULL);	g_slist_free(services);	services = NULL;}struct service *search_service(DBusConnection *conn, const char *pattern){	GSList *l;	for (l = services; l != NULL; l = l->next) {		struct service *service = l->data;		if (service->ident && !strcmp(service->ident, pattern))			return service;		if (service->bus_name && !strcmp(service->bus_name, pattern))			return service;	}	return NULL;}void append_available_services(DBusMessageIter *array_iter){	GSList *l;	for (l = services; l != NULL; l = l->next) {		struct service *service = l->data;		dbus_message_iter_append_basic(array_iter,					DBUS_TYPE_STRING, &service->object_path);	}}static struct service *create_service(const char *file){	GKeyFile *keyfile;	GError *err = NULL;	struct service *service;	gboolean autostart;	const char *slash;	service = g_try_new0(struct service, 1);	if (!service) {		error("OOM while allocating new service");		return NULL;	}	service->external = FALSE;	keyfile = g_key_file_new();	if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {		error("Parsing %s failed: %s", file, err->message);		g_error_free(err);		goto failed;	}	service->ident = g_key_file_get_string(keyfile, SERVICE_GROUP,						"Identifier", &err);	if (err) {		debug("%s: %s", file, err->message);		g_error_free(err);		goto failed;	}	service->name = g_key_file_get_string(keyfile, SERVICE_GROUP,						"Name", &err);	if (!service->name) {		error("%s: %s", file, err->message);		g_error_free(err);		goto failed;	}	slash = strrchr(file, '/');	if (!slash) {		error("No slash in service file path!?");		goto failed;	}	service->filename = g_strdup(slash + 1);	service->descr = g_key_file_get_string(keyfile, SERVICE_GROUP,						"Description", &err);	if (err) {		debug("%s: %s", file, err->message);		g_error_free(err);		err = NULL;	}	autostart = g_key_file_get_boolean(keyfile, SERVICE_GROUP,						"Autostart", &err);	if (err) {		debug("%s: %s", file, err->message);		g_error_free(err);		err = NULL;	} else		service->autostart = autostart;	g_key_file_free(keyfile);	return service;failed:	g_key_file_free(keyfile);	service_free(service);	return NULL;}static gint service_filename_cmp(struct service *service, const char *filename){	return strcmp(service->filename, filename);}static void service_notify(int action, const char *name, void *user_data){	GSList *l;	struct service *service;	size_t len;	char fullpath[PATH_MAX];	debug("Received notify event %d for %s", action, name);	len = strlen(name);	if (len < (strlen(SERVICE_SUFFIX) + 1))		return;	if (strcmp(name + (len - strlen(SERVICE_SUFFIX)), SERVICE_SUFFIX))		return;	switch (action) {	case NOTIFY_CREATE:		debug("%s was created", name);		snprintf(fullpath, sizeof(fullpath) - 1, "%s/%s", CONFIGDIR, name);		service = create_service(fullpath);		if (!service) {			error("Unable to read %s", fullpath);			break;		}		if (register_service(service) < 0) {			error("Unable to register service");			service_free(service);			break;		}		if (service->autostart)			service_start(service, get_dbus_connection());		break;	case NOTIFY_DELETE:		debug("%s was deleted", name);		l = g_slist_find_custom(services, name,					(GCompareFunc) service_filename_cmp);		if (l)			unregister_service(l->data);		break;	case NOTIFY_MODIFY:		debug("%s was modified", name);		break;	default:		debug("Unknown notify action %d", action);		break;	}}int init_services(const char *path){	DIR *d;	struct dirent *e;	d = opendir(path);	if (!d) {		error("Unable to open service dir %s: %s", path, strerror(errno));		return -1;	}	while ((e = readdir(d)) != NULL) {		char full_path[PATH_MAX];		struct service *service;		size_t len = strlen(e->d_name);		if (len < (strlen(SERVICE_SUFFIX) + 1))			continue;		/* Skip if the file doesn't end in .service */		if (strcmp(&e->d_name[len - strlen(SERVICE_SUFFIX)], SERVICE_SUFFIX))			continue;		snprintf(full_path, sizeof(full_path) - 1, "%s/%s", path, e->d_name);		service = create_service(full_path);		if (!service) {			error("Unable to read %s", full_path);			continue;		}		if (register_service(service) < 0) {			error("Unable to register service");			service_free(service);			continue;		}		if (service->autostart)			service_start(service, get_dbus_connection());	}	closedir(d);	notify_add(path, service_notify, NULL);	return 0;}static struct service *create_external_service(const char *ident,				const char *name, const char *description){	struct service *service;	service = g_try_new0(struct service, 1);	if (!service) {		error("OOM while allocating new external service");		return NULL;	}	service->filename = NULL;	service->name = g_strdup(name);	service->descr = g_strdup(description);	service->ident = g_strdup(ident);	service->external = TRUE;	return service;}static void external_service_exit(const char *name, struct service *service){	DBusConnection *conn = get_dbus_connection();	service_exit(name, service);	if (!conn)		return;	if (!dbus_connection_destroy_object_path(conn, service->object_path))		return;	dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE,					"ServiceRemoved",					DBUS_TYPE_STRING, &service->object_path,					DBUS_TYPE_INVALID);	services = g_slist_remove(services, service);	service_free(service);}int service_register(DBusConnection *conn, const char *bus_name, const char *ident,				const char *name, const char *description){	struct service *service;	if (!conn)		return -1;	service = create_external_service(ident, name, description);	if (!service)		return -1;	service->bus_name = g_strdup(bus_name);	if (register_service(service) < 0) {		service_free(service);		return -1;	}	name_listener_add(conn, bus_name, (name_cb_t) external_service_exit,				service);	dbus_connection_emit_signal(get_dbus_connection(), service->object_path,					SERVICE_INTERFACE, "Started",					DBUS_TYPE_INVALID);	return 0;}int service_unregister(DBusConnection *conn, struct service *service){	return unregister_service_for_connection(conn, service);}

⌨️ 快捷键说明

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