mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-03-25 10:02:47 +08:00
215 lines
5.5 KiB
C
215 lines
5.5 KiB
C
/*
|
|
Copyright (c) 2023 Roger Light <roger@atchoo.org>
|
|
|
|
All rights reserved. This program and the accompanying materials
|
|
are made available under the terms of the Eclipse Public License 2.0
|
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
|
|
The Eclipse Public License is available at
|
|
https://www.eclipse.org/legal/epl-2.0/
|
|
and the Eclipse Distribution License is available at
|
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
|
|
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
|
|
|
Contributors:
|
|
Roger Light - initial implementation and documentation.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ctrl_shell_internal.h"
|
|
#include "json_help.h"
|
|
|
|
#ifdef WITH_CTRL_SHELL
|
|
|
|
#define UNUSED(A) (void)(A)
|
|
|
|
static struct completion_tree_root *commands_broker = NULL;
|
|
|
|
|
|
static void command_tree_create(void)
|
|
{
|
|
struct completion_tree_cmd *cmd;
|
|
struct completion_tree_arg_list *help_arg_list;
|
|
|
|
if(commands_broker){
|
|
return;
|
|
}
|
|
|
|
commands_broker = calloc(1, sizeof(struct completion_tree_root));
|
|
|
|
cmd = completion_tree_cmd_add(commands_broker, NULL, "help");
|
|
help_arg_list = completion_tree_cmd_add_arg_list(cmd);
|
|
|
|
completion_tree_cmd_add(commands_broker, help_arg_list, "listPlugins");
|
|
completion_tree_cmd_add(commands_broker, help_arg_list, "listListeners");
|
|
completion_tree_cmd_add(commands_broker, help_arg_list, "disconnect");
|
|
completion_tree_cmd_add(commands_broker, help_arg_list, "return");
|
|
completion_tree_cmd_add(commands_broker, help_arg_list, "exit");
|
|
}
|
|
|
|
|
|
static void print_help(char **saveptr)
|
|
{
|
|
char *command = strtok_r(NULL, " ", saveptr);
|
|
if(command){
|
|
if(!strcasecmp(command, "listPlugins")){
|
|
ctrl_shell_print_help_command("listPlugins");
|
|
ctrl_shell_printf("\nLists currently loaded plugins.\n");
|
|
}else if(!strcasecmp(command, "listListeners")){
|
|
ctrl_shell_print_help_command("listListeners");
|
|
ctrl_shell_printf("\nLists current listeners.\n");
|
|
}else{
|
|
ctrl_shell_print_help_final(command, "broker");
|
|
}
|
|
}else{
|
|
ctrl_shell_printf("This is the mosquitto_ctrl interactive shell, for controlling aspects of a mosquitto broker.\n");
|
|
ctrl_shell_printf("You are in broker mode, for controlling some core broker functionality.\n");
|
|
ctrl_shell_printf("Use '%sreturn%s' to leave this mode.\n", ANSI_INPUT, ANSI_RESET);
|
|
|
|
ctrl_shell_printf("Find help on a command using '%shelp <command>%s'\n", ANSI_INPUT, ANSI_RESET);
|
|
ctrl_shell_printf("Press tab multiple times to find currently available commands.\n\n");
|
|
}
|
|
}
|
|
|
|
|
|
static void line_callback(char *line)
|
|
{
|
|
if(!line){
|
|
ctrl_shell_callback_final(NULL);
|
|
return;
|
|
}
|
|
ctrl_shell_rtrim(line);
|
|
if(strlen(line) > 0){
|
|
add_history(line);
|
|
}else{
|
|
free(line);
|
|
return;
|
|
}
|
|
|
|
char *saveptr = NULL;
|
|
char *command = strtok_r(line, " ", &saveptr);
|
|
|
|
if(!command){
|
|
free(line);
|
|
return;
|
|
}
|
|
|
|
if(!strcasecmp(command, "listPlugins")){
|
|
ctrl_shell_command_generic_arg0("listPlugins");
|
|
}else if(!strcasecmp(command, "listListeners")){
|
|
ctrl_shell_command_generic_arg0("listListeners");
|
|
}else if(!strcasecmp(command, "help")){
|
|
print_help(&saveptr);
|
|
}else{
|
|
if(!ctrl_shell_callback_final(line)){
|
|
ctrl_shell_printf("Unknown command '%s'\n", command);
|
|
}
|
|
}
|
|
|
|
free(line);
|
|
}
|
|
|
|
|
|
static void print_plugins(cJSON *j_data)
|
|
{
|
|
cJSON *j_plugins, *j_plugin;
|
|
|
|
j_plugins = cJSON_GetObjectItem(j_data, "plugins");
|
|
|
|
cJSON_ArrayForEach(j_plugin, j_plugins){
|
|
const char *name;
|
|
if(json_get_string(j_plugin, "name", &name, false) != MOSQ_ERR_SUCCESS){
|
|
ctrl_shell_printf("Invalid response from broker.\n");
|
|
return;
|
|
}
|
|
|
|
ctrl_shell_print_label(0, "Plugin:");
|
|
ctrl_shell_print_value(1, "%s\n", name);
|
|
|
|
cJSON *j_endpoints, *j_endpoint;
|
|
j_endpoints = cJSON_GetObjectItem(j_plugin, "control-endpoints");
|
|
if(j_endpoints){
|
|
ctrl_shell_print_label(0, "Control endpoints:");
|
|
cJSON_ArrayForEach(j_endpoint, j_endpoints){
|
|
ctrl_shell_print_value(1, "%s\n", j_endpoint->valuestring);
|
|
}
|
|
}
|
|
ctrl_shell_print_value(0, "\n");
|
|
}
|
|
}
|
|
|
|
|
|
static void print_listeners(cJSON *j_data)
|
|
{
|
|
cJSON *j_listeners, *j_listener;
|
|
|
|
j_listeners = cJSON_GetObjectItem(j_data, "listeners");
|
|
|
|
cJSON_ArrayForEach(j_listener, j_listeners){
|
|
int port;
|
|
const char *protocol;
|
|
bool tls;
|
|
|
|
if(json_get_int(j_listener, "port", &port, false, -1) != MOSQ_ERR_SUCCESS
|
|
|| json_get_string(j_listener, "protocol", &protocol, false) != MOSQ_ERR_SUCCESS
|
|
|| json_get_bool(j_listener, "tls", &tls, false, false) != MOSQ_ERR_SUCCESS){
|
|
|
|
ctrl_shell_printf("Invalid response from broker.\n");
|
|
return;
|
|
}
|
|
|
|
ctrl_shell_print_label(0, "Listener:");
|
|
ctrl_shell_print_label(1, "Port:");
|
|
ctrl_shell_print_value(2, "%d\n", port);
|
|
ctrl_shell_print_label(1, "Protocol:");
|
|
ctrl_shell_print_value(2, "%s\n", protocol);
|
|
ctrl_shell_print_label(1, "TLS:");
|
|
ctrl_shell_print_value(2, "%s\n\n", tls?"true":"false");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void handle_response(const char *command, cJSON *j_data, const char *payload)
|
|
{
|
|
if(!strcmp(command, "listPlugins")){
|
|
print_plugins(j_data);
|
|
}else if(!strcmp(command, "listListeners")){
|
|
print_listeners(j_data);
|
|
}else{
|
|
ctrl_shell_printf("%s %s\n", command, payload);
|
|
}
|
|
}
|
|
|
|
|
|
static void on_subscribe(void)
|
|
{
|
|
}
|
|
|
|
|
|
static void ctrl_shell__broker_cleanup(void)
|
|
{
|
|
completion_tree_free(commands_broker);
|
|
commands_broker = NULL;
|
|
}
|
|
|
|
|
|
void ctrl_shell__broker_init(struct ctrl_shell__module *mod)
|
|
{
|
|
command_tree_create();
|
|
|
|
mod->completion_commands = commands_broker;
|
|
mod->request_topic = "$CONTROL/broker/v1";
|
|
mod->response_topic = "$CONTROL/broker/v1/response";
|
|
mod->line_callback = line_callback;
|
|
mod->response_callback = handle_response;
|
|
mod->on_subscribe = on_subscribe;
|
|
mod->cleanup = ctrl_shell__broker_cleanup;
|
|
}
|
|
#endif
|