diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 6c3b3542..c50372d6 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(message-timestamp) +add_subdirectory(payload-modification) diff --git a/plugins/Makefile b/plugins/Makefile index c2ca7875..c9ca7256 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -1,5 +1,6 @@ DIRS= \ - message-timestamp + message-timestamp \ + payload-modification .PHONY : all binary check clean reallyclean test install uninstall diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 00000000..ec1df0cb --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,15 @@ +# Plugins + +This directory contains plugins for use with Mosquitto. + +## Message timestamp +This is an **example** plugin to demonstrate how it is possible to attach MQTT v5 properties to messages after they have been received, and before they are sent on to subscribers. + +This plugin attaches a user-property property to each message which contains the ISO-8601 timestamp of the time the message was received by the broker. This means it is possible for MQTT v5 clients to see how old a retained message is, for example. + +## Payload modification +This is an **example** plugin to demonstrate how it is possible to modify the payload of messages after they have been received, and before they are sent on to subscribers. + +If you are considering using this feature, you should be very certain you have verified the payload is the correct format before modifying it. + +This plugin adds the text string "hello " to the beginning of each payload, so with anything other than simple plain text messages it will corrupt the payload contents. \ No newline at end of file diff --git a/plugins/payload-modification/CMakeLists.txt b/plugins/payload-modification/CMakeLists.txt new file mode 100644 index 00000000..3f07447c --- /dev/null +++ b/plugins/payload-modification/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/include + ${STDBOOL_H_PATH} ${STDINT_H_PATH}) + +add_library(mosquitto_payload_modification SHARED mosquitto_payload_modification.c) +set_target_properties(mosquitto_payload_modification PROPERTIES + POSITION_INDEPENDENT_CODE 1 +) +set_target_properties(mosquitto_payload_modification PROPERTIES PREFIX "") + +install(TARGETS mosquitto_payload_modification RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/plugins/payload-modification/Makefile b/plugins/payload-modification/Makefile new file mode 100644 index 00000000..02f01348 --- /dev/null +++ b/plugins/payload-modification/Makefile @@ -0,0 +1,26 @@ +include ../../config.mk + +.PHONY : all binary check clean reallyclean test install uninstall + +PLUGIN_NAME=mosquitto_payload_modification + +all : binary + +binary : ${PLUGIN_NAME}.so + +${PLUGIN_NAME}.so : ${PLUGIN_NAME}.c + $(CROSS_COMPILE)$(CC) $(PLUGIN_CPPFLAGS) $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) -fPIC -shared $< -o $@ + +reallyclean : clean +clean: + -rm -f *.o ${PLUGIN_NAME}.so *.gcda *.gcno + +check: test +test: + +install: ${PLUGIN_NAME}.so + $(INSTALL) -d "${DESTDIR}$(prefix)/lib" + $(INSTALL) ${STRIP_OPTS} ${PLUGIN_NAME}.so "${DESTDIR}${prefix}/lib/${PLUGIN_NAME}.so" + +uninstall : + -rm -f "${DESTDIR}${prefix}/lib/${PLUGIN_NAME}.so" diff --git a/plugins/payload-modification/mosquitto_payload_modification.c b/plugins/payload-modification/mosquitto_payload_modification.c new file mode 100644 index 00000000..e323439d --- /dev/null +++ b/plugins/payload-modification/mosquitto_payload_modification.c @@ -0,0 +1,92 @@ +/* +Copyright (c) 2020 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + http://www.eclipse.org/legal/epl-v10.html +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +/* + * This is an *example* plugin which demonstrates how to modify the payload of + * a message after it is received by the broker and before it is sent on to + * other clients. + * + * You should be very sure of what you are doing before making use of this feature. + * + * Compile with: + * gcc -I -fPIC -shared mosquitto_payload_modification.c -o mosquitto_payload_modification.so + * + * Use in config with: + * + * plugin /path/to/mosquitto_payload_modification.so + * + * Note that this only works on Mosquitto 2.0 or later. + */ + + +#include +#include + +#include "mosquitto_broker.h" +#include "mosquitto_plugin.h" +#include "mosquitto.h" +#include "mqtt_protocol.h" + +static mosquitto_plugin_id_t *mosq_pid = NULL; + +static int callback_message(int event, void *event_data, void *userdata) +{ + struct mosquitto_evt_message *ed = event_data; + char *new_payload; + int new_payloadlen; + + /* This simply adds "hello " to the front of every payload. You can of + * course do much more complicated message processing if needed. */ + + /* Calculate the length of our new payload */ + new_payloadlen = ed->payloadlen + strlen("hello ")+1; + + /* Allocate some memory - use + * mosquitto_calloc/mosquitto_malloc/mosquitto_strdup when allocating, to + * allow the broker to track memory usage */ + new_payload = mosquitto_calloc(1, new_payloadlen); + if(new_payload == NULL){ + return MOSQ_ERR_NOMEM; + } + + /* Print "hello " to the payload */ + snprintf(new_payload, new_payloadlen, "hello "); + memcpy(new_payload+strlen("hello "), ed->payload, ed->payloadlen); + + /* Assign the new payload and payloadlen to the event data structure. You + * must *not* free the original payload, it will be handled by the + * broker. */ + ed->payload = new_payload; + ed->payloadlen = new_payloadlen; + + return MOSQ_ERR_SUCCESS; +} + +int mosquitto_plugin_version(void) +{ + return 5; +} + +int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, struct mosquitto_opt *opts, int opt_count) +{ + mosq_pid = identifier; + return mosquitto_callback_register(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL, NULL); +} + +int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count) +{ + return mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_MESSAGE, callback_message, NULL); +}