Iterate over clients instead of listing

This model avoids memory allocations and allows for re-use of
the info function for client events.
transient-seats
Andri Yngvason 2023-03-25 12:57:24 +00:00
parent 0414e1fd87
commit 842da93de4
3 changed files with 64 additions and 47 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -507,42 +507,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;
return prev ? (struct ctl_server_client*)nvnc_client_next(vnc_prev) :
(struct ctl_server_client*)nvnc_client_first(self->nvnc);
}
*clients = calloc(self->nr_clients, sizeof(**clients));
struct nvnc_client* nvnc_client = nvnc_client_first(self->nvnc);
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);
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];
snprintf(info->id, sizeof(info->id), "%u", client->id);
snprintf(ctl_client->id, sizeof(ctl_client->id), "%u",
client->id);
const char* hostname = nvnc_client_get_hostname(nvnc_client);
const char* hostname = nvnc_client_get_hostname(vnc_client);
if (hostname)
strlcpy(ctl_client->hostname, hostname,
sizeof(ctl_client->hostname));
strlcpy(info->hostname, hostname, sizeof(info->hostname));
const char* username = nvnc_client_get_auth_username(nvnc_client);
const char* username = nvnc_client_get_auth_username(vnc_client);
if (username)
strlcpy(ctl_client->username, username,
sizeof(ctl_client->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,
@ -1569,7 +1561,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,