mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-02-06 02:52:07 +08:00
1252 lines
30 KiB
C
1252 lines
30 KiB
C
/*
|
|
Copyright (c) 2018-2021 Roger Light <roger@atchoo.org>
|
|
|
|
All rights reserved. This program and the accompanying materials
|
|
are made available under the terms of the Eclipse Public License 2.0
|
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
|
|
The Eclipse Public License is available at
|
|
https://www.eclipse.org/legal/epl-2.0/
|
|
and the Eclipse Distribution License is available at
|
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
|
|
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
|
|
|
Contributors:
|
|
Roger Light - initial implementation and documentation.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifndef WIN32
|
|
# include <strings.h>
|
|
#endif
|
|
|
|
#include "mosquitto.h"
|
|
#include "property_common.h"
|
|
|
|
|
|
void mosquitto_property_free(mosquitto_property **property)
|
|
{
|
|
if(!property || !(*property)){
|
|
return;
|
|
}
|
|
|
|
switch((*property)->property_type){
|
|
case MQTT_PROP_TYPE_STRING:
|
|
mosquitto_FREE((*property)->value.s.v);
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_BINARY:
|
|
mosquitto_FREE((*property)->value.bin.v);
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_STRING_PAIR:
|
|
mosquitto_FREE((*property)->name.v);
|
|
mosquitto_FREE((*property)->value.s.v);
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_BYTE:
|
|
case MQTT_PROP_TYPE_INT16:
|
|
case MQTT_PROP_TYPE_INT32:
|
|
case MQTT_PROP_TYPE_VARINT:
|
|
/* Nothing to free */
|
|
break;
|
|
}
|
|
|
|
mosquitto_FREE(*property);
|
|
}
|
|
|
|
|
|
BROKER_EXPORT void mosquitto_property_free_all(mosquitto_property **property)
|
|
{
|
|
mosquitto_property *p, *next;
|
|
|
|
if(!property){
|
|
return;
|
|
}
|
|
|
|
p = *property;
|
|
while(p){
|
|
next = p->next;
|
|
mosquitto_property_free(&p);
|
|
p = next;
|
|
}
|
|
*property = NULL;
|
|
}
|
|
|
|
|
|
unsigned int mosquitto_property_get_length(const mosquitto_property *property)
|
|
{
|
|
if(!property){
|
|
return 0;
|
|
}
|
|
|
|
switch(property->property_type){
|
|
case MQTT_PROP_TYPE_BYTE:
|
|
return 2; /* 1 (identifier) + 1 byte */
|
|
|
|
case MQTT_PROP_TYPE_INT16:
|
|
return 3; /* 1 (identifier) + 2 bytes */
|
|
|
|
case MQTT_PROP_TYPE_INT32:
|
|
return 5; /* 1 (identifier) + 4 bytes */
|
|
|
|
case MQTT_PROP_TYPE_VARINT:
|
|
if(property->value.varint < 128){
|
|
return 2;
|
|
}else if(property->value.varint < 16384){
|
|
return 3;
|
|
}else if(property->value.varint < 2097152){
|
|
return 4;
|
|
}else if(property->value.varint < 268435456){
|
|
return 5;
|
|
}else{
|
|
return 0;
|
|
}
|
|
|
|
case MQTT_PROP_TYPE_BINARY:
|
|
return 3U + property->value.bin.len; /* 1 + 2 bytes (len) + X bytes (payload) */
|
|
|
|
case MQTT_PROP_TYPE_STRING:
|
|
return 3U + property->value.s.len; /* 1 + 2 bytes (len) + X bytes (string) */
|
|
|
|
case MQTT_PROP_TYPE_STRING_PAIR:
|
|
return 5U + property->value.s.len + property->name.len; /* 1 + 2*(2 bytes (len) + X bytes (string))*/
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
unsigned int mosquitto_property_get_length_all(const mosquitto_property *property)
|
|
{
|
|
const mosquitto_property *p;
|
|
unsigned int len = 0;
|
|
|
|
p = property;
|
|
while(p){
|
|
len += mosquitto_property_get_length(p);
|
|
p = p->next;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_check_command(int command, int identifier)
|
|
{
|
|
switch(identifier){
|
|
case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
|
|
case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
|
|
case MQTT_PROP_CONTENT_TYPE:
|
|
case MQTT_PROP_RESPONSE_TOPIC:
|
|
case MQTT_PROP_CORRELATION_DATA:
|
|
if(command != CMD_PUBLISH && command != CMD_WILL){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
|
|
if(command != CMD_PUBLISH && command != CMD_SUBSCRIBE){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
|
|
if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_DISCONNECT){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_AUTHENTICATION_METHOD:
|
|
case MQTT_PROP_AUTHENTICATION_DATA:
|
|
if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_AUTH){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
|
|
case MQTT_PROP_SERVER_KEEP_ALIVE:
|
|
case MQTT_PROP_RESPONSE_INFORMATION:
|
|
case MQTT_PROP_MAXIMUM_QOS:
|
|
case MQTT_PROP_RETAIN_AVAILABLE:
|
|
case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
|
|
case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
|
|
case MQTT_PROP_SHARED_SUB_AVAILABLE:
|
|
if(command != CMD_CONNACK){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_WILL_DELAY_INTERVAL:
|
|
if(command != CMD_WILL){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
|
|
case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
|
|
if(command != CMD_CONNECT){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_SERVER_REFERENCE:
|
|
if(command != CMD_CONNACK && command != CMD_DISCONNECT){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_REASON_STRING:
|
|
if(command == CMD_CONNECT || command == CMD_PUBLISH || command == CMD_SUBSCRIBE || command == CMD_UNSUBSCRIBE){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_RECEIVE_MAXIMUM:
|
|
case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
|
|
case MQTT_PROP_MAXIMUM_PACKET_SIZE:
|
|
if(command != CMD_CONNECT && command != CMD_CONNACK){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_TOPIC_ALIAS:
|
|
if(command != CMD_PUBLISH){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_USER_PROPERTY:
|
|
break;
|
|
|
|
default:
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const char *mosquitto_property_identifier_to_string(int identifier)
|
|
{
|
|
switch(identifier){
|
|
case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
|
|
return "payload-format-indicator";
|
|
case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL:
|
|
return "message-expiry-interval";
|
|
case MQTT_PROP_CONTENT_TYPE:
|
|
return "content-type";
|
|
case MQTT_PROP_RESPONSE_TOPIC:
|
|
return "response-topic";
|
|
case MQTT_PROP_CORRELATION_DATA:
|
|
return "correlation-data";
|
|
case MQTT_PROP_SUBSCRIPTION_IDENTIFIER:
|
|
return "subscription-identifier";
|
|
case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
|
|
return "session-expiry-interval";
|
|
case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER:
|
|
return "assigned-client-identifier";
|
|
case MQTT_PROP_SERVER_KEEP_ALIVE:
|
|
return "server-keep-alive";
|
|
case MQTT_PROP_AUTHENTICATION_METHOD:
|
|
return "authentication-method";
|
|
case MQTT_PROP_AUTHENTICATION_DATA:
|
|
return "authentication-data";
|
|
case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:
|
|
return "request-problem-information";
|
|
case MQTT_PROP_WILL_DELAY_INTERVAL:
|
|
return "will-delay-interval";
|
|
case MQTT_PROP_REQUEST_RESPONSE_INFORMATION:
|
|
return "request-response-information";
|
|
case MQTT_PROP_RESPONSE_INFORMATION:
|
|
return "response-information";
|
|
case MQTT_PROP_SERVER_REFERENCE:
|
|
return "server-reference";
|
|
case MQTT_PROP_REASON_STRING:
|
|
return "reason-string";
|
|
case MQTT_PROP_RECEIVE_MAXIMUM:
|
|
return "receive-maximum";
|
|
case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
|
|
return "topic-alias-maximum";
|
|
case MQTT_PROP_TOPIC_ALIAS:
|
|
return "topic-alias";
|
|
case MQTT_PROP_MAXIMUM_QOS:
|
|
return "maximum-qos";
|
|
case MQTT_PROP_RETAIN_AVAILABLE:
|
|
return "retain-available";
|
|
case MQTT_PROP_USER_PROPERTY:
|
|
return "user-property";
|
|
case MQTT_PROP_MAXIMUM_PACKET_SIZE:
|
|
return "maximum-packet-size";
|
|
case MQTT_PROP_WILDCARD_SUB_AVAILABLE:
|
|
return "wildcard-subscription-available";
|
|
case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE:
|
|
return "subscription-identifier-available";
|
|
case MQTT_PROP_SHARED_SUB_AVAILABLE:
|
|
return "shared-subscription-available";
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type)
|
|
{
|
|
if(!propname){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
if(!strcasecmp(propname, "payload-format-indicator")){
|
|
*identifier = MQTT_PROP_PAYLOAD_FORMAT_INDICATOR;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "message-expiry-interval")){
|
|
*identifier = MQTT_PROP_MESSAGE_EXPIRY_INTERVAL;
|
|
*type = MQTT_PROP_TYPE_INT32;
|
|
}else if(!strcasecmp(propname, "content-type")){
|
|
*identifier = MQTT_PROP_CONTENT_TYPE;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "response-topic")){
|
|
*identifier = MQTT_PROP_RESPONSE_TOPIC;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "correlation-data")){
|
|
*identifier = MQTT_PROP_CORRELATION_DATA;
|
|
*type = MQTT_PROP_TYPE_BINARY;
|
|
}else if(!strcasecmp(propname, "subscription-identifier")){
|
|
*identifier = MQTT_PROP_SUBSCRIPTION_IDENTIFIER;
|
|
*type = MQTT_PROP_TYPE_VARINT;
|
|
}else if(!strcasecmp(propname, "session-expiry-interval")){
|
|
*identifier = MQTT_PROP_SESSION_EXPIRY_INTERVAL;
|
|
*type = MQTT_PROP_TYPE_INT32;
|
|
}else if(!strcasecmp(propname, "assigned-client-identifier")){
|
|
*identifier = MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "server-keep-alive")){
|
|
*identifier = MQTT_PROP_SERVER_KEEP_ALIVE;
|
|
*type = MQTT_PROP_TYPE_INT16;
|
|
}else if(!strcasecmp(propname, "authentication-method")){
|
|
*identifier = MQTT_PROP_AUTHENTICATION_METHOD;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "authentication-data")){
|
|
*identifier = MQTT_PROP_AUTHENTICATION_DATA;
|
|
*type = MQTT_PROP_TYPE_BINARY;
|
|
}else if(!strcasecmp(propname, "request-problem-information")){
|
|
*identifier = MQTT_PROP_REQUEST_PROBLEM_INFORMATION;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "will-delay-interval")){
|
|
*identifier = MQTT_PROP_WILL_DELAY_INTERVAL;
|
|
*type = MQTT_PROP_TYPE_INT32;
|
|
}else if(!strcasecmp(propname, "request-response-information")){
|
|
*identifier = MQTT_PROP_REQUEST_RESPONSE_INFORMATION;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "response-information")){
|
|
*identifier = MQTT_PROP_RESPONSE_INFORMATION;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "server-reference")){
|
|
*identifier = MQTT_PROP_SERVER_REFERENCE;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "reason-string")){
|
|
*identifier = MQTT_PROP_REASON_STRING;
|
|
*type = MQTT_PROP_TYPE_STRING;
|
|
}else if(!strcasecmp(propname, "receive-maximum")){
|
|
*identifier = MQTT_PROP_RECEIVE_MAXIMUM;
|
|
*type = MQTT_PROP_TYPE_INT16;
|
|
}else if(!strcasecmp(propname, "topic-alias-maximum")){
|
|
*identifier = MQTT_PROP_TOPIC_ALIAS_MAXIMUM;
|
|
*type = MQTT_PROP_TYPE_INT16;
|
|
}else if(!strcasecmp(propname, "topic-alias")){
|
|
*identifier = MQTT_PROP_TOPIC_ALIAS;
|
|
*type = MQTT_PROP_TYPE_INT16;
|
|
}else if(!strcasecmp(propname, "maximum-qos")){
|
|
*identifier = MQTT_PROP_MAXIMUM_QOS;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "retain-available")){
|
|
*identifier = MQTT_PROP_RETAIN_AVAILABLE;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "user-property")){
|
|
*identifier = MQTT_PROP_USER_PROPERTY;
|
|
*type = MQTT_PROP_TYPE_STRING_PAIR;
|
|
}else if(!strcasecmp(propname, "maximum-packet-size")){
|
|
*identifier = MQTT_PROP_MAXIMUM_PACKET_SIZE;
|
|
*type = MQTT_PROP_TYPE_INT32;
|
|
}else if(!strcasecmp(propname, "wildcard-subscription-available")){
|
|
*identifier = MQTT_PROP_WILDCARD_SUB_AVAILABLE;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "subscription-identifier-available")){
|
|
*identifier = MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else if(!strcasecmp(propname, "shared-subscription-available")){
|
|
*identifier = MQTT_PROP_SHARED_SUB_AVAILABLE;
|
|
*type = MQTT_PROP_TYPE_BYTE;
|
|
}else{
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
static void property__add(mosquitto_property **proplist, struct mqtt5__property *prop)
|
|
{
|
|
mosquitto_property *p;
|
|
|
|
if(!(*proplist)){
|
|
*proplist = prop;
|
|
}
|
|
|
|
p = *proplist;
|
|
while(p->next){
|
|
p = p->next;
|
|
}
|
|
p->next = prop;
|
|
prop->next = NULL;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, uint8_t value)
|
|
{
|
|
mosquitto_property *prop;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR
|
|
&& identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION
|
|
&& identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION
|
|
&& identifier != MQTT_PROP_MAXIMUM_QOS
|
|
&& identifier != MQTT_PROP_RETAIN_AVAILABLE
|
|
&& identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE
|
|
&& identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE
|
|
&& identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->value.i8 = value;
|
|
prop->property_type = MQTT_PROP_TYPE_BYTE;
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier, uint16_t value)
|
|
{
|
|
mosquitto_property *prop;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_SERVER_KEEP_ALIVE
|
|
&& identifier != MQTT_PROP_RECEIVE_MAXIMUM
|
|
&& identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM
|
|
&& identifier != MQTT_PROP_TOPIC_ALIAS){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->value.i16 = value;
|
|
prop->property_type = MQTT_PROP_TYPE_INT16;
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier, uint32_t value)
|
|
{
|
|
mosquitto_property *prop;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL
|
|
&& identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL
|
|
&& identifier != MQTT_PROP_WILL_DELAY_INTERVAL
|
|
&& identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->value.i32 = value;
|
|
prop->property_type = MQTT_PROP_TYPE_INT32;
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value)
|
|
{
|
|
mosquitto_property *prop;
|
|
|
|
if(!proplist || value > MQTT_MAX_PAYLOAD){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->value.varint = value;
|
|
prop->property_type = MQTT_PROP_TYPE_VARINT;
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier, const void *value, uint16_t len)
|
|
{
|
|
mosquitto_property *prop;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_CORRELATION_DATA
|
|
&& identifier != MQTT_PROP_AUTHENTICATION_DATA){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->property_type = MQTT_PROP_TYPE_BINARY;
|
|
|
|
if(len){
|
|
prop->value.bin.v = mosquitto_malloc(len);
|
|
if(!prop->value.bin.v){
|
|
mosquitto_FREE(prop);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
memcpy(prop->value.bin.v, value, len);
|
|
prop->value.bin.len = len;
|
|
}
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value)
|
|
{
|
|
mosquitto_property *prop;
|
|
size_t slen = 0;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(value){
|
|
slen = strlen(value);
|
|
if(mosquitto_validate_utf8(value, (int)slen)){
|
|
return MOSQ_ERR_MALFORMED_UTF8;
|
|
}
|
|
}
|
|
|
|
if(identifier != MQTT_PROP_CONTENT_TYPE
|
|
&& identifier != MQTT_PROP_RESPONSE_TOPIC
|
|
&& identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER
|
|
&& identifier != MQTT_PROP_AUTHENTICATION_METHOD
|
|
&& identifier != MQTT_PROP_RESPONSE_INFORMATION
|
|
&& identifier != MQTT_PROP_SERVER_REFERENCE
|
|
&& identifier != MQTT_PROP_REASON_STRING){
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->property_type = MQTT_PROP_TYPE_STRING;
|
|
if(value && slen > 0){
|
|
prop->value.s.v = mosquitto_strdup(value);
|
|
if(!prop->value.s.v){
|
|
mosquitto_FREE(prop);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
prop->value.s.len = (uint16_t)slen;
|
|
}
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value)
|
|
{
|
|
mosquitto_property *prop;
|
|
size_t slen_name = 0, slen_value = 0;
|
|
|
|
if(!proplist){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(identifier != MQTT_PROP_USER_PROPERTY){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
if(name){
|
|
slen_name = strlen(name);
|
|
if(mosquitto_validate_utf8(name, (int)slen_name)){
|
|
return MOSQ_ERR_MALFORMED_UTF8;
|
|
}
|
|
}
|
|
if(value){
|
|
if(mosquitto_validate_utf8(value, (int)slen_value)){
|
|
return MOSQ_ERR_MALFORMED_UTF8;
|
|
}
|
|
}
|
|
|
|
prop = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!prop){
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
prop->client_generated = true;
|
|
prop->identifier = identifier;
|
|
prop->property_type = MQTT_PROP_TYPE_STRING_PAIR;
|
|
|
|
if(name){
|
|
prop->name.v = mosquitto_strdup(name);
|
|
if(!prop->name.v){
|
|
mosquitto_FREE(prop);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
prop->name.len = (uint16_t)strlen(name);
|
|
}
|
|
|
|
if(value){
|
|
prop->value.s.v = mosquitto_strdup(value);
|
|
if(!prop->value.s.v){
|
|
mosquitto_FREE(prop->name.v);
|
|
mosquitto_FREE(prop);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
prop->value.s.len = (uint16_t)strlen(value);
|
|
}
|
|
|
|
property__add(proplist, prop);
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties)
|
|
{
|
|
const mosquitto_property *p, *tail;
|
|
int rc;
|
|
|
|
p = properties;
|
|
|
|
while(p){
|
|
/* Validity checks */
|
|
if(p->identifier == MQTT_PROP_REQUEST_PROBLEM_INFORMATION
|
|
|| p->identifier == MQTT_PROP_PAYLOAD_FORMAT_INDICATOR
|
|
|| p->identifier == MQTT_PROP_REQUEST_RESPONSE_INFORMATION
|
|
|| p->identifier == MQTT_PROP_MAXIMUM_QOS
|
|
|| p->identifier == MQTT_PROP_RETAIN_AVAILABLE
|
|
|| p->identifier == MQTT_PROP_WILDCARD_SUB_AVAILABLE
|
|
|| p->identifier == MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE
|
|
|| p->identifier == MQTT_PROP_SHARED_SUB_AVAILABLE){
|
|
|
|
if(p->value.i8 > 1){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
}else if(p->identifier == MQTT_PROP_MAXIMUM_PACKET_SIZE){
|
|
if(p->value.i32 == 0){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
}else if(p->identifier == MQTT_PROP_RECEIVE_MAXIMUM
|
|
|| p->identifier == MQTT_PROP_TOPIC_ALIAS){
|
|
|
|
if(p->value.i16 == 0){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
}else if(p->identifier == MQTT_PROP_RESPONSE_TOPIC){
|
|
if(mosquitto_pub_topic_check(p->value.s.v) != MOSQ_ERR_SUCCESS){
|
|
return MOSQ_ERR_PROTOCOL;
|
|
}
|
|
}
|
|
|
|
/* Check for properties on incorrect commands */
|
|
rc = mosquitto_property_check_command(command, p->identifier);
|
|
if(rc){
|
|
return rc;
|
|
}
|
|
|
|
/* Check for duplicates */
|
|
if(p->identifier != MQTT_PROP_USER_PROPERTY){
|
|
tail = p->next;
|
|
while(tail){
|
|
if(p->identifier == tail->identifier){
|
|
return MOSQ_ERR_DUPLICATE_PROPERTY;
|
|
}
|
|
tail = tail->next;
|
|
}
|
|
}
|
|
|
|
p = p->next;
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
static const mosquitto_property *property__get_property(const mosquitto_property *proplist, int identifier, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
bool is_first = true;
|
|
|
|
p = proplist;
|
|
|
|
while(p){
|
|
if(p->identifier == identifier){
|
|
if(!is_first || !skip_first){
|
|
return p;
|
|
}
|
|
is_first = false;
|
|
}
|
|
p = p->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_identifier(const mosquitto_property *property)
|
|
{
|
|
if(property == NULL){
|
|
return 0;
|
|
}
|
|
|
|
return property->identifier;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_type(const mosquitto_property *property)
|
|
{
|
|
if(property == NULL){
|
|
return 0;
|
|
}
|
|
|
|
return property->property_type;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist)
|
|
{
|
|
if(proplist == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
return proplist->next;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_byte(const mosquitto_property *proplist, int identifier, uint8_t *value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR
|
|
&& p->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION
|
|
&& p->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION
|
|
&& p->identifier != MQTT_PROP_MAXIMUM_QOS
|
|
&& p->identifier != MQTT_PROP_RETAIN_AVAILABLE
|
|
&& p->identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE
|
|
&& p->identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE
|
|
&& p->identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*value = p->value.i8;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_int16(const mosquitto_property *proplist, int identifier, uint16_t *value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_SERVER_KEEP_ALIVE
|
|
&& p->identifier != MQTT_PROP_RECEIVE_MAXIMUM
|
|
&& p->identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM
|
|
&& p->identifier != MQTT_PROP_TOPIC_ALIAS){
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*value = p->value.i16;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_int32(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL
|
|
&& p->identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL
|
|
&& p->identifier != MQTT_PROP_WILL_DELAY_INTERVAL
|
|
&& p->identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*value = p->value.i32;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_varint(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*value = p->value.varint;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, uint16_t *len, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist || (value && !len) || (!value && len)){
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*value = NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_CORRELATION_DATA
|
|
&& p->identifier != MQTT_PROP_AUTHENTICATION_DATA){
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
*len = p->value.bin.len;
|
|
if(p->value.bin.len){
|
|
*value = mosquitto_calloc(1, *len + 1U);
|
|
if(!(*value)){
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(*value, p->value.bin.v, *len);
|
|
}else{
|
|
*value = NULL;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_string(const mosquitto_property *proplist, int identifier, char **value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_CONTENT_TYPE
|
|
&& p->identifier != MQTT_PROP_RESPONSE_TOPIC
|
|
&& p->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER
|
|
&& p->identifier != MQTT_PROP_AUTHENTICATION_METHOD
|
|
&& p->identifier != MQTT_PROP_RESPONSE_INFORMATION
|
|
&& p->identifier != MQTT_PROP_SERVER_REFERENCE
|
|
&& p->identifier != MQTT_PROP_REASON_STRING){
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if(value){
|
|
if(p->value.s.len){
|
|
*value = mosquitto_calloc(1, (size_t)p->value.s.len+1);
|
|
if(!(*value)){
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(*value, p->value.s.v, p->value.s.len);
|
|
}else{
|
|
*value = NULL;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT const mosquitto_property *mosquitto_property_read_string_pair(const mosquitto_property *proplist, int identifier, char **name, char **value, bool skip_first)
|
|
{
|
|
const mosquitto_property *p;
|
|
if(!proplist){
|
|
return NULL;
|
|
}
|
|
|
|
if(name){
|
|
*name = NULL;
|
|
}
|
|
if(value){
|
|
*value = NULL;
|
|
}
|
|
|
|
p = property__get_property(proplist, identifier, skip_first);
|
|
if(!p){
|
|
return NULL;
|
|
}
|
|
if(p->identifier != MQTT_PROP_USER_PROPERTY){
|
|
return NULL;
|
|
}
|
|
|
|
if(name){
|
|
if(p->name.len){
|
|
*name = mosquitto_calloc(1, (size_t)p->name.len+1);
|
|
if(!(*name)){
|
|
return NULL;
|
|
}
|
|
memcpy(*name, p->name.v, p->name.len);
|
|
}else{
|
|
*name = NULL;
|
|
}
|
|
}
|
|
|
|
if(value){
|
|
if(p->value.s.len){
|
|
*value = mosquitto_calloc(1, (size_t)p->value.s.len+1);
|
|
if(!(*value)){
|
|
if(name){
|
|
mosquitto_FREE(*name);
|
|
}
|
|
return NULL;
|
|
}
|
|
memcpy(*value, p->value.s.v, p->value.s.len);
|
|
}else{
|
|
*value = NULL;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property)
|
|
{
|
|
mosquitto_property *item, *item_prev = NULL;
|
|
|
|
if(proplist == NULL || property == NULL){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
item = *proplist;
|
|
while(item){
|
|
if(item == property){
|
|
if(item_prev == NULL){
|
|
*proplist = (*proplist)->next;
|
|
}else{
|
|
item_prev->next = item->next;
|
|
}
|
|
item->next = NULL;
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
item_prev = item;
|
|
item = item->next;
|
|
}
|
|
|
|
return MOSQ_ERR_NOT_FOUND;
|
|
}
|
|
|
|
|
|
BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const mosquitto_property *src)
|
|
{
|
|
mosquitto_property *pnew, *plast = NULL;
|
|
|
|
if(!src){
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
if(!dest){
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
*dest = NULL;
|
|
|
|
while(src){
|
|
pnew = mosquitto_calloc(1, sizeof(mosquitto_property));
|
|
if(!pnew){
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
if(plast){
|
|
plast->next = pnew;
|
|
}else{
|
|
*dest = pnew;
|
|
}
|
|
plast = pnew;
|
|
|
|
pnew->client_generated = src->client_generated;
|
|
pnew->identifier = src->identifier;
|
|
pnew->property_type = src->property_type;
|
|
switch(pnew->property_type){
|
|
case MQTT_PROP_TYPE_BYTE:
|
|
pnew->value.i8 = src->value.i8;
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_INT16:
|
|
pnew->value.i16 = src->value.i16;
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_INT32:
|
|
pnew->value.i32 = src->value.i32;
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_VARINT:
|
|
pnew->value.varint = src->value.varint;
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_STRING:
|
|
pnew->value.s.len = src->value.s.len;
|
|
pnew->value.s.v = src->value.s.v ? mosquitto_strdup(src->value.s.v) : (char *)mosquitto_calloc(1, 1);
|
|
if(!pnew->value.s.v){
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_BINARY:
|
|
pnew->value.bin.len = src->value.bin.len;
|
|
if(src->value.bin.len){
|
|
pnew->value.bin.v = mosquitto_malloc(pnew->value.bin.len);
|
|
if(!pnew->value.bin.v){
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
memcpy(pnew->value.bin.v, src->value.bin.v, pnew->value.bin.len);
|
|
}
|
|
break;
|
|
|
|
case MQTT_PROP_TYPE_STRING_PAIR:
|
|
pnew->value.s.len = src->value.s.len;
|
|
pnew->value.s.v = src->value.s.v ? mosquitto_strdup(src->value.s.v) : (char *)mosquitto_calloc(1, 1);
|
|
if(!pnew->value.s.v){
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
|
|
pnew->name.len = src->name.len;
|
|
pnew->name.v = src->name.v ? mosquitto_strdup(src->name.v) : (char *)mosquitto_calloc(1, 1);
|
|
if(!pnew->name.v){
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_NOMEM;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
mosquitto_property_free_all(dest);
|
|
return MOSQ_ERR_INVAL;
|
|
}
|
|
|
|
src = mosquitto_property_next(src);
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
}
|
|
|
|
|
|
uint8_t mosquitto_property_byte_value(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_BYTE){
|
|
return property->value.i8;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
uint16_t mosquitto_property_int16_value(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_INT16){
|
|
return property->value.i16;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t mosquitto_property_int32_value(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_INT32){
|
|
return property->value.i32;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t mosquitto_property_varint_value(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_VARINT){
|
|
return property->value.varint;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
const void *mosquitto_property_binary_value(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_BINARY){
|
|
return property->value.bin.v;
|
|
}else{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_BINARY){
|
|
return property->value.bin.len;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
const char *mosquitto_property_string_value(const mosquitto_property *property)
|
|
{
|
|
if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){
|
|
return property->value.s.v;
|
|
}else{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
uint16_t mosquitto_property_string_value_length(const mosquitto_property *property)
|
|
{
|
|
if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){
|
|
return property->value.s.len;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
const char *mosquitto_property_string_name(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){
|
|
return property->name.v;
|
|
}else{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
uint16_t mosquitto_property_string_name_length(const mosquitto_property *property)
|
|
{
|
|
if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){
|
|
return property->name.len;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Return the number of bytes we need to add on to the remaining length when
|
|
* encoding these properties. */
|
|
unsigned int mosquitto_property_get_remaining_length(const mosquitto_property *props)
|
|
{
|
|
unsigned int proplen, varbytes;
|
|
|
|
proplen = mosquitto_property_get_length_all(props);
|
|
varbytes = mosquitto_varint_bytes(proplen);
|
|
return proplen + varbytes;
|
|
}
|
|
|
|
|