diff --git a/lib/linker.version b/lib/linker.version index 490b4a23..06f6e40a 100644 --- a/lib/linker.version +++ b/lib/linker.version @@ -95,7 +95,10 @@ MOSQ_1.5 { MOSQ_1.6 { global: mosquitto_connect_bind_with_properties; + mosquitto_connect_v5_callback_set; + mosquitto_disconnect_v5_callback_set; mosquitto_disconnect_with_properties; + mosquitto_message_v5_callback_set; mosquitto_property_add_binary; mosquitto_property_add_byte; mosquitto_property_add_int16; @@ -103,20 +106,25 @@ MOSQ_1.6 { mosquitto_property_add_string; mosquitto_property_add_string_pair; mosquitto_property_add_varint; + mosquitto_property_get_property; + mosquitto_property_read_binary; + mosquitto_property_read_byte; + mosquitto_property_read_int16; + mosquitto_property_read_int32; + mosquitto_property_read_string; + mosquitto_property_read_string_pair; + mosquitto_property_read_varint; mosquitto_property_free_all; mosquitto_property_check_command; mosquitto_property_check_all; + mosquitto_publish_v5_callback_set; mosquitto_publish_with_properties; mosquitto_string_to_command; mosquitto_string_to_property_info; mosquitto_subscribe_multiple; + mosquitto_subscribe_v5_callback_set; mosquitto_subscribe_with_properties; + mosquitto_unsubscribe_v5_callback_set; mosquitto_unsubscribe_with_properties; mosquitto_will_set_with_properties; - mosquitto_connect_v5_callback_set; - mosquitto_disconnect_v5_callback_set; - mosquitto_publish_v5_callback_set; - mosquitto_message_v5_callback_set; - mosquitto_subscribe_v5_callback_set; - mosquitto_unsubscribe_v5_callback_set; } MOSQ_1.5; diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 0f586fb2..ec392a04 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -2412,6 +2412,152 @@ libmosq_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, */ libmosq_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value); +/* + * Function: mosquitto_property_get_property + * + * Retrieve a property matching an identifier, from a property list. This + * function can search for multiple entries of an identifier by using the + * returned value and skip_first. + * + * Parameters: + * proplist - mosquitto_property pointer, the list of properties + * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) + * skip_first - boolean that indicates whether the first item in the list + * should be ignored or not. + * + * Returns: + * A valid property pointer if the property is found + * NULL, if the property is not found, or proplist is NULL. + * + * Example: + * // proplist is obtained from a callback + * mosquitto_property *prop; + * prop = mosquitto_property_get_property(proplist, MQTT_PROP_USER_PROPERTY, false); + * while(prop){ + * mosquitto_property_read_string_pair(prop, &key, &value); + * printf("key: %s value: %s\n", key, value); + * + * prop = mosquitto_property_get_property(prop, MQTT_PROP_USER_PROPERTY, true); + * } + */ +libmosq_EXPORT const mosquitto_property *mosquitto_property_get_property(const mosquitto_property *proplist, int identifier, bool skip_first); + +/* + * Function: mosquitto_property_read_byte + * + * Read a byte property value from a property. + * + * Parameters: + * property - property to read + * value - pointer to integer, for the property to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a byte + */ +libmosq_EXPORT int mosquitto_property_read_byte(const mosquitto_property *property, uint8_t *value); + +/* + * Function: mosquitto_property_read_int16 + * + * Read an int16 property value from a property. + * + * Parameters: + * property - property to read + * value - pointer to integer, for the property to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a uint16 + */ +libmosq_EXPORT int mosquitto_property_read_int16(const mosquitto_property *property, uint16_t *value); + +/* + * Function: mosquitto_property_read_int32 + * + * Read an int32 property value from a property. + * + * Parameters: + * property - pointer to mosquitto_property pointer, the list of properties + * value - pointer to integer, for the property to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not an int32 + */ +libmosq_EXPORT int mosquitto_property_read_int32(const mosquitto_property *property, uint32_t *value); + +/* + * Function: mosquitto_property_read_varint + * + * Read a varint property value from a property. + * + * Parameters: + * property - property to read + * value - pointer to integer, for the property to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a varint + */ +libmosq_EXPORT int mosquitto_property_read_varint(const mosquitto_property *property, uint32_t *value); + +/* + * 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 + * value - pointer to void pointer, for the property data to be stored in + * len - int pointer to store the data length + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property, len, or value is NULL, or if property is not a binary type + * MOSQ_ERR_NOMEM - on out of memory + */ +libmosq_EXPORT int mosquitto_property_read_binary(const mosquitto_property *property, void **value, int *len); + +/* + * 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 + * value - pointer to char*, for the property data to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a string + * MOSQ_ERR_NOMEM - on out of memory + */ +libmosq_EXPORT int mosquitto_property_read_string(const mosquitto_property *property, char **value); + +/* + * 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 + * name - pointer to char* for the name property data to be stored in + * value - pointer to char* for the value property data to be stored in + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if property, name, or value is NULL, or if property is not a string pair + * MOSQ_ERR_NOMEM - on out of memory + */ +libmosq_EXPORT int mosquitto_property_read_string_pair(const mosquitto_property *property, char **name, char **value); + /* * Function: mosquitto_property_free_all * diff --git a/lib/property_mosq.c b/lib/property_mosq.c index 4dd5c22e..46ab2d8a 100644 --- a/lib/property_mosq.c +++ b/lib/property_mosq.c @@ -768,7 +768,6 @@ int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, if(value && strlen(value)){ prop->value.s.v = mosquitto__strdup(value); if(!prop->value.s.v){ - mosquitto__free(prop->name.v); mosquitto__free(prop); return MOSQ_ERR_NOMEM; } @@ -873,3 +872,151 @@ int mosquitto_property_check_all(int command, const mosquitto_property *properti return MOSQ_ERR_SUCCESS; } + +const mosquitto_property *mosquitto_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; +} + + +int mosquitto_property_read_byte(const mosquitto_property *property, uint8_t *value) +{ + if(!property || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR + && property->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION + && property->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION + && property->identifier != MQTT_PROP_MAXIMUM_QOS + && property->identifier != MQTT_PROP_RETAIN_AVAILABLE + && property->identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE + && property->identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE + && property->identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ + return MOSQ_ERR_INVAL; + } + + *value = property->value.i8; + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_int16(const mosquitto_property *property, uint16_t *value) +{ + if(!property || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_SERVER_KEEP_ALIVE + && property->identifier != MQTT_PROP_RECEIVE_MAXIMUM + && property->identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM + && property->identifier != MQTT_PROP_TOPIC_ALIAS){ + return MOSQ_ERR_INVAL; + } + + *value = property->value.i16; + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_int32(const mosquitto_property *property, uint32_t *value) +{ + if(!property || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL + && property->identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL + && property->identifier != MQTT_PROP_WILL_DELAY_INTERVAL + && property->identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){ + + return MOSQ_ERR_INVAL; + } + + *value = property->value.i32; + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_varint(const mosquitto_property *property, uint32_t *value) +{ + if(!property || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){ + return MOSQ_ERR_INVAL; + } + + *value = property->value.varint; + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_binary(const mosquitto_property *property, void **value, int *len) +{ + if(!property || !value || !len) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_CORRELATION_DATA + && property->identifier != MQTT_PROP_AUTHENTICATION_DATA){ + + return MOSQ_ERR_INVAL; + } + + *len = property->value.bin.len; + *value = malloc(*len); + if(!value) return MOSQ_ERR_NOMEM; + + memcpy(*value, property->value.bin.v, *len); + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_string(const mosquitto_property *property, char **value) +{ + if(!property || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_CONTENT_TYPE + && property->identifier != MQTT_PROP_RESPONSE_TOPIC + && property->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER + && property->identifier != MQTT_PROP_AUTHENTICATION_METHOD + && property->identifier != MQTT_PROP_RESPONSE_INFORMATION + && property->identifier != MQTT_PROP_SERVER_REFERENCE + && property->identifier != MQTT_PROP_REASON_STRING){ + + return MOSQ_ERR_INVAL; + } + + *value = calloc(1, property->value.s.len+1); + if(!value) return MOSQ_ERR_NOMEM; + + memcpy(*value, property->value.s.v, property->value.s.len); + + return MOSQ_ERR_SUCCESS; +} + + +int mosquitto_property_read_string_pair(const mosquitto_property *property, char **name, char **value) +{ + if(!property || !name || !value) return MOSQ_ERR_INVAL; + if(property->identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; + + *name = calloc(1, property->name.len+1); + if(!name) return MOSQ_ERR_NOMEM; + + *value = calloc(1, property->value.s.len+1); + if(!value){ + free(*name); + return MOSQ_ERR_NOMEM; + } + + memcpy(*name, property->name.v, property->name.len); + memcpy(*value, property->value.s.v, property->value.s.len); + + return MOSQ_ERR_SUCCESS; +}