diff --git a/pinos/modules/module-access.c b/pinos/modules/module-access.c index f4a9e9627..dd26ff167 100644 --- a/pinos/modules/module-access.c +++ b/pinos/modules/module-access.c @@ -58,9 +58,9 @@ check_global_owner (PinosCore *core, } static SpaResult -do_check_global (PinosAccess *access, - PinosClient *client, - PinosGlobal *global) +do_view_global (PinosAccess *access, + PinosClient *client, + PinosGlobal *global) { if (global->type == client->core->type.link) { PinosLink *link = global->object; @@ -84,9 +84,65 @@ do_check_global (PinosAccess *access, return SPA_RESULT_OK; } +static SpaResult +do_create_node (PinosAccess *access, + PinosAccessData *data, + const char *factory_name, + const char *name, + PinosProperties *properties) +{ + data->res = SPA_RESULT_OK; + data->complete_cb (data); + return SPA_RESULT_OK; +} + +#if 0 +static void +check_timeout (SpaSource *source, + void *d) +{ + PinosAccessData *data = d; + + data->res = SPA_RESULT_OK; + data->complete_cb (data); +} +#endif + +static SpaResult +do_create_client_node (PinosAccess *access, + PinosAccessData *data, + const char *name, + PinosProperties *properties) +{ +#if 0 + struct timespec value; + SpaSource *timer; + + pinos_log_debug ("access %p: check %s %p", access, name, properties); + + timer = pinos_loop_add_timer (data->resource->core->main_loop->loop, + check_timeout, + data->async_copy (data, 0)); + value.tv_sec = 3; + value.tv_nsec = 0; + pinos_loop_update_timer (data->resource->core->main_loop->loop, + timer, + &value, + NULL, + false); + + return SPA_RESULT_RETURN_ASYNC (0); +#else + data->res = SPA_RESULT_OK; + return SPA_RESULT_OK; +#endif +} + static PinosAccess access_checks = { - do_check_global, + do_view_global, + do_create_node, + do_create_client_node, }; static ModuleImpl * diff --git a/pinos/server/access.h b/pinos/server/access.h index 8e81fd275..f2757ef4b 100644 --- a/pinos/server/access.h +++ b/pinos/server/access.h @@ -36,10 +36,12 @@ typedef struct _PinosAccessData PinosAccessData; #include struct _PinosAccessData { - SpaResult res; - void (*complete_cb) (PinosAccessData *data); - void (*cancel_cb) (PinosAccessData *data); - void *user_data; + SpaResult res; + PinosResource *resource; + void *(*async_copy) (PinosAccessData *data, size_t size); + void (*complete_cb) (PinosAccessData *data); + void (*free_cb) (PinosAccessData *data); + void *user_data; }; @@ -49,9 +51,18 @@ struct _PinosAccessData { * Pinos Access support struct. */ struct _PinosAccess { - SpaResult (*check_global) (PinosAccess *access, - PinosClient *client, - PinosGlobal *global); + SpaResult (*view_global) (PinosAccess *access, + PinosClient *client, + PinosGlobal *global); + SpaResult (*create_node) (PinosAccess *access, + PinosAccessData *data, + const char *factory_name, + const char *name, + PinosProperties *properties); + SpaResult (*create_client_node) (PinosAccess *access, + PinosAccessData *data, + const char *name, + PinosProperties *properties); }; #ifdef __cplusplus diff --git a/pinos/server/core.c b/pinos/server/core.c index 3791a0e3b..a2f7e46bf 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -38,9 +38,9 @@ typedef struct { } PinosCoreImpl; -#define ACCESS_CHECK_GLOBAL(client,global) (client->core->access && \ - client->core->access->check_global (client->core->access, \ - client, global) == SPA_RESULT_OK) +#define ACCESS_VIEW_GLOBAL(client,global) (client->core->access && \ + client->core->access->view_global (client->core->access, \ + client, global) == SPA_RESULT_OK) static void registry_bind (void *object, @@ -59,7 +59,7 @@ registry_bind (void *object, if (&global->link == &core->global_list) goto no_id; - if (!ACCESS_CHECK_GLOBAL (client, global)) + if (!ACCESS_VIEW_GLOBAL (client, global)) goto no_id; pinos_log_debug ("global %p: bind object id %d to %d", global, id, new_id); @@ -129,7 +129,7 @@ core_get_registry (void *object, spa_list_insert (this->registry_resource_list.prev, ®istry_resource->link); spa_list_for_each (global, &this->global_list, link) { - if (ACCESS_CHECK_GLOBAL (client, global)) + if (ACCESS_VIEW_GLOBAL (client, global)) pinos_registry_notify_global (registry_resource, global->id, spa_type_map_get_type (this->type.map, global->type)); @@ -161,32 +161,57 @@ core_create_node (void *object, "not implemented"); } -static void -core_create_client_node (void *object, - const char *name, - const SpaDict *props, - uint32_t new_id) +typedef struct { + PinosAccessData data; + char *name; + PinosProperties *properties; + uint32_t new_id; + bool async; +} AccessCreateClientNode; + +static void * +async_create_client_node_copy (PinosAccessData *data, size_t size) { - PinosResource *resource = object; + AccessCreateClientNode *d; + + d = calloc (1, sizeof (AccessCreateClientNode) + size); + memcpy (d, data, sizeof (AccessCreateClientNode)); + d->name = strdup (d->name); + d->async = true; + d->data.user_data = SPA_MEMBER (d, sizeof (AccessCreateClientNode), void); + return d; +} + +static void +async_create_client_node_free (PinosAccessData *data) +{ + AccessCreateClientNode *d = (AccessCreateClientNode *) data; + + if (d->async) { + if (d->data.free_cb) + d->data.free_cb (&d->data); + free (d->name); + free (d); + } +} + +static void +async_create_client_node_complete (PinosAccessData *data) +{ + AccessCreateClientNode *d = (AccessCreateClientNode *) data; + PinosResource *resource = d->data.resource; PinosClient *client = resource->client; PinosClientNode *node; SpaResult res; - int data_fd, i; - PinosProperties *properties; + int data_fd; - properties = pinos_properties_new (NULL, NULL); - if (properties == NULL) - goto no_mem; - - for (i = 0; i < props->n_items; i++) { - pinos_properties_set (properties, props->items[i].key, - props->items[i].value); - } + if (data->res != SPA_RESULT_OK) + goto denied; node = pinos_client_node_new (client, - new_id, - name, - properties); + d->new_id, + d->name, + d->properties); if (node == NULL) goto no_mem; @@ -200,6 +225,68 @@ core_create_client_node (void *object, pinos_client_node_notify_done (node->resource, data_fd); + goto done; + +no_mem: + pinos_log_error ("can't create client node"); + pinos_core_notify_error (client->core_resource, + resource->id, + SPA_RESULT_NO_MEMORY, + "no memory"); + goto done; +denied: + pinos_log_error ("create client node refused"); + pinos_core_notify_error (client->core_resource, + resource->id, + SPA_RESULT_NO_PERMISSION, + "operation not allowed"); +done: + async_create_client_node_free (&d->data); + return; +} + +static void +core_create_client_node (void *object, + const char *name, + const SpaDict *props, + uint32_t new_id) +{ + PinosResource *resource = object; + PinosClient *client = resource->client; + int i; + PinosProperties *properties; + AccessCreateClientNode access_data; + SpaResult res; + + properties = pinos_properties_new (NULL, NULL); + if (properties == NULL) + goto no_mem; + + for (i = 0; i < props->n_items; i++) { + pinos_properties_set (properties, props->items[i].key, + props->items[i].value); + } + + access_data.data.resource = resource; + access_data.data.async_copy = async_create_client_node_copy; + access_data.data.complete_cb = async_create_client_node_complete; + access_data.data.free_cb = NULL; + access_data.name = (char *) name; + access_data.properties = properties; + access_data.new_id = new_id; + access_data.async = false; + + if (client->core->access) { + access_data.data.res = SPA_RESULT_NO_PERMISSION; + res = client->core->access->create_client_node (client->core->access, + &access_data.data, + name, + properties); + } else { + res = access_data.data.res = SPA_RESULT_OK; + } + if (!SPA_RESULT_IS_ASYNC (res)) + async_create_client_node_complete (&access_data.data); return; no_mem: @@ -406,7 +493,7 @@ pinos_core_add_global (PinosCore *core, pinos_log_debug ("global %p: new %u %s, owner %p", this, this->id, type_name, owner); spa_list_for_each (registry, &core->registry_resource_list, link) - if (ACCESS_CHECK_GLOBAL (registry->client, this)) + if (ACCESS_VIEW_GLOBAL (registry->client, this)) pinos_registry_notify_global (registry, this->id, type_name); @@ -445,7 +532,7 @@ pinos_global_destroy (PinosGlobal *global) pinos_signal_emit (&global->destroy_signal, global); spa_list_for_each (registry, &core->registry_resource_list, link) - if (ACCESS_CHECK_GLOBAL (registry->client, global)) + if (ACCESS_VIEW_GLOBAL (registry->client, global)) pinos_registry_notify_global_remove (registry, global->id); pinos_map_remove (&core->objects, global->id);