Iterate over clients instead of listing

This model avoids memory allocations and allows for re-use of
the info function for client events.
websocket-tls
Andri Yngvason 2023-03-25 12:57:24 +00:00
parent 1c9a8c0769
commit 51f868c6ff
3 changed files with 64 additions and 47 deletions

View File

@ -21,7 +21,9 @@
struct ctl; struct ctl;
struct cmd_response; struct cmd_response;
struct ctl_server_vnc_client { struct ctl_server_client;
struct ctl_server_client_info {
char id[64]; char id[64];
char hostname[256]; char hostname[256];
char username[256]; char username[256];
@ -47,11 +49,10 @@ struct ctl_server_actions {
const char* id); const char* id);
struct cmd_response* (*on_wayvnc_exit)(struct ctl*); struct cmd_response* (*on_wayvnc_exit)(struct ctl*);
// Return number of elements created struct ctl_server_client *(*client_next)(struct ctl*,
// Allocate 'clients' array or set ton ULL if none struct ctl_server_client* prev);
// Receiver will free(clients) when done. void (*client_info)(const struct ctl_server_client*,
int (*get_client_list)(struct ctl*, struct ctl_server_client_info* info);
struct ctl_server_vnc_client** clients);
// Return number of elements created // Return number of elements created
// Allocate 'outputs' array or set to NULL if none // Allocate 'outputs' array or set to NULL if none

View File

@ -328,26 +328,49 @@ static struct cmd_response* generate_version_object()
return response; 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) 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(); struct cmd_response* response = cmd_ok();
response->data = json_array(); response->data = json_array();
for (size_t i = 0; i < num_clients; ++i) {
json_t* packed = json_pack("{s:s}", "id", clients[i].id); struct ctl_server_client* client;
if (clients[i].hostname[0] != '\0') 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_object_set_new(packed, "hostname",
json_string(clients[i].hostname)); json_string(info.hostname));
if (clients[i].username[0] != '\0')
if (info.username[0] != '\0')
json_object_set_new(packed, "username", json_object_set_new(packed, "username",
json_string(clients[i].username)); json_string(info.username));
json_object_set_new(packed, "seat",
json_string(clients[i].seat)); json_object_set_new(packed, "seat", json_string(info.seat));
json_array_append_new(response->data, packed); json_array_append_new(response->data, packed);
} }
free(clients);
return response; return response;
} }

View File

@ -492,42 +492,34 @@ struct cmd_response* on_output_switch(struct ctl* ctl,
return cmd_ok(); return cmd_ok();
} }
static int get_client_list(struct ctl* ctl, static struct ctl_server_client *client_next(struct ctl* ctl,
struct ctl_server_vnc_client** clients) struct ctl_server_client *prev)
{ {
struct wayvnc* self = ctl_server_userdata(ctl); struct wayvnc* self = ctl_server_userdata(ctl);
if (self->nr_clients == 0) { struct nvnc_client* vnc_prev = (struct nvnc_client*)prev;
*clients = NULL;
return 0;
}
*clients = calloc(self->nr_clients, sizeof(**clients)); return prev ? (struct ctl_server_client*)nvnc_client_next(vnc_prev) :
struct nvnc_client* nvnc_client = nvnc_client_first(self->nvnc); (struct ctl_server_client*)nvnc_client_first(self->nvnc);
}
for (int i = 0; i < self->nr_clients && nvnc_client; ++i) { static void client_info(const struct ctl_server_client* client_handle,
struct wayvnc_client* client = nvnc_get_userdata(nvnc_client); struct ctl_server_client_info* info)
struct ctl_server_vnc_client* ctl_client =&(*clients)[i]; {
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", snprintf(info->id, sizeof(info->id), "%u", client->id);
client->id);
const char* hostname = nvnc_client_get_hostname(nvnc_client); const char* hostname = nvnc_client_get_hostname(vnc_client);
if (hostname) if (hostname)
strlcpy(ctl_client->hostname, hostname, strlcpy(info->hostname, hostname, sizeof(info->hostname));
sizeof(ctl_client->hostname));
const char* username = nvnc_client_get_auth_username(nvnc_client); const char* username = nvnc_client_get_auth_username(vnc_client);
if (username) if (username)
strlcpy(ctl_client->username, username, strlcpy(info->username, username, sizeof(info->username));
sizeof(ctl_client->username));
strlcpy(ctl_client->seat, client->seat->name, strlcpy(info->seat, client->seat->name, sizeof(info->seat));
sizeof(ctl_client->seat));
nvnc_client = nvnc_client_next(nvnc_client);
}
return self->nr_clients;
} }
static int get_output_list(struct ctl* ctl, static int get_output_list(struct ctl* ctl,
@ -1488,7 +1480,8 @@ int main(int argc, char* argv[])
.userdata = &self, .userdata = &self,
.on_output_cycle = on_output_cycle, .on_output_cycle = on_output_cycle,
.on_output_switch = on_output_switch, .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, .get_output_list = get_output_list,
.on_disconnect_client = on_disconnect_client, .on_disconnect_client = on_disconnect_client,
.on_wayvnc_exit = on_wayvnc_exit, .on_wayvnc_exit = on_wayvnc_exit,