mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									b9b57d32d5
								
							
						
					
					
						commit
						a9accd1668
					
				
					 3 changed files with 44 additions and 42 deletions
				
			
		| 
						 | 
					@ -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 = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue