Property reading, and tests for byte properties.
This commit is contained in:
parent
34c8c28e9d
commit
f4b2838574
@ -23,6 +23,7 @@ MOSQ_OBJS=mosquitto.o \
|
|||||||
options.o \
|
options.o \
|
||||||
packet_datatypes.o \
|
packet_datatypes.o \
|
||||||
packet_mosq.o \
|
packet_mosq.o \
|
||||||
|
property_mosq.o \
|
||||||
read_handle.o \
|
read_handle.o \
|
||||||
send_connect.o \
|
send_connect.o \
|
||||||
send_disconnect.o \
|
send_disconnect.o \
|
||||||
@ -143,6 +144,9 @@ packet_datatypes.o : packet_datatypes.c packet_mosq.h
|
|||||||
packet_mosq.o : packet_mosq.c packet_mosq.h
|
packet_mosq.o : packet_mosq.c packet_mosq.h
|
||||||
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@
|
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
property_mosq.o : property_mosq.c property_mosq.h
|
||||||
|
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
read_handle.o : read_handle.c read_handle.h
|
read_handle.o : read_handle.c read_handle.h
|
||||||
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@
|
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ enum mosq_err_t {
|
|||||||
MOSQ_ERR_MALFORMED_UTF8 = 18,
|
MOSQ_ERR_MALFORMED_UTF8 = 18,
|
||||||
MOSQ_ERR_KEEPALIVE = 19,
|
MOSQ_ERR_KEEPALIVE = 19,
|
||||||
MOSQ_ERR_LOOKUP = 20,
|
MOSQ_ERR_LOOKUP = 20,
|
||||||
|
MOSQ_ERR_MALFORMED_PACKET = 19,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Error values */
|
/* Error values */
|
||||||
|
@ -88,7 +88,7 @@ void packet__write_bytes(struct mosquitto__packet *packet, const void *bytes, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int packet__read_binary(struct mosquitto__packet *packet, void **data, int *length)
|
int packet__read_binary(struct mosquitto__packet *packet, uint8_t **data, int *length)
|
||||||
{
|
{
|
||||||
uint16_t slen;
|
uint16_t slen;
|
||||||
int rc;
|
int rc;
|
||||||
@ -118,7 +118,7 @@ int packet__read_string(struct mosquitto__packet *packet, char **str, int *lengt
|
|||||||
int rc;
|
int rc;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
rc = packet__read_binary(packet, (void **)str, &len);
|
rc = packet__read_binary(packet, (uint8_t **)str, &len);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
|
|
||||||
if(mosquitto_validate_utf8(*str, len)){
|
if(mosquitto_validate_utf8(*str, len)){
|
||||||
|
@ -29,7 +29,7 @@ int packet__queue(struct mosquitto *mosq, struct mosquitto__packet *packet);
|
|||||||
|
|
||||||
int packet__read_byte(struct mosquitto__packet *packet, uint8_t *byte);
|
int packet__read_byte(struct mosquitto__packet *packet, uint8_t *byte);
|
||||||
int packet__read_bytes(struct mosquitto__packet *packet, void *bytes, uint32_t count);
|
int packet__read_bytes(struct mosquitto__packet *packet, void *bytes, uint32_t count);
|
||||||
int packet__read_binary(struct mosquitto__packet *packet, void **data, int *length);
|
int packet__read_binary(struct mosquitto__packet *packet, uint8_t **data, int *length);
|
||||||
int packet__read_string(struct mosquitto__packet *packet, char **str, int *length);
|
int packet__read_string(struct mosquitto__packet *packet, char **str, int *length);
|
||||||
int packet__read_uint16(struct mosquitto__packet *packet, uint16_t *word);
|
int packet__read_uint16(struct mosquitto__packet *packet, uint16_t *word);
|
||||||
int packet__read_uint32(struct mosquitto__packet *packet, uint32_t *word);
|
int packet__read_uint32(struct mosquitto__packet *packet, uint32_t *word);
|
||||||
|
@ -26,7 +26,7 @@ Contributors:
|
|||||||
#include "packet_mosq.h"
|
#include "packet_mosq.h"
|
||||||
#include "property_mosq.h"
|
#include "property_mosq.h"
|
||||||
|
|
||||||
int property__read(struct mosquitto__packet *packet, int32_t *len)
|
int property__read(struct mosquitto__packet *packet, int32_t *len, struct mqtt5__property *property)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int32_t property_identifier;
|
int32_t property_identifier;
|
||||||
@ -35,230 +35,261 @@ int property__read(struct mosquitto__packet *packet, int32_t *len)
|
|||||||
uint16_t uint16;
|
uint16_t uint16;
|
||||||
uint32_t uint32;
|
uint32_t uint32;
|
||||||
int32_t varint;
|
int32_t varint;
|
||||||
char *str;
|
char *str1, *str2;
|
||||||
int slen;
|
int slen1, slen2;
|
||||||
*len -= 14;
|
|
||||||
|
|
||||||
rc = packet__read_varint(packet, &property_identifier, NULL);
|
rc = packet__read_varint(packet, &property_identifier, NULL);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 1;
|
*len -= 1;
|
||||||
|
|
||||||
|
memset(property, 0, sizeof(struct mqtt5__property));
|
||||||
|
|
||||||
|
property->identifier = property_identifier;
|
||||||
|
|
||||||
switch(property_identifier){
|
switch(property_identifier){
|
||||||
case PROP_PAYLOAD_FORMAT_INDICATOR:
|
case PROP_PAYLOAD_FORMAT_INDICATOR:
|
||||||
|
case PROP_REQUEST_PROBLEM_INFO:
|
||||||
|
case PROP_REQUEST_RESPONSE_INFO:
|
||||||
|
case PROP_MAXIMUM_QOS:
|
||||||
|
case PROP_RETAIN_AVAILABLE:
|
||||||
|
case PROP_WILDCARD_SUB_AVAILABLE:
|
||||||
|
case PROP_SUBSCRIPTION_ID_AVAILABLE:
|
||||||
|
case PROP_SHARED_SUB_AVAILABLE:
|
||||||
rc = packet__read_byte(packet, &byte);
|
rc = packet__read_byte(packet, &byte);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 1; /* byte */
|
*len -= 1; /* byte */
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Payload format indicator: %d", byte);
|
property->value.i8 = byte;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SERVER_KEEP_ALIVE:
|
||||||
|
case PROP_RECEIVE_MAXIMUM:
|
||||||
|
case PROP_TOPIC_ALIAS_MAXIMUM:
|
||||||
|
case PROP_TOPIC_ALIAS:
|
||||||
|
rc = packet__read_uint16(packet, &uint16);
|
||||||
|
if(rc) return rc;
|
||||||
|
*len -= 2; /* uint16 */
|
||||||
|
property->value.i16 = uint16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_MESSAGE_EXPIRY_INTERVAL:
|
case PROP_MESSAGE_EXPIRY_INTERVAL:
|
||||||
|
case PROP_SESSION_EXPIRY_INTERVAL:
|
||||||
|
case PROP_WILL_DELAY_INTERVAL:
|
||||||
|
case PROP_MAXIMUM_PACKET_SIZE:
|
||||||
rc = packet__read_uint32(packet, &uint32);
|
rc = packet__read_uint32(packet, &uint32);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 4; /* uint32 */
|
*len -= 4; /* uint32 */
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Message expiry: %d", uint32);
|
property->value.i32 = uint32;
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_CONTENT_TYPE:
|
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Content type: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_RESPONSE_TOPIC:
|
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Response topic: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_CORRELATION_DATA:
|
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Correlation data: %s", str);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_SUBSCRIPTION_IDENTIFIER:
|
case PROP_SUBSCRIPTION_IDENTIFIER:
|
||||||
rc = packet__read_varint(packet, &varint, &byte_count);
|
rc = packet__read_varint(packet, &varint, &byte_count);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= byte_count;
|
*len -= byte_count;
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Subscription identifier: %d", varint);
|
property->value.varint = varint;
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_SESSION_EXPIRY_INTERVAL:
|
|
||||||
rc = packet__read_uint32(packet, &uint32);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 4; /* uint32 */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Session expiry: %d", uint32);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_CONTENT_TYPE:
|
||||||
|
case PROP_RESPONSE_TOPIC:
|
||||||
case PROP_ASSIGNED_CLIENT_IDENTIFIER:
|
case PROP_ASSIGNED_CLIENT_IDENTIFIER:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Assigned client identifier: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_SERVER_KEEP_ALIVE:
|
|
||||||
rc = packet__read_uint16(packet, &uint16);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2; /* uint16 */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Session expiry: %d", uint16);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_AUTHENTICATION_METHOD:
|
case PROP_AUTHENTICATION_METHOD:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Authentication method: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_AUTHENTICATION_DATA:
|
case PROP_AUTHENTICATION_DATA:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Authentication data: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_REQUEST_PROBLEM_INFO:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Request problem information: %d", byte);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_WILL_DELAY_INTERVAL:
|
|
||||||
rc = packet__read_uint32(packet, &uint32);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 4; /* uint32 */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Will delay interval: %d", uint32);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_REQUEST_RESPONSE_INFO:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Request response information: %d", byte);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_RESPONSE_INFO:
|
case PROP_RESPONSE_INFO:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Response information: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_SERVER_REFERENCE:
|
case PROP_SERVER_REFERENCE:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Server reference: %s", str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_REASON_STRING:
|
case PROP_REASON_STRING:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
rc = packet__read_string(packet, &str1, &slen1);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
*len -= 2 - slen1; /* uint16, string len */
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Reason string: %s", str);
|
property->value.s.v = str1;
|
||||||
|
property->value.s.len = slen1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_RECEIVE_MAXIMUM:
|
case PROP_CORRELATION_DATA:
|
||||||
rc = packet__read_uint16(packet, &uint16);
|
rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 2; /* uint16 */
|
*len -= 2 - slen1; /* uint16, binary len */
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Receive maximum: %d", uint16);
|
property->value.bin.v = str1;
|
||||||
break;
|
property->value.bin.len = slen1;
|
||||||
|
|
||||||
case PROP_TOPIC_ALIAS_MAXIMUM:
|
|
||||||
rc = packet__read_uint16(packet, &uint16);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2; /* uint16 */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Topic alias maximum: %d", uint16);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_TOPIC_ALIAS:
|
|
||||||
rc = packet__read_uint16(packet, &uint16);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 2; /* uint16 */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Topic alias: %d", uint16);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_MAXIMUM_QOS:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Maximum QoS: %d", byte);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_RETAIN_AVAILABLE:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Retain available: %d", byte);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_USER_PROPERTY:
|
case PROP_USER_PROPERTY:
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
rc = packet__read_string(packet, &str1, &slen1);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
*len -= 2 - slen1; /* uint16, string len */
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "User property name: %s", str);
|
|
||||||
|
|
||||||
rc = packet__read_string(packet, &str, &slen);
|
rc = packet__read_string(packet, &str2, &slen2);
|
||||||
if(rc) return rc;
|
if(rc){
|
||||||
*len -= 2 - slen; /* uint16, string len */
|
mosquitto__free(str1);
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "User property value: %s", str);
|
return rc;
|
||||||
break;
|
}
|
||||||
|
*len -= 2 - slen2; /* uint16, string len */
|
||||||
|
|
||||||
case PROP_MAXIMUM_PACKET_SIZE:
|
property->name.v = str1;
|
||||||
rc = packet__read_uint32(packet, &uint32);
|
property->name.len = slen1;
|
||||||
if(rc) return rc;
|
property->value.s.v = str2;
|
||||||
*len -= 4; /* uint32 */
|
property->value.s.len = slen2;
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Maximum packet size: %d", uint32);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_WILDCARD_SUB_AVAILABLE:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Wildcard subscription available: %d", byte);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_SUBSCRIPTION_ID_AVAILABLE:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Subscription identifier available: %d", byte);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_SHARED_SUB_AVAILABLE:
|
|
||||||
rc = packet__read_byte(packet, &byte);
|
|
||||||
if(rc) return rc;
|
|
||||||
*len -= 1; /* byte */
|
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Shared subscription available: %d", byte);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", byte);
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", byte);
|
||||||
return 1;
|
return MOSQ_ERR_MALFORMED_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int property__read_all(struct mosquitto__packet *packet)
|
int property__read_all(struct mosquitto__packet *packet, struct mqtt5__property **properties)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int32_t proplen;
|
int32_t proplen;
|
||||||
|
struct mqtt5__property *p, *last = NULL;
|
||||||
|
|
||||||
|
bool have_payload_format_indicator = false;
|
||||||
|
bool have_request_problem_info = false;
|
||||||
|
bool have_request_response_info = false;
|
||||||
|
bool have_maximum_qos = false;
|
||||||
|
bool have_retain_available = false;
|
||||||
|
bool have_wildcard_sub_available = false;
|
||||||
|
bool have_subscription_id_available = false;
|
||||||
|
bool have_shared_sub_available = false;
|
||||||
|
|
||||||
rc = packet__read_varint(packet, &proplen, NULL);
|
rc = packet__read_varint(packet, &proplen, NULL);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
|
|
||||||
|
*properties = NULL;
|
||||||
|
|
||||||
|
/* The order of properties must be preserved for some types, so keep the
|
||||||
|
* same order for all */
|
||||||
while(proplen > 0){
|
while(proplen > 0){
|
||||||
rc = property__read(packet, &proplen);
|
p = mosquitto__calloc(1, sizeof(struct mqtt5__property));
|
||||||
if(rc) return rc;
|
|
||||||
|
rc = property__read(packet, &proplen, p);
|
||||||
|
if(rc){
|
||||||
|
mosquitto__free(p);
|
||||||
|
property__free_all(properties);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(*properties)){
|
||||||
|
*properties = p;
|
||||||
|
}else{
|
||||||
|
last->next = p;
|
||||||
|
}
|
||||||
|
last = p;
|
||||||
|
|
||||||
|
/* Validity checks */
|
||||||
|
if(p->identifier == PROP_PAYLOAD_FORMAT_INDICATOR){
|
||||||
|
if(have_payload_format_indicator){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_payload_format_indicator = true;
|
||||||
|
}else if(p->identifier == PROP_REQUEST_PROBLEM_INFO){
|
||||||
|
if(have_request_problem_info || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_request_problem_info = true;
|
||||||
|
}else if(p->identifier == PROP_REQUEST_RESPONSE_INFO){
|
||||||
|
if(have_request_response_info || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_request_response_info = true;
|
||||||
|
}else if(p->identifier == PROP_MAXIMUM_QOS){
|
||||||
|
if(have_maximum_qos || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_maximum_qos = true;
|
||||||
|
}else if(p->identifier == PROP_RETAIN_AVAILABLE){
|
||||||
|
if(have_retain_available || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_retain_available = true;
|
||||||
|
}else if(p->identifier == PROP_WILDCARD_SUB_AVAILABLE){
|
||||||
|
if(have_wildcard_sub_available || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_wildcard_sub_available = true;
|
||||||
|
}else if(p->identifier == PROP_SUBSCRIPTION_ID_AVAILABLE){
|
||||||
|
if(have_subscription_id_available || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_subscription_id_available = true;
|
||||||
|
}else if(p->identifier == PROP_SHARED_SUB_AVAILABLE){
|
||||||
|
if(have_shared_sub_available || p->value.i8 > 1){
|
||||||
|
property__free_all(properties);
|
||||||
|
return MOSQ_ERR_PROTOCOL;
|
||||||
|
}
|
||||||
|
have_shared_sub_available = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void property__free(struct mqtt5__property **property)
|
||||||
|
{
|
||||||
|
if(!property || !(*property)) return;
|
||||||
|
|
||||||
|
switch((*property)->identifier){
|
||||||
|
case PROP_CONTENT_TYPE:
|
||||||
|
case PROP_RESPONSE_TOPIC:
|
||||||
|
case PROP_CORRELATION_DATA:
|
||||||
|
case PROP_ASSIGNED_CLIENT_IDENTIFIER:
|
||||||
|
case PROP_AUTHENTICATION_METHOD:
|
||||||
|
case PROP_AUTHENTICATION_DATA:
|
||||||
|
case PROP_RESPONSE_INFO:
|
||||||
|
case PROP_SERVER_REFERENCE:
|
||||||
|
case PROP_REASON_STRING:
|
||||||
|
mosquitto__free((*property)->value.s.v);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_PROPERTY:
|
||||||
|
mosquitto__free((*property)->name.v);
|
||||||
|
mosquitto__free((*property)->value.s.v);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PAYLOAD_FORMAT_INDICATOR:
|
||||||
|
case PROP_MESSAGE_EXPIRY_INTERVAL:
|
||||||
|
case PROP_SUBSCRIPTION_IDENTIFIER:
|
||||||
|
case PROP_SESSION_EXPIRY_INTERVAL:
|
||||||
|
case PROP_SERVER_KEEP_ALIVE:
|
||||||
|
case PROP_REQUEST_PROBLEM_INFO:
|
||||||
|
case PROP_WILL_DELAY_INTERVAL:
|
||||||
|
case PROP_REQUEST_RESPONSE_INFO:
|
||||||
|
case PROP_RECEIVE_MAXIMUM:
|
||||||
|
case PROP_TOPIC_ALIAS_MAXIMUM:
|
||||||
|
case PROP_TOPIC_ALIAS:
|
||||||
|
case PROP_MAXIMUM_QOS:
|
||||||
|
case PROP_RETAIN_AVAILABLE:
|
||||||
|
case PROP_MAXIMUM_PACKET_SIZE:
|
||||||
|
case PROP_WILDCARD_SUB_AVAILABLE:
|
||||||
|
case PROP_SUBSCRIPTION_ID_AVAILABLE:
|
||||||
|
case PROP_SHARED_SUB_AVAILABLE:
|
||||||
|
/* Nothing to free */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(*property);
|
||||||
|
*property = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void property__free_all(struct mqtt5__property **property)
|
||||||
|
{
|
||||||
|
struct mqtt5__property *p, *next;
|
||||||
|
|
||||||
|
p = *property;
|
||||||
|
while(p){
|
||||||
|
next = p->next;
|
||||||
|
property__free(&p);
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
*property = NULL;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,28 @@ Contributors:
|
|||||||
#include "mosquitto_internal.h"
|
#include "mosquitto_internal.h"
|
||||||
#include "mosquitto.h"
|
#include "mosquitto.h"
|
||||||
|
|
||||||
int property__read_all(struct mosquitto__packet *packet);
|
struct mqtt__string {
|
||||||
|
char *v;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mqtt5__property {
|
||||||
|
struct mqtt5__property *next;
|
||||||
|
union {
|
||||||
|
uint8_t i8;
|
||||||
|
uint16_t i16;
|
||||||
|
uint32_t i32;
|
||||||
|
uint32_t varint;
|
||||||
|
struct mqtt__string bin;
|
||||||
|
struct mqtt__string s;
|
||||||
|
} value;
|
||||||
|
struct mqtt__string name;
|
||||||
|
int32_t identifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int property__read_all(struct mosquitto__packet *packet, struct mqtt5__property **property);
|
||||||
|
void property__free(struct mqtt5__property **property);
|
||||||
|
void property__free_all(struct mqtt5__property **property);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,6 +131,7 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
|
|||||||
struct mosquitto__subleaf *leaf;
|
struct mosquitto__subleaf *leaf;
|
||||||
int i;
|
int i;
|
||||||
struct mosquitto__security_options *security_opts;
|
struct mosquitto__security_options *security_opts;
|
||||||
|
struct mqtt5__property *properties;
|
||||||
#ifdef WITH_TLS
|
#ifdef WITH_TLS
|
||||||
X509 *client_cert = NULL;
|
X509 *client_cert = NULL;
|
||||||
X509_NAME *name;
|
X509_NAME *name;
|
||||||
@ -241,8 +242,9 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(protocol_version == PROTOCOL_VERSION_v5){
|
if(protocol_version == PROTOCOL_VERSION_v5){
|
||||||
rc = property__read_all(&context->in_packet);
|
rc = property__read_all(&context->in_packet, &properties);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
|
property__free_all(&properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packet__read_string(&context->in_packet, &client_id, &slen)){
|
if(packet__read_string(&context->in_packet, &client_id, &slen)){
|
||||||
|
@ -45,6 +45,8 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
|
|||||||
int len;
|
int len;
|
||||||
int slen;
|
int slen;
|
||||||
char *topic_mount;
|
char *topic_mount;
|
||||||
|
struct mqtt5__property *properties;
|
||||||
|
|
||||||
#ifdef WITH_BRIDGE
|
#ifdef WITH_BRIDGE
|
||||||
char *topic_temp;
|
char *topic_temp;
|
||||||
int i;
|
int i;
|
||||||
@ -132,8 +134,9 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(context->protocol == mosq_p_mqtt5){
|
if(context->protocol == mosq_p_mqtt5){
|
||||||
rc = property__read_all(&context->in_packet);
|
rc = property__read_all(&context->in_packet, &properties);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
|
property__free_all(&properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
payloadlen = context->in_packet.remaining_length - context->in_packet.pos;
|
payloadlen = context->in_packet.remaining_length - context->in_packet.pos;
|
||||||
|
@ -5,9 +5,21 @@ include ../../config.mk
|
|||||||
CFLAGS=-I../.. -I../../lib -coverage -Wall -ggdb
|
CFLAGS=-I../.. -I../../lib -coverage -Wall -ggdb
|
||||||
TEST_LDFLAGS=-lcunit -coverage
|
TEST_LDFLAGS=-lcunit -coverage
|
||||||
|
|
||||||
|
TEST_OBJS = test.o \
|
||||||
|
datatype_read.o \
|
||||||
|
datatype_write.o \
|
||||||
|
property_read.o \
|
||||||
|
stubs.o \
|
||||||
|
utf8.o
|
||||||
|
|
||||||
|
LIB_OBJS = memory_mosq.o \
|
||||||
|
packet_datatypes.o \
|
||||||
|
property_mosq.o \
|
||||||
|
utf8_mosq.o
|
||||||
|
|
||||||
all : test
|
all : test
|
||||||
|
|
||||||
mosq_test : test.o datatype_read.o datatype_write.o utf8.o memory_mosq.o packet_datatypes.o utf8_mosq.o
|
mosq_test : ${TEST_OBJS} ${LIB_OBJS}
|
||||||
$(CROSS_COMPILE)$(CC) -o $@ $^ ${TEST_LDFLAGS}
|
$(CROSS_COMPILE)$(CC) -o $@ $^ ${TEST_LDFLAGS}
|
||||||
|
|
||||||
memory_mosq.o : ../../lib/memory_mosq.c
|
memory_mosq.o : ../../lib/memory_mosq.c
|
||||||
@ -16,6 +28,9 @@ memory_mosq.o : ../../lib/memory_mosq.c
|
|||||||
packet_datatypes.o : ../../lib/packet_datatypes.c
|
packet_datatypes.o : ../../lib/packet_datatypes.c
|
||||||
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
|
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
|
||||||
|
|
||||||
|
property_mosq.o : ../../lib/property_mosq.c
|
||||||
|
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
|
||||||
|
|
||||||
utf8_mosq.o : ../../lib/utf8_mosq.c
|
utf8_mosq.o : ../../lib/utf8_mosq.c
|
||||||
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
|
$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ static void binary_read_helper(
|
|||||||
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
packet.payload = payload;
|
packet.payload = payload;
|
||||||
packet.remaining_length = remaining_length;
|
packet.remaining_length = remaining_length;
|
||||||
rc = packet__read_binary(&packet, (void **)&value, &length);
|
rc = packet__read_binary(&packet, (uint8_t **)&value, &length);
|
||||||
CU_ASSERT_EQUAL(rc, rc_expected);
|
CU_ASSERT_EQUAL(rc, rc_expected);
|
||||||
if(value_expected){
|
if(value_expected){
|
||||||
/* FIXME - this should be a memcmp */
|
/* FIXME - this should be a memcmp */
|
||||||
|
@ -104,7 +104,6 @@ static void TEST_string_write(void)
|
|||||||
{
|
{
|
||||||
uint8_t payload[100];
|
uint8_t payload[100];
|
||||||
struct mosquitto__packet packet;
|
struct mosquitto__packet packet;
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
memset(payload, 0, 100);
|
memset(payload, 0, 100);
|
||||||
|
390
test/unit/property_read.c
Normal file
390
test/unit/property_read.c
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
#include <CUnit/CUnit.h>
|
||||||
|
#include <CUnit/Basic.h>
|
||||||
|
|
||||||
|
#include "mqtt_protocol.h"
|
||||||
|
#include "property_mosq.h"
|
||||||
|
#include "packet_mosq.h"
|
||||||
|
|
||||||
|
static void byte_prop_read_helper(
|
||||||
|
uint8_t *payload,
|
||||||
|
int remaining_length,
|
||||||
|
int rc_expected,
|
||||||
|
int identifier,
|
||||||
|
uint8_t value_expected)
|
||||||
|
{
|
||||||
|
struct mosquitto__packet packet;
|
||||||
|
struct mqtt5__property *properties;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = remaining_length;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(rc, rc_expected);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, remaining_length);
|
||||||
|
if(properties){
|
||||||
|
CU_ASSERT_EQUAL(properties->identifier, identifier);
|
||||||
|
CU_ASSERT_EQUAL(properties->value.i8, value_expected);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties->next, NULL);
|
||||||
|
property__free_all(&properties);
|
||||||
|
}
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void duplicate_byte_helper(int identifier)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 4; /* Proplen = (Identifier + byte)*2 */
|
||||||
|
payload[1] = identifier;
|
||||||
|
payload[2] = 1;
|
||||||
|
payload[3] = identifier;
|
||||||
|
payload[4] = 0;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 5, MOSQ_ERR_PROTOCOL, identifier, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bad_byte_helper(int identifier)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = identifier;
|
||||||
|
payload[2] = 2; /* 0, 1 are only valid values */
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_PROTOCOL, identifier, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* NO PROPERTIES
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
static void TEST_no_properties(void)
|
||||||
|
{
|
||||||
|
struct mosquitto__packet packet;
|
||||||
|
struct mqtt5__property *properties = NULL;
|
||||||
|
uint8_t payload[5];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 1;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_truncated(void)
|
||||||
|
{
|
||||||
|
struct mosquitto__packet packet;
|
||||||
|
struct mqtt5__property *properties = NULL;
|
||||||
|
uint8_t payload[5];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Zero length packet */
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 0;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_PROTOCOL);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 0);
|
||||||
|
|
||||||
|
/* Proplen > 0 but not enough data */
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2;
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 1;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_PROTOCOL);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 1);
|
||||||
|
|
||||||
|
/* Proplen > 0 but not enough data */
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 4;
|
||||||
|
payload[1] = PROP_PAYLOAD_FORMAT_INDICATOR;
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 2;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_PROTOCOL);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* INVALID PROPERTY ID
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
static void TEST_invalid_property_id(void)
|
||||||
|
{
|
||||||
|
struct mosquitto__packet packet;
|
||||||
|
struct mqtt5__property *properties = NULL;
|
||||||
|
uint8_t payload[5];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* ID = 0 */
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 4;
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 2;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_MALFORMED_PACKET);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 2);
|
||||||
|
|
||||||
|
/* ID = 4 */
|
||||||
|
memset(&packet, 0, sizeof(struct mosquitto__packet));
|
||||||
|
memset(payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 4;
|
||||||
|
payload[1] = 4;
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.remaining_length = 2;
|
||||||
|
rc = property__read_all(&packet, &properties);
|
||||||
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_MALFORMED_PACKET);
|
||||||
|
CU_ASSERT_PTR_EQUAL(properties, NULL);
|
||||||
|
CU_ASSERT_EQUAL(packet.pos, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* SINGLE PROPERTIES
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
static void TEST_single_payload_format_indicator(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_PAYLOAD_FORMAT_INDICATOR;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_PAYLOAD_FORMAT_INDICATOR, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_request_problem_information(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_REQUEST_PROBLEM_INFO;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_REQUEST_PROBLEM_INFO, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_request_response_information(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_REQUEST_RESPONSE_INFO;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_REQUEST_RESPONSE_INFO, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_maximum_qos(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_MAXIMUM_QOS;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_MAXIMUM_QOS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_retain_available(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_RETAIN_AVAILABLE;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_RETAIN_AVAILABLE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_wildcard_subscription_available(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_WILDCARD_SUB_AVAILABLE;
|
||||||
|
payload[2] = 0;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_WILDCARD_SUB_AVAILABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_subscription_identifier_available(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_SUBSCRIPTION_ID_AVAILABLE;
|
||||||
|
payload[2] = 0;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_SUBSCRIPTION_ID_AVAILABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_single_shared_subscription_available(void)
|
||||||
|
{
|
||||||
|
uint8_t payload[20];
|
||||||
|
|
||||||
|
memset(&payload, 0, sizeof(payload));
|
||||||
|
payload[0] = 2; /* Proplen = Identifier + byte */
|
||||||
|
payload[1] = PROP_SHARED_SUB_AVAILABLE;
|
||||||
|
payload[2] = 1;
|
||||||
|
|
||||||
|
byte_prop_read_helper(payload, 3, MOSQ_ERR_SUCCESS, PROP_SHARED_SUB_AVAILABLE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* DUPLICATE PROPERTIES
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
static void TEST_duplicate_payload_format_indicator(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_PAYLOAD_FORMAT_INDICATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_request_problem_information(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_REQUEST_PROBLEM_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_request_response_information(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_REQUEST_RESPONSE_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_maximum_qos(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_MAXIMUM_QOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_retain_available(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_RETAIN_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_wildcard_subscription_available(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_WILDCARD_SUB_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_subscription_identifier_available(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_SUBSCRIPTION_ID_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_duplicate_shared_subscription_available(void)
|
||||||
|
{
|
||||||
|
duplicate_byte_helper(PROP_SHARED_SUB_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* BAD PROPERTY VALUES
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
static void TEST_bad_request_problem_information(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_REQUEST_PROBLEM_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_request_response_information(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_REQUEST_RESPONSE_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_maximum_qos(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_MAXIMUM_QOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_retain_available(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_RETAIN_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_wildcard_sub_available(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_WILDCARD_SUB_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_subscription_id_available(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_SUBSCRIPTION_ID_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TEST_bad_shared_sub_available(void)
|
||||||
|
{
|
||||||
|
bad_byte_helper(PROP_SHARED_SUB_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
* TEST SUITE SETUP
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
int init_property_read_tests(void)
|
||||||
|
{
|
||||||
|
CU_pSuite test_suite = NULL;
|
||||||
|
|
||||||
|
test_suite = CU_add_suite("Property read", NULL, NULL);
|
||||||
|
if(!test_suite){
|
||||||
|
printf("Error adding CUnit Property read test suite.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0
|
||||||
|
|| !CU_add_test(test_suite, "Truncated packet", TEST_truncated)
|
||||||
|
|| !CU_add_test(test_suite, "Invalid property ID", TEST_invalid_property_id)
|
||||||
|
|| !CU_add_test(test_suite, "No properties", TEST_no_properties)
|
||||||
|
|| !CU_add_test(test_suite, "Single Payload Format Indicator", TEST_single_payload_format_indicator)
|
||||||
|
|| !CU_add_test(test_suite, "Single Request Problem Information", TEST_single_request_problem_information)
|
||||||
|
|| !CU_add_test(test_suite, "Single Request Response Information", TEST_single_request_response_information)
|
||||||
|
|| !CU_add_test(test_suite, "Single Maximum QoS", TEST_single_maximum_qos)
|
||||||
|
|| !CU_add_test(test_suite, "Single Retain Available", TEST_single_retain_available)
|
||||||
|
|| !CU_add_test(test_suite, "Single Wildcard Subscription Available", TEST_single_wildcard_subscription_available)
|
||||||
|
|| !CU_add_test(test_suite, "Single Subscription Identifier Available", TEST_single_subscription_identifier_available)
|
||||||
|
|| !CU_add_test(test_suite, "Single Shared Subscription Available", TEST_single_shared_subscription_available)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Payload Format Indicator", TEST_duplicate_payload_format_indicator)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Request Problem Information", TEST_duplicate_request_problem_information)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Request Response Information", TEST_duplicate_request_response_information)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Maximum QoS", TEST_duplicate_maximum_qos)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Retain Available", TEST_duplicate_retain_available)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Wildcard Subscription Available", TEST_duplicate_wildcard_subscription_available)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Subscription Identifier Available", TEST_duplicate_subscription_identifier_available)
|
||||||
|
|| !CU_add_test(test_suite, "Duplicate Shared Subscription Available", TEST_duplicate_shared_subscription_available)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Request Problem Information", TEST_bad_request_problem_information)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Request Response Information", TEST_bad_request_response_information)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Maximum QoS", TEST_bad_maximum_qos)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Retain Available", TEST_bad_retain_available)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Wildcard Subscription Available", TEST_bad_wildcard_sub_available)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Subscription Identifier Available", TEST_bad_subscription_id_available)
|
||||||
|
|| !CU_add_test(test_suite, "Bad Shared Subscription Available", TEST_bad_shared_sub_available)
|
||||||
|
){
|
||||||
|
|
||||||
|
printf("Error adding Property read CUnit tests.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
test/unit/stubs.c
Normal file
6
test/unit/stubs.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <logging_mosq.h>
|
||||||
|
|
||||||
|
int log__printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
int init_datatype_read_tests(void);
|
int init_datatype_read_tests(void);
|
||||||
int init_datatype_write_tests(void);
|
int init_datatype_write_tests(void);
|
||||||
|
int init_property_read_tests(void);
|
||||||
int init_utf8_tests(void);
|
int init_utf8_tests(void);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -19,6 +20,7 @@ int main(int argc, char *argv[])
|
|||||||
|| init_utf8_tests()
|
|| init_utf8_tests()
|
||||||
|| init_datatype_read_tests()
|
|| init_datatype_read_tests()
|
||||||
|| init_datatype_write_tests()
|
|| init_datatype_write_tests()
|
||||||
|
|| init_property_read_tests()
|
||||||
){
|
){
|
||||||
|
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
|
Loading…
Reference in New Issue
Block a user