proto: add a version argument to ei_connection.sync

This is the only request that creates a new object but doesn't specify
the version for that object, courtesy of copy/paste from the wayland
protocol. In libei/libeis this a bit was hidden away so it didn't get
noticed - but it was already buggy: libei would always hardcode to
version 1 but libeis would take whichever ei_callback version was agreed
upon during handshake. This version could be higher than 1.

This is a protocol break but we're still pre-1.0, there are very few
people that will be affected by this and it's better than having to
carry this bug around for years.

Fixes #35
This commit is contained in:
Peter Hutterer 2023-05-25 13:36:12 +10:00
parent 552f6dcbd0
commit f081e8e79f
6 changed files with 19 additions and 11 deletions

View file

@ -248,6 +248,7 @@
</description>
<arg name="callback" type="new_id" interface="ei_callback"
summary="callback object for the sync request"/>
<arg name="version" type="uint32" summary="the interface version"/>
</request>
<request name="disconnect" type="destructor" since="1">

View file

@ -68,6 +68,12 @@ ei_callback_get_id(struct ei_callback *callback)
return callback->proto_object.id;
}
uint32_t
ei_callback_get_version(struct ei_callback *callback)
{
return callback->proto_object.version;
}
static struct brei_result *
handle_msg_done(struct ei_callback *callback, uint64_t callback_data)
{

View file

@ -51,6 +51,7 @@ struct ei_callback {
OBJECT_DECLARE_GETTER(ei_callback, context, struct ei*);
OBJECT_DECLARE_GETTER(ei_callback, proto_object, const struct brei_object *);
OBJECT_DECLARE_GETTER(ei_callback, id, object_id_t);
OBJECT_DECLARE_GETTER(ei_callback, version, uint32_t);
OBJECT_DECLARE_GETTER(ei_callback, interface, const struct ei_callback_interface *);
OBJECT_DECLARE_GETTER(ei_callback, user_data, void *);
OBJECT_DECLARE_SETTER(ei_callback, user_data, void *);

View file

@ -137,5 +137,5 @@ ei_connection_sync(struct ei_connection *connection, ei_connection_sync_callback
ei_callback_set_user_data(callback, data);
list_append(&connection->pending_callbacks, &callback->link);
ei_connection_request_sync(connection, ei_callback_get_id(callback));
ei_connection_request_sync(connection, ei_callback_get_id(callback), ei_callback_get_version(callback));
}

View file

@ -318,13 +318,13 @@ client_msg_disconnect(struct eis_connection *connection)
}
static struct brei_result *
client_msg_sync(struct eis_connection *connection, object_id_t new_id)
client_msg_sync(struct eis_connection *connection, object_id_t new_id, uint32_t version)
{
struct eis_client *client = eis_connection_get_client(connection);
DISCONNECT_IF_INVALID_ID(client, new_id);
struct eis_callback *callback = eis_callback_new(client, new_id, client->interface_versions.ei_callback);
struct eis_callback *callback = eis_callback_new(client, new_id, version);
log_debug(eis_client_get_context(client) , "object %#" PRIx64 ": connection sync done", new_id);
int rc = eis_callback_event_done(callback, 0);
eis_callback_unref(callback);

View file

@ -148,7 +148,7 @@ class Ei:
cb = EiCallback.create(next(self.object_ids), VERSION_V(1))
self.context.register(cb)
self.send(self.connection.Sync(cb.object_id))
self.send(self.connection.Sync(cb.object_id, VERSION_V(1)))
return self.wait_for(
lambda: cb not in self.find_objects_by_interface(InterfaceName.EI_CALLBACK)
@ -715,7 +715,7 @@ class TestEiProtocol:
cb = EiCallback.create(next(ei.object_ids), VERSION_V(1))
ei.context.register(cb)
assert ei.connection is not None
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
ei.dispatch()
assert cb.calllog[0].name == "Done"
@ -759,7 +759,7 @@ class TestEiProtocol:
# Send the invalid object request
ei.send(release)
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
ei.wait_for(lambda: have_sync)
assert have_invalid_object_event, "Expected invalid_object event, got none"
@ -923,20 +923,20 @@ class TestEiProtocol:
# and some of the next few ids might have been used by pingpongs
cb = EiCallback.create(0xFF00000000000100, VERSION_V(1))
ei.context.register(cb)
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
elif test_for == "repeat-id":
cb = EiCallback.create(0x100, VERSION_V(1))
ei.context.register(cb)
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
cb = EiCallback.create(0x100, VERSION_V(1))
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
elif test_for == "decreasing-id":
cb = EiCallback.create(0x101, VERSION_V(1))
ei.context.register(cb)
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
cb = EiCallback.create(0x100, VERSION_V(1))
ei.context.register(cb)
ei.send(ei.connection.Sync(cb.object_id))
ei.send(ei.connection.Sync(cb.object_id, VERSION_V(1)))
else:
assert False, "Unhandled test parameter"