Add wayvncctl get-clients command
Signed-off-by: Jim Ramsay <i.am@jimramsay.com>pull/193/head
parent
72238686c4
commit
19e3d78d78
|
@ -17,17 +17,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include <wayland-client.h>
|
|
||||||
|
|
||||||
struct ctl;
|
struct ctl;
|
||||||
struct cmd_response;
|
struct cmd_response;
|
||||||
|
|
||||||
|
struct ctl_server_vnc_client {
|
||||||
|
char id[64];
|
||||||
|
char hostname[256];
|
||||||
|
char username[256];
|
||||||
|
};
|
||||||
|
|
||||||
struct ctl_server_actions {
|
struct ctl_server_actions {
|
||||||
void* userdata;
|
void* userdata;
|
||||||
struct cmd_response* (*on_output_cycle)(struct ctl*,
|
struct cmd_response* (*on_output_cycle)(struct ctl*,
|
||||||
enum output_cycle_direction direction);
|
enum output_cycle_direction direction);
|
||||||
struct cmd_response* (*on_output_switch)(struct ctl*,
|
struct cmd_response* (*on_output_switch)(struct ctl*,
|
||||||
const char* output_name);
|
const char* output_name);
|
||||||
|
|
||||||
|
// 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* ctl_server_new(const char* socket_path,
|
struct ctl* ctl_server_new(const char* socket_path,
|
||||||
|
|
|
@ -392,6 +392,26 @@ static void pretty_version(json_t* data)
|
||||||
printf(" %s: %s\n", key, json_string_value(value));
|
printf(" %s: %s\n", key, json_string_value(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pretty_client_list(json_t* data)
|
||||||
|
{
|
||||||
|
int n = json_array_size(data);
|
||||||
|
printf("There %s %d VNC client%s connected%s\n", (n == 1) ? "is" : "are",
|
||||||
|
n, (n == 1) ? "" : "s", (n > 0) ? ":" : ".");
|
||||||
|
int i;
|
||||||
|
json_t* value;
|
||||||
|
json_array_foreach(data, i, value) {
|
||||||
|
char* id = NULL;
|
||||||
|
char* hostname = NULL;
|
||||||
|
char* username = NULL;
|
||||||
|
json_unpack(value, "{s:s, s?s, s?s}", "id", &id, "hostname",
|
||||||
|
&hostname, "username", &username);
|
||||||
|
printf(" client[%s]: ", id);
|
||||||
|
if (username)
|
||||||
|
printf("%s@", username);
|
||||||
|
printf("%s\n", hostname ? hostname : "<unknown>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void pretty_print(json_t* data,
|
static void pretty_print(json_t* data,
|
||||||
struct jsonipc_request* request)
|
struct jsonipc_request* request)
|
||||||
{
|
{
|
||||||
|
@ -400,6 +420,8 @@ static void pretty_print(json_t* data,
|
||||||
print_help(data, request->params);
|
print_help(data, request->params);
|
||||||
else if (strcmp(method, "version") == 0)
|
else if (strcmp(method, "version") == 0)
|
||||||
pretty_version(data);
|
pretty_version(data);
|
||||||
|
else if (strcmp(method, "get-clients") == 0)
|
||||||
|
pretty_client_list(data);
|
||||||
else
|
else
|
||||||
json_dumpf(data, stdout, JSON_INDENT(2));
|
json_dumpf(data, stdout, JSON_INDENT(2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ enum cmd_type {
|
||||||
CMD_VERSION,
|
CMD_VERSION,
|
||||||
CMD_EVENT_RECEIVE,
|
CMD_EVENT_RECEIVE,
|
||||||
CMD_SET_OUTPUT,
|
CMD_SET_OUTPUT,
|
||||||
|
CMD_GET_CLIENTS,
|
||||||
CMD_UNKNOWN,
|
CMD_UNKNOWN,
|
||||||
};
|
};
|
||||||
#define CMD_LIST_LEN CMD_UNKNOWN
|
#define CMD_LIST_LEN CMD_UNKNOWN
|
||||||
|
@ -94,6 +95,11 @@ static struct cmd_info cmd_list[] = {
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
[CMD_GET_CLIENTS] = { "get-clients",
|
||||||
|
"Return a list of all currently connected VNC sessions",
|
||||||
|
{{NULL, NULL}}
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLIENT_EVENT_PARAMS(including) \
|
#define CLIENT_EVENT_PARAMS(including) \
|
||||||
|
@ -283,6 +289,7 @@ static struct cmd* parse_command(struct jsonipc_request* ipc,
|
||||||
break;
|
break;
|
||||||
case CMD_VERSION:
|
case CMD_VERSION:
|
||||||
case CMD_EVENT_RECEIVE:
|
case CMD_EVENT_RECEIVE:
|
||||||
|
case CMD_GET_CLIENTS:
|
||||||
cmd = calloc(1, sizeof(*cmd));
|
cmd = calloc(1, sizeof(*cmd));
|
||||||
cmd->type = cmd_type;
|
cmd->type = cmd_type;
|
||||||
break;
|
break;
|
||||||
|
@ -308,6 +315,7 @@ static void client_destroy(struct ctl_client* self)
|
||||||
wl_list_remove(&self->link);
|
wl_list_remove(&self->link);
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_internal_error(struct cmd_response** err, int code,
|
static void set_internal_error(struct cmd_response** err, int code,
|
||||||
const char* fmt, ...)
|
const char* fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -419,6 +427,27 @@ static struct cmd_response* generate_version_object()
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (int i = 0; i < num_clients; ++i) {
|
||||||
|
json_t* packed = json_pack("{s:s}", "id", clients[i].id);
|
||||||
|
if (clients[i].hostname[0] != '\0')
|
||||||
|
json_object_set_new(packed, "hostname",
|
||||||
|
json_string(clients[i].hostname));
|
||||||
|
if (clients[i].username[0] != '\0')
|
||||||
|
json_object_set_new(packed, "username",
|
||||||
|
json_string(clients[i].username));
|
||||||
|
json_array_append_new(response->data, packed);
|
||||||
|
}
|
||||||
|
free(clients);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
|
static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
|
||||||
struct ctl_client* client, struct cmd* cmd)
|
struct ctl_client* client, struct cmd* cmd)
|
||||||
{
|
{
|
||||||
|
@ -447,6 +476,9 @@ static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
|
||||||
client->accept_events = true;
|
client->accept_events = true;
|
||||||
response = cmd_ok();
|
response = cmd_ok();
|
||||||
break;
|
break;
|
||||||
|
case CMD_GET_CLIENTS:
|
||||||
|
response = generate_vnc_client_list(self);
|
||||||
|
break;
|
||||||
case CMD_UNKNOWN:
|
case CMD_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
30
src/main.c
30
src/main.c
|
@ -464,6 +464,35 @@ struct cmd_response* on_output_switch(struct ctl* ctl,
|
||||||
return cmd_ok();
|
return cmd_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_client_list(struct ctl* ctl,
|
||||||
|
struct ctl_server_vnc_client** clients)
|
||||||
|
{
|
||||||
|
struct wayvnc* self = ctl_server_userdata(ctl);
|
||||||
|
if (self->nr_clients == 0) {
|
||||||
|
*clients = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*clients = calloc(self->nr_clients, sizeof(**clients));
|
||||||
|
struct nvnc_client* nvnc_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];
|
||||||
|
|
||||||
|
snprintf(ctl_client->id, sizeof(ctl_client->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* username = nvnc_client_get_auth_username(nvnc_client);
|
||||||
|
if (username)
|
||||||
|
strlcpy(ctl_client->username, username,
|
||||||
|
sizeof(ctl_client->username));
|
||||||
|
nvnc_client = nvnc_client_next(nvnc_client);
|
||||||
|
}
|
||||||
|
return self->nr_clients;
|
||||||
|
}
|
||||||
|
|
||||||
int init_main_loop(struct wayvnc* self)
|
int init_main_loop(struct wayvnc* self)
|
||||||
{
|
{
|
||||||
struct aml* loop = aml_get_default();
|
struct aml* loop = aml_get_default();
|
||||||
|
@ -1304,6 +1333,7 @@ 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,
|
||||||
};
|
};
|
||||||
self.ctl = ctl_server_new(socket_path, &ctl_actions);
|
self.ctl = ctl_server_new(socket_path, &ctl_actions);
|
||||||
if (!self.ctl)
|
if (!self.ctl)
|
||||||
|
|
|
@ -199,6 +199,11 @@ which parameters are supplied:
|
||||||
*switch-to=output-name*
|
*switch-to=output-name*
|
||||||
Switch to a specific output by name.
|
Switch to a specific output by name.
|
||||||
|
|
||||||
|
_GET-CLIENTS_
|
||||||
|
|
||||||
|
The *get-clients* command retrieves a list of all VNC clients currently
|
||||||
|
connected to wayvnc.
|
||||||
|
|
||||||
## IPC EVENTS
|
## IPC EVENTS
|
||||||
|
|
||||||
_CLIENT-CONNECTED_
|
_CLIENT-CONNECTED_
|
||||||
|
|
Loading…
Reference in New Issue