From 519318dd1a45e10b49fc33c5e72274508a9d3cfe Mon Sep 17 00:00:00 2001 From: flykhan Date: Wed, 25 Oct 2023 17:34:40 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=95=B4cgi-bin=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=EF=BC=8C=E5=BA=93=E6=96=87=E4=BB=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=BF=9B=E9=A1=B9=E7=9B=AE=E7=9B=B8=E5=AF=B9=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E9=81=BF=E5=85=8D=E7=8E=AF=E5=A2=83=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E4=B8=8D=E5=90=8C=E5=BC=95=E8=B5=B7=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5;=20=E5=A2=9E=E5=8A=A0mqtt=5Fsub=5Fctos?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E4=BB=8EMQTT=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E8=AE=A2=E9=98=85=E5=B9=B6=E6=8E=A5=E6=94=B6=E4=BC=A0?= =?UTF-8?q?=E6=84=9F=E5=99=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgi-bin/Makefile | 18 +- cgi-bin/includes/mosquitto.h | 1772 +++++++++++++++++ cgi-bin/includes/mosquitto_broker.h | 144 ++ cgi-bin/includes/mosquitto_plugin.h | 264 +++ cgi-bin/includes/mosquittopp.h | 139 ++ cgi-bin/{ => includes}/sqlite3.h | 0 cgi-bin/mqtt_libs/libmosquitto.so | 1 + cgi-bin/mqtt_libs/libmosquitto.so.1 | Bin 0 -> 93616 bytes cgi-bin/mqtt_libs/libmosquittopp.so | 1 + cgi-bin/mqtt_libs/libmosquittopp.so.1 | Bin 0 -> 32896 bytes cgi-bin/mqtt_libs/pkgconfig/libmosquitto.pc | 10 + cgi-bin/mqtt_libs/pkgconfig/libmosquittopp.pc | 10 + cgi-bin/mqtt_sub_ctos.c | 119 ++ cgi-bin/sqlite3.c | 1 + cgi-bin/sqlite_cgi_base.c | 3 +- cgi-bin/sqlite_cgi_insert_base.c | 3 +- 16 files changed, 2480 insertions(+), 5 deletions(-) create mode 100755 cgi-bin/includes/mosquitto.h create mode 100755 cgi-bin/includes/mosquitto_broker.h create mode 100755 cgi-bin/includes/mosquitto_plugin.h create mode 100755 cgi-bin/includes/mosquittopp.h rename cgi-bin/{ => includes}/sqlite3.h (100%) create mode 120000 cgi-bin/mqtt_libs/libmosquitto.so create mode 100755 cgi-bin/mqtt_libs/libmosquitto.so.1 create mode 120000 cgi-bin/mqtt_libs/libmosquittopp.so create mode 100755 cgi-bin/mqtt_libs/libmosquittopp.so.1 create mode 100644 cgi-bin/mqtt_libs/pkgconfig/libmosquitto.pc create mode 100644 cgi-bin/mqtt_libs/pkgconfig/libmosquittopp.pc create mode 100644 cgi-bin/mqtt_sub_ctos.c diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile index 0161651..1fae87b 100644 --- a/cgi-bin/Makefile +++ b/cgi-bin/Makefile @@ -1,7 +1,23 @@ +cc = gcc +# CFLAGS = -Wall -g +MQTT_CFLAGS = -lmosquitto -lpthread -ldl +MQTT_CFLAGS += -I./includes +MQTT_CFLAGS += -L./mqtt_libs + +SQLITE3_CFLAGS = -lpthread -ldl -lcjson +SQLITE3_CFLAGS += -I./includes + + all: sqlite_cgi_base: - gcc sqlite3.c sqlite_cgi_base.c -o sqlite_cgi_base.cgi -lpthread -ldl -lcjson + $(cc) sqlite3.c sqlite_cgi_base.c -o sqlite_cgi_base.cgi $(SQLITE3_CFLAGS) + +sqlite_cgi_insert_base: + $(cc) sqlite3.c sqlite_cgi_insert_base.c -o sqlite_cgi_insert_base.cgi $(SQLITE3_CFLAGS) + +mqtt_sub_ctos: + $(cc) mqtt_sub_ctos.c -o mqtt_sub_ctos.cgi $(MQTT_CFLAGS) clean: rm -rf *.cgi \ No newline at end of file diff --git a/cgi-bin/includes/mosquitto.h b/cgi-bin/includes/mosquitto.h new file mode 100755 index 0000000..b3600b2 --- /dev/null +++ b/cgi-bin/includes/mosquitto.h @@ -0,0 +1,1772 @@ +/* +Copyright (c) 2010-2018 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. +*/ + +#ifndef MOSQUITTO_H +#define MOSQUITTO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WIN32) && !defined(WITH_BROKER) && !defined(LIBMOSQUITTO_STATIC) +# ifdef libmosquitto_EXPORTS +# define libmosq_EXPORT __declspec(dllexport) +# else +# define libmosq_EXPORT __declspec(dllimport) +# endif +#else +# define libmosq_EXPORT +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# ifndef __cplusplus +# define bool char +# define true 1 +# define false 0 +# endif +#else +# ifndef __cplusplus +# include +# endif +#endif + +#include + +#define LIBMOSQUITTO_MAJOR 1 +#define LIBMOSQUITTO_MINOR 5 +#define LIBMOSQUITTO_REVISION 4 +/* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */ +#define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) + +/* Log types */ +#define MOSQ_LOG_NONE 0x00 +#define MOSQ_LOG_INFO 0x01 +#define MOSQ_LOG_NOTICE 0x02 +#define MOSQ_LOG_WARNING 0x04 +#define MOSQ_LOG_ERR 0x08 +#define MOSQ_LOG_DEBUG 0x10 +#define MOSQ_LOG_SUBSCRIBE 0x20 +#define MOSQ_LOG_UNSUBSCRIBE 0x40 +#define MOSQ_LOG_WEBSOCKETS 0x80 +#define MOSQ_LOG_ALL 0xFFFF + +/* Error values */ +enum mosq_err_t { + MOSQ_ERR_CONN_PENDING = -1, + MOSQ_ERR_SUCCESS = 0, + MOSQ_ERR_NOMEM = 1, + MOSQ_ERR_PROTOCOL = 2, + MOSQ_ERR_INVAL = 3, + MOSQ_ERR_NO_CONN = 4, + MOSQ_ERR_CONN_REFUSED = 5, + MOSQ_ERR_NOT_FOUND = 6, + MOSQ_ERR_CONN_LOST = 7, + MOSQ_ERR_TLS = 8, + MOSQ_ERR_PAYLOAD_SIZE = 9, + MOSQ_ERR_NOT_SUPPORTED = 10, + MOSQ_ERR_AUTH = 11, + MOSQ_ERR_ACL_DENIED = 12, + MOSQ_ERR_UNKNOWN = 13, + MOSQ_ERR_ERRNO = 14, + MOSQ_ERR_EAI = 15, + MOSQ_ERR_PROXY = 16, + MOSQ_ERR_PLUGIN_DEFER = 17, + MOSQ_ERR_MALFORMED_UTF8 = 18, + MOSQ_ERR_KEEPALIVE = 19, + MOSQ_ERR_LOOKUP = 20, +}; + +/* Error values */ +enum mosq_opt_t { + MOSQ_OPT_PROTOCOL_VERSION = 1, + MOSQ_OPT_SSL_CTX = 2, + MOSQ_OPT_SSL_CTX_WITH_DEFAULTS = 3, +}; + +/* MQTT specification restricts client ids to a maximum of 23 characters */ +#define MOSQ_MQTT_ID_MAX_LENGTH 23 + +#define MQTT_PROTOCOL_V31 3 +#define MQTT_PROTOCOL_V311 4 + +struct mosquitto_message{ + int mid; + char *topic; + void *payload; + int payloadlen; + int qos; + bool retain; +}; + +struct mosquitto; + +/* + * Topic: Threads + * libmosquitto provides thread safe operation, with the exception of + * which is not thread safe. + * + * If your application uses threads you must use to + * tell the library this is the case, otherwise it makes some optimisations + * for the single threaded case that may result in unexpected behaviour for + * the multi threaded case. + */ +/*************************************************** + * Important note + * + * The following functions that deal with network operations will return + * MOSQ_ERR_SUCCESS on success, but this does not mean that the operation has + * taken place. An attempt will be made to write the network data, but if the + * socket is not available for writing at that time then the packet will not be + * sent. To ensure the packet is sent, call mosquitto_loop() (which must also + * be called to process incoming network data). + * This is especially important when disconnecting a client that has a will. If + * the broker does not receive the DISCONNECT command, it will assume that the + * client has disconnected unexpectedly and send the will. + * + * mosquitto_connect() + * mosquitto_disconnect() + * mosquitto_subscribe() + * mosquitto_unsubscribe() + * mosquitto_publish() + ***************************************************/ + +/* + * Function: mosquitto_lib_version + * + * Can be used to obtain version information for the mosquitto library. + * This allows the application to compare the library version against the + * version it was compiled against by using the LIBMOSQUITTO_MAJOR, + * LIBMOSQUITTO_MINOR and LIBMOSQUITTO_REVISION defines. + * + * Parameters: + * major - an integer pointer. If not NULL, the major version of the + * library will be returned in this variable. + * minor - an integer pointer. If not NULL, the minor version of the + * library will be returned in this variable. + * revision - an integer pointer. If not NULL, the revision of the library will + * be returned in this variable. + * + * Returns: + * LIBMOSQUITTO_VERSION_NUMBER, which is a unique number based on the major, + * minor and revision values. + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_lib_version(int *major, int *minor, int *revision); + +/* + * Function: mosquitto_lib_init + * + * Must be called before any other mosquitto functions. + * + * This function is *not* thread safe. + * + * Returns: + * MOSQ_ERR_SUCCESS - always + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_lib_init(void); + +/* + * Function: mosquitto_lib_cleanup + * + * Call to free resources associated with the library. + * + * Returns: + * MOSQ_ERR_SUCCESS - always + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_lib_cleanup(void); + +/* + * Function: mosquitto_new + * + * Create a new mosquitto client instance. + * + * Parameters: + * id - String to use as the client id. If NULL, a random client id + * will be generated. If id is NULL, clean_session must be true. + * clean_session - set to true to instruct the broker to clean all messages + * and subscriptions on disconnect, false to instruct it to + * keep them. See the man page mqtt(7) for more details. + * Note that a client will never discard its own outgoing + * messages on disconnect. Calling or + * will cause the messages to be resent. + * Use to reset a client to its + * original state. + * Must be set to true if the id parameter is NULL. + * obj - A user pointer that will be passed as an argument to any + * callbacks that are specified. + * + * Returns: + * Pointer to a struct mosquitto on success. + * NULL on failure. Interrogate errno to determine the cause for the failure: + * - ENOMEM on out of memory. + * - EINVAL on invalid input parameters. + * + * See Also: + * , , + */ +libmosq_EXPORT struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *obj); + +/* + * Function: mosquitto_destroy + * + * Use to free memory associated with a mosquitto client instance. + * + * Parameters: + * mosq - a struct mosquitto pointer to free. + * + * See Also: + * , + */ +libmosq_EXPORT void mosquitto_destroy(struct mosquitto *mosq); + +/* + * Function: mosquitto_reinitialise + * + * This function allows an existing mosquitto client to be reused. Call on a + * mosquitto instance to close any open network connections, free memory + * and reinitialise the client with the new parameters. The end result is the + * same as the output of . + * + * Parameters: + * mosq - a valid mosquitto instance. + * id - string to use as the client id. If NULL, a random client id + * will be generated. If id is NULL, clean_session must be true. + * clean_session - set to true to instruct the broker to clean all messages + * and subscriptions on disconnect, false to instruct it to + * keep them. See the man page mqtt(7) for more details. + * Must be set to true if the id parameter is NULL. + * obj - A user pointer that will be passed as an argument to any + * callbacks that are specified. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *obj); + +/* + * Function: mosquitto_will_set + * + * Configure will information for a mosquitto instance. By default, clients do + * not have a will. This must be called before calling . + * + * Parameters: + * mosq - a valid mosquitto instance. + * topic - the topic on which to publish the will. + * payloadlen - the size of the payload (bytes). Valid values are between 0 and + * 268,435,455. + * payload - pointer to the data to send. If payloadlen > 0 this must be a + * valid memory location. + * qos - integer value 0, 1 or 2 indicating the Quality of Service to be + * used for the will. + * retain - set to true to make the will a retained message. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large. + * MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8. + */ +libmosq_EXPORT int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain); + +/* + * Function: mosquitto_will_clear + * + * Remove a previously configured will. This must be called before calling + * . + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + */ +libmosq_EXPORT int mosquitto_will_clear(struct mosquitto *mosq); + +/* + * Function: mosquitto_username_pw_set + * + * Configure username and password for a mosquitton instance. This is only + * supported by brokers that implement the MQTT spec v3.1. By default, no + * username or password will be sent. + * If username is NULL, the password argument is ignored. + * This must be called before calling mosquitto_connect(). + * + * This is must be called before calling . + * + * Parameters: + * mosq - a valid mosquitto instance. + * username - the username to send as a string, or NULL to disable + * authentication. + * password - the password to send as a string. Set to NULL when username is + * valid in order to send just a username. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + */ +libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password); + +/* + * Function: mosquitto_connect + * + * Connect to an MQTT broker. + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the hostname or ip address of the broker to connect to. + * port - the network port to connect to. Usually 1883. + * keepalive - the number of seconds after which the broker should send a PING + * message to the client if no other messages have been exchanged + * in that time. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , , , + */ +libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive); + +/* + * Function: mosquitto_connect_bind + * + * Connect to an MQTT broker. This extends the functionality of + * by adding the bind_address parameter. Use this function + * if you need to restrict network communication over a particular interface. + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the hostname or ip address of the broker to connect to. + * port - the network port to connect to. Usually 1883. + * keepalive - the number of seconds after which the broker should send a PING + * message to the client if no other messages have been exchanged + * in that time. + * bind_address - the hostname or ip address of the local network interface to + * bind to. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address); + +/* + * Function: mosquitto_connect_async + * + * Connect to an MQTT broker. This is a non-blocking call. If you use + * your client must use the threaded interface + * . If you need to use , you must use + * to connect the client. + * + * May be called before or after . + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the hostname or ip address of the broker to connect to. + * port - the network port to connect to. Usually 1883. + * keepalive - the number of seconds after which the broker should send a PING + * message to the client if no other messages have been exchanged + * in that time. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , , , + */ +libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive); + +/* + * Function: mosquitto_connect_bind_async + * + * Connect to an MQTT broker. This is a non-blocking call. If you use + * your client must use the threaded interface + * . If you need to use , you must use + * to connect the client. + * + * This extends the functionality of by adding the + * bind_address parameter. Use this function if you need to restrict network + * communication over a particular interface. + * + * May be called before or after . + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the hostname or ip address of the broker to connect to. + * port - the network port to connect to. Usually 1883. + * keepalive - the number of seconds after which the broker should send a PING + * message to the client if no other messages have been exchanged + * in that time. + * bind_address - the hostname or ip address of the local network interface to + * bind to. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address); + +/* + * Function: mosquitto_connect_srv + * + * Connect to an MQTT broker. This is a non-blocking call. If you use + * your client must use the threaded interface + * . If you need to use , you must use + * to connect the client. + * + * This extends the functionality of by adding the + * bind_address parameter. Use this function if you need to restrict network + * communication over a particular interface. + * + * May be called before or after . + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the hostname or ip address of the broker to connect to. + * keepalive - the number of seconds after which the broker should send a PING + * message to the client if no other messages have been exchanged + * in that time. + * bind_address - the hostname or ip address of the local network interface to + * bind to. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address); + +/* + * Function: mosquitto_reconnect + * + * Reconnect to a broker. + * + * This function provides an easy way of reconnecting to a broker after a + * connection has been lost. It uses the values that were provided in the + * call. It must not be called before + * . + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq); + +/* + * Function: mosquitto_reconnect_async + * + * Reconnect to a broker. Non blocking version of . + * + * This function provides an easy way of reconnecting to a broker after a + * connection has been lost. It uses the values that were provided in the + * or calls. It must not be + * called before . + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_reconnect_async(struct mosquitto *mosq); + +/* + * Function: mosquitto_disconnect + * + * Disconnect from the broker. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + */ +libmosq_EXPORT int mosquitto_disconnect(struct mosquitto *mosq); + +/* + * Function: mosquitto_publish + * + * Publish a message on a given topic. + * + * Parameters: + * mosq - a valid mosquitto instance. + * mid - pointer to an int. If not NULL, the function will set this + * to the message id of this particular message. This can be then + * used with the publish callback to determine when the message + * has been sent. + * Note that although the MQTT protocol doesn't use message ids + * for messages with QoS=0, libmosquitto assigns them message ids + * so they can be tracked with this parameter. + * topic - null terminated string of the topic to publish to. + * payloadlen - the size of the payload (bytes). Valid values are between 0 and + * 268,435,455. + * payload - pointer to the data to send. If payloadlen > 0 this must be a + * valid memory location. + * qos - integer value 0, 1 or 2 indicating the Quality of Service to be + * used for the message. + * retain - set to true to make the message retained. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large. + * MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8 + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain); + +/* + * Function: mosquitto_subscribe + * + * Subscribe to a topic. + * + * Parameters: + * mosq - a valid mosquitto instance. + * mid - a pointer to an int. If not NULL, the function will set this to + * the message id of this particular message. This can be then used + * with the subscribe callback to determine when the message has been + * sent. + * sub - the subscription pattern. + * qos - the requested Quality of Service for this subscription. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8 + */ +libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos); + +/* + * Function: mosquitto_unsubscribe + * + * Unsubscribe from a topic. + * + * Parameters: + * mosq - a valid mosquitto instance. + * mid - a pointer to an int. If not NULL, the function will set this to + * the message id of this particular message. This can be then used + * with the unsubscribe callback to determine when the message has been + * sent. + * sub - the unsubscription pattern. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8 + */ +libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub); + +/* + * Function: mosquitto_message_copy + * + * Copy the contents of a mosquitto message to another message. + * Useful for preserving a message received in the on_message() callback. + * + * Parameters: + * dst - a pointer to a valid mosquitto_message struct to copy to. + * src - a pointer to a valid mosquitto_message struct to copy from. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src); + +/* + * Function: mosquitto_message_free + * + * Completely free a mosquitto_message struct. + * + * Parameters: + * message - pointer to a mosquitto_message pointer to free. + * + * See Also: + * , + */ +libmosq_EXPORT void mosquitto_message_free(struct mosquitto_message **message); + +/* + * Function: mosquitto_message_free_contents + * + * Free a mosquitto_message struct contents, leaving the struct unaffected. + * + * Parameters: + * message - pointer to a mosquitto_message struct to free its contents. + * + * See Also: + * , + */ +libmosq_EXPORT void mosquitto_message_free_contents(struct mosquitto_message *message); + +/* + * Function: mosquitto_loop + * + * The main network loop for the client. You must call this frequently in order + * to keep communications between the client and broker working. If incoming + * data is present it will then be processed. Outgoing commands, from e.g. + * , are normally sent immediately that their function is + * called, but this is not always possible. will also attempt + * to send any remaining outgoing messages, which also includes commands that + * are part of the flow for messages with QoS>0. + * + * An alternative approach is to use to run the client + * loop in its own thread. + * + * This calls select() to monitor the client network socket. If you want to + * integrate mosquitto client operation with your own select() call, use + * , , and + * . + * + * Threads: + * + * Parameters: + * mosq - a valid mosquitto instance. + * timeout - Maximum number of milliseconds to wait for network activity + * in the select() call before timing out. Set to 0 for instant + * return. Set negative to use the default of 1000ms. + * max_packets - this parameter is currently unused and should be set to 1 for + * future compatibility. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets); + +/* + * Function: mosquitto_loop_forever + * + * This function call loop() for you in an infinite blocking loop. It is useful + * for the case where you only want to run the MQTT client loop in your + * program. + * + * It handles reconnecting in case server connection is lost. If you call + * mosquitto_disconnect() in a callback it will return. + * + * Parameters: + * mosq - a valid mosquitto instance. + * timeout - Maximum number of milliseconds to wait for network activity + * in the select() call before timing out. Set to 0 for instant + * return. Set negative to use the default of 1000ms. + * max_packets - this parameter is currently unused and should be set to 1 for + * future compatibility. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets); + +/* + * Function: mosquitto_loop_start + * + * This is part of the threaded client interface. Call this once to start a new + * thread to process network traffic. This provides an alternative to + * repeatedly calling yourself. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOT_SUPPORTED - if thread support is not available. + * + * See Also: + * , , , + */ +libmosq_EXPORT int mosquitto_loop_start(struct mosquitto *mosq); + +/* + * Function: mosquitto_loop_stop + * + * This is part of the threaded client interface. Call this once to stop the + * network thread previously created with . This call + * will block until the network thread finishes. For the network thread to end, + * you must have previously called or have set the force + * parameter to true. + * + * Parameters: + * mosq - a valid mosquitto instance. + * force - set to true to force thread cancellation. If false, + * must have already been called. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOT_SUPPORTED - if thread support is not available. + * + * See Also: + * , + */ +libmosq_EXPORT int mosquitto_loop_stop(struct mosquitto *mosq, bool force); + +/* + * Function: mosquitto_socket + * + * Return the socket handle for a mosquitto instance. Useful if you want to + * include a mosquitto client in your own select() calls. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * The socket for the mosquitto client or -1 on failure. + */ +libmosq_EXPORT int mosquitto_socket(struct mosquitto *mosq); + +/* + * Function: mosquitto_loop_read + * + * Carry out network read operations. + * This should only be used if you are not using mosquitto_loop() and are + * monitoring the client network socket for activity yourself. + * + * Parameters: + * mosq - a valid mosquitto instance. + * max_packets - this parameter is currently unused and should be set to 1 for + * future compatibility. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_loop_read(struct mosquitto *mosq, int max_packets); + +/* + * Function: mosquitto_loop_write + * + * Carry out network write operations. + * This should only be used if you are not using mosquitto_loop() and are + * monitoring the client network socket for activity yourself. + * + * Parameters: + * mosq - a valid mosquitto instance. + * max_packets - this parameter is currently unused and should be set to 1 for + * future compatibility. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * + * See Also: + * , , , + */ +libmosq_EXPORT int mosquitto_loop_write(struct mosquitto *mosq, int max_packets); + +/* + * Function: mosquitto_loop_misc + * + * Carry out miscellaneous operations required as part of the network loop. + * This should only be used if you are not using mosquitto_loop() and are + * monitoring the client network socket for activity yourself. + * + * This function deals with handling PINGs and checking whether messages need + * to be retried, so should be called fairly frequently. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_loop_misc(struct mosquitto *mosq); + +/* + * Function: mosquitto_want_write + * + * Returns true if there is data ready to be written on the socket. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * See Also: + * , , + */ +libmosq_EXPORT bool mosquitto_want_write(struct mosquitto *mosq); + +/* + * Function: mosquitto_threaded_set + * + * Used to tell the library that your application is using threads, but not + * using . The library operates slightly differently when + * not in threaded mode in order to simplify its operation. If you are managing + * your own threads and do not use this function you will experience crashes + * due to race conditions. + * + * When using , this is set automatically. + * + * Parameters: + * mosq - a valid mosquitto instance. + * threaded - true if your application is using threads, false otherwise. + */ +libmosq_EXPORT int mosquitto_threaded_set(struct mosquitto *mosq, bool threaded); + +/* + * Function: mosquitto_opts_set + * + * Used to set options for the client. + * + * Parameters: + * mosq - a valid mosquitto instance. + * option - the option to set. + * value - the option specific value. + * + * Options: + * MOSQ_OPT_PROTOCOL_VERSION + * Value must be an int, set to either MQTT_PROTOCOL_V31 or + * MQTT_PROTOCOL_V311. Must be set before the client connects. + * Defaults to MQTT_PROTOCOL_V31. + * + * MOSQ_OPT_SSL_CTX + * Pass an openssl SSL_CTX to be used when creating TLS connections + * rather than libmosquitto creating its own. This must be called + * before connecting to have any effect. If you use this option, the + * onus is on you to ensure that you are using secure settings. + * Setting to NULL means that libmosquitto will use its own SSL_CTX + * if TLS is to be used. + * This option is only available for openssl 1.1.0 and higher. + * + * MOSQ_OPT_SSL_CTX_WITH_DEFAULTS + * Value must be an int set to 1 or 0. If set to 1, then the user + * specified SSL_CTX passed in using MOSQ_OPT_SSL_CTX will have the + * default options applied to it. This means that you only need to + * change the values that are relevant to you. If you use this + * option then you must configure the TLS options as normal, i.e. + * you should use to configure the cafile/capath + * as a minimum. + * This option is only available for openssl 1.1.0 and higher. + */ +libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t option, void *value); + + +/* + * Function: mosquitto_tls_set + * + * Configure the client for certificate based SSL/TLS support. Must be called + * before . + * + * Cannot be used in conjunction with . + * + * Define the Certificate Authority certificates to be trusted (ie. the server + * certificate must be signed with one of these certificates) using cafile. + * + * If the server you are connecting to requires clients to provide a + * certificate, define certfile and keyfile with your client certificate and + * private key. If your private key is encrypted, provide a password callback + * function or you will have to enter the password at the command line. + * + * Parameters: + * mosq - a valid mosquitto instance. + * cafile - path to a file containing the PEM encoded trusted CA + * certificate files. Either cafile or capath must not be NULL. + * capath - path to a directory containing the PEM encoded trusted CA + * certificate files. See mosquitto.conf for more details on + * configuring this directory. Either cafile or capath must not + * be NULL. + * certfile - path to a file containing the PEM encoded certificate file + * for this client. If NULL, keyfile must also be NULL and no + * client certificate will be used. + * keyfile - path to a file containing the PEM encoded private key for + * this client. If NULL, certfile must also be NULL and no + * client certificate will be used. + * pw_callback - if keyfile is encrypted, set pw_callback to allow your client + * to pass the correct password for decryption. If set to NULL, + * the password must be entered on the command line. + * Your callback must write the password into "buf", which is + * "size" bytes long. The return value must be the length of the + * password. "userdata" will be set to the calling mosquitto + * instance. The mosquitto userdata member variable can be + * retrieved using . + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * See Also: + * , , + * , + */ +libmosq_EXPORT int mosquitto_tls_set(struct mosquitto *mosq, + const char *cafile, const char *capath, + const char *certfile, const char *keyfile, + int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)); + +/* + * Function: mosquitto_tls_insecure_set + * + * Configure verification of the server hostname in the server certificate. If + * value is set to true, it is impossible to guarantee that the host you are + * connecting to is not impersonating your server. This can be useful in + * initial server testing, but makes it possible for a malicious third party to + * impersonate your server through DNS spoofing, for example. + * Do not use this function in a real system. Setting value to true makes the + * connection encryption pointless. + * Must be called before . + * + * Parameters: + * mosq - a valid mosquitto instance. + * value - if set to false, the default, certificate hostname checking is + * performed. If set to true, no hostname checking is performed and + * the connection is insecure. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value); + +/* + * Function: mosquitto_tls_opts_set + * + * Set advanced SSL/TLS options. Must be called before . + * + * Parameters: + * mosq - a valid mosquitto instance. + * cert_reqs - an integer defining the verification requirements the client + * will impose on the server. This can be one of: + * * SSL_VERIFY_NONE (0): the server will not be verified in any way. + * * SSL_VERIFY_PEER (1): the server certificate will be verified + * and the connection aborted if the verification fails. + * The default and recommended value is SSL_VERIFY_PEER. Using + * SSL_VERIFY_NONE provides no security. + * tls_version - the version of the SSL/TLS protocol to use as a string. If NULL, + * the default value is used. The default value and the + * available values depend on the version of openssl that the + * library was compiled against. For openssl >= 1.0.1, the + * available options are tlsv1.2, tlsv1.1 and tlsv1, with tlv1.2 + * as the default. For openssl < 1.0.1, only tlsv1 is available. + * ciphers - a string describing the ciphers available for use. See the + * "openssl ciphers" tool for more information. If NULL, the + * default ciphers will be used. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers); + +/* + * Function: mosquitto_tls_psk_set + * + * Configure the client for pre-shared-key based TLS support. Must be called + * before . + * + * Cannot be used in conjunction with . + * + * Parameters: + * mosq - a valid mosquitto instance. + * psk - the pre-shared-key in hex format with no leading "0x". + * identity - the identity of this client. May be used as the username + * depending on the server settings. + * ciphers - a string describing the PSK ciphers available for use. See the + * "openssl ciphers" tool for more information. If NULL, the + * default ciphers will be used. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers); + +/* + * Function: mosquitto_connect_callback_set + * + * Set the connect callback. This is called when the broker sends a CONNACK + * message in response to a connection. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_connect - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int rc) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * rc - the return code of the connection response, one of: + * + * * 0 - success + * * 1 - connection refused (unacceptable protocol version) + * * 2 - connection refused (identifier rejected) + * * 3 - connection refused (broker unavailable) + * * 4-255 - reserved for future use + */ +libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int)); + +/* + * Function: mosquitto_connect_with_flags_callback_set + * + * Set the connect callback. This is called when the broker sends a CONNACK + * message in response to a connection. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_connect - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int rc) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * rc - the return code of the connection response, one of: + * flags - the connect flags. + * + * * 0 - success + * * 1 - connection refused (unacceptable protocol version) + * * 2 - connection refused (identifier rejected) + * * 3 - connection refused (broker unavailable) + * * 4-255 - reserved for future use + */ +libmosq_EXPORT void mosquitto_connect_with_flags_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int)); + +/* + * Function: mosquitto_disconnect_callback_set + * + * Set the disconnect callback. This is called when the broker has received the + * DISCONNECT command and has disconnected the client. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_disconnect - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * rc - integer value indicating the reason for the disconnect. A value of 0 + * means the client has called . Any other value + * indicates that the disconnect is unexpected. + */ +libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int)); + +/* + * Function: mosquitto_publish_callback_set + * + * Set the publish callback. This is called when a message initiated with + * has been sent to the broker successfully. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_publish - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int mid) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * mid - the message id of the sent message. + */ +libmosq_EXPORT void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int)); + +/* + * Function: mosquitto_message_callback_set + * + * Set the message callback. This is called when a message is received from the + * broker. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_message - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * message - the message data. This variable and associated memory will be + * freed by the library after the callback completes. The client + * should make copies of any of the data it requires. + * + * See Also: + * + */ +libmosq_EXPORT void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *)); + +/* + * Function: mosquitto_subscribe_callback_set + * + * Set the subscribe callback. This is called when the broker responds to a + * subscription request. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_subscribe - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * mid - the message id of the subscribe message. + * qos_count - the number of granted subscriptions (size of granted_qos). + * granted_qos - an array of integers indicating the granted QoS for each of + * the subscriptions. + */ +libmosq_EXPORT void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *)); + +/* + * Function: mosquitto_unsubscribe_callback_set + * + * Set the unsubscribe callback. This is called when the broker responds to a + * unsubscription request. + * + * Parameters: + * mosq - a valid mosquitto instance. + * on_unsubscribe - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int mid) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * mid - the message id of the unsubscribe message. + */ +libmosq_EXPORT void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int)); + +/* + * Function: mosquitto_log_callback_set + * + * Set the logging callback. This should be used if you want event logging + * information from the client library. + * + * mosq - a valid mosquitto instance. + * on_log - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, int level, const char *str) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * level - the log message level from the values: + * MOSQ_LOG_INFO + * MOSQ_LOG_NOTICE + * MOSQ_LOG_WARNING + * MOSQ_LOG_ERR + * MOSQ_LOG_DEBUG + * str - the message string. + */ +libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *)); + +/* + * Function: mosquitto_reconnect_delay_set + * + * Control the behaviour of the client when it has unexpectedly disconnected in + * or after . The default + * behaviour if this function is not used is to repeatedly attempt to reconnect + * with a delay of 1 second until the connection succeeds. + * + * Use reconnect_delay parameter to change the delay between successive + * reconnection attempts. You may also enable exponential backoff of the time + * between reconnections by setting reconnect_exponential_backoff to true and + * set an upper bound on the delay with reconnect_delay_max. + * + * Example 1: + * delay=2, delay_max=10, exponential_backoff=False + * Delays would be: 2, 4, 6, 8, 10, 10, ... + * + * Example 2: + * delay=3, delay_max=30, exponential_backoff=True + * Delays would be: 3, 6, 12, 24, 30, 30, ... + * + * Parameters: + * mosq - a valid mosquitto instance. + * reconnect_delay - the number of seconds to wait between + * reconnects. + * reconnect_delay_max - the maximum number of seconds to wait + * between reconnects. + * reconnect_exponential_backoff - use exponential backoff between + * reconnect attempts. Set to true to enable + * exponential backoff. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + */ +libmosq_EXPORT int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff); + +/* + * Function: mosquitto_max_inflight_messages_set + * + * Set the number of QoS 1 and 2 messages that can be "in flight" at one time. + * An in flight message is part way through its delivery flow. Attempts to send + * further messages with will result in the messages being + * queued until the number of in flight messages reduces. + * + * A higher number here results in greater message throughput, but if set + * higher than the maximum in flight messages on the broker may lead to + * delays in the messages being acknowledged. + * + * Set to 0 for no maximum. + * + * Parameters: + * mosq - a valid mosquitto instance. + * max_inflight_messages - the maximum number of inflight messages. Defaults + * to 20. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + */ +libmosq_EXPORT int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages); + +/* + * Function: mosquitto_message_retry_set + * + * This function now has no effect. + */ +libmosq_EXPORT void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry); + +/* + * Function: mosquitto_user_data_set + * + * When is called, the pointer given as the "obj" parameter + * will be passed to the callbacks as user data. The + * function allows this obj parameter to be updated at any time. This function + * will not modify the memory pointed to by the current user data pointer. If + * it is dynamically allocated memory you must free it yourself. + * + * Parameters: + * mosq - a valid mosquitto instance. + * obj - A user pointer that will be passed as an argument to any callbacks + * that are specified. + */ +libmosq_EXPORT void mosquitto_user_data_set(struct mosquitto *mosq, void *obj); + +/* ============================================================================= + * + * Section: SOCKS5 proxy functions + * + * ============================================================================= + */ + +/* + * Function: mosquitto_socks5_set + * + * Configure the client to use a SOCKS5 proxy when connecting. Must be called + * before connecting. "None" and "username/password" authentication is + * supported. + * + * Parameters: + * mosq - a valid mosquitto instance. + * host - the SOCKS5 proxy host to connect to. + * port - the SOCKS5 proxy port to use. + * username - if not NULL, use this username when authenticating with the proxy. + * password - if not NULL and username is not NULL, use this password when + * authenticating with the proxy. + */ +libmosq_EXPORT int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, const char *username, const char *password); + +/* ============================================================================= + * + * Section: Utility functions + * + * ============================================================================= + */ + +/* + * Function: mosquitto_strerror + * + * Call to obtain a const string description of a mosquitto error number. + * + * Parameters: + * mosq_errno - a mosquitto error number. + * + * Returns: + * A constant string describing the error. + */ +libmosq_EXPORT const char *mosquitto_strerror(int mosq_errno); + +/* + * Function: mosquitto_connack_string + * + * Call to obtain a const string description of an MQTT connection result. + * + * Parameters: + * connack_code - an MQTT connection result. + * + * Returns: + * A constant string describing the result. + */ +libmosq_EXPORT const char *mosquitto_connack_string(int connack_code); + +/* + * Function: mosquitto_sub_topic_tokenise + * + * Tokenise a topic or subscription string into an array of strings + * representing the topic hierarchy. + * + * For example: + * + * subtopic: "a/deep/topic/hierarchy" + * + * Would result in: + * + * topics[0] = "a" + * topics[1] = "deep" + * topics[2] = "topic" + * topics[3] = "hierarchy" + * + * and: + * + * subtopic: "/a/deep/topic/hierarchy/" + * + * Would result in: + * + * topics[0] = NULL + * topics[1] = "a" + * topics[2] = "deep" + * topics[3] = "topic" + * topics[4] = "hierarchy" + * + * Parameters: + * subtopic - the subscription/topic to tokenise + * topics - a pointer to store the array of strings + * count - an int pointer to store the number of items in the topics array. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8 + * + * Example: + * + * > char **topics; + * > int topic_count; + * > int i; + * > + * > mosquitto_sub_topic_tokenise("$SYS/broker/uptime", &topics, &topic_count); + * > + * > for(i=0; i printf("%d: %s\n", i, topics[i]); + * > } + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count); + +/* + * Function: mosquitto_sub_topic_tokens_free + * + * Free memory that was allocated in . + * + * Parameters: + * topics - pointer to string array. + * count - count of items in string array. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count); + +/* + * Function: mosquitto_topic_matches_sub + * Function: mosquitto_topic_matches_sub2 + * + * Check whether a topic matches a subscription. + * + * For example: + * + * foo/bar would match the subscription foo/# or +/bar + * non/matching would not match the subscription non/+/+ + * + * Parameters: + * sub - subscription string to check topic against. + * sublen - length in bytes of sub string + * topic - topic to check. + * topiclen - length in bytes of topic string + * result - bool pointer to hold result. Will be set to true if the topic + * matches the subscription. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + */ +libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result); +libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result); + +/* + * Function: mosquitto_pub_topic_check + * + * Check whether a topic to be used for publishing is valid. + * + * This searches for + or # in a topic and checks its length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. It + * may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check + * topiclen - length of the topic in bytes + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a #, or if it is too long. + * MOSQ_ERR_MALFORMED_UTF8 - if sub or topic is not valid UTF-8 + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_pub_topic_check(const char *topic); +libmosq_EXPORT int mosquitto_pub_topic_check2(const char *topic, size_t topiclen); + +/* + * Function: mosquitto_sub_topic_check + * + * Check whether a topic to be used for subscribing is valid. + * + * This searches for + or # in a topic and checks that they aren't in invalid + * positions, such as with foo/#/bar, foo/+bar or foo/bar#, and checks its + * length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. + * It may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check + * topiclen - the length in bytes of the topic + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a # that is in an + * invalid position, or if it is too long. + * MOSQ_ERR_MALFORMED_UTF8 - if topic is not valid UTF-8 + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic); +libmosq_EXPORT int mosquitto_sub_topic_check2(const char *topic, size_t topiclen); + + +struct libmosquitto_will { + char *topic; + void *payload; + int payloadlen; + int qos; + bool retain; +}; + +struct libmosquitto_auth { + char *username; + char *password; +}; + +struct libmosquitto_tls { + char *cafile; + char *capath; + char *certfile; + char *keyfile; + char *ciphers; + char *tls_version; + int (*pw_callback)(char *buf, int size, int rwflag, void *userdata); + int cert_reqs; +}; + +/* + * Function: mosquitto_subscribe_simple + * + * Helper function to make subscribing to a topic and retrieving some messages + * very straightforward. + * + * This connects to a broker, subscribes to a topic, waits for msg_count + * messages to be received, then returns after disconnecting cleanly. + * + * Parameters: + * messages - pointer to a "struct mosquitto_message *". The received + * messages will be returned here. On error, this will be set to + * NULL. + * msg_count - the number of messages to retrieve. + * want_retained - if set to true, stale retained messages will be treated as + * normal messages with regards to msg_count. If set to + * false, they will be ignored. + * topic - the subscription topic to use (wildcards are allowed). + * qos - the qos to use for the subscription. + * host - the broker to connect to. + * port - the network port the broker is listening on. + * client_id - the client id to use, or NULL if a random client id should be + * generated. + * keepalive - the MQTT keepalive value. + * clean_session - the MQTT clean session flag. + * username - the username string, or NULL for no username authentication. + * password - the password string, or NULL for an empty password. + * will - a libmosquitto_will struct containing will information, or NULL for + * no will. + * tls - a libmosquitto_tls struct containing TLS related parameters, or NULL + * for no use of TLS. + * + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * >0 - on error. + */ +libmosq_EXPORT int mosquitto_subscribe_simple( + struct mosquitto_message **messages, + int msg_count, + bool want_retained, + const char *topic, + int qos, + const char *host, + int port, + const char *client_id, + int keepalive, + bool clean_session, + const char *username, + const char *password, + const struct libmosquitto_will *will, + const struct libmosquitto_tls *tls); + + +/* + * Function: mosquitto_subscribe_callback + * + * Helper function to make subscribing to a topic and processing some messages + * very straightforward. + * + * This connects to a broker, subscribes to a topic, then passes received + * messages to a user provided callback. If the callback returns a 1, it then + * disconnects cleanly and returns. + * + * Parameters: + * callback - a callback function in the following form: + * int callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) + * Note that this is the same as the normal on_message callback, + * except that it returns an int. + * userdata - user provided pointer that will be passed to the callback. + * topic - the subscription topic to use (wildcards are allowed). + * qos - the qos to use for the subscription. + * host - the broker to connect to. + * port - the network port the broker is listening on. + * client_id - the client id to use, or NULL if a random client id should be + * generated. + * keepalive - the MQTT keepalive value. + * clean_session - the MQTT clean session flag. + * username - the username string, or NULL for no username authentication. + * password - the password string, or NULL for an empty password. + * will - a libmosquitto_will struct containing will information, or NULL for + * no will. + * tls - a libmosquitto_tls struct containing TLS related parameters, or NULL + * for no use of TLS. + * + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * >0 - on error. + */ +libmosq_EXPORT int mosquitto_subscribe_callback( + int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *), + void *userdata, + const char *topic, + int qos, + const char *host, + int port, + const char *client_id, + int keepalive, + bool clean_session, + const char *username, + const char *password, + const struct libmosquitto_will *will, + const struct libmosquitto_tls *tls); + + +/* + * Function: mosquitto_validate_utf8 + * + * Helper function to validate whether a UTF-8 string is valid, according to + * the UTF-8 spec and the MQTT additions. + * + * Parameters: + * str - a string to check + * len - the length of the string in bytes + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if str is NULL or len<0 or len>65536 + * MOSQ_ERR_MALFORMED_UTF8 - if str is not valid UTF-8 + */ +libmosq_EXPORT int mosquitto_validate_utf8(const char *str, int len); + + +/* Function: mosquitto_userdata + * + * Retrieve the "userdata" variable for a mosquitto client. + * + * Parameters: + * mosq - a valid mosquitto instance. + * + * Returns: + * A pointer to the userdata member variable. + */ +libmosq_EXPORT void *mosquitto_userdata(struct mosquitto *mosq); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cgi-bin/includes/mosquitto_broker.h b/cgi-bin/includes/mosquitto_broker.h new file mode 100755 index 0000000..f3aa184 --- /dev/null +++ b/cgi-bin/includes/mosquitto_broker.h @@ -0,0 +1,144 @@ +/* +Copyright (c) 2009-2018 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. +*/ + +#ifndef MOSQUITTO_BROKER_H +#define MOSQUITTO_BROKER_H + +#include + +struct mosquitto; + +enum mosquitto_protocol { + mp_mqtt, + mp_mqttsn, + mp_websockets +}; + +/* ========================================================================= + * + * Utility Functions + * + * Use these functions from within your plugin. + * + * There are also very useful functions in libmosquitto. + * + * ========================================================================= */ + + +/* + * Function: mosquitto_log_printf + * + * Write a log message using the broker configured logging. + * + * Parameters: + * level - Log message priority. Can currently be one of: + * + * MOSQ_LOG_INFO + * MOSQ_LOG_NOTICE + * MOSQ_LOG_WARNING + * MOSQ_LOG_ERR + * MOSQ_LOG_DEBUG + * MOSQ_LOG_SUBSCRIBE (not recommended for use by plugins) + * MOSQ_LOG_UNSUBSCRIBE (not recommended for use by plugins) + * + * These values are defined in mosquitto.h. + * + * fmt, ... - printf style format and arguments. + */ +void mosquitto_log_printf(int level, const char *fmt, ...); + + +/* ========================================================================= + * + * Client Functions + * + * Use these functions to access client information. + * + * ========================================================================= */ + +/* + * Function: mosquitto_client_address + * + * Retrieve the IP address of the client as a string. + */ +const char *mosquitto_client_address(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_clean_session + * + * Retrieve the clean session flag value for a client. + */ +bool mosquitto_client_clean_session(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_id + * + * Retrieve the client id associated with a client. + */ +const char *mosquitto_client_id(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_keepalive + * + * Retrieve the keepalive value for a client. + */ +int mosquitto_client_keepalive(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_certificate + * + * If TLS support is enabled, return the certificate provided by a client as an + * X509 pointer from openssl. If the client did not provide a certificate, then + * NULL will be returned. This function will only ever return a non-NULL value + * if the `require_certificate` option is set to true. + * + * If TLS is not supported, this function will always return NULL. + */ +void *mosquitto_client_certificate(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_protocol + * + * Retrieve the protocol with which the client has connected. Can be one of: + * + * mp_mqtt (MQTT over TCP) + * mp_mqttsn (MQTT-SN) + * mp_websockets (MQTT over Websockets) + */ +int mosquitto_client_protocol(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_sub_count + * + * Retrieve the number of subscriptions that have been made by a client. + */ +int mosquitto_client_sub_count(const struct mosquitto *client); + + +/* + * Function: mosquitto_client_username + * + * Retrieve the username associated with a client. + */ +const char *mosquitto_client_username(const struct mosquitto *client); + +#endif diff --git a/cgi-bin/includes/mosquitto_plugin.h b/cgi-bin/includes/mosquitto_plugin.h new file mode 100755 index 0000000..44ccb0b --- /dev/null +++ b/cgi-bin/includes/mosquitto_plugin.h @@ -0,0 +1,264 @@ +/* +Copyright (c) 2012-2018 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. +*/ + +#ifndef MOSQUITTO_PLUGIN_H +#define MOSQUITTO_PLUGIN_H + +#define MOSQ_AUTH_PLUGIN_VERSION 3 + +#define MOSQ_ACL_NONE 0x00 +#define MOSQ_ACL_READ 0x01 +#define MOSQ_ACL_WRITE 0x02 +#define MOSQ_ACL_SUBSCRIBE 0x04 + +#include + +struct mosquitto; + +struct mosquitto_opt { + char *key; + char *value; +}; + +struct mosquitto_auth_opt { + char *key; + char *value; +}; + +struct mosquitto_acl_msg { + const char *topic; + const void *payload; + long payloadlen; + int qos; + bool retain; +}; + +/* + * To create an authentication plugin you must include this file then implement + * the functions listed in the "Plugin Functions" section below. The resulting + * code should then be compiled as a shared library. Using gcc this can be + * achieved as follows: + * + * gcc -I -fPIC -shared plugin.c -o plugin.so + * + * On Mac OS X: + * + * gcc -I -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so + * + * Authentication plugins can implement one or both of authentication and + * access control. If your plugin does not wish to handle either of + * authentication or access control it should return MOSQ_ERR_PLUGIN_DEFER. In + * this case, the next plugin will handle it. If all plugins return + * MOSQ_ERR_PLUGIN_DEFER, the request will be denied. + * + * For each check, the following flow happens: + * + * * The default password file and/or acl file checks are made. If either one + * of these is not defined, then they are considered to be deferred. If either + * one accepts the check, no further checks are made. If an error occurs, the + * check is denied + * * The first plugin does the check, if it returns anything other than + * MOSQ_ERR_PLUGIN_DEFER, then the check returns immediately. If the plugin + * returns MOSQ_ERR_PLUGIN_DEFER then the next plugin runs its check. + * * If the final plugin returns MOSQ_ERR_PLUGIN_DEFER, then access will be + * denied. + */ + + +/* ========================================================================= + * + * Plugin Functions + * + * You must implement these functions in your plugin. + * + * ========================================================================= */ + +/* + * Function: mosquitto_auth_plugin_version + * + * The broker will call this function immediately after loading the plugin to + * check it is a supported plugin version. Your code must simply return + * MOSQ_AUTH_PLUGIN_VERSION. + */ +int mosquitto_auth_plugin_version(void); + + +/* + * Function: mosquitto_auth_plugin_init + * + * Called after the plugin has been loaded and + * has been called. This will only ever be called once and can be used to + * initialise the plugin. + * + * Parameters: + * + * user_data : The pointer set here will be passed to the other plugin + * functions. Use to hold connection information for example. + * opts : Pointer to an array of struct mosquitto_opt, which + * provides the plugin options defined in the configuration file. + * opt_count : The number of elements in the opts array. + * + * Return value: + * Return 0 on success + * Return >0 on failure. + */ +int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_opt *opts, int opt_count); + + +/* + * Function: mosquitto_auth_plugin_cleanup + * + * Called when the broker is shutting down. This will only ever be called once + * per plugin. + * Note that will be called directly before + * this function. + * + * Parameters: + * + * user_data : The pointer provided in . + * opts : Pointer to an array of struct mosquitto_opt, which + * provides the plugin options defined in the configuration file. + * opt_count : The number of elements in the opts array. + * + * Return value: + * Return 0 on success + * Return >0 on failure. + */ +int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count); + + +/* + * Function: mosquitto_auth_security_init + * + * This function is called in two scenarios: + * + * 1. When the broker starts up. + * 2. If the broker is requested to reload its configuration whilst running. In + * this case, will be called first, then + * this function will be called. In this situation, the reload parameter + * will be true. + * + * Parameters: + * + * user_data : The pointer provided in . + * opts : Pointer to an array of struct mosquitto_opt, which + * provides the plugin options defined in the configuration file. + * opt_count : The number of elements in the opts array. + * reload : If set to false, this is the first time the function has + * been called. If true, the broker has received a signal + * asking to reload its configuration. + * + * Return value: + * Return 0 on success + * Return >0 on failure. + */ +int mosquitto_auth_security_init(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload); + + +/* + * Function: mosquitto_auth_security_cleanup + * + * This function is called in two scenarios: + * + * 1. When the broker is shutting down. + * 2. If the broker is requested to reload its configuration whilst running. In + * this case, this function will be called, followed by + * . In this situation, the reload parameter + * will be true. + * + * Parameters: + * + * user_data : The pointer provided in . + * opts : Pointer to an array of struct mosquitto_opt, which + * provides the plugin options defined in the configuration file. + * opt_count : The number of elements in the opts array. + * reload : If set to false, this is the first time the function has + * been called. If true, the broker has received a signal + * asking to reload its configuration. + * + * Return value: + * Return 0 on success + * Return >0 on failure. + */ +int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload); + + +/* + * Function: mosquitto_auth_acl_check + * + * Called by the broker when topic access must be checked. access will be one + * of: + * MOSQ_ACL_SUBSCRIBE when a client is asking to subscribe to a topic string. + * This differs from MOSQ_ACL_READ in that it allows you to + * deny access to topic strings rather than by pattern. For + * example, you may use MOSQ_ACL_SUBSCRIBE to deny + * subscriptions to '#', but allow all topics in + * MOSQ_ACL_READ. This allows clients to subscribe to any + * topic they want, but not discover what topics are in use + * on the server. + * MOSQ_ACL_READ when a message is about to be sent to a client (i.e. whether + * it can read that topic or not). + * MOSQ_ACL_WRITE when a message has been received from a client (i.e. whether + * it can write to that topic or not). + * + * Return: + * MOSQ_ERR_SUCCESS if access was granted. + * MOSQ_ERR_ACL_DENIED if access was not granted. + * MOSQ_ERR_UNKNOWN for an application specific error. + * MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check. + */ +int mosquitto_auth_acl_check(void *user_data, int access, const struct mosquitto *client, const struct mosquitto_acl_msg *msg); + + +/* + * Function: mosquitto_auth_unpwd_check + * + * Called by the broker when a username/password must be checked. + * + * Return: + * MOSQ_ERR_SUCCESS if the user is authenticated. + * MOSQ_ERR_AUTH if authentication failed. + * MOSQ_ERR_UNKNOWN for an application specific error. + * MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check. + */ +int mosquitto_auth_unpwd_check(void *user_data, const struct mosquitto *client, const char *username, const char *password); + + +/* + * Function: mosquitto_psk_key_get + * + * Called by the broker when a client connects to a listener using TLS/PSK. + * This is used to retrieve the pre-shared-key associated with a client + * identity. + * + * Examine hint and identity to determine the required PSK (which must be a + * hexadecimal string with no leading "0x") and copy this string into key. + * + * Parameters: + * user_data : the pointer provided in . + * hint : the psk_hint for the listener the client is connecting to. + * identity : the identity string provided by the client + * key : a string where the hex PSK should be copied + * max_key_len : the size of key + * + * Return value: + * Return 0 on success. + * Return >0 on failure. + * Return MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check. + */ +int mosquitto_auth_psk_key_get(void *user_data, const struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len); + +#endif diff --git a/cgi-bin/includes/mosquittopp.h b/cgi-bin/includes/mosquittopp.h new file mode 100755 index 0000000..38a5835 --- /dev/null +++ b/cgi-bin/includes/mosquittopp.h @@ -0,0 +1,139 @@ +/* +Copyright (c) 2010-2018 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. +*/ + +#ifndef MOSQUITTOPP_H +#define MOSQUITTOPP_H + +#ifdef _WIN32 +# ifdef mosquittopp_EXPORTS +# define mosqpp_EXPORT __declspec(dllexport) +# else +# define mosqpp_EXPORT __declspec(dllimport) +# endif +#else +# define mosqpp_EXPORT +#endif + +#include +#include +#include + +namespace mosqpp { + +mosqpp_EXPORT const char *strerror(int mosq_errno); +mosqpp_EXPORT const char *connack_string(int connack_code); +mosqpp_EXPORT int sub_topic_tokenise(const char *subtopic, char ***topics, int *count); +mosqpp_EXPORT int sub_topic_tokens_free(char ***topics, int count); +mosqpp_EXPORT int lib_version(int *major, int *minor, int *revision); +mosqpp_EXPORT int lib_init(); +mosqpp_EXPORT int lib_cleanup(); +mosqpp_EXPORT int topic_matches_sub(const char *sub, const char *topic, bool *result); +mosqpp_EXPORT int validate_utf8(const char *str, int len); +mosqpp_EXPORT int subscribe_simple( + struct mosquitto_message **messages, + int msg_count, + bool retained, + const char *topic, + int qos=0, + const char *host="localhost", + int port=1883, + const char *client_id=NULL, + int keepalive=60, + bool clean_session=true, + const char *username=NULL, + const char *password=NULL, + const struct libmosquitto_will *will=NULL, + const struct libmosquitto_tls *tls=NULL); + +mosqpp_EXPORT int subscribe_callback( + int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *), + void *userdata, + const char *topic, + int qos=0, + bool retained=true, + const char *host="localhost", + int port=1883, + const char *client_id=NULL, + int keepalive=60, + bool clean_session=true, + const char *username=NULL, + const char *password=NULL, + const struct libmosquitto_will *will=NULL, + const struct libmosquitto_tls *tls=NULL); + +/* + * Class: mosquittopp + * + * A mosquitto client class. This is a C++ wrapper class for the mosquitto C + * library. Please see mosquitto.h for details of the functions. + */ +class mosqpp_EXPORT mosquittopp { + private: + struct mosquitto *m_mosq; + public: + mosquittopp(const char *id=NULL, bool clean_session=true); + virtual ~mosquittopp(); + + int reinitialise(const char *id, bool clean_session); + int socket(); + int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false); + int will_clear(); + int username_pw_set(const char *username, const char *password=NULL); + int connect(const char *host, int port=1883, int keepalive=60); + int connect_async(const char *host, int port=1883, int keepalive=60); + int connect(const char *host, int port, int keepalive, const char *bind_address); + int connect_async(const char *host, int port, int keepalive, const char *bind_address); + int reconnect(); + int reconnect_async(); + int disconnect(); + int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false); + int subscribe(int *mid, const char *sub, int qos=0); + int unsubscribe(int *mid, const char *sub); + void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff); + int max_inflight_messages_set(unsigned int max_inflight_messages); + void message_retry_set(unsigned int message_retry); + void user_data_set(void *userdata); + int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL); + int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL); + int tls_insecure_set(bool value); + int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL); + int opts_set(enum mosq_opt_t option, void *value); + + int loop(int timeout=-1, int max_packets=1); + int loop_misc(); + int loop_read(int max_packets=1); + int loop_write(int max_packets=1); + int loop_forever(int timeout=-1, int max_packets=1); + int loop_start(); + int loop_stop(bool force=false); + bool want_write(); + int threaded_set(bool threaded=true); + int socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL); + + // names in the functions commented to prevent unused parameter warning + virtual void on_connect(int /*rc*/) {return;} + virtual void on_connect_with_flags(int /*rc*/, int /*flags*/) {return;} + virtual void on_disconnect(int /*rc*/) {return;} + virtual void on_publish(int /*mid*/) {return;} + virtual void on_message(const struct mosquitto_message * /*message*/) {return;} + virtual void on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/) {return;} + virtual void on_unsubscribe(int /*mid*/) {return;} + virtual void on_log(int /*level*/, const char * /*str*/) {return;} + virtual void on_error() {return;} +}; + +} +#endif diff --git a/cgi-bin/sqlite3.h b/cgi-bin/includes/sqlite3.h similarity index 100% rename from cgi-bin/sqlite3.h rename to cgi-bin/includes/sqlite3.h diff --git a/cgi-bin/mqtt_libs/libmosquitto.so b/cgi-bin/mqtt_libs/libmosquitto.so new file mode 120000 index 0000000..5afdcb7 --- /dev/null +++ b/cgi-bin/mqtt_libs/libmosquitto.so @@ -0,0 +1 @@ +libmosquitto.so.1 \ No newline at end of file diff --git a/cgi-bin/mqtt_libs/libmosquitto.so.1 b/cgi-bin/mqtt_libs/libmosquitto.so.1 new file mode 100755 index 0000000000000000000000000000000000000000..411ad9f36ea1cf8c4199ed0392d667ea60bd7232 GIT binary patch literal 93616 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 literal 0 HcmV?d00001 diff --git a/cgi-bin/mqtt_libs/libmosquittopp.so b/cgi-bin/mqtt_libs/libmosquittopp.so new file mode 120000 index 0000000..6d56cc4 --- /dev/null +++ b/cgi-bin/mqtt_libs/libmosquittopp.so @@ -0,0 +1 @@ +libmosquittopp.so.1 \ No newline at end of file diff --git a/cgi-bin/mqtt_libs/libmosquittopp.so.1 b/cgi-bin/mqtt_libs/libmosquittopp.so.1 new file mode 100755 index 0000000000000000000000000000000000000000..83966680c33b09bae638327168f1053447f2f647 GIT binary patch literal 32896 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 literal 0 HcmV?d00001 diff --git a/cgi-bin/mqtt_libs/pkgconfig/libmosquitto.pc b/cgi-bin/mqtt_libs/pkgconfig/libmosquitto.pc new file mode 100644 index 0000000..3453d07 --- /dev/null +++ b/cgi-bin/mqtt_libs/pkgconfig/libmosquitto.pc @@ -0,0 +1,10 @@ +prefix=/opt/mqtt/mosquitto +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: mosquitto +Description: mosquitto MQTT library (C bindings) +Version: 1.5.4 +Cflags: -I${includedir} +Libs: -L${libdir} -lmosquitto diff --git a/cgi-bin/mqtt_libs/pkgconfig/libmosquittopp.pc b/cgi-bin/mqtt_libs/pkgconfig/libmosquittopp.pc new file mode 100644 index 0000000..27aa43c --- /dev/null +++ b/cgi-bin/mqtt_libs/pkgconfig/libmosquittopp.pc @@ -0,0 +1,10 @@ +prefix=/opt/mqtt/mosquitto +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: mosquittopp +Description: mosquitto MQTT library (C++ bindings) +Version: 1.5.4 +Cflags: -I${includedir} +Libs: -L${libdir} -lmosquittopp diff --git a/cgi-bin/mqtt_sub_ctos.c b/cgi-bin/mqtt_sub_ctos.c new file mode 100644 index 0000000..2a0f251 --- /dev/null +++ b/cgi-bin/mqtt_sub_ctos.c @@ -0,0 +1,119 @@ +/* + 用于接收 MQTT 服务器的消息 + 并将消息转发给 CG 程序 + 同时存入 sqlite3 数据库 + + 订阅 ctos 的消息,即从设备传入 MQTT 服务器的传感器数据 +*/ + +#include "includes/mosquitto.h" // MQTT 的头文件 +#include +#include +#include // bool 类型 +#include +#include +#include +#include // cJSON 的头文件 +#include "includes/sqlite3.h" // sqlite3 的头文件 + +struct mosquitto *client; // mosquitto 客户端 +int isRunning = 1; // 线程运行标志 +pthread_t main_th_id; // 主线程 ID + +// sqlite3 连接的回调函数 +void connect_callback(struct mosquitto *mosq, void *args, int rc) +{ + if (rc == 0) + { + printf("连接MQTT服务成功!\n"); + } + else + { + printf("连接MQTT服务失败!\n"); + } +} + +// sqlite3 订阅的回调函数 +void on_subscribe(struct mosquitto *mosq, + void *obj, + int mid, + int qos_count, + const int *granted_qos) +{ + printf("-订阅的消息ID为--%d 成功, Qos的granted: %d--\n", mid, + *granted_qos); +} + +// sqlite3 接收消息的回调函数(处理接收到的消息,并将消息存入 sqlite3 数据库) +void on_message(struct mosquitto *mosq, + void *obj, + const struct mosquitto_message *message) +{ + printf("收到%s(%d)的消息: %s\n", message->topic, message->mid, + (char *)message->payload); + if (strncmp((char *)message->payload, "exit", 4) == 0) + { + isRunning = 0; + mosquitto_loop_stop(client, true); + } +} +int main(int argc, char const *argv[]) +{ + main_th_id = pthread_self(); + // 1. 初始化mosquitto的库环境 + // 使用mosquitto库函数前,要先初始化,使用之后要清除。 + mosquitto_lib_init(); // 初始化(固定格式) + + // 2. 创建mosquitto的客户端 + unsigned char userdata[128] = "1"; + client = mosquitto_new("166", true, userdata); // 创建客户端句柄 + // struct mosquitto* mosquitto_new( + // const char *id,//用户自定义标识ID + // bool clean_session, //断开后是否保留订阅信息true/false + // void *userdata //回调参数 + // ); + // d可以为NULL,clean_session的标识必须是true, userdata也可以是NULL + if (client == NULL) // 创建失败 + { + printf("创建mqtt客户端失败!\n"); + perror("mosquitto_new\n"); + return -1; + } + + // 设置回调函数 + mosquitto_connect_callback_set(client, connect_callback); // 设置连接回调函数,用于连接后的处理 + mosquitto_subscribe_callback_set(client, on_subscribe); // 设置订阅回调函数,用于订阅后的处理 + mosquitto_message_callback_set(client, on_message); // 设置接收消息回调函数,用于接收到消息后的处理 + + // 3. 连接mqtt broker + int flag = mosquitto_connect(client, "flykhan.com", 1883, 60); + if (flag == MOSQ_ERR_SUCCESS) + { + printf("-----连接MQTT 服务器成功!-----\n"); + } + else + { + printf("-----连接MQTT 服务器失败!-----\n"); + return -1; + } + + int msgId = 1; // 消息ID + // 开始订阅信息 + flag = mosquitto_subscribe(client, &msgId, "ctos", 0); + if (flag == MOSQ_ERR_SUCCESS) + { + printf("订阅消息ID: %d 成功, 等待消息!\n", msgId); + } + while (isRunning) + { + // 处理网络事件 + mosquitto_loop_start(client); // 接收网络数据 + // usleep(500); + } + + // 关闭mosquitto的客户端 + mosquitto_destroy(client); + // 最后清理库环境 + mosquitto_lib_cleanup(); + return 0; +} diff --git a/cgi-bin/sqlite3.c b/cgi-bin/sqlite3.c index 25ce518..8b8c846 100644 --- a/cgi-bin/sqlite3.c +++ b/cgi-bin/sqlite3.c @@ -43,6 +43,7 @@ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ + /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks diff --git a/cgi-bin/sqlite_cgi_base.c b/cgi-bin/sqlite_cgi_base.c index fd6197c..ad4c81a 100644 --- a/cgi-bin/sqlite_cgi_base.c +++ b/cgi-bin/sqlite_cgi_base.c @@ -1,7 +1,6 @@ #include #include -// #include "cJSON.h" -#include "sqlite3.h" +#include "includes/sqlite3.h" // sqlite3 的头文件 #include // cJSON *result_json; // 用于存储查询结果 diff --git a/cgi-bin/sqlite_cgi_insert_base.c b/cgi-bin/sqlite_cgi_insert_base.c index c56f457..94ec6b3 100644 --- a/cgi-bin/sqlite_cgi_insert_base.c +++ b/cgi-bin/sqlite_cgi_insert_base.c @@ -1,8 +1,7 @@ #include #include -// #include "cJSON.h" #include -#include "sqlite3.h" +#include "includes/sqlite3.h" // cJSON *result_json; // 用于存储查询结果