From 51f868c6ff64c36dfbe95496dc2eb45753a1f2fb Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Sat, 25 Mar 2023 12:57:24 +0000 Subject: [PATCH] Iterate over clients instead of listing This model avoids memory allocations and allows for re-use of the info function for client events. --- include/ctl-server.h | 13 +++++------ src/ctl-server.c | 47 +++++++++++++++++++++++++++++----------- src/main.c | 51 +++++++++++++++++++------------------------- 3 files changed, 64 insertions(+), 47 deletions(-) diff --git a/include/ctl-server.h b/include/ctl-server.h index f787a4c..ce6249e 100644 --- a/include/ctl-server.h +++ b/include/ctl-server.h @@ -21,7 +21,9 @@ struct ctl; struct cmd_response; -struct ctl_server_vnc_client { +struct ctl_server_client; + +struct ctl_server_client_info { char id[64]; char hostname[256]; char username[256]; @@ -47,11 +49,10 @@ struct ctl_server_actions { const char* id); struct cmd_response* (*on_wayvnc_exit)(struct ctl*); - // Return number of elements created - // Allocate 'clients' array or set ton ULL if none - // Receiver will free(clients) when done. - int (*get_client_list)(struct ctl*, - struct ctl_server_vnc_client** clients); + struct ctl_server_client *(*client_next)(struct ctl*, + struct ctl_server_client* prev); + void (*client_info)(const struct ctl_server_client*, + struct ctl_server_client_info* info); // Return number of elements created // Allocate 'outputs' array or set to NULL if none diff --git a/src/ctl-server.c b/src/ctl-server.c index b68cccf..e308309 100644 --- a/src/ctl-server.c +++ b/src/ctl-server.c @@ -328,26 +328,49 @@ static struct cmd_response* generate_version_object() return response; } +static struct ctl_server_client* ctl_server_client_first(struct ctl* self) +{ + return self->actions.client_next(self, NULL); +} + +static struct ctl_server_client* ctl_server_client_next(struct ctl* self, + struct ctl_server_client* prev) +{ + return self->actions.client_next(self, prev); +} + +static void ctl_server_client_get_info(struct ctl* self, + const struct ctl_server_client* client, + struct ctl_server_client_info* info) +{ + return self->actions.client_info(client, info); +} + static struct cmd_response* generate_vnc_client_list(struct ctl* self) { - struct ctl_server_vnc_client* clients; - size_t num_clients = self->actions.get_client_list(self, &clients); struct cmd_response* response = cmd_ok(); - response->data = json_array(); - for (size_t i = 0; i < num_clients; ++i) { - json_t* packed = json_pack("{s:s}", "id", clients[i].id); - if (clients[i].hostname[0] != '\0') + + struct ctl_server_client* client; + for (client = ctl_server_client_first(self); client; + client = ctl_server_client_next(self, client)) { + struct ctl_server_client_info info = {}; + ctl_server_client_get_info(self, client, &info); + + json_t* packed = json_pack("{s:s}", "id", info.id); + + if (info.hostname[0] != '\0') json_object_set_new(packed, "hostname", - json_string(clients[i].hostname)); - if (clients[i].username[0] != '\0') + json_string(info.hostname)); + + if (info.username[0] != '\0') json_object_set_new(packed, "username", - json_string(clients[i].username)); - json_object_set_new(packed, "seat", - json_string(clients[i].seat)); + json_string(info.username)); + + json_object_set_new(packed, "seat", json_string(info.seat)); json_array_append_new(response->data, packed); } - free(clients); + return response; } diff --git a/src/main.c b/src/main.c index 2440326..01f8cf9 100644 --- a/src/main.c +++ b/src/main.c @@ -492,42 +492,34 @@ struct cmd_response* on_output_switch(struct ctl* ctl, return cmd_ok(); } -static int get_client_list(struct ctl* ctl, - struct ctl_server_vnc_client** clients) +static struct ctl_server_client *client_next(struct ctl* ctl, + struct ctl_server_client *prev) { struct wayvnc* self = ctl_server_userdata(ctl); - if (self->nr_clients == 0) { - *clients = NULL; - return 0; - } + struct nvnc_client* vnc_prev = (struct nvnc_client*)prev; - *clients = calloc(self->nr_clients, sizeof(**clients)); - struct nvnc_client* nvnc_client = nvnc_client_first(self->nvnc); + return prev ? (struct ctl_server_client*)nvnc_client_next(vnc_prev) : + (struct ctl_server_client*)nvnc_client_first(self->nvnc); +} - for (int i = 0; i < self->nr_clients && nvnc_client; ++i) { - struct wayvnc_client* client = nvnc_get_userdata(nvnc_client); - struct ctl_server_vnc_client* ctl_client =&(*clients)[i]; +static void client_info(const struct ctl_server_client* client_handle, + struct ctl_server_client_info* info) +{ + const struct nvnc_client *vnc_client = + (const struct nvnc_client*)client_handle; + const struct wayvnc_client *client = nvnc_get_userdata(vnc_client); - snprintf(ctl_client->id, sizeof(ctl_client->id), "%u", - client->id); + snprintf(info->id, sizeof(info->id), "%u", client->id); - const char* hostname = nvnc_client_get_hostname(nvnc_client); - if (hostname) - strlcpy(ctl_client->hostname, hostname, - sizeof(ctl_client->hostname)); + const char* hostname = nvnc_client_get_hostname(vnc_client); + if (hostname) + strlcpy(info->hostname, hostname, sizeof(info->hostname)); - const char* username = nvnc_client_get_auth_username(nvnc_client); - if (username) - strlcpy(ctl_client->username, username, - sizeof(ctl_client->username)); + const char* username = nvnc_client_get_auth_username(vnc_client); + if (username) + strlcpy(info->username, username, sizeof(info->username)); - strlcpy(ctl_client->seat, client->seat->name, - sizeof(ctl_client->seat)); - - nvnc_client = nvnc_client_next(nvnc_client); - } - - return self->nr_clients; + strlcpy(info->seat, client->seat->name, sizeof(info->seat)); } static int get_output_list(struct ctl* ctl, @@ -1488,7 +1480,8 @@ int main(int argc, char* argv[]) .userdata = &self, .on_output_cycle = on_output_cycle, .on_output_switch = on_output_switch, - .get_client_list = get_client_list, + .client_next = client_next, + .client_info = client_info, .get_output_list = get_output_list, .on_disconnect_client = on_disconnect_client, .on_wayvnc_exit = on_wayvnc_exit,