protocol-native: footer pre_demarshal must come first

Message footer should be handled before attempting to find the object
the main message is sent to / checking permissions, because it is not
aimed at a specific object.  E.g. the registry generation updates should
be handled regardless of whether the main message is valid or not,
because the updates will not be re-sent.

Fixes registry generation updates sometimes going missing.
This commit is contained in:
Pauli Virtanen 2022-02-26 00:31:33 +02:00 committed by Wim Taymans
parent b9b57d32d5
commit a9accd1668
3 changed files with 44 additions and 42 deletions

View file

@ -116,7 +116,7 @@ struct client {
int ref; int ref;
struct footer_proxy_global_state footer_state; struct footer_core_global_state footer_state;
unsigned int connected:1; unsigned int connected:1;
unsigned int disconnecting:1; unsigned int disconnecting:1;
@ -154,7 +154,7 @@ struct client_data {
struct pw_protocol_native_connection *connection; struct pw_protocol_native_connection *connection;
struct spa_hook conn_listener; struct spa_hook conn_listener;
struct footer_resource_global_state footer_state; struct footer_client_global_state footer_state;
unsigned int busy:1; unsigned int busy:1;
unsigned int need_flush:1; unsigned int need_flush:1;
@ -261,6 +261,9 @@ process_messages(struct client_data *data)
if (debug_messages) if (debug_messages)
debug_msg("<<<<<< in", msg, false); debug_msg("<<<<<< in", msg, false);
pre_demarshal(conn, msg, client, footer_client_demarshal,
SPA_N_ELEMENTS(footer_client_demarshal));
resource = pw_impl_client_find_resource(client, msg->id); resource = pw_impl_client_find_resource(client, msg->id);
if (resource == NULL) { if (resource == NULL) {
pw_resource_errorf(client->core_resource, pw_resource_errorf(client->core_resource,
@ -297,8 +300,6 @@ process_messages(struct client_data *data)
} }
pw_protocol_native_connection_enter(conn); pw_protocol_native_connection_enter(conn);
pre_demarshal(conn, msg, resource, footer_resource_demarshal,
SPA_N_ELEMENTS(footer_resource_demarshal));
res = demarshal[msg->opcode].func(resource, msg); res = demarshal[msg->opcode].func(resource, msg);
pw_protocol_native_connection_leave(conn); pw_protocol_native_connection_leave(conn);
if (res < 0) { if (res < 0) {
@ -817,6 +818,9 @@ process_remote(struct client *impl)
if (debug_messages) if (debug_messages)
debug_msg("<<<<<< in", msg, false); debug_msg("<<<<<< in", msg, false);
pre_demarshal(conn, msg, this, footer_core_demarshal,
SPA_N_ELEMENTS(footer_core_demarshal));
proxy = pw_core_find_proxy(this, msg->id); proxy = pw_core_find_proxy(this, msg->id);
if (proxy == NULL || proxy->zombie) { if (proxy == NULL || proxy->zombie) {
if (proxy == NULL) if (proxy == NULL)
@ -844,8 +848,6 @@ process_remote(struct client *impl)
} }
proxy->refcount++; proxy->refcount++;
pw_protocol_native_connection_enter(conn); pw_protocol_native_connection_enter(conn);
pre_demarshal(conn, msg, proxy, footer_proxy_demarshal,
SPA_N_ELEMENTS(footer_proxy_demarshal));
res = demarshal[msg->opcode].func(proxy, msg); res = demarshal[msg->opcode].func(proxy, msg);
pw_protocol_native_connection_leave(conn); pw_protocol_native_connection_leave(conn);
pw_proxy_unref(proxy); pw_proxy_unref(proxy);
@ -1295,7 +1297,7 @@ static int impl_ext_end_proxy(struct pw_proxy *proxy,
struct pw_core *core = proxy->core; struct pw_core *core = proxy->core;
struct client *impl = SPA_CONTAINER_OF(core->conn, struct client, this); struct client *impl = SPA_CONTAINER_OF(core->conn, struct client, this);
assert_single_pod(builder); assert_single_pod(builder);
marshal_proxy_footers(&impl->footer_state, proxy, builder); marshal_core_footers(&impl->footer_state, core, builder);
return core->send_seq = pw_protocol_native_connection_end(impl->connection, builder); return core->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
} }
@ -1324,7 +1326,7 @@ static int impl_ext_end_resource(struct pw_resource *resource,
struct client_data *data = resource->client->user_data; struct client_data *data = resource->client->user_data;
struct pw_impl_client *client = resource->client; struct pw_impl_client *client = resource->client;
assert_single_pod(builder); assert_single_pod(builder);
marshal_resource_footers(&data->footer_state, resource, builder); marshal_client_footers(&data->footer_state, client, builder);
return client->send_seq = pw_protocol_native_connection_end(data->connection, builder); return client->send_seq = pw_protocol_native_connection_end(data->connection, builder);
} }
static const struct pw_protocol_native_ext protocol_ext_impl = { static const struct pw_protocol_native_ext protocol_ext_impl = {

View file

@ -71,80 +71,80 @@ static void end_footer(struct footer_builder *fb)
spa_pod_builder_pop(fb->builder, &fb->outer); spa_pod_builder_pop(fb->builder, &fb->outer);
} }
void marshal_proxy_footers(struct footer_proxy_global_state *state, struct pw_proxy *proxy, void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core,
struct spa_pod_builder *builder) struct spa_pod_builder *builder)
{ {
struct footer_builder fb = FOOTER_BUILDER_INIT(builder); struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
if (proxy->core->recv_generation != state->last_recv_generation) { if (core->recv_generation != state->last_recv_generation) {
state->last_recv_generation = proxy->core->recv_generation; state->last_recv_generation = core->recv_generation;
pw_log_trace("core %p: send client registry generation:%"PRIu64, pw_log_trace("core %p: send client registry generation:%"PRIu64,
proxy->core, proxy->core->recv_generation); core, core->recv_generation);
start_footer_entry(&fb, FOOTER_RESOURCE_OPCODE_GENERATION); start_footer_entry(&fb, FOOTER_CLIENT_OPCODE_GENERATION);
spa_pod_builder_long(fb.builder, proxy->core->recv_generation); spa_pod_builder_long(fb.builder, core->recv_generation);
end_footer_entry(&fb); end_footer_entry(&fb);
} }
end_footer(&fb); end_footer(&fb);
} }
void marshal_resource_footers(struct footer_resource_global_state *state, struct pw_resource *resource, void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client,
struct spa_pod_builder *builder) struct spa_pod_builder *builder)
{ {
struct footer_builder fb = FOOTER_BUILDER_INIT(builder); struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
if (resource->context->generation != state->last_sent_generation) { if (client->context->generation != state->last_sent_generation) {
state->last_sent_generation = resource->context->generation; state->last_sent_generation = client->context->generation;
pw_log_trace("impl-client %p: send server registry generation:%"PRIu64, pw_log_trace("impl-client %p: send server registry generation:%"PRIu64,
resource->client, resource->context->generation); client, client->context->generation);
start_footer_entry(&fb, FOOTER_RESOURCE_OPCODE_GENERATION); start_footer_entry(&fb, FOOTER_CORE_OPCODE_GENERATION);
spa_pod_builder_long(fb.builder, resource->context->generation); spa_pod_builder_long(fb.builder, client->context->generation);
end_footer_entry(&fb); end_footer_entry(&fb);
} }
end_footer(&fb); end_footer(&fb);
} }
int demarshal_proxy_generation(void *object, struct spa_pod_parser *parser) int demarshal_core_generation(void *object, struct spa_pod_parser *parser)
{ {
struct pw_proxy *proxy = object; struct pw_core *core = object;
int64_t generation; int64_t generation;
if (spa_pod_parser_get_long(parser, &generation) < 0) if (spa_pod_parser_get_long(parser, &generation) < 0)
return -EINVAL; return -EINVAL;
proxy->core->recv_generation = (uint64_t)generation; core->recv_generation = (uint64_t)generation;
pw_log_trace("core %p: recv server registry generation:%"PRIu64, pw_log_trace("core %p: recv server registry generation:%"PRIu64,
proxy->core, generation); core->core, generation);
return 0; return 0;
} }
int demarshal_resource_generation(void *object, struct spa_pod_parser *parser) int demarshal_client_generation(void *object, struct spa_pod_parser *parser)
{ {
struct pw_resource *resource = object; struct pw_impl_client *client = object;
int64_t generation; int64_t generation;
if (spa_pod_parser_get_long(parser, &generation) < 0) if (spa_pod_parser_get_long(parser, &generation) < 0)
return -EINVAL; return -EINVAL;
resource->client->recv_generation = (uint64_t)generation; client->recv_generation = (uint64_t)generation;
pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64, pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64,
resource->client, generation); client, generation);
return 0; return 0;
} }
const struct footer_demarshal footer_proxy_demarshal[FOOTER_PROXY_OPCODE_LAST] = { const struct footer_demarshal footer_core_demarshal[FOOTER_CORE_OPCODE_LAST] = {
[FOOTER_PROXY_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_proxy_generation }, [FOOTER_CORE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_core_generation },
}; };
const struct footer_demarshal footer_resource_demarshal[FOOTER_RESOURCE_OPCODE_LAST] = { const struct footer_demarshal footer_client_demarshal[FOOTER_CLIENT_OPCODE_LAST] = {
[FOOTER_RESOURCE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_resource_generation }, [FOOTER_CLIENT_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_client_generation },
}; };

View file

@ -30,20 +30,20 @@
*/ */
enum { enum {
FOOTER_PROXY_OPCODE_GENERATION = 0, FOOTER_CORE_OPCODE_GENERATION = 0,
FOOTER_PROXY_OPCODE_LAST FOOTER_CORE_OPCODE_LAST
}; };
enum { enum {
FOOTER_RESOURCE_OPCODE_GENERATION = 0, FOOTER_CLIENT_OPCODE_GENERATION = 0,
FOOTER_RESOURCE_OPCODE_LAST FOOTER_CLIENT_OPCODE_LAST
}; };
struct footer_proxy_global_state { struct footer_core_global_state {
uint64_t last_recv_generation; uint64_t last_recv_generation;
}; };
struct footer_resource_global_state { struct footer_client_global_state {
uint64_t last_sent_generation; uint64_t last_sent_generation;
}; };
@ -51,10 +51,10 @@ struct footer_demarshal {
int (*demarshal)(void *object, struct spa_pod_parser *parser); int (*demarshal)(void *object, struct spa_pod_parser *parser);
}; };
extern const struct footer_demarshal footer_proxy_demarshal[FOOTER_PROXY_OPCODE_LAST]; extern const struct footer_demarshal footer_core_demarshal[FOOTER_CORE_OPCODE_LAST];
extern const struct footer_demarshal footer_resource_demarshal[FOOTER_RESOURCE_OPCODE_LAST]; extern const struct footer_demarshal footer_client_demarshal[FOOTER_CLIENT_OPCODE_LAST];
void marshal_proxy_footers(struct footer_proxy_global_state *state, struct pw_proxy *proxy, void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core,
struct spa_pod_builder *builder); struct spa_pod_builder *builder);
void marshal_resource_footers(struct footer_resource_global_state *state, struct pw_resource *resource, void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client,
struct spa_pod_builder *builder); struct spa_pod_builder *builder);