Make user functions for reading properties easier to use.

pull/1072/head
Roger A. Light 7 years ago
parent 608b8d33e7
commit 4fe75b1af0

@ -39,15 +39,32 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
uint16_t local_mid; uint16_t local_mid;
int queue_status; int queue_status;
const mosquitto_property *p; const mosquitto_property *p;
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
bool have_topic_alias; bool have_topic_alias;
int rc; int rc;
if(!mosq || qos<0 || qos>2) return MOSQ_ERR_INVAL; if(!mosq || qos<0 || qos>2) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(properties){
if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_PUBLISH, outgoing_properties);
if(rc) return rc;
}
if(!topic || STREMPTY(topic)){ if(!topic || STREMPTY(topic)){
if(topic) topic = NULL; if(topic) topic = NULL;
if(mosq->protocol == mosq_p_mqtt5){ if(mosq->protocol == mosq_p_mqtt5){
p = properties; p = outgoing_properties;
have_topic_alias = false; have_topic_alias = false;
while(p){ while(p){
if(p->identifier == MQTT_PROP_TOPIC_ALIAS){ if(p->identifier == MQTT_PROP_TOPIC_ALIAS){
@ -69,10 +86,6 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
} }
} }
if(properties){
rc = mosquitto_property_check_all(CMD_PUBLISH, properties);
if(rc) return rc;
}
local_mid = mosquitto__mid_generate(mosq); local_mid = mosquitto__mid_generate(mosq);
if(mid){ if(mid){
@ -80,7 +93,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
} }
if(qos == 0){ if(qos == 0){
return send__publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false, properties); return send__publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false, outgoing_properties);
}else{ }else{
message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all)); message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all));
if(!message) return MOSQ_ERR_NOMEM; if(!message) return MOSQ_ERR_NOMEM;
@ -120,7 +133,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
message->state = mosq_ms_wait_for_pubrec; message->state = mosq_ms_wait_for_pubrec;
} }
pthread_mutex_unlock(&mosq->out_message_mutex); pthread_mutex_unlock(&mosq->out_message_mutex);
return send__publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup, properties); return send__publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup, outgoing_properties);
}else{ }else{
message->state = mosq_ms_invalid; message->state = mosq_ms_invalid;
pthread_mutex_unlock(&mosq->out_message_mutex); pthread_mutex_unlock(&mosq->out_message_mutex);
@ -137,34 +150,57 @@ int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int q
int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, int qos, const mosquitto_property *properties) int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, int qos, const mosquitto_property *properties)
{ {
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int rc; int rc;
if(!mosq) return MOSQ_ERR_INVAL; if(!mosq) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL;
if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8; if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8;
if(properties){ if(properties){
rc = mosquitto_property_check_all(CMD_SUBSCRIBE, properties); if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_SUBSCRIBE, outgoing_properties);
if(rc) return rc; if(rc) return rc;
} }
return send__subscribe(mosq, mid, 1, (char *const *const)&sub, qos, properties); return send__subscribe(mosq, mid, 1, (char *const *const)&sub, qos, outgoing_properties);
} }
int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, int qos, const mosquitto_property *properties) int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, int qos, const mosquitto_property *properties)
{ {
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int i; int i;
int rc; int rc;
if(!mosq || !sub_count || !sub) return MOSQ_ERR_INVAL; if(!mosq || !sub_count || !sub) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(qos < 0 || qos > 2) return MOSQ_ERR_INVAL; if(qos < 0 || qos > 2) return MOSQ_ERR_INVAL;
if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
if(mosq->protocol == mosq_p_mqtt5 && properties){ if(properties){
rc = mosquitto_property_check_all(CMD_SUBSCRIBE, properties); if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_SUBSCRIBE, outgoing_properties);
if(rc) return rc; if(rc) return rc;
} }
@ -184,18 +220,30 @@ int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub)
int mosquitto_unsubscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, const mosquitto_property *properties) int mosquitto_unsubscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, const mosquitto_property *properties)
{ {
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int rc; int rc;
if(!mosq) return MOSQ_ERR_INVAL; if(!mosq) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL;
if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8; if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8;
if(properties){ if(properties){
rc = mosquitto_property_check_all(CMD_PUBLISH, properties); if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_UNSUBSCRIBE, outgoing_properties);
if(rc) return rc; if(rc) return rc;
} }
return send__unsubscribe(mosq, mid, sub, properties);
return send__unsubscribe(mosq, mid, sub, outgoing_properties);
} }

@ -149,10 +149,26 @@ int mosquitto_reconnect(struct mosquitto *mosq)
static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mosquitto_property *properties) static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mosquitto_property *properties)
{ {
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int rc; int rc;
struct mosquitto__packet *packet; struct mosquitto__packet *packet;
if(!mosq) return MOSQ_ERR_INVAL; if(!mosq) return MOSQ_ERR_INVAL;
if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(properties){
if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_DISCONNECT, outgoing_properties);
if(rc) return rc;
}
pthread_mutex_lock(&mosq->state_mutex); pthread_mutex_lock(&mosq->state_mutex);
#ifdef WITH_SOCKS #ifdef WITH_SOCKS
@ -223,7 +239,7 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos
}else }else
#endif #endif
{ {
return send__connect(mosq, mosq->keepalive, mosq->clean_start, properties); return send__connect(mosq, mosq->keepalive, mosq->clean_start, outgoing_properties);
} }
} }
@ -235,11 +251,22 @@ int mosquitto_disconnect(struct mosquitto *mosq)
int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties) int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties)
{ {
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int rc; int rc;
if(!mosq) return MOSQ_ERR_INVAL; if(!mosq) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
if(properties){ if(properties){
rc = mosquitto_property_check_all(CMD_DISCONNECT, properties); if(properties->client_generated){
outgoing_properties = properties;
}else{
memcpy(&local_property, properties, sizeof(mosquitto_property));
local_property.client_generated = true;
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_DISCONNECT, outgoing_properties);
if(rc) return rc; if(rc) return rc;
} }
@ -248,7 +275,7 @@ int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosqu
pthread_mutex_unlock(&mosq->state_mutex); pthread_mutex_unlock(&mosq->state_mutex);
if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
return send__disconnect(mosq, reason_code, properties); return send__disconnect(mosq, reason_code, outgoing_properties);
} }

@ -34,7 +34,7 @@ int handle__connack(struct mosquitto *mosq)
uint8_t reason_code; uint8_t reason_code;
int rc; int rc;
mosquitto_property *properties = NULL; mosquitto_property *properties = NULL;
const mosquitto_property *prop; char *clientid = NULL;
assert(mosq); assert(mosq);
rc = packet__read_byte(&mosq->in_packet, &connect_flags); rc = packet__read_byte(&mosq->in_packet, &connect_flags);
@ -47,30 +47,21 @@ int handle__connack(struct mosquitto *mosq)
if(rc) return rc; if(rc) return rc;
} }
prop = mosquitto_property_get_property(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, false); mosquitto_property_read_string(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, &clientid, false);
if(prop){ if(clientid){
if(mosq->id){ if(mosq->id){
/* We've been sent a client identifier but already have one. This /* We've been sent a client identifier but already have one. This
* shouldn't happen. */ * shouldn't happen. */
free(clientid);
mosquitto_property_free_all(&properties); mosquitto_property_free_all(&properties);
return MOSQ_ERR_PROTOCOL; return MOSQ_ERR_PROTOCOL;
}else{ }else{
rc = mosquitto_property_read_string(prop, &mosq->id); mosq->id = clientid;
if(rc){ clientid = NULL;
mosquitto_property_free_all(&properties);
return rc;
}
} }
} }
prop = mosquitto_property_get_property(properties, MQTT_PROP_SERVER_KEEP_ALIVE, false); mosquitto_property_read_int16(properties, MQTT_PROP_SERVER_KEEP_ALIVE, &mosq->keepalive, false);
if(prop){
rc = mosquitto_property_read_int16(prop, &mosq->keepalive);
if(rc){
mosquitto_property_free_all(&properties);
return rc;
}
}
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code); log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code);
pthread_mutex_lock(&mosq->callback_mutex); pthread_mutex_lock(&mosq->callback_mutex);

@ -106,7 +106,6 @@ MOSQ_1.6 {
mosquitto_property_add_string; mosquitto_property_add_string;
mosquitto_property_add_string_pair; mosquitto_property_add_string_pair;
mosquitto_property_add_varint; mosquitto_property_add_varint;
mosquitto_property_get_property;
mosquitto_property_read_binary; mosquitto_property_read_binary;
mosquitto_property_read_byte; mosquitto_property_read_byte;
mosquitto_property_read_int16; mosquitto_property_read_int16;

@ -2428,17 +2428,26 @@ 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); libmosq_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value);
/* /*
* Function: mosquitto_property_get_property * 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.
* *
* Retrieve a property matching an identifier, from a property list. This * If the property is not found, *value will not be modified, so it is safe to
* function can search for multiple entries of an identifier by using the * pass a variable with a default value to be potentially overwritten:
* returned value and skip_first. *
* uint16_t keepalive = 60; // default value
* // Get value from property list, or keep default if not found.
* mosquitto_property_read_int16(proplist, MQTT_PROP_SERVER_KEEP_ALIVE, &keepalive, false);
* *
* Parameters: * Parameters:
* proplist - mosquitto_property pointer, the list of properties * proplist - mosquitto_property pointer, the list of properties or single property
* identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) * 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 * skip_first - boolean that indicates whether the first item in the list
* should be ignored or not. * should be ignored or not. Should usually be set to false.
* *
* Returns: * Returns:
* A valid property pointer if the property is found * A valid property pointer if the property is found
@ -2447,30 +2456,17 @@ libmosq_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **propl
* Example: * Example:
* // proplist is obtained from a callback * // proplist is obtained from a callback
* mosquitto_property *prop; * mosquitto_property *prop;
* prop = mosquitto_property_get_property(proplist, MQTT_PROP_USER_PROPERTY, false); * prop = mosquitto_property_read_byte(proplist, identifier, &value, false);
* while(prop){ * while(prop){
* mosquitto_property_read_string_pair(prop, &key, &value); * printf("value: %s\n", value);
* printf("key: %s value: %s\n", key, value); * prop = mosquitto_property_read_byte(prop, identifier, &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); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_byte(
const mosquitto_property *proplist,
/* int identifier,
* Function: mosquitto_property_read_byte uint8_t *value,
* bool skip_first);
* 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 * Function: mosquitto_property_read_int16
@ -2479,13 +2475,23 @@ libmosq_EXPORT int mosquitto_property_read_byte(const mosquitto_property *proper
* *
* Parameters: * Parameters:
* property - property to read * property - property to read
* value - pointer to integer, for the property to be stored in * 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: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a uint16 * NULL, if the property is not found, or proplist is NULL.
*
* Example:
* See <mosquitto_property_read_byte>
*/ */
libmosq_EXPORT int mosquitto_property_read_int16(const mosquitto_property *property, uint16_t *value); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int16(
const mosquitto_property *proplist,
int identifier,
uint16_t *value,
bool skip_first);
/* /*
* Function: mosquitto_property_read_int32 * Function: mosquitto_property_read_int32
@ -2494,13 +2500,23 @@ libmosq_EXPORT int mosquitto_property_read_int16(const mosquitto_property *prope
* *
* Parameters: * Parameters:
* property - pointer to mosquitto_property pointer, the list of properties * property - pointer to mosquitto_property pointer, the list of properties
* value - pointer to integer, for the property to be stored in * 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: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property or value is NULL, or if property is not an int32 * NULL, if the property is not found, or proplist is NULL.
*
* Example:
* See <mosquitto_property_read_byte>
*/ */
libmosq_EXPORT int mosquitto_property_read_int32(const mosquitto_property *property, uint32_t *value); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int32(
const mosquitto_property *proplist,
int identifier,
uint32_t *value,
bool skip_first);
/* /*
* Function: mosquitto_property_read_varint * Function: mosquitto_property_read_varint
@ -2509,13 +2525,23 @@ libmosq_EXPORT int mosquitto_property_read_int32(const mosquitto_property *prope
* *
* Parameters: * Parameters:
* property - property to read * property - property to read
* value - pointer to integer, for the property to be stored in * 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: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a varint * NULL, if the property is not found, or proplist is NULL.
*
* Example:
* See <mosquitto_property_read_byte>
*/ */
libmosq_EXPORT int mosquitto_property_read_varint(const mosquitto_property *property, uint32_t *value); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_varint(
const mosquitto_property *proplist,
int identifier,
uint32_t *value,
bool skip_first);
/* /*
* Function: mosquitto_property_read_binary * Function: mosquitto_property_read_binary
@ -2526,15 +2552,24 @@ libmosq_EXPORT int mosquitto_property_read_varint(const mosquitto_property *prop
* *
* Parameters: * Parameters:
* property - property to read * property - property to read
* value - pointer to void pointer, for the property data to be stored in * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
* len - int pointer to store the data length * 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: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property, len, or value is NULL, or if property is not a binary type * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
* MOSQ_ERR_NOMEM - on out of memory *
* Example:
* See <mosquitto_property_read_byte>
*/ */
libmosq_EXPORT int mosquitto_property_read_binary(const mosquitto_property *property, void **value, int *len); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_binary(
const mosquitto_property *proplist,
int identifier,
void **value,
int *len,
bool skip_first);
/* /*
* Function: mosquitto_property_read_string * Function: mosquitto_property_read_string
@ -2545,14 +2580,24 @@ libmosq_EXPORT int mosquitto_property_read_binary(const mosquitto_property *prop
* *
* Parameters: * Parameters:
* property - property to read * property - property to read
* value - pointer to char*, for the property data to be stored in * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
* value - pointer to char*, for the property data to be stored in, or NULL if
* the value is not required.
* skip_first - boolean that indicates whether the first item in the list
* should be ignored or not. Should usually be set to false.
* *
* Returns: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a string * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
* MOSQ_ERR_NOMEM - on out of memory *
* Example:
* See <mosquitto_property_read_byte>
*/ */
libmosq_EXPORT int mosquitto_property_read_string(const mosquitto_property *property, char **value); libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string(
const mosquitto_property *proplist,
int identifier,
char **value,
bool skip_first);
/* /*
* Function: mosquitto_property_read_string_pair * Function: mosquitto_property_read_string_pair
@ -2563,15 +2608,27 @@ libmosq_EXPORT int mosquitto_property_read_string(const mosquitto_property *prop
* *
* Parameters: * Parameters:
* property - property to read * property - property to read
* name - pointer to char* for the name property data to be stored in * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
* value - pointer to char* for the value property data to be stored in * name - pointer to char* for the name property data to be stored in, or NULL
* if the name is not required.
* value - pointer to char*, for the property data to be stored in, or NULL if
* the value is not required.
* skip_first - boolean that indicates whether the first item in the list
* should be ignored or not. Should usually be set to false.
* *
* Returns: * Returns:
* MOSQ_ERR_SUCCESS - on success * A valid property pointer if the property is found
* MOSQ_ERR_INVAL - if property, name, or value is NULL, or if property is not a string pair * NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
* MOSQ_ERR_NOMEM - on out of memory *
*/ * Example:
libmosq_EXPORT int mosquitto_property_read_string_pair(const mosquitto_property *property, char **name, char **value); * See <mosquitto_property_read_byte>
*/
libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string_pair(
const mosquitto_property *proplist,
int identifier,
char **name,
char **value,
bool skip_first);
/* /*
* Function: mosquitto_property_free_all * Function: mosquitto_property_free_all

@ -636,6 +636,7 @@ int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, u
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
prop->value.i8 = value; prop->value.i8 = value;
@ -659,6 +660,7 @@ int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier,
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
prop->value.i16 = value; prop->value.i16 = value;
@ -683,6 +685,7 @@ int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier,
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
prop->value.i32 = value; prop->value.i32 = value;
@ -701,6 +704,7 @@ int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier,
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
prop->value.varint = value; prop->value.varint = value;
@ -723,6 +727,7 @@ int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier,
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
if(len){ if(len){
@ -764,6 +769,7 @@ int mosquitto_property_add_string(mosquitto_property **proplist, int identifier,
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
if(value && strlen(value)){ if(value && strlen(value)){
prop->value.s.v = mosquitto__strdup(value); prop->value.s.v = mosquitto__strdup(value);
@ -795,6 +801,7 @@ int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identi
prop = mosquitto__calloc(1, sizeof(mosquitto_property)); prop = mosquitto__calloc(1, sizeof(mosquitto_property));
if(!prop) return MOSQ_ERR_NOMEM; if(!prop) return MOSQ_ERR_NOMEM;
prop->client_generated = true;
prop->identifier = identifier; prop->identifier = identifier;
if(name && strlen(name)){ if(name && strlen(name)){
@ -873,7 +880,7 @@ int mosquitto_property_check_all(int command, const mosquitto_property *properti
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
const mosquitto_property *mosquitto_property_get_property(const mosquitto_property *proplist, int identifier, bool skip_first) const mosquitto_property *property__get_property(const mosquitto_property *proplist, int identifier, bool skip_first)
{ {
const mosquitto_property *p; const mosquitto_property *p;
bool is_first = true; bool is_first = true;
@ -893,132 +900,168 @@ const mosquitto_property *mosquitto_property_get_property(const mosquitto_proper
} }
int mosquitto_property_read_byte(const mosquitto_property *property, uint8_t *value) const mosquitto_property *mosquitto_property_read_byte(const mosquitto_property *proplist, int identifier, uint8_t *value, bool skip_first)
{ {
if(!property || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR if(!proplist) return NULL;
&& property->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION
&& property->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION p = property__get_property(proplist, identifier, skip_first);
&& property->identifier != MQTT_PROP_MAXIMUM_QOS if(!p) return NULL;
&& property->identifier != MQTT_PROP_RETAIN_AVAILABLE if(p->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR
&& property->identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE && p->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION
&& property->identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE && p->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION
&& property->identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ && p->identifier != MQTT_PROP_MAXIMUM_QOS
return MOSQ_ERR_INVAL; && 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;
} }
*value = property->value.i8; if(value) *value = p->value.i8;
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_int16(const mosquitto_property *property, uint16_t *value) const mosquitto_property *mosquitto_property_read_int16(const mosquitto_property *proplist, int identifier, uint16_t *value, bool skip_first)
{ {
if(!property || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_SERVER_KEEP_ALIVE if(!proplist) return NULL;
&& property->identifier != MQTT_PROP_RECEIVE_MAXIMUM
&& property->identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM p = property__get_property(proplist, identifier, skip_first);
&& property->identifier != MQTT_PROP_TOPIC_ALIAS){ if(!p) return NULL;
return MOSQ_ERR_INVAL; 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;
} }
*value = property->value.i16; if(value) *value = p->value.i16;
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_int32(const mosquitto_property *property, uint32_t *value) const mosquitto_property *mosquitto_property_read_int32(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first)
{ {
if(!property || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL if(!proplist) return NULL;
&& 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; 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;
} }
*value = property->value.i32; if(value) *value = p->value.i32;
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_varint(const mosquitto_property *property, uint32_t *value) const mosquitto_property *mosquitto_property_read_varint(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first)
{ {
if(!property || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){ if(!proplist) return NULL;
return MOSQ_ERR_INVAL;
p = property__get_property(proplist, identifier, skip_first);
if(!p) return NULL;
if(p->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){
return NULL;
} }
*value = property->value.varint; if(value) *value = p->value.varint;
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_binary(const mosquitto_property *property, void **value, int *len) const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, int *len, bool skip_first)
{ {
if(!property || !value || !len) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_CORRELATION_DATA if(!proplist || (value && !len) || (!value && len)) return NULL;
&& property->identifier != MQTT_PROP_AUTHENTICATION_DATA){
return MOSQ_ERR_INVAL; 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;
} }
*len = property->value.bin.len; if(value){
*value = malloc(*len); *len = p->value.bin.len;
if(!value) return MOSQ_ERR_NOMEM; *value = malloc(*len);
if(!value) return NULL;
memcpy(*value, property->value.bin.v, *len); memcpy(*value, p->value.bin.v, *len);
}
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_string(const mosquitto_property *property, char **value) const mosquitto_property *mosquitto_property_read_string(const mosquitto_property *proplist, int identifier, char **value, bool skip_first)
{ {
if(!property || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_CONTENT_TYPE if(!proplist) return NULL;
&& property->identifier != MQTT_PROP_RESPONSE_TOPIC
&& property->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER p = property__get_property(proplist, identifier, skip_first);
&& property->identifier != MQTT_PROP_AUTHENTICATION_METHOD if(!p) return NULL;
&& property->identifier != MQTT_PROP_RESPONSE_INFORMATION if(p->identifier != MQTT_PROP_CONTENT_TYPE
&& property->identifier != MQTT_PROP_SERVER_REFERENCE && p->identifier != MQTT_PROP_RESPONSE_TOPIC
&& property->identifier != MQTT_PROP_REASON_STRING){ && p->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER
&& p->identifier != MQTT_PROP_AUTHENTICATION_METHOD
return MOSQ_ERR_INVAL; && p->identifier != MQTT_PROP_RESPONSE_INFORMATION
&& p->identifier != MQTT_PROP_SERVER_REFERENCE
&& p->identifier != MQTT_PROP_REASON_STRING){
return NULL;
} }
*value = calloc(1, property->value.s.len+1); if(value){
if(!value) return MOSQ_ERR_NOMEM; *value = calloc(1, p->value.s.len+1);
if(!value) return NULL;
memcpy(*value, p->value.s.v, p->value.s.len);
}
memcpy(*value, property->value.s.v, property->value.s.len);
return MOSQ_ERR_SUCCESS; return p;
} }
int mosquitto_property_read_string_pair(const mosquitto_property *property, char **name, char **value) const mosquitto_property *mosquitto_property_read_string_pair(const mosquitto_property *proplist, int identifier, char **name, char **value, bool skip_first)
{ {
if(!property || !name || !value) return MOSQ_ERR_INVAL; const mosquitto_property *p;
if(property->identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; if(!proplist) return NULL;
*name = calloc(1, property->name.len+1); p = property__get_property(proplist, identifier, skip_first);
if(!name) return MOSQ_ERR_NOMEM; if(!p) return NULL;
if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL;
*value = calloc(1, property->value.s.len+1); if(name){
if(!value){ *name = calloc(1, p->name.len+1);
free(*name); if(!name) return NULL;
return MOSQ_ERR_NOMEM; memcpy(*name, p->name.v, p->name.len);
} }
memcpy(*name, property->name.v, property->name.len); if(value){
memcpy(*value, property->value.s.v, property->value.s.len); *value = calloc(1, p->value.s.len+1);
if(!value){
if(name) free(*name);
return NULL;
}
memcpy(*value, p->value.s.v, p->value.s.len);
}
return MOSQ_ERR_SUCCESS; return p;
} }

@ -36,6 +36,7 @@ struct mqtt5__property {
} value; } value;
struct mqtt__string name; struct mqtt__string name;
int32_t identifier; int32_t identifier;
bool client_generated;
}; };

@ -23,7 +23,13 @@ suback_packet = mosq_test.gen_suback(mid, 0, proto_ver=5)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, resp_topic) props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, resp_topic)
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_CORRELATION_DATA, "corridor") props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_CORRELATION_DATA, "corridor")
props = mqtt5_props.prop_finalise(props) props = mqtt5_props.prop_finalise(props)
publish1_packet = mosq_test.gen_publish(pub_topic, qos=0, payload="action", proto_ver=5, properties=props) publish1_packet_incoming = mosq_test.gen_publish(pub_topic, qos=0, payload="action", proto_ver=5, properties=props)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, resp_topic)
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_CORRELATION_DATA, "corridor")
props += mqtt5_props.gen_string_pair_prop(mqtt5_props.PROP_USER_PROPERTY, "user", "data")
props = mqtt5_props.prop_finalise(props)
publish1_packet_outgoing = mosq_test.gen_publish(pub_topic, qos=0, payload="action", proto_ver=5, properties=props)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_CORRELATION_DATA, "corridor") props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_CORRELATION_DATA, "corridor")
props = mqtt5_props.prop_finalise(props) props = mqtt5_props.prop_finalise(props)
@ -65,8 +71,8 @@ try:
if mosq_test.expect_packet(conn2, "subscribe2", subscribe2_packet): if mosq_test.expect_packet(conn2, "subscribe2", subscribe2_packet):
conn2.send(suback_packet) conn2.send(suback_packet)
if mosq_test.expect_packet(conn1, "publish1", publish1_packet): if mosq_test.expect_packet(conn1, "publish1", publish1_packet_incoming):
conn2.send(publish1_packet) conn2.send(publish1_packet_outgoing)
if mosq_test.expect_packet(conn2, "publish2", publish2_packet): if mosq_test.expect_packet(conn2, "publish2", publish2_packet):
rc = 0 rc = 0

@ -24,13 +24,11 @@ void on_message_v5(struct mosquitto *mosq, void *obj, const struct mosquitto_mes
int rc; int rc;
if(!strcmp(msg->topic, "request/topic")){ if(!strcmp(msg->topic, "request/topic")){
p_resp = mosquitto_property_get_property(props, MQTT_PROP_RESPONSE_TOPIC, false); p_resp = mosquitto_property_read_string(props, MQTT_PROP_RESPONSE_TOPIC, &resp_topic, false);
if(p_resp){ if(p_resp){
p_corr = mosquitto_property_get_property(props, MQTT_PROP_CORRELATION_DATA, false); p_corr = mosquitto_property_read_binary(props, MQTT_PROP_CORRELATION_DATA, NULL, NULL, false);
if(mosquitto_property_read_string(p_resp, &resp_topic) == MOSQ_ERR_SUCCESS){ rc = mosquitto_publish_v5(mosq, NULL, resp_topic, strlen("a response"), "a response", 0, false, p_corr);
rc = mosquitto_publish_v5(mosq, NULL, resp_topic, strlen("a response"), "a response", 0, false, p_corr); free(resp_topic);
free(resp_topic);
}
} }
} }
} }

Loading…
Cancel
Save