Implement access control

Move send and dispatch functions to the implementation. This makes it
possible to place an access check before sending and dispatching.
Add module-access that allows to bind and notify on globals owned by
the client.
This commit is contained in:
Wim Taymans 2017-01-10 17:12:53 +01:00
parent a8964ca657
commit ee0aa6a2ac
27 changed files with 819 additions and 220 deletions

27
pinos/server/access.c Normal file
View file

@ -0,0 +1,27 @@
/* Pinos
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "pinos/server/core.h"
void
pinos_access_init (PinosAccess *access)
{
pinos_signal_init (&access->check_send);
pinos_signal_init (&access->check_dispatch);
}

68
pinos/server/access.h Normal file
View file

@ -0,0 +1,68 @@
/* Pinos
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __PINOS_ACCESS_H__
#define __PINOS_ACCESS_H__
#ifdef __cplusplus
extern "C" {
#endif
#define PINOS_ACCESS_URI "http://pinos.org/ns/access"
#define PINOS_ACCESS_PREFIX PINOS_ACCESS_URI "#"
#include <pinos/client/sig.h>
typedef struct _PinosAccess PinosAccess;
#include <pinos/server/client.h>
#include <pinos/server/resource.h>
typedef struct {
SpaResult res;
PinosClient *client;
PinosResource *resource;
uint32_t opcode;
void *message;
bool flush;
} PinosAccessData;
typedef SpaResult (*PinosAccessFunc) (PinosAccessData *data);
/**
* PinosAccess:
*
* Pinos Access support struct.
*/
struct _PinosAccess {
PINOS_SIGNAL (check_send, (PinosListener *listener,
PinosAccessFunc func,
PinosAccessData *data));
PINOS_SIGNAL (check_dispatch, (PinosListener *listener,
PinosAccessFunc func,
PinosAccessData *data));
};
void pinos_access_init (PinosAccess *access);
#ifdef __cplusplus
}
#endif
#endif /* __PINOS_ACCESS_H__ */

View file

@ -121,6 +121,7 @@ typedef struct
PinosListener transport_changed;
PinosListener loop_changed;
PinosListener global_added;
int data_fd;
} PinosClientNodeImpl;
@ -1187,6 +1188,16 @@ on_loop_changed (PinosListener *listener,
impl->proxy.data_loop = node->data_loop->loop->loop;
}
static void
on_global_added (PinosListener *listener,
PinosCore *core,
PinosGlobal *global)
{
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, global_added);
if (global->object == impl->this.node)
global->owner = impl->this.client;
}
static SpaResult
proxy_clear (SpaProxy *this)
{
@ -1256,14 +1267,6 @@ pinos_client_node_new (PinosClient *client,
impl->proxy.pnode = this->node;
pinos_signal_add (&this->node->transport_changed,
&impl->transport_changed,
on_transport_changed);
pinos_signal_add (&this->node->loop_changed,
&impl->loop_changed,
on_loop_changed);
this->resource = pinos_resource_new (client,
id,
client->core->uri.client_node,
@ -1273,8 +1276,22 @@ pinos_client_node_new (PinosClient *client,
goto error_no_resource;
impl->proxy.resource = this->resource;
this->resource->dispatch_func = client_node_dispatch_func;
this->resource->dispatch_data = this;
pinos_signal_add (&this->node->transport_changed,
&impl->transport_changed,
on_transport_changed);
pinos_signal_add (&this->node->loop_changed,
&impl->loop_changed,
on_loop_changed);
pinos_signal_add (&impl->core->global_added,
&impl->global_added,
on_global_added);
pinos_resource_set_dispatch (this->resource,
client_node_dispatch_func,
this);
return this;
@ -1312,6 +1329,8 @@ pinos_client_node_destroy (PinosClientNode * this)
pinos_log_debug ("client-node %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this);
pinos_signal_remove (&impl->global_added);
pinos_node_destroy (this->node);
pinos_main_loop_defer (this->node->core->main_loop,

View file

@ -26,6 +26,9 @@
typedef struct
{
PinosClient this;
PinosSendFunc send_func;
void *send_data;
} PinosClientImpl;
@ -53,7 +56,7 @@ client_unbind_func (void *data)
spa_list_remove (&resource->link);
}
static void
static SpaResult
client_bind_func (PinosGlobal *global,
PinosClient *client,
uint32_t version,
@ -66,14 +69,15 @@ client_bind_func (PinosGlobal *global,
resource = pinos_resource_new (client,
id,
global->core->uri.client,
global->type,
global->object,
client_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = client_dispatch_func;
resource->dispatch_data = global;
pinos_resource_set_dispatch (resource,
client_dispatch_func,
global);
pinos_log_debug ("client %p: bound to %d", global->object, resource->id);
@ -84,16 +88,15 @@ client_bind_func (PinosGlobal *global,
info.change_mask = ~0;
info.props = this->properties ? &this->properties->dict : NULL;
pinos_resource_send_message (resource,
PINOS_MESSAGE_CLIENT_INFO,
&m,
true);
return;
return pinos_resource_send_message (resource,
PINOS_MESSAGE_CLIENT_INFO,
&m,
true);
no_mem:
pinos_resource_send_error (client->core_resource,
SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY;
}
/**
@ -130,6 +133,7 @@ pinos_client_new (PinosCore *core,
spa_list_insert (core->client_list.prev, &this->link);
this->global = pinos_core_add_global (core,
this,
core->uri.client,
0,
this,
@ -191,6 +195,78 @@ pinos_client_destroy (PinosClient * client)
client);
}
void
pinos_client_set_send (PinosClient *client,
PinosSendFunc func,
void *data)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
impl->send_func = func;
impl->send_data = data;
}
static SpaResult
do_send_message (PinosAccessData *data)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (data->client, PinosClientImpl, this);
if (data->res == SPA_RESULT_SKIPPED) {
data->res = SPA_RESULT_OK;
} else if (data->res == SPA_RESULT_NO_PERMISSION) {
pinos_resource_send_error (data->resource,
data->res,
"no permission");
} else if (SPA_RESULT_IS_ERROR (data->res)) {
pinos_resource_send_error (data->resource,
data->res,
"error %d", data->res);
} else {
data->res = impl->send_func (data->resource,
data->resource->id,
data->opcode,
data->message,
data->flush,
impl->send_data);
}
return data->res;
}
SpaResult
pinos_client_send_message (PinosClient *client,
PinosResource *resource,
uint32_t opcode,
void *message,
bool flush)
{
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
if (impl->send_func) {
PinosAccessData data;
data.client = client;
data.resource = resource;
data.opcode = opcode;
data.message = message;
data.flush = flush;
data.res = SPA_RESULT_OK;
pinos_signal_emit (&client->core->access.check_send,
do_send_message,
&data);
if (SPA_RESULT_IS_ASYNC (data.res))
return data.res;
return do_send_message (&data);
}
pinos_log_error ("client %p: send func not implemented", client);
return SPA_RESULT_NOT_IMPLEMENTED;
}
void
pinos_client_update_properties (PinosClient *client,
const SpaDict *dict)

View file

@ -26,9 +26,21 @@ extern "C" {
typedef struct _PinosClient PinosClient;
#include <sys/socket.h>
#include <pinos/client/properties.h>
#include <pinos/client/sig.h>
#include <pinos/server/core.h>
#include <pinos/server/resource.h>
typedef SpaResult (*PinosSendFunc) (void *object,
uint32_t id,
uint32_t opcode,
void *message,
bool flush,
void *data);
/**
* PinosClient:
*
@ -40,6 +52,8 @@ struct _PinosClient {
PinosGlobal *global;
PinosProperties *properties;
bool ucred_valid;
struct ucred ucred;
PinosResource *core_resource;
@ -47,9 +61,6 @@ struct _PinosClient {
SpaList resource_list;
PinosSendFunc send_func;
void *send_data;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosClient *client));
};
@ -57,6 +68,17 @@ struct _PinosClient {
PinosClient * pinos_client_new (PinosCore *core,
PinosProperties *properties);
void pinos_client_destroy (PinosClient *client);
void pinos_client_set_send (PinosClient *client,
PinosSendFunc func,
void *data);
SpaResult pinos_client_send_message (PinosClient *client,
PinosResource *resource,
uint32_t opcode,
void *message,
bool flush);
void pinos_client_update_properties (PinosClient *client,
const SpaDict *dict);

View file

@ -23,6 +23,11 @@
#include <pinos/server/data-loop.h>
#include <pinos/server/client-node.h>
typedef struct {
PinosGlobal this;
PinosBindFunc bind;
} PinosGlobalImpl;
typedef struct {
PinosCore this;
@ -36,6 +41,7 @@ registry_dispatch_func (void *object,
void *message,
void *data)
{
SpaResult res;
PinosResource *resource = object;
PinosClient *client = resource->client;
PinosCore *this = data;
@ -56,22 +62,16 @@ registry_dispatch_func (void *object,
"unknown object id %u", m->id);
return SPA_RESULT_ERROR;
}
if (global->bind == NULL) {
pinos_resource_send_error (resource,
SPA_RESULT_NOT_IMPLEMENTED,
"can't bind object id %d", m->id);
return SPA_RESULT_ERROR;
}
pinos_log_debug ("global %p: bind object id %d", global, m->id);
global->bind (global, client, 0, m->id);
res = pinos_global_bind (global, client, 0, m->id);
break;
}
default:
pinos_log_error ("unhandled message %d", type);
res = SPA_RESULT_NOT_IMPLEMENTED;
break;
}
return SPA_RESULT_OK;
return res;
}
static void
@ -116,8 +116,9 @@ core_dispatch_func (void *object,
if (registry_resource == NULL)
goto no_mem;
registry_resource->dispatch_func = registry_dispatch_func;
registry_resource->dispatch_data = this;
pinos_resource_set_dispatch (registry_resource,
registry_dispatch_func,
this);
spa_list_insert (this->registry_resource_list.prev, &registry_resource->link);
@ -191,7 +192,7 @@ no_mem:
return SPA_RESULT_NO_MEMORY;
}
static void
static SpaResult
core_bind_func (PinosGlobal *global,
PinosClient *client,
uint32_t version,
@ -204,14 +205,15 @@ core_bind_func (PinosGlobal *global,
resource = pinos_resource_new (client,
id,
global->core->uri.core,
global->type,
global->object,
NULL);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = core_dispatch_func;
resource->dispatch_data = this;
pinos_resource_set_dispatch (resource,
core_dispatch_func,
this);
client->core_resource = resource;
@ -228,14 +230,13 @@ core_bind_func (PinosGlobal *global,
info.cookie = random ();
info.props = NULL;
pinos_resource_send_message (resource,
PINOS_MESSAGE_CORE_INFO,
&m,
true);
return;
return pinos_resource_send_message (resource,
PINOS_MESSAGE_CORE_INFO,
&m,
true);
no_mem:
pinos_log_error ("can't create core resource");
return SPA_RESULT_NO_MEMORY;
}
PinosCore *
@ -256,6 +257,7 @@ pinos_core_new (PinosMainLoop *main_loop)
this->main_loop = main_loop;
pinos_uri_init (&this->uri);
pinos_access_init (&this->access);
pinos_map_init (&this->objects, 512);
impl->support[0].uri = SPA_ID_MAP_URI;
@ -290,6 +292,7 @@ pinos_core_new (PinosMainLoop *main_loop)
pinos_signal_init (&this->node_unlink_done);
this->global = pinos_core_add_global (this,
NULL,
this->uri.core,
0,
this,
@ -315,44 +318,70 @@ pinos_core_destroy (PinosCore *core)
}
PinosGlobal *
pinos_core_add_global (PinosCore *core,
uint32_t type,
uint32_t version,
void *object,
PinosBindFunc bind)
pinos_core_add_global (PinosCore *core,
PinosClient *owner,
uint32_t type,
uint32_t version,
void *object,
PinosBindFunc bind)
{
PinosGlobal *global;
PinosGlobalImpl *impl;
PinosGlobal *this;
PinosResource *registry;
PinosMessageNotifyGlobal ng;
global = calloc (1, sizeof (PinosGlobal));
if (global == NULL)
impl = calloc (1, sizeof (PinosGlobalImpl));
if (impl == NULL)
return NULL;
global->core = core;
global->type = type;
global->version = version;
global->object = object;
global->bind = bind;
this = &impl->this;
impl->bind = bind;
pinos_signal_init (&global->destroy_signal);
this->core = core;
this->owner = owner;
this->type = type;
this->version = version;
this->object = object;
global->id = pinos_map_insert_new (&core->objects, global);
pinos_signal_init (&this->destroy_signal);
spa_list_insert (core->global_list.prev, &global->link);
pinos_signal_emit (&core->global_added, core, global);
this->id = pinos_map_insert_new (&core->objects, this);
pinos_log_debug ("global %p: new %u", global, global->id);
spa_list_insert (core->global_list.prev, &this->link);
pinos_signal_emit (&core->global_added, core, this);
ng.id = global->id;
ng.type = spa_id_map_get_uri (core->uri.map, global->type);
pinos_log_debug ("global %p: new %u", this, this->id);
ng.id = this->id;
ng.type = spa_id_map_get_uri (core->uri.map, this->type);
spa_list_for_each (registry, &core->registry_resource_list, link) {
pinos_resource_send_message (registry,
PINOS_MESSAGE_NOTIFY_GLOBAL,
&ng,
true);
}
return global;
return this;
}
SpaResult
pinos_global_bind (PinosGlobal *global,
PinosClient *client,
uint32_t version,
uint32_t id)
{
SpaResult res;
PinosGlobalImpl *impl = SPA_CONTAINER_OF (global, PinosGlobalImpl, this);
if (impl->bind) {
res = impl->bind (global, client, version, id);
} else {
res = SPA_RESULT_NOT_IMPLEMENTED;
pinos_resource_send_error (client->core_resource,
res,
"can't bind object id %d", id);
}
return res;
}
static void

View file

@ -31,26 +31,26 @@ typedef struct _PinosGlobal PinosGlobal;
#include <pinos/client/uri.h>
#include <pinos/server/access.h>
#include <pinos/server/main-loop.h>
#include <pinos/server/data-loop.h>
#include <pinos/server/node.h>
#include <pinos/server/link.h>
#include <pinos/server/node-factory.h>
typedef void (*PinosBindFunc) (PinosGlobal *global,
PinosClient *client,
uint32_t version,
uint32_t id);
typedef SpaResult (*PinosBindFunc) (PinosGlobal *global,
PinosClient *client,
uint32_t version,
uint32_t id);
struct _PinosGlobal {
PinosCore *core;
SpaList link;
uint32_t id;
uint32_t type;
uint32_t version;
void *object;
PinosBindFunc bind;
PinosCore *core;
PinosClient *owner;
SpaList link;
uint32_t id;
uint32_t type;
uint32_t version;
void *object;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosGlobal *global));
@ -65,6 +65,7 @@ struct _PinosCore {
PinosGlobal *global;
PinosURI uri;
PinosAccess access;
PinosMap objects;
@ -119,12 +120,18 @@ struct _PinosCore {
PinosCore * pinos_core_new (PinosMainLoop *main_loop);
void pinos_core_destroy (PinosCore *core);
PinosGlobal * pinos_core_add_global (PinosCore *core,
uint32_t type,
uint32_t version,
void *object,
PinosBindFunc bind);
void pinos_global_destroy (PinosGlobal *global);
PinosGlobal * pinos_core_add_global (PinosCore *core,
PinosClient *owner,
uint32_t type,
uint32_t version,
void *object,
PinosBindFunc bind);
SpaResult pinos_global_bind (PinosGlobal *global,
PinosClient *client,
uint32_t version,
uint32_t id);
void pinos_global_destroy (PinosGlobal *global);
PinosPort * pinos_core_find_port (PinosCore *core,

View file

@ -756,7 +756,7 @@ link_unbind_func (void *data)
spa_list_remove (&resource->link);
}
static void
static SpaResult
link_bind_func (PinosGlobal *global,
PinosClient *client,
uint32_t version,
@ -769,14 +769,15 @@ link_bind_func (PinosGlobal *global,
resource = pinos_resource_new (client,
id,
global->core->uri.link,
global->type,
global->object,
link_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = link_dispatch_func;
resource->dispatch_data = global;
pinos_resource_set_dispatch (resource,
link_dispatch_func,
global);
pinos_log_debug ("link %p: bound to %d", global->object, resource->id);
@ -789,16 +790,15 @@ link_bind_func (PinosGlobal *global,
info.output_port_id = this->output ? this->output->port_id : -1;
info.input_node_id = this->input ? this->input->node->global->id : -1;
info.input_port_id = this->input ? this->input->port_id : -1;
pinos_resource_send_message (resource,
PINOS_MESSAGE_LINK_INFO,
&m,
true);
return;
return pinos_resource_send_message (resource,
PINOS_MESSAGE_LINK_INFO,
&m,
true);
no_mem:
pinos_resource_send_error (client->core_resource,
SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY;
}
PinosLink *
@ -853,6 +853,7 @@ pinos_link_new (PinosCore *core,
spa_list_insert (core->link_list.prev, &this->link);
this->global = pinos_core_add_global (core,
NULL,
core->uri.link,
0,
this,

View file

@ -1,4 +1,5 @@
pinoscore_headers = [
'access.h',
'client.h',
'client-node.h',
'command.h',
@ -14,6 +15,7 @@ pinoscore_headers = [
]
pinoscore_sources = [
'access.c',
'client.c',
'client-node.c',
'command.c',

View file

@ -107,7 +107,7 @@ module_dispatch_func (void *object,
return SPA_RESULT_OK;
}
static void
static SpaResult
module_bind_func (PinosGlobal *global,
PinosClient *client,
uint32_t version,
@ -120,14 +120,15 @@ module_bind_func (PinosGlobal *global,
resource = pinos_resource_new (client,
id,
global->core->uri.module,
global->type,
global->object,
NULL);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = module_dispatch_func;
resource->dispatch_data = global;
pinos_resource_set_dispatch (resource,
module_dispatch_func,
global);
pinos_log_debug ("module %p: bound to %d", global->object, resource->id);
@ -139,16 +140,15 @@ module_bind_func (PinosGlobal *global,
info.args = this->args;
info.props = NULL;
pinos_resource_send_message (resource,
PINOS_MESSAGE_MODULE_INFO,
&m,
true);
return;
return pinos_resource_send_message (resource,
PINOS_MESSAGE_MODULE_INFO,
&m,
true);
no_mem:
pinos_resource_send_error (resource,
SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY;
}
/**
@ -226,6 +226,7 @@ pinos_module_load (PinosCore *core,
pinos_log_debug ("loaded module: %s", this->name);
this->global = pinos_core_add_global (core,
NULL,
core->uri.module,
0,
impl,

View file

@ -406,7 +406,7 @@ node_unbind_func (void *data)
spa_list_remove (&resource->link);
}
static void
static SpaResult
node_bind_func (PinosGlobal *global,
PinosClient *client,
uint32_t version,
@ -419,14 +419,15 @@ node_bind_func (PinosGlobal *global,
resource = pinos_resource_new (client,
id,
global->core->uri.registry,
global->type,
global->object,
node_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = node_dispatch_func;
resource->dispatch_data = global;
pinos_resource_set_dispatch (resource,
node_dispatch_func,
global);
pinos_log_debug ("node %p: bound to %d", this, resource->id);
@ -440,16 +441,15 @@ node_bind_func (PinosGlobal *global,
info.error = this->error;
info.props = this->properties ? &this->properties->dict : NULL;
pinos_resource_send_message (resource,
PINOS_MESSAGE_NODE_INFO,
&m,
true);
return;
return pinos_resource_send_message (resource,
PINOS_MESSAGE_NODE_INFO,
&m,
true);
no_mem:
pinos_resource_send_error (resource,
SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY;
}
static void
@ -466,6 +466,7 @@ init_complete (PinosNode *this)
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
this->global = pinos_core_add_global (this->core,
NULL,
this->core->uri.node,
0,
this,

View file

@ -21,6 +21,13 @@
#include "pinos/server/resource.h"
typedef struct {
PinosResource this;
PinosDispatchFunc dispatch_func;
void *dispatch_data;
} PinosResourceImpl;
PinosResource *
pinos_resource_new (PinosClient *client,
uint32_t id,
@ -28,12 +35,15 @@ pinos_resource_new (PinosClient *client,
void *object,
PinosDestroy destroy)
{
PinosResourceImpl *impl;
PinosResource *this;
this = calloc (1, sizeof (PinosResource));
if (this == NULL)
impl = calloc (1, sizeof (PinosResourceImpl));
if (impl == NULL)
return NULL;
this = &impl->this;
this->core = client->core;
this->client = client;
this->id = id;
@ -41,9 +51,6 @@ pinos_resource_new (PinosClient *client,
this->object = object;
this->destroy = destroy;
this->send_func = client->send_func;
this->send_data = client->send_data;
pinos_signal_init (&this->destroy_signal);
this->id = pinos_map_insert_new (&client->objects, this);
@ -92,23 +99,82 @@ pinos_resource_destroy (PinosResource *resource)
return SPA_RESULT_OK;
}
void
pinos_resource_set_dispatch (PinosResource *resource,
PinosDispatchFunc func,
void *data)
{
PinosResourceImpl *impl = SPA_CONTAINER_OF (resource, PinosResourceImpl, this);
impl->dispatch_func = func;
impl->dispatch_data = data;
}
static SpaResult
do_dispatch_message (PinosAccessData *data)
{
PinosResourceImpl *impl = SPA_CONTAINER_OF (data->resource, PinosResourceImpl, this);
if (data->res == SPA_RESULT_NO_PERMISSION) {
pinos_resource_send_error (data->resource,
data->res,
"no permission");
} else if (SPA_RESULT_IS_ERROR (data->res)) {
pinos_resource_send_error (data->resource,
data->res,
"error %d", data->res);
} else {
data->res = impl->dispatch_func (data->resource,
data->opcode,
data->message,
impl->dispatch_data);
}
return data->res;
}
SpaResult
pinos_resource_dispatch (PinosResource *resource,
uint32_t opcode,
void *message)
{
PinosResourceImpl *impl = SPA_CONTAINER_OF (resource, PinosResourceImpl, this);
if (impl->dispatch_func) {
PinosAccessData data;
data.client = resource->client;
data.resource = resource;
data.opcode = opcode;
data.message = message;
data.flush = false;
data.res = SPA_RESULT_OK;
pinos_signal_emit (&resource->core->access.check_dispatch,
do_dispatch_message,
&data);
if (SPA_RESULT_IS_ASYNC (data.res))
return data.res;
return do_dispatch_message (&data);
}
pinos_log_error ("resource %p: dispatch func not implemented", resource);
return SPA_RESULT_NOT_IMPLEMENTED;
}
SpaResult
pinos_resource_send_message (PinosResource *resource,
uint32_t opcode,
void *message,
bool flush)
{
if (!resource->send_func) {
pinos_log_error ("resource %p: send func not implemented", resource);
return SPA_RESULT_NOT_IMPLEMENTED;
}
return resource->send_func (resource,
resource->id,
opcode,
message,
flush,
resource->send_data);
return pinos_client_send_message (resource->client,
resource,
opcode,
message,
flush);
}
SpaResult

View file

@ -29,17 +29,14 @@ extern "C" {
typedef struct _PinosResource PinosResource;
#include <spa/include/spa/list.h>
#include <pinos/client/sig.h>
#include <pinos/server/core.h>
typedef void (*PinosDestroy) (void *object);
typedef SpaResult (*PinosSendFunc) (void *object,
uint32_t id,
uint32_t opcode,
void *message,
bool flush,
void *data);
typedef SpaResult (*PinosDispatchFunc) (void *object,
uint32_t opcode,
void *message,
@ -56,22 +53,25 @@ struct _PinosResource {
void *object;
PinosDestroy destroy;
PinosSendFunc send_func;
void *send_data;
PinosDispatchFunc dispatch_func;
void *dispatch_data;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosResource *resource));
};
PinosResource * pinos_resource_new (PinosClient *client,
uint32_t id,
uint32_t type,
void *object,
PinosDestroy destroy);
PinosResource * pinos_resource_new (PinosClient *client,
uint32_t id,
uint32_t type,
void *object,
PinosDestroy destroy);
SpaResult pinos_resource_destroy (PinosResource *resource);
void pinos_resource_set_dispatch (PinosResource *resource,
PinosDispatchFunc func,
void *data);
SpaResult pinos_resource_dispatch (PinosResource *resource,
uint32_t opcode,
void *message);
SpaResult pinos_resource_send_message (PinosResource *resource,
uint32_t opcode,
void *message,