mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
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:
parent
a8964ca657
commit
ee0aa6a2ac
27 changed files with 819 additions and 220 deletions
|
|
@ -37,6 +37,9 @@ typedef struct {
|
||||||
SpaSource source;
|
SpaSource source;
|
||||||
|
|
||||||
bool disconnecting;
|
bool disconnecting;
|
||||||
|
|
||||||
|
PinosSendFunc send_func;
|
||||||
|
void *send_data;
|
||||||
} PinosContextImpl;
|
} PinosContextImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -334,32 +337,40 @@ registry_dispatch_func (void *object,
|
||||||
this->uri.node);
|
this->uri.node);
|
||||||
if (proxy == NULL)
|
if (proxy == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
proxy->dispatch_func = node_dispatch_func;
|
|
||||||
proxy->dispatch_data = impl;
|
pinos_proxy_set_dispatch (proxy,
|
||||||
|
node_dispatch_func,
|
||||||
|
impl);
|
||||||
} else if (!strcmp (ng->type, PINOS_MODULE_URI)) {
|
} else if (!strcmp (ng->type, PINOS_MODULE_URI)) {
|
||||||
proxy = pinos_proxy_new (this,
|
proxy = pinos_proxy_new (this,
|
||||||
SPA_ID_INVALID,
|
SPA_ID_INVALID,
|
||||||
this->uri.module);
|
this->uri.module);
|
||||||
if (proxy == NULL)
|
if (proxy == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
proxy->dispatch_func = module_dispatch_func;
|
|
||||||
proxy->dispatch_data = impl;
|
pinos_proxy_set_dispatch (proxy,
|
||||||
|
module_dispatch_func,
|
||||||
|
impl);
|
||||||
} else if (!strcmp (ng->type, PINOS_CLIENT_URI)) {
|
} else if (!strcmp (ng->type, PINOS_CLIENT_URI)) {
|
||||||
proxy = pinos_proxy_new (this,
|
proxy = pinos_proxy_new (this,
|
||||||
SPA_ID_INVALID,
|
SPA_ID_INVALID,
|
||||||
this->uri.client);
|
this->uri.client);
|
||||||
if (proxy == NULL)
|
if (proxy == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
proxy->dispatch_func = client_dispatch_func;
|
|
||||||
proxy->dispatch_data = impl;
|
pinos_proxy_set_dispatch (proxy,
|
||||||
|
client_dispatch_func,
|
||||||
|
impl);
|
||||||
} else if (!strcmp (ng->type, PINOS_LINK_URI)) {
|
} else if (!strcmp (ng->type, PINOS_LINK_URI)) {
|
||||||
proxy = pinos_proxy_new (this,
|
proxy = pinos_proxy_new (this,
|
||||||
SPA_ID_INVALID,
|
SPA_ID_INVALID,
|
||||||
this->uri.link);
|
this->uri.link);
|
||||||
if (proxy == NULL)
|
if (proxy == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
proxy->dispatch_func = link_dispatch_func;
|
|
||||||
proxy->dispatch_data = impl;
|
pinos_proxy_set_dispatch (proxy,
|
||||||
|
link_dispatch_func,
|
||||||
|
impl);
|
||||||
}
|
}
|
||||||
if (proxy) {
|
if (proxy) {
|
||||||
PinosMessageBind m;
|
PinosMessageBind m;
|
||||||
|
|
@ -431,12 +442,8 @@ on_context_data (SpaSource *source,
|
||||||
pinos_log_error ("context %p: could not find proxy %u", this, id);
|
pinos_log_error ("context %p: could not find proxy %u", this, id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (proxy->dispatch_func == NULL) {
|
|
||||||
pinos_log_error ("context %p: no dispatch function for proxy %u", this, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy->dispatch_func (proxy, type, p, proxy->dispatch_data);
|
pinos_proxy_dispatch (proxy, type, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -502,8 +509,9 @@ pinos_context_new (PinosLoop *loop,
|
||||||
|
|
||||||
this->state = PINOS_CONTEXT_STATE_UNCONNECTED;
|
this->state = PINOS_CONTEXT_STATE_UNCONNECTED;
|
||||||
|
|
||||||
this->send_func = context_send_func;
|
pinos_context_set_send (this,
|
||||||
this->send_data = this;
|
context_send_func,
|
||||||
|
this);
|
||||||
|
|
||||||
pinos_map_init (&this->objects, 64);
|
pinos_map_init (&this->objects, 64);
|
||||||
|
|
||||||
|
|
@ -621,8 +629,9 @@ pinos_context_connect (PinosContext *context)
|
||||||
if (context->core_proxy == NULL)
|
if (context->core_proxy == NULL)
|
||||||
goto no_proxy;
|
goto no_proxy;
|
||||||
|
|
||||||
context->core_proxy->dispatch_func = core_dispatch_func;
|
pinos_proxy_set_dispatch (context->core_proxy,
|
||||||
context->core_proxy->dispatch_data = impl;
|
core_dispatch_func,
|
||||||
|
impl);
|
||||||
|
|
||||||
cu.props = &context->properties->dict;
|
cu.props = &context->properties->dict;
|
||||||
pinos_proxy_send_message (context->core_proxy,
|
pinos_proxy_send_message (context->core_proxy,
|
||||||
|
|
@ -636,8 +645,9 @@ pinos_context_connect (PinosContext *context)
|
||||||
if (context->registry_proxy == NULL)
|
if (context->registry_proxy == NULL)
|
||||||
goto no_registry;
|
goto no_registry;
|
||||||
|
|
||||||
context->registry_proxy->dispatch_func = registry_dispatch_func;
|
pinos_proxy_set_dispatch (context->registry_proxy,
|
||||||
context->registry_proxy->dispatch_data = impl;
|
registry_dispatch_func,
|
||||||
|
impl);
|
||||||
|
|
||||||
grm.seq = 0;
|
grm.seq = 0;
|
||||||
grm.new_id = context->registry_proxy->id;
|
grm.new_id = context->registry_proxy->id;
|
||||||
|
|
@ -681,6 +691,35 @@ pinos_context_disconnect (PinosContext *context)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pinos_context_set_send (PinosContext *context,
|
||||||
|
PinosSendFunc func,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this);
|
||||||
|
|
||||||
|
impl->send_func = func;
|
||||||
|
impl->send_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpaResult
|
||||||
|
pinos_context_send_message (PinosContext *context,
|
||||||
|
PinosProxy *proxy,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message,
|
||||||
|
bool flush)
|
||||||
|
{
|
||||||
|
PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this);
|
||||||
|
|
||||||
|
if (impl->send_func)
|
||||||
|
return impl->send_func (proxy, proxy->id, opcode, message, flush, impl->send_data);
|
||||||
|
|
||||||
|
pinos_log_error ("context %p: send func not implemented", context);
|
||||||
|
|
||||||
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pinos_context_get_core_info (PinosContext *context,
|
pinos_context_get_core_info (PinosContext *context,
|
||||||
PinosCoreInfoCallback cb,
|
PinosCoreInfoCallback cb,
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,12 @@ typedef struct _PinosContext PinosContext;
|
||||||
#include <pinos/client/proxy.h>
|
#include <pinos/client/proxy.h>
|
||||||
#include <pinos/client/uri.h>
|
#include <pinos/client/uri.h>
|
||||||
|
|
||||||
|
typedef SpaResult (*PinosSendFunc) (void *object,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message,
|
||||||
|
bool flush,
|
||||||
|
void *data);
|
||||||
/**
|
/**
|
||||||
* PinosContextState:
|
* PinosContextState:
|
||||||
* @PINOS_CONTEXT_STATE_ERROR: context is in error
|
* @PINOS_CONTEXT_STATE_ERROR: context is in error
|
||||||
|
|
@ -73,9 +79,6 @@ struct _PinosContext {
|
||||||
SpaList stream_list;
|
SpaList stream_list;
|
||||||
SpaList proxy_list;
|
SpaList proxy_list;
|
||||||
|
|
||||||
PinosSendFunc send_func;
|
|
||||||
void *send_data;
|
|
||||||
|
|
||||||
PinosContextState state;
|
PinosContextState state;
|
||||||
char *error;
|
char *error;
|
||||||
PINOS_SIGNAL (state_changed, (PinosListener *listener,
|
PINOS_SIGNAL (state_changed, (PinosListener *listener,
|
||||||
|
|
@ -96,6 +99,16 @@ PinosContext * pinos_context_new (PinosLoop *loop,
|
||||||
PinosProperties *properties);
|
PinosProperties *properties);
|
||||||
void pinos_context_destroy (PinosContext *context);
|
void pinos_context_destroy (PinosContext *context);
|
||||||
|
|
||||||
|
void pinos_context_set_send (PinosContext *context,
|
||||||
|
PinosSendFunc func,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
SpaResult pinos_context_send_message (PinosContext *context,
|
||||||
|
PinosProxy *proxy,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message,
|
||||||
|
bool flush);
|
||||||
|
|
||||||
bool pinos_context_connect (PinosContext *context);
|
bool pinos_context_connect (PinosContext *context);
|
||||||
bool pinos_context_disconnect (PinosContext *context);
|
bool pinos_context_disconnect (PinosContext *context);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ struct _PinosMap {
|
||||||
#define pinos_map_item_is_free(item) ((item)->next & 0x1)
|
#define pinos_map_item_is_free(item) ((item)->next & 0x1)
|
||||||
#define pinos_map_id_is_free(m,id) (pinos_map_item_is_free (pinos_map_get_item(m,id)))
|
#define pinos_map_id_is_free(m,id) (pinos_map_item_is_free (pinos_map_get_item(m,id)))
|
||||||
#define pinos_map_check_id(m,id) ((id) < pinos_map_get_size (m))
|
#define pinos_map_check_id(m,id) ((id) < pinos_map_get_size (m))
|
||||||
#define pinos_map_has_item(m,id) (pinos_map_check_id(m,id) && !pinos_map_item_is_free(m, id))
|
#define pinos_map_has_item(m,id) (pinos_map_check_id(m,id) && !pinos_map_id_is_free(m, id))
|
||||||
#define pinos_map_lookup_unchecked(m,id) pinos_map_get_item(m,id)->data
|
#define pinos_map_lookup_unchecked(m,id) pinos_map_get_item(m,id)->data
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
@ -100,8 +100,11 @@ static inline void *
|
||||||
pinos_map_lookup (PinosMap *map,
|
pinos_map_lookup (PinosMap *map,
|
||||||
uint32_t id)
|
uint32_t id)
|
||||||
{
|
{
|
||||||
if (SPA_LIKELY (pinos_map_check_id (map, id)))
|
if (SPA_LIKELY (pinos_map_check_id (map, id))) {
|
||||||
return pinos_map_lookup_unchecked (map, id);
|
PinosMapItem *item = pinos_map_get_item (map, id);
|
||||||
|
if (!pinos_map_item_is_free (item))
|
||||||
|
return item->data;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _PinosProperties PinosProperties;
|
typedef struct _PinosProperties PinosProperties;
|
||||||
|
|
||||||
|
#include <spa/include/spa/dict.h>
|
||||||
|
|
||||||
struct _PinosProperties {
|
struct _PinosProperties {
|
||||||
SpaDict dict;
|
SpaDict dict;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinosProxy this;
|
PinosProxy this;
|
||||||
|
|
||||||
|
PinosDispatchFunc dispatch_func;
|
||||||
|
void *dispatch_data;
|
||||||
} PinosProxyImpl;
|
} PinosProxyImpl;
|
||||||
|
|
||||||
PinosProxy *
|
PinosProxy *
|
||||||
|
|
@ -40,8 +43,6 @@ pinos_proxy_new (PinosContext *context,
|
||||||
|
|
||||||
this->context = context;
|
this->context = context;
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->send_func = context->send_func;
|
|
||||||
this->send_data = context->send_data;
|
|
||||||
|
|
||||||
pinos_signal_init (&this->destroy_signal);
|
pinos_signal_init (&this->destroy_signal);
|
||||||
|
|
||||||
|
|
@ -64,16 +65,41 @@ pinos_proxy_destroy (PinosProxy *proxy)
|
||||||
free (impl);
|
free (impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pinos_proxy_set_dispatch (PinosProxy *proxy,
|
||||||
|
PinosDispatchFunc func,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
PinosProxyImpl *impl = SPA_CONTAINER_OF (proxy, PinosProxyImpl, this);
|
||||||
|
|
||||||
|
impl->dispatch_func = func;
|
||||||
|
impl->dispatch_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
SpaResult
|
SpaResult
|
||||||
pinos_proxy_send_message (PinosProxy *proxy,
|
pinos_proxy_send_message (PinosProxy *proxy,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
void *message,
|
void *message,
|
||||||
bool flush)
|
bool flush)
|
||||||
{
|
{
|
||||||
if (proxy->send_func)
|
return pinos_context_send_message (proxy->context,
|
||||||
return proxy->send_func (proxy, proxy->id, opcode, message, flush, proxy->send_data);
|
proxy,
|
||||||
|
opcode,
|
||||||
|
message,
|
||||||
|
flush);
|
||||||
|
}
|
||||||
|
|
||||||
pinos_log_error ("proxy %p: send func not implemented", proxy);
|
SpaResult
|
||||||
|
pinos_proxy_dispatch (PinosProxy *proxy,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message)
|
||||||
|
{
|
||||||
|
PinosProxyImpl *impl = SPA_CONTAINER_OF (proxy, PinosProxyImpl, this);
|
||||||
|
|
||||||
|
if (impl->dispatch_func)
|
||||||
|
return impl->dispatch_func (proxy, opcode, message, impl->dispatch_data);
|
||||||
|
|
||||||
|
pinos_log_error ("proxy %p: dispatch func not implemented", proxy);
|
||||||
|
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,6 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _PinosProxy PinosProxy;
|
typedef struct _PinosProxy PinosProxy;
|
||||||
|
|
||||||
typedef SpaResult (*PinosSendFunc) (void *object,
|
|
||||||
uint32_t id,
|
|
||||||
uint32_t opcode,
|
|
||||||
void *message,
|
|
||||||
bool flush,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef SpaResult (*PinosDispatchFunc) (void *object,
|
typedef SpaResult (*PinosDispatchFunc) (void *object,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
|
|
@ -47,11 +41,6 @@ struct _PinosProxy {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
|
||||||
PinosSendFunc send_func;
|
|
||||||
void *send_data;
|
|
||||||
PinosDispatchFunc dispatch_func;
|
|
||||||
void *dispatch_data;
|
|
||||||
|
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||||
|
|
@ -63,11 +52,18 @@ PinosProxy * pinos_proxy_new (PinosContext *contex
|
||||||
uint32_t type);
|
uint32_t type);
|
||||||
void pinos_proxy_destroy (PinosProxy *proxy);
|
void pinos_proxy_destroy (PinosProxy *proxy);
|
||||||
|
|
||||||
|
void pinos_proxy_set_dispatch (PinosProxy *proxy,
|
||||||
|
PinosDispatchFunc func,
|
||||||
|
void *data);
|
||||||
|
|
||||||
SpaResult pinos_proxy_send_message (PinosProxy *proxy,
|
SpaResult pinos_proxy_send_message (PinosProxy *proxy,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
void *message,
|
void *message,
|
||||||
bool flush);
|
bool flush);
|
||||||
|
|
||||||
|
SpaResult pinos_proxy_dispatch (PinosProxy *proxy,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -868,8 +868,9 @@ pinos_stream_connect (PinosStream *stream,
|
||||||
SPA_ID_INVALID,
|
SPA_ID_INVALID,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
impl->node_proxy->dispatch_func = stream_dispatch_func;
|
pinos_proxy_set_dispatch (impl->node_proxy,
|
||||||
impl->node_proxy->dispatch_data = impl;
|
stream_dispatch_func,
|
||||||
|
impl);
|
||||||
|
|
||||||
ccn.seq = ++impl->seq;
|
ccn.seq = ++impl->seq;
|
||||||
ccn.name = "client-node";
|
ccn.name = "client-node";
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ load-module libpinos-module-protocol-native
|
||||||
load-module libpinos-module-suspend-on-idle
|
load-module libpinos-module-suspend-on-idle
|
||||||
load-module libpinos-module-spa --pattern snow
|
load-module libpinos-module-spa --pattern snow
|
||||||
load-module libpinos-module-autolink
|
load-module libpinos-module-autolink
|
||||||
|
load-module libpinos-module-access
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,15 @@ pinos_module_c_args = [
|
||||||
'-D_GNU_SOURCE',
|
'-D_GNU_SOURCE',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
pinos_module_access = shared_library('pinos-module-access', [ 'module-access.c' ],
|
||||||
|
c_args : pinos_module_c_args,
|
||||||
|
include_directories : [configinc, spa_inc],
|
||||||
|
link_with : spalib,
|
||||||
|
install : true,
|
||||||
|
install_dir : '@0@/pinos-0.1'.format(get_option('libdir')),
|
||||||
|
dependencies : [mathlib, dl_lib, pinos_dep, pinoscore_dep],
|
||||||
|
)
|
||||||
|
|
||||||
pinos_module_autolink = shared_library('pinos-module-autolink', [ 'module-autolink.c' ],
|
pinos_module_autolink = shared_library('pinos-module-autolink', [ 'module-autolink.c' ],
|
||||||
c_args : pinos_module_c_args,
|
c_args : pinos_module_c_args,
|
||||||
include_directories : [configinc, spa_inc],
|
include_directories : [configinc, spa_inc],
|
||||||
|
|
|
||||||
160
pinos/modules/module-access.c
Normal file
160
pinos/modules/module-access.c
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
/* Pinos
|
||||||
|
* Copyright (C) 2016 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 <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "pinos/server/core.h"
|
||||||
|
#include "pinos/server/module.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PinosCore *core;
|
||||||
|
PinosProperties *properties;
|
||||||
|
|
||||||
|
PinosListener check_send;
|
||||||
|
PinosListener check_dispatch;
|
||||||
|
} ModuleImpl;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
check_global_owner (PinosCore *core,
|
||||||
|
PinosClient *client,
|
||||||
|
uint32_t id)
|
||||||
|
{
|
||||||
|
PinosGlobal *global;
|
||||||
|
|
||||||
|
global = pinos_map_lookup (&core->objects, id);
|
||||||
|
|
||||||
|
return (global && global->owner == client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_check_send (PinosListener *listener,
|
||||||
|
PinosAccessFunc func,
|
||||||
|
PinosAccessData *data)
|
||||||
|
{
|
||||||
|
PinosClient *client = data->client;
|
||||||
|
PinosCore *core = client->core;
|
||||||
|
|
||||||
|
if (data->resource->type == core->uri.registry) {
|
||||||
|
switch (data->opcode) {
|
||||||
|
case PINOS_MESSAGE_NOTIFY_GLOBAL:
|
||||||
|
{
|
||||||
|
PinosMessageNotifyGlobal *m = data->message;
|
||||||
|
|
||||||
|
if (check_global_owner (core, client, m->id))
|
||||||
|
data->res = SPA_RESULT_OK;
|
||||||
|
else
|
||||||
|
data->res = SPA_RESULT_SKIPPED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE:
|
||||||
|
{
|
||||||
|
PinosMessageNotifyGlobalRemove *m = data->message;
|
||||||
|
|
||||||
|
if (check_global_owner (core, client, m->id))
|
||||||
|
data->res = SPA_RESULT_OK;
|
||||||
|
else
|
||||||
|
data->res = SPA_RESULT_SKIPPED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
data->res = SPA_RESULT_NO_PERMISSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->res = SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_check_dispatch (PinosListener *listener,
|
||||||
|
PinosAccessFunc func,
|
||||||
|
PinosAccessData *data)
|
||||||
|
{
|
||||||
|
PinosClient *client = data->client;
|
||||||
|
PinosCore *core = client->core;
|
||||||
|
|
||||||
|
if (data->resource->type == core->uri.registry) {
|
||||||
|
if (data->opcode == PINOS_MESSAGE_BIND) {
|
||||||
|
PinosMessageBind *m = data->message;
|
||||||
|
|
||||||
|
if (check_global_owner (core, client, m->id))
|
||||||
|
data->res = SPA_RESULT_OK;
|
||||||
|
else
|
||||||
|
data->res = SPA_RESULT_NO_PERMISSION;
|
||||||
|
} else {
|
||||||
|
data->res = SPA_RESULT_NO_PERMISSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->res = SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ModuleImpl *
|
||||||
|
module_new (PinosCore *core,
|
||||||
|
PinosProperties *properties)
|
||||||
|
{
|
||||||
|
ModuleImpl *impl;
|
||||||
|
|
||||||
|
impl = calloc (1, sizeof (ModuleImpl));
|
||||||
|
pinos_log_debug ("module %p: new", impl);
|
||||||
|
|
||||||
|
impl->core = core;
|
||||||
|
impl->properties = properties;
|
||||||
|
|
||||||
|
pinos_signal_add (&core->access.check_send,
|
||||||
|
&impl->check_send,
|
||||||
|
do_check_send);
|
||||||
|
pinos_signal_add (&core->access.check_dispatch,
|
||||||
|
&impl->check_dispatch,
|
||||||
|
do_check_dispatch);
|
||||||
|
|
||||||
|
return impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
module_destroy (ModuleImpl *impl)
|
||||||
|
{
|
||||||
|
pinos_log_debug ("module %p: destroy", impl);
|
||||||
|
|
||||||
|
pinos_global_destroy (impl->global);
|
||||||
|
|
||||||
|
pinos_signal_remove (&impl->global_added);
|
||||||
|
pinos_signal_remove (&impl->global_removed);
|
||||||
|
pinos_signal_remove (&impl->port_added);
|
||||||
|
pinos_signal_remove (&impl->port_removed);
|
||||||
|
pinos_signal_remove (&impl->port_unlinked);
|
||||||
|
pinos_signal_remove (&impl->link_state_changed);
|
||||||
|
free (impl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool
|
||||||
|
pinos__module_init (PinosModule * module, const char * args)
|
||||||
|
{
|
||||||
|
module_new (module->core, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -76,7 +76,6 @@ typedef struct {
|
||||||
SpaList link;
|
SpaList link;
|
||||||
PinosClient *client;
|
PinosClient *client;
|
||||||
int fd;
|
int fd;
|
||||||
struct ucred ucred;
|
|
||||||
SpaSource *source;
|
SpaSource *source;
|
||||||
PinosConnection *connection;
|
PinosConnection *connection;
|
||||||
} PinosProtocolNativeClient;
|
} PinosProtocolNativeClient;
|
||||||
|
|
@ -168,10 +167,9 @@ connection_data (SpaSource *source,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource->dispatch_func (resource,
|
pinos_resource_dispatch (resource,
|
||||||
type,
|
type,
|
||||||
message,
|
message);
|
||||||
resource->dispatch_data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,14 +178,14 @@ client_new (PinosProtocolNative *impl,
|
||||||
int fd)
|
int fd)
|
||||||
{
|
{
|
||||||
PinosProtocolNativeClient *this;
|
PinosProtocolNativeClient *this;
|
||||||
|
PinosClient *client;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
|
||||||
this = calloc (1, sizeof (PinosProtocolNativeClient));
|
this = calloc (1, sizeof (PinosProtocolNativeClient));
|
||||||
|
if (this == NULL)
|
||||||
|
goto no_native_client;
|
||||||
|
|
||||||
this->impl = impl;
|
this->impl = impl;
|
||||||
len = sizeof (this->ucred);
|
|
||||||
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &this->ucred, &len) < 0) {
|
|
||||||
pinos_log_error ("no peercred: %m");
|
|
||||||
}
|
|
||||||
this->fd = fd;
|
this->fd = fd;
|
||||||
this->source = pinos_loop_add_io (impl->core->main_loop->loop,
|
this->source = pinos_loop_add_io (impl->core->main_loop->loop,
|
||||||
this->fd,
|
this->fd,
|
||||||
|
|
@ -195,21 +193,48 @@ client_new (PinosProtocolNative *impl,
|
||||||
false,
|
false,
|
||||||
connection_data,
|
connection_data,
|
||||||
this);
|
this);
|
||||||
|
if (this->source == NULL)
|
||||||
|
goto no_source;
|
||||||
|
|
||||||
this->connection = pinos_connection_new (fd);
|
this->connection = pinos_connection_new (fd);
|
||||||
|
if (this->connection == NULL)
|
||||||
|
goto no_connection;
|
||||||
|
|
||||||
|
client = pinos_client_new (impl->core, NULL);
|
||||||
|
if (client == NULL)
|
||||||
|
goto no_client;
|
||||||
|
|
||||||
|
this->client = client;
|
||||||
|
|
||||||
|
pinos_client_set_send (client,
|
||||||
|
client_send_func,
|
||||||
|
this);
|
||||||
|
|
||||||
|
len = sizeof (client->ucred);
|
||||||
|
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &client->ucred, &len) < 0) {
|
||||||
|
client->ucred_valid = false;
|
||||||
|
pinos_log_error ("no peercred: %m");
|
||||||
|
} else {
|
||||||
|
client->ucred_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
spa_list_insert (impl->client_list.prev, &this->link);
|
spa_list_insert (impl->client_list.prev, &this->link);
|
||||||
|
|
||||||
this->client = pinos_client_new (impl->core, NULL);
|
pinos_global_bind (impl->core->global,
|
||||||
this->client->send_func = client_send_func;
|
client,
|
||||||
this->client->send_data = this;
|
|
||||||
|
|
||||||
impl->core->global->bind (impl->core->global,
|
|
||||||
this->client,
|
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
no_client:
|
||||||
|
pinos_connection_destroy (this->connection);
|
||||||
|
no_connection:
|
||||||
|
pinos_loop_destroy_source (impl->core->main_loop->loop,
|
||||||
|
this->source);
|
||||||
|
no_source:
|
||||||
|
free (this);
|
||||||
|
no_native_client:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Socket *
|
static Socket *
|
||||||
|
|
@ -326,7 +351,11 @@ socket_data (SpaSource *source,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client_new (impl, client_fd);
|
if (client_new (impl, client_fd) == NULL) {
|
||||||
|
pinos_log_error ("failed to create client");
|
||||||
|
close (client_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
|
||||||
27
pinos/server/access.c
Normal file
27
pinos/server/access.c
Normal 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
68
pinos/server/access.h
Normal 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__ */
|
||||||
|
|
@ -121,6 +121,7 @@ typedef struct
|
||||||
|
|
||||||
PinosListener transport_changed;
|
PinosListener transport_changed;
|
||||||
PinosListener loop_changed;
|
PinosListener loop_changed;
|
||||||
|
PinosListener global_added;
|
||||||
|
|
||||||
int data_fd;
|
int data_fd;
|
||||||
} PinosClientNodeImpl;
|
} PinosClientNodeImpl;
|
||||||
|
|
@ -1187,6 +1188,16 @@ on_loop_changed (PinosListener *listener,
|
||||||
impl->proxy.data_loop = node->data_loop->loop->loop;
|
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
|
static SpaResult
|
||||||
proxy_clear (SpaProxy *this)
|
proxy_clear (SpaProxy *this)
|
||||||
{
|
{
|
||||||
|
|
@ -1256,14 +1267,6 @@ pinos_client_node_new (PinosClient *client,
|
||||||
|
|
||||||
impl->proxy.pnode = this->node;
|
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,
|
this->resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
client->core->uri.client_node,
|
client->core->uri.client_node,
|
||||||
|
|
@ -1273,8 +1276,22 @@ pinos_client_node_new (PinosClient *client,
|
||||||
goto error_no_resource;
|
goto error_no_resource;
|
||||||
|
|
||||||
impl->proxy.resource = this->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;
|
return this;
|
||||||
|
|
||||||
|
|
@ -1312,6 +1329,8 @@ pinos_client_node_destroy (PinosClientNode * this)
|
||||||
pinos_log_debug ("client-node %p: destroy", impl);
|
pinos_log_debug ("client-node %p: destroy", impl);
|
||||||
pinos_signal_emit (&this->destroy_signal, this);
|
pinos_signal_emit (&this->destroy_signal, this);
|
||||||
|
|
||||||
|
pinos_signal_remove (&impl->global_added);
|
||||||
|
|
||||||
pinos_node_destroy (this->node);
|
pinos_node_destroy (this->node);
|
||||||
|
|
||||||
pinos_main_loop_defer (this->node->core->main_loop,
|
pinos_main_loop_defer (this->node->core->main_loop,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PinosClient this;
|
PinosClient this;
|
||||||
|
|
||||||
|
PinosSendFunc send_func;
|
||||||
|
void *send_data;
|
||||||
} PinosClientImpl;
|
} PinosClientImpl;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,7 +56,7 @@ client_unbind_func (void *data)
|
||||||
spa_list_remove (&resource->link);
|
spa_list_remove (&resource->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SpaResult
|
||||||
client_bind_func (PinosGlobal *global,
|
client_bind_func (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
|
|
@ -66,14 +69,15 @@ client_bind_func (PinosGlobal *global,
|
||||||
|
|
||||||
resource = pinos_resource_new (client,
|
resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
global->core->uri.client,
|
global->type,
|
||||||
global->object,
|
global->object,
|
||||||
client_unbind_func);
|
client_unbind_func);
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
resource->dispatch_func = client_dispatch_func;
|
pinos_resource_set_dispatch (resource,
|
||||||
resource->dispatch_data = global;
|
client_dispatch_func,
|
||||||
|
global);
|
||||||
|
|
||||||
pinos_log_debug ("client %p: bound to %d", global->object, resource->id);
|
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.change_mask = ~0;
|
||||||
info.props = this->properties ? &this->properties->dict : NULL;
|
info.props = this->properties ? &this->properties->dict : NULL;
|
||||||
|
|
||||||
pinos_resource_send_message (resource,
|
return pinos_resource_send_message (resource,
|
||||||
PINOS_MESSAGE_CLIENT_INFO,
|
PINOS_MESSAGE_CLIENT_INFO,
|
||||||
&m,
|
&m,
|
||||||
true);
|
true);
|
||||||
return;
|
|
||||||
|
|
||||||
no_mem:
|
no_mem:
|
||||||
pinos_resource_send_error (client->core_resource,
|
pinos_resource_send_error (client->core_resource,
|
||||||
SPA_RESULT_NO_MEMORY,
|
SPA_RESULT_NO_MEMORY,
|
||||||
"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);
|
spa_list_insert (core->client_list.prev, &this->link);
|
||||||
|
|
||||||
this->global = pinos_core_add_global (core,
|
this->global = pinos_core_add_global (core,
|
||||||
|
this,
|
||||||
core->uri.client,
|
core->uri.client,
|
||||||
0,
|
0,
|
||||||
this,
|
this,
|
||||||
|
|
@ -191,6 +195,78 @@ pinos_client_destroy (PinosClient * client)
|
||||||
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
|
void
|
||||||
pinos_client_update_properties (PinosClient *client,
|
pinos_client_update_properties (PinosClient *client,
|
||||||
const SpaDict *dict)
|
const SpaDict *dict)
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,21 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _PinosClient PinosClient;
|
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/core.h>
|
||||||
#include <pinos/server/resource.h>
|
#include <pinos/server/resource.h>
|
||||||
|
|
||||||
|
typedef SpaResult (*PinosSendFunc) (void *object,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t opcode,
|
||||||
|
void *message,
|
||||||
|
bool flush,
|
||||||
|
void *data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PinosClient:
|
* PinosClient:
|
||||||
*
|
*
|
||||||
|
|
@ -40,6 +52,8 @@ struct _PinosClient {
|
||||||
PinosGlobal *global;
|
PinosGlobal *global;
|
||||||
|
|
||||||
PinosProperties *properties;
|
PinosProperties *properties;
|
||||||
|
bool ucred_valid;
|
||||||
|
struct ucred ucred;
|
||||||
|
|
||||||
PinosResource *core_resource;
|
PinosResource *core_resource;
|
||||||
|
|
||||||
|
|
@ -47,9 +61,6 @@ struct _PinosClient {
|
||||||
|
|
||||||
SpaList resource_list;
|
SpaList resource_list;
|
||||||
|
|
||||||
PinosSendFunc send_func;
|
|
||||||
void *send_data;
|
|
||||||
|
|
||||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||||
PinosClient *client));
|
PinosClient *client));
|
||||||
};
|
};
|
||||||
|
|
@ -57,6 +68,17 @@ struct _PinosClient {
|
||||||
PinosClient * pinos_client_new (PinosCore *core,
|
PinosClient * pinos_client_new (PinosCore *core,
|
||||||
PinosProperties *properties);
|
PinosProperties *properties);
|
||||||
void pinos_client_destroy (PinosClient *client);
|
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,
|
void pinos_client_update_properties (PinosClient *client,
|
||||||
const SpaDict *dict);
|
const SpaDict *dict);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@
|
||||||
#include <pinos/server/data-loop.h>
|
#include <pinos/server/data-loop.h>
|
||||||
#include <pinos/server/client-node.h>
|
#include <pinos/server/client-node.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PinosGlobal this;
|
||||||
|
PinosBindFunc bind;
|
||||||
|
} PinosGlobalImpl;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinosCore this;
|
PinosCore this;
|
||||||
|
|
||||||
|
|
@ -36,6 +41,7 @@ registry_dispatch_func (void *object,
|
||||||
void *message,
|
void *message,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
SpaResult res;
|
||||||
PinosResource *resource = object;
|
PinosResource *resource = object;
|
||||||
PinosClient *client = resource->client;
|
PinosClient *client = resource->client;
|
||||||
PinosCore *this = data;
|
PinosCore *this = data;
|
||||||
|
|
@ -56,22 +62,16 @@ registry_dispatch_func (void *object,
|
||||||
"unknown object id %u", m->id);
|
"unknown object id %u", m->id);
|
||||||
return SPA_RESULT_ERROR;
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
pinos_log_error ("unhandled message %d", type);
|
pinos_log_error ("unhandled message %d", type);
|
||||||
|
res = SPA_RESULT_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return SPA_RESULT_OK;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -116,8 +116,9 @@ core_dispatch_func (void *object,
|
||||||
if (registry_resource == NULL)
|
if (registry_resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
registry_resource->dispatch_func = registry_dispatch_func;
|
pinos_resource_set_dispatch (registry_resource,
|
||||||
registry_resource->dispatch_data = this;
|
registry_dispatch_func,
|
||||||
|
this);
|
||||||
|
|
||||||
spa_list_insert (this->registry_resource_list.prev, ®istry_resource->link);
|
spa_list_insert (this->registry_resource_list.prev, ®istry_resource->link);
|
||||||
|
|
||||||
|
|
@ -191,7 +192,7 @@ no_mem:
|
||||||
return SPA_RESULT_NO_MEMORY;
|
return SPA_RESULT_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SpaResult
|
||||||
core_bind_func (PinosGlobal *global,
|
core_bind_func (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
|
|
@ -204,14 +205,15 @@ core_bind_func (PinosGlobal *global,
|
||||||
|
|
||||||
resource = pinos_resource_new (client,
|
resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
global->core->uri.core,
|
global->type,
|
||||||
global->object,
|
global->object,
|
||||||
NULL);
|
NULL);
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
resource->dispatch_func = core_dispatch_func;
|
pinos_resource_set_dispatch (resource,
|
||||||
resource->dispatch_data = this;
|
core_dispatch_func,
|
||||||
|
this);
|
||||||
|
|
||||||
client->core_resource = resource;
|
client->core_resource = resource;
|
||||||
|
|
||||||
|
|
@ -228,14 +230,13 @@ core_bind_func (PinosGlobal *global,
|
||||||
info.cookie = random ();
|
info.cookie = random ();
|
||||||
info.props = NULL;
|
info.props = NULL;
|
||||||
|
|
||||||
pinos_resource_send_message (resource,
|
return pinos_resource_send_message (resource,
|
||||||
PINOS_MESSAGE_CORE_INFO,
|
PINOS_MESSAGE_CORE_INFO,
|
||||||
&m,
|
&m,
|
||||||
true);
|
true);
|
||||||
return;
|
|
||||||
|
|
||||||
no_mem:
|
no_mem:
|
||||||
pinos_log_error ("can't create core resource");
|
pinos_log_error ("can't create core resource");
|
||||||
|
return SPA_RESULT_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinosCore *
|
PinosCore *
|
||||||
|
|
@ -256,6 +257,7 @@ pinos_core_new (PinosMainLoop *main_loop)
|
||||||
this->main_loop = main_loop;
|
this->main_loop = main_loop;
|
||||||
|
|
||||||
pinos_uri_init (&this->uri);
|
pinos_uri_init (&this->uri);
|
||||||
|
pinos_access_init (&this->access);
|
||||||
pinos_map_init (&this->objects, 512);
|
pinos_map_init (&this->objects, 512);
|
||||||
|
|
||||||
impl->support[0].uri = SPA_ID_MAP_URI;
|
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);
|
pinos_signal_init (&this->node_unlink_done);
|
||||||
|
|
||||||
this->global = pinos_core_add_global (this,
|
this->global = pinos_core_add_global (this,
|
||||||
|
NULL,
|
||||||
this->uri.core,
|
this->uri.core,
|
||||||
0,
|
0,
|
||||||
this,
|
this,
|
||||||
|
|
@ -316,43 +319,69 @@ pinos_core_destroy (PinosCore *core)
|
||||||
|
|
||||||
PinosGlobal *
|
PinosGlobal *
|
||||||
pinos_core_add_global (PinosCore *core,
|
pinos_core_add_global (PinosCore *core,
|
||||||
|
PinosClient *owner,
|
||||||
uint32_t type,
|
uint32_t type,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
void *object,
|
void *object,
|
||||||
PinosBindFunc bind)
|
PinosBindFunc bind)
|
||||||
{
|
{
|
||||||
PinosGlobal *global;
|
PinosGlobalImpl *impl;
|
||||||
|
PinosGlobal *this;
|
||||||
PinosResource *registry;
|
PinosResource *registry;
|
||||||
PinosMessageNotifyGlobal ng;
|
PinosMessageNotifyGlobal ng;
|
||||||
|
|
||||||
global = calloc (1, sizeof (PinosGlobal));
|
impl = calloc (1, sizeof (PinosGlobalImpl));
|
||||||
if (global == NULL)
|
if (impl == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
global->core = core;
|
this = &impl->this;
|
||||||
global->type = type;
|
impl->bind = bind;
|
||||||
global->version = version;
|
|
||||||
global->object = object;
|
|
||||||
global->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);
|
this->id = pinos_map_insert_new (&core->objects, this);
|
||||||
pinos_signal_emit (&core->global_added, core, global);
|
|
||||||
|
|
||||||
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;
|
pinos_log_debug ("global %p: new %u", this, this->id);
|
||||||
ng.type = spa_id_map_get_uri (core->uri.map, global->type);
|
|
||||||
|
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) {
|
spa_list_for_each (registry, &core->registry_resource_list, link) {
|
||||||
pinos_resource_send_message (registry,
|
pinos_resource_send_message (registry,
|
||||||
PINOS_MESSAGE_NOTIFY_GLOBAL,
|
PINOS_MESSAGE_NOTIFY_GLOBAL,
|
||||||
&ng,
|
&ng,
|
||||||
true);
|
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
|
static void
|
||||||
|
|
|
||||||
|
|
@ -31,27 +31,27 @@ typedef struct _PinosGlobal PinosGlobal;
|
||||||
|
|
||||||
#include <pinos/client/uri.h>
|
#include <pinos/client/uri.h>
|
||||||
|
|
||||||
|
#include <pinos/server/access.h>
|
||||||
#include <pinos/server/main-loop.h>
|
#include <pinos/server/main-loop.h>
|
||||||
#include <pinos/server/data-loop.h>
|
#include <pinos/server/data-loop.h>
|
||||||
#include <pinos/server/node.h>
|
#include <pinos/server/node.h>
|
||||||
#include <pinos/server/link.h>
|
#include <pinos/server/link.h>
|
||||||
#include <pinos/server/node-factory.h>
|
#include <pinos/server/node-factory.h>
|
||||||
|
|
||||||
typedef void (*PinosBindFunc) (PinosGlobal *global,
|
typedef SpaResult (*PinosBindFunc) (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
uint32_t id);
|
uint32_t id);
|
||||||
|
|
||||||
struct _PinosGlobal {
|
struct _PinosGlobal {
|
||||||
PinosCore *core;
|
PinosCore *core;
|
||||||
|
PinosClient *owner;
|
||||||
SpaList link;
|
SpaList link;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
void *object;
|
void *object;
|
||||||
|
|
||||||
PinosBindFunc bind;
|
|
||||||
|
|
||||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||||
PinosGlobal *global));
|
PinosGlobal *global));
|
||||||
};
|
};
|
||||||
|
|
@ -65,6 +65,7 @@ struct _PinosCore {
|
||||||
PinosGlobal *global;
|
PinosGlobal *global;
|
||||||
|
|
||||||
PinosURI uri;
|
PinosURI uri;
|
||||||
|
PinosAccess access;
|
||||||
|
|
||||||
PinosMap objects;
|
PinosMap objects;
|
||||||
|
|
||||||
|
|
@ -120,10 +121,16 @@ PinosCore * pinos_core_new (PinosMainLoop *main_loop);
|
||||||
void pinos_core_destroy (PinosCore *core);
|
void pinos_core_destroy (PinosCore *core);
|
||||||
|
|
||||||
PinosGlobal * pinos_core_add_global (PinosCore *core,
|
PinosGlobal * pinos_core_add_global (PinosCore *core,
|
||||||
|
PinosClient *owner,
|
||||||
uint32_t type,
|
uint32_t type,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
void *object,
|
void *object,
|
||||||
PinosBindFunc bind);
|
PinosBindFunc bind);
|
||||||
|
|
||||||
|
SpaResult pinos_global_bind (PinosGlobal *global,
|
||||||
|
PinosClient *client,
|
||||||
|
uint32_t version,
|
||||||
|
uint32_t id);
|
||||||
void pinos_global_destroy (PinosGlobal *global);
|
void pinos_global_destroy (PinosGlobal *global);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -756,7 +756,7 @@ link_unbind_func (void *data)
|
||||||
spa_list_remove (&resource->link);
|
spa_list_remove (&resource->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SpaResult
|
||||||
link_bind_func (PinosGlobal *global,
|
link_bind_func (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
|
|
@ -769,14 +769,15 @@ link_bind_func (PinosGlobal *global,
|
||||||
|
|
||||||
resource = pinos_resource_new (client,
|
resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
global->core->uri.link,
|
global->type,
|
||||||
global->object,
|
global->object,
|
||||||
link_unbind_func);
|
link_unbind_func);
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
resource->dispatch_func = link_dispatch_func;
|
pinos_resource_set_dispatch (resource,
|
||||||
resource->dispatch_data = global;
|
link_dispatch_func,
|
||||||
|
global);
|
||||||
|
|
||||||
pinos_log_debug ("link %p: bound to %d", global->object, resource->id);
|
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.output_port_id = this->output ? this->output->port_id : -1;
|
||||||
info.input_node_id = this->input ? this->input->node->global->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;
|
info.input_port_id = this->input ? this->input->port_id : -1;
|
||||||
pinos_resource_send_message (resource,
|
return pinos_resource_send_message (resource,
|
||||||
PINOS_MESSAGE_LINK_INFO,
|
PINOS_MESSAGE_LINK_INFO,
|
||||||
&m,
|
&m,
|
||||||
true);
|
true);
|
||||||
return;
|
|
||||||
|
|
||||||
no_mem:
|
no_mem:
|
||||||
pinos_resource_send_error (client->core_resource,
|
pinos_resource_send_error (client->core_resource,
|
||||||
SPA_RESULT_NO_MEMORY,
|
SPA_RESULT_NO_MEMORY,
|
||||||
"no memory");
|
"no memory");
|
||||||
|
return SPA_RESULT_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinosLink *
|
PinosLink *
|
||||||
|
|
@ -853,6 +853,7 @@ pinos_link_new (PinosCore *core,
|
||||||
spa_list_insert (core->link_list.prev, &this->link);
|
spa_list_insert (core->link_list.prev, &this->link);
|
||||||
|
|
||||||
this->global = pinos_core_add_global (core,
|
this->global = pinos_core_add_global (core,
|
||||||
|
NULL,
|
||||||
core->uri.link,
|
core->uri.link,
|
||||||
0,
|
0,
|
||||||
this,
|
this,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
pinoscore_headers = [
|
pinoscore_headers = [
|
||||||
|
'access.h',
|
||||||
'client.h',
|
'client.h',
|
||||||
'client-node.h',
|
'client-node.h',
|
||||||
'command.h',
|
'command.h',
|
||||||
|
|
@ -14,6 +15,7 @@ pinoscore_headers = [
|
||||||
]
|
]
|
||||||
|
|
||||||
pinoscore_sources = [
|
pinoscore_sources = [
|
||||||
|
'access.c',
|
||||||
'client.c',
|
'client.c',
|
||||||
'client-node.c',
|
'client-node.c',
|
||||||
'command.c',
|
'command.c',
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ module_dispatch_func (void *object,
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SpaResult
|
||||||
module_bind_func (PinosGlobal *global,
|
module_bind_func (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
|
|
@ -120,14 +120,15 @@ module_bind_func (PinosGlobal *global,
|
||||||
|
|
||||||
resource = pinos_resource_new (client,
|
resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
global->core->uri.module,
|
global->type,
|
||||||
global->object,
|
global->object,
|
||||||
NULL);
|
NULL);
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
resource->dispatch_func = module_dispatch_func;
|
pinos_resource_set_dispatch (resource,
|
||||||
resource->dispatch_data = global;
|
module_dispatch_func,
|
||||||
|
global);
|
||||||
|
|
||||||
pinos_log_debug ("module %p: bound to %d", global->object, resource->id);
|
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.args = this->args;
|
||||||
info.props = NULL;
|
info.props = NULL;
|
||||||
|
|
||||||
pinos_resource_send_message (resource,
|
return pinos_resource_send_message (resource,
|
||||||
PINOS_MESSAGE_MODULE_INFO,
|
PINOS_MESSAGE_MODULE_INFO,
|
||||||
&m,
|
&m,
|
||||||
true);
|
true);
|
||||||
return;
|
|
||||||
|
|
||||||
no_mem:
|
no_mem:
|
||||||
pinos_resource_send_error (resource,
|
pinos_resource_send_error (resource,
|
||||||
SPA_RESULT_NO_MEMORY,
|
SPA_RESULT_NO_MEMORY,
|
||||||
"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);
|
pinos_log_debug ("loaded module: %s", this->name);
|
||||||
|
|
||||||
this->global = pinos_core_add_global (core,
|
this->global = pinos_core_add_global (core,
|
||||||
|
NULL,
|
||||||
core->uri.module,
|
core->uri.module,
|
||||||
0,
|
0,
|
||||||
impl,
|
impl,
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,7 @@ node_unbind_func (void *data)
|
||||||
spa_list_remove (&resource->link);
|
spa_list_remove (&resource->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SpaResult
|
||||||
node_bind_func (PinosGlobal *global,
|
node_bind_func (PinosGlobal *global,
|
||||||
PinosClient *client,
|
PinosClient *client,
|
||||||
uint32_t version,
|
uint32_t version,
|
||||||
|
|
@ -419,14 +419,15 @@ node_bind_func (PinosGlobal *global,
|
||||||
|
|
||||||
resource = pinos_resource_new (client,
|
resource = pinos_resource_new (client,
|
||||||
id,
|
id,
|
||||||
global->core->uri.registry,
|
global->type,
|
||||||
global->object,
|
global->object,
|
||||||
node_unbind_func);
|
node_unbind_func);
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
goto no_mem;
|
goto no_mem;
|
||||||
|
|
||||||
resource->dispatch_func = node_dispatch_func;
|
pinos_resource_set_dispatch (resource,
|
||||||
resource->dispatch_data = global;
|
node_dispatch_func,
|
||||||
|
global);
|
||||||
|
|
||||||
pinos_log_debug ("node %p: bound to %d", this, resource->id);
|
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.error = this->error;
|
||||||
info.props = this->properties ? &this->properties->dict : NULL;
|
info.props = this->properties ? &this->properties->dict : NULL;
|
||||||
|
|
||||||
pinos_resource_send_message (resource,
|
return pinos_resource_send_message (resource,
|
||||||
PINOS_MESSAGE_NODE_INFO,
|
PINOS_MESSAGE_NODE_INFO,
|
||||||
&m,
|
&m,
|
||||||
true);
|
true);
|
||||||
return;
|
|
||||||
|
|
||||||
no_mem:
|
no_mem:
|
||||||
pinos_resource_send_error (resource,
|
pinos_resource_send_error (resource,
|
||||||
SPA_RESULT_NO_MEMORY,
|
SPA_RESULT_NO_MEMORY,
|
||||||
"no memory");
|
"no memory");
|
||||||
|
return SPA_RESULT_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -466,6 +466,7 @@ init_complete (PinosNode *this)
|
||||||
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
|
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
|
||||||
|
|
||||||
this->global = pinos_core_add_global (this->core,
|
this->global = pinos_core_add_global (this->core,
|
||||||
|
NULL,
|
||||||
this->core->uri.node,
|
this->core->uri.node,
|
||||||
0,
|
0,
|
||||||
this,
|
this,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,13 @@
|
||||||
|
|
||||||
#include "pinos/server/resource.h"
|
#include "pinos/server/resource.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PinosResource this;
|
||||||
|
|
||||||
|
PinosDispatchFunc dispatch_func;
|
||||||
|
void *dispatch_data;
|
||||||
|
} PinosResourceImpl;
|
||||||
|
|
||||||
PinosResource *
|
PinosResource *
|
||||||
pinos_resource_new (PinosClient *client,
|
pinos_resource_new (PinosClient *client,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
|
|
@ -28,12 +35,15 @@ pinos_resource_new (PinosClient *client,
|
||||||
void *object,
|
void *object,
|
||||||
PinosDestroy destroy)
|
PinosDestroy destroy)
|
||||||
{
|
{
|
||||||
|
PinosResourceImpl *impl;
|
||||||
PinosResource *this;
|
PinosResource *this;
|
||||||
|
|
||||||
this = calloc (1, sizeof (PinosResource));
|
impl = calloc (1, sizeof (PinosResourceImpl));
|
||||||
if (this == NULL)
|
if (impl == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
this = &impl->this;
|
||||||
|
|
||||||
this->core = client->core;
|
this->core = client->core;
|
||||||
this->client = client;
|
this->client = client;
|
||||||
this->id = id;
|
this->id = id;
|
||||||
|
|
@ -41,9 +51,6 @@ pinos_resource_new (PinosClient *client,
|
||||||
this->object = object;
|
this->object = object;
|
||||||
this->destroy = destroy;
|
this->destroy = destroy;
|
||||||
|
|
||||||
this->send_func = client->send_func;
|
|
||||||
this->send_data = client->send_data;
|
|
||||||
|
|
||||||
pinos_signal_init (&this->destroy_signal);
|
pinos_signal_init (&this->destroy_signal);
|
||||||
|
|
||||||
this->id = pinos_map_insert_new (&client->objects, this);
|
this->id = pinos_map_insert_new (&client->objects, this);
|
||||||
|
|
@ -92,23 +99,82 @@ pinos_resource_destroy (PinosResource *resource)
|
||||||
return SPA_RESULT_OK;
|
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
|
SpaResult
|
||||||
pinos_resource_send_message (PinosResource *resource,
|
pinos_resource_send_message (PinosResource *resource,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
void *message,
|
void *message,
|
||||||
bool flush)
|
bool flush)
|
||||||
{
|
{
|
||||||
if (!resource->send_func) {
|
return pinos_client_send_message (resource->client,
|
||||||
pinos_log_error ("resource %p: send func not implemented", resource);
|
resource,
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resource->send_func (resource,
|
|
||||||
resource->id,
|
|
||||||
opcode,
|
opcode,
|
||||||
message,
|
message,
|
||||||
flush,
|
flush);
|
||||||
resource->send_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaResult
|
SpaResult
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,14 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _PinosResource PinosResource;
|
typedef struct _PinosResource PinosResource;
|
||||||
|
|
||||||
|
#include <spa/include/spa/list.h>
|
||||||
|
|
||||||
|
#include <pinos/client/sig.h>
|
||||||
|
|
||||||
#include <pinos/server/core.h>
|
#include <pinos/server/core.h>
|
||||||
|
|
||||||
typedef void (*PinosDestroy) (void *object);
|
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,
|
typedef SpaResult (*PinosDispatchFunc) (void *object,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
void *message,
|
void *message,
|
||||||
|
|
@ -56,11 +53,6 @@ struct _PinosResource {
|
||||||
void *object;
|
void *object;
|
||||||
PinosDestroy destroy;
|
PinosDestroy destroy;
|
||||||
|
|
||||||
PinosSendFunc send_func;
|
|
||||||
void *send_data;
|
|
||||||
PinosDispatchFunc dispatch_func;
|
|
||||||
void *dispatch_data;
|
|
||||||
|
|
||||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||||
PinosResource *resource));
|
PinosResource *resource));
|
||||||
};
|
};
|
||||||
|
|
@ -72,6 +64,14 @@ PinosResource * pinos_resource_new (PinosClient *client,
|
||||||
PinosDestroy destroy);
|
PinosDestroy destroy);
|
||||||
SpaResult pinos_resource_destroy (PinosResource *resource);
|
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,
|
SpaResult pinos_resource_send_message (PinosResource *resource,
|
||||||
uint32_t opcode,
|
uint32_t opcode,
|
||||||
void *message,
|
void *message,
|
||||||
|
|
|
||||||
|
|
@ -178,32 +178,31 @@ dump_object (PinosContext *context,
|
||||||
pinos_context_get_core_info (context,
|
pinos_context_get_core_info (context,
|
||||||
dump_core_info,
|
dump_core_info,
|
||||||
data);
|
data);
|
||||||
}
|
} else if (type == context->uri.node) {
|
||||||
if (type == context->uri.node) {
|
|
||||||
pinos_context_get_node_info_by_id (context,
|
pinos_context_get_node_info_by_id (context,
|
||||||
id,
|
id,
|
||||||
dump_node_info,
|
dump_node_info,
|
||||||
data);
|
data);
|
||||||
}
|
} else if (type == context->uri.module) {
|
||||||
if (type == context->uri.module) {
|
|
||||||
pinos_context_get_module_info_by_id (context,
|
pinos_context_get_module_info_by_id (context,
|
||||||
id,
|
id,
|
||||||
dump_module_info,
|
dump_module_info,
|
||||||
data);
|
data);
|
||||||
}
|
} else if (type == context->uri.client) {
|
||||||
if (type == context->uri.client) {
|
|
||||||
pinos_context_get_client_info_by_id (context,
|
pinos_context_get_client_info_by_id (context,
|
||||||
id,
|
id,
|
||||||
dump_client_info,
|
dump_client_info,
|
||||||
data);
|
data);
|
||||||
}
|
} else if (type == context->uri.link) {
|
||||||
if (type == context->uri.link) {
|
|
||||||
pinos_context_get_link_info_by_id (context,
|
pinos_context_get_link_info_by_id (context,
|
||||||
id,
|
id,
|
||||||
dump_link_info,
|
dump_link_info,
|
||||||
data);
|
data);
|
||||||
|
} else {
|
||||||
|
printf ("\tid: %u\n", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ typedef enum {
|
||||||
SPA_RESULT_ASYNC_BUSY = -30,
|
SPA_RESULT_ASYNC_BUSY = -30,
|
||||||
SPA_RESULT_INVALID_OBJECT_ID = -31,
|
SPA_RESULT_INVALID_OBJECT_ID = -31,
|
||||||
SPA_RESULT_NO_MEMORY = -32,
|
SPA_RESULT_NO_MEMORY = -32,
|
||||||
|
SPA_RESULT_NO_PERMISSION = -33,
|
||||||
|
SPA_RESULT_SKIPPED = -34,
|
||||||
} SpaResult;
|
} SpaResult;
|
||||||
|
|
||||||
#define SPA_ASYNC_MASK (3 << 30)
|
#define SPA_ASYNC_MASK (3 << 30)
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
spa_headers = [
|
spa_headers = [
|
||||||
|
'barrier.h',
|
||||||
'buffer.h',
|
'buffer.h',
|
||||||
'clock.h',
|
'clock.h',
|
||||||
'control.h',
|
|
||||||
'debug.h',
|
|
||||||
'defs.h',
|
'defs.h',
|
||||||
'dict.h',
|
'dict.h',
|
||||||
'format.h',
|
'format.h',
|
||||||
|
'id-map.h',
|
||||||
|
'list.h',
|
||||||
'log.h',
|
'log.h',
|
||||||
|
'loop.h',
|
||||||
'monitor.h',
|
'monitor.h',
|
||||||
'node-command.h',
|
'node-command.h',
|
||||||
'node-event.h',
|
'node-event.h',
|
||||||
'node.h',
|
'node.h',
|
||||||
'plugin.h',
|
'plugin.h',
|
||||||
'poll.h',
|
|
||||||
'port.h',
|
'port.h',
|
||||||
'props.h',
|
'props.h',
|
||||||
'queue.h',
|
|
||||||
'ringbuffer.h'
|
'ringbuffer.h'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue