From 0a347f433ff22a787ac925edc30b608e2f72174c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 6 Feb 2023 13:56:22 +1000 Subject: [PATCH] protocol: make the connection setup the zero object with a proper handover This changes the initial connection negotiation to have the ei_connection_setup as the pre-existing object id 0. Once the client has sent all the data to set up the connection, the EIS implementation replies with a new object ID that is the ei_connection protocol object, i.e. the main object. This allows for version negotiation of our main protocol object. --- proto/protocol.xml | 256 ++++++++++++++++++++-------------- src/libei-connection-setup.c | 82 ++++++++++- src/libei-connection-setup.h | 2 +- src/libei-connection.c | 21 ++- src/libei-connection.h | 4 +- src/libei-private.h | 7 + src/libei.c | 96 +++---------- src/libeis-client.c | 17 +-- src/libeis-connection-setup.c | 12 +- src/libeis-connection-setup.h | 2 +- src/libeis-connection.c | 14 +- src/libeis-connection.h | 2 + 12 files changed, 302 insertions(+), 213 deletions(-) diff --git a/proto/protocol.xml b/proto/protocol.xml index f20f228..5fd38aa 100644 --- a/proto/protocol.xml +++ b/proto/protocol.xml @@ -37,7 +37,7 @@ EIS implementation's native byte order. - length is the length of the message in bytes, including the 12 header bytes - sender-id is the id of the object sending the request/event. The sender-id - 0 is reserved for the special "ei" object. + 0 is reserved for the special "ei_connection_setup" object. - opcode is the event or requeset-specific opcode, starting at 0 requests and events have overlapping opcode ranges, i.e. the first request and the first event both have opcode 0. @@ -45,125 +45,42 @@ Types: - 'uint': a 32-bit unsigned integer - - 'uint': a 32-bit signed integer + - 'int': a 32-bit signed integer - 'float': a 32-bit IEEE-754 float - 'fd': a file descriptor. Zero bytes in the message itself, transmitted in the overhead - 'string': a length-prefix zero-terminated string. Encoded as one 32-bit unsigned integer for the length followed by the string. The string is padded to the nearest 4-byte units, for example the string - "hello" is of length 6 but is zero-padded to 8 bytes. Full (le) encoding: + "hello" is of length 6 but is zero-padded to 8 bytes and with the 4-byte + length field thus takes 12 bytes in total. Full (le) encoding: [0x06, 0x00, 0x00, 0x00, 'h', 'e', 'l', 'l', 'o', '\0', '\0\, '\0'] + - 'new_id': an object id allocated by the caller. Client-allocated IDs begin + at 1 and must be less than 0xff000000. + IDs allocated by the EIS implementation start at and must not be less + than 0xff000000. + - 'object_id': a previously allocated object id + + The initial connection is a two-step process: + An ei_connection_setup object with the special ID 0 is guaranteed to + exists. The client must send the appropriate requests to set up + its connection, followed by the .done request. The server replies + by creating the ei_connection object with the client-requested version + (or any lower version) that is the connection for the remainder of this + client. --> - - - The core global object. This is a special singleton object. It - is used for internal ei protocol features. - - - - - The sync request asks the EIS implementation to emit the 'done' event - on the returned ei_callback object. Since requests are - handled in-order and events are delivered in-order, this can - be used as a synchronization point to ensure all previous requests and the - resulting events have been handled. - - The object returned by this request will be destroyed by the - EIS implementation after the callback is fired and as such the client must not - attempt to use it after that point. - - - The callback_data passed in the callback is always zero. - - - - - - - - - - Provides the client with an object to initialize and setup the connection. - This event is sent immediately after the client connects to the EIS - implementation. - - A client should configure itself through that object, if applicable, - and complete this configuration with the ei_connection_setup.done event. - The object returned by this request will be destroyed by the - EIS implementation after that done event and a client must not - attempt to use it after that point. - - The version sent by the server is the highest supported version - of the connection setup interface. A client must only use - requests supported by that version (or any lower version). - - - - - - - - A reason why a client was disconnected. - - - - - - - - This event may be sent by the EIS implementation immediately before - the client is disconnected. - - Where a client is disconnected by EIS directly, the reason is - disconnect_reason.disconnected and the explanation is NULL. - - Where a client is disconnected due to some invalid request or other - protocol error, the reason is disconnect_reason.error and - explanation may contain a string explaining why. This string is - intended to help debugging only and is not guaranteed to stay constant. - - There is no guarantee this event is sent - the connection may be closed - without a disconnection event. - - - - - - - - Notification that a new seat has been added. - - The interface version is equal or less to the client-supported - version in ei_connection_setup.interface for the "ei_seat" - interface. - - - - - - - - - Clients can handle the 'done' event to get notified when - the related request is done. - - - - - Notify the client when the related request is done. - - - - - + This is a special interface to setup the client as seen by the EIS + implementation. The object for this interface has the fixed object + id 0 and only exists until the connection has been set up, see the + ei_connection_setup.connection event. + + Once set up, the connection setup hands over to the main + ei_connection object which is the top-level object for all future + requests and events. @@ -220,6 +137,129 @@ + + + + The highest supported version of this interface + by the EIS implementation. Any requests + send by the client must be provided in this version + or any lower version. + + This event is sent immediately after connection. A client + should not issue any requests until processing this version. + + Note that the EIS implementation assumes that the supported + client version of this interface is 1 until the client announces + a higher version of this interface in the + ei_connection_setup.interface request. + + + + + + + Provides the client with the connection object that is the top-level + object for all future requests and events. + This event is sent immediately after the client sends the + ei_connection_setup.done request to the EIS implementation. + + The ei_connection_setup object will be destroyed by the + EIS implementation immediately after this event has been sent, a + client must not attempt to use it after that point. + + The version sent by the server is the version of the ei_connection + interface as announced by ei_connection_setup.interface, or any + lower version. + + + + + + + + + The core global object. This is a special singleton object. It + is used for internal ei protocol features. + + + + + The sync request asks the EIS implementation to emit the 'done' event + on the returned ei_callback object. Since requests are + handled in-order and events are delivered in-order, this can + be used as a synchronization point to ensure all previous requests and the + resulting events have been handled. + + The object returned by this request will be destroyed by the + EIS implementation after the callback is fired and as such the client must not + attempt to use it after that point. + + + The callback_data passed in the callback is always zero. + + + + + + + + + + A reason why a client was disconnected. + + + + + + + + This event may be sent by the EIS implementation immediately before + the client is disconnected. + + Where a client is disconnected by EIS directly, the reason is + disconnect_reason.disconnected and the explanation is NULL. + + Where a client is disconnected due to some invalid request or other + protocol error, the reason is disconnect_reason.error and + explanation may contain a string explaining why. This string is + intended to help debugging only and is not guaranteed to stay constant. + + There is no guarantee this event is sent - the connection may be closed + without a disconnection event. + + + + + + + + Notification that a new seat has been added. + + The interface version is equal or less to the client-supported + version in ei_connection_setup.interface for the "ei_seat" + interface. + + + + + + + + + Clients can handle the 'done' event to get notified when + the related request is done. + + + + + Notify the client when the related request is done. + + + diff --git a/src/libei-connection-setup.c b/src/libei-connection-setup.c index 0ac01e6..eeb50ce 100644 --- a/src/libei-connection-setup.c +++ b/src/libei-connection-setup.c @@ -32,6 +32,7 @@ #include "util-mem.h" #include "util-io.h" #include "util-strings.h" +#include "util-version.h" #include "libei-private.h" #include "ei-proto.h" @@ -67,8 +68,82 @@ ei_connection_setup_get_version(struct ei_connection_setup *connection_setup) return connection_setup->proto_object.version; } +static int +ei_connection_setup_initialize(struct ei_connection_setup *setup, uint32_t version) +{ + struct ei *ei = ei_connection_setup_get_context(setup); + + if (version >= EI_CONNECTION_SETUP_REQUEST_TYPE_SINCE_VERSION) + ei_connection_setup_request_type(setup, + ei->is_sender ? + EI_CONNECTION_SETUP_CONTEXT_TYPE_SENDER : + EI_CONNECTION_SETUP_CONTEXT_TYPE_RECEIVER); + + if (version >= EI_CONNECTION_SETUP_REQUEST_NAME_SINCE_VERSION) + ei_connection_setup_request_name(setup, ei->name); + + if (version >= EI_CONNECTION_SETUP_REQUEST_INTERFACE_SINCE_VERSION) { + ei_connection_setup_request_interface(setup, "ei_connection_setup", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_connection", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_callback", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_seat", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_device", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_pointer", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_keyboard", VERSION_V(1)); + ei_connection_setup_request_interface(setup, "ei_touchscreen", VERSION_V(1)); + } + + ei_connection_setup_request_done(setup); + + return 0; +} + +static int +handle_msg_version(struct ei_connection_setup *setup, uint32_t version) +{ + uint32_t min_version = min(version, setup->proto_object.version); + setup->proto_object.version = min_version; + + /* Now send all the bits we need to send */ + ei_connection_setup_initialize(setup, version); + + return 0; +} + +static void +connected(struct ei_connection *connection, void *user_data) +{ + struct ei *ei = ei_connection_get_context(connection); + + /* If we get here, the server didn't immediately disconnect us */ + if (ei->state == EI_STATE_DISCONNECTED) + return; + + ei_connected(ei); +} + +static int +handle_msg_connection(struct ei_connection_setup *setup, uint32_t id, uint32_t version) +{ + struct ei *ei = ei_connection_setup_get_context(setup); + assert(setup == ei->connection_setup); + /* we're done with our connection setup, drop it */ + ei_connection_setup_unref(steal(&ei->connection_setup)); + + ei->connection = ei_connection_new(ei, id, version); + ei->state = EI_STATE_CONNECTING; + + /* Send a sync on the connection - EIS should immediately send a + * disconnect event where applicable, so if we get through to our + * sync callback, we didn't immediately get disconnected */ + ei_connection_sync(ei->connection, connected, NULL); + + return 0; +} + static const struct ei_connection_setup_interface interface = { - /* no events */ + .version = handle_msg_version, + .connection = handle_msg_connection, }; const struct ei_connection_setup_interface * @@ -77,11 +152,12 @@ ei_connection_setup_get_interface(struct ei_connection_setup *connection_setup) } struct ei_connection_setup * -ei_connection_setup_new(struct ei *ei, uint32_t id, uint32_t version) +ei_connection_setup_new(struct ei *ei, uint32_t version) { struct ei_connection_setup *connection_setup = ei_connection_setup_create(&ei->object); - connection_setup->proto_object.id = id; + connection_setup->proto_object.id = ei_get_new_id(ei); + assert(connection_setup->proto_object.id == 0); /* Special object */ connection_setup->proto_object.implementation = connection_setup; connection_setup->proto_object.interface = &ei_connection_setup_proto_interface; connection_setup->proto_object.version = version; diff --git a/src/libei-connection-setup.h b/src/libei-connection-setup.h index ad86d80..eae75de 100644 --- a/src/libei-connection-setup.h +++ b/src/libei-connection-setup.h @@ -52,4 +52,4 @@ OBJECT_DECLARE_REF(ei_connection_setup); OBJECT_DECLARE_UNREF(ei_connection_setup); struct ei_connection_setup * -ei_connection_setup_new(struct ei *ei, uint32_t id, uint32_t version); +ei_connection_setup_new(struct ei *ei, uint32_t version); diff --git a/src/libei-connection.c b/src/libei-connection.c index ccf2024..45024c5 100644 --- a/src/libei-connection.c +++ b/src/libei-connection.c @@ -60,6 +60,18 @@ static OBJECT_IMPLEMENT_PARENT(ei_connection, ei); OBJECT_IMPLEMENT_GETTER_AS_REF(ei_connection, proto_object, const struct brei_object*); +uint32_t +ei_connection_get_version(struct ei_connection *connection) +{ + return connection->proto_object.version; +} + +uint32_t +ei_connection_get_id(struct ei_connection *connection) +{ + return connection->proto_object.id; +} + struct ei* ei_connection_get_context(struct ei_connection *connection) { @@ -74,17 +86,14 @@ ei_connection_get_interface(struct ei_connection *connection) { } struct ei_connection * -ei_connection_new(struct ei *ei) +ei_connection_new(struct ei *ei, uint32_t id, uint32_t version) { struct ei_connection *connection = ei_connection_create(&ei->object); - connection->proto_object.id = ei_get_new_id(ei); - /* This is a special object and must have id 0 */ - assert(connection->proto_object.id == 0); - + connection->proto_object.id = id; connection->proto_object.implementation = connection; connection->proto_object.interface = &ei_connection_proto_interface; - connection->proto_object.version = VERSION_V(1); + connection->proto_object.version = version; ei_register_object(ei, &connection->proto_object); list_init(&connection->pending_callbacks); diff --git a/src/libei-connection.h b/src/libei-connection.h index 2da9bc1..56ab294 100644 --- a/src/libei-connection.h +++ b/src/libei-connection.h @@ -41,13 +41,15 @@ struct ei_connection { }; OBJECT_DECLARE_GETTER(ei_connection, context, struct ei*); +OBJECT_DECLARE_GETTER(ei_connection, version, uint32_t); +OBJECT_DECLARE_GETTER(ei_connection, id, uint32_t); OBJECT_DECLARE_GETTER(ei_connection, proto_object, const struct brei_object*); OBJECT_DECLARE_GETTER(ei_connection, interface, const struct ei_connection_interface *); OBJECT_DECLARE_REF(ei_connection); OBJECT_DECLARE_UNREF(ei_connection); struct ei_connection * -ei_connection_new(struct ei *ei); +ei_connection_new(struct ei *ei, uint32_t id, uint32_t version); /** * Called when the ei_callback.done event is received after diff --git a/src/libei-private.h b/src/libei-private.h index 5810e7e..f633b5a 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -63,6 +63,7 @@ struct ei { struct object object; struct ei_connection *connection; + struct ei_connection_setup *connection_setup; struct list proto_objects; /* brei_object list */ uint32_t next_object_id; @@ -117,6 +118,12 @@ ei_send_message(struct ei *ei, const struct brei_object *object, void ei_add_seat(struct ei_seat *seat); +void +ei_connected(struct ei *ei); + +void +ei_queue_connect_event(struct ei *ei); + void ei_queue_device_removed_event(struct ei_device *device); diff --git a/src/libei.c b/src/libei.c index 4d99c65..41a1755 100644 --- a/src/libei.c +++ b/src/libei.c @@ -62,6 +62,7 @@ ei_destroy(struct ei *ei) if (ei->backend_interface.destroy) ei->backend_interface.destroy(ei, ei->backend); ei->backend = NULL; + ei_connection_setup_unref(ei->connection_setup); ei_connection_unref(ei->connection); sink_unref(ei->sink); free(ei->name); @@ -98,7 +99,7 @@ ei_create_context(bool is_sender, void *user_data) list_init(&ei->seats); list_init(&ei->proto_objects); - ei->connection = ei_connection_new(ei); + ei->connection_setup = ei_connection_setup_new(ei, VERSION_V(1)); ei->next_object_id = 1; ei_log_set_handler(ei, NULL); @@ -259,8 +260,8 @@ insert_event(struct ei *ei, struct ei_event *event) } -static void -queue_connect_event(struct ei *ei) +void +ei_queue_connect_event(struct ei *ei) { struct ei_event *e = ei_event_new(ei); e->type = EI_EVENT_CONNECT; @@ -580,9 +581,13 @@ static int handle_msg_seat(struct ei_connection *connection, uint32_t seat_id, uint32_t version) { struct ei *ei = ei_connection_get_context(connection); - struct ei_seat *seat = ei_seat_new(ei, seat_id, version); + /* We might get the seat event before our callback finished, so make sure + * we know we're connected + */ + ei_connected(ei); + /* seats list owns the ref */ list_append(&ei->seats, &seat->link); @@ -629,6 +634,15 @@ ei_peek_event(struct ei *ei) return ei_event_ref(e); } +void +ei_connected(struct ei *ei) +{ + if (ei->state == EI_STATE_CONNECTING) { + ei->state = EI_STATE_CONNECTED; + ei_queue_connect_event(ei); + } +} + static int handle_msg_disconnected(struct ei_connection *connection, uint32_t reason, const char *explanation) { struct ei *ei = ei_connection_get_context(connection); @@ -648,80 +662,15 @@ static int handle_msg_disconnected(struct ei_connection *connection, uint32_t re } \ } while(0) -static void -connected(struct ei_connection *connection, void *user_data) -{ - struct ei *ei = ei_connection_get_context(connection); - - /* FIXME: the connected event *should* mean that the server - * has accepted us but we don't currently have any event - * for this to hook onto. So let's just assume "connected" means - * the server has seen our messages. - */ - ei->state = EI_STATE_CONNECTED; - queue_connect_event(ei); -} - -static int -handle_msg_connection_setup(struct ei_connection *connection, uint32_t new_id, uint32_t version) -{ - struct ei *ei = ei_connection_get_context(connection); - - struct ei_connection_setup *setup = ei_connection_setup_new(ei, new_id, version); - if (version >= EI_CONNECTION_SETUP_REQUEST_TYPE_SINCE_VERSION) - ei_connection_setup_request_type(setup, ei->is_sender ? EI_CONNECTION_SETUP_CONTEXT_TYPE_SENDER : EI_CONNECTION_SETUP_CONTEXT_TYPE_RECEIVER); - if (version >= EI_CONNECTION_SETUP_REQUEST_NAME_SINCE_VERSION) - ei_connection_setup_request_name(setup, ei->name); - if (version >= EI_CONNECTION_SETUP_REQUEST_INTERFACE_SINCE_VERSION) { - ei_connection_setup_request_interface(setup, "ei_connection", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_callback", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_seat", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_device", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_pointer", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_keyboard", VERSION_V(1)); - ei_connection_setup_request_interface(setup, "ei_touchscreen", VERSION_V(1)); - } - ei_connection_setup_request_done(setup); - ei_connection_setup_unref(setup); - - ei->state = EI_STATE_CONNECTING; - - ei_connection_sync(ei->connection, connected, NULL); - - return 0; -} - -static const struct ei_connection_interface intf_state_backend = { - .connection_setup = handle_msg_connection_setup, - /* Everything triggers -EPROTO */ -}; - -static const struct ei_connection_interface intf_state_connecting = { - .connection_setup = handle_msg_connection_setup, - .disconnected = handle_msg_disconnected, -}; - -static const struct ei_connection_interface intf_state_connected = { - .connection_setup = NULL, /* EPROTO */ +static const struct ei_connection_interface interface = { .disconnected = handle_msg_disconnected, .seat = handle_msg_seat, }; -static const struct ei_connection_interface *interfaces[] = { - [EI_STATE_NEW] = NULL, - [EI_STATE_BACKEND] = &intf_state_backend, - [EI_STATE_CONNECTING] = &intf_state_connecting, - [EI_STATE_CONNECTED] = &intf_state_connected, - [EI_STATE_DISCONNECTING] = NULL, - [EI_STATE_DISCONNECTED] = NULL, -}; - - const struct ei_connection_interface * ei_get_interface(struct ei *ei) { - assert(ei->state < ARRAY_LENGTH(interfaces)); - return interfaces[ei->state]; + return &interface; } static int @@ -803,8 +752,9 @@ ei_set_socket(struct ei *ei, int fd) ei->source = source_ref(source); ei->state = EI_STATE_BACKEND; - /* The server SHOULD have already sent the connection setup, let's - * process that. If not ready, it'll happen in the next dispatch. + /* The server SHOULD have already sent the connection setup + * version, let's process that. If not ready, it'll happen + * in the next dispatch. * * FIXME: this will block if O_NONBLOCK is missing */ diff --git a/src/libeis-client.c b/src/libeis-client.c index a221a65..827332e 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -163,14 +163,6 @@ eis_client_send_message(struct eis_client *client, const struct brei_object *obj return rc < 0 ? rc : 0; } -static int -client_send_connection_setup(struct eis_client *client, struct eis_connection_setup *setup) -{ - return eis_connection_event_connection_setup(client->connection, - eis_connection_setup_get_id(setup), - eis_connection_setup_get_version(setup)); -} - static int client_send_disconnect(struct eis_client *client, const char *reason) { @@ -382,9 +374,6 @@ eis_client_new(struct eis *eis, int fd) .ei_keyboard = VERSION_V(1), .ei_touchscreen = VERSION_V(1), }; - - client->connection = eis_connection_new(client); - struct source *s = source_new(fd, client_dispatch, client); int rc = sink_add_source(eis->sink, s); @@ -405,11 +394,7 @@ eis_client_new(struct eis *eis, int fd) source_unref(s); - /* Send the event for the connection setup interface */ - struct eis_connection_setup *setup = eis_connection_setup_new(client, eis_client_get_new_id(client), - &client->interface_versions); - client_send_connection_setup(client, setup); - client->setup = setup; + client->setup = eis_connection_setup_new(client, &client->interface_versions); return client; } diff --git a/src/libeis-connection-setup.c b/src/libeis-connection-setup.c index b2dabcb..7ceab2f 100644 --- a/src/libeis-connection-setup.c +++ b/src/libeis-connection-setup.c @@ -86,6 +86,10 @@ client_msg_done(struct eis_connection_setup *setup) rc = 0; } + + client->connection = eis_connection_new(client); + eis_connection_setup_event_connection(setup, eis_connection_get_id(client->connection), + eis_connection_get_version(client->connection)); eis_connection_setup_unref(setup); return rc; @@ -175,21 +179,23 @@ eis_connection_setup_get_interface(struct eis_connection_setup *setup) { } struct eis_connection_setup * -eis_connection_setup_new(struct eis_client *client, uint32_t new_id, +eis_connection_setup_new(struct eis_client *client, const struct eis_client_interface_versions *versions) { struct eis_connection_setup *setup = eis_connection_setup_create(&client->object); - setup->proto_object.id = new_id; + setup->proto_object.id = 0; setup->proto_object.implementation = setup; setup->proto_object.interface = &eis_connection_setup_proto_interface; - setup->proto_object.version = versions->ei_connection_setup; + /* This object is always v1 until the client tells us otherwise */ + setup->proto_object.version = VERSION_V(1); list_init(&setup->proto_object.link); setup->version = VERSION_V(1); /* our ei-connection-setup version */ setup->server_versions = *versions; eis_client_register_object(client, &setup->proto_object); + eis_connection_setup_event_version(setup, versions->ei_connection_setup); return setup; /* ref owned by caller */ } diff --git a/src/libeis-connection-setup.h b/src/libeis-connection-setup.h index d143fbd..541ab72 100644 --- a/src/libeis-connection-setup.h +++ b/src/libeis-connection-setup.h @@ -55,5 +55,5 @@ OBJECT_DECLARE_REF(eis_connection_setup); OBJECT_DECLARE_UNREF(eis_connection_setup); struct eis_connection_setup * -eis_connection_setup_new(struct eis_client *client, uint32_t new_id, +eis_connection_setup_new(struct eis_client *client, const struct eis_client_interface_versions *versions); diff --git a/src/libeis-connection.c b/src/libeis-connection.c index 743f45f..f7bca73 100644 --- a/src/libeis-connection.c +++ b/src/libeis-connection.c @@ -53,6 +53,18 @@ OBJECT_IMPLEMENT_CREATE(eis_connection); static OBJECT_IMPLEMENT_PARENT(eis_connection, eis_client); +uint32_t +eis_connection_get_version(struct eis_connection *connection) +{ + return connection->proto_object.version; +} + +uint32_t +eis_connection_get_id(struct eis_connection *connection) +{ + return connection->proto_object.id; +} + struct eis_client* eis_connection_get_client(struct eis_connection *connection) { @@ -80,7 +92,7 @@ eis_connection_new(struct eis_client *client) connection->proto_object.id = eis_client_get_new_id(client); connection->proto_object.implementation = connection; connection->proto_object.interface = &eis_connection_proto_interface; - connection->proto_object.version = VERSION_V(1); + connection->proto_object.version = client->interface_versions.ei_connection; eis_client_register_object(client, &connection->proto_object); return connection; /* ref owned by caller */ diff --git a/src/libeis-connection.h b/src/libeis-connection.h index 1203674..e0d7cdf 100644 --- a/src/libeis-connection.h +++ b/src/libeis-connection.h @@ -38,6 +38,8 @@ struct eis_connection { }; OBJECT_DECLARE_GETTER(eis_connection, context, struct eis *); +OBJECT_DECLARE_GETTER(eis_connection, id, uint32_t); +OBJECT_DECLARE_GETTER(eis_connection, version, uint32_t); OBJECT_DECLARE_GETTER(eis_connection, client, struct eis_client *); OBJECT_DECLARE_GETTER(eis_connection, proto_object, const struct brei_object *); OBJECT_DECLARE_GETTER(eis_connection, interface, const struct eis_connection_interface *);