diff --git a/lib/actions.c b/lib/actions.c index 38074b1b..65388195 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -39,15 +39,32 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in uint16_t local_mid; int queue_status; const mosquitto_property *p; + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; bool have_topic_alias; int rc; 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) topic = NULL; if(mosq->protocol == mosq_p_mqtt5){ - p = properties; + p = outgoing_properties; have_topic_alias = false; while(p){ 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; } } - if(properties){ - rc = mosquitto_property_check_all(CMD_PUBLISH, properties); - if(rc) return rc; - } local_mid = mosquitto__mid_generate(mosq); if(mid){ @@ -80,7 +93,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in } 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{ message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all)); 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; } 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{ message->state = mosq_ms_invalid; 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) { + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; + int rc; if(!mosq) return MOSQ_ERR_INVAL; + if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8; 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; } - 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) { + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; int i; int rc; 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(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; - if(mosq->protocol == mosq_p_mqtt5 && properties){ - rc = mosquitto_property_check_all(CMD_SUBSCRIBE, properties); + if(properties){ + if(properties->client_generated){ + outgoing_properties = properties; + }else{ + memcpy(&local_property, properties, sizeof(mosquitto_property)); + local_property.client_generated = true; + local_property.next = NULL; + outgoing_properties = &local_property; + } + rc = mosquitto_property_check_all(CMD_SUBSCRIBE, outgoing_properties); if(rc) return rc; } @@ -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) { + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; int rc; if(!mosq) return MOSQ_ERR_INVAL; + if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; if(mosquitto_sub_topic_check(sub)) return MOSQ_ERR_INVAL; if(mosquitto_validate_utf8(sub, strlen(sub))) return MOSQ_ERR_MALFORMED_UTF8; 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; } - return send__unsubscribe(mosq, mid, sub, properties); + + return send__unsubscribe(mosq, mid, sub, outgoing_properties); } diff --git a/lib/connect.c b/lib/connect.c index 0de00322..791aadd5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -149,10 +149,26 @@ int mosquitto_reconnect(struct mosquitto *mosq) static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mosquitto_property *properties) { + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; int rc; struct mosquitto__packet *packet; if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; + if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; + + if(properties){ + if(properties->client_generated){ + outgoing_properties = properties; + }else{ + memcpy(&local_property, properties, sizeof(mosquitto_property)); + local_property.client_generated = true; + local_property.next = NULL; + outgoing_properties = &local_property; + } + rc = mosquitto_property_check_all(CMD_DISCONNECT, outgoing_properties); + if(rc) return rc; + } pthread_mutex_lock(&mosq->state_mutex); #ifdef WITH_SOCKS @@ -223,7 +239,7 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos }else #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) { + const mosquitto_property *outgoing_properties = NULL; + mosquitto_property local_property; int rc; if(!mosq) return MOSQ_ERR_INVAL; + if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED; if(properties){ - 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; } @@ -248,7 +275,7 @@ int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosqu pthread_mutex_unlock(&mosq->state_mutex); 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); } diff --git a/lib/handle_connack.c b/lib/handle_connack.c index 7cd65d4e..5e5fa86d 100644 --- a/lib/handle_connack.c +++ b/lib/handle_connack.c @@ -34,7 +34,7 @@ int handle__connack(struct mosquitto *mosq) uint8_t reason_code; int rc; mosquitto_property *properties = NULL; - const mosquitto_property *prop; + char *clientid = NULL; assert(mosq); rc = packet__read_byte(&mosq->in_packet, &connect_flags); @@ -47,30 +47,21 @@ int handle__connack(struct mosquitto *mosq) if(rc) return rc; } - prop = mosquitto_property_get_property(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, false); - if(prop){ + mosquitto_property_read_string(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, &clientid, false); + if(clientid){ if(mosq->id){ /* We've been sent a client identifier but already have one. This * shouldn't happen. */ + free(clientid); mosquitto_property_free_all(&properties); return MOSQ_ERR_PROTOCOL; }else{ - rc = mosquitto_property_read_string(prop, &mosq->id); - if(rc){ - mosquitto_property_free_all(&properties); - return rc; - } + mosq->id = clientid; + clientid = NULL; } } - prop = mosquitto_property_get_property(properties, MQTT_PROP_SERVER_KEEP_ALIVE, false); - if(prop){ - rc = mosquitto_property_read_int16(prop, &mosq->keepalive); - if(rc){ - mosquitto_property_free_all(&properties); - return rc; - } - } + mosquitto_property_read_int16(properties, MQTT_PROP_SERVER_KEEP_ALIVE, &mosq->keepalive, false); log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code); pthread_mutex_lock(&mosq->callback_mutex); diff --git a/lib/linker.version b/lib/linker.version index b1be3a11..e9ee68ca 100644 --- a/lib/linker.version +++ b/lib/linker.version @@ -106,7 +106,6 @@ 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; diff --git a/lib/mosquitto.h b/lib/mosquitto.h index e641a8d1..f8ca0794 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -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); /* - * 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 - * function can search for multiple entries of an identifier by using the - * returned value and skip_first. + * If the property is not found, *value will not be modified, so it is safe to + * pass a variable with a default value to be potentially overwritten: + * + * uint16_t keepalive = 60; // default value + * // Get value from property list, or keep default if not found. + * mosquitto_property_read_int16(proplist, MQTT_PROP_SERVER_KEEP_ALIVE, &keepalive, false); * * Parameters: - * proplist - mosquitto_property pointer, the list of properties + * 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 be ignored or not. Should usually be set to false. * * Returns: * 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: * // proplist is obtained from a callback * 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){ - * 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); + * printf("value: %s\n", value); + * prop = mosquitto_property_read_byte(prop, identifier, &value); * } */ -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); +libmosq_EXPORT const mosquitto_property *mosquitto_property_read_byte( + const mosquitto_property *proplist, + int identifier, + uint8_t *value, + bool skip_first); /* * Function: mosquitto_property_read_int16 @@ -2479,13 +2475,23 @@ libmosq_EXPORT int mosquitto_property_read_byte(const mosquitto_property *proper * * Parameters: * 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: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a uint16 + * A valid property pointer if the property is found + * NULL, if the property is not found, or proplist is NULL. + * + * Example: + * See */ -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 @@ -2494,13 +2500,23 @@ libmosq_EXPORT int mosquitto_property_read_int16(const mosquitto_property *prope * * Parameters: * 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: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not an int32 + * A valid property pointer if the property is found + * NULL, if the property is not found, or proplist is NULL. + * + * Example: + * See */ -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 @@ -2509,13 +2525,23 @@ libmosq_EXPORT int mosquitto_property_read_int32(const mosquitto_property *prope * * Parameters: * 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: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if property or value is NULL, or if property is not a varint + * A valid property pointer if the property is found + * NULL, if the property is not found, or proplist is NULL. + * + * Example: + * See */ -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 @@ -2526,15 +2552,24 @@ libmosq_EXPORT int mosquitto_property_read_varint(const mosquitto_property *prop * * 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 + * 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: - * 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 + * 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 */ -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 @@ -2545,14 +2580,24 @@ libmosq_EXPORT int mosquitto_property_read_binary(const mosquitto_property *prop * * Parameters: * 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: - * 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 + * 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 */ -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 @@ -2563,15 +2608,27 @@ libmosq_EXPORT int mosquitto_property_read_string(const mosquitto_property *prop * * 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 + * identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) + * name - pointer to char* for the name property data to be stored in, or NULL + * if the name is not required. + * value - pointer to char*, for the property data to be stored in, or NULL if + * the value is not required. + * skip_first - boolean that indicates whether the first item in the list + * should be ignored or not. Should usually be set to false. * * Returns: - * 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); + * 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 + */ +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 diff --git a/lib/property_mosq.c b/lib/property_mosq.c index 40fc3909..ae2d02bb 100644 --- a/lib/property_mosq.c +++ b/lib/property_mosq.c @@ -636,6 +636,7 @@ int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, u prop = mosquitto__calloc(1, sizeof(mosquitto_property)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; 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)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; 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)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; 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)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; 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)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; if(len){ @@ -764,6 +769,7 @@ int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, prop = mosquitto__calloc(1, sizeof(mosquitto_property)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; if(value && strlen(value)){ prop->value.s.v = mosquitto__strdup(value); @@ -795,6 +801,7 @@ int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identi prop = mosquitto__calloc(1, sizeof(mosquitto_property)); if(!prop) return MOSQ_ERR_NOMEM; + prop->client_generated = true; prop->identifier = identifier; if(name && strlen(name)){ @@ -873,7 +880,7 @@ 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 *property__get_property(const mosquitto_property *proplist, int identifier, bool skip_first) { const mosquitto_property *p; 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; - 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; + 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; } - *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; - 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; + 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; } - *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; - 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){ + const mosquitto_property *p; + 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_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; - if(property->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){ - return MOSQ_ERR_INVAL; + 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; } - *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; - if(property->identifier != MQTT_PROP_CORRELATION_DATA - && property->identifier != MQTT_PROP_AUTHENTICATION_DATA){ + const mosquitto_property *p; + if(!proplist || (value && !len) || (!value && len)) return NULL; - 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; - *value = malloc(*len); - if(!value) return MOSQ_ERR_NOMEM; + if(value){ + *len = p->value.bin.len; + *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; - 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; + 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; } - *value = calloc(1, property->value.s.len+1); - if(!value) return MOSQ_ERR_NOMEM; + if(value){ + *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; - if(property->identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; + const mosquitto_property *p; + if(!proplist) return NULL; - *name = calloc(1, property->name.len+1); - if(!name) return MOSQ_ERR_NOMEM; + p = property__get_property(proplist, identifier, skip_first); + if(!p) return NULL; + if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL; - *value = calloc(1, property->value.s.len+1); - if(!value){ - free(*name); - return MOSQ_ERR_NOMEM; + if(name){ + *name = calloc(1, p->name.len+1); + if(!name) return NULL; + memcpy(*name, p->name.v, p->name.len); } - memcpy(*name, property->name.v, property->name.len); - memcpy(*value, property->value.s.v, property->value.s.len); + if(value){ + *value = calloc(1, p->value.s.len+1); + if(!value){ + if(name) free(*name); + return NULL; + } + memcpy(*value, p->value.s.v, p->value.s.len); + } - return MOSQ_ERR_SUCCESS; + return p; } diff --git a/lib/property_mosq.h b/lib/property_mosq.h index 97c11564..d31ce85e 100644 --- a/lib/property_mosq.h +++ b/lib/property_mosq.h @@ -36,6 +36,7 @@ struct mqtt5__property { } value; struct mqtt__string name; int32_t identifier; + bool client_generated; }; diff --git a/test/lib/03-request-response-correlation.py b/test/lib/03-request-response-correlation.py index b1ed9ccd..a2ab54be 100755 --- a/test/lib/03-request-response-correlation.py +++ b/test/lib/03-request-response-correlation.py @@ -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_CORRELATION_DATA, "corridor") 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.prop_finalise(props) @@ -65,8 +71,8 @@ try: if mosq_test.expect_packet(conn2, "subscribe2", subscribe2_packet): conn2.send(suback_packet) - if mosq_test.expect_packet(conn1, "publish1", publish1_packet): - conn2.send(publish1_packet) + if mosq_test.expect_packet(conn1, "publish1", publish1_packet_incoming): + conn2.send(publish1_packet_outgoing) if mosq_test.expect_packet(conn2, "publish2", publish2_packet): rc = 0 diff --git a/test/lib/c/03-request-response-2.c b/test/lib/c/03-request-response-2.c index 0f16f1ef..3419f395 100644 --- a/test/lib/c/03-request-response-2.c +++ b/test/lib/c/03-request-response-2.c @@ -24,13 +24,11 @@ void on_message_v5(struct mosquitto *mosq, void *obj, const struct mosquitto_mes int rc; 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){ - p_corr = mosquitto_property_get_property(props, MQTT_PROP_CORRELATION_DATA, 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); - free(resp_topic); - } + p_corr = mosquitto_property_read_binary(props, MQTT_PROP_CORRELATION_DATA, NULL, NULL, false); + rc = mosquitto_publish_v5(mosq, NULL, resp_topic, strlen("a response"), "a response", 0, false, p_corr); + free(resp_topic); } } }