pipewire/src/modules/module-protocol-native/security-context.c

133 lines
3.1 KiB
C
Raw Normal View History

/* PipeWire */
/* SPDX-FileCopyrightText: Copyright © 2024 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#include <pipewire/pipewire.h>
#include <pipewire/impl.h>
#include <pipewire/private.h>
#include <pipewire/extensions/security-context.h>
PW_LOG_TOPIC_EXTERN(mod_topic);
#define PW_LOG_TOPIC_DEFAULT mod_topic
PW_LOG_TOPIC_EXTERN(mod_topic_connection);
struct impl {
struct pw_context *context;
struct pw_global *global;
struct pw_protocol *protocol;
};
struct resource_data {
struct impl *impl;
struct pw_resource *resource;
struct spa_hook resource_listener;
struct spa_hook object_listener;
};
static int security_context_create(void *object,
const char *engine_name,
int listen_fd,
int close_fd,
const struct spa_dict *props)
{
struct resource_data *d = object;
struct impl *impl = d->impl;
pw_protocol_add_fd_server(impl->protocol, impl->context->core,
listen_fd, close_fd, props);
return 0;
}
static const struct pw_security_context_methods security_context_methods = {
PW_VERSION_SECURITY_CONTEXT_METHODS,
.create = security_context_create,
};
static void global_unbind(void *data)
{
struct resource_data *d = data;
if (d->resource) {
spa_hook_remove(&d->resource_listener);
}
}
static const struct pw_resource_events resource_events = {
PW_VERSION_RESOURCE_EVENTS,
.destroy = global_unbind,
};
static int
global_bind(void *object, struct pw_impl_client *client, uint32_t permissions,
uint32_t version, uint32_t id)
{
struct impl *impl = object;
struct pw_resource *resource;
struct resource_data *data;
resource = pw_resource_new(client, id, permissions,
PW_TYPE_INTERFACE_SecurityContext,
version, sizeof(*data));
if (resource == NULL)
return -errno;
data = pw_resource_get_user_data(resource);
data->impl = impl;
data->resource = resource;
pw_global_add_resource(impl->global, resource);
/* listen for when the resource goes away */
pw_resource_add_listener(resource,
&data->resource_listener,
&resource_events, data);
/* resource methods -> implementation */
pw_resource_add_object_listener(resource,
&data->object_listener,
&security_context_methods, data);
return 0;
}
int protocol_native_security_context_init(struct pw_impl_module *module, struct pw_protocol *protocol)
{
struct pw_context *context = pw_impl_module_get_context(module);
struct impl *impl;
char serial_str[32];
struct spa_dict_item items[1] = {
SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
};
struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
static const char * const keys[] = {
PW_KEY_OBJECT_SERIAL,
NULL
};
impl = calloc(1, sizeof(struct impl));
if (impl == NULL)
return -errno;
impl->context = context;
impl->protocol = protocol;
impl->global = pw_global_new(context,
PW_TYPE_INTERFACE_SecurityContext,
PW_VERSION_SECURITY_CONTEXT,
PW_SECURITY_CONTEXT_PERM_MASK,
NULL,
global_bind, impl);
if (impl->global == NULL) {
free(impl);
return -errno;
}
spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
pw_global_get_serial(impl->global));
pw_global_update_keys(impl->global, &extra_props, keys);
pw_global_register(impl->global);
return 0;
}