From 8076d62fe37de4b54fe311539e64f32b1a6bfa3a Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Tue, 8 Nov 2022 07:32:04 -0500 Subject: [PATCH] Added event help text Signed-off-by: Jim Ramsay --- src/ctl-client.c | 83 ++++++++++++++++++++++++++++----------- src/ctl-server.c | 100 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 143 insertions(+), 40 deletions(-) diff --git a/src/ctl-client.c b/src/ctl-client.c index 67856905..52d3248b 100644 --- a/src/ctl-client.c +++ b/src/ctl-client.c @@ -263,41 +263,76 @@ static void print_error(struct jsonipc_response* response, const char* method) printf("\n"); } -static void print_help(json_t* data) +static void print_command_usage(const char* name, json_t* data) +{ + char* desc = NULL; + json_t* params = NULL; + json_unpack(data, "{s:s, s?o}", "description", &desc, + "params", ¶ms); + printf("Usage: wayvncctl [options] %s%s\n\n%s\n", name, + params ? " [params]" : "", + desc); + if (params) { + printf("\nParameters:"); + const char* param_name; + json_t* param_value; + json_object_foreach(params, param_name, param_value) { + printf("\n --%s=...\n %s\n", param_name, + json_string_value(param_value)); + } + } + printf("\nRun 'wayvncctl --help' for allowed Options\n"); +} + +static void print_event_details(const char* name, json_t* data) +{ + char* desc = NULL; + json_t* params = NULL; + json_unpack(data, "{s:s, s?o}", "description", &desc, + "params", ¶ms); + printf("Event: %s\n\n%s\n", name, + desc); + if (params) { + printf("\nParameters:"); + const char* param_name; + json_t* param_value; + json_object_foreach(params, param_name, param_value) { + printf("\n %s:...\n %s\n", param_name, + json_string_value(param_value)); + } + } +} + +static void print_help(json_t* data, json_t* request) { if (json_object_get(data, "commands")) { printf("Allowed commands:\n"); json_t* cmd_list = json_object_get(data, "commands"); + size_t index; json_t* value; - json_array_foreach(cmd_list, index, value) { printf(" - %s\n", json_string_value(value)); } printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n"); + + printf("\nSupported events:\n"); + json_t* evt_list = json_object_get(data, "events"); + json_array_foreach(evt_list, index, value) { + printf(" - %s\n", json_string_value(value)); + } + printf("\nRun 'wayvncctl help --event=event-name' for event-specific details.\n"); return; } + + bool is_command = json_object_get(request, "command"); const char* key; json_t* value; - json_object_foreach(data, key, value) { - char* desc = NULL; - json_t* params = NULL; - json_unpack(value, "{s:s, s?o}", "description", &desc, - "params", ¶ms); - printf("Usage: wayvncctl [options] %s%s\n\n%s\n", key, - params ? " [params]" : "", - desc); - if (params) { - printf("\nParameters:"); - const char* param_name; - json_t* param_value; - json_object_foreach(params, param_name, param_value) { - printf("\n --%s=...\n %s\n", param_name, - json_string_value(param_value)); - } - } - printf("\nRun 'wayvncctl --help' for allowed Options\n"); + if (is_command) + print_command_usage(key, value); + else + print_event_details(key, value); } } @@ -310,10 +345,12 @@ static void pretty_version(json_t* data) printf(" %s: %s\n", key, json_string_value(value)); } -static void pretty_print(json_t* data, const char* method) +static void pretty_print(json_t* data, + struct jsonipc_request* request) { + const char* method = request->method; if (strcmp(method, "help") == 0) - print_help(data); + print_help(data, request->params); else if (strcmp(method, "version") == 0) pretty_version(data); else @@ -336,7 +373,7 @@ static int ctl_client_print_response(struct ctl_client* self, if (flags & PRINT_JSON) print_compact_json(response->data); else if (response->code == 0) - pretty_print(response->data, request->method); + pretty_print(response->data, request); else print_error(response, request->method); } diff --git a/src/ctl-server.c b/src/ctl-server.c index 8ab3c103..8f622375 100644 --- a/src/ctl-server.c +++ b/src/ctl-server.c @@ -47,6 +47,14 @@ enum cmd_type { CMD_SET_OUTPUT, CMD_UNKNOWN, }; +#define CMD_LIST_LEN CMD_UNKNOWN + +enum event_type { + EVT_CLIENT_CONNECTED, + EVT_CLIENT_DISCONNECTED, + EVT_UNKNOWN, +}; +#define EVT_LIST_LEN EVT_UNKNOWN struct cmd_param_info { char* name; @@ -61,9 +69,10 @@ struct cmd_info { static struct cmd_info cmd_list[] = { [CMD_HELP] = { "help", - "List all commands, or show usage of a specific command", + "List all commands and events, or show usage of a specific command or event", { {"command", "The command to show (optional)"}, + {"event", "The event to show (optional)"}, {NULL, NULL}, } }, @@ -86,13 +95,32 @@ static struct cmd_info cmd_list[] = { }, }; +#define CLIENT_EVENT_PARAMS(including) \ + {"id", "A unique identifier for this client"}, \ + {"connection_count", "The total number of connected VNC clients " including " this one."}, \ + {"hostname", "The hostname or IP address of this client (may be null)"}, \ + {"username", "The username used to authentice this client (may be null)."}, \ + {NULL, NULL}, + +static struct cmd_info evt_list[] = { + [EVT_CLIENT_CONNECTED] = {"client-connected", + "Sent when a new vnc client connects to wayvnc", + { CLIENT_EVENT_PARAMS("including") } + }, + [EVT_CLIENT_DISCONNECTED] = {"client-disconnected", + "Sent when a vnc client disconnects from wayvnc", + { CLIENT_EVENT_PARAMS("not including") } + }, +}; + struct cmd { enum cmd_type type; }; struct cmd_help { struct cmd cmd; - char command[64]; + char id[64]; + bool id_is_command; }; struct cmd_set_output { @@ -147,7 +175,7 @@ static enum cmd_type parse_command_name(const char* name) { if (!name || name[0] == '\0') return CMD_UNKNOWN; - for (int i = 0; i < CMD_UNKNOWN; ++i) { + for (int i = 0; i < CMD_LIST_LEN; ++i) { if (strcmp(name, cmd_list[i].name) == 0) { return i; } @@ -159,15 +187,28 @@ static struct cmd_help* cmd_help_new(json_t* args, struct jsonipc_error* err) { const char* command = NULL; - if (args && json_unpack(args, "{s?s}", "command", &command) == -1) { + const char* event = NULL; + if (args && json_unpack(args, "{s?s, s?s}", + "command", &command, + "event", &event) == -1) { jsonipc_error_printf(err, EINVAL, - "expecting \"command\" (optional)"); + "expecting \"command\" or \"event\" (optional)"); + return NULL; + } + if (command && event) { + jsonipc_error_printf(err, EINVAL, + "expecting exacly one of \"command\" or \"event\""); return NULL; } struct cmd_help* cmd = calloc(1, sizeof(*cmd)); cmd->cmd.type = CMD_HELP; - if (command) - strlcpy(cmd->command, command, sizeof(cmd->command)); + if (command) { + strlcpy(cmd->id, command, sizeof(cmd->id)); + cmd->id_is_command = true; + } else if (event) { + strlcpy(cmd->id, event, sizeof(cmd->id)); + cmd->id_is_command = false; + } return cmd; } @@ -207,14 +248,25 @@ static struct cmd_set_output* cmd_set_output_new(json_t* args, return cmd; } -static json_t* list_allowed_commands() +static json_t* list_allowed(struct cmd_info (*list)[], size_t len) { json_t* allowed = json_array(); - for (int i = 0; i < CMD_UNKNOWN; ++i) - json_array_append_new(allowed, json_string(cmd_list[i].name)); + for (int i = 0; i < len; ++i) { + json_array_append_new(allowed, json_string((*list)[i].name)); + } return allowed; } +static json_t* list_allowed_commands() +{ + return list_allowed(&cmd_list, CMD_LIST_LEN); +} + +static json_t* list_allowed_events() +{ + return list_allowed(&evt_list, EVT_LIST_LEN); +} + static struct cmd* parse_command(struct jsonipc_request* ipc, struct jsonipc_error* err) { @@ -316,14 +368,28 @@ static json_t* client_next_object(struct ctl_client* self, struct cmd_response** return root; } -static struct cmd_response* generate_help_object(const char* cmd) +static struct cmd_info* find_info(const char* id, struct cmd_info (*list)[], + size_t len) +{ + for (int i = 0; i < len; ++i) { + struct cmd_info* info = &(*list)[i]; + if (strcmp(info->name, id) == 0) + return info; + } + return NULL; +} + +static struct cmd_response* generate_help_object(const char* id, bool id_is_command) { - enum cmd_type ctype = parse_command_name(cmd); + struct cmd_info* info = id_is_command ? + find_info(id, &cmd_list, CMD_LIST_LEN) : + find_info(id, &evt_list, EVT_LIST_LEN); json_t* data; - if (ctype == CMD_UNKNOWN) { - data = json_pack("{s:o}", "commands", list_allowed_commands()); + if (!info) { + data = json_pack("{s:o, s:o}", + "commands", list_allowed_commands(), + "events", list_allowed_events()); } else { - struct cmd_info* info = &cmd_list[ctype]; json_t* param_list = NULL; if (info->params[0].name) { param_list = json_object(); @@ -362,7 +428,7 @@ static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self, switch (cmd->type) { case CMD_HELP:{ struct cmd_help* c = (struct cmd_help*)cmd; - response = generate_help_object(c->command); + response = generate_help_object(c->id, c->id_is_command); break; } case CMD_SET_OUTPUT: { @@ -799,7 +865,7 @@ int ctl_server_enqueue_event(struct ctl* self, const char* event_name, return enqueued; } -void ctl_server_event_connect(struct ctl* self, +static void ctl_server_event_connect(struct ctl* self, bool connected, const char* client_id, const char* client_hostname,