diff options
Diffstat (limited to 'libs')
65 files changed, 0 insertions, 16078 deletions
diff --git a/libs/libmosquitto/include/config.h b/libs/libmosquitto/include/config.h deleted file mode 100644 index f717d00c8a..0000000000 --- a/libs/libmosquitto/include/config.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H -/* ============================================================ - * Platform options - * ============================================================ */ - -#ifdef __APPLE__ -# define __DARWIN_C_SOURCE -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__SYMBIAN32__) || defined(__QNX__) -# define _XOPEN_SOURCE 700 -# define __BSD_VISIBLE 1 -# define HAVE_NETINET_IN_H -#else -# define _XOPEN_SOURCE 700 -# define _DEFAULT_SOURCE 1 -# define _POSIX_C_SOURCE 200809L -#endif - -#define _GNU_SOURCE - -#define OPENSSL_LOAD_CONF - -/* ============================================================ - * Compatibility defines - * ============================================================ */ -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf sprintf_s -# define EPROTO ECONNABORTED -#endif - -#ifdef WIN32 -# ifndef strcasecmp -# define strcasecmp strcmpi -# endif -# define strtok_r strtok_s -# define strerror_r(e, b, l) strerror_s(b, l, e) -#endif - - -#define uthash_malloc(sz) mosquitto__malloc(sz) -#define uthash_free(ptr,sz) mosquitto__free(ptr) - - -#ifdef WITH_TLS -# include <openssl/opensslconf.h> -# if defined(WITH_TLS_PSK) && !defined(OPENSSL_NO_PSK) -# define FINAL_WITH_TLS_PSK -# endif -#endif - - -#ifdef __COVERITY__ -# include <stdint.h> -/* These are "wrong", but we don't use them so it doesn't matter */ -# define _Float32 uint32_t -# define _Float32x uint32_t -# define _Float64 uint64_t -# define _Float64x uint64_t -# define _Float128 uint64_t -#endif - -#define UNUSED(A) (void)(A) - -/* Android Bionic libpthread implementation doesn't have pthread_cancel */ -#ifndef ANDROID -# define HAVE_PTHREAD_CANCEL -#endif - -#endif diff --git a/libs/libmosquitto/include/mosquitto.h b/libs/libmosquitto/include/mosquitto.h deleted file mode 100644 index 09bba66e08..0000000000 --- a/libs/libmosquitto/include/mosquitto.h +++ /dev/null @@ -1,2993 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 <stdbool.h> -# endif -#endif - -#include <stddef.h> -#include <stdint.h> - -#define LIBMOSQUITTO_MAJOR 1 -#define LIBMOSQUITTO_MINOR 6 -#define LIBMOSQUITTO_REVISION 3 -/* 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 0 -#define MOSQ_LOG_INFO (1<<0) -#define MOSQ_LOG_NOTICE (1<<1) -#define MOSQ_LOG_WARNING (1<<2) -#define MOSQ_LOG_ERR (1<<3) -#define MOSQ_LOG_DEBUG (1<<4) -#define MOSQ_LOG_SUBSCRIBE (1<<5) -#define MOSQ_LOG_UNSUBSCRIBE (1<<6) -#define MOSQ_LOG_WEBSOCKETS (1<<7) -#define MOSQ_LOG_INTERNAL 0x80000000 -#define MOSQ_LOG_ALL 0x7FFFFFFF - -/* Error values */ -enum mosq_err_t { - MOSQ_ERR_AUTH_CONTINUE = -4, - MOSQ_ERR_NO_SUBSCRIBERS = -3, - MOSQ_ERR_SUB_EXISTS = -2, - 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, - MOSQ_ERR_MALFORMED_PACKET = 21, - MOSQ_ERR_DUPLICATE_PROPERTY = 22, - MOSQ_ERR_TLS_HANDSHAKE = 23, - MOSQ_ERR_QOS_NOT_SUPPORTED = 24, - MOSQ_ERR_OVERSIZE_PACKET = 25, - MOSQ_ERR_OCSP = 26, -}; - -/* Option values */ -enum mosq_opt_t { - MOSQ_OPT_PROTOCOL_VERSION = 1, - MOSQ_OPT_SSL_CTX = 2, - MOSQ_OPT_SSL_CTX_WITH_DEFAULTS = 3, - MOSQ_OPT_RECEIVE_MAXIMUM = 4, - MOSQ_OPT_SEND_MAXIMUM = 5, - MOSQ_OPT_TLS_KEYFORM = 6, - MOSQ_OPT_TLS_ENGINE = 7, - MOSQ_OPT_TLS_ENGINE_KPASS_SHA1 = 8, - MOSQ_OPT_TLS_OCSP_REQUIRED = 9, - MOSQ_OPT_TLS_ALPN = 10, -}; - - -/* 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 -#define MQTT_PROTOCOL_V5 5 - -struct mosquitto_message{ - int mid; - char *topic; - void *payload; - int payloadlen; - int qos; - bool retain; -}; - -struct mosquitto; -typedef struct mqtt5__property mosquitto_property; - -/* - * Topic: Threads - * libmosquitto provides thread safe operation, with the exception of - * <mosquitto_lib_init> which is not thread safe. - * - * If your application uses threads you must use <mosquitto_threaded_set> 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() - ***************************************************/ - - -/* ====================================================================== - * - * Section: Library version, init, and cleanup - * - * ====================================================================== */ -/* - * 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: - * <mosquitto_lib_cleanup>, <mosquitto_lib_init> - */ -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: - * <mosquitto_lib_cleanup>, <mosquitto_lib_version> - */ -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: - * <mosquitto_lib_init>, <mosquitto_lib_version> - */ -libmosq_EXPORT int mosquitto_lib_cleanup(void); - - -/* ====================================================================== - * - * Section: Client creation, destruction, and reinitialisation - * - * ====================================================================== */ -/* - * 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 <mosquitto_connect> or - * <mosquitto_reconnect> will cause the messages to be resent. - * Use <mosquitto_reinitialise> 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: - * <mosquitto_reinitialise>, <mosquitto_destroy>, <mosquitto_user_data_set> - */ -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: - * <mosquitto_new>, <mosquitto_reinitialise> - */ -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 <mosquitto_new>. - * - * 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: - * <mosquitto_new>, <mosquitto_destroy> - */ -libmosq_EXPORT int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *obj); - - -/* ====================================================================== - * - * Section: Will - * - * ====================================================================== */ -/* - * 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 <mosquitto_connect>. - * - * 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_set_v5 - * - * Configure will information for a mosquitto instance, with attached - * properties. By default, clients do not have a will. This must be called - * before calling <mosquitto_connect>. - * - * 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. - * properties - list of MQTT 5 properties. Can be NULL. On success only, the - * property list becomes the property of libmosquitto once this - * function is called and will be freed by the library. The - * property list must be freed by the application on error. - * - * 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. - * MOSQ_ERR_NOT_SUPPORTED - if properties is not NULL and the client is not - * using MQTT v5 - * MOSQ_ERR_PROTOCOL - if a property is invalid for use with wills. - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - */ -libmosq_EXPORT int mosquitto_will_set_v5(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties); - -/* - * Function: mosquitto_will_clear - * - * Remove a previously configured will. This must be called before calling - * <mosquitto_connect>. - * - * 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); - - -/* ====================================================================== - * - * Section: Username and password - * - * ====================================================================== */ -/* - * 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 <mosquitto_connect>. - * - * 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); - - -/* ====================================================================== - * - * Section: Connecting, reconnecting, disconnecting - * - * ====================================================================== */ -/* - * 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: - * <mosquitto_connect_bind>, <mosquitto_connect_async>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set> - */ -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 - * <mosquitto_connect> 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: - * <mosquitto_connect>, <mosquitto_connect_async>, <mosquitto_connect_bind_async> - */ -libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address); - -/* - * Function: mosquitto_connect_bind_v5 - * - * Connect to an MQTT broker. This extends the functionality of - * <mosquitto_connect> 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. - * properties - the MQTT 5 properties for the connect (not for the Will). - * - * 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. - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid for use with CONNECT. - * - * See Also: - * <mosquitto_connect>, <mosquitto_connect_async>, <mosquitto_connect_bind_async> - */ -libmosq_EXPORT int mosquitto_connect_bind_v5(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address, const mosquitto_property *properties); - -/* - * Function: mosquitto_connect_async - * - * Connect to an MQTT broker. This is a non-blocking call. If you use - * <mosquitto_connect_async> your client must use the threaded interface - * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use - * <mosquitto_connect> to connect the client. - * - * May be called before or after <mosquitto_loop_start>. - * - * 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: - * <mosquitto_connect_bind_async>, <mosquitto_connect>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set> - */ -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 - * <mosquitto_connect_bind_async> your client must use the threaded interface - * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use - * <mosquitto_connect> to connect the client. - * - * This extends the functionality of <mosquitto_connect_async> 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 <mosquitto_loop_start>. - * - * 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: - * <mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind> - */ -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 - * <mosquitto_connect_async> your client must use the threaded interface - * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use - * <mosquitto_connect> to connect the client. - * - * This extends the functionality of <mosquitto_connect_async> 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 <mosquitto_loop_start>. - * - * 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: - * <mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind> - */ -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 - * <mosquitto_connect> call. It must not be called before - * <mosquitto_connect>. - * - * 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: - * <mosquitto_connect>, <mosquitto_disconnect>, <mosquitto_reconnect_async> - */ -libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq); - -/* - * Function: mosquitto_reconnect_async - * - * Reconnect to a broker. Non blocking version of <mosquitto_reconnect>. - * - * 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 - * <mosquitto_connect> or <mosquitto_connect_async> calls. It must not be - * called before <mosquitto_connect>. - * - * 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: - * <mosquitto_connect>, <mosquitto_disconnect> - */ -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_disconnect_v5 - * - * Disconnect from the broker, with attached MQTT properties. - * - * Use <mosquitto_property_add_*> to create a list of properties, then attach - * them to this publish. Properties need freeing with - * <mosquitto_property_free_all>. - * - * Parameters: - * mosq - a valid mosquitto instance. - * reason_code - the disconnect reason code. - * properties - a valid mosquitto_property list, or NULL. - * - * 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. - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid for use with DISCONNECT. - */ -libmosq_EXPORT int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties); - - -/* ====================================================================== - * - * Section: Publishing, subscribing, unsubscribing - * - * ====================================================================== */ -/* - * 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 - * MOSQ_ERR_QOS_NOT_SUPPORTED - if the QoS is greater than that supported by - * the broker. - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - * - * See Also: - * <mosquitto_max_inflight_messages_set> - */ -libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain); - - -/* - * Function: mosquitto_publish_v5 - * - * Publish a message on a given topic, with attached MQTT properties. - * - * Use <mosquitto_property_add_*> to create a list of properties, then attach - * them to this publish. Properties need freeing with - * <mosquitto_property_free_all>. - * - * Requires the mosquitto instance to be connected with MQTT 5. - * - * 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. - * properties - a valid mosquitto_property list, or NULL. - * - * 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 - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid for use with PUBLISH. - * MOSQ_ERR_QOS_NOT_SUPPORTED - if the QoS is greater than that supported by - * the broker. - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_publish_v5( - struct mosquitto *mosq, - int *mid, - const char *topic, - int payloadlen, - const void *payload, - int qos, - bool retain, - const mosquitto_property *properties); - - -/* - * 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 - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos); - -/* - * Function: mosquitto_subscribe_v5 - * - * Subscribe to a topic, with attached MQTT properties. - * - * Use <mosquitto_property_add_*> to create a list of properties, then attach - * them to this subscribe. Properties need freeing with - * <mosquitto_property_free_all>. - * - * Requires the mosquitto instance to be connected with MQTT 5. - * - * - * 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. - * options - options to apply to this subscription, OR'd together. Set to 0 to - * use the default options, otherwise choose from the list: - * MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client - * publishes to a topic to which it is subscribed, the - * broker will not publish the message back to the - * client. - * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages - * published for this subscription will keep the - * retain flag as was set by the publishing client. - * The default behaviour without this option set has - * the retain flag indicating whether a message is - * fresh/stale. - * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set, - * pre-existing retained messages are sent as soon as - * the subscription is made, even if the subscription - * already exists. This is the default behaviour, so - * it is not necessary to set this option. - * MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing - * retained messages for this subscription will be - * sent when the subscription is made, but only if the - * subscription does not already exist. - * MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set, - * pre-existing retained messages will never be sent - * for this subscription. - * properties - a valid mosquitto_property list, or NULL. - * - * 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 - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid for use with SUBSCRIBE. - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, int qos, int options, const mosquitto_property *properties); - -/* - * Function: mosquitto_subscribe_multiple - * - * Subscribe to multiple topics. - * - * 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_count - the count of subscriptions to be made - * sub - array of sub_count pointers, each pointing to a subscription string. - * The "char *const *const" datatype ensures that neither the array of - * pointers nor the strings that they point to are mutable. If you aren't - * familiar with this, just think of it as a safer "char **", - * equivalent to "const char *" for a simple string pointer. - * qos - the requested Quality of Service for each subscription. - * options - options to apply to this subscription, OR'd together. Set to 0 to - * use the default options, otherwise choose from the list: - * MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client - * publishes to a topic to which it is subscribed, the - * broker will not publish the message back to the - * client. - * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages - * published for this subscription will keep the - * retain flag as was set by the publishing client. - * The default behaviour without this option set has - * the retain flag indicating whether a message is - * fresh/stale. - * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set, - * pre-existing retained messages are sent as soon as - * the subscription is made, even if the subscription - * already exists. This is the default behaviour, so - * it is not necessary to set this option. - * MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing - * retained messages for this subscription will be - * sent when the subscription is made, but only if the - * subscription does not already exist. - * MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set, - * pre-existing retained messages will never be sent - * for this subscription. - * properties - a valid mosquitto_property list, or NULL. Only used with MQTT - * v5 clients. - * - * 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 a topic is not valid UTF-8 - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, int qos, int options, const mosquitto_property *properties); - -/* - * 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 - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub); - -/* - * Function: mosquitto_unsubscribe_v5 - * - * Unsubscribe from a topic, with attached MQTT properties. - * - * 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. - * properties - a valid mosquitto_property list, or NULL. Only used with MQTT - * v5 clients. - * - * 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 - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid for use with UNSUBSCRIBE. - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_unsubscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, const mosquitto_property *properties); - -/* - * Function: mosquitto_unsubscribe_multiple - * - * Unsubscribe from multiple topics. - * - * 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_count - the count of unsubscriptions to be made - * sub - array of sub_count pointers, each pointing to an unsubscription string. - * The "char *const *const" datatype ensures that neither the array of - * pointers nor the strings that they point to are mutable. If you aren't - * familiar with this, just think of it as a safer "char **", - * equivalent to "const char *" for a simple string pointer. - * properties - a valid mosquitto_property list, or NULL. Only used with MQTT - * v5 clients. - * - * 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 a topic is not valid UTF-8 - * MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than - * supported by the broker. - */ -libmosq_EXPORT int mosquitto_unsubscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, const mosquitto_property *properties); - - -/* ====================================================================== - * - * Section: Struct mosquitto_message helper functions - * - * ====================================================================== */ -/* - * 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: - * <mosquitto_message_free> - */ -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: - * <mosquitto_message_copy>, <mosquitto_message_free_contents> - */ -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: - * <mosquitto_message_copy>, <mosquitto_message_free> - */ -libmosq_EXPORT void mosquitto_message_free_contents(struct mosquitto_message *message); - - -/* ====================================================================== - * - * Section: Network loop (managed by libmosquitto) - * - * ====================================================================== */ -/* - * 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. - * <mosquitto_publish>, are normally sent immediately that their function is - * called, but this is not always possible. <mosquitto_loop> 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 <mosquitto_loop_start> 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 - * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write> and - * <mosquitto_loop_misc>. - * - * 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: - * <mosquitto_loop_forever>, <mosquitto_loop_start>, <mosquitto_loop_stop> - */ -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: - * <mosquitto_loop>, <mosquitto_loop_start> - */ -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 <mosquitto_loop> 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: - * <mosquitto_connect_async>, <mosquitto_loop>, <mosquitto_loop_forever>, <mosquitto_loop_stop> - */ -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 <mosquitto_loop_start>. This call - * will block until the network thread finishes. For the network thread to end, - * you must have previously called <mosquitto_disconnect> or have set the force - * parameter to true. - * - * Parameters: - * mosq - a valid mosquitto instance. - * force - set to true to force thread cancellation. If false, - * <mosquitto_disconnect> 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: - * <mosquitto_loop>, <mosquitto_loop_start> - */ -libmosq_EXPORT int mosquitto_loop_stop(struct mosquitto *mosq, bool force); - - -/* ====================================================================== - * - * Section: Network loop (for use in other event loops) - * - * ====================================================================== */ -/* - * 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: - * <mosquitto_socket>, <mosquitto_loop_write>, <mosquitto_loop_misc> - */ -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: - * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_misc>, <mosquitto_want_write> - */ -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: - * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write> - */ -libmosq_EXPORT int mosquitto_loop_misc(struct mosquitto *mosq); - - -/* ====================================================================== - * - * Section: Network loop (helper functions) - * - * ====================================================================== */ -/* - * 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_want_write - * - * Returns true if there is data ready to be written on the socket. - * - * Parameters: - * mosq - a valid mosquitto instance. - * - * See Also: - * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write> - */ -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 <mosquitto_loop_start>. 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 <mosquitto_loop_start>, 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); - - -/* ====================================================================== - * - * Section: Client options - * - * ====================================================================== */ -/* - * Function: mosquitto_opts_set - * - * Used to set options for the client. - * - * This function is deprecated, the replacement <mosquitto_int_option> and - * <mosquitto_void_option> functions should be used instead. - * - * 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 <mosquitto_tls_set> 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_int_option - * - * Used to set integer 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 set to either MQTT_PROTOCOL_V31, - * MQTT_PROTOCOL_V311, or MQTT_PROTOCOL_V5. Must be set before the - * client connects. Defaults to MQTT_PROTOCOL_V311. - * - * MOSQ_OPT_RECEIVE_MAXIMUM - * Value can be set between 1 and 65535 inclusive, and represents - * the maximum number of incoming QoS 1 and QoS 2 messages that this - * client wants to process at once. Defaults to 20. This option is - * not valid for MQTT v3.1 or v3.1.1 clients. - * Note that if the MQTT_PROP_RECEIVE_MAXIMUM property is in the - * proplist passed to mosquitto_connect_v5(), then that property - * will override this option. Using this option is the recommended - * method however. - * - * MOSQ_OPT_SEND_MAXIMUM - * Value can be set between 1 and 65535 inclusive, and represents - * the maximum number of outgoing QoS 1 and QoS 2 messages that this - * client will attempt to have "in flight" at once. Defaults to 20. - * This option is not valid for MQTT v3.1 or v3.1.1 clients. - * Note that if the broker being connected to sends a - * MQTT_PROP_RECEIVE_MAXIMUM property that has a lower value than - * this option, then the broker provided value will be used. - * - * MOSQ_OPT_SSL_CTX_WITH_DEFAULTS - * If value is set to a non zero value, 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 <mosquitto_tls_set> to configure the cafile/capath as a - * minimum. - * This option is only available for openssl 1.1.0 and higher. - * MOSQ_OPT_TLS_OCSP_REQUIRED - * Set whether OCSP checking on TLS connections is required. Set to - * 1 to enable checking, or 0 (the default) for no checking. - */ -libmosq_EXPORT int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int value); - - -/* - * Function: mosquitto_void_option - * - * Used to set void* options for the client. - * - * Parameters: - * mosq - a valid mosquitto instance. - * option - the option to set. - * value - the option specific value. - * - * Options: - * 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. - */ -libmosq_EXPORT int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value); - - -/* - * Function: mosquitto_reconnect_delay_set - * - * Control the behaviour of the client when it has unexpectedly disconnected in - * <mosquitto_loop_forever> or after <mosquitto_loop_start>. 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 - * - * This function is deprected. Use the <mosquitto_int_option> function with the - * MOSQ_OPT_SEND_MAXIMUM option instead. - * - * 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 <mosquitto_publish> 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 <mosquitto_new> is called, the pointer given as the "obj" parameter - * will be passed to the callbacks as user data. The <mosquitto_user_data_set> - * 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); - -/* 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); - - -/* ====================================================================== - * - * Section: TLS support - * - * ====================================================================== */ -/* - * Function: mosquitto_tls_set - * - * Configure the client for certificate based SSL/TLS support. Must be called - * before <mosquitto_connect>. - * - * Cannot be used in conjunction with <mosquitto_tls_psk_set>. - * - * 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 <mosquitto_userdata>. - * - * 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: - * <mosquitto_tls_opts_set>, <mosquitto_tls_psk_set>, - * <mosquitto_tls_insecure_set>, <mosquitto_userdata> - */ -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 <mosquitto_connect>. - * - * 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: - * <mosquitto_tls_set> - */ -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 <mosquitto_connect>. - * - * 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: - * <mosquitto_tls_set> - */ -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 <mosquitto_connect>. - * - * Cannot be used in conjunction with <mosquitto_tls_set>. - * - * 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: - * <mosquitto_tls_set> - */ -libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers); - - -/* ====================================================================== - * - * Section: Callbacks - * - * ====================================================================== */ -/* - * 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 <mosquitto_new> - * 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 <mosquitto_new> - * 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_connect_v5_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 <mosquitto_new> - * 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 - * flags - the connect flags. - * props - list of MQTT 5 properties, or NULL - * - */ -libmosq_EXPORT void mosquitto_connect_v5_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int, const mosquitto_property *props)); - -/* - * 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 <mosquitto_new> - * rc - integer value indicating the reason for the disconnect. A value of 0 - * means the client has called <mosquitto_disconnect>. 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_disconnect_v5_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 <mosquitto_new> - * rc - integer value indicating the reason for the disconnect. A value of 0 - * means the client has called <mosquitto_disconnect>. Any other value - * indicates that the disconnect is unexpected. - * props - list of MQTT 5 properties, or NULL - */ -libmosq_EXPORT void mosquitto_disconnect_v5_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int, const mosquitto_property *)); - -/* - * Function: mosquitto_publish_callback_set - * - * Set the publish callback. This is called when a message initiated with - * <mosquitto_publish> 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 <mosquitto_new> - * 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_publish_v5_callback_set - * - * Set the publish callback. This is called when a message initiated with - * <mosquitto_publish> has been sent to the broker. This callback will be - * called both if the message is sent successfully, or if the broker responded - * with an error, which will be reflected in the reason_code parameter. - * - * 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 <mosquitto_new> - * mid - the message id of the sent message. - * reason_code - the MQTT 5 reason code - * props - list of MQTT 5 properties, or NULL - */ -libmosq_EXPORT void mosquitto_publish_v5_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int, int, const mosquitto_property *)); - -/* - * 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 <mosquitto_new> - * 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: - * <mosquitto_message_copy> - */ -libmosq_EXPORT void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *)); - -/* - * Function: mosquitto_message_v5_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 <mosquitto_new> - * 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. - * props - list of MQTT 5 properties, or NULL - * - * See Also: - * <mosquitto_message_copy> - */ -libmosq_EXPORT void mosquitto_message_v5_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *, const mosquitto_property *)); - -/* - * 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 <mosquitto_new> - * 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_subscribe_v5_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 <mosquitto_new> - * 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. - * props - list of MQTT 5 properties, or NULL - */ -libmosq_EXPORT void mosquitto_subscribe_v5_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *, const mosquitto_property *)); - -/* - * 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 <mosquitto_new> - * 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_unsubscribe_v5_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 <mosquitto_new> - * mid - the message id of the unsubscribe message. - * props - list of MQTT 5 properties, or NULL - */ -libmosq_EXPORT void mosquitto_unsubscribe_v5_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int, const mosquitto_property *)); - -/* - * 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 <mosquitto_new> - * 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_string_option - * - * Used to set const char* options for the client. - * - * Parameters: - * mosq - a valid mosquitto instance. - * option - the option to set. - * value - the option specific value. - * - * Options: - * MOSQ_OPT_TLS_ENGINE - * Configure the client for TLS Engine support. Pass a TLS Engine ID - * to be used when creating TLS connections. - * Must be set before <mosquitto_connect>. - * MOSQ_OPT_TLS_KEYFORM - * Configure the client to treat the keyfile differently depending - * on its type. Must be set before <mosquitto_connect>. - * Set as either "pem" or "engine", to determine from where the - * private key for a TLS connection will be obtained. Defaults to - * "pem", a normal private key file. - * MOSQ_OPT_TLS_KPASS_SHA1 - * Where the TLS Engine requires the use of a password to be - * accessed, this option allows a hex encoded SHA1 hash of the - * private key password to be passed to the engine directly. - * Must be set before <mosquitto_connect>. - * MOSQ_OPT_TLS_ALPN - * If the broker being connected to has multiple services available - * on a single TLS port, such as both MQTT and WebSockets, use this - * option to configure the ALPN option for the connection. - */ -libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value); - - -/* - * Function: mosquitto_reconnect_delay_set - * - * Control the behaviour of the client when it has unexpectedly disconnected in - * <mosquitto_loop_forever> or after <mosquitto_loop_start>. 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); - - -/* ============================================================================= - * - * 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_reason_string - * - * Call to obtain a const string description of an MQTT reason code. - * - * Parameters: - * reason_code - an MQTT reason code. - * - * Returns: - * A constant string describing the reason. - */ -libmosq_EXPORT const char *mosquitto_reason_string(int reason_code); - -/* Function: mosquitto_string_to_command - * - * Take a string input representing an MQTT command and convert it to the - * libmosquitto integer representation. - * - * Parameters: - * str - the string to parse. - * cmd - pointer to an int, for the result. - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - on an invalid input. - * - * Example: - * mosquitto_string_to_command("CONNECT", &cmd); - * // cmd == CMD_CONNECT - */ -libmosq_EXPORT int mosquitto_string_to_command(const char *str, int *cmd); - -/* - * 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<token_count; i++){ - * > printf("%d: %s\n", i, topics[i]); - * > } - * - * See Also: - * <mosquitto_sub_topic_tokens_free> - */ -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 <mosquitto_sub_topic_tokenise>. - * - * 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: - * <mosquitto_sub_topic_tokenise> - */ -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 <mosquitto_publish> and - * <mosquitto_will_set>, 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: - * <mosquitto_sub_topic_check> - */ -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 <mosquitto_subscribe> and - * <mosquitto_unsubscribe>, 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: - * <mosquitto_sub_topic_check> - */ -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); - - -/* ============================================================================= - * - * Section: Properties - * - * ============================================================================= - */ - - -/* - * Function: mosquitto_property_add_byte - * - * Add a new byte property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - integer value for the new property - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_byte(&proplist, MQTT_PROP_PAYLOAD_FORMAT_IDENTIFIER, 1); - */ -libmosq_EXPORT int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, uint8_t value); - -/* - * Function: mosquitto_property_add_int16 - * - * Add a new int16 property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_RECEIVE_MAXIMUM) - * value - integer value for the new property - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_int16(&proplist, MQTT_PROP_RECEIVE_MAXIMUM, 1000); - */ -libmosq_EXPORT int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier, uint16_t value); - -/* - * Function: mosquitto_property_add_int32 - * - * Add a new int32 property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_MESSAGE_EXPIRY_INTERVAL) - * value - integer value for the new property - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_int32(&proplist, MQTT_PROP_MESSAGE_EXPIRY_INTERVAL, 86400); - */ -libmosq_EXPORT int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier, uint32_t value); - -/* - * Function: mosquitto_property_add_varint - * - * Add a new varint property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_SUBSCRIPTION_IDENTIFIER) - * value - integer value for the new property - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_varint(&proplist, MQTT_PROP_SUBSCRIPTION_IDENTIFIER, 1); - */ -libmosq_EXPORT int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value); - -/* - * Function: mosquitto_property_add_binary - * - * Add a new binary property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to the property data - * len - length of property data in bytes - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_binary(&proplist, MQTT_PROP_AUTHENTICATION_DATA, auth_data, auth_data_len); - */ -libmosq_EXPORT int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier, const void *value, uint16_t len); - -/* - * Function: mosquitto_property_add_string - * - * Add a new string property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_CONTENT_TYPE) - * value - string value for the new property, must be UTF-8 and zero terminated - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, if value is NULL, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * MOSQ_ERR_MALFORMED_UTF8 - value is not valid UTF-8. - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_string(&proplist, MQTT_PROP_CONTENT_TYPE, "application/json"); - */ -libmosq_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value); - -/* - * Function: mosquitto_property_add_string_pair - * - * Add a new string pair property to a property list. - * - * If *proplist == NULL, a new list will be created, otherwise the new property - * will be appended to the list. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_USER_PROPERTY) - * name - string name for the new property, must be UTF-8 and zero terminated - * value - string value for the new property, must be UTF-8 and zero terminated - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if identifier is invalid, if name or value is NULL, or if proplist is NULL - * MOSQ_ERR_NOMEM - on out of memory - * MOSQ_ERR_MALFORMED_UTF8 - if name or value are not valid UTF-8. - * - * Example: - * mosquitto_property *proplist = NULL; - * mosquitto_property_add_string_pair(&proplist, MQTT_PROP_USER_PROPERTY, "client", "mosquitto_pub"); - */ -libmosq_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value); - -/* - * Function: mosquitto_property_read_byte - * - * Attempt to read a byte property matching an identifier, from a property list - * or single property. This function can search for multiple entries of the - * same identifier by using the returned value and skip_first. Note however - * that it is forbidden for most properties to be duplicated. - * - * If the property is not found, *value will not be modified, so it is safe to - * pass a variable with a default value to be potentially overwritten: - * - * uint16_t keepalive = 60; // default value - * // Get value from property list, or keep default if not found. - * mosquitto_property_read_int16(proplist, MQTT_PROP_SERVER_KEEP_ALIVE, &keepalive, false); - * - * Parameters: - * proplist - mosquitto_property pointer, the list of properties or single property - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to store the value, or NULL if the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL. - * - * Example: - * // proplist is obtained from a callback - * mosquitto_property *prop; - * prop = mosquitto_property_read_byte(proplist, identifier, &value, false); - * while(prop){ - * printf("value: %s\n", value); - * prop = mosquitto_property_read_byte(prop, identifier, &value); - * } - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_byte( - const mosquitto_property *proplist, - int identifier, - uint8_t *value, - bool skip_first); - -/* - * Function: mosquitto_property_read_int16 - * - * Read an int16 property value from a property. - * - * Parameters: - * property - property to read - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to store the value, or NULL if the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int16( - const mosquitto_property *proplist, - int identifier, - uint16_t *value, - bool skip_first); - -/* - * Function: mosquitto_property_read_int32 - * - * Read an int32 property value from a property. - * - * Parameters: - * property - pointer to mosquitto_property pointer, the list of properties - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to store the value, or NULL if the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int32( - const mosquitto_property *proplist, - int identifier, - uint32_t *value, - bool skip_first); - -/* - * Function: mosquitto_property_read_varint - * - * Read a varint property value from a property. - * - * Parameters: - * property - property to read - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to store the value, or NULL if the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_varint( - const mosquitto_property *proplist, - int identifier, - uint32_t *value, - bool skip_first); - -/* - * Function: mosquitto_property_read_binary - * - * Read a binary property value from a property. - * - * On success, value must be free()'d by the application. - * - * Parameters: - * property - property to read - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to store the value, or NULL if the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_binary( - const mosquitto_property *proplist, - int identifier, - void **value, - uint16_t *len, - bool skip_first); - -/* - * Function: mosquitto_property_read_string - * - * Read a string property value from a property. - * - * On success, value must be free()'d by the application. - * - * Parameters: - * property - property to read - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * value - pointer to char*, for the property data to be stored in, or NULL if - * the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string( - const mosquitto_property *proplist, - int identifier, - char **value, - bool skip_first); - -/* - * Function: mosquitto_property_read_string_pair - * - * Read a string pair property value pair from a property. - * - * On success, name and value must be free()'d by the application. - * - * Parameters: - * property - property to read - * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) - * name - pointer to char* for the name property data to be stored in, or NULL - * if the name is not required. - * value - pointer to char*, for the property data to be stored in, or NULL if - * the value is not required. - * skip_first - boolean that indicates whether the first item in the list - * should be ignored or not. Should usually be set to false. - * - * Returns: - * A valid property pointer if the property is found - * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred. - * - * Example: - * See <mosquitto_property_read_byte> - */ -libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string_pair( - const mosquitto_property *proplist, - int identifier, - char **name, - char **value, - bool skip_first); - -/* - * Function: mosquitto_property_free_all - * - * Free all properties from a list of properties. Frees the list and sets *properties to NULL. - * - * Parameters: - * properties - list of properties to free - * - * Example: - * mosquitto_properties *properties = NULL; - * // Add properties - * mosquitto_property_free_all(&properties); - */ -libmosq_EXPORT void mosquitto_property_free_all(mosquitto_property **properties); - -/* - * Function: mosquitto_property_copy_all - * - * Parameters: - * dest : pointer for new property list - * src : property list - * - * Returns: - * MOSQ_ERR_SUCCESS - on successful copy - * MOSQ_ERR_INVAL - if dest is NULL - * MOSQ_ERR_NOMEM - on out of memory (dest will be set to NULL) - */ -libmosq_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const mosquitto_property *src); - -/* - * Function: mosquitto_property_check_command - * - * Check whether a property identifier is valid for the given command. - * - * Parameters: - * command - MQTT command (e.g. CMD_CONNECT) - * identifier - MQTT property (e.g. MQTT_PROP_USER_PROPERTY) - * - * Returns: - * MOSQ_ERR_SUCCESS - if the identifier is valid for command - * MOSQ_ERR_PROTOCOL - if the identifier is not valid for use with command. - */ -libmosq_EXPORT int mosquitto_property_check_command(int command, int identifier); - - -/* - * Function: mosquitto_property_check_all - * - * Check whether a list of properties are valid for a particular command, - * whether there are duplicates, and whether the values are valid where - * possible. - * - * Note that this function is used internally in the library whenever - * properties are passed to it, so in basic use this is not needed, but should - * be helpful to check property lists *before* the point of using them. - * - * Parameters: - * command - MQTT command (e.g. CMD_CONNECT) - * properties - list of MQTT properties to check. - * - * Returns: - * MOSQ_ERR_SUCCESS - if all properties are valid - * MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden. - * MOSQ_ERR_PROTOCOL - if any property is invalid - */ -libmosq_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties); - -/* Function: mosquitto_string_to_property_info - * - * Parse a property name string and convert to a property identifier and data type. - * The property name is as defined in the MQTT specification, with - as a - * separator, for example: payload-format-indicator. - * - * Parameters: - * propname - the string to parse - * identifier - pointer to an int to receive the property identifier - * type - pointer to an int to receive the property type - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if the string does not match a property - * - * Example: - * mosquitto_string_to_property_info("response-topic", &id, &type); - * // id == MQTT_PROP_RESPONSE_TOPIC - * // type == MQTT_PROP_TYPE_STRING - */ -libmosq_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libs/libmosquitto/include/uthash.h b/libs/libmosquitto/include/uthash.h deleted file mode 100644 index 915a8254ee..0000000000 --- a/libs/libmosquitto/include/uthash.h +++ /dev/null @@ -1,948 +0,0 @@ -/* -Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#include <string.h> /* memcmp,strlen */ -#include <stddef.h> /* ptrdiff_t */ -#include <stdlib.h> /* exit() */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define DECLTYPE(x) -#endif -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while(0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while(0) -#endif - -/* a number of the hash function use uint32_t which isn't defined on win32 */ -#ifdef _MSC_VER -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#else -#include <inttypes.h> /* uint32_t */ -#endif - -#define UTHASH_VERSION 1.9.8 - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#endif -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhe */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_bkt,_hf_hashv; \ - out=NULL; \ - if (head) { \ - HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ - keyptr,keylen,out); \ - } \ - } \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0 -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while(0) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - replaced=NULL; \ - HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ - if (replaced!=NULL) { \ - HASH_DELETE(hh,head,replaced); \ - }; \ - HASH_ADD(hh,head,fieldname,keylen_in,add); \ -} while(0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.next = NULL; \ - (add)->hh.key = (char*)keyptr; \ - (add)->hh.keylen = (unsigned)keylen_in; \ - if (!(head)) { \ - head = (add); \ - (head)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh,head); \ - } else { \ - (head)->hh.tbl->tail->next = (add); \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail = &((add)->hh); \ - } \ - (head)->hh.tbl->num_items++; \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ - (add)->hh.hashv, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ - HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ - HASH_FSCK(hh,head); \ -} while(0) - -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - unsigned _hd_bkt; \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - head = NULL; \ - } else { \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ - } \ - if (_hd_hh_del->next) { \ - ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield,strlen(add->strfield),add) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - unsigned _bkt_i; \ - unsigned _count, _bkt_count; \ - char *_prev; \ - struct UT_hash_handle *_thh; \ - if (head) { \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %d, actual %d\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include <unistd.h> to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#ifdef HASH_FUNCTION -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6 */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _sx_i; \ - char *_hs_key=(char*)(key); \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - bkt = hashv & (num_bkts-1); \ -} while (0) - -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _fn_i; \ - char *_hf_key=(char*)(key); \ - hashv = 2166136261UL; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) \ - hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _ho_i; \ - char *_ho_key=(char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned char *_hj_key=(unsigned char*)(key); \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = (unsigned)keylen; \ - while (_hj_k >= 12) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12; \ - } \ - hashv += keylen; \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - case 5: _hj_j += _hj_key[4]; \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned char *_sfh_key=(unsigned char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ - \ - int _sfh_rem = _sfh_len & 3; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6b; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35l; \ - _h ^= _h >> 16; \ -} while(0) - -#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353; \ - uint32_t _mur_c1 = 0xcc9e2d51; \ - uint32_t _mur_c2 = 0x1b873593; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ - int _mur_i; \ - for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = _mur_h1*5+0xe6546b64; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ - _mur_k1=0; \ - switch((keylen) & 3) { \ - case 3: _mur_k1 ^= _mur_tail[2] << 16; \ - case 2: _mur_k1 ^= _mur_tail[1] << 8; \ - case 1: _mur_k1 ^= _mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ - bkt = hashv & (num_bkts-1); \ -} while(0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* key comparison function; return 0 if keys equal */ -#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ -do { \ - if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ - else out=NULL; \ - while (out) { \ - if ((out)->hh.keylen == keylen_in) { \ - if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ - } \ - if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ - else out = NULL; \ - } \ -} while(0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ - && (addhh)->tbl->noexpand != 1) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while(0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ - ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ - _he_thh; \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - tbl->num_buckets *= 2; \ - tbl->log2_num_buckets++; \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1) : 0; \ - if (tbl->ineff_expands > 1) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while(0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) break; \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ - if (_hs_psize == 0) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else if (( \ - cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail ) { \ - _hs_tail->next = ((_hs_e) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e) { \ - _hs_e->prev = ((_hs_tail) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail){ \ - _hs_tail->next = NULL; \ - } \ - if ( _hs_nmerges <= 1 ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ - if (!dst) { \ - DECLTYPE_ASSIGN(dst,_elt); \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)=NULL; \ - } \ -} while(0) - -#define HASH_OVERHEAD(hh,head) \ - (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - (sizeof(UT_hash_table)) + \ - (HASH_BLOOM_BYTELEN))) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1 -#define HASH_BLOOM_SIGNATURE 0xb12220f2 - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - char bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ diff --git a/libs/libmosquitto/include/utlist.h b/libs/libmosquitto/include/utlist.h deleted file mode 100644 index 5bb1ac9b72..0000000000 --- a/libs/libmosquitto/include/utlist.h +++ /dev/null @@ -1,1073 +0,0 @@ -/* -Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTLIST_H -#define UTLIST_H - -#define UTLIST_VERSION 2.1.0 - -#include <assert.h> - -/* - * This file contains macros to manipulate singly and doubly-linked lists. - * - * 1. LL_ macros: singly-linked lists. - * 2. DL_ macros: doubly-linked lists. - * 3. CDL_ macros: circular doubly-linked lists. - * - * To use singly-linked lists, your structure must have a "next" pointer. - * To use doubly-linked lists, your structure must "prev" and "next" pointers. - * Either way, the pointer to the head of the list must be initialized to NULL. - * - * ----------------.EXAMPLE ------------------------- - * struct item { - * int id; - * struct item *prev, *next; - * } - * - * struct item *list = NULL: - * - * int main() { - * struct item *item; - * ... allocate and populate item ... - * DL_APPEND(list, item); - * } - * -------------------------------------------------- - * - * For doubly-linked lists, the append and delete macros are O(1) - * For singly-linked lists, append and delete are O(n) but prepend is O(1) - * The sort macro is O(n log(n)) for all types of single/double/circular lists. - */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define LDECLTYPE(x) decltype(x) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#endif -#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) -#define NO_DECLTYPE -#else /* GNU, Sun and other compilers */ -#define LDECLTYPE(x) __typeof(x) -#endif -#endif - -/* for VS2008 we use some workarounds to get around the lack of decltype, - * namely, we always reassign our tmp variable to the list head if we need - * to dereference its prev/next pointers, and save/restore the real head.*/ -#ifdef NO_DECLTYPE -#define IF_NO_DECLTYPE(x) x -#define LDECLTYPE(x) char* -#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } -#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) -#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } -/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ -#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } -#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } -#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } -#else -#define IF_NO_DECLTYPE(x) -#define UTLIST_SV(elt,list) -#define UTLIST_NEXT(elt,list,next) ((elt)->next) -#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) -/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ -#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) -#define UTLIST_RS(list) -#define UTLIST_CASTASGN(a,b) (a)=(b) -#endif - -/****************************************************************************** - * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * - * Unwieldy variable names used here to avoid shadowing passed-in variables. * - *****************************************************************************/ -#define LL_SORT(list, cmp) \ - LL_SORT2(list, cmp, next) - -#define LL_SORT2(list, cmp, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - } \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - - -#define DL_SORT(list, cmp) \ - DL_SORT2(list, cmp, prev, next) - -#define DL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if ((_ls_qsize == 0) || (!_ls_q)) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev, _ls_tail); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -#define CDL_SORT(list, cmp) \ - CDL_SORT2(list, cmp, prev, next) - -#define CDL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - LDECLTYPE(list) _ls_oldhead; \ - LDECLTYPE(list) _tmp; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - UTLIST_CASTASGN(_ls_oldhead,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); \ - if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ - _ls_q = NULL; \ - } else { \ - _ls_q = UTLIST_NEXT(_ls_q,list,next); \ - } \ - UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev,_ls_tail); \ - UTLIST_CASTASGN(_tmp,list); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -/****************************************************************************** - * singly linked list macros (non-circular) * - *****************************************************************************/ -#define LL_PREPEND(head,add) \ - LL_PREPEND2(head,add,next) - -#define LL_PREPEND2(head,add,next) \ -do { \ - (add)->next = (head); \ - (head) = (add); \ -} while (0) - -#define LL_CONCAT(head1,head2) \ - LL_CONCAT2(head1,head2,next) - -#define LL_CONCAT2(head1,head2,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head1) { \ - _tmp = (head1); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(head2); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) - -#define LL_APPEND(head,add) \ - LL_APPEND2(head,add,next) - -#define LL_APPEND2(head,add,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - (add)->next=NULL; \ - if (head) { \ - _tmp = (head); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(add); \ - } else { \ - (head)=(add); \ - } \ -} while (0) - -#define LL_INSERT_INORDER(head,add,cmp) \ - LL_INSERT_INORDER2(head,add,cmp,next) - -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - LL_APPEND_ELEM2(head, _tmp, add, next); \ - } else { \ - (head) = (add); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define LL_LOWER_BOUND(head,elt,like,cmp) \ - LL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ - do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if (cmp((elt)->next, like) >= 0) { \ - break; \ - } \ - } \ - } \ - } while (0) - -#define LL_DELETE(head,del) \ - LL_DELETE2(head,del,next) - -#define LL_DELETE2(head,del,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (del))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (del)->next; \ - } \ - } \ -} while (0) - -#define LL_COUNT(head,el,counter) \ - LL_COUNT2(head,el,counter,next) \ - -#define LL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - LL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define LL_FOREACH(head,el) \ - LL_FOREACH2(head,el,next) - -#define LL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) - -#define LL_FOREACH_SAFE(head,el,tmp) \ - LL_FOREACH_SAFE2(head,el,tmp,next) - -#define LL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) - -#define LL_SEARCH_SCALAR(head,out,field,val) \ - LL_SEARCH_SCALAR2(head,out,field,val,next) - -#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) - -#define LL_SEARCH(head,out,elt,cmp) \ - LL_SEARCH2(head,out,elt,cmp,next) - -#define LL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) - -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - LDECLTYPE(head) _tmp; \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ -} while (0) - -#define LL_REPLACE_ELEM(head, el, add) \ - LL_REPLACE_ELEM2(head, el, add, next) - -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - LDECLTYPE(head) _tmp; \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ - -#define LL_PREPEND_ELEM(head, el, add) \ - LL_PREPEND_ELEM2(head, el, add, next) - -#define LL_APPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (el)->next = (add); \ - } else { \ - LL_PREPEND2(head, add, next); \ - } \ -} while (0) \ - -#define LL_APPEND_ELEM(head, el, add) \ - LL_APPEND_ELEM2(head, el, add, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef LL_CONCAT2 -#define LL_CONCAT2(head1,head2,next) \ -do { \ - char *_tmp; \ - if (head1) { \ - _tmp = (char*)(head1); \ - while ((head1)->next) { (head1) = (head1)->next; } \ - (head1)->next = (head2); \ - UTLIST_RS(head1); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) - -#undef LL_APPEND2 -#define LL_APPEND2(head,add,next) \ -do { \ - if (head) { \ - (add)->next = head; /* use add->next as a temp variable */ \ - while ((add)->next->next) { (add)->next = (add)->next->next; } \ - (add)->next->next=(add); \ - } else { \ - (head)=(add); \ - } \ - (add)->next=NULL; \ -} while (0) - -#undef LL_INSERT_INORDER2 -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, add)) >= 0) { \ - (add)->next = (head); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) - -#undef LL_DELETE2 -#define LL_DELETE2(head,del,next) \ -do { \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && ((head)->next != (del))) { \ - (head) = (head)->next; \ - } \ - if ((head)->next) { \ - (head)->next = ((del)->next); \ - } \ - UTLIST_RS(head); \ - } \ -} while (0) - -#undef LL_REPLACE_ELEM2 -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = head; \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el)->next; \ -} while (0) - -#undef LL_PREPEND_ELEM2 -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = (head); \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el); \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ - -#endif /* NO_DECLTYPE */ - -/****************************************************************************** - * doubly linked list macros (non-circular) * - *****************************************************************************/ -#define DL_PREPEND(head,add) \ - DL_PREPEND2(head,add,prev,next) - -#define DL_PREPEND2(head,add,prev,next) \ -do { \ - (add)->next = (head); \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev = (add); \ - } else { \ - (add)->prev = (add); \ - } \ - (head) = (add); \ -} while (0) - -#define DL_APPEND(head,add) \ - DL_APPEND2(head,add,prev,next) - -#define DL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev->next = (add); \ - (head)->prev = (add); \ - (add)->next = NULL; \ - } else { \ - (head)=(add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define DL_INSERT_INORDER(head,add,cmp) \ - DL_INSERT_INORDER2(head,add,cmp,prev,next) - -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define DL_LOWER_BOUND(head,elt,like,cmp) \ - DL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) - -#define DL_CONCAT(head1,head2) \ - DL_CONCAT2(head1,head2,prev,next) - -#define DL_CONCAT2(head1,head2,prev,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head2) { \ - if (head1) { \ - UTLIST_CASTASGN(_tmp, (head2)->prev); \ - (head2)->prev = (head1)->prev; \ - (head1)->prev->next = (head2); \ - UTLIST_CASTASGN((head1)->prev, _tmp); \ - } else { \ - (head1)=(head2); \ - } \ - } \ -} while (0) - -#define DL_DELETE(head,del) \ - DL_DELETE2(head,del,prev,next) - -#define DL_DELETE2(head,del,prev,next) \ -do { \ - assert((head) != NULL); \ - assert((del)->prev != NULL); \ - if ((del)->prev == (del)) { \ - (head)=NULL; \ - } else if ((del)==(head)) { \ - (del)->next->prev = (del)->prev; \ - (head) = (del)->next; \ - } else { \ - (del)->prev->next = (del)->next; \ - if ((del)->next) { \ - (del)->next->prev = (del)->prev; \ - } else { \ - (head)->prev = (del)->prev; \ - } \ - } \ -} while (0) - -#define DL_COUNT(head,el,counter) \ - DL_COUNT2(head,el,counter,next) \ - -#define DL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - DL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define DL_FOREACH(head,el) \ - DL_FOREACH2(head,el,next) - -#define DL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) - -/* this version is safe for deleting the elements during iteration */ -#define DL_FOREACH_SAFE(head,el,tmp) \ - DL_FOREACH_SAFE2(head,el,tmp,next) - -#define DL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) - -/* these are identical to their singly-linked list counterparts */ -#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR -#define DL_SEARCH LL_SEARCH -#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 -#define DL_SEARCH2 LL_SEARCH2 - -#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - (add)->next = (el)->next; \ - if ((el)->next == NULL) { \ - (add)->prev = (add); \ - } else { \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - } \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->prev->next = (add); \ - if ((el)->next == NULL) { \ - (head)->prev = (add); \ - } else { \ - (add)->next->prev = (add); \ - } \ - } \ -} while (0) - -#define DL_REPLACE_ELEM(head, el, add) \ - DL_REPLACE_ELEM2(head, el, add, prev, next) - -#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->prev->next = (add); \ - } \ - } else { \ - DL_APPEND2(head, add, prev, next); \ - } \ -} while (0) \ - -#define DL_PREPEND_ELEM(head, el, add) \ - DL_PREPEND_ELEM2(head, el, add, prev, next) - -#define DL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } else { \ - DL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) \ - -#define DL_APPEND_ELEM(head, el, add) \ - DL_APPEND_ELEM2(head, el, add, prev, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef DL_INSERT_INORDER2 -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = NULL; \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } \ -} while (0) -#endif /* NO_DECLTYPE */ - -/****************************************************************************** - * circular doubly linked list macros * - *****************************************************************************/ -#define CDL_APPEND(head,add) \ - CDL_APPEND2(head,add,prev,next) - -#define CDL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } \ -} while (0) - -#define CDL_PREPEND(head,add) \ - CDL_PREPEND2(head,add,prev,next) - -#define CDL_PREPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - } \ - (head) = (add); \ -} while (0) - -#define CDL_INSERT_INORDER(head,add,cmp) \ - CDL_INSERT_INORDER2(head,add,cmp,prev,next) - -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->next = (head); \ - (head)->prev = (head); \ - } \ -} while (0) - -#define CDL_LOWER_BOUND(head,elt,like,cmp) \ - CDL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) - -#define CDL_DELETE(head,del) \ - CDL_DELETE2(head,del,prev,next) - -#define CDL_DELETE2(head,del,prev,next) \ -do { \ - if (((head)==(del)) && ((head)->next == (head))) { \ - (head) = NULL; \ - } else { \ - (del)->next->prev = (del)->prev; \ - (del)->prev->next = (del)->next; \ - if ((del) == (head)) (head)=(del)->next; \ - } \ -} while (0) - -#define CDL_COUNT(head,el,counter) \ - CDL_COUNT2(head,el,counter,next) \ - -#define CDL_COUNT2(head, el, counter,next) \ -do { \ - (counter) = 0; \ - CDL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define CDL_FOREACH(head,el) \ - CDL_FOREACH2(head,el,next) - -#define CDL_FOREACH2(head,el,next) \ - for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) - -#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ - CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) - -#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ - for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ - (el) && ((tmp2) = (el)->next, 1); \ - (el) = ((el) == (tmp1) ? NULL : (tmp2))) - -#define CDL_SEARCH_SCALAR(head,out,field,val) \ - CDL_SEARCH_SCALAR2(head,out,field,val,next) - -#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) - -#define CDL_SEARCH(head,out,elt,cmp) \ - CDL_SEARCH2(head,out,elt,cmp,next) - -#define CDL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) - -#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((el)->next == (el)) { \ - (add)->next = (add); \ - (add)->prev = (add); \ - (head) = (add); \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } \ -} while (0) - -#define CDL_REPLACE_ELEM(head, el, add) \ - CDL_REPLACE_ELEM2(head, el, add, prev, next) - -#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } else { \ - CDL_APPEND2(head, add, prev, next); \ - } \ -} while (0) - -#define CDL_PREPEND_ELEM(head, el, add) \ - CDL_PREPEND_ELEM2(head, el, add, prev, next) - -#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - (add)->next->prev = (add); \ - } else { \ - CDL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) - -#define CDL_APPEND_ELEM(head, el, add) \ - CDL_APPEND_ELEM2(head, el, add, prev, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef CDL_INSERT_INORDER2 -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (add)->prev->next = (add); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (add)->next->prev = (add); \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) -#endif /* NO_DECLTYPE */ - -#endif /* UTLIST_H */ diff --git a/libs/libmosquitto/libmosquitto.vcxproj b/libs/libmosquitto/libmosquitto.vcxproj deleted file mode 100644 index a9154fd38c..0000000000 --- a/libs/libmosquitto/libmosquitto.vcxproj +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{6D19209B-ECE7-4B9C-941C-1AA2B484F199}</ProjectGuid> - <ProjectName>libmosquitto</ProjectName> - <TargetName>libmosquitto</TargetName> - </PropertyGroup> - <Import Project="$(ProjectDir)..\..\build\vc.common\lib.props" /> - <ItemDefinitionGroup> - <ClCompile> - <AdditionalIncludeDirectories>.\include\;.\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>libmosquitto_EXPORTS;WIN32;WITH_TLS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> -</Project>
\ No newline at end of file diff --git a/libs/libmosquitto/libmosquitto.vcxproj.filters b/libs/libmosquitto/libmosquitto.vcxproj.filters deleted file mode 100644 index 6f18071f64..0000000000 --- a/libs/libmosquitto/libmosquitto.vcxproj.filters +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" /> - <ItemGroup> - <ClInclude Include="src\*.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClCompile Include="src\*.cpp;src\*.cxx"> - <Filter>Source Files</Filter> - </ClCompile> - <ResourceCompile Include="res\*.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - <None Include="res\*.ico;res\*.bmp;res\*.cur"> - <Filter>Resource Files</Filter> - </None> - </ItemGroup> -</Project> diff --git a/libs/libmosquitto/src/actions.c b/libs/libmosquitto/src/actions.c deleted file mode 100644 index a5bf673fa9..0000000000 --- a/libs/libmosquitto/src/actions.c +++ /dev/null @@ -1,260 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <string.h> - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "send_mosq.h" -#include "util_mosq.h" - - -int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain) -{ - return mosquitto_publish_v5(mosq, mid, topic, payloadlen, payload, qos, retain, NULL); -} - -int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain, const mosquitto_property *properties) -{ - struct mosquitto_message_all *message; - uint16_t local_mid; - const mosquitto_property *p; - const mosquitto_property *outgoing_properties = NULL; - mosquitto_property local_property; - bool have_topic_alias; - int rc; - int tlen = 0; - uint32_t remaining_length; - - if(!mosq || qos<0 || qos>2) return MOSQ_ERR_INVAL; - if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; - if(qos > mosq->maximum_qos) return MOSQ_ERR_QOS_NOT_SUPPORTED; - - if(properties){ - if(properties->client_generated){ - outgoing_properties = properties; - }else{ - memcpy(&local_property, properties, sizeof(mosquitto_property)); - local_property.client_generated = true; - local_property.next = NULL; - outgoing_properties = &local_property; - } - rc = mosquitto_property_check_all(CMD_PUBLISH, outgoing_properties); - if(rc) return rc; - } - - if(!topic || STREMPTY(topic)){ - if(topic) topic = NULL; - - if(mosq->protocol == mosq_p_mqtt5){ - p = outgoing_properties; - have_topic_alias = false; - while(p){ - if(p->identifier == MQTT_PROP_TOPIC_ALIAS){ - have_topic_alias = true; - break; - } - p = p->next; - } - if(have_topic_alias == false){ - return MOSQ_ERR_INVAL; - } - }else{ - return MOSQ_ERR_INVAL; - } - }else{ - tlen = strlen(topic); - if(mosquitto_validate_utf8(topic, tlen)) return MOSQ_ERR_MALFORMED_UTF8; - if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; - if(mosquitto_pub_topic_check(topic) != MOSQ_ERR_SUCCESS){ - return MOSQ_ERR_INVAL; - } - } - - if(mosq->maximum_packet_size > 0){ - remaining_length = 1 + 2+tlen + payloadlen + property__get_length_all(outgoing_properties); - if(qos > 0){ - remaining_length++; - } - if(packet__check_oversize(mosq, remaining_length)){ - return MOSQ_ERR_OVERSIZE_PACKET; - } - } - - local_mid = mosquitto__mid_generate(mosq); - if(mid){ - *mid = local_mid; - } - - if(qos == 0){ - return send__publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false, outgoing_properties, NULL, 0); - }else{ - message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all)); - if(!message) return MOSQ_ERR_NOMEM; - - message->next = NULL; - message->timestamp = mosquitto_time(); - message->msg.mid = local_mid; - if(topic){ - message->msg.topic = mosquitto__strdup(topic); - if(!message->msg.topic){ - message__cleanup(&message); - return MOSQ_ERR_NOMEM; - } - } - if(payloadlen){ - message->msg.payloadlen = payloadlen; - message->msg.payload = mosquitto__malloc(payloadlen*sizeof(uint8_t)); - if(!message->msg.payload){ - message__cleanup(&message); - return MOSQ_ERR_NOMEM; - } - memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); - }else{ - message->msg.payloadlen = 0; - message->msg.payload = NULL; - } - message->msg.qos = qos; - message->msg.retain = retain; - message->dup = false; - - pthread_mutex_lock(&mosq->msgs_out.mutex); - message->state = mosq_ms_invalid; - message__queue(mosq, message, mosq_md_out); - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_SUCCESS; - } -} - - -int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos) -{ - return mosquitto_subscribe_multiple(mosq, mid, 1, (char *const *const)&sub, qos, 0, NULL); -} - - -int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, int qos, int options, const mosquitto_property *properties) -{ - return mosquitto_subscribe_multiple(mosq, mid, 1, (char *const *const)&sub, qos, options, properties); -} - - -int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, int qos, int options, const mosquitto_property *properties) -{ - const mosquitto_property *outgoing_properties = NULL; - mosquitto_property local_property; - int i; - int rc; - uint32_t remaining_length = 0; - int slen; - - if(!mosq || !sub_count || !sub) return MOSQ_ERR_INVAL; - if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; - if(qos < 0 || qos > 2) return MOSQ_ERR_INVAL; - if((options & 0x30) == 0x30 || (options & 0xC0) != 0) return MOSQ_ERR_INVAL; - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - - if(properties){ - if(properties->client_generated){ - outgoing_properties = properties; - }else{ - memcpy(&local_property, properties, sizeof(mosquitto_property)); - local_property.client_generated = true; - local_property.next = NULL; - outgoing_properties = &local_property; - } - rc = mosquitto_property_check_all(CMD_SUBSCRIBE, outgoing_properties); - if(rc) return rc; - } - - for(i=0; i<sub_count; i++){ - if(mosquitto_sub_topic_check(sub[i])) return MOSQ_ERR_INVAL; - slen = strlen(sub[i]); - if(mosquitto_validate_utf8(sub[i], slen)) return MOSQ_ERR_MALFORMED_UTF8; - remaining_length += 2+slen + 1; - } - - if(mosq->maximum_packet_size > 0){ - remaining_length += 2 + property__get_length_all(outgoing_properties); - if(packet__check_oversize(mosq, remaining_length)){ - return MOSQ_ERR_OVERSIZE_PACKET; - } - } - - return send__subscribe(mosq, mid, sub_count, sub, qos|options, outgoing_properties); -} - - -int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub) -{ - return mosquitto_unsubscribe_multiple(mosq, mid, 1, (char *const *const)&sub, NULL); -} - -int mosquitto_unsubscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, const mosquitto_property *properties) -{ - return mosquitto_unsubscribe_multiple(mosq, mid, 1, (char *const *const)&sub, properties); -} - -int mosquitto_unsubscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, const mosquitto_property *properties) -{ - const mosquitto_property *outgoing_properties = NULL; - mosquitto_property local_property; - int rc; - int i; - uint32_t remaining_length = 0; - int slen; - - if(!mosq) return MOSQ_ERR_INVAL; - if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - - if(properties){ - if(properties->client_generated){ - outgoing_properties = properties; - }else{ - memcpy(&local_property, properties, sizeof(mosquitto_property)); - local_property.client_generated = true; - local_property.next = NULL; - outgoing_properties = &local_property; - } - rc = mosquitto_property_check_all(CMD_UNSUBSCRIBE, outgoing_properties); - if(rc) return rc; - } - - for(i=0; i<sub_count; i++){ - if(mosquitto_sub_topic_check(sub[i])) return MOSQ_ERR_INVAL; - slen = strlen(sub[i]); - if(mosquitto_validate_utf8(sub[i], slen)) return MOSQ_ERR_MALFORMED_UTF8; - remaining_length += 2+slen; - } - - if(mosq->maximum_packet_size > 0){ - remaining_length += 2 + property__get_length_all(outgoing_properties); - if(packet__check_oversize(mosq, remaining_length)){ - return MOSQ_ERR_OVERSIZE_PACKET; - } - } - - return send__unsubscribe(mosq, mid, sub_count, sub, outgoing_properties); -} - diff --git a/libs/libmosquitto/src/callbacks.c b/libs/libmosquitto/src/callbacks.c deleted file mode 100644 index 17f5161bff..0000000000 --- a/libs/libmosquitto/src/callbacks.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include "mosquitto.h" -#include "mosquitto_internal.h" - - -void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_connect = on_connect; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_connect_with_flags_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_connect_with_flags = on_connect; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_connect_v5_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int, const mosquitto_property *)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_connect_v5 = on_connect; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_disconnect = on_disconnect; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_disconnect_v5_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int, const mosquitto_property *)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_disconnect_v5 = on_disconnect; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_publish = on_publish; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_publish_v5_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int, int, const mosquitto_property *props)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_publish_v5 = on_publish; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_message = on_message; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_message_v5_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *, const mosquitto_property *props)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_message_v5 = on_message; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_subscribe = on_subscribe; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_subscribe_v5_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *, const mosquitto_property *props)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_subscribe_v5 = on_subscribe; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_unsubscribe = on_unsubscribe; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_unsubscribe_v5_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int, const mosquitto_property *props)) -{ - pthread_mutex_lock(&mosq->callback_mutex); - mosq->on_unsubscribe_v5 = on_unsubscribe; - pthread_mutex_unlock(&mosq->callback_mutex); -} - -void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *)) -{ - pthread_mutex_lock(&mosq->log_callback_mutex); - mosq->on_log = on_log; - pthread_mutex_unlock(&mosq->log_callback_mutex); -} - diff --git a/libs/libmosquitto/src/connect.c b/libs/libmosquitto/src/connect.c deleted file mode 100644 index 7543d4af74..0000000000 --- a/libs/libmosquitto/src/connect.c +++ /dev/null @@ -1,330 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <string.h> - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "messages_mosq.h" -#include "memory_mosq.h" -#include "packet_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "send_mosq.h" -#include "socks_mosq.h" -#include "util_mosq.h" - -static char alphanum[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mosquitto_property *properties); -static int mosquitto__connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address); - - -static int mosquitto__connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address) -{ - int i; - int rc; - - if(!mosq) return MOSQ_ERR_INVAL; - if(!host || port <= 0) return MOSQ_ERR_INVAL; - - if(mosq->id == NULL && (mosq->protocol == mosq_p_mqtt31 || mosq->protocol == mosq_p_mqtt311)){ - mosq->id = (char *)mosquitto__calloc(24, sizeof(char)); - if(!mosq->id){ - return MOSQ_ERR_NOMEM; - } - mosq->id[0] = 'm'; - mosq->id[1] = 'o'; - mosq->id[2] = 's'; - mosq->id[3] = 'q'; - mosq->id[4] = '/'; - - rc = util__random_bytes(&mosq->id[5], 18); - if(rc) return rc; - - for(i=5; i<23; i++){ - mosq->id[i] = alphanum[(mosq->id[i]&0x7F)%(sizeof(alphanum)-1)]; - } - } - - mosquitto__free(mosq->host); - mosq->host = mosquitto__strdup(host); - if(!mosq->host) return MOSQ_ERR_NOMEM; - mosq->port = port; - - mosquitto__free(mosq->bind_address); - if(bind_address){ - mosq->bind_address = mosquitto__strdup(bind_address); - if(!mosq->bind_address) return MOSQ_ERR_NOMEM; - } - - mosq->keepalive = keepalive; - mosq->msgs_in.inflight_quota = mosq->msgs_in.inflight_maximum; - mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum; - - if(mosq->sockpairR != INVALID_SOCKET){ - COMPAT_CLOSE(mosq->sockpairR); - mosq->sockpairR = INVALID_SOCKET; - } - if(mosq->sockpairW != INVALID_SOCKET){ - COMPAT_CLOSE(mosq->sockpairW); - mosq->sockpairW = INVALID_SOCKET; - } - - if(net__socketpair(&mosq->sockpairR, &mosq->sockpairW)){ - log__printf(mosq, MOSQ_LOG_WARNING, - "Warning: Unable to open socket pair, outgoing publish commands may be delayed."); - } - - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive) -{ - return mosquitto_connect_bind(mosq, host, port, keepalive, NULL); -} - - -int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address) -{ - return mosquitto_connect_bind_v5(mosq, host, port, keepalive, bind_address, NULL); -} - -int mosquitto_connect_bind_v5(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address, const mosquitto_property *properties) -{ - int rc; - - if(properties){ - rc = mosquitto_property_check_all(CMD_CONNECT, properties); - if(rc) return rc; - } - - rc = mosquitto__connect_init(mosq, host, port, keepalive, bind_address); - if(rc) return rc; - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_new; - pthread_mutex_unlock(&mosq->state_mutex); - - return mosquitto__reconnect(mosq, true, properties); -} - - -int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive) -{ - return mosquitto_connect_bind_async(mosq, host, port, keepalive, NULL); -} - - -int mosquitto_connect_bind_async(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address) -{ - int rc = mosquitto__connect_init(mosq, host, port, keepalive, bind_address); - if(rc) return rc; - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_connect_async; - pthread_mutex_unlock(&mosq->state_mutex); - - return mosquitto__reconnect(mosq, false, NULL); -} - - -int mosquitto_reconnect_async(struct mosquitto *mosq) -{ - return mosquitto__reconnect(mosq, false, NULL); -} - - -int mosquitto_reconnect(struct mosquitto *mosq) -{ - return mosquitto__reconnect(mosq, true, NULL); -} - - -static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mosquitto_property *properties) -{ - const mosquitto_property *outgoing_properties = NULL; - mosquitto_property local_property; - int rc; - struct mosquitto__packet *packet; - if(!mosq) return MOSQ_ERR_INVAL; - if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; - if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; - - if(properties){ - if(properties->client_generated){ - outgoing_properties = properties; - }else{ - memcpy(&local_property, properties, sizeof(mosquitto_property)); - local_property.client_generated = true; - local_property.next = NULL; - outgoing_properties = &local_property; - } - rc = mosquitto_property_check_all(CMD_CONNECT, outgoing_properties); - if(rc) return rc; - } - - pthread_mutex_lock(&mosq->state_mutex); -#ifdef WITH_SOCKS - if(mosq->socks5_host){ - mosq->state = mosq_cs_socks5_new; - }else -#endif - { - mosq->state = mosq_cs_new; - } - pthread_mutex_unlock(&mosq->state_mutex); - - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->last_msg_in = mosquitto_time(); - mosq->next_msg_out = mosq->last_msg_in + mosq->keepalive; - pthread_mutex_unlock(&mosq->msgtime_mutex); - - mosq->ping_t = 0; - - packet__cleanup(&mosq->in_packet); - - pthread_mutex_lock(&mosq->current_out_packet_mutex); - pthread_mutex_lock(&mosq->out_packet_mutex); - - if(mosq->out_packet && !mosq->current_out_packet){ - mosq->current_out_packet = mosq->out_packet; - mosq->out_packet = mosq->out_packet->next; - } - - while(mosq->current_out_packet){ - packet = mosq->current_out_packet; - /* Free data and reset values */ - mosq->current_out_packet = mosq->out_packet; - if(mosq->out_packet){ - mosq->out_packet = mosq->out_packet->next; - } - - packet__cleanup(packet); - mosquitto__free(packet); - } - pthread_mutex_unlock(&mosq->out_packet_mutex); - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - - message__reconnect_reset(mosq); - - if(mosq->sock != INVALID_SOCKET){ - net__socket_close(mosq); //close socket - } - -#ifdef WITH_SOCKS - if(mosq->socks5_host){ - rc = net__socket_connect(mosq, mosq->socks5_host, mosq->socks5_port, mosq->bind_address, blocking); - }else -#endif - { - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_connecting; - pthread_mutex_unlock(&mosq->state_mutex); - rc = net__socket_connect(mosq, mosq->host, mosq->port, mosq->bind_address, blocking); - } - if(rc>0){ - return rc; - } - -#ifdef WITH_SOCKS - if(mosq->socks5_host){ - return socks5__send(mosq); - }else -#endif - { - return send__connect(mosq, mosq->keepalive, mosq->clean_start, outgoing_properties); - } -} - - -int mosquitto_disconnect(struct mosquitto *mosq) -{ - return mosquitto_disconnect_v5(mosq, 0, NULL); -} - -int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties) -{ - const mosquitto_property *outgoing_properties = NULL; - mosquitto_property local_property; - int rc; - if(!mosq) return MOSQ_ERR_INVAL; - if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; - - if(properties){ - if(properties->client_generated){ - outgoing_properties = properties; - }else{ - memcpy(&local_property, properties, sizeof(mosquitto_property)); - local_property.client_generated = true; - local_property.next = NULL; - outgoing_properties = &local_property; - } - rc = mosquitto_property_check_all(CMD_DISCONNECT, outgoing_properties); - if(rc) return rc; - } - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_disconnecting; - pthread_mutex_unlock(&mosq->state_mutex); - - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - return send__disconnect(mosq, reason_code, outgoing_properties); -} - - -void do_client_disconnect(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties) -{ - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_disconnecting; - pthread_mutex_unlock(&mosq->state_mutex); - - net__socket_close(mosq); - - /* Free data and reset values */ - pthread_mutex_lock(&mosq->out_packet_mutex); - mosq->current_out_packet = mosq->out_packet; - if(mosq->out_packet){ - mosq->out_packet = mosq->out_packet->next; - if(!mosq->out_packet){ - mosq->out_packet_last = NULL; - } - } - pthread_mutex_unlock(&mosq->out_packet_mutex); - - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->next_msg_out = mosquitto_time() + mosq->keepalive; - pthread_mutex_unlock(&mosq->msgtime_mutex); - - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_disconnect){ - mosq->in_callback = true; - mosq->on_disconnect(mosq, mosq->userdata, reason_code); - mosq->in_callback = false; - } - if(mosq->on_disconnect_v5){ - mosq->in_callback = true; - mosq->on_disconnect_v5(mosq, mosq->userdata, reason_code, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - pthread_mutex_unlock(&mosq->current_out_packet_mutex); -} - diff --git a/libs/libmosquitto/src/dummypthread.h b/libs/libmosquitto/src/dummypthread.h deleted file mode 100644 index 4207f3d68c..0000000000 --- a/libs/libmosquitto/src/dummypthread.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef DUMMYPTHREAD_H -#define DUMMYPTHREAD_H - -#define pthread_create(A, B, C, D) -#define pthread_join(A, B) -#define pthread_cancel(A) - -#define pthread_mutex_init(A, B) -#define pthread_mutex_destroy(A) -#define pthread_mutex_lock(A) -#define pthread_mutex_unlock(A) - -#endif diff --git a/libs/libmosquitto/src/handle_auth.c b/libs/libmosquitto/src/handle_auth.c deleted file mode 100644 index 5b84d3de31..0000000000 --- a/libs/libmosquitto/src/handle_auth.c +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright (c) 2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <stdio.h> -#include <string.h> - -#include "logging_mosq.h" -#include "mosquitto_internal.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" - - -int handle__auth(struct mosquitto *mosq) -{ - int rc = 0; - uint8_t reason_code; - mosquitto_property *properties = NULL; - - if(!mosq) return MOSQ_ERR_INVAL; - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received AUTH", mosq->id); - - if(mosq->protocol != mosq_p_mqtt5){ - return MOSQ_ERR_PROTOCOL; - } - - if(packet__read_byte(&mosq->in_packet, &reason_code)) return 1; - - rc = property__read_all(CMD_AUTH, &mosq->in_packet, &properties); - if(rc) return rc; - mosquitto_property_free_all(&properties); /* FIXME - TEMPORARY UNTIL PROPERTIES PROCESSED */ - - return MOSQ_ERR_SUCCESS; -} diff --git a/libs/libmosquitto/src/handle_connack.c b/libs/libmosquitto/src/handle_connack.c deleted file mode 100644 index 19b6a66160..0000000000 --- a/libs/libmosquitto/src/handle_connack.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "read_handle.h" - -int handle__connack(struct mosquitto *mosq) -{ - uint8_t connect_flags; - uint8_t reason_code; - int rc; - mosquitto_property *properties = NULL; - char *clientid = NULL; - - assert(mosq); - rc = packet__read_byte(&mosq->in_packet, &connect_flags); - if(rc) return rc; - rc = packet__read_byte(&mosq->in_packet, &reason_code); - if(rc) return rc; - - if(mosq->protocol == mosq_p_mqtt5){ - rc = property__read_all(CMD_CONNACK, &mosq->in_packet, &properties); - if(rc) return rc; - } - - mosquitto_property_read_string(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, &clientid, false); - if(clientid){ - if(mosq->id){ - /* We've been sent a client identifier but already have one. This - * shouldn't happen. */ - free(clientid); - mosquitto_property_free_all(&properties); - return MOSQ_ERR_PROTOCOL; - }else{ - mosq->id = clientid; - clientid = NULL; - } - } - - mosquitto_property_read_byte(properties, MQTT_PROP_MAXIMUM_QOS, &mosq->maximum_qos, false); - mosquitto_property_read_int16(properties, MQTT_PROP_RECEIVE_MAXIMUM, &mosq->msgs_out.inflight_maximum, false); - mosquitto_property_read_int16(properties, MQTT_PROP_SERVER_KEEP_ALIVE, &mosq->keepalive, false); - mosquitto_property_read_int32(properties, MQTT_PROP_MAXIMUM_PACKET_SIZE, &mosq->maximum_packet_size, false); - - mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum; - - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code); - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_connect){ - mosq->in_callback = true; - mosq->on_connect(mosq, mosq->userdata, reason_code); - mosq->in_callback = false; - } - if(mosq->on_connect_with_flags){ - mosq->in_callback = true; - mosq->on_connect_with_flags(mosq, mosq->userdata, reason_code, connect_flags); - mosq->in_callback = false; - } - if(mosq->on_connect_v5){ - mosq->in_callback = true; - mosq->on_connect_v5(mosq, mosq->userdata, reason_code, connect_flags, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - mosquitto_property_free_all(&properties); - - switch(reason_code){ - case 0: - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state != mosq_cs_disconnecting){ - mosq->state = mosq_cs_connected; - } - pthread_mutex_unlock(&mosq->state_mutex); - message__retry_check(mosq); - return MOSQ_ERR_SUCCESS; - case 1: - case 2: - case 3: - case 4: - case 5: - return MOSQ_ERR_CONN_REFUSED; - default: - return MOSQ_ERR_PROTOCOL; - } -} - diff --git a/libs/libmosquitto/src/handle_disconnect.c b/libs/libmosquitto/src/handle_disconnect.c deleted file mode 100644 index 0ec1c8b3cb..0000000000 --- a/libs/libmosquitto/src/handle_disconnect.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright (c) 2009-2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <stdio.h> -#include <string.h> - -#include "logging_mosq.h" -#include "mqtt_protocol.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" -#include "util_mosq.h" - -int handle__disconnect(struct mosquitto *mosq) -{ - int rc; - uint8_t reason_code; - mosquitto_property *properties = NULL; - - if(!mosq){ - return MOSQ_ERR_INVAL; - } - - if(mosq->protocol != mosq_p_mqtt5){ - return MOSQ_ERR_PROTOCOL; - } - - rc = packet__read_byte(&mosq->in_packet, &reason_code); - if(rc) return rc; - - if(mosq->in_packet.remaining_length > 2){ - rc = property__read_all(CMD_DISCONNECT, &mosq->in_packet, &properties); - if(rc) return rc; - mosquitto_property_free_all(&properties); - } - - log__printf(mosq, MOSQ_LOG_DEBUG, "Received DISCONNECT (%d)", reason_code); - - do_client_disconnect(mosq, reason_code, properties); - - mosquitto_property_free_all(&properties); - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/handle_ping.c b/libs/libmosquitto/src/handle_ping.c deleted file mode 100644 index 56d89a3c3f..0000000000 --- a/libs/libmosquitto/src/handle_ping.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" - -int handle__pingreq(struct mosquitto *mosq) -{ - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received PINGREQ from %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGREQ", mosq->id); -#endif - return send__pingresp(mosq); -} - -int handle__pingresp(struct mosquitto *mosq) -{ - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - - mosq->ping_t = 0; /* No longer waiting for a PINGRESP. */ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGRESP", mosq->id); -#endif - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/handle_pubackcomp.c b/libs/libmosquitto/src/handle_pubackcomp.c deleted file mode 100644 index 67921494e2..0000000000 --- a/libs/libmosquitto/src/handle_pubackcomp.c +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" - - -#ifdef WITH_BROKER -int handle__pubackcomp(struct mosquitto_db *db, struct mosquitto *mosq, const char *type) -#else -int handle__pubackcomp(struct mosquitto *mosq, const char *type) -#endif -{ - uint8_t reason_code = 0; - uint16_t mid; - int rc; - mosquitto_property *properties = NULL; - int qos; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - - pthread_mutex_lock(&mosq->msgs_out.mutex); - util__increment_send_quota(mosq); - pthread_mutex_unlock(&mosq->msgs_out.mutex); - - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc) return rc; - qos = type[3] == 'A'?1:2; /* pubAck or pubComp */ - if(mid == 0) return MOSQ_ERR_PROTOCOL; - - if(mosq->protocol == mosq_p_mqtt5 && mosq->in_packet.remaining_length > 2){ - rc = packet__read_byte(&mosq->in_packet, &reason_code); - if(rc) return rc; - - if(mosq->in_packet.remaining_length > 3){ - rc = property__read_all(CMD_PUBACK, &mosq->in_packet, &properties); - if(rc) return rc; - } - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d, RC:%d)", type, mosq->id, mid, reason_code); - - /* Immediately free, we don't do anything with Reason String or User Property at the moment */ - mosquitto_property_free_all(&properties); - - rc = db__message_delete_outgoing(db, mosq, mid, mosq_ms_wait_for_pubcomp, qos); - if(rc == MOSQ_ERR_NOT_FOUND){ - log__printf(mosq, MOSQ_LOG_WARNING, "Warning: Received %s from %s for an unknown packet identifier %d.", type, mosq->id, mid); - return MOSQ_ERR_SUCCESS; - }else{ - return rc; - } -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d, RC:%d)", mosq->id, type, mid, reason_code); - - rc = message__delete(mosq, mid, mosq_md_out, qos); - if(rc){ - return rc; - }else{ - /* Only inform the client the message has been sent once. */ - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_publish){ - mosq->in_callback = true; - mosq->on_publish(mosq, mosq->userdata, mid); - mosq->in_callback = false; - } - if(mosq->on_publish_v5){ - mosq->in_callback = true; - mosq->on_publish_v5(mosq, mosq->userdata, mid, reason_code, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - mosquitto_property_free_all(&properties); - } - pthread_mutex_lock(&mosq->msgs_out.mutex); - message__release_to_inflight(mosq, mosq_md_out); - pthread_mutex_unlock(&mosq->msgs_out.mutex); - - return MOSQ_ERR_SUCCESS; -#endif -} - diff --git a/libs/libmosquitto/src/handle_publish.c b/libs/libmosquitto/src/handle_publish.c deleted file mode 100644 index 8c93e3cefb..0000000000 --- a/libs/libmosquitto/src/handle_publish.c +++ /dev/null @@ -1,167 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "messages_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "util_mosq.h" - - -int handle__publish(struct mosquitto *mosq) -{ - uint8_t header; - struct mosquitto_message_all *message; - int rc = 0; - uint16_t mid; - int slen; - mosquitto_property *properties = NULL; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - - message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all)); - if(!message) return MOSQ_ERR_NOMEM; - - header = mosq->in_packet.command; - - message->dup = (header & 0x08)>>3; - message->msg.qos = (header & 0x06)>>1; - message->msg.retain = (header & 0x01); - - rc = packet__read_string(&mosq->in_packet, &message->msg.topic, &slen); - if(rc){ - message__cleanup(&message); - return rc; - } - if(!slen){ - message__cleanup(&message); - return MOSQ_ERR_PROTOCOL; - } - - if(message->msg.qos > 0){ - if(mosq->protocol == mosq_p_mqtt5){ - if(mosq->msgs_in.inflight_quota == 0){ - message__cleanup(&message); - /* FIXME - should send a DISCONNECT here */ - return MOSQ_ERR_PROTOCOL; - } - } - - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc){ - message__cleanup(&message); - return rc; - } - if(mid == 0){ - message__cleanup(&message); - return MOSQ_ERR_PROTOCOL; - } - message->msg.mid = (int)mid; - } - - if(mosq->protocol == mosq_p_mqtt5){ - rc = property__read_all(CMD_PUBLISH, &mosq->in_packet, &properties); - if(rc) return rc; - } - - message->msg.payloadlen = mosq->in_packet.remaining_length - mosq->in_packet.pos; - if(message->msg.payloadlen){ - message->msg.payload = mosquitto__calloc(message->msg.payloadlen+1, sizeof(uint8_t)); - if(!message->msg.payload){ - message__cleanup(&message); - mosquitto_property_free_all(&properties); - return MOSQ_ERR_NOMEM; - } - rc = packet__read_bytes(&mosq->in_packet, message->msg.payload, message->msg.payloadlen); - if(rc){ - message__cleanup(&message); - mosquitto_property_free_all(&properties); - return rc; - } - } - log__printf(mosq, MOSQ_LOG_DEBUG, - "Client %s received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", - mosq->id, message->dup, message->msg.qos, message->msg.retain, - message->msg.mid, message->msg.topic, - (long)message->msg.payloadlen); - - message->timestamp = mosquitto_time(); - switch(message->msg.qos){ - case 0: - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_message){ - mosq->in_callback = true; - mosq->on_message(mosq, mosq->userdata, &message->msg); - mosq->in_callback = false; - } - if(mosq->on_message_v5){ - mosq->in_callback = true; - mosq->on_message_v5(mosq, mosq->userdata, &message->msg, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - message__cleanup(&message); - mosquitto_property_free_all(&properties); - return MOSQ_ERR_SUCCESS; - case 1: - util__decrement_receive_quota(mosq); - rc = send__puback(mosq, message->msg.mid, 0); - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_message){ - mosq->in_callback = true; - mosq->on_message(mosq, mosq->userdata, &message->msg); - mosq->in_callback = false; - } - if(mosq->on_message_v5){ - mosq->in_callback = true; - mosq->on_message_v5(mosq, mosq->userdata, &message->msg, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - message__cleanup(&message); - mosquitto_property_free_all(&properties); - return rc; - case 2: - util__decrement_receive_quota(mosq); - rc = send__pubrec(mosq, message->msg.mid, 0); - pthread_mutex_lock(&mosq->msgs_in.mutex); - message->state = mosq_ms_wait_for_pubrel; - message__queue(mosq, message, mosq_md_in); - pthread_mutex_unlock(&mosq->msgs_in.mutex); - mosquitto_property_free_all(&properties); - return rc; - default: - message__cleanup(&message); - mosquitto_property_free_all(&properties); - return MOSQ_ERR_PROTOCOL; - } -} - diff --git a/libs/libmosquitto/src/handle_pubrec.c b/libs/libmosquitto/src/handle_pubrec.c deleted file mode 100644 index 81f1b4962a..0000000000 --- a/libs/libmosquitto/src/handle_pubrec.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" - -int handle__pubrec(struct mosquitto_db *db, struct mosquitto *mosq) -{ - uint8_t reason_code = 0; - uint16_t mid; - int rc; - mosquitto_property *properties = NULL; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc) return rc; - if(mid == 0) return MOSQ_ERR_PROTOCOL; - - if(mosq->protocol == mosq_p_mqtt5 && mosq->in_packet.remaining_length > 2){ - rc = packet__read_byte(&mosq->in_packet, &reason_code); - if(rc) return rc; - - if(mosq->in_packet.remaining_length > 3){ - rc = property__read_all(CMD_PUBREC, &mosq->in_packet, &properties); - if(rc) return rc; - /* Immediately free, we don't do anything with Reason String or User Property at the moment */ - mosquitto_property_free_all(&properties); - } - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREC from %s (Mid: %d)", mosq->id, mid); - - if(reason_code < 0x80){ - rc = db__message_update_outgoing(mosq, mid, mosq_ms_wait_for_pubcomp, 2); - }else{ - return db__message_delete_outgoing(db, mosq, mid, mosq_ms_wait_for_pubrec, 2); - } -#else - UNUSED(db); - - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREC (Mid: %d)", mosq->id, mid); - - if(reason_code < 0x80 || mosq->protocol != mosq_p_mqtt5){ - rc = message__out_update(mosq, mid, mosq_ms_wait_for_pubcomp, 2); - }else{ - if(!message__delete(mosq, mid, mosq_md_out, 2)){ - /* Only inform the client the message has been sent once. */ - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_publish_v5){ - mosq->in_callback = true; - mosq->on_publish_v5(mosq, mosq->userdata, mid, reason_code, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - } - util__increment_send_quota(mosq); - pthread_mutex_lock(&mosq->msgs_out.mutex); - message__release_to_inflight(mosq, mosq_md_out); - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_SUCCESS; - } -#endif - if(rc == MOSQ_ERR_NOT_FOUND){ - log__printf(mosq, MOSQ_LOG_WARNING, "Warning: Received PUBREC from %s for an unknown packet identifier %d.", mosq->id, mid); - }else if(rc != MOSQ_ERR_SUCCESS){ - return rc; - } - rc = send__pubrel(mosq, mid); - if(rc) return rc; - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/handle_pubrel.c b/libs/libmosquitto/src/handle_pubrel.c deleted file mode 100644 index d4a90652d2..0000000000 --- a/libs/libmosquitto/src/handle_pubrel.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" - - -int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq) -{ - uint8_t reason_code; - uint16_t mid; -#ifndef WITH_BROKER - struct mosquitto_message_all *message = NULL; -#endif - int rc; - mosquitto_property *properties = NULL; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - - if(mosq->protocol != mosq_p_mqtt31){ - if((mosq->in_packet.command&0x0F) != 0x02){ - return MOSQ_ERR_PROTOCOL; - } - } - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc) return rc; - if(mid == 0) return MOSQ_ERR_PROTOCOL; - - if(mosq->protocol == mosq_p_mqtt5 && mosq->in_packet.remaining_length > 2){ - rc = packet__read_byte(&mosq->in_packet, &reason_code); - if(rc) return rc; - - if(mosq->in_packet.remaining_length > 3){ - rc = property__read_all(CMD_PUBREL, &mosq->in_packet, &properties); - if(rc) return rc; - } - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", mosq->id, mid); - - /* Immediately free, we don't do anything with Reason String or User Property at the moment */ - mosquitto_property_free_all(&properties); - - rc = db__message_release_incoming(db, mosq, mid); - if(rc == MOSQ_ERR_PROTOCOL){ - return rc; - }else if(rc != MOSQ_ERR_SUCCESS){ - /* Message not found. Still send a PUBCOMP anyway because this could be - * due to a repeated PUBREL after a client has reconnected. */ - } - - rc = send__pubcomp(mosq, mid); - if(rc) return rc; -#else - UNUSED(db); - - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", mosq->id, mid); - - rc = send__pubcomp(mosq, mid); - if(rc){ - message__remove(mosq, mid, mosq_md_in, &message, 2); - return rc; - } - - rc = message__remove(mosq, mid, mosq_md_in, &message, 2); - if(rc){ - return rc; - }else{ - /* Only pass the message on if we have removed it from the queue - this - * prevents multiple callbacks for the same message. */ - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_message){ - mosq->in_callback = true; - mosq->on_message(mosq, mosq->userdata, &message->msg); - mosq->in_callback = false; - } - if(mosq->on_message_v5){ - mosq->in_callback = true; - mosq->on_message_v5(mosq, mosq->userdata, &message->msg, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - mosquitto_property_free_all(&properties); - message__cleanup(&message); - } -#endif - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/handle_suback.c b/libs/libmosquitto/src/handle_suback.c deleted file mode 100644 index dadebcd79f..0000000000 --- a/libs/libmosquitto/src/handle_suback.c +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" - - -int handle__suback(struct mosquitto *mosq) -{ - uint16_t mid; - uint8_t qos; - int *granted_qos; - int qos_count; - int i = 0; - int rc; - mosquitto_property *properties = NULL; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id); -#endif - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc) return rc; - if(mid == 0) return MOSQ_ERR_PROTOCOL; - - if(mosq->protocol == mosq_p_mqtt5){ - rc = property__read_all(CMD_SUBACK, &mosq->in_packet, &properties); - if(rc) return rc; - } - - qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos; - granted_qos = mosquitto__malloc(qos_count*sizeof(int)); - if(!granted_qos) return MOSQ_ERR_NOMEM; - while(mosq->in_packet.pos < mosq->in_packet.remaining_length){ - rc = packet__read_byte(&mosq->in_packet, &qos); - if(rc){ - mosquitto__free(granted_qos); - return rc; - } - granted_qos[i] = (int)qos; - i++; - } -#ifdef WITH_BROKER - /* Immediately free, we don't do anything with Reason String or User Property at the moment */ - mosquitto_property_free_all(&properties); -#else - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_subscribe){ - mosq->in_callback = true; - mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos); - mosq->in_callback = false; - } - if(mosq->on_subscribe_v5){ - mosq->in_callback = true; - mosq->on_subscribe_v5(mosq, mosq->userdata, mid, qos_count, granted_qos, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - mosquitto_property_free_all(&properties); -#endif - mosquitto__free(granted_qos); - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/handle_unsuback.c b/libs/libmosquitto/src/handle_unsuback.c deleted file mode 100644 index 3ced0e5280..0000000000 --- a/libs/libmosquitto/src/handle_unsuback.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" - - -int handle__unsuback(struct mosquitto *mosq) -{ - uint16_t mid; - int rc; - mosquitto_property *properties = NULL; - - assert(mosq); - - if(mosq->state != mosq_cs_connected){ - return MOSQ_ERR_PROTOCOL; - } - -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBACK from %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received UNSUBACK", mosq->id); -#endif - rc = packet__read_uint16(&mosq->in_packet, &mid); - if(rc) return rc; - if(mid == 0) return MOSQ_ERR_PROTOCOL; - - if(mosq->protocol == mosq_p_mqtt5){ - rc = property__read_all(CMD_UNSUBACK, &mosq->in_packet, &properties); - if(rc) return rc; - } - -#ifdef WITH_BROKER - /* Immediately free, we don't do anything with Reason String or User Property at the moment */ - mosquitto_property_free_all(&properties); -#else - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_unsubscribe){ - mosq->in_callback = true; - mosq->on_unsubscribe(mosq, mosq->userdata, mid); - mosq->in_callback = false; - } - if(mosq->on_unsubscribe_v5){ - mosq->in_callback = true; - mosq->on_unsubscribe_v5(mosq, mosq->userdata, mid, properties); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - mosquitto_property_free_all(&properties); -#endif - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/helpers.c b/libs/libmosquitto/src/helpers.c deleted file mode 100644 index 0f60501edc..0000000000 --- a/libs/libmosquitto/src/helpers.c +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright (c) 2016-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <errno.h> -#include <stdbool.h> - -#include "mosquitto.h" -#include "mosquitto_internal.h" - -struct userdata__callback { - const char *topic; - int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *); - void *userdata; - int qos; - int rc; -}; - -struct userdata__simple { - struct mosquitto_message *messages; - int max_msg_count; - int message_count; - bool want_retained; -}; - - -static void on_connect(struct mosquitto *mosq, void *obj, int rc) -{ - struct userdata__callback *userdata = obj; - - UNUSED(rc); - - mosquitto_subscribe(mosq, NULL, userdata->topic, userdata->qos); -} - - -static void on_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) -{ - int rc; - struct userdata__callback *userdata = obj; - - rc = userdata->callback(mosq, userdata->userdata, message); - if(rc){ - mosquitto_disconnect(mosq); - } -} - -static int on_message_simple(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) -{ - struct userdata__simple *userdata = obj; - int rc; - - if(userdata->max_msg_count == 0){ - return 0; - } - - /* Don't process stale retained messages if 'want_retained' was false */ - if(!userdata->want_retained && message->retain){ - return 0; - } - - userdata->max_msg_count--; - - rc = mosquitto_message_copy(&userdata->messages[userdata->message_count], message); - if(rc){ - return rc; - } - userdata->message_count++; - if(userdata->max_msg_count == 0){ - mosquitto_disconnect(mosq); - } - return 0; -} - - -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) -{ - struct userdata__simple userdata; - int rc; - int i; - - if(!topic || msg_count < 1 || !messages){ - return MOSQ_ERR_INVAL; - } - - *messages = NULL; - - userdata.messages = calloc(sizeof(struct mosquitto_message), msg_count); - if(!userdata.messages){ - return MOSQ_ERR_NOMEM; - } - userdata.message_count = 0; - userdata.max_msg_count = msg_count; - userdata.want_retained = want_retained; - - rc = mosquitto_subscribe_callback( - on_message_simple, &userdata, - topic, qos, - host, port, - client_id, keepalive, clean_session, - username, password, - will, tls); - - if(!rc && userdata.max_msg_count == 0){ - *messages = userdata.messages; - return MOSQ_ERR_SUCCESS; - }else{ - for(i=0; i<msg_count; i++){ - mosquitto_message_free_contents(&userdata.messages[i]); - } - free(userdata.messages); - userdata.messages = NULL; - return rc; - } -} - - -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) -{ - struct mosquitto *mosq; - struct userdata__callback cb_userdata; - int rc; - - if(!callback || !topic){ - return MOSQ_ERR_INVAL; - } - - cb_userdata.topic = topic; - cb_userdata.qos = qos; - cb_userdata.rc = 0; - cb_userdata.userdata = userdata; - cb_userdata.callback = callback; - - mosq = mosquitto_new(client_id, clean_session, &cb_userdata); - if(!mosq){ - return MOSQ_ERR_NOMEM; - } - - if(will){ - rc = mosquitto_will_set(mosq, will->topic, will->payloadlen, will->payload, will->qos, will->retain); - if(rc){ - mosquitto_destroy(mosq); - return rc; - } - } - if(username){ - rc = mosquitto_username_pw_set(mosq, username, password); - if(rc){ - mosquitto_destroy(mosq); - return rc; - } - } - if(tls){ - rc = mosquitto_tls_set(mosq, tls->cafile, tls->capath, tls->certfile, tls->keyfile, tls->pw_callback); - if(rc){ - mosquitto_destroy(mosq); - return rc; - } - rc = mosquitto_tls_opts_set(mosq, tls->cert_reqs, tls->tls_version, tls->ciphers); - if(rc){ - mosquitto_destroy(mosq); - return rc; - } - } - - mosquitto_connect_callback_set(mosq, on_connect); - mosquitto_message_callback_set(mosq, on_message_callback); - - rc = mosquitto_connect(mosq, host, port, keepalive); - if(rc){ - mosquitto_destroy(mosq); - return rc; - } - rc = mosquitto_loop_forever(mosq, -1, 1); - mosquitto_destroy(mosq); - if(cb_userdata.rc){ - rc = cb_userdata.rc; - } - //if(!rc && cb_userdata.max_msg_count == 0){ - //return MOSQ_ERR_SUCCESS; - //}else{ - //return rc; - //} - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/logging_mosq.c b/libs/libmosquitto/src/logging_mosq.c deleted file mode 100644 index eab6356239..0000000000 --- a/libs/libmosquitto/src/logging_mosq.c +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - -#include "mosquitto_internal.h" -#include "mosquitto.h" -#include "memory_mosq.h" - -int log__printf(struct mosquitto *mosq, int priority, const char *fmt, ...) -{ - va_list va; - char *s; - int len; - - assert(mosq); - assert(fmt); - - pthread_mutex_lock(&mosq->log_callback_mutex); - if(mosq->on_log){ - len = strlen(fmt) + 500; - s = mosquitto__malloc(len*sizeof(char)); - if(!s){ - pthread_mutex_unlock(&mosq->log_callback_mutex); - return MOSQ_ERR_NOMEM; - } - - va_start(va, fmt); - vsnprintf(s, len, fmt, va); - va_end(va); - s[len-1] = '\0'; /* Ensure string is null terminated. */ - - mosq->on_log(mosq, mosq->userdata, priority, s); - - mosquitto__free(s); - } - pthread_mutex_unlock(&mosq->log_callback_mutex); - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/logging_mosq.h b/libs/libmosquitto/src/logging_mosq.h deleted file mode 100644 index c3cc29d9ee..0000000000 --- a/libs/libmosquitto/src/logging_mosq.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 LOGGING_MOSQ_H -#define LOGGING_MOSQ_H - -#include "mosquitto.h" - -int log__printf(struct mosquitto *mosq, int priority, const char *fmt, ...); - -#endif diff --git a/libs/libmosquitto/src/loop.c b/libs/libmosquitto/src/loop.c deleted file mode 100644 index 2342c945aa..0000000000 --- a/libs/libmosquitto/src/loop.c +++ /dev/null @@ -1,390 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <errno.h> -#ifndef WIN32 -#include <sys/select.h> -#include <time.h> -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "socks_mosq.h" -#include "tls_mosq.h" -#include "util_mosq.h" - -#if !defined(WIN32) && !defined(__SYMBIAN32__) -#define HAVE_PSELECT -#endif - -int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets) -{ -#ifdef HAVE_PSELECT - struct timespec local_timeout; -#else - struct timeval local_timeout; -#endif - fd_set readfds, writefds; - int fdcount; - int rc; - char pairbuf; - int maxfd = 0; - time_t now; - - if(!mosq || max_packets < 1) return MOSQ_ERR_INVAL; -#ifndef WIN32 - if(mosq->sock >= FD_SETSIZE || mosq->sockpairR >= FD_SETSIZE){ - return MOSQ_ERR_INVAL; - } -#endif - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - if(mosq->sock != INVALID_SOCKET){ - maxfd = mosq->sock; - FD_SET(mosq->sock, &readfds); - pthread_mutex_lock(&mosq->current_out_packet_mutex); - pthread_mutex_lock(&mosq->out_packet_mutex); - if(mosq->out_packet || mosq->current_out_packet){ - FD_SET(mosq->sock, &writefds); - } -#ifdef WITH_TLS - if(mosq->ssl){ - if(mosq->want_write){ - FD_SET(mosq->sock, &writefds); - }else if(mosq->want_connect){ - /* Remove possible FD_SET from above, we don't want to check - * for writing if we are still connecting, unless want_write is - * definitely set. The presence of outgoing packets does not - * matter yet. */ - FD_CLR(mosq->sock, &writefds); - } - } -#endif - pthread_mutex_unlock(&mosq->out_packet_mutex); - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - }else{ -#ifdef WITH_SRV - if(mosq->achan){ - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state == mosq_cs_connect_srv){ - rc = ares_fds(mosq->achan, &readfds, &writefds); - if(rc > maxfd){ - maxfd = rc; - } - }else{ - pthread_mutex_unlock(&mosq->state_mutex); - return MOSQ_ERR_NO_CONN; - } - pthread_mutex_unlock(&mosq->state_mutex); - } -#else - return MOSQ_ERR_NO_CONN; -#endif - } - if(mosq->sockpairR != INVALID_SOCKET){ - /* sockpairR is used to break out of select() before the timeout, on a - * call to publish() etc. */ - FD_SET(mosq->sockpairR, &readfds); - if(mosq->sockpairR > maxfd){ - maxfd = mosq->sockpairR; - } - } - - if(timeout < 0){ - timeout = 1000; - } - - now = mosquitto_time(); - if(mosq->next_msg_out && now + timeout/1000 > mosq->next_msg_out){ - timeout = (mosq->next_msg_out - now)*1000; - } - - if(timeout < 0){ - /* There has been a delay somewhere which means we should have already - * sent a message. */ - timeout = 0; - } - - local_timeout.tv_sec = timeout/1000; -#ifdef HAVE_PSELECT - local_timeout.tv_nsec = (timeout-local_timeout.tv_sec*1000)*1e6; -#else - local_timeout.tv_usec = (timeout-local_timeout.tv_sec*1000)*1000; -#endif - -#ifdef HAVE_PSELECT - fdcount = pselect(maxfd+1, &readfds, &writefds, NULL, &local_timeout, NULL); -#else - fdcount = select(maxfd+1, &readfds, &writefds, NULL, &local_timeout); -#endif - if(fdcount == -1){ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EINTR){ - return MOSQ_ERR_SUCCESS; - }else{ - return MOSQ_ERR_ERRNO; - } - }else{ - if(mosq->sock != INVALID_SOCKET){ - if(FD_ISSET(mosq->sock, &readfds)){ - rc = mosquitto_loop_read(mosq, max_packets); - if(rc || mosq->sock == INVALID_SOCKET){ - return rc; - } - } - if(mosq->sockpairR != INVALID_SOCKET && FD_ISSET(mosq->sockpairR, &readfds)){ -#ifndef WIN32 - if(read(mosq->sockpairR, &pairbuf, 1) == 0){ - } -#else - recv(mosq->sockpairR, &pairbuf, 1, 0); -#endif - /* Fake write possible, to stimulate output write even though - * we didn't ask for it, because at that point the publish or - * other command wasn't present. */ - if(mosq->sock != INVALID_SOCKET) - FD_SET(mosq->sock, &writefds); - } - if(mosq->sock != INVALID_SOCKET && FD_ISSET(mosq->sock, &writefds)){ -#ifdef WITH_TLS - if(mosq->want_connect){ - rc = net__socket_connect_tls(mosq); - if(rc) return rc; - }else -#endif - { - rc = mosquitto_loop_write(mosq, max_packets); - if(rc || mosq->sock == INVALID_SOCKET){ - return rc; - } - } - } - } -#ifdef WITH_SRV - if(mosq->achan){ - ares_process(mosq->achan, &readfds, &writefds); - } -#endif - } - return mosquitto_loop_misc(mosq); -} - - -int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets) -{ - int run = 1; - int rc; - unsigned int reconnects = 0; - unsigned long reconnect_delay; -#ifndef WIN32 - struct timespec req, rem; -#endif - - if(!mosq) return MOSQ_ERR_INVAL; - - if(mosq->state == mosq_cs_connect_async){ - mosquitto_reconnect(mosq); - } - - while(run){ - do{ - rc = mosquitto_loop(mosq, timeout, max_packets); - if (reconnects !=0 && rc == MOSQ_ERR_SUCCESS){ - reconnects = 0; - } - }while(run && rc == MOSQ_ERR_SUCCESS); - /* Quit after fatal errors. */ - switch(rc){ - case MOSQ_ERR_NOMEM: - case MOSQ_ERR_PROTOCOL: - case MOSQ_ERR_INVAL: - case MOSQ_ERR_NOT_FOUND: - case MOSQ_ERR_TLS: - case MOSQ_ERR_PAYLOAD_SIZE: - case MOSQ_ERR_NOT_SUPPORTED: - case MOSQ_ERR_AUTH: - case MOSQ_ERR_ACL_DENIED: - case MOSQ_ERR_UNKNOWN: - case MOSQ_ERR_EAI: - case MOSQ_ERR_PROXY: - return rc; - case MOSQ_ERR_ERRNO: - break; - } - if(errno == EPROTO){ - return rc; - } - do{ - rc = MOSQ_ERR_SUCCESS; - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state == mosq_cs_disconnecting){ - run = 0; - pthread_mutex_unlock(&mosq->state_mutex); - }else{ - pthread_mutex_unlock(&mosq->state_mutex); - - if(mosq->reconnect_delay_max > mosq->reconnect_delay){ - if(mosq->reconnect_exponential_backoff){ - reconnect_delay = mosq->reconnect_delay*(reconnects+1)*(reconnects+1); - }else{ - reconnect_delay = mosq->reconnect_delay*(reconnects+1); - } - }else{ - reconnect_delay = mosq->reconnect_delay; - } - - if(reconnect_delay > mosq->reconnect_delay_max){ - reconnect_delay = mosq->reconnect_delay_max; - }else{ - reconnects++; - } - -#ifdef WIN32 - Sleep(reconnect_delay*1000); -#else - req.tv_sec = reconnect_delay; - req.tv_nsec = 0; - while(nanosleep(&req, &rem) == -1 && errno == EINTR){ - req = rem; - } -#endif - - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state == mosq_cs_disconnecting){ - run = 0; - pthread_mutex_unlock(&mosq->state_mutex); - }else{ - pthread_mutex_unlock(&mosq->state_mutex); - rc = mosquitto_reconnect(mosq); - } - } - }while(run && rc != MOSQ_ERR_SUCCESS); - } - return rc; -} - - -int mosquitto_loop_misc(struct mosquitto *mosq) -{ - if(!mosq) return MOSQ_ERR_INVAL; - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - - return mosquitto__check_keepalive(mosq); -} - - -static int mosquitto__loop_rc_handle(struct mosquitto *mosq, int rc) -{ - if(rc){ - net__socket_close(mosq); - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state == mosq_cs_disconnecting){ - rc = MOSQ_ERR_SUCCESS; - } - pthread_mutex_unlock(&mosq->state_mutex); - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_disconnect){ - mosq->in_callback = true; - mosq->on_disconnect(mosq, mosq->userdata, rc); - mosq->in_callback = false; - } - if(mosq->on_disconnect_v5){ - mosq->in_callback = true; - mosq->on_disconnect_v5(mosq, mosq->userdata, rc, NULL); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - return rc; - } - return rc; -} - - -int mosquitto_loop_read(struct mosquitto *mosq, int max_packets) -{ - int rc; - int i; - if(max_packets < 1) return MOSQ_ERR_INVAL; - -#ifdef WITH_TLS - if(mosq->want_connect){ - return net__socket_connect_tls(mosq); - } -#endif - - pthread_mutex_lock(&mosq->msgs_out.mutex); - max_packets = mosq->msgs_out.queue_len; - pthread_mutex_unlock(&mosq->msgs_out.mutex); - - pthread_mutex_lock(&mosq->msgs_in.mutex); - max_packets += mosq->msgs_in.queue_len; - pthread_mutex_unlock(&mosq->msgs_in.mutex); - - if(max_packets < 1) max_packets = 1; - /* Queue len here tells us how many messages are awaiting processing and - * have QoS > 0. We should try to deal with that many in this loop in order - * to keep up. */ - for(i=0; i<max_packets || SSL_DATA_PENDING(mosq); i++){ -#ifdef WITH_SOCKS - if(mosq->socks5_host){ - rc = socks5__read(mosq); - }else -#endif - { - rc = packet__read(mosq); - } - if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return mosquitto__loop_rc_handle(mosq, rc); - } - } - return rc; -} - - -int mosquitto_loop_write(struct mosquitto *mosq, int max_packets) -{ - int rc; - int i; - if(max_packets < 1) return MOSQ_ERR_INVAL; - - pthread_mutex_lock(&mosq->msgs_out.mutex); - max_packets = mosq->msgs_out.queue_len; - pthread_mutex_unlock(&mosq->msgs_out.mutex); - - pthread_mutex_lock(&mosq->msgs_in.mutex); - max_packets += mosq->msgs_in.queue_len; - pthread_mutex_unlock(&mosq->msgs_in.mutex); - - if(max_packets < 1) max_packets = 1; - /* Queue len here tells us how many messages are awaiting processing and - * have QoS > 0. We should try to deal with that many in this loop in order - * to keep up. */ - for(i=0; i<max_packets; i++){ - rc = packet__write(mosq); - if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return mosquitto__loop_rc_handle(mosq, rc); - } - } - return rc; -} - diff --git a/libs/libmosquitto/src/memory_mosq.c b/libs/libmosquitto/src/memory_mosq.c deleted file mode 100644 index a9b01e5477..0000000000 --- a/libs/libmosquitto/src/memory_mosq.c +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <stdlib.h> -#include <string.h> - -#include "memory_mosq.h" - -#ifdef REAL_WITH_MEMORY_TRACKING -# if defined(__APPLE__) -# include <malloc/malloc.h> -# define malloc_usable_size malloc_size -# elif defined(__FreeBSD__) -# include <malloc_np.h> -# else -# include <malloc.h> -# endif -#endif - -#ifdef REAL_WITH_MEMORY_TRACKING -static unsigned long memcount = 0; -static unsigned long max_memcount = 0; -#endif - -#ifdef WITH_BROKER -static size_t mem_limit = 0; -void memory__set_limit(size_t lim) -{ - mem_limit = lim; -} -#endif - -void *mosquitto__calloc(size_t nmemb, size_t size) -{ -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem_limit && memcount + size > mem_limit){ - return NULL; - } -#endif - void *mem = calloc(nmemb, size); - -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem){ - memcount += malloc_usable_size(mem); - if(memcount > max_memcount){ - max_memcount = memcount; - } - } -#endif - - return mem; -} - -void mosquitto__free(void *mem) -{ -#ifdef REAL_WITH_MEMORY_TRACKING - if(!mem){ - return; - } - memcount -= malloc_usable_size(mem); -#endif - free(mem); -} - -void *mosquitto__malloc(size_t size) -{ -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem_limit && memcount + size > mem_limit){ - return NULL; - } -#endif - void *mem = malloc(size); - -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem){ - memcount += malloc_usable_size(mem); - if(memcount > max_memcount){ - max_memcount = memcount; - } - } -#endif - - return mem; -} - -#ifdef REAL_WITH_MEMORY_TRACKING -unsigned long mosquitto__memory_used(void) -{ - return memcount; -} - -unsigned long mosquitto__max_memory_used(void) -{ - return max_memcount; -} -#endif - -void *mosquitto__realloc(void *ptr, size_t size) -{ -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem_limit && memcount + size > mem_limit){ - return NULL; - } -#endif - void *mem; -#ifdef REAL_WITH_MEMORY_TRACKING - if(ptr){ - memcount -= malloc_usable_size(ptr); - } -#endif - mem = realloc(ptr, size); - -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem){ - memcount += malloc_usable_size(mem); - if(memcount > max_memcount){ - max_memcount = memcount; - } - } -#endif - - return mem; -} - -char *mosquitto__strdup(const char *s) -{ -#ifdef REAL_WITH_MEMORY_TRACKING - if(mem_limit && memcount + strlen(s) > mem_limit){ - return NULL; - } -#endif - char *str = strdup(s); - -#ifdef REAL_WITH_MEMORY_TRACKING - if(str){ - memcount += malloc_usable_size(str); - if(memcount > max_memcount){ - max_memcount = memcount; - } - } -#endif - - return str; -} - diff --git a/libs/libmosquitto/src/memory_mosq.h b/libs/libmosquitto/src/memory_mosq.h deleted file mode 100644 index 63386a2115..0000000000 --- a/libs/libmosquitto/src/memory_mosq.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 MEMORY_MOSQ_H -#define MEMORY_MOSQ_H - -#include <stdio.h> -#include <sys/types.h> - -#if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) && defined(__GLIBC__) -#define REAL_WITH_MEMORY_TRACKING -#endif - -void *mosquitto__calloc(size_t nmemb, size_t size); -void mosquitto__free(void *mem); -void *mosquitto__malloc(size_t size); -#ifdef REAL_WITH_MEMORY_TRACKING -unsigned long mosquitto__memory_used(void); -unsigned long mosquitto__max_memory_used(void); -#endif -void *mosquitto__realloc(void *ptr, size_t size); -char *mosquitto__strdup(const char *s); - -#ifdef WITH_BROKER -void memory__set_limit(size_t lim); -#endif - -#endif diff --git a/libs/libmosquitto/src/messages_mosq.c b/libs/libmosquitto/src/messages_mosq.c deleted file mode 100644 index bf77f5e64b..0000000000 --- a/libs/libmosquitto/src/messages_mosq.c +++ /dev/null @@ -1,348 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <utlist.h> - -#include "mosquitto_internal.h" -#include "mosquitto.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "util_mosq.h" - -void message__cleanup(struct mosquitto_message_all **message) -{ - struct mosquitto_message_all *msg; - - if(!message || !*message) return; - - msg = *message; - - mosquitto__free(msg->msg.topic); - mosquitto__free(msg->msg.payload); - mosquitto__free(msg); -} - -void message__cleanup_all(struct mosquitto *mosq) -{ - struct mosquitto_message_all *tail, *tmp; - - assert(mosq); - - DL_FOREACH_SAFE(mosq->msgs_in.inflight, tail, tmp){ - DL_DELETE(mosq->msgs_in.inflight, tail); - message__cleanup(&tail); - } - DL_FOREACH_SAFE(mosq->msgs_out.inflight, tail, tmp){ - DL_DELETE(mosq->msgs_out.inflight, tail); - message__cleanup(&tail); - } -} - -int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src) -{ - if(!dst || !src) return MOSQ_ERR_INVAL; - - dst->mid = src->mid; - dst->topic = mosquitto__strdup(src->topic); - if(!dst->topic) return MOSQ_ERR_NOMEM; - dst->qos = src->qos; - dst->retain = src->retain; - if(src->payloadlen){ - dst->payload = mosquitto__calloc(src->payloadlen+1, sizeof(uint8_t)); - if(!dst->payload){ - mosquitto__free(dst->topic); - return MOSQ_ERR_NOMEM; - } - memcpy(dst->payload, src->payload, src->payloadlen); - dst->payloadlen = src->payloadlen; - }else{ - dst->payloadlen = 0; - dst->payload = NULL; - } - return MOSQ_ERR_SUCCESS; -} - -int message__delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, int qos) -{ - struct mosquitto_message_all *message; - int rc; - assert(mosq); - - rc = message__remove(mosq, mid, dir, &message, qos); - if(rc == MOSQ_ERR_SUCCESS){ - message__cleanup(&message); - } - return rc; -} - -void mosquitto_message_free(struct mosquitto_message **message) -{ - struct mosquitto_message *msg; - - if(!message || !*message) return; - - msg = *message; - - mosquitto__free(msg->topic); - mosquitto__free(msg->payload); - mosquitto__free(msg); -} - -void mosquitto_message_free_contents(struct mosquitto_message *message) -{ - if(!message) return; - - mosquitto__free(message->topic); - mosquitto__free(message->payload); -} - -int message__queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir) -{ - /* mosq->*_message_mutex should be locked before entering this function */ - assert(mosq); - assert(message); - assert(message->msg.qos != 0); - - if(dir == mosq_md_out){ - DL_APPEND(mosq->msgs_out.inflight, message); - mosq->msgs_out.queue_len++; - }else{ - DL_APPEND(mosq->msgs_in.inflight, message); - mosq->msgs_in.queue_len++; - } - - return message__release_to_inflight(mosq, dir); -} - -void message__reconnect_reset(struct mosquitto *mosq) -{ - struct mosquitto_message_all *message, *tmp; - assert(mosq); - - pthread_mutex_lock(&mosq->msgs_in.mutex); - mosq->msgs_in.inflight_quota = mosq->msgs_in.inflight_maximum; - mosq->msgs_in.queue_len = 0; - DL_FOREACH_SAFE(mosq->msgs_in.inflight, message, tmp){ - mosq->msgs_in.queue_len++; - message->timestamp = 0; - if(message->msg.qos != 2){ - DL_DELETE(mosq->msgs_in.inflight, message); - message__cleanup(&message); - }else{ - /* Message state can be preserved here because it should match - * whatever the client has got. */ - util__decrement_receive_quota(mosq); - } - } - pthread_mutex_unlock(&mosq->msgs_in.mutex); - - - pthread_mutex_lock(&mosq->msgs_out.mutex); - mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum; - mosq->msgs_out.queue_len = 0; - DL_FOREACH_SAFE(mosq->msgs_out.inflight, message, tmp){ - mosq->msgs_out.queue_len++; - - message->timestamp = 0; - if(mosq->msgs_out.inflight_quota != 0){ - util__decrement_send_quota(mosq); - if(message->msg.qos == 1){ - message->state = mosq_ms_publish_qos1; - }else if(message->msg.qos == 2){ - if(message->state == mosq_ms_wait_for_pubrec){ - message->state = mosq_ms_publish_qos2; - }else if(message->state == mosq_ms_wait_for_pubcomp){ - message->state = mosq_ms_resend_pubrel; - } - /* Should be able to preserve state. */ - } - }else{ - message->state = mosq_ms_invalid; - } - } - pthread_mutex_unlock(&mosq->msgs_out.mutex); -} - - -int message__release_to_inflight(struct mosquitto *mosq, enum mosquitto_msg_direction dir) -{ - /* mosq->*_message_mutex should be locked before entering this function */ - struct mosquitto_message_all *cur, *tmp; - int rc = MOSQ_ERR_SUCCESS; - - if(dir == mosq_md_out){ - DL_FOREACH_SAFE(mosq->msgs_out.inflight, cur, tmp){ - if(mosq->msgs_out.inflight_quota > 0){ - if(cur->msg.qos > 0 && cur->state == mosq_ms_invalid){ - if(cur->msg.qos == 1){ - cur->state = mosq_ms_wait_for_puback; - }else if(cur->msg.qos == 2){ - cur->state = mosq_ms_wait_for_pubrec; - } - rc = send__publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup, NULL, NULL, 0); - if(rc){ - return rc; - } - util__decrement_send_quota(mosq); - } - }else{ - return MOSQ_ERR_SUCCESS; - } - } - } - - return rc; -} - - -int message__remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message, int qos) -{ - struct mosquitto_message_all *cur, *tmp; - bool found = false; - assert(mosq); - assert(message); - - if(dir == mosq_md_out){ - pthread_mutex_lock(&mosq->msgs_out.mutex); - - DL_FOREACH_SAFE(mosq->msgs_out.inflight, cur, tmp){ - if(found == false && cur->msg.mid == mid){ - if(cur->msg.qos != qos){ - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_PROTOCOL; - } - DL_DELETE(mosq->msgs_out.inflight, cur); - - *message = cur; - mosq->msgs_out.queue_len--; - found = true; - break; - } - } - pthread_mutex_unlock(&mosq->msgs_out.mutex); - if(found){ - return MOSQ_ERR_SUCCESS; - }else{ - return MOSQ_ERR_NOT_FOUND; - } - }else{ - pthread_mutex_lock(&mosq->msgs_in.mutex); - DL_FOREACH_SAFE(mosq->msgs_in.inflight, cur, tmp){ - if(cur->msg.mid == mid){ - if(cur->msg.qos != qos){ - pthread_mutex_unlock(&mosq->msgs_in.mutex); - return MOSQ_ERR_PROTOCOL; - } - DL_DELETE(mosq->msgs_in.inflight, cur); - *message = cur; - mosq->msgs_in.queue_len--; - found = true; - break; - } - } - - pthread_mutex_unlock(&mosq->msgs_in.mutex); - if(found){ - return MOSQ_ERR_SUCCESS; - }else{ - return MOSQ_ERR_NOT_FOUND; - } - } -} - -void message__retry_check(struct mosquitto *mosq) -{ - struct mosquitto_message_all *msg; - time_t now = mosquitto_time(); - assert(mosq); - -#ifdef WITH_THREADING - pthread_mutex_lock(&mosq->msgs_out.mutex); -#endif - - DL_FOREACH(mosq->msgs_out.inflight, msg){ - switch(msg->state){ - case mosq_ms_publish_qos1: - case mosq_ms_publish_qos2: - msg->timestamp = now; - msg->dup = true; - send__publish(mosq, msg->msg.mid, msg->msg.topic, msg->msg.payloadlen, msg->msg.payload, msg->msg.qos, msg->msg.retain, msg->dup, NULL, NULL, 0); - break; - case mosq_ms_wait_for_pubrel: - msg->timestamp = now; - msg->dup = true; - send__pubrec(mosq, msg->msg.mid, 0); - break; - case mosq_ms_resend_pubrel: - case mosq_ms_wait_for_pubcomp: - msg->timestamp = now; - msg->dup = true; - send__pubrel(mosq, msg->msg.mid); - break; - default: - break; - } - } -#ifdef WITH_THREADING - pthread_mutex_unlock(&mosq->msgs_out.mutex); -#endif -} - - -void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry) -{ - UNUSED(mosq); - UNUSED(message_retry); -} - -int message__out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state, int qos) -{ - struct mosquitto_message_all *message, *tmp; - assert(mosq); - - pthread_mutex_lock(&mosq->msgs_out.mutex); - DL_FOREACH_SAFE(mosq->msgs_out.inflight, message, tmp){ - if(message->msg.mid == mid){ - if(message->msg.qos != qos){ - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_PROTOCOL; - } - message->state = state; - message->timestamp = mosquitto_time(); - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_SUCCESS; - } - } - pthread_mutex_unlock(&mosq->msgs_out.mutex); - return MOSQ_ERR_NOT_FOUND; -} - -int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - mosq->send_maximum = max_inflight_messages; - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/messages_mosq.h b/libs/libmosquitto/src/messages_mosq.h deleted file mode 100644 index 1951bfc79c..0000000000 --- a/libs/libmosquitto/src/messages_mosq.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 MESSAGES_MOSQ_H -#define MESSAGES_MOSQ_H - -#include "mosquitto_internal.h" -#include "mosquitto.h" - -void message__cleanup_all(struct mosquitto *mosq); -void message__cleanup(struct mosquitto_message_all **message); -int message__delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, int qos); -int message__queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir); -void message__reconnect_reset(struct mosquitto *mosq); -int message__release_to_inflight(struct mosquitto *mosq, enum mosquitto_msg_direction dir); -int message__remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message, int qos); -void message__retry_check(struct mosquitto *mosq); -int message__out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state, int qos); - -#endif diff --git a/libs/libmosquitto/src/mosquitto.c b/libs/libmosquitto/src/mosquitto.c deleted file mode 100644 index 4b5768f38b..0000000000 --- a/libs/libmosquitto/src/mosquitto.c +++ /dev/null @@ -1,612 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <errno.h> -#include <signal.h> -#include <string.h> -#ifndef WIN32 -#include <sys/time.h> -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "will_mosq.h" - - -void mosquitto__destroy(struct mosquitto *mosq); - -int mosquitto_lib_version(int *major, int *minor, int *revision) -{ - if(major) *major = LIBMOSQUITTO_MAJOR; - if(minor) *minor = LIBMOSQUITTO_MINOR; - if(revision) *revision = LIBMOSQUITTO_REVISION; - return LIBMOSQUITTO_VERSION_NUMBER; -} - -int mosquitto_lib_init(void) -{ -#ifdef WIN32 - srand(GetTickCount64()); -#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK) - struct timespec tp; - - clock_gettime(CLOCK_MONOTONIC, &tp); - srand(tp.tv_nsec); -#elif defined(__APPLE__) - uint64_t ticks; - - ticks = mach_absolute_time(); - srand((unsigned int)ticks); -#else - struct timeval tv; - - gettimeofday(&tv, NULL); - srand(tv.tv_sec*1000 + tv.tv_usec/1000); -#endif - - return net__init(); -} - -int mosquitto_lib_cleanup(void) -{ - net__cleanup(); - - return MOSQ_ERR_SUCCESS; -} - -struct mosquitto *mosquitto_new(const char *id, bool clean_start, void *userdata) -{ - struct mosquitto *mosq = NULL; - int rc; - - if(clean_start == false && id == NULL){ - errno = EINVAL; - return NULL; - } - -#ifndef WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - mosq = (struct mosquitto *)mosquitto__calloc(1, sizeof(struct mosquitto)); - if(mosq){ - mosq->sock = INVALID_SOCKET; - mosq->sockpairR = INVALID_SOCKET; - mosq->sockpairW = INVALID_SOCKET; -#ifdef WITH_THREADING - mosq->thread_id = pthread_self(); -#endif - rc = mosquitto_reinitialise(mosq, id, clean_start, userdata); - if(rc){ - mosquitto_destroy(mosq); - if(rc == MOSQ_ERR_INVAL){ - errno = EINVAL; - }else if(rc == MOSQ_ERR_NOMEM){ - errno = ENOMEM; - } - return NULL; - } - }else{ - errno = ENOMEM; - } - return mosq; -} - -int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_start, void *userdata) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - if(clean_start == false && id == NULL){ - return MOSQ_ERR_INVAL; - } - - mosquitto__destroy(mosq); - memset(mosq, 0, sizeof(struct mosquitto)); - - if(userdata){ - mosq->userdata = userdata; - }else{ - mosq->userdata = mosq; - } - mosq->protocol = mosq_p_mqtt311; - mosq->sock = INVALID_SOCKET; - mosq->sockpairR = INVALID_SOCKET; - mosq->sockpairW = INVALID_SOCKET; - mosq->keepalive = 60; - mosq->clean_start = clean_start; - if(id){ - if(STREMPTY(id)){ - return MOSQ_ERR_INVAL; - } - if(mosquitto_validate_utf8(id, strlen(id))){ - return MOSQ_ERR_MALFORMED_UTF8; - } - mosq->id = mosquitto__strdup(id); - } - mosq->in_packet.payload = NULL; - packet__cleanup(&mosq->in_packet); - mosq->out_packet = NULL; - mosq->current_out_packet = NULL; - mosq->last_msg_in = mosquitto_time(); - mosq->next_msg_out = mosquitto_time() + mosq->keepalive; - mosq->ping_t = 0; - mosq->last_mid = 0; - mosq->state = mosq_cs_new; - mosq->maximum_qos = 2; - mosq->msgs_in.inflight_maximum = 20; - mosq->msgs_out.inflight_maximum = 20; - mosq->msgs_in.inflight_quota = 20; - mosq->msgs_out.inflight_quota = 20; - mosq->will = NULL; - mosq->on_connect = NULL; - mosq->on_publish = NULL; - mosq->on_message = NULL; - mosq->on_subscribe = NULL; - mosq->on_unsubscribe = NULL; - mosq->host = NULL; - mosq->port = 1883; - mosq->in_callback = false; - mosq->reconnect_delay = 1; - mosq->reconnect_delay_max = 1; - mosq->reconnect_exponential_backoff = false; - mosq->threaded = mosq_ts_none; -#ifdef WITH_TLS - mosq->ssl = NULL; - mosq->ssl_ctx = NULL; - mosq->tls_cert_reqs = SSL_VERIFY_PEER; - mosq->tls_insecure = false; - mosq->want_write = false; - mosq->tls_ocsp_required = false; -#endif -#ifdef WITH_THREADING - pthread_mutex_init(&mosq->callback_mutex, NULL); - pthread_mutex_init(&mosq->log_callback_mutex, NULL); - pthread_mutex_init(&mosq->state_mutex, NULL); - pthread_mutex_init(&mosq->out_packet_mutex, NULL); - pthread_mutex_init(&mosq->current_out_packet_mutex, NULL); - pthread_mutex_init(&mosq->msgtime_mutex, NULL); - pthread_mutex_init(&mosq->msgs_in.mutex, NULL); - pthread_mutex_init(&mosq->msgs_out.mutex, NULL); - pthread_mutex_init(&mosq->mid_mutex, NULL); - mosq->thread_id = pthread_self(); -#endif - - return MOSQ_ERR_SUCCESS; -} - - -void mosquitto__destroy(struct mosquitto *mosq) -{ - struct mosquitto__packet *packet; - if(!mosq) return; - -#ifdef WITH_THREADING -# ifdef HAVE_PTHREAD_CANCEL - if(mosq->threaded == mosq_ts_self && !pthread_equal(mosq->thread_id, pthread_self())){ - pthread_cancel(mosq->thread_id); - pthread_join(mosq->thread_id, NULL); - mosq->threaded = mosq_ts_none; - } -# endif - - if(mosq->id){ - /* If mosq->id is not NULL then the client has already been initialised - * and so the mutexes need destroying. If mosq->id is NULL, the mutexes - * haven't been initialised. */ - pthread_mutex_destroy(&mosq->callback_mutex); - pthread_mutex_destroy(&mosq->log_callback_mutex); - pthread_mutex_destroy(&mosq->state_mutex); - pthread_mutex_destroy(&mosq->out_packet_mutex); - pthread_mutex_destroy(&mosq->current_out_packet_mutex); - pthread_mutex_destroy(&mosq->msgtime_mutex); - pthread_mutex_destroy(&mosq->msgs_in.mutex); - pthread_mutex_destroy(&mosq->msgs_out.mutex); - pthread_mutex_destroy(&mosq->mid_mutex); - } -#endif - if(mosq->sock != INVALID_SOCKET){ - net__socket_close(mosq); - } - message__cleanup_all(mosq); - will__clear(mosq); -#ifdef WITH_TLS - if(mosq->ssl){ - SSL_free(mosq->ssl); - } - if(mosq->ssl_ctx){ - SSL_CTX_free(mosq->ssl_ctx); - } - mosquitto__free(mosq->tls_cafile); - mosquitto__free(mosq->tls_capath); - mosquitto__free(mosq->tls_certfile); - mosquitto__free(mosq->tls_keyfile); - if(mosq->tls_pw_callback) mosq->tls_pw_callback = NULL; - mosquitto__free(mosq->tls_version); - mosquitto__free(mosq->tls_ciphers); - mosquitto__free(mosq->tls_psk); - mosquitto__free(mosq->tls_psk_identity); - mosquitto__free(mosq->tls_alpn); -#endif - - mosquitto__free(mosq->address); - mosq->address = NULL; - - mosquitto__free(mosq->id); - mosq->id = NULL; - - mosquitto__free(mosq->username); - mosq->username = NULL; - - mosquitto__free(mosq->password); - mosq->password = NULL; - - mosquitto__free(mosq->host); - mosq->host = NULL; - - mosquitto__free(mosq->bind_address); - mosq->bind_address = NULL; - - /* Out packet cleanup */ - if(mosq->out_packet && !mosq->current_out_packet){ - mosq->current_out_packet = mosq->out_packet; - mosq->out_packet = mosq->out_packet->next; - } - while(mosq->current_out_packet){ - packet = mosq->current_out_packet; - /* Free data and reset values */ - mosq->current_out_packet = mosq->out_packet; - if(mosq->out_packet){ - mosq->out_packet = mosq->out_packet->next; - } - - packet__cleanup(packet); - mosquitto__free(packet); - } - - packet__cleanup(&mosq->in_packet); - if(mosq->sockpairR != INVALID_SOCKET){ - COMPAT_CLOSE(mosq->sockpairR); - mosq->sockpairR = INVALID_SOCKET; - } - if(mosq->sockpairW != INVALID_SOCKET){ - COMPAT_CLOSE(mosq->sockpairW); - mosq->sockpairW = INVALID_SOCKET; - } -} - -void mosquitto_destroy(struct mosquitto *mosq) -{ - if(!mosq) return; - - mosquitto__destroy(mosq); - mosquitto__free(mosq); -} - -int mosquitto_socket(struct mosquitto *mosq) -{ - if(!mosq) return INVALID_SOCKET; - return mosq->sock; -} - - -bool mosquitto_want_write(struct mosquitto *mosq) -{ - bool result = false; - if(mosq->out_packet || mosq->current_out_packet){ - result = true; - } -#ifdef WITH_TLS - if(mosq->ssl){ - if (mosq->want_write) { - result = true; - }else if(mosq->want_connect){ - result = false; - } - } -#endif - return result; -} - - -const char *mosquitto_strerror(int mosq_errno) -{ - switch(mosq_errno){ - case MOSQ_ERR_AUTH_CONTINUE: - return "Continue with authentication."; - case MOSQ_ERR_NO_SUBSCRIBERS: - return "No subscribers."; - case MOSQ_ERR_SUB_EXISTS: - return "Subscription already exists."; - case MOSQ_ERR_CONN_PENDING: - return "Connection pending."; - case MOSQ_ERR_SUCCESS: - return "No error."; - case MOSQ_ERR_NOMEM: - return "Out of memory."; - case MOSQ_ERR_PROTOCOL: - return "A network protocol error occurred when communicating with the broker."; - case MOSQ_ERR_INVAL: - return "Invalid function arguments provided."; - case MOSQ_ERR_NO_CONN: - return "The client is not currently connected."; - case MOSQ_ERR_CONN_REFUSED: - return "The connection was refused."; - case MOSQ_ERR_NOT_FOUND: - return "Message not found (internal error)."; - case MOSQ_ERR_CONN_LOST: - return "The connection was lost."; - case MOSQ_ERR_TLS: - return "A TLS error occurred."; - case MOSQ_ERR_PAYLOAD_SIZE: - return "Payload too large."; - case MOSQ_ERR_NOT_SUPPORTED: - return "This feature is not supported."; - case MOSQ_ERR_AUTH: - return "Authorisation failed."; - case MOSQ_ERR_ACL_DENIED: - return "Access denied by ACL."; - case MOSQ_ERR_UNKNOWN: - return "Unknown error."; - case MOSQ_ERR_ERRNO: - return strerror(errno); - case MOSQ_ERR_EAI: - return "Lookup error."; - case MOSQ_ERR_PROXY: - return "Proxy error."; - case MOSQ_ERR_MALFORMED_UTF8: - return "Malformed UTF-8"; - case MOSQ_ERR_DUPLICATE_PROPERTY: - return "Duplicate property in property list"; - case MOSQ_ERR_TLS_HANDSHAKE: - return "TLS handshake failed."; - case MOSQ_ERR_QOS_NOT_SUPPORTED: - return "Requested QoS not supported on server."; - case MOSQ_ERR_OVERSIZE_PACKET: - return "Packet larger than supported by the server."; - case MOSQ_ERR_OCSP: - return "OCSP error."; - default: - return "Unknown error."; - } -} - -const char *mosquitto_connack_string(int connack_code) -{ - switch(connack_code){ - case 0: - return "Connection Accepted."; - case 1: - return "Connection Refused: unacceptable protocol version."; - case 2: - return "Connection Refused: identifier rejected."; - case 3: - return "Connection Refused: broker unavailable."; - case 4: - return "Connection Refused: bad user name or password."; - case 5: - return "Connection Refused: not authorised."; - default: - return "Connection Refused: unknown reason."; - } -} - -const char *mosquitto_reason_string(int reason_code) -{ - switch(reason_code){ - case MQTT_RC_SUCCESS: - return "Success"; - case MQTT_RC_GRANTED_QOS1: - return "Granted QoS 1"; - case MQTT_RC_GRANTED_QOS2: - return "Granted QoS 2"; - case MQTT_RC_DISCONNECT_WITH_WILL_MSG: - return "Disconnect with Will Message"; - case MQTT_RC_NO_MATCHING_SUBSCRIBERS: - return "No matching subscribers"; - case MQTT_RC_NO_SUBSCRIPTION_EXISTED: - return "No subscription existed"; - case MQTT_RC_CONTINUE_AUTHENTICATION: - return "Continue authentication"; - case MQTT_RC_REAUTHENTICATE: - return "Re-authenticate"; - - case MQTT_RC_UNSPECIFIED: - return "Unspecified error"; - case MQTT_RC_MALFORMED_PACKET: - return "Malformed Packet"; - case MQTT_RC_PROTOCOL_ERROR: - return "Protocol Error"; - case MQTT_RC_IMPLEMENTATION_SPECIFIC: - return "Implementation specific error"; - case MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION: - return "Unsupported Protocol Version"; - case MQTT_RC_CLIENTID_NOT_VALID: - return "Client Identifier not valid"; - case MQTT_RC_BAD_USERNAME_OR_PASSWORD: - return "Bad User Name or Password"; - case MQTT_RC_NOT_AUTHORIZED: - return "Not authorized"; - case MQTT_RC_SERVER_UNAVAILABLE: - return "Server unavailable"; - case MQTT_RC_SERVER_BUSY: - return "Server busy"; - case MQTT_RC_BANNED: - return "Banned"; - case MQTT_RC_SERVER_SHUTTING_DOWN: - return "Server shutting down"; - case MQTT_RC_BAD_AUTHENTICATION_METHOD: - return "Bad authentication method"; - case MQTT_RC_KEEP_ALIVE_TIMEOUT: - return "Keep Alive timeout"; - case MQTT_RC_SESSION_TAKEN_OVER: - return "Session taken over"; - case MQTT_RC_TOPIC_FILTER_INVALID: - return "Topic Filter invalid"; - case MQTT_RC_TOPIC_NAME_INVALID: - return "Topic Name invalid"; - case MQTT_RC_PACKET_ID_IN_USE: - return "Packet Identifier in use"; - case MQTT_RC_PACKET_ID_NOT_FOUND: - return "Packet Identifier not found"; - case MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED: - return "Receive Maximum exceeded"; - case MQTT_RC_TOPIC_ALIAS_INVALID: - return "Topic Alias invalid"; - case MQTT_RC_PACKET_TOO_LARGE: - return "Packet too large"; - case MQTT_RC_MESSAGE_RATE_TOO_HIGH: - return "Message rate too high"; - case MQTT_RC_QUOTA_EXCEEDED: - return "Quota exceeded"; - case MQTT_RC_ADMINISTRATIVE_ACTION: - return "Administrative action"; - case MQTT_RC_PAYLOAD_FORMAT_INVALID: - return "Payload format invalid"; - case MQTT_RC_RETAIN_NOT_SUPPORTED: - return "Retain not supported"; - case MQTT_RC_QOS_NOT_SUPPORTED: - return "QoS not supported"; - case MQTT_RC_USE_ANOTHER_SERVER: - return "Use another server"; - case MQTT_RC_SERVER_MOVED: - return "Server moved"; - case MQTT_RC_SHARED_SUBS_NOT_SUPPORTED: - return "Shared Subscriptions not supported"; - case MQTT_RC_CONNECTION_RATE_EXCEEDED: - return "Connection rate exceeded"; - case MQTT_RC_MAXIMUM_CONNECT_TIME: - return "Maximum connect time"; - case MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED: - return "Subscription identifiers not supported"; - case MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED: - return "Wildcard Subscriptions not supported"; - default: - return "Unknown reason"; - } -} - - -int mosquitto_string_to_command(const char *str, int *cmd) -{ - if(!strcasecmp(str, "connect")){ - *cmd = CMD_CONNECT; - }else if(!strcasecmp(str, "connack")){ - *cmd = CMD_CONNACK; - }else if(!strcasecmp(str, "publish")){ - *cmd = CMD_PUBLISH; - }else if(!strcasecmp(str, "puback")){ - *cmd = CMD_PUBACK; - }else if(!strcasecmp(str, "pubrec")){ - *cmd = CMD_PUBREC; - }else if(!strcasecmp(str, "pubrel")){ - *cmd = CMD_PUBREL; - }else if(!strcasecmp(str, "pubcomp")){ - *cmd = CMD_PUBCOMP; - }else if(!strcasecmp(str, "subscribe")){ - *cmd = CMD_SUBSCRIBE; - }else if(!strcasecmp(str, "unsubscribe")){ - *cmd = CMD_UNSUBSCRIBE; - }else if(!strcasecmp(str, "disconnect")){ - *cmd = CMD_DISCONNECT; - }else if(!strcasecmp(str, "auth")){ - *cmd = CMD_AUTH; - }else if(!strcasecmp(str, "will")){ - *cmd = CMD_WILL; - }else{ - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count) -{ - int len; - int hier_count = 1; - int start, stop; - int hier; - int tlen; - int i, j; - - if(!subtopic || !topics || !count) return MOSQ_ERR_INVAL; - - len = strlen(subtopic); - - for(i=0; i<len; i++){ - if(subtopic[i] == '/'){ - if(i > len-1){ - /* Separator at end of line */ - }else{ - hier_count++; - } - } - } - - (*topics) = mosquitto__calloc(hier_count, sizeof(char *)); - if(!(*topics)) return MOSQ_ERR_NOMEM; - - start = 0; - stop = 0; - hier = 0; - - for(i=0; i<len+1; i++){ - if(subtopic[i] == '/' || subtopic[i] == '\0'){ - stop = i; - if(start != stop){ - tlen = stop-start + 1; - (*topics)[hier] = mosquitto__calloc(tlen, sizeof(char)); - if(!(*topics)[hier]){ - for(j=0; j<hier; j++){ - mosquitto__free((*topics)[j]); - } - mosquitto__free((*topics)); - return MOSQ_ERR_NOMEM; - } - for(j=start; j<stop; j++){ - (*topics)[hier][j-start] = subtopic[j]; - } - } - start = i+1; - hier++; - } - } - - *count = hier_count; - - return MOSQ_ERR_SUCCESS; -} - -int mosquitto_sub_topic_tokens_free(char ***topics, int count) -{ - int i; - - if(!topics || !(*topics) || count<1) return MOSQ_ERR_INVAL; - - for(i=0; i<count; i++){ - mosquitto__free((*topics)[i]); - } - mosquitto__free(*topics); - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/mosquitto_internal.h b/libs/libmosquitto/src/mosquitto_internal.h deleted file mode 100644 index ff656a4375..0000000000 --- a/libs/libmosquitto/src/mosquitto_internal.h +++ /dev/null @@ -1,358 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. - Tatsuzo Osawa - Add epoll. -*/ - -#ifndef MOSQUITTO_INTERNAL_H -#define MOSQUITTO_INTERNAL_H - -#include "config.h" - -#ifdef WIN32 -# include <winsock2.h> -#endif - -#ifdef WITH_TLS -# include <openssl/ssl.h> -#else -# include <time.h> -#endif -#include <stdlib.h> - -#if defined(WITH_THREADING) && !defined(WITH_BROKER) -# include <pthread.h> -#else -# include <dummypthread.h> -#endif - -#ifdef WITH_SRV -# include <ares.h> -#endif - -#ifdef WIN32 -# if _MSC_VER < 1600 - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; -# else -# include <stdint.h> -# endif -#else -# include <stdint.h> -#endif - -#include "mosquitto.h" -#include "time_mosq.h" -#ifdef WITH_BROKER -# ifdef __linux__ -# include <netdb.h> -# endif -# include "uthash.h" -struct mosquitto_client_msg; -#endif - -#ifdef WIN32 -typedef SOCKET mosq_sock_t; -#else -typedef int mosq_sock_t; -#endif - -enum mosquitto_msg_direction { - mosq_md_in = 0, - mosq_md_out = 1 -}; - -enum mosquitto_msg_state { - mosq_ms_invalid = 0, - mosq_ms_publish_qos0 = 1, - mosq_ms_publish_qos1 = 2, - mosq_ms_wait_for_puback = 3, - mosq_ms_publish_qos2 = 4, - mosq_ms_wait_for_pubrec = 5, - mosq_ms_resend_pubrel = 6, - mosq_ms_wait_for_pubrel = 7, - mosq_ms_resend_pubcomp = 8, - mosq_ms_wait_for_pubcomp = 9, - mosq_ms_send_pubrec = 10, - mosq_ms_queued = 11 -}; - -enum mosquitto_client_state { - mosq_cs_new = 0, - mosq_cs_connected = 1, - mosq_cs_disconnecting = 2, - mosq_cs_connect_async = 3, - mosq_cs_connect_pending = 4, - mosq_cs_connect_srv = 5, - mosq_cs_disconnect_ws = 6, - mosq_cs_disconnected = 7, - mosq_cs_socks5_new = 8, - mosq_cs_socks5_start = 9, - mosq_cs_socks5_request = 10, - mosq_cs_socks5_reply = 11, - mosq_cs_socks5_auth_ok = 12, - mosq_cs_socks5_userpass_reply = 13, - mosq_cs_socks5_send_userpass = 14, - mosq_cs_expiring = 15, - mosq_cs_connecting = 16, - mosq_cs_duplicate = 17, /* client that has been taken over by another with the same id */ - mosq_cs_disconnect_with_will = 18, - mosq_cs_disused = 19, /* client that has been added to the disused list to be freed */ - mosq_cs_authenticating = 20, /* Client has sent CONNECT but is still undergoing extended authentication */ - mosq_cs_reauthenticating = 21, /* Client is undergoing reauthentication and shouldn't do anything else until complete */ -}; - -enum mosquitto__protocol { - mosq_p_invalid = 0, - mosq_p_mqtt31 = 1, - mosq_p_mqtt311 = 2, - mosq_p_mqtts = 3, - mosq_p_mqtt5 = 5, -}; - -enum mosquitto__threaded_state { - mosq_ts_none, /* No threads in use */ - mosq_ts_self, /* Threads started by libmosquitto */ - mosq_ts_external /* Threads started by external code */ -}; - -enum mosquitto__transport { - mosq_t_invalid = 0, - mosq_t_tcp = 1, - mosq_t_ws = 2, - mosq_t_sctp = 3 -}; - - -struct mosquitto__alias{ - char *topic; - uint16_t alias; -}; - -struct session_expiry_list { - struct mosquitto *context; - struct session_expiry_list *prev; - struct session_expiry_list *next; -}; - -struct mosquitto__packet{ - uint8_t *payload; - struct mosquitto__packet *next; - uint32_t remaining_mult; - uint32_t remaining_length; - uint32_t packet_length; - uint32_t to_process; - uint32_t pos; - uint16_t mid; - uint8_t command; - int8_t remaining_count; -}; - -struct mosquitto_message_all{ - struct mosquitto_message_all *next; - struct mosquitto_message_all *prev; - mosquitto_property *properties; - time_t timestamp; - //enum mosquitto_msg_direction direction; - enum mosquitto_msg_state state; - bool dup; - struct mosquitto_message msg; - uint32_t expiry_interval; -}; - -#ifdef WITH_TLS -enum mosquitto__keyform { - mosq_k_pem = 0, - mosq_k_engine = 1, -}; -#endif - -struct will_delay_list { - struct mosquitto *context; - struct will_delay_list *prev; - struct will_delay_list *next; -}; - -struct mosquitto_msg_data{ -#ifdef WITH_BROKER - struct mosquitto_client_msg *inflight; - struct mosquitto_client_msg *queued; - unsigned long msg_bytes; - unsigned long msg_bytes12; - int msg_count; - int msg_count12; -#else - struct mosquitto_message_all *inflight; - int queue_len; -# ifdef WITH_THREADING - pthread_mutex_t mutex; -# endif -#endif - int inflight_quota; - uint16_t inflight_maximum; -}; - - -struct mosquitto { - mosq_sock_t sock; -#ifndef WITH_BROKER - mosq_sock_t sockpairR, sockpairW; -#endif -#if defined(__GLIBC__) && defined(WITH_ADNS) - struct gaicb *adns; /* For getaddrinfo_a */ -#endif - enum mosquitto__protocol protocol; - char *address; - char *id; - char *username; - char *password; - uint16_t keepalive; - uint16_t last_mid; - enum mosquitto_client_state state; - time_t last_msg_in; - time_t next_msg_out; - time_t ping_t; - struct mosquitto__packet in_packet; - struct mosquitto__packet *current_out_packet; - struct mosquitto__packet *out_packet; - struct mosquitto_message_all *will; - struct mosquitto__alias *aliases; - struct will_delay_list *will_delay_entry; - uint32_t maximum_packet_size; - int alias_count; - uint32_t will_delay_interval; - time_t will_delay_time; -#ifdef WITH_TLS - SSL *ssl; - SSL_CTX *ssl_ctx; - char *tls_cafile; - char *tls_capath; - char *tls_certfile; - char *tls_keyfile; - int (*tls_pw_callback)(char *buf, int size, int rwflag, void *userdata); - char *tls_version; - char *tls_ciphers; - char *tls_psk; - char *tls_psk_identity; - int tls_cert_reqs; - bool tls_insecure; - bool ssl_ctx_defaults; - bool tls_ocsp_required; - char *tls_engine; - char *tls_engine_kpass_sha1; - enum mosquitto__keyform tls_keyform; - char *tls_alpn; -#endif - bool want_write; - bool want_connect; -#if defined(WITH_THREADING) && !defined(WITH_BROKER) - pthread_mutex_t callback_mutex; - pthread_mutex_t log_callback_mutex; - pthread_mutex_t msgtime_mutex; - pthread_mutex_t out_packet_mutex; - pthread_mutex_t current_out_packet_mutex; - pthread_mutex_t state_mutex; - pthread_mutex_t mid_mutex; - pthread_t thread_id; -#endif - bool clean_start; - uint32_t session_expiry_interval; - time_t session_expiry_time; -#ifdef WITH_BROKER - bool removed_from_by_id; /* True if removed from by_id hash */ - bool is_dropping; - bool is_bridge; - struct mosquitto__bridge *bridge; - struct mosquitto_msg_data msgs_in; - struct mosquitto_msg_data msgs_out; - struct mosquitto__acl_user *acl_list; - struct mosquitto__listener *listener; - struct mosquitto__packet *out_packet_last; - struct mosquitto__subhier **subs; - struct mosquitto__subshared_ref **shared_subs; - char *auth_method; - int sub_count; - int shared_sub_count; - int pollfd_index; -# ifdef WITH_WEBSOCKETS -# if defined(LWS_LIBRARY_VERSION_NUMBER) - struct lws *wsi; -# else - struct libwebsocket_context *ws_context; - struct libwebsocket *wsi; -# endif -# endif - bool ws_want_write; - bool assigned_id; -#else -# ifdef WITH_SOCKS - char *socks5_host; - int socks5_port; - char *socks5_username; - char *socks5_password; -# endif - void *userdata; - bool in_callback; - struct mosquitto_msg_data msgs_in; - struct mosquitto_msg_data msgs_out; - void (*on_connect)(struct mosquitto *, void *userdata, int rc); - void (*on_connect_with_flags)(struct mosquitto *, void *userdata, int rc, int flags); - void (*on_connect_v5)(struct mosquitto *, void *userdata, int rc, int flags, const mosquitto_property *props); - void (*on_disconnect)(struct mosquitto *, void *userdata, int rc); - void (*on_disconnect_v5)(struct mosquitto *, void *userdata, int rc, const mosquitto_property *props); - void (*on_publish)(struct mosquitto *, void *userdata, int mid); - void (*on_publish_v5)(struct mosquitto *, void *userdata, int mid, int reason_code, const mosquitto_property *props); - void (*on_message)(struct mosquitto *, void *userdata, const struct mosquitto_message *message); - void (*on_message_v5)(struct mosquitto *, void *userdata, const struct mosquitto_message *message, const mosquitto_property *props); - void (*on_subscribe)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos); - void (*on_subscribe_v5)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos, const mosquitto_property *props); - void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid); - void (*on_unsubscribe_v5)(struct mosquitto *, void *userdata, int mid, const mosquitto_property *props); - void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str); - //void (*on_error)(); - char *host; - int port; - char *bind_address; - unsigned int reconnect_delay; - unsigned int reconnect_delay_max; - bool reconnect_exponential_backoff; - char threaded; - struct mosquitto__packet *out_packet_last; -# ifdef WITH_SRV - ares_channel achan; -# endif - uint16_t send_maximum; - uint16_t receive_maximum; -#endif - uint8_t maximum_qos; - -#ifdef WITH_BROKER - UT_hash_handle hh_id; - UT_hash_handle hh_sock; - struct mosquitto *for_free_next; - struct session_expiry_list *expiry_list_item; -#endif -#ifdef WITH_EPOLL - uint32_t events; -#endif -}; - -#define STREMPTY(str) (str[0] == '\0') - -void do_client_disconnect(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties); - -#endif - diff --git a/libs/libmosquitto/src/mqtt_protocol.h b/libs/libmosquitto/src/mqtt_protocol.h deleted file mode 100644 index 672d50b767..0000000000 --- a/libs/libmosquitto/src/mqtt_protocol.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -Copyright (c) 2009-2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 MQTT_PROTOCOL_H -#define MQTT_PROTOCOL_H - -#define PROTOCOL_NAME_v31 "MQIsdp" -#define PROTOCOL_VERSION_v31 3 - -#define PROTOCOL_NAME "MQTT" - -#define PROTOCOL_VERSION_v311 4 -#define PROTOCOL_VERSION_v5 5 - - -/* Message types */ -#define CMD_CONNECT 0x10 -#define CMD_CONNACK 0x20 -#define CMD_PUBLISH 0x30 -#define CMD_PUBACK 0x40 -#define CMD_PUBREC 0x50 -#define CMD_PUBREL 0x60 -#define CMD_PUBCOMP 0x70 -#define CMD_SUBSCRIBE 0x80 -#define CMD_SUBACK 0x90 -#define CMD_UNSUBSCRIBE 0xA0 -#define CMD_UNSUBACK 0xB0 -#define CMD_PINGREQ 0xC0 -#define CMD_PINGRESP 0xD0 -#define CMD_DISCONNECT 0xE0 -#define CMD_AUTH 0xF0 - -/* Mosquitto only: for distinguishing CONNECT and WILL properties */ -#define CMD_WILL 0x100 - -enum mqtt311_connack_codes { - CONNACK_ACCEPTED = 0, - CONNACK_REFUSED_PROTOCOL_VERSION = 1, - CONNACK_REFUSED_IDENTIFIER_REJECTED = 2, - CONNACK_REFUSED_SERVER_UNAVAILABLE = 3, - CONNACK_REFUSED_BAD_USERNAME_PASSWORD = 4, - CONNACK_REFUSED_NOT_AUTHORIZED = 5, -}; - - -enum mqtt5_return_codes { - MQTT_RC_SUCCESS = 0, /* CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH */ - MQTT_RC_NORMAL_DISCONNECTION = 0, /* DISCONNECT */ - MQTT_RC_GRANTED_QOS0 = 0, /* SUBACK */ - MQTT_RC_GRANTED_QOS1 = 1, /* SUBACK */ - MQTT_RC_GRANTED_QOS2 = 2, /* SUBACK */ - MQTT_RC_DISCONNECT_WITH_WILL_MSG = 4, /* DISCONNECT */ - MQTT_RC_NO_MATCHING_SUBSCRIBERS = 16, /* PUBACK, PUBREC */ - MQTT_RC_NO_SUBSCRIPTION_EXISTED = 17, /* UNSUBACK */ - MQTT_RC_CONTINUE_AUTHENTICATION = 24, /* AUTH */ - MQTT_RC_REAUTHENTICATE = 25, /* AUTH */ - - MQTT_RC_UNSPECIFIED = 128, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */ - MQTT_RC_MALFORMED_PACKET = 129, /* CONNACK, DISCONNECT */ - MQTT_RC_PROTOCOL_ERROR = 130, /* DISCONNECT */ - MQTT_RC_IMPLEMENTATION_SPECIFIC = 131, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */ - MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION = 132, /* CONNACK */ - MQTT_RC_CLIENTID_NOT_VALID = 133, /* CONNACK */ - MQTT_RC_BAD_USERNAME_OR_PASSWORD = 134, /* CONNACK */ - MQTT_RC_NOT_AUTHORIZED = 135, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */ - MQTT_RC_SERVER_UNAVAILABLE = 136, /* CONNACK */ - MQTT_RC_SERVER_BUSY = 137, /* CONNACK, DISCONNECT */ - MQTT_RC_BANNED = 138, /* CONNACK */ - MQTT_RC_SERVER_SHUTTING_DOWN = 139, /* DISCONNECT */ - MQTT_RC_BAD_AUTHENTICATION_METHOD = 140, /* CONNACK */ - MQTT_RC_KEEP_ALIVE_TIMEOUT = 141, /* DISCONNECT */ - MQTT_RC_SESSION_TAKEN_OVER = 142, /* DISCONNECT */ - MQTT_RC_TOPIC_FILTER_INVALID = 143, /* SUBACK, UNSUBACK, DISCONNECT */ - MQTT_RC_TOPIC_NAME_INVALID = 144, /* CONNACK, PUBACK, PUBREC, DISCONNECT */ - MQTT_RC_PACKET_ID_IN_USE = 145, /* PUBACK, SUBACK, UNSUBACK */ - MQTT_RC_PACKET_ID_NOT_FOUND = 146, /* PUBREL, PUBCOMP */ - MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED = 147, /* DISCONNECT */ - MQTT_RC_TOPIC_ALIAS_INVALID = 148, /* DISCONNECT */ - MQTT_RC_PACKET_TOO_LARGE = 149, /* CONNACK, PUBACK, PUBREC, DISCONNECT */ - MQTT_RC_MESSAGE_RATE_TOO_HIGH = 150, /* DISCONNECT */ - MQTT_RC_QUOTA_EXCEEDED = 151, /* PUBACK, PUBREC, SUBACK, DISCONNECT */ - MQTT_RC_ADMINISTRATIVE_ACTION = 152, /* DISCONNECT */ - MQTT_RC_PAYLOAD_FORMAT_INVALID = 153, /* CONNACK, DISCONNECT */ - MQTT_RC_RETAIN_NOT_SUPPORTED = 154, /* CONNACK, DISCONNECT */ - MQTT_RC_QOS_NOT_SUPPORTED = 155, /* CONNACK, DISCONNECT */ - MQTT_RC_USE_ANOTHER_SERVER = 156, /* CONNACK, DISCONNECT */ - MQTT_RC_SERVER_MOVED = 157, /* CONNACK, DISCONNECT */ - MQTT_RC_SHARED_SUBS_NOT_SUPPORTED = 158, /* SUBACK, DISCONNECT */ - MQTT_RC_CONNECTION_RATE_EXCEEDED = 159, /* CONNACK, DISCONNECT */ - MQTT_RC_MAXIMUM_CONNECT_TIME = 160, /* DISCONNECT */ - MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED = 161, /* SUBACK, DISCONNECT */ - MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED = 162, /* SUBACK, DISCONNECT */ -}; - -enum mqtt5_property { - MQTT_PROP_PAYLOAD_FORMAT_INDICATOR = 1, /* Byte : PUBLISH, Will Properties */ - MQTT_PROP_MESSAGE_EXPIRY_INTERVAL = 2, /* 4 byte int : PUBLISH, Will Properties */ - MQTT_PROP_CONTENT_TYPE = 3, /* UTF-8 string : PUBLISH, Will Properties */ - MQTT_PROP_RESPONSE_TOPIC = 8, /* UTF-8 string : PUBLISH, Will Properties */ - MQTT_PROP_CORRELATION_DATA = 9, /* Binary Data : PUBLISH, Will Properties */ - MQTT_PROP_SUBSCRIPTION_IDENTIFIER = 11, /* Variable byte int : PUBLISH, SUBSCRIBE */ - MQTT_PROP_SESSION_EXPIRY_INTERVAL = 17, /* 4 byte int : CONNECT, CONNACK, DISCONNECT */ - MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER = 18, /* UTF-8 string : CONNACK */ - MQTT_PROP_SERVER_KEEP_ALIVE = 19, /* 2 byte int : CONNACK */ - MQTT_PROP_AUTHENTICATION_METHOD = 21, /* UTF-8 string : CONNECT, CONNACK, AUTH */ - MQTT_PROP_AUTHENTICATION_DATA = 22, /* Binary Data : CONNECT, CONNACK, AUTH */ - MQTT_PROP_REQUEST_PROBLEM_INFORMATION = 23, /* Byte : CONNECT */ - MQTT_PROP_WILL_DELAY_INTERVAL = 24, /* 4 byte int : Will properties */ - MQTT_PROP_REQUEST_RESPONSE_INFORMATION = 25,/* Byte : CONNECT */ - MQTT_PROP_RESPONSE_INFORMATION = 26, /* UTF-8 string : CONNACK */ - MQTT_PROP_SERVER_REFERENCE = 28, /* UTF-8 string : CONNACK, DISCONNECT */ - MQTT_PROP_REASON_STRING = 31, /* UTF-8 string : All except Will properties */ - MQTT_PROP_RECEIVE_MAXIMUM = 33, /* 2 byte int : CONNECT, CONNACK */ - MQTT_PROP_TOPIC_ALIAS_MAXIMUM = 34, /* 2 byte int : CONNECT, CONNACK */ - MQTT_PROP_TOPIC_ALIAS = 35, /* 2 byte int : PUBLISH */ - MQTT_PROP_MAXIMUM_QOS = 36, /* Byte : CONNACK */ - MQTT_PROP_RETAIN_AVAILABLE = 37, /* Byte : CONNACK */ - MQTT_PROP_USER_PROPERTY = 38, /* UTF-8 string pair : All */ - MQTT_PROP_MAXIMUM_PACKET_SIZE = 39, /* 4 byte int : CONNECT, CONNACK */ - MQTT_PROP_WILDCARD_SUB_AVAILABLE = 40, /* Byte : CONNACK */ - MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE = 41, /* Byte : CONNACK */ - MQTT_PROP_SHARED_SUB_AVAILABLE = 42, /* Byte : CONNACK */ -}; - -enum mqtt5_property_type { - MQTT_PROP_TYPE_BYTE = 1, - MQTT_PROP_TYPE_INT16 = 2, - MQTT_PROP_TYPE_INT32 = 3, - MQTT_PROP_TYPE_VARINT = 4, - MQTT_PROP_TYPE_BINARY = 5, - MQTT_PROP_TYPE_STRING = 6, - MQTT_PROP_TYPE_STRING_PAIR = 7 -}; - -enum mqtt5_sub_options { - MQTT_SUB_OPT_NO_LOCAL = 0x04, - MQTT_SUB_OPT_RETAIN_AS_PUBLISHED = 0x08, - MQTT_SUB_OPT_SEND_RETAIN_ALWAYS = 0x00, - MQTT_SUB_OPT_SEND_RETAIN_NEW = 0x10, - MQTT_SUB_OPT_SEND_RETAIN_NEVER = 0x20, -}; - -#define MQTT_MAX_PAYLOAD 268435455 - -#endif diff --git a/libs/libmosquitto/src/net_mosq.c b/libs/libmosquitto/src/net_mosq.c deleted file mode 100644 index f207e32aea..0000000000 --- a/libs/libmosquitto/src/net_mosq.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#define _GNU_SOURCE -#include "config.h" - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#ifndef WIN32 -#define _GNU_SOURCE -#include <netdb.h> -#include <sys/socket.h> -#include <unistd.h> -#else -#include <winsock2.h> -#include <ws2tcpip.h> -#endif - -#ifdef __ANDROID__ -#include <linux/in.h> -#include <linux/in6.h> -#include <sys/endian.h> -#endif - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif - -#ifdef __QNX__ -#include <net/netbyte.h> -#endif - -#ifdef WITH_TLS -#include <openssl/conf.h> -#include <openssl/engine.h> -#include <openssl/err.h> -#include <openssl/ui.h> -#include <tls_mosq.h> -#endif - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -# ifdef WITH_WEBSOCKETS -# include <libwebsockets.h> -# endif -#else -# include "read_handle.h" -#endif - -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "time_mosq.h" -#include "util_mosq.h" - -#ifdef WITH_TLS -int tls_ex_index_mosq = -1; -UI_METHOD *_ui_method = NULL; - -/* Functions taken from OpenSSL s_server/s_client */ -static int ui_open(UI *ui) -{ - return UI_method_get_opener(UI_OpenSSL())(ui); -} - -static int ui_read(UI *ui, UI_STRING *uis) -{ - return UI_method_get_reader(UI_OpenSSL())(ui, uis); -} - -static int ui_write(UI *ui, UI_STRING *uis) -{ - return UI_method_get_writer(UI_OpenSSL())(ui, uis); -} - -static int ui_close(UI *ui) -{ - return UI_method_get_closer(UI_OpenSSL())(ui); -} - -static void setup_ui_method(void) -{ - _ui_method = UI_create_method("OpenSSL application user interface"); - UI_method_set_opener(_ui_method, ui_open); - UI_method_set_reader(_ui_method, ui_read); - UI_method_set_writer(_ui_method, ui_write); - UI_method_set_closer(_ui_method, ui_close); -} - -static void cleanup_ui_method(void) -{ - if(_ui_method){ - UI_destroy_method(_ui_method); - _ui_method = NULL; - } -} - -UI_METHOD *net__get_ui_method(void) -{ - return _ui_method; -} -#endif - -int net__init(void) -{ -#ifdef WIN32 - WSADATA wsaData; - if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0){ - return MOSQ_ERR_UNKNOWN; - } -#endif - -#ifdef WITH_SRV - ares_library_init(ARES_LIB_INIT_ALL); -#endif - -#ifdef WITH_TLS -# if OPENSSL_VERSION_NUMBER < 0x10100000L - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); -# else - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ - | OPENSSL_INIT_ADD_ALL_DIGESTS \ - | OPENSSL_INIT_LOAD_CONFIG, NULL); -# endif -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_load_builtin_engines(); -#endif - setup_ui_method(); - if(tls_ex_index_mosq == -1){ - tls_ex_index_mosq = SSL_get_ex_new_index(0, "client context", NULL, NULL, NULL); - } -#endif - return MOSQ_ERR_SUCCESS; -} - -void net__cleanup(void) -{ -#ifdef WITH_TLS -# if OPENSSL_VERSION_NUMBER < 0x10100000L - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - -# if !defined(OPENSSL_NO_ENGINE) - ENGINE_cleanup(); -# endif -# endif - - CONF_modules_unload(1); - cleanup_ui_method(); -#endif - -#ifdef WITH_SRV - ares_library_cleanup(); -#endif - -#ifdef WIN32 - WSACleanup(); -#endif -} - - -/* Close a socket associated with a context and set it to -1. - * Returns 1 on failure (context is NULL) - * Returns 0 on success. - */ -#ifdef WITH_BROKER -int net__socket_close(struct mosquitto_db *db, struct mosquitto *mosq) -#else -int net__socket_close(struct mosquitto *mosq) -#endif -{ - int rc = 0; - - assert(mosq); -#ifdef WITH_TLS -#ifdef WITH_WEBSOCKETS - if(!mosq->wsi) -#endif - { - if(mosq->ssl){ - SSL_shutdown(mosq->ssl); - SSL_free(mosq->ssl); - mosq->ssl = NULL; - } - } -#endif - -#ifdef WITH_WEBSOCKETS - if(mosq->wsi) - { - if(mosq->state != mosq_cs_disconnecting){ - context__set_state(mosq, mosq_cs_disconnect_ws); - } - libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi); - }else -#endif - { - if(mosq->sock != INVALID_SOCKET){ -#ifdef WITH_BROKER - HASH_DELETE(hh_sock, db->contexts_by_sock, mosq); -#endif - rc = COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - } - } - -#ifdef WITH_BROKER - if(mosq->listener){ - mosq->listener->client_count--; - } -#endif - - return rc; -} - - -#ifdef FINAL_WITH_TLS_PSK -static unsigned int psk_client_callback(SSL *ssl, const char *hint, - char *identity, unsigned int max_identity_len, - unsigned char *psk, unsigned int max_psk_len) -{ - struct mosquitto *mosq; - int len; - - UNUSED(hint); - - mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq); - if(!mosq) return 0; - - snprintf(identity, max_identity_len, "%s", mosq->tls_psk_identity); - - len = mosquitto__hex2bin(mosq->tls_psk, psk, max_psk_len); - if (len < 0) return 0; - return len; -} -#endif - -#if defined(WITH_BROKER) && defined(__GLIBC__) && defined(WITH_ADNS) -/* Async connect, part 1 (dns lookup) */ -int net__try_connect_step1(struct mosquitto *mosq, const char *host) -{ - int s; - void *sevp = NULL; - struct addrinfo *hints; - - if(mosq->adns){ - gai_cancel(mosq->adns); - mosquitto__free((struct addrinfo *)mosq->adns->ar_request); - mosquitto__free(mosq->adns); - } - mosq->adns = mosquitto__calloc(1, sizeof(struct gaicb)); - if(!mosq->adns){ - return MOSQ_ERR_NOMEM; - } - - hints = mosquitto__calloc(1, sizeof(struct addrinfo)); - if(!hints){ - mosquitto__free(mosq->adns); - mosq->adns = NULL; - return MOSQ_ERR_NOMEM; - } - - hints->ai_family = AF_UNSPEC; - hints->ai_socktype = SOCK_STREAM; - - mosq->adns->ar_name = host; - mosq->adns->ar_request = hints; - - s = getaddrinfo_a(GAI_NOWAIT, &mosq->adns, 1, sevp); - if(s){ - errno = s; - if(mosq->adns){ - mosquitto__free((struct addrinfo *)mosq->adns->ar_request); - mosquitto__free(mosq->adns); - mosq->adns = NULL; - } - return MOSQ_ERR_EAI; - } - - return MOSQ_ERR_SUCCESS; -} - -/* Async connect part 2, the connection. */ -int net__try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *sock) -{ - struct addrinfo *ainfo, *rp; - int rc; - - ainfo = mosq->adns->ar_result; - - for(rp = ainfo; rp != NULL; rp = rp->ai_next){ - *sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if(*sock == INVALID_SOCKET) continue; - - if(rp->ai_family == AF_INET){ - ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); - }else if(rp->ai_family == AF_INET6){ - ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); - }else{ - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - continue; - } - - /* Set non-blocking */ - if(net__socket_nonblock(sock)){ - continue; - } - - rc = connect(*sock, rp->ai_addr, rp->ai_addrlen); -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){ - if(rc < 0 && (errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK)){ - rc = MOSQ_ERR_CONN_PENDING; - } - - /* Set non-blocking */ - if(net__socket_nonblock(sock)){ - continue; - } - break; - } - - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - } - freeaddrinfo(mosq->adns->ar_result); - mosq->adns->ar_result = NULL; - - mosquitto__free((struct addrinfo *)mosq->adns->ar_request); - mosquitto__free(mosq->adns); - mosq->adns = NULL; - - if(!rp){ - return MOSQ_ERR_ERRNO; - } - - return rc; -} - -#endif - - -int net__try_connect(const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking) -{ - struct addrinfo hints; - struct addrinfo *ainfo, *rp; - struct addrinfo *ainfo_bind, *rp_bind; - int s; - int rc = MOSQ_ERR_SUCCESS; -#ifdef WIN32 - uint32_t val = 1; -#endif - - *sock = INVALID_SOCKET; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - s = getaddrinfo(host, NULL, &hints, &ainfo); - if(s){ - errno = s; - return MOSQ_ERR_EAI; - } - - if(bind_address){ - s = getaddrinfo(bind_address, NULL, &hints, &ainfo_bind); - if(s){ - freeaddrinfo(ainfo); - errno = s; - return MOSQ_ERR_EAI; - } - } - - for(rp = ainfo; rp != NULL; rp = rp->ai_next){ - *sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if(*sock == INVALID_SOCKET) continue; - - if(rp->ai_family == AF_INET){ - ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); - }else if(rp->ai_family == AF_INET6){ - ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); - }else{ - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - continue; - } - - if(bind_address){ - for(rp_bind = ainfo_bind; rp_bind != NULL; rp_bind = rp_bind->ai_next){ - if(bind(*sock, rp_bind->ai_addr, rp_bind->ai_addrlen) == 0){ - break; - } - } - if(!rp_bind){ - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - continue; - } - } - - if(!blocking){ - /* Set non-blocking */ - if(net__socket_nonblock(sock)){ - continue; - } - } - - rc = connect(*sock, rp->ai_addr, rp->ai_addrlen); -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){ - if(rc < 0 && (errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK)){ - rc = MOSQ_ERR_CONN_PENDING; - } - - if(blocking){ - /* Set non-blocking */ - if(net__socket_nonblock(sock)){ - continue; - } - } - break; - } - - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - } - freeaddrinfo(ainfo); - if(bind_address){ - freeaddrinfo(ainfo_bind); - } - if(!rp){ - return MOSQ_ERR_ERRNO; - } - return rc; -} - - -#ifdef WITH_TLS -void net__print_ssl_error(struct mosquitto *mosq) -{ - char ebuf[256]; - unsigned long e; - - e = ERR_get_error(); - while(e){ - log__printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf)); - e = ERR_get_error(); - } -} - - -int net__socket_connect_tls(struct mosquitto *mosq) -{ - int ret, err; - - ERR_clear_error(); - long res; - if (mosq->tls_ocsp_required) { - // Note: OCSP is available in all currently supported OpenSSL versions. - if ((res=SSL_set_tlsext_status_type(mosq->ssl, TLSEXT_STATUSTYPE_ocsp)) != 1) { - log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res); - return MOSQ_ERR_OCSP; - } - if ((res=SSL_CTX_set_tlsext_status_cb(mosq->ssl_ctx, mosquitto__verify_ocsp_status_cb)) != 1) { - log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res); - return MOSQ_ERR_OCSP; - } - if ((res=SSL_CTX_set_tlsext_status_arg(mosq->ssl_ctx, mosq)) != 1) { - log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res); - return MOSQ_ERR_OCSP; - } - } - - ret = SSL_connect(mosq->ssl); - if(ret != 1) { - err = SSL_get_error(mosq->ssl, ret); - if (err == SSL_ERROR_SYSCALL) { - mosq->want_connect = true; - return MOSQ_ERR_SUCCESS; - } - if(err == SSL_ERROR_WANT_READ){ - mosq->want_connect = true; - /* We always try to read anyway */ - }else if(err == SSL_ERROR_WANT_WRITE){ - mosq->want_write = true; - mosq->want_connect = true; - }else{ - net__print_ssl_error(mosq); - - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - }else{ - mosq->want_connect = false; - } - return MOSQ_ERR_SUCCESS; -} -#endif - - -#ifdef WITH_TLS -static int net__init_ssl_ctx(struct mosquitto *mosq) -{ - int ret; - ENGINE *engine = NULL; - uint8_t tls_alpn_wire[256]; - uint8_t tls_alpn_len; - - if(mosq->ssl_ctx){ - if(!mosq->ssl_ctx_defaults){ - return MOSQ_ERR_SUCCESS; - }else if(!mosq->tls_cafile && !mosq->tls_capath && !mosq->tls_psk){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: MOSQ_OPT_SSL_CTX_WITH_DEFAULTS used without specifying cafile, capath or psk."); - return MOSQ_ERR_INVAL; - } - } - - /* Apply default SSL_CTX settings. This is only used if MOSQ_OPT_SSL_CTX - * has not been set, or if both of MOSQ_OPT_SSL_CTX and - * MOSQ_OPT_SSL_CTX_WITH_DEFAULTS are set. */ - if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ - if(!mosq->ssl_ctx){ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - mosq->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); -#else - mosq->ssl_ctx = SSL_CTX_new(TLS_client_method()); -#endif - - if(!mosq->ssl_ctx){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - } - - if(!mosq->tls_version){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); -#ifdef SSL_OP_NO_TLSv1_3 - }else if(!strcmp(mosq->tls_version, "tlsv1.3")){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); - }else if(!strcmp(mosq->tls_version, "tlsv1.2")){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_3); - }else if(!strcmp(mosq->tls_version, "tlsv1.1")){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); -#else - }else if(!strcmp(mosq->tls_version, "tlsv1.2")){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); - }else if(!strcmp(mosq->tls_version, "tlsv1.1")){ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2); -#endif - }else{ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version); - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - return MOSQ_ERR_INVAL; - } - - /* Disable compression */ - SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION); - - /* Set ALPN */ - if(mosq->tls_alpn) { - tls_alpn_len = (uint8_t) strnlen(mosq->tls_alpn, 254); - tls_alpn_wire[0] = tls_alpn_len; // first byte is length of string - memcpy(tls_alpn_wire + 1, mosq->tls_alpn, tls_alpn_len); - SSL_CTX_set_alpn_protos(mosq->ssl_ctx, tls_alpn_wire, tls_alpn_len + 1); - } - -#ifdef SSL_MODE_RELEASE_BUFFERS - /* Use even less memory per SSL connection. */ - SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); -#endif - -#if !defined(OPENSSL_NO_ENGINE) - if(mosq->tls_engine){ - engine = ENGINE_by_id(mosq->tls_engine); - if(!engine){ - log__printf(mosq, MOSQ_LOG_ERR, "Error loading %s engine\n", mosq->tls_engine); - COMPAT_CLOSE(mosq->sock); - return MOSQ_ERR_TLS; - } - if(!ENGINE_init(engine)){ - log__printf(mosq, MOSQ_LOG_ERR, "Failed engine initialisation\n"); - ENGINE_free(engine); - COMPAT_CLOSE(mosq->sock); - return MOSQ_ERR_TLS; - } - ENGINE_set_default(engine, ENGINE_METHOD_ALL); - ENGINE_free(engine); /* release the structural reference from ENGINE_by_id() */ - } -#endif - - if(mosq->tls_ciphers){ - ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers); - if(ret == 0){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers); -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_FINISH(engine); -#endif - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - } - if(mosq->tls_cafile || mosq->tls_capath){ - ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath); - if(ret == 0){ -#ifdef WITH_BROKER - if(mosq->tls_cafile && mosq->tls_capath){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); - }else if(mosq->tls_cafile){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile); - }else{ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath); - } -#else - if(mosq->tls_cafile && mosq->tls_capath){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); - }else if(mosq->tls_cafile){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile); - }else{ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath); - } -#endif -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_FINISH(engine); -#endif - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - if(mosq->tls_cert_reqs == 0){ - SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL); - }else{ - SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, mosquitto__server_certificate_verify); - } - - if(mosq->tls_pw_callback){ - SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback); - SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq); - } - - if(mosq->tls_certfile){ - ret = SSL_CTX_use_certificate_chain_file(mosq->ssl_ctx, mosq->tls_certfile); - if(ret != 1){ -#ifdef WITH_BROKER - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile); -#else - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile); -#endif -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_FINISH(engine); -#endif - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - } - if(mosq->tls_keyfile){ - if(mosq->tls_keyform == mosq_k_engine){ -#if !defined(OPENSSL_NO_ENGINE) - UI_METHOD *ui_method = net__get_ui_method(); - if(mosq->tls_engine_kpass_sha1){ - if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha1"); - ENGINE_FINISH(engine); - COMPAT_CLOSE(mosq->sock); - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, mosq->tls_engine_kpass_sha1, NULL, 0)){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine pin"); - ENGINE_FINISH(engine); - COMPAT_CLOSE(mosq->sock); - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - ui_method = NULL; - } - EVP_PKEY *pkey = ENGINE_load_private_key(engine, mosq->tls_keyfile, ui_method, NULL); - if(!pkey){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", mosq->tls_keyfile); - ENGINE_FINISH(engine); - COMPAT_CLOSE(mosq->sock); - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - if(SSL_CTX_use_PrivateKey(mosq->ssl_ctx, pkey) <= 0){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to use engine private key file \"%s\".", mosq->tls_keyfile); - ENGINE_FINISH(engine); - COMPAT_CLOSE(mosq->sock); - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } -#endif - }else{ - ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM); - if(ret != 1){ -#ifdef WITH_BROKER - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile); -#else - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile); -#endif -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_FINISH(engine); -#endif - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - } - ret = SSL_CTX_check_private_key(mosq->ssl_ctx); - if(ret != 1){ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent."); -#if !defined(OPENSSL_NO_ENGINE) - ENGINE_FINISH(engine); -#endif - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - } -#ifdef FINAL_WITH_TLS_PSK - }else if(mosq->tls_psk){ - SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback); -#endif - } - } - - return MOSQ_ERR_SUCCESS; -} -#endif - - -int net__socket_connect_step3(struct mosquitto *mosq, const char *host) -{ -#ifdef WITH_TLS - BIO *bio; - - int rc = net__init_ssl_ctx(mosq); - if(rc) return rc; - - if(mosq->ssl_ctx){ - if(mosq->ssl){ - SSL_free(mosq->ssl); - } - mosq->ssl = SSL_new(mosq->ssl_ctx); - if(!mosq->ssl){ - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - - SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); - bio = BIO_new_socket(mosq->sock, BIO_NOCLOSE); - if(!bio){ - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - net__print_ssl_error(mosq); - return MOSQ_ERR_TLS; - } - SSL_set_bio(mosq->ssl, bio, bio); - - /* - * required for the SNI resolving - */ - if(SSL_set_tlsext_host_name(mosq->ssl, host) != 1) { - COMPAT_CLOSE(mosq->sock); - mosq->sock = INVALID_SOCKET; - return MOSQ_ERR_TLS; - } - - if(net__socket_connect_tls(mosq)){ - return MOSQ_ERR_TLS; - } - - } -#endif - return MOSQ_ERR_SUCCESS; -} - -/* Create a socket and connect it to 'ip' on port 'port'. */ -int net__socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking) -{ - mosq_sock_t sock = INVALID_SOCKET; - int rc, rc2; - - if(!mosq || !host || !port) return MOSQ_ERR_INVAL; - - rc = net__try_connect(host, port, &sock, bind_address, blocking); - if(rc > 0) return rc; - - mosq->sock = sock; - -#if defined(WITH_SOCKS) && !defined(WITH_BROKER) - if(!mosq->socks5_host) -#endif - { - rc2 = net__socket_connect_step3(mosq, host); - if(rc2) return rc2; - } - - return MOSQ_ERR_SUCCESS; -} - - -ssize_t net__read(struct mosquitto *mosq, void *buf, size_t count) -{ -#ifdef WITH_TLS - int ret; - int err; -#endif - assert(mosq); - errno = 0; -#ifdef WITH_TLS - if(mosq->ssl){ - ERR_clear_error(); - ret = SSL_read(mosq->ssl, buf, count); - if(ret <= 0){ - err = SSL_get_error(mosq->ssl, ret); - if(err == SSL_ERROR_WANT_READ){ - ret = -1; - errno = EAGAIN; - }else if(err == SSL_ERROR_WANT_WRITE){ - ret = -1; - mosq->want_write = true; - errno = EAGAIN; - }else{ - net__print_ssl_error(mosq); - errno = EPROTO; - } -#ifdef WIN32 - WSASetLastError(errno); -#endif - } - return (ssize_t )ret; - }else{ - /* Call normal read/recv */ - -#endif - -#ifndef WIN32 - return read(mosq->sock, buf, count); -#else - return recv(mosq->sock, buf, count, 0); -#endif - -#ifdef WITH_TLS - } -#endif -} - -ssize_t net__write(struct mosquitto *mosq, void *buf, size_t count) -{ -#ifdef WITH_TLS - int ret; - int err; -#endif - assert(mosq); - - errno = 0; -#ifdef WITH_TLS - if(mosq->ssl){ - mosq->want_write = false; - ERR_clear_error(); - ret = SSL_write(mosq->ssl, buf, count); - if(ret < 0){ - err = SSL_get_error(mosq->ssl, ret); - if(err == SSL_ERROR_WANT_READ){ - ret = -1; - errno = EAGAIN; - }else if(err == SSL_ERROR_WANT_WRITE){ - ret = -1; - mosq->want_write = true; - errno = EAGAIN; - }else{ - net__print_ssl_error(mosq); - errno = EPROTO; - } -#ifdef WIN32 - WSASetLastError(errno); -#endif - } - return (ssize_t )ret; - }else{ - /* Call normal write/send */ -#endif - -#ifndef WIN32 - return write(mosq->sock, buf, count); -#else - return send(mosq->sock, buf, count, 0); -#endif - -#ifdef WITH_TLS - } -#endif -} - - -int net__socket_nonblock(mosq_sock_t *sock) -{ -#ifndef WIN32 - int opt; - /* Set non-blocking */ - opt = fcntl(*sock, F_GETFL, 0); - if(opt == -1){ - COMPAT_CLOSE(*sock); - *sock = INVALID_SOCKET; - return MOSQ_ERR_ERRNO; - } - if(fcntl(*sock, F_SETFL, opt | O_NONBLOCK) == -1){ - /* If either fcntl fails, don't want to allow this client to connect. */ - COMPAT_CLOSE(*sock); - return MOSQ_ERR_ERRNO; - } -#else - unsigned long opt = 1; - if(ioctlsocket(*sock, FIONBIO, &opt)){ - COMPAT_CLOSE(*sock); - return MOSQ_ERR_ERRNO; - } -#endif - return MOSQ_ERR_SUCCESS; -} - - -#ifndef WITH_BROKER -int net__socketpair(mosq_sock_t *pairR, mosq_sock_t *pairW) -{ -#ifdef WIN32 - int family[2] = {AF_INET, AF_INET6}; - int i; - struct sockaddr_storage ss; - struct sockaddr_in *sa = (struct sockaddr_in *)&ss; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&ss; - socklen_t ss_len; - mosq_sock_t spR, spW; - - mosq_sock_t listensock; - - *pairR = INVALID_SOCKET; - *pairW = INVALID_SOCKET; - - for(i=0; i<2; i++){ - memset(&ss, 0, sizeof(ss)); - if(family[i] == AF_INET){ - sa->sin_family = family[i]; - sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sa->sin_port = 0; - ss_len = sizeof(struct sockaddr_in); - }else if(family[i] == AF_INET6){ - sa6->sin6_family = family[i]; - sa6->sin6_addr = in6addr_loopback; - sa6->sin6_port = 0; - ss_len = sizeof(struct sockaddr_in6); - }else{ - return MOSQ_ERR_INVAL; - } - - listensock = socket(family[i], SOCK_STREAM, IPPROTO_TCP); - if(listensock == -1){ - continue; - } - - if(bind(listensock, (struct sockaddr *)&ss, ss_len) == -1){ - COMPAT_CLOSE(listensock); - continue; - } - - if(listen(listensock, 1) == -1){ - COMPAT_CLOSE(listensock); - continue; - } - memset(&ss, 0, sizeof(ss)); - ss_len = sizeof(ss); - if(getsockname(listensock, (struct sockaddr *)&ss, &ss_len) < 0){ - COMPAT_CLOSE(listensock); - continue; - } - - if(family[i] == AF_INET){ - sa->sin_family = family[i]; - sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - ss_len = sizeof(struct sockaddr_in); - }else if(family[i] == AF_INET6){ - sa6->sin6_family = family[i]; - sa6->sin6_addr = in6addr_loopback; - ss_len = sizeof(struct sockaddr_in6); - } - - spR = socket(family[i], SOCK_STREAM, IPPROTO_TCP); - if(spR == -1){ - COMPAT_CLOSE(listensock); - continue; - } - if(net__socket_nonblock(&spR)){ - COMPAT_CLOSE(listensock); - continue; - } - if(connect(spR, (struct sockaddr *)&ss, ss_len) < 0){ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){ - COMPAT_CLOSE(spR); - COMPAT_CLOSE(listensock); - continue; - } - } - spW = accept(listensock, NULL, 0); - if(spW == -1){ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){ - COMPAT_CLOSE(spR); - COMPAT_CLOSE(listensock); - continue; - } - } - - if(net__socket_nonblock(&spW)){ - COMPAT_CLOSE(spR); - COMPAT_CLOSE(listensock); - continue; - } - COMPAT_CLOSE(listensock); - - *pairR = spR; - *pairW = spW; - return MOSQ_ERR_SUCCESS; - } - return MOSQ_ERR_UNKNOWN; -#else - int sv[2]; - - if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1){ - return MOSQ_ERR_ERRNO; - } - if(net__socket_nonblock(&sv[0])){ - COMPAT_CLOSE(sv[1]); - return MOSQ_ERR_ERRNO; - } - if(net__socket_nonblock(&sv[1])){ - COMPAT_CLOSE(sv[0]); - return MOSQ_ERR_ERRNO; - } - *pairR = sv[0]; - *pairW = sv[1]; - return MOSQ_ERR_SUCCESS; -#endif -} -#endif diff --git a/libs/libmosquitto/src/net_mosq.h b/libs/libmosquitto/src/net_mosq.h deleted file mode 100644 index b843ebe388..0000000000 --- a/libs/libmosquitto/src/net_mosq.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 NET_MOSQ_H -#define NET_MOSQ_H - -#ifndef WIN32 -#include <unistd.h> -#else -#include <winsock2.h> -typedef SSIZE_T ssize_t; -#endif - -#include "mosquitto_internal.h" -#include "mosquitto.h" - -#ifdef WITH_BROKER -struct mosquitto_db; -#endif - -#ifdef WIN32 -# define COMPAT_CLOSE(a) closesocket(a) -# define COMPAT_ECONNRESET WSAECONNRESET -# define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK -#else -# define COMPAT_CLOSE(a) close(a) -# define COMPAT_ECONNRESET ECONNRESET -# define COMPAT_EWOULDBLOCK EWOULDBLOCK -#endif - -/* For when not using winsock libraries. */ -#ifndef INVALID_SOCKET -#define INVALID_SOCKET -1 -#endif - -/* Macros for accessing the MSB and LSB of a uint16_t */ -#define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8) -#define MOSQ_LSB(A) (uint8_t)(A & 0x00FF) - -int net__init(void); -void net__cleanup(void); - -int net__socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking); -#ifdef WITH_BROKER -int net__socket_close(struct mosquitto_db *db, struct mosquitto *mosq); -#else -int net__socket_close(struct mosquitto *mosq); -#endif -int net__try_connect(const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking); -int net__try_connect_step1(struct mosquitto *mosq, const char *host); -int net__try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *sock); -int net__socket_connect_step3(struct mosquitto *mosq, const char *host); -int net__socket_nonblock(mosq_sock_t *sock); -int net__socketpair(mosq_sock_t *sp1, mosq_sock_t *sp2); - -ssize_t net__read(struct mosquitto *mosq, void *buf, size_t count); -ssize_t net__write(struct mosquitto *mosq, void *buf, size_t count); - -#ifdef WITH_TLS -int net__socket_apply_tls(struct mosquitto *mosq); -int net__socket_connect_tls(struct mosquitto *mosq); -int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg); -UI_METHOD *net__get_ui_method(void); -#define ENGINE_FINISH(e) if(e) ENGINE_finish(e) -#define ENGINE_SECRET_MODE "SECRET_MODE" -#define ENGINE_SECRET_MODE_SHA 0x1000 -#define ENGINE_PIN "PIN" -#endif - -#endif diff --git a/libs/libmosquitto/src/net_mosq_ocsp.c b/libs/libmosquitto/src/net_mosq_ocsp.c deleted file mode 100644 index 32f2a3e321..0000000000 --- a/libs/libmosquitto/src/net_mosq_ocsp.c +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright (c) 2009-2014 Roger Light <roger@atchoo.org> -Copyright (c) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG), Dr. Lars Voelker <lars.voelker@bmw.de> - -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: - Dr. Lars Voelker, BMW AG -*/ - -/* -COPYRIGHT AND PERMISSION NOTICE of curl on which the ocsp code is based: - -Copyright (c) 1996 - 2016, Daniel Stenberg, <daniel@haxx.se>, and many -contributors, see the THANKS file. - -All rights reserved. - -Permission to use, copy, modify, and distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright -notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall not -be used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization of the copyright holder. -*/ - -#ifdef WITH_TLS -#include <logging_mosq.h> -#include <mosquitto_internal.h> -#include <net_mosq.h> - -#include <openssl/safestack.h> -#include <openssl/tls1.h> -#include <openssl/ssl.h> -#include <openssl/ocsp.h> - -int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg) -{ - struct mosquitto *mosq = (struct mosquitto *)arg; - int ocsp_status, result2, i; - unsigned char *p; - const unsigned char *cp; - OCSP_RESPONSE *rsp = NULL; - OCSP_BASICRESP *br = NULL; - X509_STORE *st = NULL; - STACK_OF(X509) *ch = NULL; - - long len = SSL_get_tlsext_status_ocsp_resp(mosq->ssl, &p); - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL_get_tlsext_status_ocsp_resp returned %ld bytes", len); - - // the following functions expect a const pointer - cp = (const unsigned char *)p; - - if (!cp || len <= 0) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: no response"); - goto end; - } - - - rsp = d2i_OCSP_RESPONSE(NULL, &cp, len); - if (rsp==NULL) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response"); - goto end; - } - - ocsp_status = OCSP_response_status(rsp); - if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid status: %s (%d)", - OCSP_response_status_str(ocsp_status), ocsp_status); - goto end; - } - - br = OCSP_response_get1_basic(rsp); - if (!br) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response"); - goto end; - } - - ch = SSL_get_peer_cert_chain(mosq->ssl); - if (sk_X509_num(ch) <= 0) { - log__printf(mosq, MOSQ_LOG_ERR, "OCSP: we did not receive certificates of the server (num: %d)", sk_X509_num(ch)); - goto end; - } - - st = SSL_CTX_get_cert_store(mosq->ssl_ctx); - - // Note: - // Other checkers often fix problems in OpenSSL before 1.0.2a (e.g. libcurl). - // For all currently supported versions of the OpenSSL project, this is not needed anymore. - - if ((result2=OCSP_basic_verify(br, ch, st, 0)) <= 0) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: response verification failed (error: %d)", result2); - goto end; - } - - for(i = 0; i < OCSP_resp_count(br); i++) { - int cert_status, crl_reason; - OCSP_SINGLERESP *single = NULL; - - ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; - - single = OCSP_resp_get0(br, i); - if(!single) - continue; - - cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, &thisupd, &nextupd); - - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate status: %s (%d)", - OCSP_cert_status_str(cert_status), cert_status); - - switch(cert_status) { - case V_OCSP_CERTSTATUS_GOOD: - // Note: A OCSP stapling result will be accepted up to 5 minutes after it expired! - if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: OCSP response has expired"); - goto end; - } - break; - - case V_OCSP_CERTSTATUS_REVOKED: - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation reason: %s (%d)", - OCSP_crl_reason_str(crl_reason), crl_reason); - goto end; - - case V_OCSP_CERTSTATUS_UNKNOWN: - goto end; - - default: - log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation status unknown"); - goto end; - } - } - - if (br!=NULL) OCSP_BASICRESP_free(br); - if (rsp!=NULL) OCSP_RESPONSE_free(rsp); - return 1; // OK - -end: - if (br!=NULL) OCSP_BASICRESP_free(br); - if (rsp!=NULL) OCSP_RESPONSE_free(rsp); - return 0; // Not OK -} -#endif diff --git a/libs/libmosquitto/src/options.c b/libs/libmosquitto/src/options.c deleted file mode 100644 index 7bab736628..0000000000 --- a/libs/libmosquitto/src/options.c +++ /dev/null @@ -1,486 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#ifndef WIN32 -# include <strings.h> -#endif - -#include <string.h> - -#ifdef WITH_TLS -# ifdef WIN32 -# include <winsock2.h> -# endif -# include <openssl/engine.h> -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "util_mosq.h" -#include "will_mosq.h" - - -int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain) -{ - return mosquitto_will_set_v5(mosq, topic, payloadlen, payload, qos, retain, NULL); -} - - -int mosquitto_will_set_v5(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties) -{ - int rc; - - if(!mosq) return MOSQ_ERR_INVAL; - - if(properties){ - rc = mosquitto_property_check_all(CMD_WILL, properties); - if(rc) return rc; - } - - return will__set(mosq, topic, payloadlen, payload, qos, retain, properties); -} - - -int mosquitto_will_clear(struct mosquitto *mosq) -{ - if(!mosq) return MOSQ_ERR_INVAL; - return will__clear(mosq); -} - - -int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - if(mosq->protocol == mosq_p_mqtt311 || mosq->protocol == mosq_p_mqtt31){ - if(password != NULL && username == NULL){ - return MOSQ_ERR_INVAL; - } - } - - mosquitto__free(mosq->username); - mosq->username = NULL; - - mosquitto__free(mosq->password); - mosq->password = NULL; - - if(username){ - if(mosquitto_validate_utf8(username, strlen(username))){ - return MOSQ_ERR_MALFORMED_UTF8; - } - mosq->username = mosquitto__strdup(username); - if(!mosq->username) return MOSQ_ERR_NOMEM; - } - - if(password){ - mosq->password = mosquitto__strdup(password); - if(!mosq->password){ - mosquitto__free(mosq->username); - mosq->username = NULL; - return MOSQ_ERR_NOMEM; - } - } - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - if(reconnect_delay == 0) reconnect_delay = 1; - - mosq->reconnect_delay = reconnect_delay; - mosq->reconnect_delay_max = reconnect_delay_max; - mosq->reconnect_exponential_backoff = reconnect_exponential_backoff; - - return MOSQ_ERR_SUCCESS; - -} - - -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)) -{ -#ifdef WITH_TLS - FILE *fptr; - - if(!mosq || (!cafile && !capath) || (certfile && !keyfile) || (!certfile && keyfile)) return MOSQ_ERR_INVAL; - - mosquitto__free(mosq->tls_cafile); - mosq->tls_cafile = NULL; - if(cafile){ - fptr = mosquitto__fopen(cafile, "rt", false); - if(fptr){ - fclose(fptr); - }else{ - return MOSQ_ERR_INVAL; - } - mosq->tls_cafile = mosquitto__strdup(cafile); - - if(!mosq->tls_cafile){ - return MOSQ_ERR_NOMEM; - } - } - - mosquitto__free(mosq->tls_capath); - mosq->tls_capath = NULL; - if(capath){ - mosq->tls_capath = mosquitto__strdup(capath); - if(!mosq->tls_capath){ - return MOSQ_ERR_NOMEM; - } - } - - mosquitto__free(mosq->tls_certfile); - mosq->tls_certfile = NULL; - if(certfile){ - fptr = mosquitto__fopen(certfile, "rt", false); - if(fptr){ - fclose(fptr); - }else{ - mosquitto__free(mosq->tls_cafile); - mosq->tls_cafile = NULL; - - mosquitto__free(mosq->tls_capath); - mosq->tls_capath = NULL; - return MOSQ_ERR_INVAL; - } - mosq->tls_certfile = mosquitto__strdup(certfile); - if(!mosq->tls_certfile){ - return MOSQ_ERR_NOMEM; - } - } - - mosquitto__free(mosq->tls_keyfile); - mosq->tls_keyfile = NULL; - if(keyfile){ - fptr = mosquitto__fopen(keyfile, "rt", false); - if(fptr){ - fclose(fptr); - }else{ - mosquitto__free(mosq->tls_cafile); - mosq->tls_cafile = NULL; - - mosquitto__free(mosq->tls_capath); - mosq->tls_capath = NULL; - - mosquitto__free(mosq->tls_certfile); - mosq->tls_certfile = NULL; - return MOSQ_ERR_INVAL; - } - mosq->tls_keyfile = mosquitto__strdup(keyfile); - if(!mosq->tls_keyfile){ - return MOSQ_ERR_NOMEM; - } - } - - mosq->tls_pw_callback = pw_callback; - - - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; - -#endif -} - - -int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers) -{ -#ifdef WITH_TLS - if(!mosq) return MOSQ_ERR_INVAL; - - mosq->tls_cert_reqs = cert_reqs; - if(tls_version){ - if(!strcasecmp(tls_version, "tlsv1.3") - || !strcasecmp(tls_version, "tlsv1.2") - || !strcasecmp(tls_version, "tlsv1.1")){ - - mosq->tls_version = mosquitto__strdup(tls_version); - if(!mosq->tls_version) return MOSQ_ERR_NOMEM; - }else{ - return MOSQ_ERR_INVAL; - } - }else{ - mosq->tls_version = mosquitto__strdup("tlsv1.2"); - if(!mosq->tls_version) return MOSQ_ERR_NOMEM; - } - if(ciphers){ - mosq->tls_ciphers = mosquitto__strdup(ciphers); - if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; - }else{ - mosq->tls_ciphers = NULL; - } - - - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; - -#endif -} - - -int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value) -{ -#ifdef WITH_TLS - if(!mosq) return MOSQ_ERR_INVAL; - mosq->tls_insecure = value; - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - - -int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value) -{ -#ifdef WITH_TLS - ENGINE *eng; - char *str; -#endif - - if(!mosq) return MOSQ_ERR_INVAL; - - switch(option){ - case MOSQ_OPT_TLS_ENGINE: -#ifdef WITH_TLS -# if !defined(OPENSSL_NO_ENGINE) - eng = ENGINE_by_id(value); - if(!eng){ - return MOSQ_ERR_INVAL; - } - ENGINE_free(eng); /* release the structural reference from ENGINE_by_id() */ - mosq->tls_engine = mosquitto__strdup(value); - if(!mosq->tls_engine){ - return MOSQ_ERR_NOMEM; - } - return MOSQ_ERR_SUCCESS; -#endif -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - break; - - case MOSQ_OPT_TLS_KEYFORM: -#ifdef WITH_TLS - if(!value) return MOSQ_ERR_INVAL; - if(!strcasecmp(value, "pem")){ - mosq->tls_keyform = mosq_k_pem; - }else if (!strcasecmp(value, "engine")){ - mosq->tls_keyform = mosq_k_engine; - }else{ - return MOSQ_ERR_INVAL; - } -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - break; - - - case MOSQ_OPT_TLS_ENGINE_KPASS_SHA1: -#ifdef WITH_TLS - if(mosquitto__hex2bin_sha1(value, (unsigned char**)&str) != MOSQ_ERR_SUCCESS){ - return MOSQ_ERR_INVAL; - } - mosq->tls_engine_kpass_sha1 = str; - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - break; - - case MOSQ_OPT_TLS_ALPN: -#ifdef WITH_TLS - mosq->tls_alpn = mosquitto__strdup(value); - if(!mosq->tls_alpn){ - return MOSQ_ERR_NOMEM; - } - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - break; - - default: - return MOSQ_ERR_INVAL; - } - - return MOSQ_ERR_INVAL; -} - - -int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers) -{ -#ifdef FINAL_WITH_TLS_PSK - if(!mosq || !psk || !identity) return MOSQ_ERR_INVAL; - - /* Check for hex only digits */ - if(strspn(psk, "0123456789abcdefABCDEF") < strlen(psk)){ - return MOSQ_ERR_INVAL; - } - mosq->tls_psk = mosquitto__strdup(psk); - if(!mosq->tls_psk) return MOSQ_ERR_NOMEM; - - mosq->tls_psk_identity = mosquitto__strdup(identity); - if(!mosq->tls_psk_identity){ - mosquitto__free(mosq->tls_psk); - return MOSQ_ERR_NOMEM; - } - if(ciphers){ - mosq->tls_ciphers = mosquitto__strdup(ciphers); - if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; - }else{ - mosq->tls_ciphers = NULL; - } - - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - - -int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t option, void *value) -{ - int ival; - - if(!mosq || !value) return MOSQ_ERR_INVAL; - - switch(option){ - case MOSQ_OPT_PROTOCOL_VERSION: - ival = *((int *)value); - return mosquitto_int_option(mosq, option, ival); - case MOSQ_OPT_SSL_CTX: -#ifdef WITH_TLS - mosq->ssl_ctx = (SSL_CTX *)value; - if(mosq->ssl_ctx){ -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) - SSL_CTX_up_ref(mosq->ssl_ctx); -#else - CRYPTO_add(&(mosq->ssl_ctx)->references, 1, CRYPTO_LOCK_SSL_CTX); -#endif - } - break; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - default: - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int value) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - switch(option){ - case MOSQ_OPT_PROTOCOL_VERSION: - if(value == MQTT_PROTOCOL_V31){ - mosq->protocol = mosq_p_mqtt31; - }else if(value == MQTT_PROTOCOL_V311){ - mosq->protocol = mosq_p_mqtt311; - }else if(value == MQTT_PROTOCOL_V5){ - mosq->protocol = mosq_p_mqtt5; - }else{ - return MOSQ_ERR_INVAL; - } - break; - - case MOSQ_OPT_RECEIVE_MAXIMUM: - if(value < 0 || value > 65535){ - return MOSQ_ERR_INVAL; - } - mosq->receive_maximum = value; - break; - - case MOSQ_OPT_SEND_MAXIMUM: - if(value < 0 || value > 65535){ - return MOSQ_ERR_INVAL; - } - mosq->send_maximum = value; - break; - - case MOSQ_OPT_SSL_CTX_WITH_DEFAULTS: -#if defined(WITH_TLS) && OPENSSL_VERSION_NUMBER >= 0x10100000L - if(value){ - mosq->ssl_ctx_defaults = true; - }else{ - mosq->ssl_ctx_defaults = false; - } - break; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - - case MOSQ_OPT_TLS_OCSP_REQUIRED: -#ifdef WITH_TLS - mosq->tls_ocsp_required = (bool)value; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - break; - - default: - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value) -{ - if(!mosq || !value) return MOSQ_ERR_INVAL; - - switch(option){ - case MOSQ_OPT_SSL_CTX: -#ifdef WITH_TLS - mosq->ssl_ctx = (SSL_CTX *)value; - if(mosq->ssl_ctx){ -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) - SSL_CTX_up_ref(mosq->ssl_ctx); -#else - CRYPTO_add(&(mosq->ssl_ctx)->references, 1, CRYPTO_LOCK_SSL_CTX); -#endif - } - break; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif - default: - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_SUCCESS; -} - - -void mosquitto_user_data_set(struct mosquitto *mosq, void *userdata) -{ - if(mosq){ - mosq->userdata = userdata; - } -} - -void *mosquitto_userdata(struct mosquitto *mosq) -{ - return mosq->userdata; -} diff --git a/libs/libmosquitto/src/packet_datatypes.c b/libs/libmosquitto/src/packet_datatypes.c deleted file mode 100644 index 335cb9f02d..0000000000 --- a/libs/libmosquitto/src/packet_datatypes.c +++ /dev/null @@ -1,271 +0,0 @@ -/* -Copyright (c) 2009-2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <errno.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -# ifdef WITH_WEBSOCKETS -# include <libwebsockets.h> -# endif -#else -# include "read_handle.h" -#endif - -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#ifdef WITH_BROKER -# include "sys_tree.h" -#else -# define G_BYTES_RECEIVED_INC(A) -# define G_BYTES_SENT_INC(A) -# define G_MSGS_SENT_INC(A) -# define G_PUB_MSGS_SENT_INC(A) -#endif - - -int packet__read_byte(struct mosquitto__packet *packet, uint8_t *byte) -{ - assert(packet); - if(packet->pos+1 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; - - *byte = packet->payload[packet->pos]; - packet->pos++; - - return MOSQ_ERR_SUCCESS; -} - - -void packet__write_byte(struct mosquitto__packet *packet, uint8_t byte) -{ - assert(packet); - assert(packet->pos+1 <= packet->packet_length); - - packet->payload[packet->pos] = byte; - packet->pos++; -} - - -int packet__read_bytes(struct mosquitto__packet *packet, void *bytes, uint32_t count) -{ - assert(packet); - if(packet->pos+count > packet->remaining_length) return MOSQ_ERR_PROTOCOL; - - memcpy(bytes, &(packet->payload[packet->pos]), count); - packet->pos += count; - - return MOSQ_ERR_SUCCESS; -} - - -void packet__write_bytes(struct mosquitto__packet *packet, const void *bytes, uint32_t count) -{ - assert(packet); - assert(packet->pos+count <= packet->packet_length); - - memcpy(&(packet->payload[packet->pos]), bytes, count); - packet->pos += count; -} - - -int packet__read_binary(struct mosquitto__packet *packet, uint8_t **data, int *length) -{ - uint16_t slen; - int rc; - - assert(packet); - rc = packet__read_uint16(packet, &slen); - if(rc) return rc; - - if(slen == 0){ - *data = NULL; - *length = 0; - return MOSQ_ERR_SUCCESS; - } - - if(packet->pos+slen > packet->remaining_length) return MOSQ_ERR_PROTOCOL; - - *data = mosquitto__malloc(slen+1); - if(*data){ - memcpy(*data, &(packet->payload[packet->pos]), slen); - ((uint8_t *)(*data))[slen] = '\0'; - packet->pos += slen; - }else{ - return MOSQ_ERR_NOMEM; - } - - *length = slen; - return MOSQ_ERR_SUCCESS; -} - - -int packet__read_string(struct mosquitto__packet *packet, char **str, int *length) -{ - int rc; - - rc = packet__read_binary(packet, (uint8_t **)str, length); - if(rc) return rc; - if(*length == 0) return MOSQ_ERR_SUCCESS; - - if(mosquitto_validate_utf8(*str, *length)){ - mosquitto__free(*str); - *str = NULL; - *length = -1; - return MOSQ_ERR_MALFORMED_UTF8; - } - - return MOSQ_ERR_SUCCESS; -} - - -void packet__write_string(struct mosquitto__packet *packet, const char *str, uint16_t length) -{ - assert(packet); - packet__write_uint16(packet, length); - packet__write_bytes(packet, str, length); -} - - -int packet__read_uint16(struct mosquitto__packet *packet, uint16_t *word) -{ - uint8_t msb, lsb; - - assert(packet); - if(packet->pos+2 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; - - msb = packet->payload[packet->pos]; - packet->pos++; - lsb = packet->payload[packet->pos]; - packet->pos++; - - *word = (msb<<8) + lsb; - - return MOSQ_ERR_SUCCESS; -} - - -void packet__write_uint16(struct mosquitto__packet *packet, uint16_t word) -{ - packet__write_byte(packet, MOSQ_MSB(word)); - packet__write_byte(packet, MOSQ_LSB(word)); -} - - -int packet__read_uint32(struct mosquitto__packet *packet, uint32_t *word) -{ - uint32_t val = 0; - int i; - - assert(packet); - if(packet->pos+4 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; - - for(i=0; i<4; i++){ - val = (val << 8) + packet->payload[packet->pos]; - packet->pos++; - } - - *word = val; - - return MOSQ_ERR_SUCCESS; -} - - -void packet__write_uint32(struct mosquitto__packet *packet, uint32_t word) -{ - packet__write_byte(packet, (word & 0xFF000000) >> 24); - packet__write_byte(packet, (word & 0x00FF0000) >> 16); - packet__write_byte(packet, (word & 0x0000FF00) >> 8); - packet__write_byte(packet, (word & 0x000000FF)); -} - - -int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, int8_t *bytes) -{ - int i; - uint8_t byte; - int remaining_mult = 1; - int32_t lword = 0; - uint8_t lbytes = 0; - - for(i=0; i<4; i++){ - if(packet->pos < packet->remaining_length){ - lbytes++; - byte = packet->payload[packet->pos]; - lword += (byte & 127) * remaining_mult; - remaining_mult *= 128; - packet->pos++; - if((byte & 128) == 0){ - if(lbytes > 1 && byte == 0){ - /* Catch overlong encodings */ - return MOSQ_ERR_PROTOCOL; - }else{ - *word = lword; - if(bytes) (*bytes) = lbytes; - return MOSQ_ERR_SUCCESS; - } - } - }else{ - return MOSQ_ERR_PROTOCOL; - } - } - return MOSQ_ERR_PROTOCOL; -} - - -int packet__write_varint(struct mosquitto__packet *packet, int32_t word) -{ - uint8_t byte; - int count = 0; - - do{ - byte = word % 128; - word = word / 128; - /* If there are more digits to encode, set the top bit of this digit */ - if(word > 0){ - byte = byte | 0x80; - } - packet__write_byte(packet, byte); - count++; - }while(word > 0 && count < 5); - - if(count == 5){ - return MOSQ_ERR_PROTOCOL; - } - return MOSQ_ERR_SUCCESS; -} - - -int packet__varint_bytes(int32_t word) -{ - if(word < 128){ - return 1; - }else if(word < 16384){ - return 2; - }else if(word < 2097152){ - return 3; - }else if(word < 268435456){ - return 4; - }else{ - return 5; - } -} diff --git a/libs/libmosquitto/src/packet_mosq.c b/libs/libmosquitto/src/packet_mosq.c deleted file mode 100644 index 0f7af7426c..0000000000 --- a/libs/libmosquitto/src/packet_mosq.c +++ /dev/null @@ -1,456 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <errno.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -# ifdef WITH_WEBSOCKETS -# include <libwebsockets.h> -# endif -#else -# include "read_handle.h" -#endif - -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#ifdef WITH_BROKER -# include "sys_tree.h" -# include "send_mosq.h" -#else -# define G_BYTES_RECEIVED_INC(A) -# define G_BYTES_SENT_INC(A) -# define G_MSGS_SENT_INC(A) -# define G_PUB_MSGS_SENT_INC(A) -#endif - -int packet__alloc(struct mosquitto__packet *packet) -{ - uint8_t remaining_bytes[5], byte; - uint32_t remaining_length; - int i; - - assert(packet); - - remaining_length = packet->remaining_length; - packet->payload = NULL; - packet->remaining_count = 0; - do{ - byte = remaining_length % 128; - remaining_length = remaining_length / 128; - /* If there are more digits to encode, set the top bit of this digit */ - if(remaining_length > 0){ - byte = byte | 0x80; - } - remaining_bytes[packet->remaining_count] = byte; - packet->remaining_count++; - }while(remaining_length > 0 && packet->remaining_count < 5); - if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE; - packet->packet_length = packet->remaining_length + 1 + packet->remaining_count; -#ifdef WITH_WEBSOCKETS - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length + LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING); -#else - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); -#endif - if(!packet->payload) return MOSQ_ERR_NOMEM; - - packet->payload[0] = packet->command; - for(i=0; i<packet->remaining_count; i++){ - packet->payload[i+1] = remaining_bytes[i]; - } - packet->pos = 1 + packet->remaining_count; - - return MOSQ_ERR_SUCCESS; -} - -void packet__cleanup(struct mosquitto__packet *packet) -{ - if(!packet) return; - - /* Free data and reset values */ - packet->command = 0; - packet->remaining_count = 0; - packet->remaining_mult = 1; - packet->remaining_length = 0; - mosquitto__free(packet->payload); - packet->payload = NULL; - packet->to_process = 0; - packet->pos = 0; -} - -int packet__queue(struct mosquitto *mosq, struct mosquitto__packet *packet) -{ -#ifndef WITH_BROKER - char sockpair_data = 0; -#endif - assert(mosq); - assert(packet); - - packet->pos = 0; - packet->to_process = packet->packet_length; - - packet->next = NULL; - pthread_mutex_lock(&mosq->out_packet_mutex); - if(mosq->out_packet){ - mosq->out_packet_last->next = packet; - }else{ - mosq->out_packet = packet; - } - mosq->out_packet_last = packet; - pthread_mutex_unlock(&mosq->out_packet_mutex); -#ifdef WITH_BROKER -# ifdef WITH_WEBSOCKETS - if(mosq->wsi){ - libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi); - return MOSQ_ERR_SUCCESS; - }else{ - return packet__write(mosq); - } -# else - return packet__write(mosq); -# endif -#else - - /* Write a single byte to sockpairW (connected to sockpairR) to break out - * of select() if in threaded mode. */ - if(mosq->sockpairW != INVALID_SOCKET){ -#ifndef WIN32 - if(write(mosq->sockpairW, &sockpair_data, 1)){ - } -#else - send(mosq->sockpairW, &sockpair_data, 1, 0); -#endif - } - - if(mosq->in_callback == false && mosq->threaded == mosq_ts_none){ - return packet__write(mosq); - }else{ - return MOSQ_ERR_SUCCESS; - } -#endif -} - - -int packet__check_oversize(struct mosquitto *mosq, uint32_t remaining_length) -{ - uint32_t len; - - if(mosq->maximum_packet_size == 0) return MOSQ_ERR_SUCCESS; - - len = remaining_length + packet__varint_bytes(remaining_length); - if(len > mosq->maximum_packet_size){ - return MOSQ_ERR_OVERSIZE_PACKET; - }else{ - return MOSQ_ERR_SUCCESS; - } -} - - -int packet__write(struct mosquitto *mosq) -{ - ssize_t write_length; - struct mosquitto__packet *packet; - - if(!mosq) return MOSQ_ERR_INVAL; - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - - pthread_mutex_lock(&mosq->current_out_packet_mutex); - pthread_mutex_lock(&mosq->out_packet_mutex); - if(mosq->out_packet && !mosq->current_out_packet){ - mosq->current_out_packet = mosq->out_packet; - mosq->out_packet = mosq->out_packet->next; - if(!mosq->out_packet){ - mosq->out_packet_last = NULL; - } - } - pthread_mutex_unlock(&mosq->out_packet_mutex); - -#if defined(WITH_TLS) && !defined(WITH_BROKER) - if((mosq->state == mosq_cs_connect_pending) || mosq->want_connect){ -#else - if(mosq->state == mosq_cs_connect_pending){ -#endif - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - return MOSQ_ERR_SUCCESS; - } - - while(mosq->current_out_packet){ - packet = mosq->current_out_packet; - - while(packet->to_process > 0){ - write_length = net__write(mosq, &(packet->payload[packet->pos]), packet->to_process); - if(write_length > 0){ - G_BYTES_SENT_INC(write_length); - packet->to_process -= write_length; - packet->pos += write_length; - }else{ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - return MOSQ_ERR_SUCCESS; - }else{ - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - switch(errno){ - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - - G_MSGS_SENT_INC(1); - if(((packet->command)&0xF6) == CMD_PUBLISH){ - G_PUB_MSGS_SENT_INC(1); -#ifndef WITH_BROKER - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_publish){ - /* This is a QoS=0 message */ - mosq->in_callback = true; - mosq->on_publish(mosq, mosq->userdata, packet->mid); - mosq->in_callback = false; - } - if(mosq->on_publish_v5){ - /* This is a QoS=0 message */ - mosq->in_callback = true; - mosq->on_publish_v5(mosq, mosq->userdata, packet->mid, 0, NULL); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - }else if(((packet->command)&0xF0) == CMD_DISCONNECT){ - do_client_disconnect(mosq, MOSQ_ERR_SUCCESS, NULL); - packet__cleanup(packet); - mosquitto__free(packet); - return MOSQ_ERR_SUCCESS; -#endif - } - - /* Free data and reset values */ - pthread_mutex_lock(&mosq->out_packet_mutex); - mosq->current_out_packet = mosq->out_packet; - if(mosq->out_packet){ - mosq->out_packet = mosq->out_packet->next; - if(!mosq->out_packet){ - mosq->out_packet_last = NULL; - } - } - pthread_mutex_unlock(&mosq->out_packet_mutex); - - packet__cleanup(packet); - mosquitto__free(packet); - - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->next_msg_out = mosquitto_time() + mosq->keepalive; - pthread_mutex_unlock(&mosq->msgtime_mutex); - } - pthread_mutex_unlock(&mosq->current_out_packet_mutex); - return MOSQ_ERR_SUCCESS; -} - - -#ifdef WITH_BROKER -int packet__read(struct mosquitto_db *db, struct mosquitto *mosq) -#else -int packet__read(struct mosquitto *mosq) -#endif -{ - uint8_t byte; - ssize_t read_length; - int rc = 0; - - if(!mosq){ - return MOSQ_ERR_INVAL; - } - if(mosq->sock == INVALID_SOCKET){ - return MOSQ_ERR_NO_CONN; - } - if(mosq->state == mosq_cs_connect_pending){ - return MOSQ_ERR_SUCCESS; - } - - /* This gets called if pselect() indicates that there is network data - * available - ie. at least one byte. What we do depends on what data we - * already have. - * If we've not got a command, attempt to read one and save it. This should - * always work because it's only a single byte. - * Then try to read the remaining length. This may fail because it is may - * be more than one byte - will need to save data pending next read if it - * does fail. - * Then try to read the remaining payload, where 'payload' here means the - * combined variable header and actual payload. This is the most likely to - * fail due to longer length, so save current data and current position. - * After all data is read, send to mosquitto__handle_packet() to deal with. - * Finally, free the memory and reset everything to starting conditions. - */ - if(!mosq->in_packet.command){ - read_length = net__read(mosq, &byte, 1); - if(read_length == 1){ - mosq->in_packet.command = byte; -#ifdef WITH_BROKER - G_BYTES_RECEIVED_INC(1); - /* Clients must send CONNECT as their first command. */ - if(!(mosq->bridge) && mosq->state == mosq_cs_new && (byte&0xF0) != CMD_CONNECT){ - return MOSQ_ERR_PROTOCOL; - } -#endif - }else{ - if(read_length == 0){ - return MOSQ_ERR_CONN_LOST; /* EOF */ - } -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return MOSQ_ERR_SUCCESS; - }else{ - switch(errno){ - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - /* remaining_count is the number of bytes that the remaining_length - * parameter occupied in this incoming packet. We don't use it here as such - * (it is used when allocating an outgoing packet), but we must be able to - * determine whether all of the remaining_length parameter has been read. - * remaining_count has three states here: - * 0 means that we haven't read any remaining_length bytes - * <0 means we have read some remaining_length bytes but haven't finished - * >0 means we have finished reading the remaining_length bytes. - */ - if(mosq->in_packet.remaining_count <= 0){ - do{ - read_length = net__read(mosq, &byte, 1); - if(read_length == 1){ - mosq->in_packet.remaining_count--; - /* Max 4 bytes length for remaining length as defined by protocol. - * Anything more likely means a broken/malicious client. - */ - if(mosq->in_packet.remaining_count < -4){ - return MOSQ_ERR_PROTOCOL; - } - - G_BYTES_RECEIVED_INC(1); - mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult; - mosq->in_packet.remaining_mult *= 128; - }else{ - if(read_length == 0){ - return MOSQ_ERR_CONN_LOST; /* EOF */ - } -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return MOSQ_ERR_SUCCESS; - }else{ - switch(errno){ - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - }while((byte & 128) != 0); - /* We have finished reading remaining_length, so make remaining_count - * positive. */ - mosq->in_packet.remaining_count *= -1; - -#ifdef WITH_BROKER - if(db->config->max_packet_size > 0 && mosq->in_packet.remaining_length+1 > db->config->max_packet_size){ - log__printf(NULL, MOSQ_LOG_INFO, "Client %s sent too large packet %d, disconnecting.", mosq->id, mosq->in_packet.remaining_length+1); - if(mosq->protocol == mosq_p_mqtt5){ - send__disconnect(mosq, MQTT_RC_PACKET_TOO_LARGE, NULL); - } - return MOSQ_ERR_OVERSIZE_PACKET; - } -#else - // FIXME - client case for incoming message received from broker too large -#endif - if(mosq->in_packet.remaining_length > 0){ - mosq->in_packet.payload = mosquitto__malloc(mosq->in_packet.remaining_length*sizeof(uint8_t)); - if(!mosq->in_packet.payload){ - return MOSQ_ERR_NOMEM; - } - mosq->in_packet.to_process = mosq->in_packet.remaining_length; - } - } - while(mosq->in_packet.to_process>0){ - read_length = net__read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); - if(read_length > 0){ - G_BYTES_RECEIVED_INC(read_length); - mosq->in_packet.to_process -= read_length; - mosq->in_packet.pos += read_length; - }else{ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - if(mosq->in_packet.to_process > 1000){ - /* Update last_msg_in time if more than 1000 bytes left to - * receive. Helps when receiving large messages. - * This is an arbitrary limit, but with some consideration. - * If a client can't send 1000 bytes in a second it - * probably shouldn't be using a 1 second keep alive. */ - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->last_msg_in = mosquitto_time(); - pthread_mutex_unlock(&mosq->msgtime_mutex); - } - return MOSQ_ERR_SUCCESS; - }else{ - switch(errno){ - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - - /* All data for this packet is read. */ - mosq->in_packet.pos = 0; -#ifdef WITH_BROKER - G_MSGS_RECEIVED_INC(1); - if(((mosq->in_packet.command)&0xF5) == CMD_PUBLISH){ - G_PUB_MSGS_RECEIVED_INC(1); - } - rc = handle__packet(db, mosq); -#else - rc = handle__packet(mosq); -#endif - - /* Free data and reset values */ - packet__cleanup(&mosq->in_packet); - - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->last_msg_in = mosquitto_time(); - pthread_mutex_unlock(&mosq->msgtime_mutex); - return rc; -} diff --git a/libs/libmosquitto/src/packet_mosq.h b/libs/libmosquitto/src/packet_mosq.h deleted file mode 100644 index 5967f09406..0000000000 --- a/libs/libmosquitto/src/packet_mosq.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 PACKET_MOSQ_H -#define PACKET_MOSQ_H - -#include "mosquitto_internal.h" -#include "mosquitto.h" - -#ifdef WITH_BROKER -struct mosquitto_db; -#endif - -int packet__alloc(struct mosquitto__packet *packet); -void packet__cleanup(struct mosquitto__packet *packet); -int packet__queue(struct mosquitto *mosq, struct mosquitto__packet *packet); - -int packet__check_oversize(struct mosquitto *mosq, uint32_t remaining_length); - -int packet__read_byte(struct mosquitto__packet *packet, uint8_t *byte); -int packet__read_bytes(struct mosquitto__packet *packet, void *bytes, uint32_t count); -int packet__read_binary(struct mosquitto__packet *packet, uint8_t **data, int *length); -int packet__read_string(struct mosquitto__packet *packet, char **str, int *length); -int packet__read_uint16(struct mosquitto__packet *packet, uint16_t *word); -int packet__read_uint32(struct mosquitto__packet *packet, uint32_t *word); -int packet__read_varint(struct mosquitto__packet *packet, int32_t *word, int8_t *bytes); - -void packet__write_byte(struct mosquitto__packet *packet, uint8_t byte); -void packet__write_bytes(struct mosquitto__packet *packet, const void *bytes, uint32_t count); -void packet__write_string(struct mosquitto__packet *packet, const char *str, uint16_t length); -void packet__write_uint16(struct mosquitto__packet *packet, uint16_t word); -void packet__write_uint32(struct mosquitto__packet *packet, uint32_t word); -int packet__write_varint(struct mosquitto__packet *packet, int32_t word); - -int packet__varint_bytes(int32_t word); - -int packet__write(struct mosquitto *mosq); -#ifdef WITH_BROKER -int packet__read(struct mosquitto_db *db, struct mosquitto *mosq); -#else -int packet__read(struct mosquitto *mosq); -#endif - -#endif diff --git a/libs/libmosquitto/src/property_mosq.c b/libs/libmosquitto/src/property_mosq.c deleted file mode 100644 index 76158e584d..0000000000 --- a/libs/libmosquitto/src/property_mosq.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* -Copyright (c) 2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <errno.h> -#include <string.h> - -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" - - -int property__read(struct mosquitto__packet *packet, int32_t *len, mosquitto_property *property) -{ - int rc; - int32_t property_identifier; - uint8_t byte; - int8_t byte_count; - uint16_t uint16; - uint32_t uint32; - int32_t varint; - char *str1, *str2; - int slen1, slen2; - - if(!property) return MOSQ_ERR_INVAL; - - rc = packet__read_varint(packet, &property_identifier, NULL); - if(rc) return rc; - *len -= 1; - - memset(property, 0, sizeof(mosquitto_property)); - - property->identifier = property_identifier; - - switch(property_identifier){ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - rc = packet__read_byte(packet, &byte); - if(rc) return rc; - *len -= 1; /* byte */ - property->value.i8 = byte; - break; - - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS: - rc = packet__read_uint16(packet, &uint16); - if(rc) return rc; - *len -= 2; /* uint16 */ - property->value.i16 = uint16; - break; - - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - case MQTT_PROP_WILL_DELAY_INTERVAL: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - rc = packet__read_uint32(packet, &uint32); - if(rc) return rc; - *len -= 4; /* uint32 */ - property->value.i32 = uint32; - break; - - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - rc = packet__read_varint(packet, &varint, &byte_count); - if(rc) return rc; - *len -= byte_count; - property->value.varint = varint; - break; - - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_SERVER_REFERENCE: - case MQTT_PROP_REASON_STRING: - rc = packet__read_string(packet, &str1, &slen1); - if(rc) return rc; - *len = (*len) - 2 - slen1; /* uint16, string len */ - property->value.s.v = str1; - property->value.s.len = slen1; - break; - - case MQTT_PROP_AUTHENTICATION_DATA: - case MQTT_PROP_CORRELATION_DATA: - rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1); - if(rc) return rc; - *len = (*len) - 2 - slen1; /* uint16, binary len */ - property->value.bin.v = str1; - property->value.bin.len = slen1; - break; - - case MQTT_PROP_USER_PROPERTY: - rc = packet__read_string(packet, &str1, &slen1); - if(rc) return rc; - *len = (*len) - 2 - slen1; /* uint16, string len */ - - rc = packet__read_string(packet, &str2, &slen2); - if(rc){ - mosquitto__free(str1); - return rc; - } - *len = (*len) - 2 - slen2; /* uint16, string len */ - - property->name.v = str1; - property->name.len = slen1; - property->value.s.v = str2; - property->value.s.len = slen2; - break; - - default: - log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier); - return MOSQ_ERR_MALFORMED_PACKET; - } - - return MOSQ_ERR_SUCCESS; -} - - -int property__read_all(int command, struct mosquitto__packet *packet, mosquitto_property **properties) -{ - int rc; - int32_t proplen; - mosquitto_property *p, *tail = NULL; - - rc = packet__read_varint(packet, &proplen, NULL); - if(rc) return rc; - - *properties = NULL; - - /* The order of properties must be preserved for some types, so keep the - * same order for all */ - while(proplen > 0){ - p = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!p){ - mosquitto_property_free_all(properties); - return MOSQ_ERR_NOMEM; - } - - rc = property__read(packet, &proplen, p); - if(rc){ - mosquitto__free(p); - mosquitto_property_free_all(properties); - return rc; - } - - if(!(*properties)){ - *properties = p; - }else{ - tail->next = p; - } - tail = p; - - } - - rc = mosquitto_property_check_all(command, *properties); - if(rc){ - mosquitto_property_free_all(properties); - return rc; - } - return MOSQ_ERR_SUCCESS; -} - - -void property__free(mosquitto_property **property) -{ - if(!property || !(*property)) return; - - switch((*property)->identifier){ - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_SERVER_REFERENCE: - case MQTT_PROP_REASON_STRING: - mosquitto__free((*property)->value.s.v); - break; - - case MQTT_PROP_AUTHENTICATION_DATA: - case MQTT_PROP_CORRELATION_DATA: - mosquitto__free((*property)->value.bin.v); - break; - - case MQTT_PROP_USER_PROPERTY: - mosquitto__free((*property)->name.v); - mosquitto__free((*property)->value.s.v); - break; - - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_WILL_DELAY_INTERVAL: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - /* Nothing to free */ - break; - } - - free(*property); - *property = NULL; -} - - -void mosquitto_property_free_all(mosquitto_property **property) -{ - mosquitto_property *p, *next; - - if(!property) return; - - p = *property; - while(p){ - next = p->next; - property__free(&p); - p = next; - } - *property = NULL; -} - - -int property__get_length(const mosquitto_property *property) -{ - if(!property) return 0; - - switch(property->identifier){ - /* Byte */ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - return 2; /* 1 (identifier) + 1 byte */ - - /* uint16 */ - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS: - return 3; /* 1 (identifier) + 2 bytes */ - - /* uint32 */ - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_WILL_DELAY_INTERVAL: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - return 5; /* 1 (identifier) + 4 bytes */ - - /* varint */ - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - if(property->value.varint < 128){ - return 2; - }else if(property->value.varint < 16384){ - return 3; - }else if(property->value.varint < 2097152){ - return 4; - }else if(property->value.varint < 268435456){ - return 5; - }else{ - return 0; - } - - /* binary */ - case MQTT_PROP_CORRELATION_DATA: - case MQTT_PROP_AUTHENTICATION_DATA: - return 3 + property->value.bin.len; /* 1 + 2 bytes (len) + X bytes (payload) */ - - /* string */ - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_SERVER_REFERENCE: - case MQTT_PROP_REASON_STRING: - return 3 + property->value.s.len; /* 1 + 2 bytes (len) + X bytes (string) */ - - /* string pair */ - case MQTT_PROP_USER_PROPERTY: - return 5 + property->value.s.len + property->name.len; /* 1 + 2*(2 bytes (len) + X bytes (string))*/ - - default: - return 0; - } - return 0; -} - - -int property__get_length_all(const mosquitto_property *property) -{ - const mosquitto_property *p; - int len = 0; - - p = property; - while(p){ - len += property__get_length(p); - p = p->next; - } - return len; -} - - -int property__write(struct mosquitto__packet *packet, const mosquitto_property *property) -{ - int rc; - - rc = packet__write_varint(packet, property->identifier); - if(rc) return rc; - - switch(property->identifier){ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - packet__write_byte(packet, property->value.i8); - break; - - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS: - packet__write_uint16(packet, property->value.i16); - break; - - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - case MQTT_PROP_WILL_DELAY_INTERVAL: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - packet__write_uint32(packet, property->value.i32); - break; - - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - return packet__write_varint(packet, property->value.varint); - - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_SERVER_REFERENCE: - case MQTT_PROP_REASON_STRING: - packet__write_string(packet, property->value.s.v, property->value.s.len); - break; - - case MQTT_PROP_AUTHENTICATION_DATA: - case MQTT_PROP_CORRELATION_DATA: - packet__write_uint16(packet, property->value.bin.len); - packet__write_bytes(packet, property->value.bin.v, property->value.bin.len); - break; - - case MQTT_PROP_USER_PROPERTY: - packet__write_string(packet, property->name.v, property->name.len); - packet__write_string(packet, property->value.s.v, property->value.s.len); - break; - - default: - log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier); - return MOSQ_ERR_INVAL; - } - - return MOSQ_ERR_SUCCESS; -} - - -int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len) -{ - int rc; - const mosquitto_property *p; - - if(write_len){ - rc = packet__write_varint(packet, property__get_length_all(properties)); - if(rc) return rc; - } - - p = properties; - while(p){ - rc = property__write(packet, p); - if(rc) return rc; - p = p->next; - } - - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_check_command(int command, int identifier) -{ - switch(identifier){ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_CORRELATION_DATA: - if(command != CMD_PUBLISH && command != CMD_WILL){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - if(command != CMD_PUBLISH && command != CMD_SUBSCRIBE){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_DISCONNECT){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_AUTHENTICATION_DATA: - if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_AUTH){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - if(command != CMD_CONNACK){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_WILL_DELAY_INTERVAL: - if(command != CMD_WILL){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - if(command != CMD_CONNECT){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_SERVER_REFERENCE: - if(command != CMD_CONNACK && command != CMD_DISCONNECT){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_REASON_STRING: - if(command == CMD_CONNECT || command == CMD_PUBLISH || command == CMD_SUBSCRIBE || command == CMD_UNSUBSCRIBE){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - if(command != CMD_CONNECT && command != CMD_CONNACK){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_TOPIC_ALIAS: - if(command != CMD_PUBLISH){ - return MOSQ_ERR_PROTOCOL; - } - break; - - case MQTT_PROP_USER_PROPERTY: - break; - - default: - return MOSQ_ERR_PROTOCOL; - } - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type) -{ - if(!propname) return MOSQ_ERR_INVAL; - - if(!strcasecmp(propname, "payload-format-indicator")){ - *identifier = MQTT_PROP_PAYLOAD_FORMAT_INDICATOR; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "message-expiry-interval")){ - *identifier = MQTT_PROP_MESSAGE_EXPIRY_INTERVAL; - *type = MQTT_PROP_TYPE_INT32; - }else if(!strcasecmp(propname, "content-type")){ - *identifier = MQTT_PROP_CONTENT_TYPE; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "response-topic")){ - *identifier = MQTT_PROP_RESPONSE_TOPIC; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "correlation-data")){ - *identifier = MQTT_PROP_CORRELATION_DATA; - *type = MQTT_PROP_TYPE_BINARY; - }else if(!strcasecmp(propname, "subscription-identifier")){ - *identifier = MQTT_PROP_SUBSCRIPTION_IDENTIFIER; - *type = MQTT_PROP_TYPE_VARINT; - }else if(!strcasecmp(propname, "session-expiry-interval")){ - *identifier = MQTT_PROP_SESSION_EXPIRY_INTERVAL; - *type = MQTT_PROP_TYPE_INT32; - }else if(!strcasecmp(propname, "assigned-client-identifier")){ - *identifier = MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "server-keep-alive")){ - *identifier = MQTT_PROP_SERVER_KEEP_ALIVE; - *type = MQTT_PROP_TYPE_INT16; - }else if(!strcasecmp(propname, "authentication-method")){ - *identifier = MQTT_PROP_AUTHENTICATION_METHOD; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "authentication-data")){ - *identifier = MQTT_PROP_AUTHENTICATION_DATA; - *type = MQTT_PROP_TYPE_BINARY; - }else if(!strcasecmp(propname, "request-problem-information")){ - *identifier = MQTT_PROP_REQUEST_PROBLEM_INFORMATION; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "will-delay-interval")){ - *identifier = MQTT_PROP_WILL_DELAY_INTERVAL; - *type = MQTT_PROP_TYPE_INT32; - }else if(!strcasecmp(propname, "request-response-information")){ - *identifier = MQTT_PROP_REQUEST_RESPONSE_INFORMATION; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "response-information")){ - *identifier = MQTT_PROP_RESPONSE_INFORMATION; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "server-reference")){ - *identifier = MQTT_PROP_SERVER_REFERENCE; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "reason-string")){ - *identifier = MQTT_PROP_REASON_STRING; - *type = MQTT_PROP_TYPE_STRING; - }else if(!strcasecmp(propname, "receive-maximum")){ - *identifier = MQTT_PROP_RECEIVE_MAXIMUM; - *type = MQTT_PROP_TYPE_INT16; - }else if(!strcasecmp(propname, "topic-alias-maximum")){ - *identifier = MQTT_PROP_TOPIC_ALIAS_MAXIMUM; - *type = MQTT_PROP_TYPE_INT16; - }else if(!strcasecmp(propname, "topic-alias")){ - *identifier = MQTT_PROP_TOPIC_ALIAS; - *type = MQTT_PROP_TYPE_INT16; - }else if(!strcasecmp(propname, "maximum-qos")){ - *identifier = MQTT_PROP_MAXIMUM_QOS; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "retain-available")){ - *identifier = MQTT_PROP_RETAIN_AVAILABLE; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "user-property")){ - *identifier = MQTT_PROP_USER_PROPERTY; - *type = MQTT_PROP_TYPE_STRING_PAIR; - }else if(!strcasecmp(propname, "maximum-packet-size")){ - *identifier = MQTT_PROP_MAXIMUM_PACKET_SIZE; - *type = MQTT_PROP_TYPE_INT32; - }else if(!strcasecmp(propname, "wildcard-subscription-available")){ - *identifier = MQTT_PROP_WILDCARD_SUB_AVAILABLE; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "subscription-identifier-available")){ - *identifier = MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE; - *type = MQTT_PROP_TYPE_BYTE; - }else if(!strcasecmp(propname, "shared-subscription-available")){ - *identifier = MQTT_PROP_SHARED_SUB_AVAILABLE; - *type = MQTT_PROP_TYPE_BYTE; - }else{ - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_SUCCESS; -} - - -static void property__add(mosquitto_property **proplist, struct mqtt5__property *prop) -{ - mosquitto_property *p; - - if(!(*proplist)){ - *proplist = prop; - } - - p = *proplist; - while(p->next){ - p = p->next; - } - p->next = prop; - prop->next = NULL; -} - - -int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, uint8_t value) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR - && identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION - && identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION - && identifier != MQTT_PROP_MAXIMUM_QOS - && identifier != MQTT_PROP_RETAIN_AVAILABLE - && identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE - && identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - && identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ - return MOSQ_ERR_INVAL; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - prop->value.i8 = value; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier, uint16_t value) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_SERVER_KEEP_ALIVE - && identifier != MQTT_PROP_RECEIVE_MAXIMUM - && identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM - && identifier != MQTT_PROP_TOPIC_ALIAS){ - return MOSQ_ERR_INVAL; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - prop->value.i16 = value; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier, uint32_t value) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL - && identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL - && identifier != MQTT_PROP_WILL_DELAY_INTERVAL - && identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){ - - return MOSQ_ERR_INVAL; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - prop->value.i32 = value; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value) -{ - mosquitto_property *prop; - - if(!proplist || value > 268435455) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER) return MOSQ_ERR_INVAL; - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - prop->value.varint = value; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier, const void *value, uint16_t len) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_CORRELATION_DATA - && identifier != MQTT_PROP_AUTHENTICATION_DATA){ - - return MOSQ_ERR_INVAL; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - - if(len){ - prop->value.bin.v = mosquitto__malloc(len); - if(!prop->value.bin.v){ - mosquitto__free(prop); - return MOSQ_ERR_NOMEM; - } - - memcpy(prop->value.bin.v, value, len); - prop->value.bin.len = len; - } - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(value){ - if(mosquitto_validate_utf8(value, strlen(value))) return MOSQ_ERR_MALFORMED_UTF8; - } - - if(identifier != MQTT_PROP_CONTENT_TYPE - && identifier != MQTT_PROP_RESPONSE_TOPIC - && identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER - && identifier != MQTT_PROP_AUTHENTICATION_METHOD - && identifier != MQTT_PROP_RESPONSE_INFORMATION - && identifier != MQTT_PROP_SERVER_REFERENCE - && identifier != MQTT_PROP_REASON_STRING){ - - return MOSQ_ERR_INVAL; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - if(value && strlen(value)){ - prop->value.s.v = mosquitto__strdup(value); - if(!prop->value.s.v){ - mosquitto__free(prop); - return MOSQ_ERR_NOMEM; - } - prop->value.s.len = strlen(value); - } - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value) -{ - mosquitto_property *prop; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; - if(name){ - if(mosquitto_validate_utf8(name, strlen(name))) return MOSQ_ERR_MALFORMED_UTF8; - } - if(value){ - if(mosquitto_validate_utf8(value, strlen(value))) return MOSQ_ERR_MALFORMED_UTF8; - } - - prop = mosquitto__calloc(1, sizeof(mosquitto_property)); - if(!prop) return MOSQ_ERR_NOMEM; - - prop->client_generated = true; - prop->identifier = identifier; - - if(name && strlen(name)){ - prop->name.v = mosquitto__strdup(name); - if(!prop->name.v){ - mosquitto__free(prop); - return MOSQ_ERR_NOMEM; - } - prop->name.len = strlen(name); - } - - if(value && strlen(value)){ - prop->value.s.v = mosquitto__strdup(value); - if(!prop->value.s.v){ - mosquitto__free(prop->name.v); - mosquitto__free(prop); - return MOSQ_ERR_NOMEM; - } - prop->value.s.len = strlen(value); - } - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - -int mosquitto_property_check_all(int command, const mosquitto_property *properties) -{ - const mosquitto_property *p, *tail; - int rc; - - p = properties; - - while(p){ - /* Validity checks */ - if(p->identifier == MQTT_PROP_REQUEST_PROBLEM_INFORMATION - || p->identifier == MQTT_PROP_REQUEST_RESPONSE_INFORMATION - || p->identifier == MQTT_PROP_MAXIMUM_QOS - || p->identifier == MQTT_PROP_RETAIN_AVAILABLE - || p->identifier == MQTT_PROP_WILDCARD_SUB_AVAILABLE - || p->identifier == MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - || p->identifier == MQTT_PROP_SHARED_SUB_AVAILABLE){ - - if(p->value.i8 > 1){ - return MOSQ_ERR_PROTOCOL; - } - }else if(p->identifier == MQTT_PROP_MAXIMUM_PACKET_SIZE){ - if( p->value.i32 == 0){ - return MOSQ_ERR_PROTOCOL; - } - }else if(p->identifier == MQTT_PROP_RECEIVE_MAXIMUM - || p->identifier == MQTT_PROP_TOPIC_ALIAS){ - - if(p->value.i16 == 0){ - return MOSQ_ERR_PROTOCOL; - } - } - - /* Check for properties on incorrect commands */ - rc = mosquitto_property_check_command(command, p->identifier); - if(rc) return rc; - - /* Check for duplicates */ - tail = p->next; - while(tail){ - if(p->identifier == tail->identifier - && p->identifier != MQTT_PROP_USER_PROPERTY){ - - return MOSQ_ERR_DUPLICATE_PROPERTY; - } - tail = tail->next; - } - - p = p->next; - } - - return MOSQ_ERR_SUCCESS; -} - -const mosquitto_property *property__get_property(const mosquitto_property *proplist, int identifier, bool skip_first) -{ - const mosquitto_property *p; - bool is_first = true; - - p = proplist; - - while(p){ - if(p->identifier == identifier){ - if(!is_first || !skip_first){ - return p; - } - is_first = false; - } - p = p->next; - } - return NULL; -} - - -const mosquitto_property *mosquitto_property_read_byte(const mosquitto_property *proplist, int identifier, uint8_t *value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR - && p->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION - && p->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION - && p->identifier != MQTT_PROP_MAXIMUM_QOS - && p->identifier != MQTT_PROP_RETAIN_AVAILABLE - && p->identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE - && p->identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - && p->identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ - return NULL; - } - - if(value) *value = p->value.i8; - - return p; -} - - -const mosquitto_property *mosquitto_property_read_int16(const mosquitto_property *proplist, int identifier, uint16_t *value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_SERVER_KEEP_ALIVE - && p->identifier != MQTT_PROP_RECEIVE_MAXIMUM - && p->identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM - && p->identifier != MQTT_PROP_TOPIC_ALIAS){ - return NULL; - } - - if(value) *value = p->value.i16; - - return p; -} - - -const mosquitto_property *mosquitto_property_read_int32(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL - && p->identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL - && p->identifier != MQTT_PROP_WILL_DELAY_INTERVAL - && p->identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){ - - return NULL; - } - - if(value) *value = p->value.i32; - - return p; -} - - -const mosquitto_property *mosquitto_property_read_varint(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){ - return NULL; - } - - if(value) *value = p->value.varint; - - return p; -} - - -const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, uint16_t *len, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist || (value && !len) || (!value && len)) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_CORRELATION_DATA - && p->identifier != MQTT_PROP_AUTHENTICATION_DATA){ - - return NULL; - } - - if(value){ - *len = p->value.bin.len; - *value = malloc(*len); - if(!(*value)) return NULL; - - memcpy(*value, p->value.bin.v, *len); - } - - return p; -} - - -const mosquitto_property *mosquitto_property_read_string(const mosquitto_property *proplist, int identifier, char **value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_CONTENT_TYPE - && p->identifier != MQTT_PROP_RESPONSE_TOPIC - && p->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER - && p->identifier != MQTT_PROP_AUTHENTICATION_METHOD - && p->identifier != MQTT_PROP_RESPONSE_INFORMATION - && p->identifier != MQTT_PROP_SERVER_REFERENCE - && p->identifier != MQTT_PROP_REASON_STRING){ - - return NULL; - } - - if(value){ - *value = calloc(1, p->value.s.len+1); - if(!(*value)) return NULL; - - memcpy(*value, p->value.s.v, p->value.s.len); - } - - return p; -} - - -const mosquitto_property *mosquitto_property_read_string_pair(const mosquitto_property *proplist, int identifier, char **name, char **value, bool skip_first) -{ - const mosquitto_property *p; - if(!proplist) return NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL; - - if(name){ - *name = calloc(1, p->name.len+1); - if(!(*name)) return NULL; - memcpy(*name, p->name.v, p->name.len); - } - - if(value){ - *value = calloc(1, p->value.s.len+1); - if(!(*value)){ - if(name) free(*name); - return NULL; - } - memcpy(*value, p->value.s.v, p->value.s.len); - } - - return p; -} - - -int mosquitto_property_copy_all(mosquitto_property **dest, const mosquitto_property *src) -{ - mosquitto_property *pnew, *plast = NULL; - - if(!src) return MOSQ_ERR_SUCCESS; - if(!dest) return MOSQ_ERR_INVAL; - - *dest = NULL; - - while(src){ - pnew = calloc(1, sizeof(mosquitto_property)); - if(!pnew){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - if(plast){ - plast->next = pnew; - }else{ - *dest = pnew; - } - plast = pnew; - - pnew->identifier = src->identifier; - switch(pnew->identifier){ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - case MQTT_PROP_MAXIMUM_QOS: - case MQTT_PROP_RETAIN_AVAILABLE: - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - case MQTT_PROP_SHARED_SUB_AVAILABLE: - pnew->value.i8 = src->value.i8; - break; - - case MQTT_PROP_SERVER_KEEP_ALIVE: - case MQTT_PROP_RECEIVE_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - case MQTT_PROP_TOPIC_ALIAS: - pnew->value.i16 = src->value.i16; - break; - - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - case MQTT_PROP_WILL_DELAY_INTERVAL: - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - pnew->value.i32 = src->value.i32; - break; - - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - pnew->value.varint = src->value.varint; - break; - - case MQTT_PROP_CONTENT_TYPE: - case MQTT_PROP_RESPONSE_TOPIC: - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - case MQTT_PROP_AUTHENTICATION_METHOD: - case MQTT_PROP_RESPONSE_INFORMATION: - case MQTT_PROP_SERVER_REFERENCE: - case MQTT_PROP_REASON_STRING: - pnew->value.s.len = src->value.s.len; - pnew->value.s.v = strdup(src->value.s.v); - if(!pnew->value.s.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - break; - - case MQTT_PROP_AUTHENTICATION_DATA: - case MQTT_PROP_CORRELATION_DATA: - pnew->value.bin.len = src->value.bin.len; - pnew->value.bin.v = malloc(pnew->value.bin.len); - if(!pnew->value.bin.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - memcpy(pnew->value.bin.v, src->value.bin.v, pnew->value.bin.len); - break; - - case MQTT_PROP_USER_PROPERTY: - pnew->value.s.len = src->value.s.len; - pnew->value.s.v = strdup(src->value.s.v); - if(!pnew->value.s.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - - pnew->name.len = src->name.len; - pnew->name.v = strdup(src->name.v); - if(!pnew->name.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - break; - - default: - mosquitto_property_free_all(dest); - return MOSQ_ERR_INVAL; - } - - src = src->next; - } - - return MOSQ_ERR_SUCCESS; -} diff --git a/libs/libmosquitto/src/property_mosq.h b/libs/libmosquitto/src/property_mosq.h deleted file mode 100644 index d965d8a3e6..0000000000 --- a/libs/libmosquitto/src/property_mosq.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright (c) 2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 PROPERTY_MOSQ_H -#define PROPERTY_MOSQ_H - -#include "mosquitto_internal.h" -#include "mosquitto.h" - -struct mqtt__string { - char *v; - int len; -}; - -struct mqtt5__property { - struct mqtt5__property *next; - union { - uint8_t i8; - uint16_t i16; - uint32_t i32; - uint32_t varint; - struct mqtt__string bin; - struct mqtt__string s; - } value; - struct mqtt__string name; - int32_t identifier; - bool client_generated; -}; - - -int property__read_all(int command, struct mosquitto__packet *packet, mosquitto_property **property); -int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *property, bool write_len); -void property__free(mosquitto_property **property); - -int property__get_length(const mosquitto_property *property); -int property__get_length_all(const mosquitto_property *property); - -#endif diff --git a/libs/libmosquitto/src/read_handle.c b/libs/libmosquitto/src/read_handle.c deleted file mode 100644 index 19c0c35b1e..0000000000 --- a/libs/libmosquitto/src/read_handle.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "messages_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "util_mosq.h" - -int handle__packet(struct mosquitto *mosq) -{ - assert(mosq); - - switch((mosq->in_packet.command)&0xF0){ - case CMD_PINGREQ: - return handle__pingreq(mosq); - case CMD_PINGRESP: - return handle__pingresp(mosq); - case CMD_PUBACK: - return handle__pubackcomp(mosq, "PUBACK"); - case CMD_PUBCOMP: - return handle__pubackcomp(mosq, "PUBCOMP"); - case CMD_PUBLISH: - return handle__publish(mosq); - case CMD_PUBREC: - return handle__pubrec(NULL, mosq); - case CMD_PUBREL: - return handle__pubrel(NULL, mosq); - case CMD_CONNACK: - return handle__connack(mosq); - case CMD_SUBACK: - return handle__suback(mosq); - case CMD_UNSUBACK: - return handle__unsuback(mosq); - case CMD_DISCONNECT: - return handle__disconnect(mosq); - case CMD_AUTH: - return handle__auth(mosq); - default: - /* If we don't recognise the command, return an error straight away. */ - log__printf(mosq, MOSQ_LOG_ERR, "Error: Unrecognised command %d\n", (mosq->in_packet.command)&0xF0); - return MOSQ_ERR_PROTOCOL; - } -} - diff --git a/libs/libmosquitto/src/read_handle.h b/libs/libmosquitto/src/read_handle.h deleted file mode 100644 index 2a6936d817..0000000000 --- a/libs/libmosquitto/src/read_handle.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 READ_HANDLE_H -#define READ_HANDLE_H - -#include "mosquitto.h" -struct mosquitto_db; - -int handle__pingreq(struct mosquitto *mosq); -int handle__pingresp(struct mosquitto *mosq); -#ifdef WITH_BROKER -int handle__pubackcomp(struct mosquitto_db *db, struct mosquitto *mosq, const char *type); -#else -int handle__packet(struct mosquitto *mosq); -int handle__connack(struct mosquitto *mosq); -int handle__disconnect(struct mosquitto *mosq); -int handle__pubackcomp(struct mosquitto *mosq, const char *type); -int handle__publish(struct mosquitto *mosq); -int handle__auth(struct mosquitto *mosq); -#endif -int handle__pubrec(struct mosquitto_db *db, struct mosquitto *mosq); -int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq); -int handle__suback(struct mosquitto *mosq); -int handle__unsuback(struct mosquitto *mosq); - - -#endif diff --git a/libs/libmosquitto/src/send_connect.c b/libs/libmosquitto/src/send_connect.c deleted file mode 100644 index 210f125a80..0000000000 --- a/libs/libmosquitto/src/send_connect.c +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" - -int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session, const mosquitto_property *properties) -{ - struct mosquitto__packet *packet = NULL; - int payloadlen; - uint8_t will = 0; - uint8_t byte; - int rc; - uint8_t version; - char *clientid, *username, *password; - int headerlen; - int proplen = 0, will_proplen, varbytes; - mosquitto_property *local_props = NULL; - uint16_t receive_maximum; - - assert(mosq); - - if(mosq->protocol == mosq_p_mqtt31 && !mosq->id) return MOSQ_ERR_PROTOCOL; - -#if defined(WITH_BROKER) && defined(WITH_BRIDGE) - if(mosq->bridge){ - clientid = mosq->bridge->remote_clientid; - username = mosq->bridge->remote_username; - password = mosq->bridge->remote_password; - }else{ - clientid = mosq->id; - username = mosq->username; - password = mosq->password; - } -#else - clientid = mosq->id; - username = mosq->username; - password = mosq->password; -#endif - - if(mosq->protocol == mosq_p_mqtt5){ - /* Generate properties from options */ - if(!mosquitto_property_read_int16(properties, MQTT_PROP_RECEIVE_MAXIMUM, &receive_maximum, false)){ - rc = mosquitto_property_add_int16(&local_props, MQTT_PROP_RECEIVE_MAXIMUM, mosq->msgs_in.inflight_maximum); - if(rc) return rc; - }else{ - mosq->msgs_in.inflight_maximum = receive_maximum; - mosq->msgs_in.inflight_quota = receive_maximum; - } - - version = MQTT_PROTOCOL_V5; - headerlen = 10; - proplen = 0; - proplen += property__get_length_all(properties); - proplen += property__get_length_all(local_props); - varbytes = packet__varint_bytes(proplen); - headerlen += proplen + varbytes; - }else if(mosq->protocol == mosq_p_mqtt311){ - version = MQTT_PROTOCOL_V311; - headerlen = 10; - }else if(mosq->protocol == mosq_p_mqtt31){ - version = MQTT_PROTOCOL_V31; - headerlen = 12; - }else{ - return MOSQ_ERR_INVAL; - } - - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - if(clientid){ - payloadlen = 2+strlen(clientid); - }else{ - payloadlen = 2; - } - if(mosq->will){ - will = 1; - assert(mosq->will->msg.topic); - - payloadlen += 2+strlen(mosq->will->msg.topic) + 2+mosq->will->msg.payloadlen; - if(mosq->protocol == mosq_p_mqtt5){ - will_proplen = property__get_length_all(mosq->will->properties); - varbytes = packet__varint_bytes(will_proplen); - payloadlen += will_proplen + varbytes; - } - } - - /* After this check we can be sure that the username and password are - * always valid for the current protocol, so there is no need to check - * username before checking password. */ - if(mosq->protocol == mosq_p_mqtt31 || mosq->protocol == mosq_p_mqtt311){ - if(password != NULL && username == NULL){ - return MOSQ_ERR_INVAL; - } - } - - if(username){ - payloadlen += 2+strlen(username); - } - if(password){ - payloadlen += 2+strlen(password); - } - - packet->command = CMD_CONNECT; - packet->remaining_length = headerlen + payloadlen; - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - - /* Variable header */ - if(version == MQTT_PROTOCOL_V31){ - packet__write_string(packet, PROTOCOL_NAME_v31, strlen(PROTOCOL_NAME_v31)); - }else{ - packet__write_string(packet, PROTOCOL_NAME, strlen(PROTOCOL_NAME)); - } -#if defined(WITH_BROKER) && defined(WITH_BRIDGE) - if(mosq->bridge && mosq->bridge->try_private && mosq->bridge->try_private_accepted){ - version |= 0x80; - }else{ - } -#endif - packet__write_byte(packet, version); - byte = (clean_session&0x1)<<1; - if(will){ - byte = byte | ((mosq->will->msg.retain&0x1)<<5) | ((mosq->will->msg.qos&0x3)<<3) | ((will&0x1)<<2); - } - if(username){ - byte = byte | 0x1<<7; - } - if(mosq->password){ - byte = byte | 0x1<<6; - } - packet__write_byte(packet, byte); - packet__write_uint16(packet, keepalive); - - if(mosq->protocol == mosq_p_mqtt5){ - /* Write properties */ - packet__write_varint(packet, proplen); - property__write_all(packet, properties, false); - property__write_all(packet, local_props, false); - } - - /* Payload */ - if(clientid){ - packet__write_string(packet, clientid, strlen(clientid)); - }else{ - packet__write_uint16(packet, 0); - } - if(will){ - if(mosq->protocol == mosq_p_mqtt5){ - /* Write will properties */ - property__write_all(packet, mosq->will->properties, true); - } - packet__write_string(packet, mosq->will->msg.topic, strlen(mosq->will->msg.topic)); - packet__write_string(packet, (const char *)mosq->will->msg.payload, mosq->will->msg.payloadlen); - } - - if(username){ - packet__write_string(packet, username, strlen(username)); - } - if(password){ - packet__write_string(packet, password, strlen(password)); - } - - mosq->keepalive = keepalive; -#ifdef WITH_BROKER -# ifdef WITH_BRIDGE - log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", clientid); -# endif -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", clientid); -#endif - return packet__queue(mosq, packet); -} - diff --git a/libs/libmosquitto/src/send_disconnect.c b/libs/libmosquitto/src/send_disconnect.c deleted file mode 100644 index 3598988755..0000000000 --- a/libs/libmosquitto/src/send_disconnect.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" - - -int send__disconnect(struct mosquitto *mosq, uint8_t reason_code, const mosquitto_property *properties) -{ - struct mosquitto__packet *packet = NULL; - int rc; - int proplen, varbytes; - - assert(mosq); -#ifdef WITH_BROKER -# ifdef WITH_BRIDGE - if(mosq->bridge){ - log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id); - }else -# else - { - log__printf(mosq, MOSQ_LOG_DEBUG, "Sending DISCONNECT to %s (rc%d)", mosq->id, reason_code); - } -# endif -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id); -#endif - assert(mosq); - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packet->command = CMD_DISCONNECT; - if(mosq->protocol == mosq_p_mqtt5 && (reason_code != 0 || properties)){ - packet->remaining_length = 1; - if(properties){ - proplen = property__get_length_all(properties); - varbytes = packet__varint_bytes(proplen); - packet->remaining_length += proplen + varbytes; - } - }else{ - packet->remaining_length = 0; - } - - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - if(mosq->protocol == mosq_p_mqtt5 && (reason_code != 0 || properties)){ - packet__write_byte(packet, reason_code); - if(properties){ - property__write_all(packet, properties, true); - } - } - - return packet__queue(mosq, packet); -} - diff --git a/libs/libmosquitto/src/send_mosq.c b/libs/libmosquitto/src/send_mosq.c deleted file mode 100644 index 27bc1fda17..0000000000 --- a/libs/libmosquitto/src/send_mosq.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -# include "sys_tree.h" -#else -# define G_PUB_BYTES_SENT_INC(A) -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "mqtt_protocol.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "util_mosq.h" - -int send__pingreq(struct mosquitto *mosq) -{ - int rc; - assert(mosq); -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id); -#endif - rc = send__simple_command(mosq, CMD_PINGREQ); - if(rc == MOSQ_ERR_SUCCESS){ - mosq->ping_t = mosquitto_time(); - } - return rc; -} - -int send__pingresp(struct mosquitto *mosq) -{ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id); -#endif - return send__simple_command(mosq, CMD_PINGRESP); -} - -int send__puback(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code) -{ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (m%d, rc%d)", mosq->id, mid, reason_code); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (m%d, rc%d)", mosq->id, mid, reason_code); -#endif - util__increment_receive_quota(mosq); - /* We don't use Reason String or User Property yet. */ - return send__command_with_mid(mosq, CMD_PUBACK, mid, false, reason_code, NULL); -} - -int send__pubcomp(struct mosquitto *mosq, uint16_t mid) -{ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (m%d)", mosq->id, mid); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (m%d)", mosq->id, mid); -#endif - util__increment_receive_quota(mosq); - /* We don't use Reason String or User Property yet. */ - return send__command_with_mid(mosq, CMD_PUBCOMP, mid, false, 0, NULL); -} - - -int send__pubrec(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code) -{ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (m%d, rc%d)", mosq->id, mid, reason_code); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (m%d, rc%d)", mosq->id, mid, reason_code); -#endif - if(reason_code >= 0x80 && mosq->protocol == mosq_p_mqtt5){ - util__increment_receive_quota(mosq); - } - /* We don't use Reason String or User Property yet. */ - return send__command_with_mid(mosq, CMD_PUBREC, mid, false, reason_code, NULL); -} - -int send__pubrel(struct mosquitto *mosq, uint16_t mid) -{ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (m%d)", mosq->id, mid); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (m%d)", mosq->id, mid); -#endif - /* We don't use Reason String or User Property yet. */ - return send__command_with_mid(mosq, CMD_PUBREL|2, mid, false, 0, NULL); -} - -/* For PUBACK, PUBCOMP, PUBREC, and PUBREL */ -int send__command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup, uint8_t reason_code, const mosquitto_property *properties) -{ - struct mosquitto__packet *packet = NULL; - int rc; - int proplen, varbytes; - - assert(mosq); - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packet->command = command; - if(dup){ - packet->command |= 8; - } - packet->remaining_length = 2; - - if(mosq->protocol == mosq_p_mqtt5){ - if(reason_code != 0 || properties){ - packet->remaining_length += 1; - } - - if(properties){ - proplen = property__get_length_all(properties); - varbytes = packet__varint_bytes(proplen); - packet->remaining_length += varbytes + proplen; - } - } - - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - - packet__write_uint16(packet, mid); - - if(mosq->protocol == mosq_p_mqtt5){ - if(reason_code != 0 || properties){ - packet__write_byte(packet, reason_code); - } - if(properties){ - property__write_all(packet, properties, true); - } - } - - return packet__queue(mosq, packet); -} - -/* For DISCONNECT, PINGREQ and PINGRESP */ -int send__simple_command(struct mosquitto *mosq, uint8_t command) -{ - struct mosquitto__packet *packet = NULL; - int rc; - - assert(mosq); - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packet->command = command; - packet->remaining_length = 0; - - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - - return packet__queue(mosq, packet); -} - diff --git a/libs/libmosquitto/src/send_mosq.h b/libs/libmosquitto/src/send_mosq.h deleted file mode 100644 index 4b76f2f952..0000000000 --- a/libs/libmosquitto/src/send_mosq.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 SEND_MOSQ_H -#define SEND_MOSQ_H - -#include "mosquitto.h" -#include "property_mosq.h" - -int send__simple_command(struct mosquitto *mosq, uint8_t command); -int send__command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup, uint8_t reason_code, const mosquitto_property *properties); -int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props, uint32_t expiry_interval); - -int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session, const mosquitto_property *properties); -int send__disconnect(struct mosquitto *mosq, uint8_t reason_code, const mosquitto_property *properties); -int send__pingreq(struct mosquitto *mosq); -int send__pingresp(struct mosquitto *mosq); -int send__puback(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code); -int send__pubcomp(struct mosquitto *mosq, uint16_t mid); -int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props, uint32_t expiry_interval); -int send__pubrec(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code); -int send__pubrel(struct mosquitto *mosq, uint16_t mid); -int send__subscribe(struct mosquitto *mosq, int *mid, int topic_count, char *const *const topic, int topic_qos, const mosquitto_property *properties); -int send__unsubscribe(struct mosquitto *mosq, int *mid, int topic_count, char *const *const topic, const mosquitto_property *properties); - -#endif diff --git a/libs/libmosquitto/src/send_publish.c b/libs/libmosquitto/src/send_publish.c deleted file mode 100644 index f07c539d40..0000000000 --- a/libs/libmosquitto/src/send_publish.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -# include "sys_tree.h" -#else -# define G_PUB_BYTES_SENT_INC(A) -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "mqtt_protocol.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" - - -int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props, uint32_t expiry_interval) -{ -#ifdef WITH_BROKER - size_t len; -#ifdef WITH_BRIDGE - int i; - struct mosquitto__bridge_topic *cur_topic; - bool match; - int rc; - char *mapped_topic = NULL; - char *topic_temp = NULL; -#endif -#endif - assert(mosq); - -#if defined(WITH_BROKER) && defined(WITH_WEBSOCKETS) - if(mosq->sock == INVALID_SOCKET && !mosq->wsi) return MOSQ_ERR_NO_CONN; -#else - if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; -#endif - -#ifdef WITH_BROKER - if(mosq->listener && mosq->listener->mount_point){ - len = strlen(mosq->listener->mount_point); - if(len < strlen(topic)){ - topic += len; - }else{ - /* Invalid topic string. Should never happen, but silently swallow the message anyway. */ - return MOSQ_ERR_SUCCESS; - } - } -#ifdef WITH_BRIDGE - if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){ - for(i=0; i<mosq->bridge->topic_count; i++){ - cur_topic = &mosq->bridge->topics[i]; - if((cur_topic->direction == bd_both || cur_topic->direction == bd_out) - && (cur_topic->remote_prefix || cur_topic->local_prefix)){ - /* Topic mapping required on this topic if the message matches */ - - rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match); - if(rc){ - return rc; - } - if(match){ - mapped_topic = mosquitto__strdup(topic); - if(!mapped_topic) return MOSQ_ERR_NOMEM; - if(cur_topic->local_prefix){ - /* This prefix needs removing. */ - if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){ - topic_temp = mosquitto__strdup(mapped_topic+strlen(cur_topic->local_prefix)); - mosquitto__free(mapped_topic); - if(!topic_temp){ - return MOSQ_ERR_NOMEM; - } - mapped_topic = topic_temp; - } - } - - if(cur_topic->remote_prefix){ - /* This prefix needs adding. */ - len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1; - topic_temp = mosquitto__malloc(len+1); - if(!topic_temp){ - mosquitto__free(mapped_topic); - return MOSQ_ERR_NOMEM; - } - snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic); - topic_temp[len] = '\0'; - mosquitto__free(mapped_topic); - mapped_topic = topic_temp; - } - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, mapped_topic, (long)payloadlen); - G_PUB_BYTES_SENT_INC(payloadlen); - rc = send__real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup, cmsg_props, store_props, expiry_interval); - mosquitto__free(mapped_topic); - return rc; - } - } - } - } -#endif - log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen); - G_PUB_BYTES_SENT_INC(payloadlen); -#else - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen); -#endif - - return send__real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup, cmsg_props, store_props, expiry_interval); -} - - -int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props, uint32_t expiry_interval) -{ - struct mosquitto__packet *packet = NULL; - int packetlen; - int proplen = 0, varbytes; - int rc; - mosquitto_property expiry_prop; - - assert(mosq); - - if(topic){ - packetlen = 2+strlen(topic) + payloadlen; - }else{ - packetlen = 2 + payloadlen; - } - if(qos > 0) packetlen += 2; /* For message id */ - if(mosq->protocol == mosq_p_mqtt5){ - proplen = 0; - proplen += property__get_length_all(cmsg_props); - proplen += property__get_length_all(store_props); - if(expiry_interval > 0){ - expiry_prop.next = NULL; - expiry_prop.value.i32 = expiry_interval; - expiry_prop.identifier = MQTT_PROP_MESSAGE_EXPIRY_INTERVAL; - expiry_prop.client_generated = false; - - proplen += property__get_length_all(&expiry_prop); - } - - varbytes = packet__varint_bytes(proplen); - if(varbytes > 4){ - /* FIXME - Properties too big, don't publish any - should remove some first really */ - cmsg_props = NULL; - store_props = NULL; - expiry_interval = 0; - }else{ - packetlen += proplen + varbytes; - } - } - if(packet__check_oversize(mosq, packetlen)){ -#ifdef WITH_BROKER - log__printf(NULL, MOSQ_LOG_NOTICE, "Dropping too large outgoing PUBLISH for %s (%d bytes)", mosq->id, packetlen); -#else - log__printf(NULL, MOSQ_LOG_NOTICE, "Dropping too large outgoing PUBLISH (%d bytes)", packetlen); -#endif - return MOSQ_ERR_OVERSIZE_PACKET; - } - - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packet->mid = mid; - packet->command = CMD_PUBLISH | ((dup&0x1)<<3) | (qos<<1) | retain; - packet->remaining_length = packetlen; - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - /* Variable header (topic string) */ - if(topic){ - packet__write_string(packet, topic, strlen(topic)); - }else{ - packet__write_uint16(packet, 0); - } - if(qos > 0){ - packet__write_uint16(packet, mid); - } - - if(mosq->protocol == mosq_p_mqtt5){ - packet__write_varint(packet, proplen); - property__write_all(packet, cmsg_props, false); - property__write_all(packet, store_props, false); - if(expiry_interval > 0){ - property__write_all(packet, &expiry_prop, false); - } - } - - /* Payload */ - if(payloadlen){ - packet__write_bytes(packet, payload, payloadlen); - } - - return packet__queue(mosq, packet); -} diff --git a/libs/libmosquitto/src/send_subscribe.c b/libs/libmosquitto/src/send_subscribe.c deleted file mode 100644 index 1f2760f985..0000000000 --- a/libs/libmosquitto/src/send_subscribe.c +++ /dev/null @@ -1,96 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "util_mosq.h" - - -int send__subscribe(struct mosquitto *mosq, int *mid, int topic_count, const char **topic, int topic_qos, const mosquitto_property *properties) -{ - struct mosquitto__packet *packet = NULL; - uint32_t packetlen; - uint16_t local_mid; - int rc; - int i; - int proplen, varbytes; - - assert(mosq); - assert(topic); - - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packetlen = 2; - if(mosq->protocol == mosq_p_mqtt5){ - proplen = property__get_length_all(properties); - varbytes = packet__varint_bytes(proplen); - packetlen += proplen + varbytes; - } - for(i=0; i<topic_count; i++){ - packetlen += 2+strlen(topic[i]) + 1; - } - - packet->command = CMD_SUBSCRIBE | (1<<1); - packet->remaining_length = packetlen; - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - - /* Variable header */ - local_mid = mosquitto__mid_generate(mosq); - if(mid) *mid = (int)local_mid; - packet__write_uint16(packet, local_mid); - - if(mosq->protocol == mosq_p_mqtt5){ - property__write_all(packet, properties, true); - } - - /* Payload */ - for(i=0; i<topic_count; i++){ - packet__write_string(packet, topic[i], strlen(topic[i])); - packet__write_byte(packet, topic_qos); - } - -#ifdef WITH_BROKER -# ifdef WITH_BRIDGE - log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d, Options: 0x%02x)", mosq->id, local_mid, topic[0], topic_qos&0x03, topic_qos&0xFC); -# endif -#else - for(i=0; i<topic_count; i++){ - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d, Options: 0x%02x)", mosq->id, local_mid, topic[i], topic_qos&0x03, topic_qos&0xFC); - } -#endif - - return packet__queue(mosq, packet); -} - diff --git a/libs/libmosquitto/src/send_unsubscribe.c b/libs/libmosquitto/src/send_unsubscribe.c deleted file mode 100644 index e7317151a5..0000000000 --- a/libs/libmosquitto/src/send_unsubscribe.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "packet_mosq.h" -#include "property_mosq.h" -#include "send_mosq.h" -#include "util_mosq.h" - - -int send__unsubscribe(struct mosquitto *mosq, int *mid, int topic_count, char *const *const topic, const mosquitto_property *properties) -{ - /* FIXME - only deals with a single topic */ - struct mosquitto__packet *packet = NULL; - uint32_t packetlen; - uint16_t local_mid; - int rc; - int proplen, varbytes; - int i; - - assert(mosq); - assert(topic); - - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - packetlen = 2; - - for(i=0; i<topic_count; i++){ - packetlen += 2+strlen(topic[i]); - } - if(mosq->protocol == mosq_p_mqtt5){ - proplen = property__get_length_all(properties); - varbytes = packet__varint_bytes(proplen); - packetlen += proplen + varbytes; - } - - packet->command = CMD_UNSUBSCRIBE | (1<<1); - packet->remaining_length = packetlen; - rc = packet__alloc(packet); - if(rc){ - mosquitto__free(packet); - return rc; - } - - /* Variable header */ - local_mid = mosquitto__mid_generate(mosq); - if(mid) *mid = (int)local_mid; - packet__write_uint16(packet, local_mid); - - if(mosq->protocol == mosq_p_mqtt5){ - /* We don't use User Property yet. */ - property__write_all(packet, properties, true); - } - - /* Payload */ - for(i=0; i<topic_count; i++){ - packet__write_string(packet, topic[i], strlen(topic[i])); - } - -#ifdef WITH_BROKER -# ifdef WITH_BRIDGE - for(i=0; i<topic_count; i++){ - log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic[i]); - } -# endif -#else - for(i=0; i<topic_count; i++){ - log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic[i]); - } -#endif - return packet__queue(mosq, packet); -} - diff --git a/libs/libmosquitto/src/socks_mosq.c b/libs/libmosquitto/src/socks_mosq.c deleted file mode 100644 index 0df58a4b65..0000000000 --- a/libs/libmosquitto/src/socks_mosq.c +++ /dev/null @@ -1,460 +0,0 @@ -/* -Copyright (c) 2014-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <errno.h> -#include <string.h> -#include <limits.h> -#ifdef WIN32 -# include <ws2tcpip.h> -#elif __QNX__ -# include <sys/socket.h> -# include <netinet/in.h> -#else -# include <arpa/inet.h> -#endif -#ifdef __FreeBSD__ -# include <sys/socket.h> -# include <netinet/in.h> -#endif - -#include "mosquitto_internal.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "packet_mosq.h" -#include "send_mosq.h" - -#define SOCKS_AUTH_NONE 0x00 -#define SOCKS_AUTH_GSS 0x01 -#define SOCKS_AUTH_USERPASS 0x02 -#define SOCKS_AUTH_NO_ACCEPTABLE 0xFF - -#define SOCKS_ATYPE_IP_V4 1 /* four bytes */ -#define SOCKS_ATYPE_DOMAINNAME 3 /* one byte length, followed by fqdn no null, 256 max chars */ -#define SOCKS_ATYPE_IP_V6 4 /* 16 bytes */ - -#define SOCKS_REPLY_SUCCEEDED 0x00 -#define SOCKS_REPLY_GENERAL_FAILURE 0x01 -#define SOCKS_REPLY_CONNECTION_NOT_ALLOWED 0x02 -#define SOCKS_REPLY_NETWORK_UNREACHABLE 0x03 -#define SOCKS_REPLY_HOST_UNREACHABLE 0x04 -#define SOCKS_REPLY_CONNECTION_REFUSED 0x05 -#define SOCKS_REPLY_TTL_EXPIRED 0x06 -#define SOCKS_REPLY_COMMAND_NOT_SUPPORTED 0x07 -#define SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED 0x08 - -int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, const char *username, const char *password) -{ -#ifdef WITH_SOCKS - if(!mosq) return MOSQ_ERR_INVAL; - if(!host || strlen(host) > 256) return MOSQ_ERR_INVAL; - if(port < 1 || port > 65535) return MOSQ_ERR_INVAL; - - mosquitto__free(mosq->socks5_host); - mosq->socks5_host = NULL; - - mosq->socks5_host = mosquitto__strdup(host); - if(!mosq->socks5_host){ - return MOSQ_ERR_NOMEM; - } - - mosq->socks5_port = port; - - mosquitto__free(mosq->socks5_username); - mosq->socks5_username = NULL; - - mosquitto__free(mosq->socks5_password); - mosq->socks5_password = NULL; - - if(username){ - mosq->socks5_username = mosquitto__strdup(username); - if(!mosq->socks5_username){ - return MOSQ_ERR_NOMEM; - } - - if(password){ - mosq->socks5_password = mosquitto__strdup(password); - if(!mosq->socks5_password){ - mosquitto__free(mosq->socks5_username); - return MOSQ_ERR_NOMEM; - } - } - } - - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - -#ifdef WITH_SOCKS -int socks5__send(struct mosquitto *mosq) -{ - struct mosquitto__packet *packet; - int slen; - int ulen, plen; - - struct in_addr addr_ipv4; - struct in6_addr addr_ipv6; - int ipv4_pton_result; - int ipv6_pton_result; - - if(mosq->state == mosq_cs_socks5_new){ - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - if(mosq->socks5_username){ - packet->packet_length = 4; - }else{ - packet->packet_length = 3; - } - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); - - packet->payload[0] = 0x05; - if(mosq->socks5_username){ - packet->payload[1] = 2; - packet->payload[2] = SOCKS_AUTH_NONE; - packet->payload[3] = SOCKS_AUTH_USERPASS; - }else{ - packet->payload[1] = 1; - packet->payload[2] = SOCKS_AUTH_NONE; - } - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_socks5_start; - pthread_mutex_unlock(&mosq->state_mutex); - - mosq->in_packet.pos = 0; - mosq->in_packet.packet_length = 2; - mosq->in_packet.to_process = 2; - mosq->in_packet.payload = mosquitto__malloc(sizeof(uint8_t)*2); - if(!mosq->in_packet.payload){ - mosquitto__free(packet->payload); - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - - return packet__queue(mosq, packet); - }else if(mosq->state == mosq_cs_socks5_auth_ok){ - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - ipv4_pton_result = inet_pton(AF_INET, mosq->host, &addr_ipv4); - ipv6_pton_result = inet_pton(AF_INET6, mosq->host, &addr_ipv6); - - if(ipv4_pton_result == 1){ - packet->packet_length = 10; - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); - if(!packet->payload){ - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - packet->payload[3] = SOCKS_ATYPE_IP_V4; - memcpy(&(packet->payload[4]), (const void*)&addr_ipv4, 4); - packet->payload[4+4] = MOSQ_MSB(mosq->port); - packet->payload[4+4+1] = MOSQ_LSB(mosq->port); - - }else if(ipv6_pton_result == 1){ - packet->packet_length = 22; - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); - if(!packet->payload){ - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - packet->payload[3] = SOCKS_ATYPE_IP_V6; - memcpy(&(packet->payload[4]), (const void*)&addr_ipv6, 16); - packet->payload[4+16] = MOSQ_MSB(mosq->port); - packet->payload[4+16+1] = MOSQ_LSB(mosq->port); - - }else{ - slen = strlen(mosq->host); - if(slen > UCHAR_MAX){ - return MOSQ_ERR_NOMEM; - } - packet->packet_length = 7 + slen; - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); - if(!packet->payload){ - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - packet->payload[3] = SOCKS_ATYPE_DOMAINNAME; - packet->payload[4] = (uint8_t)slen; - memcpy(&(packet->payload[5]), mosq->host, slen); - packet->payload[5+slen] = MOSQ_MSB(mosq->port); - packet->payload[6+slen] = MOSQ_LSB(mosq->port); - } - packet->payload[0] = 0x05; - packet->payload[1] = 0x01; - packet->payload[2] = 0x00; - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_socks5_request; - pthread_mutex_unlock(&mosq->state_mutex); - - mosq->in_packet.pos = 0; - mosq->in_packet.packet_length = 5; - mosq->in_packet.to_process = 5; - mosq->in_packet.payload = mosquitto__malloc(sizeof(uint8_t)*5); - if(!mosq->in_packet.payload){ - mosquitto__free(packet->payload); - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - - return packet__queue(mosq, packet); - }else if(mosq->state == mosq_cs_socks5_send_userpass){ - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet)); - if(!packet) return MOSQ_ERR_NOMEM; - - ulen = strlen(mosq->socks5_username); - plen = strlen(mosq->socks5_password); - packet->packet_length = 3 + ulen + plen; - packet->payload = mosquitto__malloc(sizeof(uint8_t)*packet->packet_length); - - - packet->payload[0] = 0x01; - packet->payload[1] = ulen; - memcpy(&(packet->payload[2]), mosq->socks5_username, ulen); - packet->payload[2+ulen] = plen; - memcpy(&(packet->payload[3+ulen]), mosq->socks5_password, plen); - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_socks5_userpass_reply; - pthread_mutex_unlock(&mosq->state_mutex); - - mosq->in_packet.pos = 0; - mosq->in_packet.packet_length = 2; - mosq->in_packet.to_process = 2; - mosq->in_packet.payload = mosquitto__malloc(sizeof(uint8_t)*2); - if(!mosq->in_packet.payload){ - mosquitto__free(packet->payload); - mosquitto__free(packet); - return MOSQ_ERR_NOMEM; - } - - return packet__queue(mosq, packet); - } - return MOSQ_ERR_SUCCESS; -} - -int socks5__read(struct mosquitto *mosq) -{ - ssize_t len; - uint8_t *payload; - uint8_t i; - - if(mosq->state == mosq_cs_socks5_start){ - while(mosq->in_packet.to_process > 0){ - len = net__read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); - if(len > 0){ - mosq->in_packet.pos += len; - mosq->in_packet.to_process -= len; - }else{ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return MOSQ_ERR_SUCCESS; - }else{ - packet__cleanup(&mosq->in_packet); - switch(errno){ - case 0: - return MOSQ_ERR_PROXY; - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - if(mosq->in_packet.payload[0] != 5){ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_PROXY; - } - switch(mosq->in_packet.payload[1]){ - case SOCKS_AUTH_NONE: - packet__cleanup(&mosq->in_packet); - mosq->state = mosq_cs_socks5_auth_ok; - return socks5__send(mosq); - case SOCKS_AUTH_USERPASS: - packet__cleanup(&mosq->in_packet); - mosq->state = mosq_cs_socks5_send_userpass; - return socks5__send(mosq); - default: - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_AUTH; - } - }else if(mosq->state == mosq_cs_socks5_userpass_reply){ - while(mosq->in_packet.to_process > 0){ - len = net__read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); - if(len > 0){ - mosq->in_packet.pos += len; - mosq->in_packet.to_process -= len; - }else{ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return MOSQ_ERR_SUCCESS; - }else{ - packet__cleanup(&mosq->in_packet); - switch(errno){ - case 0: - return MOSQ_ERR_PROXY; - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - if(mosq->in_packet.payload[0] != 1){ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_PROXY; - } - if(mosq->in_packet.payload[1] == 0){ - packet__cleanup(&mosq->in_packet); - mosq->state = mosq_cs_socks5_auth_ok; - return socks5__send(mosq); - }else{ - i = mosq->in_packet.payload[1]; - packet__cleanup(&mosq->in_packet); - switch(i){ - case SOCKS_REPLY_CONNECTION_NOT_ALLOWED: - return MOSQ_ERR_AUTH; - - case SOCKS_REPLY_NETWORK_UNREACHABLE: - case SOCKS_REPLY_HOST_UNREACHABLE: - case SOCKS_REPLY_CONNECTION_REFUSED: - return MOSQ_ERR_NO_CONN; - - case SOCKS_REPLY_GENERAL_FAILURE: - case SOCKS_REPLY_TTL_EXPIRED: - case SOCKS_REPLY_COMMAND_NOT_SUPPORTED: - case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: - return MOSQ_ERR_PROXY; - - default: - return MOSQ_ERR_INVAL; - } - return MOSQ_ERR_PROXY; - } - }else if(mosq->state == mosq_cs_socks5_request){ - while(mosq->in_packet.to_process > 0){ - len = net__read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); - if(len > 0){ - mosq->in_packet.pos += len; - mosq->in_packet.to_process -= len; - }else{ -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ - return MOSQ_ERR_SUCCESS; - }else{ - packet__cleanup(&mosq->in_packet); - switch(errno){ - case 0: - return MOSQ_ERR_PROXY; - case COMPAT_ECONNRESET: - return MOSQ_ERR_CONN_LOST; - default: - return MOSQ_ERR_ERRNO; - } - } - } - } - - if(mosq->in_packet.packet_length == 5){ - /* First part of the packet has been received, we now know what else to expect. */ - if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V4){ - mosq->in_packet.to_process += 4+2-1; /* 4 bytes IPv4, 2 bytes port, -1 byte because we've already read the first byte */ - mosq->in_packet.packet_length += 4+2-1; - }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V6){ - mosq->in_packet.to_process += 16+2-1; /* 16 bytes IPv6, 2 bytes port, -1 byte because we've already read the first byte */ - mosq->in_packet.packet_length += 16+2-1; - }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_DOMAINNAME){ - if(mosq->in_packet.payload[4] > 0){ - mosq->in_packet.to_process += mosq->in_packet.payload[4]; - mosq->in_packet.packet_length += mosq->in_packet.payload[4]; - } - }else{ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_PROTOCOL; - } - payload = mosquitto__realloc(mosq->in_packet.payload, mosq->in_packet.packet_length); - if(payload){ - mosq->in_packet.payload = payload; - }else{ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_NOMEM; - } - payload = mosquitto__realloc(mosq->in_packet.payload, mosq->in_packet.packet_length); - if(payload){ - mosq->in_packet.payload = payload; - }else{ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_NOMEM; - } - return MOSQ_ERR_SUCCESS; - } - - /* Entire packet is now read. */ - if(mosq->in_packet.payload[0] != 5){ - packet__cleanup(&mosq->in_packet); - return MOSQ_ERR_PROXY; - } - if(mosq->in_packet.payload[1] == 0){ - /* Auth passed */ - packet__cleanup(&mosq->in_packet); - mosq->state = mosq_cs_new; - if(mosq->socks5_host){ - int rc = net__socket_connect_step3(mosq, mosq->host); - if(rc) return rc; - } - return send__connect(mosq, mosq->keepalive, mosq->clean_start, NULL); - }else{ - i = mosq->in_packet.payload[1]; - packet__cleanup(&mosq->in_packet); - mosq->state = mosq_cs_socks5_new; - switch(i){ - case SOCKS_REPLY_CONNECTION_NOT_ALLOWED: - return MOSQ_ERR_AUTH; - - case SOCKS_REPLY_NETWORK_UNREACHABLE: - case SOCKS_REPLY_HOST_UNREACHABLE: - case SOCKS_REPLY_CONNECTION_REFUSED: - return MOSQ_ERR_NO_CONN; - - case SOCKS_REPLY_GENERAL_FAILURE: - case SOCKS_REPLY_TTL_EXPIRED: - case SOCKS_REPLY_COMMAND_NOT_SUPPORTED: - case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: - return MOSQ_ERR_PROXY; - - default: - return MOSQ_ERR_INVAL; - } - } - }else{ - return packet__read(mosq); - } - return MOSQ_ERR_SUCCESS; -} -#endif diff --git a/libs/libmosquitto/src/socks_mosq.h b/libs/libmosquitto/src/socks_mosq.h deleted file mode 100644 index 27b3dc3f31..0000000000 --- a/libs/libmosquitto/src/socks_mosq.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2014-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 SOCKS_MOSQ_H -#define SOCKS_MOSQ_H - -int socks5__send(struct mosquitto *mosq); -int socks5__read(struct mosquitto *mosq); - -#endif diff --git a/libs/libmosquitto/src/srv_mosq.c b/libs/libmosquitto/src/srv_mosq.c deleted file mode 100644 index d08c2bd0cc..0000000000 --- a/libs/libmosquitto/src/srv_mosq.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright (c) 2013-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#ifdef WITH_SRV -# include <ares.h> - -# include <arpa/nameser.h> -# include <stdio.h> -# include <string.h> -#endif - -#include "logging_mosq.h" -#include "memory_mosq.h" -#include "mosquitto_internal.h" -#include "mosquitto.h" - -#ifdef WITH_SRV -static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen) -{ - struct mosquitto *mosq = arg; - struct ares_srv_reply *reply = NULL; - if(status == ARES_SUCCESS){ - status = ares_parse_srv_reply(abuf, alen, &reply); - if(status == ARES_SUCCESS){ - // FIXME - choose which answer to use based on rfc2782 page 3. */ - mosquitto_connect(mosq, reply->host, reply->port, mosq->keepalive); - } - }else{ - log__printf(mosq, MOSQ_LOG_ERR, "Error: SRV lookup failed (%d).", status); - /* FIXME - calling on_disconnect here isn't correct. */ - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_disconnect){ - mosq->in_callback = true; - mosq->on_disconnect(mosq, mosq->userdata, MOSQ_ERR_LOOKUP); - mosq->in_callback = false; - } - if(mosq->on_disconnect_v5){ - mosq->in_callback = true; - mosq->on_disconnect_v5(mosq, mosq->userdata, MOSQ_ERR_LOOKUP, NULL); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - } -} -#endif - -int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address) -{ -#ifdef WITH_SRV - char *h; - int rc; - if(!mosq) return MOSQ_ERR_INVAL; - - rc = ares_init(&mosq->achan); - if(rc != ARES_SUCCESS){ - return MOSQ_ERR_UNKNOWN; - } - - if(!host){ - // get local domain - }else{ -#ifdef WITH_TLS - if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ - h = mosquitto__malloc(strlen(host) + strlen("_secure-mqtt._tcp.") + 1); - if(!h) return MOSQ_ERR_NOMEM; - sprintf(h, "_secure-mqtt._tcp.%s", host); - }else{ -#endif - h = mosquitto__malloc(strlen(host) + strlen("_mqtt._tcp.") + 1); - if(!h) return MOSQ_ERR_NOMEM; - sprintf(h, "_mqtt._tcp.%s", host); -#ifdef WITH_TLS - } -#endif - ares_search(mosq->achan, h, ns_c_in, ns_t_srv, srv_callback, mosq); - mosquitto__free(h); - } - - pthread_mutex_lock(&mosq->state_mutex); - mosq->state = mosq_cs_connect_srv; - pthread_mutex_unlock(&mosq->state_mutex); - - mosq->keepalive = keepalive; - - return MOSQ_ERR_SUCCESS; - -#else - UNUSED(mosq); - UNUSED(host); - UNUSED(keepalive); - UNUSED(bind_address); - - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - - diff --git a/libs/libmosquitto/src/stdafx.cxx b/libs/libmosquitto/src/stdafx.cxx deleted file mode 100644 index 1647228cd0..0000000000 --- a/libs/libmosquitto/src/stdafx.cxx +++ /dev/null @@ -1,2 +0,0 @@ - -#include "stdafx.h"
\ No newline at end of file diff --git a/libs/libmosquitto/src/stdafx.h b/libs/libmosquitto/src/stdafx.h deleted file mode 100644 index 6f70f09bee..0000000000 --- a/libs/libmosquitto/src/stdafx.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/libs/libmosquitto/src/thread_mosq.c b/libs/libmosquitto/src/thread_mosq.c deleted file mode 100644 index 7bde453d3d..0000000000 --- a/libs/libmosquitto/src/thread_mosq.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright (c) 2011-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#ifndef WIN32 -#include <time.h> -#endif - -#include "mosquitto_internal.h" -#include "net_mosq.h" - -void *mosquitto__thread_main(void *obj); - -int mosquitto_loop_start(struct mosquitto *mosq) -{ -#if defined(WITH_THREADING) && defined(HAVE_PTHREAD_CANCEL) - if(!mosq || mosq->threaded != mosq_ts_none) return MOSQ_ERR_INVAL; - - mosq->threaded = mosq_ts_self; - if(!pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)){ - return MOSQ_ERR_SUCCESS; - }else{ - return MOSQ_ERR_ERRNO; - } -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - -int mosquitto_loop_stop(struct mosquitto *mosq, bool force) -{ -#if defined(WITH_THREADING) && defined(HAVE_PTHREAD_CANCEL) -# ifndef WITH_BROKER - char sockpair_data = 0; -# endif - - if(!mosq || mosq->threaded != mosq_ts_self) return MOSQ_ERR_INVAL; - - - /* Write a single byte to sockpairW (connected to sockpairR) to break out - * of select() if in threaded mode. */ - if(mosq->sockpairW != INVALID_SOCKET){ -#ifndef WIN32 - if(write(mosq->sockpairW, &sockpair_data, 1)){ - } -#else - send(mosq->sockpairW, &sockpair_data, 1, 0); -#endif - } - - if(force){ - pthread_cancel(mosq->thread_id); - } - pthread_join(mosq->thread_id, NULL); - mosq->thread_id = pthread_self(); - mosq->threaded = mosq_ts_none; - - return MOSQ_ERR_SUCCESS; -#else - return MOSQ_ERR_NOT_SUPPORTED; -#endif -} - -#ifdef WITH_THREADING -void *mosquitto__thread_main(void *obj) -{ - struct mosquitto *mosq = obj; - int state; -#ifndef WIN32 - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 10000000; -#endif - - if(!mosq) return NULL; - - do{ - pthread_mutex_lock(&mosq->state_mutex); - state = mosq->state; - pthread_mutex_unlock(&mosq->state_mutex); - if(state == mosq_cs_new){ -#ifdef WIN32 - Sleep(10); -#else - nanosleep(&ts, NULL); -#endif - }else{ - break; - } - }while(1); - - if(state == mosq_cs_connect_async){ - mosquitto_reconnect(mosq); - } - - if(!mosq->keepalive){ - /* Sleep for a day if keepalive disabled. */ - mosquitto_loop_forever(mosq, 1000*86400, 1); - }else{ - /* Sleep for our keepalive value. publish() etc. will wake us up. */ - mosquitto_loop_forever(mosq, mosq->keepalive*1000, 1); - } - - return obj; -} -#endif - -int mosquitto_threaded_set(struct mosquitto *mosq, bool threaded) -{ - if(!mosq) return MOSQ_ERR_INVAL; - - if(threaded){ - mosq->threaded = mosq_ts_external; - }else{ - mosq->threaded = mosq_ts_none; - } - - return MOSQ_ERR_SUCCESS; -} diff --git a/libs/libmosquitto/src/time_mosq.c b/libs/libmosquitto/src/time_mosq.c deleted file mode 100644 index c66d985444..0000000000 --- a/libs/libmosquitto/src/time_mosq.c +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright (c) 2013-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#ifdef __APPLE__ -#include <mach/mach.h> -#include <mach/mach_time.h> -#endif - -#ifdef WIN32 -# define _WIN32_WINNT _WIN32_WINNT_VISTA -# include <windows.h> -#else -# include <unistd.h> -#endif -#include <time.h> - -#include "mosquitto.h" -#include "time_mosq.h" - -time_t mosquitto_time(void) -{ -#ifdef WIN32 - return GetTickCount64()/1000; -#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK) - struct timespec tp; - - clock_gettime(CLOCK_MONOTONIC, &tp); - return tp.tv_sec; -#elif defined(__APPLE__) - static mach_timebase_info_data_t tb; - uint64_t ticks; - uint64_t sec; - - ticks = mach_absolute_time(); - - if(tb.denom == 0){ - mach_timebase_info(&tb); - } - sec = ticks*tb.numer/tb.denom/1000000000; - - return (time_t)sec; -#else - return time(NULL); -#endif -} - diff --git a/libs/libmosquitto/src/time_mosq.h b/libs/libmosquitto/src/time_mosq.h deleted file mode 100644 index 75758a8291..0000000000 --- a/libs/libmosquitto/src/time_mosq.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright (c) 2013-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 TIME_MOSQ_H -#define TIME_MOSQ_H - -time_t mosquitto_time(void); - -#endif diff --git a/libs/libmosquitto/src/tls_mosq.c b/libs/libmosquitto/src/tls_mosq.c deleted file mode 100644 index c2f1204f42..0000000000 --- a/libs/libmosquitto/src/tls_mosq.c +++ /dev/null @@ -1,183 +0,0 @@ -/* -Copyright (c) 2013-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#ifdef WITH_TLS - -#include "config.h" - -#ifdef WIN32 -# include <winsock2.h> -# include <ws2tcpip.h> -#else -# include <arpa/inet.h> -# include <sys/socket.h> -# include <strings.h> -#endif - -#include <string.h> -#include <openssl/conf.h> -#include <openssl/x509v3.h> -#include <openssl/ssl.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "tls_mosq.h" - -extern int tls_ex_index_mosq; - -int mosquitto__server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx) -{ - /* Preverify should have already checked expiry, revocation. - * We need to verify the hostname. */ - struct mosquitto *mosq; - SSL *ssl; - X509 *cert; - - /* Always reject if preverify_ok has failed. */ - if(!preverify_ok) return 0; - - ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq); - if(!mosq) return 0; - - if(mosq->tls_insecure == false){ - if(X509_STORE_CTX_get_error_depth(ctx) == 0){ - /* FIXME - use X509_check_host() etc. for sufficiently new openssl (>=1.1.x) */ - cert = X509_STORE_CTX_get_current_cert(ctx); - /* This is the peer certificate, all others are upwards in the chain. */ -#if defined(WITH_BROKER) - preverify_ok = mosquitto__verify_certificate_hostname(cert, mosq->bridge->addresses[mosq->bridge->cur_address].address); -#else - preverify_ok = mosquitto__verify_certificate_hostname(cert, mosq->host); -#endif - if (preverify_ok != 1) { - log__printf(mosq, MOSQ_LOG_ERR, "Error: host name verification failed."); - } - return preverify_ok; - }else{ - return preverify_ok; - } - }else{ - return preverify_ok; - } -} - -int mosquitto__cmp_hostname_wildcard(char *certname, const char *hostname) -{ - int i; - int len; - - if(!certname || !hostname){ - return 1; - } - - if(certname[0] == '*'){ - if(certname[1] != '.'){ - return 1; - } - certname += 2; - len = strlen(hostname); - for(i=0; i<len-1; i++){ - if(hostname[i] == '.'){ - hostname += i+1; - break; - } - } - return strcasecmp(certname, hostname); - }else{ - return strcasecmp(certname, hostname); - } -} - -/* This code is based heavily on the example provided in "Secure Programming - * Cookbook for C and C++". - */ -int mosquitto__verify_certificate_hostname(X509 *cert, const char *hostname) -{ - int i; - char name[256]; - X509_NAME *subj; - bool have_san_dns = false; - STACK_OF(GENERAL_NAME) *san; - const GENERAL_NAME *nval; - const unsigned char *data; - unsigned char ipv6_addr[16]; - unsigned char ipv4_addr[4]; - int ipv6_ok; - int ipv4_ok; - -#ifdef WIN32 - ipv6_ok = InetPton(AF_INET6, hostname, &ipv6_addr); - ipv4_ok = InetPton(AF_INET, hostname, &ipv4_addr); -#else - ipv6_ok = inet_pton(AF_INET6, hostname, &ipv6_addr); - ipv4_ok = inet_pton(AF_INET, hostname, &ipv4_addr); -#endif - - san = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - if(san){ - for(i=0; i<sk_GENERAL_NAME_num(san); i++){ - nval = sk_GENERAL_NAME_value(san, i); - if(nval->type == GEN_DNS){ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - data = ASN1_STRING_data(nval->d.dNSName); -#else - data = ASN1_STRING_get0_data(nval->d.dNSName); -#endif - if(data && !mosquitto__cmp_hostname_wildcard((char *)data, hostname)){ - sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free); - return 1; - } - have_san_dns = true; - }else if(nval->type == GEN_IPADD){ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - data = ASN1_STRING_data(nval->d.iPAddress); -#else - data = ASN1_STRING_get0_data(nval->d.iPAddress); -#endif - if(nval->d.iPAddress->length == 4 && ipv4_ok){ - if(!memcmp(ipv4_addr, data, 4)){ - sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free); - return 1; - } - }else if(nval->d.iPAddress->length == 16 && ipv6_ok){ - if(!memcmp(ipv6_addr, data, 16)){ - sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free); - return 1; - } - } - } - } - sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free); - if(have_san_dns){ - /* Only check CN if subjectAltName DNS entry does not exist. */ - return 0; - } - } - - subj = X509_get_subject_name(cert); - if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){ - name[sizeof(name) - 1] = '\0'; - if (!mosquitto__cmp_hostname_wildcard(name, hostname)) return 1; - } - return 0; -} - -#endif - diff --git a/libs/libmosquitto/src/tls_mosq.h b/libs/libmosquitto/src/tls_mosq.h deleted file mode 100644 index 5a1cda54fc..0000000000 --- a/libs/libmosquitto/src/tls_mosq.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (c) 2013-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 TLS_MOSQ_H -#define TLS_MOSQ_H - -#ifdef WITH_TLS -# define SSL_DATA_PENDING(A) ((A)->ssl && SSL_pending((A)->ssl)) -#else -# define SSL_DATA_PENDING(A) 0 -#endif - -#ifdef WITH_TLS - -#include <openssl/ssl.h> -#include <openssl/engine.h> - -int mosquitto__server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx); -int mosquitto__verify_certificate_hostname(X509 *cert, const char *hostname); - -#endif /* WITH_TLS */ - -#endif diff --git a/libs/libmosquitto/src/utf8_mosq.c b/libs/libmosquitto/src/utf8_mosq.c deleted file mode 100644 index 875c1c7f27..0000000000 --- a/libs/libmosquitto/src/utf8_mosq.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -Copyright (c) 2016-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <stdio.h> -#include "mosquitto.h" - -int mosquitto_validate_utf8(const char *str, int len) -{ - int i; - int j; - int codelen; - int codepoint; - const unsigned char *ustr = (const unsigned char *)str; - - if(!str) return MOSQ_ERR_INVAL; - if(len < 0 || len > 65536) return MOSQ_ERR_INVAL; - - for(i=0; i<len; i++){ - if(ustr[i] == 0){ - return MOSQ_ERR_MALFORMED_UTF8; - }else if(ustr[i] <= 0x7f){ - codelen = 1; - codepoint = ustr[i]; - }else if((ustr[i] & 0xE0) == 0xC0){ - /* 110xxxxx - 2 byte sequence */ - if(ustr[i] == 0xC0 || ustr[i] == 0xC1){ - /* Invalid bytes */ - return MOSQ_ERR_MALFORMED_UTF8; - } - codelen = 2; - codepoint = (ustr[i] & 0x1F); - }else if((ustr[i] & 0xF0) == 0xE0){ - // 1110xxxx - 3 byte sequence - codelen = 3; - codepoint = (ustr[i] & 0x0F); - }else if((ustr[i] & 0xF8) == 0xF0){ - // 11110xxx - 4 byte sequence - if(ustr[i] > 0xF4){ - /* Invalid, this would produce values > 0x10FFFF. */ - return MOSQ_ERR_MALFORMED_UTF8; - } - codelen = 4; - codepoint = (ustr[i] & 0x07); - }else{ - /* Unexpected continuation byte. */ - return MOSQ_ERR_MALFORMED_UTF8; - } - - /* Reconstruct full code point */ - if(i == len-codelen+1){ - /* Not enough data */ - return MOSQ_ERR_MALFORMED_UTF8; - } - for(j=0; j<codelen-1; j++){ - if((ustr[++i] & 0xC0) != 0x80){ - /* Not a continuation byte */ - return MOSQ_ERR_MALFORMED_UTF8; - } - codepoint = (codepoint<<6) | (ustr[i] & 0x3F); - } - - /* Check for UTF-16 high/low surrogates */ - if(codepoint >= 0xD800 && codepoint <= 0xDFFF){ - return MOSQ_ERR_MALFORMED_UTF8; - } - - /* Check for overlong or out of range encodings */ - /* Checking codelen == 2 isn't necessary here, because it is already - * covered above in the C0 and C1 checks. - * if(codelen == 2 && codepoint < 0x0080){ - * return MOSQ_ERR_MALFORMED_UTF8; - * }else - */ - if(codelen == 3 && codepoint < 0x0800){ - return MOSQ_ERR_MALFORMED_UTF8; - }else if(codelen == 4 && (codepoint < 0x10000 || codepoint > 0x10FFFF)){ - return MOSQ_ERR_MALFORMED_UTF8; - } - - /* Check for non-characters */ - if(codepoint >= 0xFDD0 && codepoint <= 0xFDEF){ - return MOSQ_ERR_MALFORMED_UTF8; - } - if((codepoint & 0xFFFF) == 0xFFFE || (codepoint & 0xFFFF) == 0xFFFF){ - return MOSQ_ERR_MALFORMED_UTF8; - } - /* Check for control characters */ - if(codepoint <= 0x001F || (codepoint >= 0x007F && codepoint <= 0x009F)){ - return MOSQ_ERR_MALFORMED_UTF8; - } - } - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/util_mosq.c b/libs/libmosquitto/src/util_mosq.c deleted file mode 100644 index 5e1065e7c4..0000000000 --- a/libs/libmosquitto/src/util_mosq.c +++ /dev/null @@ -1,354 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WIN32 -# include <winsock2.h> -# include <aclapi.h> -# include <io.h> -# include <lmcons.h> -#else -# include <sys/stat.h> -#endif - -#if !defined(WITH_TLS) && defined(__linux__) && defined(__GLIBC__) -# if __GLIBC_PREREQ(2, 25) -# include <sys/random.h> -# define HAVE_GETRANDOM 1 -# endif -#endif - -#ifdef WITH_TLS -# include <openssl/bn.h> -# include <openssl/rand.h> -#endif - -#ifdef WITH_BROKER -#include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "tls_mosq.h" -#include "util_mosq.h" - -#ifdef WITH_WEBSOCKETS -#include <libwebsockets.h> -#endif - -#ifdef WITH_BROKER -int mosquitto__check_keepalive(struct mosquitto_db *db, struct mosquitto *mosq) -#else -int mosquitto__check_keepalive(struct mosquitto *mosq) -#endif -{ - time_t next_msg_out; - time_t last_msg_in; - time_t now = mosquitto_time(); -#ifndef WITH_BROKER - int rc; -#endif - - assert(mosq); -#if defined(WITH_BROKER) && defined(WITH_BRIDGE) - /* Check if a lazy bridge should be timed out due to idle. */ - if(mosq->bridge && mosq->bridge->start_type == bst_lazy - && mosq->sock != INVALID_SOCKET - && now - mosq->next_msg_out - mosq->keepalive >= mosq->bridge->idle_timeout){ - - log__printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id); - net__socket_close(db, mosq); - return MOSQ_ERR_SUCCESS; - } -#endif - pthread_mutex_lock(&mosq->msgtime_mutex); - next_msg_out = mosq->next_msg_out; - last_msg_in = mosq->last_msg_in; - pthread_mutex_unlock(&mosq->msgtime_mutex); - if(mosq->keepalive && mosq->sock != INVALID_SOCKET && - (now >= next_msg_out || now - last_msg_in >= mosq->keepalive)){ - - if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){ - send__pingreq(mosq); - /* Reset last msg times to give the server time to send a pingresp */ - pthread_mutex_lock(&mosq->msgtime_mutex); - mosq->last_msg_in = now; - mosq->next_msg_out = now + mosq->keepalive; - pthread_mutex_unlock(&mosq->msgtime_mutex); - }else{ -#ifdef WITH_BROKER - net__socket_close(db, mosq); -#else - net__socket_close(mosq); - pthread_mutex_lock(&mosq->state_mutex); - if(mosq->state == mosq_cs_disconnecting){ - rc = MOSQ_ERR_SUCCESS; - }else{ - rc = MOSQ_ERR_KEEPALIVE; - } - pthread_mutex_unlock(&mosq->state_mutex); - pthread_mutex_lock(&mosq->callback_mutex); - if(mosq->on_disconnect){ - mosq->in_callback = true; - mosq->on_disconnect(mosq, mosq->userdata, rc); - mosq->in_callback = false; - } - if(mosq->on_disconnect_v5){ - mosq->in_callback = true; - mosq->on_disconnect_v5(mosq, mosq->userdata, rc, NULL); - mosq->in_callback = false; - } - pthread_mutex_unlock(&mosq->callback_mutex); - - return rc; -#endif - } - } - return MOSQ_ERR_SUCCESS; -} - -uint16_t mosquitto__mid_generate(struct mosquitto *mosq) -{ - /* FIXME - this would be better with atomic increment, but this is safer - * for now for a bug fix release. - * - * If this is changed to use atomic increment, callers of this function - * will have to be aware that they may receive a 0 result, which may not be - * used as a mid. - */ - uint16_t mid; - assert(mosq); - - pthread_mutex_lock(&mosq->mid_mutex); - mosq->last_mid++; - if(mosq->last_mid == 0) mosq->last_mid++; - mid = mosq->last_mid; - pthread_mutex_unlock(&mosq->mid_mutex); - - return mid; -} - - -#ifdef WITH_TLS -int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin) -{ - unsigned char *sha, tmp[SHA_DIGEST_LENGTH]; - - if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH){ - return MOSQ_ERR_INVAL; - } - - sha = mosquitto__malloc(SHA_DIGEST_LENGTH); - memcpy(sha, tmp, SHA_DIGEST_LENGTH); - *bin = sha; - return MOSQ_ERR_SUCCESS; -} - -int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len) -{ - BIGNUM *bn = NULL; - int len; - int leading_zero = 0; - int start = 0; - size_t i = 0; - - /* Count the number of leading zero */ - for(i=0; i<strlen(hex); i=i+2) { - if(strncmp(hex + i, "00", 2) == 0) { - leading_zero++; - /* output leading zero to bin */ - bin[start++] = 0; - }else{ - break; - } - } - - if(BN_hex2bn(&bn, hex) == 0){ - if(bn) BN_free(bn); - return 0; - } - if(BN_num_bytes(bn) + leading_zero > bin_max_len){ - BN_free(bn); - return 0; - } - - len = BN_bn2bin(bn, bin + leading_zero); - BN_free(bn); - return len + leading_zero; -} -#endif - -FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read) -{ -#ifdef WIN32 - char buf[4096]; - int rc; - rc = ExpandEnvironmentStrings(path, buf, 4096); - if(rc == 0 || rc > 4096){ - return NULL; - }else{ - if (restrict_read) { - HANDLE hfile; - SECURITY_ATTRIBUTES sec; - EXPLICIT_ACCESS ea; - PACL pacl = NULL; - char username[UNLEN + 1]; - int ulen = UNLEN; - SECURITY_DESCRIPTOR sd; - DWORD dwCreationDisposition; - - switch(mode[0]){ - case 'a': - dwCreationDisposition = OPEN_ALWAYS; - break; - case 'r': - dwCreationDisposition = OPEN_EXISTING; - break; - case 'w': - dwCreationDisposition = CREATE_ALWAYS; - break; - default: - return NULL; - } - - GetUserName(username, &ulen); - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - return NULL; - } - BuildExplicitAccessWithName(&ea, username, GENERIC_ALL, SET_ACCESS, NO_INHERITANCE); - if (SetEntriesInAcl(1, &ea, NULL, &pacl) != ERROR_SUCCESS) { - return NULL; - } - if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE)) { - LocalFree(pacl); - return NULL; - } - - sec.nLength = sizeof(SECURITY_ATTRIBUTES); - sec.bInheritHandle = FALSE; - sec.lpSecurityDescriptor = &sd; - - hfile = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, 0, - &sec, - dwCreationDisposition, - FILE_ATTRIBUTE_NORMAL, - NULL); - - LocalFree(pacl); - - int fd = _open_osfhandle((intptr_t)hfile, 0); - if (fd < 0) { - return NULL; - } - - FILE *fptr = _fdopen(fd, mode); - if (!fptr) { - _close(fd); - return NULL; - } - return fptr; - - }else { - return fopen(buf, mode); - } - } -#else - if (restrict_read) { - FILE *fptr; - mode_t old_mask; - - old_mask = umask(0077); - fptr = fopen(path, mode); - umask(old_mask); - - return fptr; - }else{ - return fopen(path, mode); - } -#endif -} - -void util__increment_receive_quota(struct mosquitto *mosq) -{ - if(mosq->msgs_in.inflight_quota < mosq->msgs_in.inflight_maximum){ - mosq->msgs_in.inflight_quota++; - } -} - -void util__increment_send_quota(struct mosquitto *mosq) -{ - if(mosq->msgs_out.inflight_quota < mosq->msgs_out.inflight_maximum){ - mosq->msgs_out.inflight_quota++; - } -} - - -void util__decrement_receive_quota(struct mosquitto *mosq) -{ - if(mosq->msgs_in.inflight_quota > 0){ - mosq->msgs_in.inflight_quota--; - } -} - -void util__decrement_send_quota(struct mosquitto *mosq) -{ - if(mosq->msgs_out.inflight_quota > 0){ - mosq->msgs_out.inflight_quota--; - } -} - - -int util__random_bytes(void *bytes, int count) -{ - int rc = MOSQ_ERR_UNKNOWN; - -#ifdef WITH_TLS - if(RAND_bytes(bytes, count) == 1){ - rc = MOSQ_ERR_SUCCESS; - } -#elif defined(HAVE_GETRANDOM) - if(getrandom(bytes, count, 0) == count){ - rc = MOSQ_ERR_SUCCESS; - } -#elif defined(WIN32) - HCRYPTPROV provider; - - if(!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){ - return MOSQ_ERR_UNKNOWN; - } - - if(CryptGenRandom(provider, count, bytes)){ - rc = MOSQ_ERR_SUCCESS; - } - - CryptReleaseContext(provider, 0); -#else - int i; - - for(i=0; i<count; i++){ - ((uint8_t *)bytes)[i] = (uint8_t )(random()&0xFF); - } - rc = MOSQ_ERR_SUCCESS; -#endif - return rc; -} diff --git a/libs/libmosquitto/src/util_mosq.h b/libs/libmosquitto/src/util_mosq.h deleted file mode 100644 index 9ee570f3e9..0000000000 --- a/libs/libmosquitto/src/util_mosq.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright (c) 2009-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 UTIL_MOSQ_H -#define UTIL_MOSQ_H - -#include <stdio.h> - -#include "tls_mosq.h" -#include "mosquitto.h" -#include "mosquitto_internal.h" -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#ifdef WITH_BROKER -int mosquitto__check_keepalive(struct mosquitto_db *db, struct mosquitto *mosq); -#else -int mosquitto__check_keepalive(struct mosquitto *mosq); -#endif -uint16_t mosquitto__mid_generate(struct mosquitto *mosq); -FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read); - -#ifdef WITH_TLS -int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin); -int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len); -#endif - -int util__random_bytes(void *bytes, int count); - -void util__increment_receive_quota(struct mosquitto *mosq); -void util__increment_send_quota(struct mosquitto *mosq); -void util__decrement_receive_quota(struct mosquitto *mosq); -void util__decrement_send_quota(struct mosquitto *mosq); -#endif diff --git a/libs/libmosquitto/src/util_topic.c b/libs/libmosquitto/src/util_topic.c deleted file mode 100644 index 67b78782ef..0000000000 --- a/libs/libmosquitto/src/util_topic.c +++ /dev/null @@ -1,252 +0,0 @@ -/* -Copyright (c) 2009-2018 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <assert.h> -#include <string.h> - -#ifdef WIN32 -# include <winsock2.h> -# include <aclapi.h> -# include <io.h> -# include <lmcons.h> -#else -# include <sys/stat.h> -#endif - - -#ifdef WITH_BROKER -#include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "memory_mosq.h" -#include "net_mosq.h" -#include "send_mosq.h" -#include "time_mosq.h" -#include "tls_mosq.h" -#include "util_mosq.h" - -/* Check that a topic used for publishing is valid. - * Search for + or # in a topic. Return MOSQ_ERR_INVAL if found. - * Also returns MOSQ_ERR_INVAL if the topic string is too long. - * Returns MOSQ_ERR_SUCCESS if everything is fine. - */ -int mosquitto_pub_topic_check(const char *str) -{ - int len = 0; - while(str && str[0]){ - if(str[0] == '+' || str[0] == '#'){ - return MOSQ_ERR_INVAL; - } - len++; - str = &str[1]; - } - if(len > 65535) return MOSQ_ERR_INVAL; - - return MOSQ_ERR_SUCCESS; -} - -int mosquitto_pub_topic_check2(const char *str, size_t len) -{ - size_t i; - - if(len > 65535) return MOSQ_ERR_INVAL; - - for(i=0; i<len; i++){ - if(str[i] == '+' || str[i] == '#'){ - return MOSQ_ERR_INVAL; - } - } - - return MOSQ_ERR_SUCCESS; -} - -/* Check that a topic used for subscriptions is valid. - * Search for + or # in a topic, check they aren't in invalid positions such as - * foo/#/bar, foo/+bar or foo/bar#. - * Return MOSQ_ERR_INVAL if invalid position found. - * Also returns MOSQ_ERR_INVAL if the topic string is too long. - * Returns MOSQ_ERR_SUCCESS if everything is fine. - */ -int mosquitto_sub_topic_check(const char *str) -{ - char c = '\0'; - int len = 0; - while(str && str[0]){ - if(str[0] == '+'){ - if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){ - return MOSQ_ERR_INVAL; - } - }else if(str[0] == '#'){ - if((c != '\0' && c != '/') || str[1] != '\0'){ - return MOSQ_ERR_INVAL; - } - } - len++; - c = str[0]; - str = &str[1]; - } - if(len > 65535) return MOSQ_ERR_INVAL; - - return MOSQ_ERR_SUCCESS; -} - -int mosquitto_sub_topic_check2(const char *str, size_t len) -{ - char c = '\0'; - size_t i; - - if(len > 65535) return MOSQ_ERR_INVAL; - - for(i=0; i<len; i++){ - if(str[i] == '+'){ - if((c != '\0' && c != '/') || (i<len-1 && str[i+1] != '/')){ - return MOSQ_ERR_INVAL; - } - }else if(str[i] == '#'){ - if((c != '\0' && c != '/') || i<len-1){ - return MOSQ_ERR_INVAL; - } - } - c = str[i]; - } - - return MOSQ_ERR_SUCCESS; -} - -int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result) -{ - return mosquitto_topic_matches_sub2(sub, 0, topic, 0, result); -} - -/* Does a topic match a subscription? */ -int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result) -{ - size_t spos; - - UNUSED(sublen); - UNUSED(topiclen); - - if(!result) return MOSQ_ERR_INVAL; - *result = false; - - if(!sub || !topic || sub[0] == 0 || topic[0] == 0){ - return MOSQ_ERR_INVAL; - } - - if((sub[0] == '$' && topic[0] != '$') - || (topic[0] == '$' && sub[0] != '$')){ - - return MOSQ_ERR_SUCCESS; - } - - spos = 0; - - while(sub[0] != 0){ - if(topic[0] == '+' || topic[0] == '#'){ - return MOSQ_ERR_INVAL; - } - if(sub[0] != topic[0] || topic[0] == 0){ /* Check for wildcard matches */ - if(sub[0] == '+'){ - /* Check for bad "+foo" or "a/+foo" subscription */ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - /* Check for bad "foo+" or "foo+/a" subscription */ - if(sub[1] != 0 && sub[1] != '/'){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - while(topic[0] != 0 && topic[0] != '/'){ - topic++; - } - if(topic[0] == 0 && sub[0] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - } - }else if(sub[0] == '#'){ - /* Check for bad "foo#" subscription */ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - /* Check for # not the final character of the sub, e.g. "#foo" */ - if(sub[1] != 0){ - return MOSQ_ERR_INVAL; - }else{ - *result = true; - return MOSQ_ERR_SUCCESS; - } - }else{ - /* Check for e.g. foo/bar matching foo/+/# */ - if(topic[0] == 0 - && spos > 0 - && sub[-1] == '+' - && sub[0] == '/' - && sub[1] == '#') - { - *result = true; - return MOSQ_ERR_SUCCESS; - } - - /* There is no match at this point, but is the sub invalid? */ - while(sub[0] != 0){ - if(sub[0] == '#' && sub[1] != 0){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - } - - /* Valid input, but no match */ - return MOSQ_ERR_SUCCESS; - } - }else{ - /* sub[spos] == topic[tpos] */ - if(topic[1] == 0){ - /* Check for e.g. foo matching foo/# */ - if(sub[1] == '/' - && sub[2] == '#' - && sub[3] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - } - } - spos++; - sub++; - topic++; - if(sub[0] == 0 && topic[0] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - }else if(topic[0] == 0 && sub[0] == '+' && sub[1] == 0){ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - *result = true; - return MOSQ_ERR_SUCCESS; - } - } - } - if((topic[0] != 0 || sub[0] != 0)){ - *result = false; - } - - return MOSQ_ERR_SUCCESS; -} diff --git a/libs/libmosquitto/src/will_mosq.c b/libs/libmosquitto/src/will_mosq.c deleted file mode 100644 index f9f1f32a56..0000000000 --- a/libs/libmosquitto/src/will_mosq.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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. -*/ - -#include "config.h" - -#include <stdio.h> -#include <string.h> - -#ifdef WITH_BROKER -# include "mosquitto_broker_internal.h" -#endif - -#include "mosquitto.h" -#include "mosquitto_internal.h" -#include "logging_mosq.h" -#include "messages_mosq.h" -#include "memory_mosq.h" -#include "mqtt_protocol.h" -#include "net_mosq.h" -#include "read_handle.h" -#include "send_mosq.h" -#include "util_mosq.h" -#include "will_mosq.h" - -int will__set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties) -{ - int rc = MOSQ_ERR_SUCCESS; - mosquitto_property *p; - - if(!mosq || !topic) return MOSQ_ERR_INVAL; - if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; - if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL; - - if(mosquitto_pub_topic_check(topic)) return MOSQ_ERR_INVAL; - if(mosquitto_validate_utf8(topic, strlen(topic))) return MOSQ_ERR_MALFORMED_UTF8; - - if(properties){ - if(mosq->protocol != mosq_p_mqtt5){ - return MOSQ_ERR_NOT_SUPPORTED; - } - p = properties; - while(p){ - rc = mosquitto_property_check_command(CMD_WILL, p->identifier); - if(rc) return rc; - p = p->next; - } - } - - if(mosq->will){ - mosquitto__free(mosq->will->msg.topic); - mosquitto__free(mosq->will->msg.payload); - mosquitto_property_free_all(&mosq->will->properties); - mosquitto__free(mosq->will); - } - - mosq->will = mosquitto__calloc(1, sizeof(struct mosquitto_message_all)); - if(!mosq->will) return MOSQ_ERR_NOMEM; - mosq->will->msg.topic = mosquitto__strdup(topic); - if(!mosq->will->msg.topic){ - rc = MOSQ_ERR_NOMEM; - goto cleanup; - } - mosq->will->msg.payloadlen = payloadlen; - if(mosq->will->msg.payloadlen > 0){ - if(!payload){ - rc = MOSQ_ERR_INVAL; - goto cleanup; - } - mosq->will->msg.payload = mosquitto__malloc(sizeof(char)*mosq->will->msg.payloadlen); - if(!mosq->will->msg.payload){ - rc = MOSQ_ERR_NOMEM; - goto cleanup; - } - - memcpy(mosq->will->msg.payload, payload, payloadlen); - } - mosq->will->msg.qos = qos; - mosq->will->msg.retain = retain; - - mosq->will->properties = properties; - - return MOSQ_ERR_SUCCESS; - -cleanup: - if(mosq->will){ - mosquitto__free(mosq->will->msg.topic); - mosquitto__free(mosq->will->msg.payload); - - mosquitto__free(mosq->will); - mosq->will = NULL; - } - - return rc; -} - -int will__clear(struct mosquitto *mosq) -{ - if(!mosq->will) return MOSQ_ERR_SUCCESS; - - mosquitto__free(mosq->will->msg.topic); - mosq->will->msg.topic = NULL; - - mosquitto__free(mosq->will->msg.payload); - mosq->will->msg.payload = NULL; - - mosquitto_property_free_all(&mosq->will->properties); - - mosquitto__free(mosq->will); - mosq->will = NULL; - - return MOSQ_ERR_SUCCESS; -} - diff --git a/libs/libmosquitto/src/will_mosq.h b/libs/libmosquitto/src/will_mosq.h deleted file mode 100644 index c96dad1a71..0000000000 --- a/libs/libmosquitto/src/will_mosq.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright (c) 2010-2019 Roger Light <roger@atchoo.org> - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 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 WILL_MOSQ_H -#define WILL_MOSQ_H - -#include "mosquitto.h" -#include "mosquitto_internal.h" - -int will__set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties); -int will__clear(struct mosquitto *mosq); - -#endif |