libei/src/libeis-connection.c
Peter Hutterer e0a6c75cb4 protocol: widen the callback_data arg for ping/sync to 64bit
The only invocations we have right now of these callbacks ignore the
argument or force it to zero. But in the future we may have an interface
that requires a callback and that interface may need to store a
timestamp or object ID in this argument - so let's make sure we have
enough space for that.
2023-05-16 15:09:47 +10:00

151 lines
4.7 KiB
C

/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <errno.h>
#include <stdbool.h>
#include "util-bits.h"
#include "util-macros.h"
#include "util-mem.h"
#include "util-io.h"
#include "util-strings.h"
#include "util-version.h"
#include "libeis-private.h"
#include "eis-proto.h"
static void
eis_connection_destroy(struct eis_connection *connection)
{
struct eis_client *client = eis_connection_get_client(connection);
eis_client_unregister_object(client, &connection->proto_object);
struct eis_pingpong *cb;
list_for_each_safe(cb, &connection->pending_pingpongs, link) {
list_remove(&cb->link);
free(eis_pingpong_get_user_data(cb));
eis_pingpong_unref(cb);
}
}
OBJECT_IMPLEMENT_REF(eis_connection);
OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_connection);
OBJECT_IMPLEMENT_GETTER_AS_REF(eis_connection, proto_object, const struct brei_object *);
static
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;
}
object_id_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)
{
return eis_connection_parent(connection);
}
struct eis*
eis_connection_get_context(struct eis_connection *connection)
{
struct eis_client *client = eis_connection_parent(connection);
return eis_client_get_context(client);
}
const struct eis_connection_interface *
eis_connection_get_interface(struct eis_connection *connection) {
struct eis_client *client = eis_connection_parent(connection);
return eis_client_get_interface(client);
}
struct eis_connection *
eis_connection_new(struct eis_client *client)
{
struct eis_connection *connection = eis_connection_create(&client->object);
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 = client->interface_versions.ei_connection;
eis_client_register_object(client, &connection->proto_object);
list_init(&connection->pending_pingpongs);
return connection; /* ref owned by caller */
}
struct pingpong_user_data {
eis_connection_ping_callback_t cb;
void *user_data;
};
static void
ping_pingpong(struct eis_pingpong *pingpong, void *pingpong_data,
uint64_t proto_data)
{
struct eis_connection *connection = pingpong_data;
_cleanup_free_ struct pingpong_user_data *data = eis_pingpong_get_user_data(pingpong);
if (data->cb)
data->cb(connection, data->user_data);
/* remove from pending callbacks */
list_remove(&pingpong->link);
eis_pingpong_unref(pingpong);
}
void
eis_connection_ping(struct eis_connection *connection, eis_connection_ping_callback_t cb,
void *user_data)
{
struct eis_client *client = eis_connection_get_client(connection);
/* This is double-wrapped because we only use this for debugging purposes for
* now. The actual callback calls sync_callback with our connection,
* then we extract the user_data on the object and call into the
* cb supplied to this function.
*/
struct eis_pingpong *pingpong = eis_pingpong_new(client, ping_pingpong, connection);
struct pingpong_user_data *data = xalloc(sizeof *data);
data->cb = cb;
data->user_data = user_data;
eis_pingpong_set_user_data(pingpong, data);
list_append(&connection->pending_pingpongs, &pingpong->link);
eis_connection_event_ping(connection, eis_pingpong_get_id(pingpong),
eis_pingpong_get_version(pingpong));
}