parent
c75b64eae8
commit
debd8a67cb
|
@ -263,41 +263,76 @@ out:
|
||||||
printf("\n");
|
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")) {
|
if (json_object_get(data, "commands")) {
|
||||||
printf("Allowed commands:\n");
|
printf("Allowed commands:\n");
|
||||||
json_t* cmd_list = json_object_get(data, "commands");
|
json_t* cmd_list = json_object_get(data, "commands");
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
json_t* value;
|
json_t* value;
|
||||||
|
|
||||||
json_array_foreach(cmd_list, index, value) {
|
json_array_foreach(cmd_list, index, value) {
|
||||||
printf(" - %s\n", json_string_value(value));
|
printf(" - %s\n", json_string_value(value));
|
||||||
}
|
}
|
||||||
printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_command = json_object_get(request, "command");
|
||||||
const char* key;
|
const char* key;
|
||||||
json_t* value;
|
json_t* value;
|
||||||
|
|
||||||
json_object_foreach(data, key, value) {
|
json_object_foreach(data, key, value) {
|
||||||
char* desc = NULL;
|
if (is_command)
|
||||||
json_t* params = NULL;
|
print_command_usage(key, value);
|
||||||
json_unpack(value, "{s:s, s?o}", "description", &desc,
|
else
|
||||||
"params", ¶ms);
|
print_event_details(key, value);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,10 +345,12 @@ 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_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)
|
if (strcmp(method, "help") == 0)
|
||||||
print_help(data);
|
print_help(data, request->params);
|
||||||
else if (strcmp(method, "version") == 0)
|
else if (strcmp(method, "version") == 0)
|
||||||
pretty_version(data);
|
pretty_version(data);
|
||||||
else
|
else
|
||||||
|
@ -336,7 +373,7 @@ static int ctl_client_print_response(struct ctl_client* self,
|
||||||
if (flags & PRINT_JSON)
|
if (flags & PRINT_JSON)
|
||||||
print_compact_json(response->data);
|
print_compact_json(response->data);
|
||||||
else if (response->code == 0)
|
else if (response->code == 0)
|
||||||
pretty_print(response->data, request->method);
|
pretty_print(response->data, request);
|
||||||
else
|
else
|
||||||
print_error(response, request->method);
|
print_error(response, request->method);
|
||||||
}
|
}
|
||||||
|
|
100
src/ctl-server.c
100
src/ctl-server.c
|
@ -47,6 +47,14 @@ enum cmd_type {
|
||||||
CMD_SET_OUTPUT,
|
CMD_SET_OUTPUT,
|
||||||
CMD_UNKNOWN,
|
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 {
|
struct cmd_param_info {
|
||||||
char* name;
|
char* name;
|
||||||
|
@ -61,9 +69,10 @@ struct cmd_info {
|
||||||
|
|
||||||
static struct cmd_info cmd_list[] = {
|
static struct cmd_info cmd_list[] = {
|
||||||
[CMD_HELP] = { "help",
|
[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)"},
|
{"command", "The command to show (optional)"},
|
||||||
|
{"event", "The event to show (optional)"},
|
||||||
{NULL, NULL},
|
{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 {
|
struct cmd {
|
||||||
enum cmd_type type;
|
enum cmd_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_help {
|
struct cmd_help {
|
||||||
struct cmd cmd;
|
struct cmd cmd;
|
||||||
char command[64];
|
char id[64];
|
||||||
|
bool id_is_command;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_set_output {
|
struct cmd_set_output {
|
||||||
|
@ -147,7 +175,7 @@ static enum cmd_type parse_command_name(const char* name)
|
||||||
{
|
{
|
||||||
if (!name || name[0] == '\0')
|
if (!name || name[0] == '\0')
|
||||||
return CMD_UNKNOWN;
|
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) {
|
if (strcmp(name, cmd_list[i].name) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -159,15 +187,28 @@ static struct cmd_help* cmd_help_new(json_t* args,
|
||||||
struct jsonipc_error* err)
|
struct jsonipc_error* err)
|
||||||
{
|
{
|
||||||
const char* command = NULL;
|
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,
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct cmd_help* cmd = calloc(1, sizeof(*cmd));
|
struct cmd_help* cmd = calloc(1, sizeof(*cmd));
|
||||||
cmd->cmd.type = CMD_HELP;
|
cmd->cmd.type = CMD_HELP;
|
||||||
if (command)
|
if (command) {
|
||||||
strlcpy(cmd->command, command, sizeof(cmd->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;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +248,25 @@ static struct cmd_set_output* cmd_set_output_new(json_t* args,
|
||||||
return cmd;
|
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();
|
json_t* allowed = json_array();
|
||||||
for (int i = 0; i < CMD_UNKNOWN; ++i)
|
for (int i = 0; i < len; ++i) {
|
||||||
json_array_append_new(allowed, json_string(cmd_list[i].name));
|
json_array_append_new(allowed, json_string((*list)[i].name));
|
||||||
|
}
|
||||||
return allowed;
|
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,
|
static struct cmd* parse_command(struct jsonipc_request* ipc,
|
||||||
struct jsonipc_error* err)
|
struct jsonipc_error* err)
|
||||||
{
|
{
|
||||||
|
@ -316,14 +368,28 @@ static json_t* client_next_object(struct ctl_client* self, struct cmd_response**
|
||||||
return root;
|
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)
|
||||||
{
|
{
|
||||||
enum cmd_type ctype = parse_command_name(cmd);
|
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)
|
||||||
|
{
|
||||||
|
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;
|
json_t* data;
|
||||||
if (ctype == CMD_UNKNOWN) {
|
if (!info) {
|
||||||
data = json_pack("{s:o}", "commands", list_allowed_commands());
|
data = json_pack("{s:o, s:o}",
|
||||||
|
"commands", list_allowed_commands(),
|
||||||
|
"events", list_allowed_events());
|
||||||
} else {
|
} else {
|
||||||
struct cmd_info* info = &cmd_list[ctype];
|
|
||||||
json_t* param_list = NULL;
|
json_t* param_list = NULL;
|
||||||
if (info->params[0].name) {
|
if (info->params[0].name) {
|
||||||
param_list = json_object();
|
param_list = json_object();
|
||||||
|
@ -362,7 +428,7 @@ static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
|
||||||
switch (cmd->type) {
|
switch (cmd->type) {
|
||||||
case CMD_HELP:{
|
case CMD_HELP:{
|
||||||
struct cmd_help* c = (struct cmd_help*)cmd;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_SET_OUTPUT: {
|
case CMD_SET_OUTPUT: {
|
||||||
|
@ -799,7 +865,7 @@ int ctl_server_enqueue_event(struct ctl* self, const char* event_name,
|
||||||
return enqueued;
|
return enqueued;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctl_server_event_connect(struct ctl* self,
|
static void ctl_server_event_connect(struct ctl* self,
|
||||||
bool connected,
|
bool connected,
|
||||||
const char* client_id,
|
const char* client_id,
|
||||||
const char* client_hostname,
|
const char* client_hostname,
|
||||||
|
|
Loading…
Reference in New Issue