diff --git a/include/mosquitto/libcommon_properties.h b/include/mosquitto/libcommon_properties.h index b3fecb87..f46d12f9 100644 --- a/include/mosquitto/libcommon_properties.h +++ b/include/mosquitto/libcommon_properties.h @@ -1,758 +1,758 @@ -/* -Copyright (c) 2010-2021 Roger Light - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 2.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - https://www.eclipse.org/legal/epl-2.0/ -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -Contributors: - Roger Light - initial implementation and documentation. -*/ - -#ifndef MOSQUITTO_LIBCOMMON_PROPERTIES_H -#define MOSQUITTO_LIBCOMMON_PROPERTIES_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================= - * - * 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); - */ -libmosqcommon_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); - */ -libmosqcommon_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); - */ -libmosqcommon_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); - */ -libmosqcommon_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); - */ -libmosqcommon_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"); - */ -libmosqcommon_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"); - */ -libmosqcommon_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value); - - -/* - * Function: mosquitto_property_remove - * - * Remove a property from a property list. The property will not be freed. - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * property - pointer to the property to remove - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if proplist is NULL or property is NULL - * MOSQ_ERR_NOT_FOUND - if the property was not found - */ -libmosqcommon_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property); - - -/* - * Function: mosquitto_property_identifier - * - * Return the property identifier for a single property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * A valid property identifier on success - * 0 - on error - */ -libmosqcommon_EXPORT int mosquitto_property_identifier(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_next - * - * Return the next property in a property list. Use to iterate over a property - * list, e.g.: - * - * (start code) - * for(prop = proplist; prop != NULL; prop = mosquitto_property_next(prop)){ - * if(mosquitto_property_identifier(prop) == MQTT_PROP_CONTENT_TYPE){ - * ... - * } - * } - * (end) - * - * Parameters: - * proplist - pointer to mosquitto_property pointer, the list of properties - * - * Returns: - * Pointer to the next item in the list - * NULL, if proplist is NULL, or if there are no more items in the list. - */ -libmosqcommon_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist); - - -/* - * 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: - * - * (start code) - * 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); - * (end) - * - * 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: - * (start code) - * // 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); - * } - * (end) - */ -libmosqcommon_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 - */ -libmosqcommon_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 - */ -libmosqcommon_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 - */ -libmosqcommon_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. - * Will be set to NULL if the value has zero length. - * 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 - */ -libmosqcommon_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. - * Will be set to NULL if the value has zero length. - * 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 - */ -libmosqcommon_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. - * Will be set to NULL if the name has zero length. - * value - pointer to char*, for the property data to be stored in, or NULL if - * the value is not required. - * Will be set to NULL if the value has zero length. - * 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 - */ -libmosqcommon_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_type - * - * Return the property type for a single property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * A valid property type on success - * 0 - on error - */ -libmosqcommon_EXPORT int mosquitto_property_type(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_byte_value - * - * Return the property value for a byte type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Byte value on success - * 0 - on error (property is NULL, or not a byte) - */ -libmosqcommon_EXPORT uint8_t mosquitto_property_byte_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_int16_value - * - * Return the property value for an int16 type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Int16 value on success - * 0 - on error (property is NULL, or not a int16) - */ -libmosqcommon_EXPORT uint16_t mosquitto_property_int16_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_int32_value - * - * Return the property value for an int32 type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Int32 value on success - * 0 - on error (property is NULL, or not a int32) - */ -libmosqcommon_EXPORT uint32_t mosquitto_property_int32_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_varint_value - * - * Return the property value for a varint type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Varint value on success - * 0 - on error (property is NULL, or not a varint) - */ -libmosqcommon_EXPORT uint32_t mosquitto_property_varint_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_binary_value - * - * Return the property value for a binary type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Binary value on success - * NULL - on error (property is NULL, or not a binary) - */ -libmosqcommon_EXPORT const void *mosquitto_property_binary_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_byte_value_length - * - * Return the property value for a byte type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Binary value length on success - * 0 - on error (property is NULL, or not a binary) - */ -libmosqcommon_EXPORT uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_string_value - * - * Return the property value for a string or string pair type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * String value on success - * NULL - on error (property is NULL, or not a string or string pair) - */ -libmosqcommon_EXPORT const char *mosquitto_property_string_value(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_string_value_length - * - * Return the length of the property value for a string or string pair type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Value length on success - * 0 - on error (property is NULL, or not a string or string pair) - */ -libmosqcommon_EXPORT uint16_t mosquitto_property_string_value_length(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_string_value - * - * Return the property name for a string pair type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * String name on success - * NULL - on error (property is NULL, or not a string pair) - */ -libmosqcommon_EXPORT const char *mosquitto_property_string_name(const mosquitto_property *property); - - -/* - * Function: mosquitto_property_string_name_length - * - * Return the property name length for a string pair type property. - * - * Parameters: - * property - pointer to a valid mosquitto_property pointer. - * - * Returns: - * Name length on success - * 0 - on error (property is NULL, or not a string pair) - */ -libmosqcommon_EXPORT uint16_t mosquitto_property_string_name_length(const mosquitto_property *property); - - -/* - * 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); - */ -libmosqcommon_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) - */ -libmosqcommon_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. - */ -libmosqcommon_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 - */ -libmosqcommon_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties); - -/* - * Function: mosquitto_property_identifier_to_string - * - * Return the property name as a string for a property identifier. - * The property name is as defined in the MQTT specification, with - as a - * separator, for example: payload-format-indicator. - * - * Parameters: - * identifier - valid MQTT property identifier integer - * - * Returns: - * A const string to the property name on success - * NULL on failure - */ -libmosqcommon_EXPORT const char *mosquitto_property_identifier_to_string(int identifier); - - -/* 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: - * (start code) - * mosquitto_string_to_property_info("response-topic", &id, &type); - * // id == MQTT_PROP_RESPONSE_TOPIC - * // type == MQTT_PROP_TYPE_STRING - * (end) - */ -libmosqcommon_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type); - - -libmosqcommon_EXPORT void mosquitto_property_free(mosquitto_property **property); -libmosqcommon_EXPORT unsigned int mosquitto_property_get_length(const mosquitto_property *property); -libmosqcommon_EXPORT unsigned int mosquitto_property_get_length_all(const mosquitto_property *property); -libmosqcommon_EXPORT unsigned int mosquitto_property_get_remaining_length(const mosquitto_property* props); -libmosqcommon_EXPORT unsigned int mosquitto_varint_bytes(uint32_t word); - -#ifdef __cplusplus -} -#endif - -#endif +/* +Copyright (c) 2010-2021 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#ifndef MOSQUITTO_LIBCOMMON_PROPERTIES_H +#define MOSQUITTO_LIBCOMMON_PROPERTIES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================= + * + * 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); + */ +libmosqcommon_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); + */ +libmosqcommon_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); + */ +libmosqcommon_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); + */ +libmosqcommon_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); + */ +libmosqcommon_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"); + */ +libmosqcommon_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"); + */ +libmosqcommon_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value); + + +/* + * Function: mosquitto_property_remove + * + * Remove a property from a property list. The property will not be freed. + * + * Parameters: + * proplist - pointer to mosquitto_property pointer, the list of properties + * property - pointer to the property to remove + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if proplist is NULL or property is NULL + * MOSQ_ERR_NOT_FOUND - if the property was not found + */ +libmosqcommon_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property); + + +/* + * Function: mosquitto_property_identifier + * + * Return the property identifier for a single property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * A valid property identifier on success + * 0 - on error + */ +libmosqcommon_EXPORT int mosquitto_property_identifier(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_next + * + * Return the next property in a property list. Use to iterate over a property + * list, e.g.: + * + * (start code) + * for(prop = proplist; prop != NULL; prop = mosquitto_property_next(prop)){ + * if(mosquitto_property_identifier(prop) == MQTT_PROP_CONTENT_TYPE){ + * ... + * } + * } + * (end) + * + * Parameters: + * proplist - pointer to mosquitto_property pointer, the list of properties + * + * Returns: + * Pointer to the next item in the list + * NULL, if proplist is NULL, or if there are no more items in the list. + */ +libmosqcommon_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist); + + +/* + * 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: + * + * (start code) + * 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); + * (end) + * + * 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: + * (start code) + * // 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); + * } + * (end) + */ +libmosqcommon_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 + */ +libmosqcommon_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 + */ +libmosqcommon_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 + */ +libmosqcommon_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. + * Will be set to NULL if the value has zero length. + * 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 + */ +libmosqcommon_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. + * Will be set to NULL if the value has zero length. + * 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 + */ +libmosqcommon_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. + * Will be set to NULL if the name has zero length. + * value - pointer to char*, for the property data to be stored in, or NULL if + * the value is not required. + * Will be set to NULL if the value has zero length. + * 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 + */ +libmosqcommon_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_type + * + * Return the property type for a single property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * A valid property type on success + * 0 - on error + */ +libmosqcommon_EXPORT int mosquitto_property_type(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_byte_value + * + * Return the property value for a byte type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Byte value on success + * 0 - on error (property is NULL, or not a byte) + */ +libmosqcommon_EXPORT uint8_t mosquitto_property_byte_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_int16_value + * + * Return the property value for an int16 type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Int16 value on success + * 0 - on error (property is NULL, or not a int16) + */ +libmosqcommon_EXPORT uint16_t mosquitto_property_int16_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_int32_value + * + * Return the property value for an int32 type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Int32 value on success + * 0 - on error (property is NULL, or not a int32) + */ +libmosqcommon_EXPORT uint32_t mosquitto_property_int32_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_varint_value + * + * Return the property value for a varint type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Varint value on success + * 0 - on error (property is NULL, or not a varint) + */ +libmosqcommon_EXPORT uint32_t mosquitto_property_varint_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_binary_value + * + * Return the property value for a binary type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Binary value on success + * NULL - on error (property is NULL, or not a binary) + */ +libmosqcommon_EXPORT const void *mosquitto_property_binary_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_byte_value_length + * + * Return the property value for a byte type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Binary value length on success + * 0 - on error (property is NULL, or not a binary) + */ +libmosqcommon_EXPORT uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_string_value + * + * Return the property value for a string or string pair type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * String value on success + * NULL - on error (property is NULL, or not a string or string pair) + */ +libmosqcommon_EXPORT const char *mosquitto_property_string_value(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_string_value_length + * + * Return the length of the property value for a string or string pair type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Value length on success + * 0 - on error (property is NULL, or not a string or string pair) + */ +libmosqcommon_EXPORT uint16_t mosquitto_property_string_value_length(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_string_value + * + * Return the property name for a string pair type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * String name on success + * NULL - on error (property is NULL, or not a string pair) + */ +libmosqcommon_EXPORT const char *mosquitto_property_string_name(const mosquitto_property *property); + + +/* + * Function: mosquitto_property_string_name_length + * + * Return the property name length for a string pair type property. + * + * Parameters: + * property - pointer to a valid mosquitto_property pointer. + * + * Returns: + * Name length on success + * 0 - on error (property is NULL, or not a string pair) + */ +libmosqcommon_EXPORT uint16_t mosquitto_property_string_name_length(const mosquitto_property *property); + + +/* + * 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); + */ +libmosqcommon_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) + */ +libmosqcommon_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. + */ +libmosqcommon_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 + */ +libmosqcommon_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties); + +/* + * Function: mosquitto_property_identifier_to_string + * + * Return the property name as a string for a property identifier. + * The property name is as defined in the MQTT specification, with - as a + * separator, for example: payload-format-indicator. + * + * Parameters: + * identifier - valid MQTT property identifier integer + * + * Returns: + * A const string to the property name on success + * NULL on failure + */ +libmosqcommon_EXPORT const char *mosquitto_property_identifier_to_string(int identifier); + + +/* 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: + * (start code) + * mosquitto_string_to_property_info("response-topic", &id, &type); + * // id == MQTT_PROP_RESPONSE_TOPIC + * // type == MQTT_PROP_TYPE_STRING + * (end) + */ +libmosqcommon_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type); + + +libmosqcommon_EXPORT void mosquitto_property_free(mosquitto_property **property); +libmosqcommon_EXPORT unsigned int mosquitto_property_get_length(const mosquitto_property *property); +libmosqcommon_EXPORT unsigned int mosquitto_property_get_length_all(const mosquitto_property *property); +libmosqcommon_EXPORT unsigned int mosquitto_property_get_remaining_length(const mosquitto_property* props); +libmosqcommon_EXPORT unsigned int mosquitto_varint_bytes(uint32_t word); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/mosquitto/mqtt_protocol.h b/include/mosquitto/mqtt_protocol.h index f9437a10..9f4a9798 100644 --- a/include/mosquitto/mqtt_protocol.h +++ b/include/mosquitto/mqtt_protocol.h @@ -1,294 +1,294 @@ -/* -Copyright (c) 2009-2021 Roger Light - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 2.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - https://www.eclipse.org/legal/epl-2.0/ -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -Contributors: - Roger Light - initial implementation and documentation. -*/ - -#ifndef MQTT_PROTOCOL_H -#define MQTT_PROTOCOL_H - -#include - -/* - * File: mosquitto/mqtt_protocol.h - * - * This header contains definitions of MQTT values as defined in the specifications. - */ -#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 0x10U -#define CMD_CONNACK 0x20U -#define CMD_PUBLISH 0x30U -#define CMD_PUBACK 0x40U -#define CMD_PUBREC 0x50U -#define CMD_PUBREL 0x60U -#define CMD_PUBCOMP 0x70U -#define CMD_SUBSCRIBE 0x80U -#define CMD_SUBACK 0x90U -#define CMD_UNSUBSCRIBE 0xA0U -#define CMD_UNSUBACK 0xB0U -#define CMD_PINGREQ 0xC0U -#define CMD_PINGRESP 0xD0U -#define CMD_DISCONNECT 0xE0U -#define CMD_AUTH 0xF0U - -/* Mosquitto only: for distinguishing CONNECT and WILL properties */ -#define CMD_WILL 0x100 - -/* Enum: mqtt311_connack_codes - * - * The CONNACK results for MQTT v3.1.1, and v3.1. - * - * Values: - * 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 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 - * The reason codes returned in various MQTT commands. - * - * Values: - * MQTT_RC_SUCCESS - 0 - * MQTT_RC_NORMAL_DISCONNECTION - 0 - * MQTT_RC_GRANTED_QOS0 - 0 - * MQTT_RC_GRANTED_QOS1 - 1 - * MQTT_RC_GRANTED_QOS2 - 2 - * MQTT_RC_DISCONNECT_WITH_WILL_MSG - 4 - * MQTT_RC_NO_MATCHING_SUBSCRIBERS - 16 - * MQTT_RC_NO_SUBSCRIPTION_EXISTED - 17 - * MQTT_RC_CONTINUE_AUTHENTICATION - 24 - * MQTT_RC_REAUTHENTICATE - 25 - * MQTT_RC_UNSPECIFIED - 128 - * MQTT_RC_MALFORMED_PACKET - 129 - * MQTT_RC_PROTOCOL_ERROR - 130 - * MQTT_RC_IMPLEMENTATION_SPECIFIC - 131 - * MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION - 132 - * MQTT_RC_CLIENTID_NOT_VALID - 133 - * MQTT_RC_BAD_USERNAME_OR_PASSWORD - 134 - * MQTT_RC_NOT_AUTHORIZED - 135 - * MQTT_RC_SERVER_UNAVAILABLE - 136 - * MQTT_RC_SERVER_BUSY - 137 - * MQTT_RC_BANNED - 138 - * MQTT_RC_SERVER_SHUTTING_DOWN - 139 - * MQTT_RC_BAD_AUTHENTICATION_METHOD - 140 - * MQTT_RC_KEEP_ALIVE_TIMEOUT - 141 - * MQTT_RC_SESSION_TAKEN_OVER - 142 - * MQTT_RC_TOPIC_FILTER_INVALID - 143 - * MQTT_RC_TOPIC_NAME_INVALID - 144 - * MQTT_RC_PACKET_ID_IN_USE - 145 - * MQTT_RC_PACKET_ID_NOT_FOUND - 146 - * MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED - 147 - * MQTT_RC_TOPIC_ALIAS_INVALID - 148 - * MQTT_RC_PACKET_TOO_LARGE - 149 - * MQTT_RC_MESSAGE_RATE_TOO_HIGH - 150 - * MQTT_RC_QUOTA_EXCEEDED - 151 - * MQTT_RC_ADMINISTRATIVE_ACTION - 152 - * MQTT_RC_PAYLOAD_FORMAT_INVALID - 153 - * MQTT_RC_RETAIN_NOT_SUPPORTED - 154 - * MQTT_RC_QOS_NOT_SUPPORTED - 155 - * MQTT_RC_USE_ANOTHER_SERVER - 156 - * MQTT_RC_SERVER_MOVED - 157 - * MQTT_RC_SHARED_SUBS_NOT_SUPPORTED - 158 - * MQTT_RC_CONNECTION_RATE_EXCEEDED - 159 - * MQTT_RC_MAXIMUM_CONNECT_TIME - 160 - * MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED - 161 - * MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED - 162 - */ -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 - * Options for use with MQTTv5 properties. - * Options: - * - * MQTT_PROP_PAYLOAD_FORMAT_INDICATOR - property option. - * MQTT_PROP_MESSAGE_EXPIRY_INTERVAL - property option. - * MQTT_PROP_CONTENT_TYPE - property option. - * MQTT_PROP_RESPONSE_TOPIC - property option. - * MQTT_PROP_CORRELATION_DATA - property option. - * MQTT_PROP_SUBSCRIPTION_IDENTIFIER - property option. - * MQTT_PROP_SESSION_EXPIRY_INTERVAL - property option. - * MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER - property option. - * MQTT_PROP_SERVER_KEEP_ALIVE - property option. - * MQTT_PROP_AUTHENTICATION_METHOD - property option. - * MQTT_PROP_AUTHENTICATION_DATA - property option. - * MQTT_PROP_REQUEST_PROBLEM_INFORMATION - property option. - * MQTT_PROP_WILL_DELAY_INTERVAL - property option. - * MQTT_PROP_REQUEST_RESPONSE_INFORMATION - property option. - * MQTT_PROP_RESPONSE_INFORMATION - property option. - * MQTT_PROP_SERVER_REFERENCE - property option. - * MQTT_PROP_REASON_STRING - property option. - * MQTT_PROP_RECEIVE_MAXIMUM - property option. - * MQTT_PROP_TOPIC_ALIAS_MAXIMUM - property option. - * MQTT_PROP_TOPIC_ALIAS - property option. - * MQTT_PROP_MAXIMUM_QOS - property option. - * MQTT_PROP_RETAIN_AVAILABLE - property option. - * MQTT_PROP_USER_PROPERTY - property option. - * MQTT_PROP_MAXIMUM_PACKET_SIZE - property option. - * MQTT_PROP_WILDCARD_SUB_AVAILABLE - property option. - * MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - property option. - * MQTT_PROP_SHARED_SUB_AVAILABLE - property option. - */ -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 : CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH */ - 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 - * Options for use with MQTTv5 subscriptions. - * - * 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. - */ -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 268435455U - -#define MQTT_SUB_OPT_GET_QOS(opt) ((opt) & 0x03) -#define MQTT_SUB_OPT_GET_NO_LOCAL(opt) ((opt) & MQTT_SUB_OPT_NO_LOCAL) -#define MQTT_SUB_OPT_GET_RETAIN_AS_PUBLISHED(opt) ((opt) & MQTT_SUB_OPT_RETAIN_AS_PUBLISHED) -#define MQTT_SUB_OPT_GET_SEND_RETAIN(opt) ((opt) & (MQTT_SUB_OPT_SEND_RETAIN_NEW | MQTT_SUB_OPT_SEND_RETAIN_NEVER)) - -#define MQTT_SUB_OPT_SET_QOS(opt, qos) ((opt) = ((opt) & 0xFC) | ((qos) & 0x03)) - -#define MQTT_SUB_OPT_SET(opt, val) ((opt) |= val) -#define MQTT_SUB_OPT_CLEAR(opt, val) ((opt) = (opt) & !val) - -#endif +/* +Copyright (c) 2009-2021 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#ifndef MQTT_PROTOCOL_H +#define MQTT_PROTOCOL_H + +#include + +/* + * File: mosquitto/mqtt_protocol.h + * + * This header contains definitions of MQTT values as defined in the specifications. + */ +#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 0x10U +#define CMD_CONNACK 0x20U +#define CMD_PUBLISH 0x30U +#define CMD_PUBACK 0x40U +#define CMD_PUBREC 0x50U +#define CMD_PUBREL 0x60U +#define CMD_PUBCOMP 0x70U +#define CMD_SUBSCRIBE 0x80U +#define CMD_SUBACK 0x90U +#define CMD_UNSUBSCRIBE 0xA0U +#define CMD_UNSUBACK 0xB0U +#define CMD_PINGREQ 0xC0U +#define CMD_PINGRESP 0xD0U +#define CMD_DISCONNECT 0xE0U +#define CMD_AUTH 0xF0U + +/* Mosquitto only: for distinguishing CONNECT and WILL properties */ +#define CMD_WILL 0x100 + +/* Enum: mqtt311_connack_codes + * + * The CONNACK results for MQTT v3.1.1, and v3.1. + * + * Values: + * 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 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 + * The reason codes returned in various MQTT commands. + * + * Values: + * MQTT_RC_SUCCESS - 0 + * MQTT_RC_NORMAL_DISCONNECTION - 0 + * MQTT_RC_GRANTED_QOS0 - 0 + * MQTT_RC_GRANTED_QOS1 - 1 + * MQTT_RC_GRANTED_QOS2 - 2 + * MQTT_RC_DISCONNECT_WITH_WILL_MSG - 4 + * MQTT_RC_NO_MATCHING_SUBSCRIBERS - 16 + * MQTT_RC_NO_SUBSCRIPTION_EXISTED - 17 + * MQTT_RC_CONTINUE_AUTHENTICATION - 24 + * MQTT_RC_REAUTHENTICATE - 25 + * MQTT_RC_UNSPECIFIED - 128 + * MQTT_RC_MALFORMED_PACKET - 129 + * MQTT_RC_PROTOCOL_ERROR - 130 + * MQTT_RC_IMPLEMENTATION_SPECIFIC - 131 + * MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION - 132 + * MQTT_RC_CLIENTID_NOT_VALID - 133 + * MQTT_RC_BAD_USERNAME_OR_PASSWORD - 134 + * MQTT_RC_NOT_AUTHORIZED - 135 + * MQTT_RC_SERVER_UNAVAILABLE - 136 + * MQTT_RC_SERVER_BUSY - 137 + * MQTT_RC_BANNED - 138 + * MQTT_RC_SERVER_SHUTTING_DOWN - 139 + * MQTT_RC_BAD_AUTHENTICATION_METHOD - 140 + * MQTT_RC_KEEP_ALIVE_TIMEOUT - 141 + * MQTT_RC_SESSION_TAKEN_OVER - 142 + * MQTT_RC_TOPIC_FILTER_INVALID - 143 + * MQTT_RC_TOPIC_NAME_INVALID - 144 + * MQTT_RC_PACKET_ID_IN_USE - 145 + * MQTT_RC_PACKET_ID_NOT_FOUND - 146 + * MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED - 147 + * MQTT_RC_TOPIC_ALIAS_INVALID - 148 + * MQTT_RC_PACKET_TOO_LARGE - 149 + * MQTT_RC_MESSAGE_RATE_TOO_HIGH - 150 + * MQTT_RC_QUOTA_EXCEEDED - 151 + * MQTT_RC_ADMINISTRATIVE_ACTION - 152 + * MQTT_RC_PAYLOAD_FORMAT_INVALID - 153 + * MQTT_RC_RETAIN_NOT_SUPPORTED - 154 + * MQTT_RC_QOS_NOT_SUPPORTED - 155 + * MQTT_RC_USE_ANOTHER_SERVER - 156 + * MQTT_RC_SERVER_MOVED - 157 + * MQTT_RC_SHARED_SUBS_NOT_SUPPORTED - 158 + * MQTT_RC_CONNECTION_RATE_EXCEEDED - 159 + * MQTT_RC_MAXIMUM_CONNECT_TIME - 160 + * MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED - 161 + * MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED - 162 + */ +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 + * Options for use with MQTTv5 properties. + * Options: + * + * MQTT_PROP_PAYLOAD_FORMAT_INDICATOR - property option. + * MQTT_PROP_MESSAGE_EXPIRY_INTERVAL - property option. + * MQTT_PROP_CONTENT_TYPE - property option. + * MQTT_PROP_RESPONSE_TOPIC - property option. + * MQTT_PROP_CORRELATION_DATA - property option. + * MQTT_PROP_SUBSCRIPTION_IDENTIFIER - property option. + * MQTT_PROP_SESSION_EXPIRY_INTERVAL - property option. + * MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER - property option. + * MQTT_PROP_SERVER_KEEP_ALIVE - property option. + * MQTT_PROP_AUTHENTICATION_METHOD - property option. + * MQTT_PROP_AUTHENTICATION_DATA - property option. + * MQTT_PROP_REQUEST_PROBLEM_INFORMATION - property option. + * MQTT_PROP_WILL_DELAY_INTERVAL - property option. + * MQTT_PROP_REQUEST_RESPONSE_INFORMATION - property option. + * MQTT_PROP_RESPONSE_INFORMATION - property option. + * MQTT_PROP_SERVER_REFERENCE - property option. + * MQTT_PROP_REASON_STRING - property option. + * MQTT_PROP_RECEIVE_MAXIMUM - property option. + * MQTT_PROP_TOPIC_ALIAS_MAXIMUM - property option. + * MQTT_PROP_TOPIC_ALIAS - property option. + * MQTT_PROP_MAXIMUM_QOS - property option. + * MQTT_PROP_RETAIN_AVAILABLE - property option. + * MQTT_PROP_USER_PROPERTY - property option. + * MQTT_PROP_MAXIMUM_PACKET_SIZE - property option. + * MQTT_PROP_WILDCARD_SUB_AVAILABLE - property option. + * MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - property option. + * MQTT_PROP_SHARED_SUB_AVAILABLE - property option. + */ +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 : CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH */ + 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 + * Options for use with MQTTv5 subscriptions. + * + * 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. + */ +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 268435455U + +#define MQTT_SUB_OPT_GET_QOS(opt) ((opt) & 0x03) +#define MQTT_SUB_OPT_GET_NO_LOCAL(opt) ((opt) & MQTT_SUB_OPT_NO_LOCAL) +#define MQTT_SUB_OPT_GET_RETAIN_AS_PUBLISHED(opt) ((opt) & MQTT_SUB_OPT_RETAIN_AS_PUBLISHED) +#define MQTT_SUB_OPT_GET_SEND_RETAIN(opt) ((opt) & (MQTT_SUB_OPT_SEND_RETAIN_NEW | MQTT_SUB_OPT_SEND_RETAIN_NEVER)) + +#define MQTT_SUB_OPT_SET_QOS(opt, qos) ((opt) = ((opt) & 0xFC) | ((qos) & 0x03)) + +#define MQTT_SUB_OPT_SET(opt, val) ((opt) |= val) +#define MQTT_SUB_OPT_CLEAR(opt, val) ((opt) = (opt) & !val) + +#endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index da7fceff..e3bde9d2 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,171 +1,171 @@ -option(WITH_LIB_CPP "Build C++ library?" ON) -if(WITH_LIB_CPP) - add_subdirectory(cpp) -endif() - -set(C_SRC - actions_publish.c - actions_subscribe.c - actions_unsubscribe.c - alias_mosq.c alias_mosq.h - callbacks.c - connect.c - handle_auth.c - handle_connack.c - handle_disconnect.c - handle_ping.c - handle_pubackcomp.c - handle_publish.c - handle_pubrec.c - handle_pubrel.c - handle_suback.c - handle_unsuback.c - helpers.c - http_client.c http_client.h - logging_mosq.c logging_mosq.h - loop.c - messages_mosq.c messages_mosq.h - mosquitto.c ../include/mosquitto.h - mosquitto_internal.h - ../include/mosquitto/mqtt_protocol.h - net_mosq_ocsp.c net_mosq.c net_mosq.h - net_ws.c - options.c - packet_datatypes.c - packet_mosq.c packet_mosq.h - property_mosq.c property_mosq.h - read_handle.c read_handle.h - send_connect.c - send_disconnect.c - send_mosq.c - send_publish.c - send_subscribe.c - send_unsubscribe.c - send_mosq.c send_mosq.h - socks_mosq.c - srv_mosq.c - thread_mosq.c - tls_mosq.c - util_mosq.c util_mosq.h - will_mosq.c will_mosq.h) - -set(LIBRARIES common-options) - -if(WITH_TLS) - set (LIBRARIES ${LIBRARIES} OpenSSL::SSL) -endif() - -if(UNIX AND NOT APPLE AND NOT ANDROID) - find_library(LIBRT rt) - if(LIBRT) - set (LIBRARIES ${LIBRARIES} rt) - endif() -endif() - -if(WIN32) - set (LIBRARIES ${LIBRARIES} ws2_32) -endif() - -if(WITH_SRV) - # Simple detect c-ares - find_path(ARES_HEADER ares.h) - if(ARES_HEADER) - add_definitions("-DWITH_SRV") - set (LIBRARIES ${LIBRARIES} cares) - else() - message(WARNING "c-ares library not found.") - endif() -endif() - -if(WITH_WEBSOCKETS AND WITH_WEBSOCKETS_BUILTIN) - add_definitions("-DWITH_WEBSOCKETS=WS_IS_BUILTIN") - set(C_SRC ${C_SRC} - ../deps/picohttpparser/picohttpparser.c - http_client.c http_client.h - net_ws.c - ) -endif() - -add_library(libmosquitto SHARED - ${C_SRC} -) - -if(WITH_WEBSOCKETS AND WITH_WEBSOCKETS_BUILTIN) - target_include_directories(libmosquitto PRIVATE - "${mosquitto_SOURCE_DIR}/deps/picohttpparser") -endif() - -target_include_directories(libmosquitto - PUBLIC - "${mosquitto_SOURCE_DIR}/include" - "${mosquitto_SOURCE_DIR}/lib" - PRIVATE - "${mosquitto_SOURCE_DIR}" - "${mosquitto_SOURCE_DIR}/common" - "${mosquitto_SOURCE_DIR}/libcommon" -) - -if(WITH_BUNDLED_DEPS) - target_include_directories(libmosquitto PRIVATE - "${mosquitto_SOURCE_DIR}/deps" - ) -endif() - -if(WITH_THREADING) - if(WIN32) - target_link_libraries(libmosquitto PRIVATE PThreads4W::PThreads4W) - else() - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads REQUIRED) - - target_link_libraries(libmosquitto PRIVATE Threads::Threads) - endif() -endif() - -target_link_libraries(libmosquitto - PUBLIC - libmosquitto_common -) -target_link_libraries(libmosquitto PRIVATE ${LIBRARIES}) - -set_target_properties(libmosquitto PROPERTIES - OUTPUT_NAME mosquitto - VERSION ${VERSION} - SOVERSION 1 - LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.version - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.version" - POSITION_INDEPENDENT_CODE 1 -) - -install(TARGETS libmosquitto - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" -) - -if(WITH_STATIC_LIBRARIES) - add_library(libmosquitto_static STATIC ${C_SRC}) - if(WITH_PIC) - set_target_properties(libmosquitto_static PROPERTIES - POSITION_INDEPENDENT_CODE 1 - ) - endif() - - target_link_libraries(libmosquitto_static PRIVATE ${LIBRARIES}) - - target_include_directories(libmosquitto_static PRIVATE - "${mosquitto_SOURCE_DIR}" - "${mosquitto_SOURCE_DIR}/include" - "${mosquitto_SOURCE_DIR}/lib" - ) - - set_target_properties(libmosquitto_static PROPERTIES - OUTPUT_NAME mosquitto_static - VERSION ${VERSION} - ) - - target_compile_definitions(libmosquitto_static PUBLIC "LIBMOSQUITTO_STATIC") - install(TARGETS libmosquitto_static - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - ) -endif() +option(WITH_LIB_CPP "Build C++ library?" ON) +if(WITH_LIB_CPP) + add_subdirectory(cpp) +endif() + +set(C_SRC + actions_publish.c + actions_subscribe.c + actions_unsubscribe.c + alias_mosq.c alias_mosq.h + callbacks.c + connect.c + handle_auth.c + handle_connack.c + handle_disconnect.c + handle_ping.c + handle_pubackcomp.c + handle_publish.c + handle_pubrec.c + handle_pubrel.c + handle_suback.c + handle_unsuback.c + helpers.c + http_client.c http_client.h + logging_mosq.c logging_mosq.h + loop.c + messages_mosq.c messages_mosq.h + mosquitto.c ../include/mosquitto.h + mosquitto_internal.h + ../include/mosquitto/mqtt_protocol.h + net_mosq_ocsp.c net_mosq.c net_mosq.h + net_ws.c + options.c + packet_datatypes.c + packet_mosq.c packet_mosq.h + property_mosq.c property_mosq.h + read_handle.c read_handle.h + send_connect.c + send_disconnect.c + send_mosq.c + send_publish.c + send_subscribe.c + send_unsubscribe.c + send_mosq.c send_mosq.h + socks_mosq.c + srv_mosq.c + thread_mosq.c + tls_mosq.c + util_mosq.c util_mosq.h + will_mosq.c will_mosq.h) + +set(LIBRARIES common-options) + +if(WITH_TLS) + set (LIBRARIES ${LIBRARIES} OpenSSL::SSL) +endif() + +if(UNIX AND NOT APPLE AND NOT ANDROID) + find_library(LIBRT rt) + if(LIBRT) + set (LIBRARIES ${LIBRARIES} rt) + endif() +endif() + +if(WIN32) + set (LIBRARIES ${LIBRARIES} ws2_32) +endif() + +if(WITH_SRV) + # Simple detect c-ares + find_path(ARES_HEADER ares.h) + if(ARES_HEADER) + add_definitions("-DWITH_SRV") + set (LIBRARIES ${LIBRARIES} cares) + else() + message(WARNING "c-ares library not found.") + endif() +endif() + +if(WITH_WEBSOCKETS AND WITH_WEBSOCKETS_BUILTIN) + add_definitions("-DWITH_WEBSOCKETS=WS_IS_BUILTIN") + set(C_SRC ${C_SRC} + ../deps/picohttpparser/picohttpparser.c + http_client.c http_client.h + net_ws.c + ) +endif() + +add_library(libmosquitto SHARED + ${C_SRC} +) + +if(WITH_WEBSOCKETS AND WITH_WEBSOCKETS_BUILTIN) + target_include_directories(libmosquitto PRIVATE + "${mosquitto_SOURCE_DIR}/deps/picohttpparser") +endif() + +target_include_directories(libmosquitto + PUBLIC + "${mosquitto_SOURCE_DIR}/include" + "${mosquitto_SOURCE_DIR}/lib" + PRIVATE + "${mosquitto_SOURCE_DIR}" + "${mosquitto_SOURCE_DIR}/common" + "${mosquitto_SOURCE_DIR}/libcommon" +) + +if(WITH_BUNDLED_DEPS) + target_include_directories(libmosquitto PRIVATE + "${mosquitto_SOURCE_DIR}/deps" + ) +endif() + +if(WITH_THREADING) + if(WIN32) + target_link_libraries(libmosquitto PRIVATE PThreads4W::PThreads4W) + else() + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) + + target_link_libraries(libmosquitto PRIVATE Threads::Threads) + endif() +endif() + +target_link_libraries(libmosquitto + PUBLIC + libmosquitto_common +) +target_link_libraries(libmosquitto PRIVATE ${LIBRARIES}) + +set_target_properties(libmosquitto PROPERTIES + OUTPUT_NAME mosquitto + VERSION ${VERSION} + SOVERSION 1 + LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.version + LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.version" + POSITION_INDEPENDENT_CODE 1 +) + +install(TARGETS libmosquitto + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) + +if(WITH_STATIC_LIBRARIES) + add_library(libmosquitto_static STATIC ${C_SRC}) + if(WITH_PIC) + set_target_properties(libmosquitto_static PROPERTIES + POSITION_INDEPENDENT_CODE 1 + ) + endif() + + target_link_libraries(libmosquitto_static PRIVATE ${LIBRARIES}) + + target_include_directories(libmosquitto_static PRIVATE + "${mosquitto_SOURCE_DIR}" + "${mosquitto_SOURCE_DIR}/include" + "${mosquitto_SOURCE_DIR}/lib" + ) + + set_target_properties(libmosquitto_static PROPERTIES + OUTPUT_NAME mosquitto_static + VERSION ${VERSION} + ) + + target_compile_definitions(libmosquitto_static PUBLIC "LIBMOSQUITTO_STATIC") + install(TARGETS libmosquitto_static + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ) +endif() diff --git a/libcommon/CMakeLists.txt b/libcommon/CMakeLists.txt index cea48408..13245b6e 100644 --- a/libcommon/CMakeLists.txt +++ b/libcommon/CMakeLists.txt @@ -1,59 +1,59 @@ -set(C_SRC - base64_common.c - file_common.c - memory_common.c - mqtt_common.c - property_common.c - random_common.c - strings_common.c - time_common.c - topic_common.c - utf8_common.c - - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_base64.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_file.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_memory.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_properties.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_random.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_string.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_time.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_topic.h" - "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_utf8.h" -) - -if(WIN32) - add_library(libmosquitto_common SHARED - ${C_SRC} - ) -else() - add_library(libmosquitto_common OBJECT - ${C_SRC} - ) -endif() - -target_include_directories(libmosquitto_common - PUBLIC - "${mosquitto_SOURCE_DIR}/" - "${mosquitto_SOURCE_DIR}/include" -) - -target_link_libraries(libmosquitto_common - PUBLIC - config-header -) - -if (WITH_TLS) - target_link_libraries(libmosquitto_common - PUBLIC - OpenSSL::SSL - ) -endif() - - -set_target_properties(libmosquitto_common PROPERTIES - OUTPUT_NAME mosquitto_common - VERSION ${VERSION} - SOVERSION 1 - POSITION_INDEPENDENT_CODE 1 -) +set(C_SRC + base64_common.c + file_common.c + memory_common.c + mqtt_common.c + property_common.c + random_common.c + strings_common.c + time_common.c + topic_common.c + utf8_common.c + + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_base64.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_file.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_memory.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_properties.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_random.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_string.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_time.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_topic.h" + "${mosquitto_SOURCE_DIR}/include/mosquitto/libcommon_utf8.h" +) + +if(WIN32) + add_library(libmosquitto_common SHARED + ${C_SRC} + ) +else() + add_library(libmosquitto_common OBJECT + ${C_SRC} + ) +endif() + +target_include_directories(libmosquitto_common + PUBLIC + "${mosquitto_SOURCE_DIR}/" + "${mosquitto_SOURCE_DIR}/include" +) + +target_link_libraries(libmosquitto_common + PUBLIC + config-header +) + +if (WITH_TLS) + target_link_libraries(libmosquitto_common + PUBLIC + OpenSSL::SSL + ) +endif() + + +set_target_properties(libmosquitto_common PROPERTIES + OUTPUT_NAME mosquitto_common + VERSION ${VERSION} + SOVERSION 1 + POSITION_INDEPENDENT_CODE 1 +) diff --git a/libcommon/memory_common.c b/libcommon/memory_common.c index d746c71e..4ab4659e 100644 --- a/libcommon/memory_common.c +++ b/libcommon/memory_common.c @@ -1,180 +1,180 @@ -/* -Copyright (c) 2009-2021 Roger Light - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 2.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - https://www.eclipse.org/legal/epl-2.0/ -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -Contributors: - Roger Light - initial implementation and documentation. -*/ - -#include "config.h" - -#include -#include - -#include "mosquitto.h" - -#if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) -# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) -# define REAL_WITH_MEMORY_TRACKING -# endif -#endif - -#ifdef REAL_WITH_MEMORY_TRACKING -# if defined(__APPLE__) -# include -# define malloc_usable_size malloc_size -# elif defined(__FreeBSD__) -# include -# else -# include -# endif -#endif - -static unsigned long memcount = 0; -static unsigned long max_memcount = 0; - -static size_t mem_limit = 0; -void mosquitto_memory_set_limit(size_t lim) -{ - mem_limit = lim; -} - -unsigned long mosquitto_memory_used(void) -{ - return memcount; -} - -unsigned long mosquitto_max_memory_used(void) -{ - return max_memcount; -} - - -#ifdef WITH_REAL_MEMORY_TRACKING - -BROKER_EXPORT void *mosquitto_malloc(size_t size) -{ - void *mem; - - if(mem_limit && memcount + size > mem_limit){ - return NULL; - } - mem = malloc(size); - if(mem){ - memcount += malloc_usable_size(mem); - if(memcount > max_memcount){ - max_memcount = memcount; - } - } - - return mem; -} - -BROKER_EXPORT void *mosquitto_realloc(void *ptr, size_t size) -{ - void *mem; - size_t free_size = ptr != NULL ? malloc_usable_size(ptr) : 0; - - /* Avoid counter underflow due to mismatched memory allocation function usage */ - if(free_size > memcount){ - free_size = memcount; - } - if(mem_limit && memcount - free_size + size > mem_limit){ - return NULL; - } - mem = realloc(ptr, size); - if(mem){ - memcount -= free_size; - memcount += malloc_usable_size(mem); - if(memcount > max_memcount){ - max_memcount = memcount; - } - }else if(size == 0){ - memcount -= free_size; - } - - return mem; -} - -BROKER_EXPORT void mosquitto_free(void *mem) -{ - if(!mem){ - return; - } - size_t free_size = malloc_usable_size(mem); - free(mem); - - /* Avoid counter underflow due to mismatched memory function allocation usage */ - if(free_size > memcount){ - free_size = memcount; - } - memcount -= free_size; -} - -#else /* #ifdef WITH_REAL_MEMORY_TRACKING */ - -BROKER_EXPORT void *mosquitto_malloc(size_t size) -{ - return malloc(size); -} - -BROKER_EXPORT void *mosquitto_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - -BROKER_EXPORT void mosquitto_free(void *mem) -{ - free(mem); -} - -#endif /* #ifdef WITH_REAL_MEMORY_TRACKING */ - -BROKER_EXPORT void *mosquitto_calloc(size_t nmemb, size_t size) -{ - void *mem; - const size_t alloc_size = nmemb * size; - mem = mosquitto_malloc(alloc_size); - if(mem){ - memset(mem, 0, alloc_size); - } - return mem; -} - -BROKER_EXPORT char *mosquitto_strdup(const char *s) -{ - char *str; - size_t size = strlen(s) + 1; - - str = mosquitto_malloc(size); - if(str){ - memcpy(str, s, size); - } - return str; -} - -BROKER_EXPORT char *mosquitto_strndup(const char *s, size_t n) -{ - char *str; - size_t size = strnlen(s, n); - - if(size > n){ - size = n; - } - str = mosquitto_malloc(size + 1); - if(str){ - memcpy(str, s, size); - } - str[size] = 0; - return str; -} +/* +Copyright (c) 2009-2021 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#include "config.h" + +#include +#include + +#include "mosquitto.h" + +#if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) +# define REAL_WITH_MEMORY_TRACKING +# endif +#endif + +#ifdef REAL_WITH_MEMORY_TRACKING +# if defined(__APPLE__) +# include +# define malloc_usable_size malloc_size +# elif defined(__FreeBSD__) +# include +# else +# include +# endif +#endif + +static unsigned long memcount = 0; +static unsigned long max_memcount = 0; + +static size_t mem_limit = 0; +void mosquitto_memory_set_limit(size_t lim) +{ + mem_limit = lim; +} + +unsigned long mosquitto_memory_used(void) +{ + return memcount; +} + +unsigned long mosquitto_max_memory_used(void) +{ + return max_memcount; +} + + +#ifdef WITH_REAL_MEMORY_TRACKING + +BROKER_EXPORT void *mosquitto_malloc(size_t size) +{ + void *mem; + + if(mem_limit && memcount + size > mem_limit){ + return NULL; + } + mem = malloc(size); + if(mem){ + memcount += malloc_usable_size(mem); + if(memcount > max_memcount){ + max_memcount = memcount; + } + } + + return mem; +} + +BROKER_EXPORT void *mosquitto_realloc(void *ptr, size_t size) +{ + void *mem; + size_t free_size = ptr != NULL ? malloc_usable_size(ptr) : 0; + + /* Avoid counter underflow due to mismatched memory allocation function usage */ + if(free_size > memcount){ + free_size = memcount; + } + if(mem_limit && memcount - free_size + size > mem_limit){ + return NULL; + } + mem = realloc(ptr, size); + if(mem){ + memcount -= free_size; + memcount += malloc_usable_size(mem); + if(memcount > max_memcount){ + max_memcount = memcount; + } + }else if(size == 0){ + memcount -= free_size; + } + + return mem; +} + +BROKER_EXPORT void mosquitto_free(void *mem) +{ + if(!mem){ + return; + } + size_t free_size = malloc_usable_size(mem); + free(mem); + + /* Avoid counter underflow due to mismatched memory function allocation usage */ + if(free_size > memcount){ + free_size = memcount; + } + memcount -= free_size; +} + +#else /* #ifdef WITH_REAL_MEMORY_TRACKING */ + +BROKER_EXPORT void *mosquitto_malloc(size_t size) +{ + return malloc(size); +} + +BROKER_EXPORT void *mosquitto_realloc(void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +BROKER_EXPORT void mosquitto_free(void *mem) +{ + free(mem); +} + +#endif /* #ifdef WITH_REAL_MEMORY_TRACKING */ + +BROKER_EXPORT void *mosquitto_calloc(size_t nmemb, size_t size) +{ + void *mem; + const size_t alloc_size = nmemb * size; + mem = mosquitto_malloc(alloc_size); + if(mem){ + memset(mem, 0, alloc_size); + } + return mem; +} + +BROKER_EXPORT char *mosquitto_strdup(const char *s) +{ + char *str; + size_t size = strlen(s) + 1; + + str = mosquitto_malloc(size); + if(str){ + memcpy(str, s, size); + } + return str; +} + +BROKER_EXPORT char *mosquitto_strndup(const char *s, size_t n) +{ + char *str; + size_t size = strnlen(s, n); + + if(size > n){ + size = n; + } + str = mosquitto_malloc(size + 1); + if(str){ + memcpy(str, s, size); + } + str[size] = 0; + return str; +} diff --git a/libcommon/mqtt_common.c b/libcommon/mqtt_common.c index 1afe4b45..8864c440 100644 --- a/libcommon/mqtt_common.c +++ b/libcommon/mqtt_common.c @@ -1,39 +1,39 @@ -/* -Copyright (c) 2009-2021 Roger Light - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 2.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - https://www.eclipse.org/legal/epl-2.0/ -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -Contributors: - Roger Light - initial implementation and documentation. -*/ - -#include "config.h" - -#include - -#include "mosquitto.h" - - -unsigned int mosquitto_varint_bytes(uint32_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; - } -} +/* +Copyright (c) 2009-2021 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#include "config.h" + +#include + +#include "mosquitto.h" + + +unsigned int mosquitto_varint_bytes(uint32_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/libcommon/property_common.c b/libcommon/property_common.c index 5cca3fa2..75859006 100644 --- a/libcommon/property_common.c +++ b/libcommon/property_common.c @@ -1,1138 +1,1138 @@ -/* -Copyright (c) 2018-2021 Roger Light - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License 2.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - https://www.eclipse.org/legal/epl-2.0/ -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -Contributors: - Roger Light - initial implementation and documentation. -*/ - -#include "config.h" - -#include -#include -#include - -#ifndef WIN32 -# include -#endif - -#include "mosquitto.h" -#include "property_common.h" - - -void mosquitto_property_free(mosquitto_property **property) -{ - if(!property || !(*property)) return; - - switch((*property)->property_type){ - case MQTT_PROP_TYPE_STRING: - mosquitto_FREE((*property)->value.s.v); - break; - - case MQTT_PROP_TYPE_BINARY: - mosquitto_FREE((*property)->value.bin.v); - break; - - case MQTT_PROP_TYPE_STRING_PAIR: - mosquitto_FREE((*property)->name.v); - mosquitto_FREE((*property)->value.s.v); - break; - - case MQTT_PROP_TYPE_BYTE: - case MQTT_PROP_TYPE_INT16: - case MQTT_PROP_TYPE_INT32: - case MQTT_PROP_TYPE_VARINT: - /* Nothing to free */ - break; - } - - free(*property); - *property = NULL; -} - - -BROKER_EXPORT void mosquitto_property_free_all(mosquitto_property **property) -{ - mosquitto_property *p, *next; - - if(!property) return; - - p = *property; - while(p){ - next = p->next; - mosquitto_property_free(&p); - p = next; - } - *property = NULL; -} - - -unsigned int mosquitto_property_get_length(const mosquitto_property *property) -{ - if(!property) return 0; - - switch(property->property_type){ - case MQTT_PROP_TYPE_BYTE: - return 2; /* 1 (identifier) + 1 byte */ - - case MQTT_PROP_TYPE_INT16: - return 3; /* 1 (identifier) + 2 bytes */ - - case MQTT_PROP_TYPE_INT32: - return 5; /* 1 (identifier) + 4 bytes */ - - case MQTT_PROP_TYPE_VARINT: - 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; - } - - case MQTT_PROP_TYPE_BINARY: - return 3U + property->value.bin.len; /* 1 + 2 bytes (len) + X bytes (payload) */ - - case MQTT_PROP_TYPE_STRING: - return 3U + property->value.s.len; /* 1 + 2 bytes (len) + X bytes (string) */ - - case MQTT_PROP_TYPE_STRING_PAIR: - return 5U + property->value.s.len + property->name.len; /* 1 + 2*(2 bytes (len) + X bytes (string))*/ - - default: - return 0; - } - return 0; -} - - -unsigned int mosquitto_property_get_length_all(const mosquitto_property *property) -{ - const mosquitto_property *p; - unsigned int len = 0; - - p = property; - while(p){ - len += mosquitto_property_get_length(p); - p = p->next; - } - return len; -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT const char *mosquitto_property_identifier_to_string(int identifier) -{ - switch(identifier){ - case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: - return "payload-format-indicator"; - case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: - return "message-expiry-interval"; - case MQTT_PROP_CONTENT_TYPE: - return "content-type"; - case MQTT_PROP_RESPONSE_TOPIC: - return "response-topic"; - case MQTT_PROP_CORRELATION_DATA: - return "correlation-data"; - case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: - return "subscription-identifier"; - case MQTT_PROP_SESSION_EXPIRY_INTERVAL: - return "session-expiry-interval"; - case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: - return "assigned-client-identifier"; - case MQTT_PROP_SERVER_KEEP_ALIVE: - return "server-keep-alive"; - case MQTT_PROP_AUTHENTICATION_METHOD: - return "authentication-method"; - case MQTT_PROP_AUTHENTICATION_DATA: - return "authentication-data"; - case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: - return "request-problem-information"; - case MQTT_PROP_WILL_DELAY_INTERVAL: - return "will-delay-interval"; - case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: - return "request-response-information"; - case MQTT_PROP_RESPONSE_INFORMATION: - return "response-information"; - case MQTT_PROP_SERVER_REFERENCE: - return "server-reference"; - case MQTT_PROP_REASON_STRING: - return "reason-string"; - case MQTT_PROP_RECEIVE_MAXIMUM: - return "receive-maximum"; - case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: - return "topic-alias-maximum"; - case MQTT_PROP_TOPIC_ALIAS: - return "topic-alias"; - case MQTT_PROP_MAXIMUM_QOS: - return "maximum-qos"; - case MQTT_PROP_RETAIN_AVAILABLE: - return "retain-available"; - case MQTT_PROP_USER_PROPERTY: - return "user-property"; - case MQTT_PROP_MAXIMUM_PACKET_SIZE: - return "maximum-packet-size"; - case MQTT_PROP_WILDCARD_SUB_AVAILABLE: - return "wildcard-subscription-available"; - case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: - return "subscription-identifier-available"; - case MQTT_PROP_SHARED_SUB_AVAILABLE: - return "shared-subscription-available"; - default: - return NULL; - } -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT 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; - prop->property_type = MQTT_PROP_TYPE_BYTE; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -BROKER_EXPORT 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; - prop->property_type = MQTT_PROP_TYPE_INT16; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -BROKER_EXPORT 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; - prop->property_type = MQTT_PROP_TYPE_INT32; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -BROKER_EXPORT 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; - prop->property_type = MQTT_PROP_TYPE_VARINT; - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -BROKER_EXPORT 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; - prop->property_type = MQTT_PROP_TYPE_BINARY; - - 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; -} - - -BROKER_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value) -{ - mosquitto_property *prop; - size_t slen = 0; - - if(!proplist) return MOSQ_ERR_INVAL; - if(value){ - slen = strlen(value); - if(mosquitto_validate_utf8(value, (int)slen)) 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; - prop->property_type = MQTT_PROP_TYPE_STRING; - if(value && slen > 0){ - prop->value.s.v = mosquitto_strdup(value); - if(!prop->value.s.v){ - mosquitto_FREE(prop); - return MOSQ_ERR_NOMEM; - } - prop->value.s.len = (uint16_t)slen; - } - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - - -BROKER_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value) -{ - mosquitto_property *prop; - size_t slen_name = 0, slen_value = 0; - - if(!proplist) return MOSQ_ERR_INVAL; - if(identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; - if(name){ - slen_name = strlen(name); - if(mosquitto_validate_utf8(name, (int)slen_name)) return MOSQ_ERR_MALFORMED_UTF8; - } - if(value){ - if(mosquitto_validate_utf8(value, (int)slen_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; - prop->property_type = MQTT_PROP_TYPE_STRING_PAIR; - - if(name){ - prop->name.v = mosquitto_strdup(name); - if(!prop->name.v){ - mosquitto_FREE(prop); - return MOSQ_ERR_NOMEM; - } - prop->name.len = (uint16_t)strlen(name); - } - - if(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 = (uint16_t)strlen(value); - } - - property__add(proplist, prop); - return MOSQ_ERR_SUCCESS; -} - -BROKER_EXPORT 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_PAYLOAD_FORMAT_INDICATOR - || 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 */ - if(p->identifier != MQTT_PROP_USER_PROPERTY){ - tail = p->next; - while(tail){ - if(p->identifier == tail->identifier){ - return MOSQ_ERR_DUPLICATE_PROPERTY; - } - tail = tail->next; - } - } - - p = p->next; - } - - return MOSQ_ERR_SUCCESS; -} - -static 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; -} - - -BROKER_EXPORT int mosquitto_property_identifier(const mosquitto_property *property) -{ - if(property == NULL) return 0; - - return property->identifier; -} - - -BROKER_EXPORT int mosquitto_property_type(const mosquitto_property *property) -{ - if(property == NULL) return 0; - - return property->property_type; -} - - -BROKER_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist) -{ - if(proplist == NULL) return NULL; - - return proplist->next; -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT 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; -} - - -BROKER_EXPORT 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; - - if(value) *value = 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; - if(p->value.bin.len){ - *value = calloc(1, *len + 1U); - if(!(*value)) return NULL; - - memcpy(*value, p->value.bin.v, *len); - }else{ - *value = NULL; - } - } - - return p; -} - - -BROKER_EXPORT 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){ - if(p->value.s.len){ - *value = calloc(1, (size_t)p->value.s.len+1); - if(!(*value)) return NULL; - - memcpy(*value, p->value.s.v, p->value.s.len); - }else{ - *value = NULL; - } - } - - return p; -} - - -BROKER_EXPORT 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; - - if(name) *name = NULL; - if(value) *value = NULL; - - p = property__get_property(proplist, identifier, skip_first); - if(!p) return NULL; - if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL; - - if(name){ - if(p->name.len){ - *name = calloc(1, (size_t)p->name.len+1); - if(!(*name)) return NULL; - memcpy(*name, p->name.v, p->name.len); - }else{ - *name = NULL; - } - } - - if(value){ - if(p->value.s.len){ - *value = calloc(1, (size_t)p->value.s.len+1); - if(!(*value)){ - if(name){ - free(*name); - *name = NULL; - } - return NULL; - } - memcpy(*value, p->value.s.v, p->value.s.len); - }else{ - *value = NULL; - } - } - - return p; -} - - -BROKER_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property) -{ - mosquitto_property *item, *item_prev = NULL; - - if(proplist == NULL || property == NULL){ - return MOSQ_ERR_INVAL; - } - - item = *proplist; - while(item){ - if(item == property){ - if(item_prev == NULL){ - *proplist = (*proplist)->next; - }else{ - item_prev->next = item->next; - } - item->next = NULL; - return MOSQ_ERR_SUCCESS; - } - item_prev = item; - item = item->next; - } - - return MOSQ_ERR_NOT_FOUND; -} - - -BROKER_EXPORT 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->client_generated = src->client_generated; - pnew->identifier = src->identifier; - pnew->property_type = src->property_type; - switch(pnew->property_type){ - case MQTT_PROP_TYPE_BYTE: - pnew->value.i8 = src->value.i8; - break; - - case MQTT_PROP_TYPE_INT16: - pnew->value.i16 = src->value.i16; - break; - - case MQTT_PROP_TYPE_INT32: - pnew->value.i32 = src->value.i32; - break; - - case MQTT_PROP_TYPE_VARINT: - pnew->value.varint = src->value.varint; - break; - - case MQTT_PROP_TYPE_STRING: - pnew->value.s.len = src->value.s.len; - pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1); - if(!pnew->value.s.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - break; - - case MQTT_PROP_TYPE_BINARY: - pnew->value.bin.len = src->value.bin.len; - if(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_TYPE_STRING_PAIR: - pnew->value.s.len = src->value.s.len; - pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1); - if(!pnew->value.s.v){ - mosquitto_property_free_all(dest); - return MOSQ_ERR_NOMEM; - } - - pnew->name.len = src->name.len; - pnew->name.v = src->name.v ? strdup(src->name.v) : (char*)calloc(1,1); - 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 = mosquitto_property_next(src); - } - - return MOSQ_ERR_SUCCESS; -} - - -uint8_t mosquitto_property_byte_value(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_BYTE){ - return property->value.i8; - }else{ - return 0; - } -} - - -uint16_t mosquitto_property_int16_value(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_INT16){ - return property->value.i16; - }else{ - return 0; - } -} - - -uint32_t mosquitto_property_int32_value(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_INT32){ - return property->value.i32; - }else{ - return 0; - } -} - - -uint32_t mosquitto_property_varint_value(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_VARINT){ - return property->value.varint; - }else{ - return 0; - } -} - - -const void *mosquitto_property_binary_value(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ - return property->value.bin.v; - }else{ - return NULL; - } -} - - -uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ - return property->value.bin.len; - }else{ - return 0; - } -} - - -const char *mosquitto_property_string_value(const mosquitto_property *property) -{ - if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ - return property->value.s.v; - }else{ - return NULL; - } -} - - -uint16_t mosquitto_property_string_value_length(const mosquitto_property *property) -{ - if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ - return property->value.s.len; - }else{ - return 0; - } -} - - -const char *mosquitto_property_string_name(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ - return property->name.v; - }else{ - return NULL; - } -} - - -uint16_t mosquitto_property_string_name_length(const mosquitto_property *property) -{ - if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ - return property->name.len; - }else{ - return 0; - } -} - -/* Return the number of bytes we need to add on to the remaining length when - * encoding these properties. */ -unsigned int mosquitto_property_get_remaining_length(const mosquitto_property *props) -{ - unsigned int proplen, varbytes; - - proplen = mosquitto_property_get_length_all(props); - varbytes = mosquitto_varint_bytes(proplen); - return proplen + varbytes; -} - - +/* +Copyright (c) 2018-2021 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#include "config.h" + +#include +#include +#include + +#ifndef WIN32 +# include +#endif + +#include "mosquitto.h" +#include "property_common.h" + + +void mosquitto_property_free(mosquitto_property **property) +{ + if(!property || !(*property)) return; + + switch((*property)->property_type){ + case MQTT_PROP_TYPE_STRING: + mosquitto_FREE((*property)->value.s.v); + break; + + case MQTT_PROP_TYPE_BINARY: + mosquitto_FREE((*property)->value.bin.v); + break; + + case MQTT_PROP_TYPE_STRING_PAIR: + mosquitto_FREE((*property)->name.v); + mosquitto_FREE((*property)->value.s.v); + break; + + case MQTT_PROP_TYPE_BYTE: + case MQTT_PROP_TYPE_INT16: + case MQTT_PROP_TYPE_INT32: + case MQTT_PROP_TYPE_VARINT: + /* Nothing to free */ + break; + } + + free(*property); + *property = NULL; +} + + +BROKER_EXPORT void mosquitto_property_free_all(mosquitto_property **property) +{ + mosquitto_property *p, *next; + + if(!property) return; + + p = *property; + while(p){ + next = p->next; + mosquitto_property_free(&p); + p = next; + } + *property = NULL; +} + + +unsigned int mosquitto_property_get_length(const mosquitto_property *property) +{ + if(!property) return 0; + + switch(property->property_type){ + case MQTT_PROP_TYPE_BYTE: + return 2; /* 1 (identifier) + 1 byte */ + + case MQTT_PROP_TYPE_INT16: + return 3; /* 1 (identifier) + 2 bytes */ + + case MQTT_PROP_TYPE_INT32: + return 5; /* 1 (identifier) + 4 bytes */ + + case MQTT_PROP_TYPE_VARINT: + 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; + } + + case MQTT_PROP_TYPE_BINARY: + return 3U + property->value.bin.len; /* 1 + 2 bytes (len) + X bytes (payload) */ + + case MQTT_PROP_TYPE_STRING: + return 3U + property->value.s.len; /* 1 + 2 bytes (len) + X bytes (string) */ + + case MQTT_PROP_TYPE_STRING_PAIR: + return 5U + property->value.s.len + property->name.len; /* 1 + 2*(2 bytes (len) + X bytes (string))*/ + + default: + return 0; + } + return 0; +} + + +unsigned int mosquitto_property_get_length_all(const mosquitto_property *property) +{ + const mosquitto_property *p; + unsigned int len = 0; + + p = property; + while(p){ + len += mosquitto_property_get_length(p); + p = p->next; + } + return len; +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT const char *mosquitto_property_identifier_to_string(int identifier) +{ + switch(identifier){ + case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: + return "payload-format-indicator"; + case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: + return "message-expiry-interval"; + case MQTT_PROP_CONTENT_TYPE: + return "content-type"; + case MQTT_PROP_RESPONSE_TOPIC: + return "response-topic"; + case MQTT_PROP_CORRELATION_DATA: + return "correlation-data"; + case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: + return "subscription-identifier"; + case MQTT_PROP_SESSION_EXPIRY_INTERVAL: + return "session-expiry-interval"; + case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: + return "assigned-client-identifier"; + case MQTT_PROP_SERVER_KEEP_ALIVE: + return "server-keep-alive"; + case MQTT_PROP_AUTHENTICATION_METHOD: + return "authentication-method"; + case MQTT_PROP_AUTHENTICATION_DATA: + return "authentication-data"; + case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: + return "request-problem-information"; + case MQTT_PROP_WILL_DELAY_INTERVAL: + return "will-delay-interval"; + case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: + return "request-response-information"; + case MQTT_PROP_RESPONSE_INFORMATION: + return "response-information"; + case MQTT_PROP_SERVER_REFERENCE: + return "server-reference"; + case MQTT_PROP_REASON_STRING: + return "reason-string"; + case MQTT_PROP_RECEIVE_MAXIMUM: + return "receive-maximum"; + case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: + return "topic-alias-maximum"; + case MQTT_PROP_TOPIC_ALIAS: + return "topic-alias"; + case MQTT_PROP_MAXIMUM_QOS: + return "maximum-qos"; + case MQTT_PROP_RETAIN_AVAILABLE: + return "retain-available"; + case MQTT_PROP_USER_PROPERTY: + return "user-property"; + case MQTT_PROP_MAXIMUM_PACKET_SIZE: + return "maximum-packet-size"; + case MQTT_PROP_WILDCARD_SUB_AVAILABLE: + return "wildcard-subscription-available"; + case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: + return "subscription-identifier-available"; + case MQTT_PROP_SHARED_SUB_AVAILABLE: + return "shared-subscription-available"; + default: + return NULL; + } +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT 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; + prop->property_type = MQTT_PROP_TYPE_BYTE; + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + + +BROKER_EXPORT 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; + prop->property_type = MQTT_PROP_TYPE_INT16; + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + + +BROKER_EXPORT 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; + prop->property_type = MQTT_PROP_TYPE_INT32; + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + + +BROKER_EXPORT 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; + prop->property_type = MQTT_PROP_TYPE_VARINT; + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + + +BROKER_EXPORT 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; + prop->property_type = MQTT_PROP_TYPE_BINARY; + + 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; +} + + +BROKER_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value) +{ + mosquitto_property *prop; + size_t slen = 0; + + if(!proplist) return MOSQ_ERR_INVAL; + if(value){ + slen = strlen(value); + if(mosquitto_validate_utf8(value, (int)slen)) 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; + prop->property_type = MQTT_PROP_TYPE_STRING; + if(value && slen > 0){ + prop->value.s.v = mosquitto_strdup(value); + if(!prop->value.s.v){ + mosquitto_FREE(prop); + return MOSQ_ERR_NOMEM; + } + prop->value.s.len = (uint16_t)slen; + } + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + + +BROKER_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value) +{ + mosquitto_property *prop; + size_t slen_name = 0, slen_value = 0; + + if(!proplist) return MOSQ_ERR_INVAL; + if(identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; + if(name){ + slen_name = strlen(name); + if(mosquitto_validate_utf8(name, (int)slen_name)) return MOSQ_ERR_MALFORMED_UTF8; + } + if(value){ + if(mosquitto_validate_utf8(value, (int)slen_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; + prop->property_type = MQTT_PROP_TYPE_STRING_PAIR; + + if(name){ + prop->name.v = mosquitto_strdup(name); + if(!prop->name.v){ + mosquitto_FREE(prop); + return MOSQ_ERR_NOMEM; + } + prop->name.len = (uint16_t)strlen(name); + } + + if(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 = (uint16_t)strlen(value); + } + + property__add(proplist, prop); + return MOSQ_ERR_SUCCESS; +} + +BROKER_EXPORT 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_PAYLOAD_FORMAT_INDICATOR + || 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 */ + if(p->identifier != MQTT_PROP_USER_PROPERTY){ + tail = p->next; + while(tail){ + if(p->identifier == tail->identifier){ + return MOSQ_ERR_DUPLICATE_PROPERTY; + } + tail = tail->next; + } + } + + p = p->next; + } + + return MOSQ_ERR_SUCCESS; +} + +static 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; +} + + +BROKER_EXPORT int mosquitto_property_identifier(const mosquitto_property *property) +{ + if(property == NULL) return 0; + + return property->identifier; +} + + +BROKER_EXPORT int mosquitto_property_type(const mosquitto_property *property) +{ + if(property == NULL) return 0; + + return property->property_type; +} + + +BROKER_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist) +{ + if(proplist == NULL) return NULL; + + return proplist->next; +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT 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; +} + + +BROKER_EXPORT 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; + + if(value) *value = 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; + if(p->value.bin.len){ + *value = calloc(1, *len + 1U); + if(!(*value)) return NULL; + + memcpy(*value, p->value.bin.v, *len); + }else{ + *value = NULL; + } + } + + return p; +} + + +BROKER_EXPORT 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){ + if(p->value.s.len){ + *value = calloc(1, (size_t)p->value.s.len+1); + if(!(*value)) return NULL; + + memcpy(*value, p->value.s.v, p->value.s.len); + }else{ + *value = NULL; + } + } + + return p; +} + + +BROKER_EXPORT 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; + + if(name) *name = NULL; + if(value) *value = NULL; + + p = property__get_property(proplist, identifier, skip_first); + if(!p) return NULL; + if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL; + + if(name){ + if(p->name.len){ + *name = calloc(1, (size_t)p->name.len+1); + if(!(*name)) return NULL; + memcpy(*name, p->name.v, p->name.len); + }else{ + *name = NULL; + } + } + + if(value){ + if(p->value.s.len){ + *value = calloc(1, (size_t)p->value.s.len+1); + if(!(*value)){ + if(name){ + free(*name); + *name = NULL; + } + return NULL; + } + memcpy(*value, p->value.s.v, p->value.s.len); + }else{ + *value = NULL; + } + } + + return p; +} + + +BROKER_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property) +{ + mosquitto_property *item, *item_prev = NULL; + + if(proplist == NULL || property == NULL){ + return MOSQ_ERR_INVAL; + } + + item = *proplist; + while(item){ + if(item == property){ + if(item_prev == NULL){ + *proplist = (*proplist)->next; + }else{ + item_prev->next = item->next; + } + item->next = NULL; + return MOSQ_ERR_SUCCESS; + } + item_prev = item; + item = item->next; + } + + return MOSQ_ERR_NOT_FOUND; +} + + +BROKER_EXPORT 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->client_generated = src->client_generated; + pnew->identifier = src->identifier; + pnew->property_type = src->property_type; + switch(pnew->property_type){ + case MQTT_PROP_TYPE_BYTE: + pnew->value.i8 = src->value.i8; + break; + + case MQTT_PROP_TYPE_INT16: + pnew->value.i16 = src->value.i16; + break; + + case MQTT_PROP_TYPE_INT32: + pnew->value.i32 = src->value.i32; + break; + + case MQTT_PROP_TYPE_VARINT: + pnew->value.varint = src->value.varint; + break; + + case MQTT_PROP_TYPE_STRING: + pnew->value.s.len = src->value.s.len; + pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1); + if(!pnew->value.s.v){ + mosquitto_property_free_all(dest); + return MOSQ_ERR_NOMEM; + } + break; + + case MQTT_PROP_TYPE_BINARY: + pnew->value.bin.len = src->value.bin.len; + if(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_TYPE_STRING_PAIR: + pnew->value.s.len = src->value.s.len; + pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1); + if(!pnew->value.s.v){ + mosquitto_property_free_all(dest); + return MOSQ_ERR_NOMEM; + } + + pnew->name.len = src->name.len; + pnew->name.v = src->name.v ? strdup(src->name.v) : (char*)calloc(1,1); + 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 = mosquitto_property_next(src); + } + + return MOSQ_ERR_SUCCESS; +} + + +uint8_t mosquitto_property_byte_value(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_BYTE){ + return property->value.i8; + }else{ + return 0; + } +} + + +uint16_t mosquitto_property_int16_value(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_INT16){ + return property->value.i16; + }else{ + return 0; + } +} + + +uint32_t mosquitto_property_int32_value(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_INT32){ + return property->value.i32; + }else{ + return 0; + } +} + + +uint32_t mosquitto_property_varint_value(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_VARINT){ + return property->value.varint; + }else{ + return 0; + } +} + + +const void *mosquitto_property_binary_value(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ + return property->value.bin.v; + }else{ + return NULL; + } +} + + +uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ + return property->value.bin.len; + }else{ + return 0; + } +} + + +const char *mosquitto_property_string_value(const mosquitto_property *property) +{ + if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ + return property->value.s.v; + }else{ + return NULL; + } +} + + +uint16_t mosquitto_property_string_value_length(const mosquitto_property *property) +{ + if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ + return property->value.s.len; + }else{ + return 0; + } +} + + +const char *mosquitto_property_string_name(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ + return property->name.v; + }else{ + return NULL; + } +} + + +uint16_t mosquitto_property_string_name_length(const mosquitto_property *property) +{ + if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ + return property->name.len; + }else{ + return 0; + } +} + +/* Return the number of bytes we need to add on to the remaining length when + * encoding these properties. */ +unsigned int mosquitto_property_get_remaining_length(const mosquitto_property *props) +{ + unsigned int proplen, varbytes; + + proplen = mosquitto_property_get_length_all(props); + varbytes = mosquitto_varint_bytes(proplen); + return proplen + varbytes; +} + +