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
parent
1c9a8c0769
commit
51f868c6ff
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
51
src/main.c
51
src/main.c
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue