From 318dead6bf912422aa9724a6be989b86e66fc0d3 Mon Sep 17 00:00:00 2001 From: Roger Light Date: Thu, 28 May 2020 23:56:09 +0100 Subject: [PATCH] Function to allow plugins to publish messages. --- ChangeLog.txt | 2 ++ src/linker.syms | 5 +++-- src/loop.c | 15 +++++++++++++++ src/mosquitto_broker.h | 20 +++++++++++++++++++ src/mosquitto_broker_internal.h | 13 +++++++++++++ src/plugin.c | 34 +++++++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 2 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 36698e5b..57d9005a 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -12,6 +12,8 @@ Broker: to a v3.x only broker. - DLT logging is now configurable at runtime with `log_dest dlt`. Closes #1735. +- Add `mosquitto_plugin_publish()` function, which can be used by plugins to + publish messages. Client library: - Client no longer generates random client ids for v3.1.1 clients, these are diff --git a/src/linker.syms b/src/linker.syms index 31420d34..fdea2a51 100644 --- a/src/linker.syms +++ b/src/linker.syms @@ -1,12 +1,13 @@ { - mosquitto_log_printf; mosquitto_client_address; + mosquitto_client_certificate; mosquitto_client_clean_session; mosquitto_client_id; mosquitto_client_keepalive; - mosquitto_client_certificate; mosquitto_client_protocol; mosquitto_client_sub_count; mosquitto_client_username; + mosquitto_log_printf; + mosquitto_plugin_publish; mosquitto_set_username; }; diff --git a/src/loop.c b/src/loop.c index 29a4894c..c8c3ebd4 100644 --- a/src/loop.c +++ b/src/loop.c @@ -38,6 +38,7 @@ Contributors: # include #endif #include +#include #ifdef WITH_WEBSOCKETS # include @@ -98,6 +99,19 @@ void lws__sul_callback(struct lws_sorted_usec_list *l) static struct lws_sorted_usec_list sul; #endif + +void queue_plugin_msgs(struct mosquitto_db *db) +{ + struct mosquitto_message_v5 *msg, *tmp; + + DL_FOREACH_SAFE(db->plugin_msgs, msg, tmp){ + DL_DELETE(db->plugin_msgs, msg); + db__messages_easy_queue(db, NULL, msg->topic, msg->qos, msg->payloadlen, msg->payload, msg->retain, 0, &msg->properties); + mosquitto__free(msg); + } +} + + int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int listensock_count) { #ifdef WITH_SYS_TREE @@ -130,6 +144,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li #endif while(run){ + queue_plugin_msgs(db); context__free_disused(db); #ifdef WITH_SYS_TREE if(db->config->sys_interval > 0){ diff --git a/src/mosquitto_broker.h b/src/mosquitto_broker.h index c7512470..1c9ade7b 100644 --- a/src/mosquitto_broker.h +++ b/src/mosquitto_broker.h @@ -24,6 +24,7 @@ extern "C" { #include struct mosquitto; +typedef struct mqtt5__property mosquitto_property; enum mosquitto_protocol { mp_mqtt, @@ -165,6 +166,25 @@ const char *mosquitto_client_username(const struct mosquitto *client); */ int mosquitto_set_username(struct mosquitto *client, const char *username); + +/* Function: mosquitto_plugin_publish + * + * Publish a message from within a plugin. + * + * This function allows a plugin to publish a message. Messages published in + * this way are treated as coming from the broker and so will not be passed to + * `mosquitto_auth_acl_check(, MOSQ_ACL_WRITE, , )` for checking. Read access + * will be enforced as normal for individual clients when they are due to + * receive the message. + */ +int mosquitto_plugin_publish( + const char *topic, + int payloadlen, + const void *payload, + int qos, + bool retain, + mosquitto_property *properties); + #ifdef __cplusplus } #endif diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index e87573b1..3cfd86d0 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -440,6 +440,18 @@ struct mosquitto__acl_user{ struct mosquitto__acl *acl; }; + +struct mosquitto_message_v5{ + struct mosquitto_message_v5 *next, *prev; + char *topic; + void *payload; + mosquitto_property *properties; + int payloadlen; + int qos; + bool retain; +}; + + struct mosquitto_db{ dbid_t last_db_id; struct mosquitto__subhier *subs; @@ -474,6 +486,7 @@ struct mosquitto_db{ #ifdef WITH_EPOLL int epollfd; #endif + struct mosquitto_message_v5 *plugin_msgs; }; enum mosquitto__bridge_direction{ diff --git a/src/plugin.c b/src/plugin.c index f1b01ed9..2aba5721 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -20,6 +20,7 @@ Contributors: #include "mosquitto_internal.h" #include "mosquitto_broker.h" #include "memory_mosq.h" +#include "utlist.h" #ifdef WITH_TLS # include @@ -94,6 +95,39 @@ const char *mosquitto_client_username(const struct mosquitto *context) } } + +int mosquitto_plugin_publish( + const char *topic, + int payloadlen, + const void *payload, + int qos, + bool retain, + mosquitto_property *properties) +{ + struct mosquitto_message_v5 *msg; + struct mosquitto_db *db; + + msg = mosquitto__malloc(sizeof(struct mosquitto_message_v5)); + if(msg == NULL) return MOSQ_ERR_NOMEM; + + msg->next = NULL; + msg->prev = NULL; + msg->topic = mosquitto__strdup(topic); + msg->payloadlen = payloadlen; + msg->payload = mosquitto__calloc(1, payloadlen+1); + memcpy(msg->payload, payload, payloadlen); + msg->qos = qos; + msg->retain = retain; + msg->properties = properties; + + db = mosquitto__get_db(); + + DL_APPEND(db->plugin_msgs, msg); + + return MOSQ_ERR_SUCCESS; +} + + int mosquitto_set_username(struct mosquitto *client, const char *username) { char *u_dup;