listListeners command.

pull/2345/head
Roger A. Light 4 years ago
parent 839ae93ce8
commit 82658805c7

@ -31,6 +31,7 @@ void broker__print_usage(void)
printf("=======================\n");
printf("Get plugin information: getPluginInfo\n");
printf("List listeners : listListeners\n");
}
/* ################################################################
@ -39,6 +40,53 @@ void broker__print_usage(void)
* #
* ################################################################ */
static void print_listeners(cJSON *j_response)
{
cJSON *j_data, *j_listeners, *j_listener, *jtmp;
int i=1;
j_data = cJSON_GetObjectItem(j_response, "data");
if(j_data == NULL || !cJSON_IsObject(j_data)){
fprintf(stderr, "Error: Invalid response from server.\n");
return;
}
j_listeners = cJSON_GetObjectItem(j_data, "listeners");
if(j_listeners == NULL || !cJSON_IsArray(j_listeners)){
fprintf(stderr, "Error: Invalid response from server.\n");
return;
}
cJSON_ArrayForEach(j_listener, j_listeners){
printf("Listener %d:\n", i);
jtmp = cJSON_GetObjectItem(j_listener, "port");
if(jtmp && cJSON_IsNumber(jtmp)){
printf(" Port: %d\n", jtmp->valueint);
}
jtmp = cJSON_GetObjectItem(j_listener, "protocol");
if(jtmp && cJSON_IsString(jtmp)){
printf(" Protocol: %s\n", jtmp->valuestring);
}
jtmp = cJSON_GetObjectItem(j_listener, "socket-path");
if(jtmp && cJSON_IsString(jtmp)){
printf(" Socket path: %s\n", jtmp->valuestring);
}
jtmp = cJSON_GetObjectItem(j_listener, "bind-address");
if(jtmp && cJSON_IsString(jtmp)){
printf(" Bind address: %s\n", jtmp->valuestring);
}
jtmp = cJSON_GetObjectItem(j_listener, "tls");
printf(" TLS: %s\n", jtmp && cJSON_IsBool(jtmp) && cJSON_IsTrue(jtmp)?"true":"false");
printf("\n");
}
}
static void print_plugin_info(cJSON *j_response)
{
cJSON *j_data, *j_plugins, *j_plugin, *jtmp, *j_eps;
@ -131,6 +179,8 @@ static void broker__payload_callback(struct mosq_ctrl *ctrl, long payloadlen, co
}else{
if(!strcasecmp(j_command->valuestring, "getPluginInfo")){
print_plugin_info(j_response);
}else if(!strcasecmp(j_command->valuestring, "listListeners")){
print_listeners(j_response);
}else{
/* fprintf(stderr, "%s: Success\n", j_command->valuestring); */
}
@ -152,6 +202,20 @@ static int broker__get_plugin_info(int argc, char *argv[], cJSON *j_command)
return MOSQ_ERR_SUCCESS;
}
static int broker__list_listeners(int argc, char *argv[], cJSON *j_command)
{
UNUSED(argc);
UNUSED(argv);
if(cJSON_AddStringToObject(j_command, "command", "listListeners") == NULL
){
return MOSQ_ERR_NOMEM;
}
return MOSQ_ERR_SUCCESS;
}
/* ################################################################
* #
* # Main
@ -195,6 +259,8 @@ int broker__main(int argc, char *argv[], struct mosq_ctrl *ctrl)
if(!strcasecmp(argv[0], "getPluginInfo")){
rc = broker__get_plugin_info(argc-1, &argv[1], j_command);
}else if(!strcasecmp(argv[0], "listListeners")){
rc = broker__list_listeners(argc-1, &argv[1], j_command);
}else{
fprintf(stderr, "Command '%s' not recognised.\n", argv[0]);

@ -112,7 +112,7 @@ static int add_plugin_info(cJSON *j_plugins, mosquitto_plugin_id_t *pid)
}
cJSON_AddItemToArray(j_eps, j_ep);
}
cJSON_AddItemToArray(j_plugins, j_plugin);
return MOSQ_ERR_SUCCESS;
}
@ -173,6 +173,101 @@ internal_error:
}
static int add_listener(cJSON *j_listeners, struct mosquitto__listener *listener)
{
cJSON *j_listener;
const char *protocol = NULL;
j_listener = cJSON_CreateObject();
if(j_listener == NULL){
return MOSQ_ERR_NOMEM;
}
cJSON_AddItemToArray(j_listeners, j_listener);
if(listener->protocol == mp_mqtt){
protocol = "mqtt";
}else if(listener->protocol == mp_websockets){
protocol = "mqtt+websockets";
}
if(cJSON_AddNumberToObject(j_listener, "port", listener->port) == NULL
|| (protocol && cJSON_AddStringToObject(j_listener, "protocol", protocol) == NULL)
|| (listener->host && cJSON_AddStringToObject(j_listener, "bind-address", listener->host) == NULL)
#ifdef WITH_UNIX_SOCKETS
|| (listener->unix_socket_path && cJSON_AddStringToObject(j_listener, "socket-path", listener->unix_socket_path) == NULL)
#endif
){
return MOSQ_ERR_NOMEM;
}
#ifdef WITH_TLS
if(cJSON_AddBoolToObject(j_listener, "tls", listener->ssl_ctx != NULL) == NULL
){
return MOSQ_ERR_NOMEM;
}
#endif
return MOSQ_ERR_SUCCESS;
}
static int broker__process_list_listeners(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data)
{
cJSON *tree, *jtmp, *j_data, *j_listeners;
const char *admin_clientid, *admin_username;
int i;
UNUSED(command);
tree = cJSON_CreateObject();
if(tree == NULL){
broker__command_reply(j_responses, context, "listListeners", "Internal error", correlation_data);
return MOSQ_ERR_NOMEM;
}
admin_clientid = mosquitto_client_id(context);
admin_username = mosquitto_client_username(context);
mosquitto_log_printf(MOSQ_LOG_INFO, "Broker: %s/%s | listListeners",
admin_clientid, admin_username);
if(cJSON_AddStringToObject(tree, "command", "listListeners") == NULL
|| ((j_data = cJSON_AddObjectToObject(tree, "data")) == NULL)
){
goto internal_error;
}
j_listeners = cJSON_AddArrayToObject(j_data, "listeners");
if(j_listeners == NULL){
goto internal_error;
}
for(i=0; i<db.config->listener_count; i++){
if(add_listener(j_listeners, &db.config->listeners[i])){
goto internal_error;
}
}
cJSON_AddItemToArray(j_responses, tree);
if(correlation_data){
jtmp = cJSON_AddStringToObject(tree, "correlationData", correlation_data);
if(jtmp == NULL){
goto internal_error;
}
}
return MOSQ_ERR_SUCCESS;
internal_error:
cJSON_Delete(tree);
broker__command_reply(j_responses, context, "listListeners", "Internal error", correlation_data);
return MOSQ_ERR_NOMEM;
}
static int broker_control_callback(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_control *ed = event_data;
@ -273,6 +368,8 @@ static int broker__handle_control(cJSON *j_responses, struct mosquitto *context,
if(!strcasecmp(command, "getPluginInfo")){
rc = broker__process_get_plugin_info(j_responses, context, aiter, correlation_data);
}else if(!strcasecmp(command, "listListeners")){
rc = broker__process_list_listeners(j_responses, context, aiter, correlation_data);
/* Unknown */
}else{

@ -0,0 +1,139 @@
#!/usr/bin/env python3
# Test $CONTROL/broker/v1 listListeners
from mosq_test_helper import *
import json
import shutil
def write_config(filename, ports):
with open(filename, 'w') as f:
f.write("enable_control_api true\n")
f.write("allow_anonymous true\n")
f.write("listener %d\n" % (ports[0]))
f.write("protocol mqtt\n")
f.write("listener %d\n" % (ports[1]))
f.write("protocol websockets\n")
f.write("listener %d\n" % (ports[2]))
f.write("protocol mqtt\n")
f.write("certfile ../ssl/server.crt\n")
f.write("keyfile ../ssl/server.key\n")
f.write("listener %d\n" % (ports[3]))
f.write("protocol websockets\n")
f.write("certfile ../ssl/server.crt\n")
f.write("keyfile ../ssl/server.key\n")
f.write("listener 0 17-list-listeners-mqtt.sock\n")
f.write("protocol mqtt\n")
f.write("listener 0 17-list-listeners-websockets.sock\n")
f.write("protocol websockets\n")
def command_check(sock, command_payload, expected_response):
command_packet = mosq_test.gen_publish(topic="$CONTROL/broker/v1", qos=0, payload=json.dumps(command_payload))
sock.send(command_packet)
response = json.loads(mosq_test.read_publish(sock))
if response != expected_response:
print(expected_response)
print(response)
raise ValueError(response)
def invalid_command_check(sock, command_payload, cmd_name, error_msg):
command_packet = mosq_test.gen_publish(topic="$CONTROL/broker/v1", qos=0, payload=command_payload)
sock.send(command_packet)
response = json.loads(mosq_test.read_publish(sock))
expected_response = {'responses': [{'command': cmd_name, 'error': error_msg}]}
if response != expected_response:
print(expected_response)
print(response)
raise ValueError(response)
ports = mosq_test.get_port(4)
conf_file = os.path.basename(__file__).replace('.py', '.conf')
write_config(conf_file, ports)
cmd_success = {"commands":[{"command": "listListeners", "correlationData": "m3CtYVnySLCOwnHzITSeowvgla0InV4G"}]}
response_success = {'responses': [{'command': 'listListeners', "correlationData": "m3CtYVnySLCOwnHzITSeowvgla0InV4G", 'data':{
'listeners':[
{
'port': ports[0],
'protocol': 'mqtt',
'tls': False
},{
'port': ports[1],
'protocol': 'mqtt+websockets',
'tls': False
},{
'port': ports[2],
'protocol': 'mqtt',
'tls': True
},{
'port': ports[3],
'protocol': 'mqtt+websockets',
'tls': True
},{
'port': 0,
'protocol': 'mqtt',
'socket-path': '17-list-listeners-mqtt.sock',
'tls': False
},{
'port': 0,
'protocol': 'mqtt+websockets',
'socket-path': '17-list-listeners-websockets.sock',
'tls': False
}
]}}]}
rc = 1
connect_packet = mosq_test.gen_connect("17-list-listeners")
connack_packet = mosq_test.gen_connack(rc=0)
mid = 2
subscribe_packet = mosq_test.gen_subscribe(mid, "$CONTROL/broker/#", 0)
suback_packet = mosq_test.gen_suback(mid, 0)
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=ports[0])
try:
sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=ports[0])
mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
invalid_command_check(sock, "not valid json", "Unknown command", "Payload not valid JSON")
invalid_command_check(sock, "{}", "Unknown command", "Invalid/missing commands")
cmd = {"commands":["command"]}
invalid_command_check(sock, json.dumps(cmd), "Unknown command", "Command not an object")
cmd = {"commands":[{}]}
invalid_command_check(sock, json.dumps(cmd), "Unknown command", "Missing command")
cmd = {"commands":[{"command": "unknown command"}]}
invalid_command_check(sock, json.dumps(cmd), "unknown command", "Unknown command")
cmd = {"commands":[{"command": "listListeners", "correlationData": True}]}
invalid_command_check(sock, json.dumps(cmd), "listListeners", "Invalid correlationData data type.")
command_check(sock, cmd_success, response_success)
mosq_test.do_ping(sock)
rc = 0
sock.close()
except mosq_test.TestError:
pass
finally:
os.remove(conf_file)
for f in ["17-list-listeners-mqtt.sock", "17-list-listeners-websockets.sock"]:
try:
os.remove(f)
except FileNotFoundError:
pass
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde.decode('utf-8'))
exit(rc)

@ -17,7 +17,7 @@ test-compile :
ptest : test-compile msg_sequence_test
./test.py
test : test-compile msg_sequence_test 01 02 03 04 05 06 07 08 09 10 11 12 13 14 16
test : test-compile msg_sequence_test 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17
msg_sequence_test:
./msg_sequence_test.py
@ -285,3 +285,6 @@ endif
./16-cmd-args.py
./16-config-includedir.py
./16-config-parse-errors.py
17 :
./17-control-list-listeners.py

@ -245,6 +245,8 @@ tests = [
(1, './16-cmd-args.py'),
(1, './16-config-includedir.py'),
(1, './16-config-parse-errors.py'),
(4, './17-control-list-listeners.py'),
]
ptest.run_tests(tests)

Loading…
Cancel
Save