Subscription identifier support.

This commit is contained in:
Roger A. Light 2018-12-20 15:32:43 +00:00
parent ef724e6d33
commit 7c3666d593
25 changed files with 109 additions and 74 deletions

View File

@ -123,7 +123,7 @@ int cfg_parse_property(struct mosq_config *cfg, int argc, char *argv[], int *idx
break;
case CMD_SUBSCRIBE:
if(identifier != MQTT_PROP_USER_PROPERTY){
if(identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER && identifier != MQTT_PROP_USER_PROPERTY){
fprintf(stderr, "Error: %s property not supported for %s in --property argument.\n\n", propname, cmdname);
return MOSQ_ERR_NOT_SUPPORTED;
}

View File

@ -93,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, outgoing_properties);
return send__publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false, outgoing_properties, NULL);
}else{
message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all));
if(!message) return MOSQ_ERR_NOMEM;
@ -133,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, outgoing_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, NULL);
}else{
message->state = mosq_ms_invalid;
pthread_mutex_unlock(&mosq->out_message_mutex);

View File

@ -168,7 +168,7 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos
local_property.next = NULL;
outgoing_properties = &local_property;
}
rc = mosquitto_property_check_all(CMD_DISCONNECT, outgoing_properties);
rc = mosquitto_property_check_all(CMD_CONNECT, outgoing_properties);
if(rc) return rc;
}

View File

@ -264,7 +264,7 @@ int message__remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_dir
}else if(cur->msg.qos == 2){
cur->state = mosq_ms_wait_for_pubrec;
}
rc = send__publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup, NULL);
rc = send__publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup, NULL, NULL);
if(rc){
pthread_mutex_unlock(&mosq->out_message_mutex);
return rc;
@ -334,7 +334,7 @@ void message__retry_check_actual(struct mosquitto *mosq, struct mosquitto_messag
case mosq_ms_publish_qos2:
messages->timestamp = now;
messages->dup = true;
send__publish(mosq, messages->msg.mid, messages->msg.topic, messages->msg.payloadlen, messages->msg.payload, messages->msg.qos, messages->msg.retain, messages->dup, NULL);
send__publish(mosq, messages->msg.mid, messages->msg.topic, messages->msg.payloadlen, messages->msg.payload, messages->msg.qos, messages->msg.retain, messages->dup, NULL, NULL);
break;
case mosq_ms_wait_for_pubrel:
messages->timestamp = now;

View File

@ -397,13 +397,15 @@ int property__write(struct mosquitto__packet *packet, const mosquitto_property *
}
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties)
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len)
{
int rc;
const mosquitto_property *p;
if(write_len){
rc = packet__write_varint(packet, property__get_length_all(properties));
if(rc) return rc;
}
p = properties;
while(p){

View File

@ -41,7 +41,7 @@ struct mqtt5__property {
int property__read_all(int command, struct mosquitto__packet *packet, mosquitto_property **property);
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *property);
int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *property, bool write_len);
void property__free(mosquitto_property **property);
int property__get_length(const mosquitto_property *property);

View File

@ -141,7 +141,7 @@ int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session
if(mosq->protocol == mosq_p_mqtt5){
/* Write properties */
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
/* Payload */
@ -153,7 +153,7 @@ int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session
if(will){
if(mosq->protocol == mosq_p_mqtt5){
/* Write will properties */
property__write_all(packet, mosq->will->properties);
property__write_all(packet, mosq->will->properties, true);
}
packet__write_string(packet, mosq->will->msg.topic, strlen(mosq->will->msg.topic));
packet__write_string(packet, (const char *)mosq->will->msg.payload, mosq->will->msg.payloadlen);

View File

@ -67,7 +67,7 @@ int send__disconnect(struct mosquitto *mosq, uint8_t reason_code, const mosquitt
}
if(mosq->protocol == mosq_p_mqtt5){
packet__write_byte(packet, reason_code);
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
return packet__queue(mosq, packet);

View File

@ -144,7 +144,7 @@ int send__command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid
if(mosq->protocol == mosq_p_mqtt5){
packet__write_byte(packet, reason_code);
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
return packet__queue(mosq, packet);

View File

@ -21,7 +21,7 @@ Contributors:
int send__simple_command(struct mosquitto *mosq, uint8_t command);
int send__command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup, uint8_t reason_code, const mosquitto_property *properties);
int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *properties);
int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props);
int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session, const mosquitto_property *properties);
int send__disconnect(struct mosquitto *mosq, uint8_t reason_code, const mosquitto_property *properties);
@ -29,7 +29,7 @@ int send__pingreq(struct mosquitto *mosq);
int send__pingresp(struct mosquitto *mosq);
int send__puback(struct mosquitto *mosq, uint16_t mid);
int send__pubcomp(struct mosquitto *mosq, uint16_t mid);
int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *properties);
int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props);
int send__pubrec(struct mosquitto *mosq, uint16_t mid);
int send__pubrel(struct mosquitto *mosq, uint16_t mid);
int send__subscribe(struct mosquitto *mosq, int *mid, int topic_count, char *const *const topic, int topic_qos, const mosquitto_property *properties);

View File

@ -37,7 +37,7 @@ Contributors:
#include "send_mosq.h"
int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *properties)
int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props)
{
#ifdef WITH_BROKER
size_t len;
@ -110,7 +110,7 @@ int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint3
}
log__printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, mapped_topic, (long)payloadlen);
G_PUB_BYTES_SENT_INC(payloadlen);
rc = send__real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup, properties);
rc = send__real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup, cmsg_props, store_props);
mosquitto__free(mapped_topic);
return rc;
}
@ -124,15 +124,15 @@ int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint3
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen);
#endif
return send__real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup, properties);
return send__real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup, cmsg_props, store_props);
}
int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *properties)
int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props)
{
struct mosquitto__packet *packet = NULL;
int packetlen;
int proplen, varbytes;
int proplen = 0, varbytes;
int rc;
assert(mosq);
@ -144,11 +144,14 @@ int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic,
}
if(qos > 0) packetlen += 2; /* For message id */
if(mosq->protocol == mosq_p_mqtt5){
proplen = property__get_length_all(properties);
proplen = 0;
proplen += property__get_length_all(cmsg_props);
proplen += property__get_length_all(store_props);
varbytes = packet__varint_bytes(proplen);
if(varbytes > 4){
/* FIXME - Properties too big, don't publish any - should remove some first really */
properties = NULL;
cmsg_props = NULL;
store_props = NULL;
}else{
packetlen += proplen + varbytes;
}
@ -175,7 +178,9 @@ int send__real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic,
}
if(mosq->protocol == mosq_p_mqtt5){
property__write_all(packet, properties);
packet__write_varint(packet, proplen);
property__write_all(packet, cmsg_props, false);
property__write_all(packet, store_props, false);
}
/* Payload */

View File

@ -72,7 +72,7 @@ int send__subscribe(struct mosquitto *mosq, int *mid, int topic_count, const cha
packet__write_uint16(packet, local_mid);
if(mosq->protocol == mosq_p_mqtt5){
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
/* Payload */

View File

@ -70,7 +70,7 @@ int send__unsubscribe(struct mosquitto *mosq, int *mid, const char *topic, const
if(mosq->protocol == mosq_p_mqtt5){
/* We don't use User Property yet. */
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
/* Payload */

View File

@ -149,6 +149,7 @@ int bridge__connect_step1(struct mosquitto_db *db, struct mosquitto *context)
context,
context->bridge->topics[i].local_topic,
context->bridge->topics[i].qos,
0,
MQTT_SUB_OPT_NO_LOCAL | MQTT_SUB_OPT_RETAIN_AS_PUBLISHED,
&db->subs) > 0){
return 1;
@ -322,6 +323,7 @@ int bridge__connect(struct mosquitto_db *db, struct mosquitto *context)
context,
context->bridge->topics[i].local_topic,
context->bridge->topics[i].qos,
0,
MQTT_SUB_OPT_NO_LOCAL | MQTT_SUB_OPT_RETAIN_AS_PUBLISHED,
&db->subs) > 0){
@ -329,7 +331,7 @@ int bridge__connect(struct mosquitto_db *db, struct mosquitto *context)
}
sub__retain_queue(db, context,
context->bridge->topics[i].local_topic,
context->bridge->topics[i].qos);
context->bridge->topics[i].qos, 0);
}
}

View File

@ -336,7 +336,7 @@ int db__message_delete(struct mosquitto_db *db, struct mosquitto *context, uint1
return MOSQ_ERR_SUCCESS;
}
int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored)
int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties)
{
struct mosquitto_client_msg *msg;
struct mosquitto_client_msg **msgs, **last_msg;
@ -362,6 +362,7 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
for(i=0; i<stored->dest_id_count; i++){
if(!strcmp(stored->dest_ids[i], context->id)){
/* We have already sent this message to this client. */
mosquitto_property_free_all(&properties);
return MOSQ_ERR_SUCCESS;
}
}
@ -370,9 +371,11 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
/* Client is not connected only queue messages with QoS>0. */
if(qos == 0 && !db->config->queue_qos0_messages){
if(!context->bridge){
mosquitto_property_free_all(&properties);
return 2;
}else{
if(context->bridge->start_type != bst_lazy){
mosquitto_property_free_all(&properties);
return 2;
}
}
@ -397,6 +400,7 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
if(qos == 2){
state = mosq_ms_wait_for_pubrel;
}else{
mosquitto_property_free_all(&properties);
return 1;
}
}
@ -412,6 +416,7 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
context->id);
}
G_MSGS_DROPPED_INC();
mosquitto_property_free_all(&properties);
return 2;
}
}else{
@ -425,6 +430,7 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
"Outgoing messages are being dropped for client %s.",
context->id);
}
mosquitto_property_free_all(&properties);
return 2;
}
}
@ -448,6 +454,7 @@ int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint1
msg->dup = false;
msg->qos = qos;
msg->retain = retain;
msg->properties = properties;
if (state == mosq_ms_queued){
msgs = &(context->queued_msgs);
@ -875,7 +882,7 @@ int db__message_write(struct mosquitto_db *db, struct mosquitto *context)
uint32_t payloadlen;
const void *payload;
int msg_count = 0;
mosquitto_property *properties;
mosquitto_property *cmsg_props = NULL, *store_props = NULL;
time_t now;
if(!context || context->sock == INVALID_SOCKET
@ -903,11 +910,12 @@ int db__message_write(struct mosquitto_db *db, struct mosquitto *context)
qos = tail->qos;
payloadlen = tail->store->payloadlen;
payload = UHPA_ACCESS_PAYLOAD(tail->store);
properties = tail->store->properties;
cmsg_props = tail->properties;
store_props = tail->store->properties;
switch(tail->state){
case mosq_ms_publish_qos0:
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, properties);
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, cmsg_props, store_props);
if(!rc){
db__message_remove(db, context, &tail, last);
}else{
@ -916,7 +924,7 @@ int db__message_write(struct mosquitto_db *db, struct mosquitto *context)
break;
case mosq_ms_publish_qos1:
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, properties);
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, cmsg_props, store_props);
if(!rc){
tail->timestamp = mosquitto_time();
tail->dup = 1; /* Any retry attempts are a duplicate. */
@ -929,7 +937,7 @@ int db__message_write(struct mosquitto_db *db, struct mosquitto *context)
break;
case mosq_ms_publish_qos2:
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, properties);
rc = send__publish(context, mid, topic, payloadlen, payload, qos, retain, retries, cmsg_props, store_props);
if(!rc){
tail->timestamp = mosquitto_time();
tail->dup = 1; /* Any retry attempts are a duplicate. */

View File

@ -59,7 +59,7 @@ int handle__connack(struct mosquitto_db *db, struct mosquitto *context)
if(context->bridge->notification_topic){
if(!context->bridge->notifications_local_only){
if(send__real_publish(context, mosquitto__mid_generate(context),
context->bridge->notification_topic, 1, &notification_payload, 1, true, 0, NULL)){
context->bridge->notification_topic, 1, &notification_payload, 1, true, 0, NULL, NULL)){
return 1;
}
@ -74,7 +74,7 @@ int handle__connack(struct mosquitto_db *db, struct mosquitto *context)
notification_payload = '1';
if(!context->bridge->notifications_local_only){
if(send__real_publish(context, mosquitto__mid_generate(context),
notification_topic, 1, &notification_payload, 1, true, 0, NULL)){
notification_topic, 1, &notification_payload, 1, true, 0, NULL, NULL)){
mosquitto__free(notification_topic);
return 1;
@ -107,11 +107,12 @@ int handle__connack(struct mosquitto_db *db, struct mosquitto *context)
context,
context->bridge->topics[i].local_topic,
context->bridge->topics[i].qos,
0,
MQTT_SUB_OPT_NO_LOCAL | MQTT_SUB_OPT_RETAIN_AS_PUBLISHED,
&db->subs)) return 1;
sub__retain_queue(db, context,
context->bridge->topics[i].local_topic,
context->bridge->topics[i].qos);
context->bridge->topics[i].qos, 0);
}
}
}

View File

@ -279,7 +279,7 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
break;
case 2:
if(!dup){
res = db__message_insert(db, context, mid, mosq_md_in, qos, retain, stored);
res = db__message_insert(db, context, mid, mosq_md_in, qos, retain, stored, NULL);
}else{
res = 0;
}
@ -308,7 +308,7 @@ process_bad_message:
if(db__message_store(db, context->id, mid, NULL, qos, 0, NULL, false, &stored, 0, NULL, 0)){
return 1;
}
res = db__message_insert(db, context, mid, mosq_md_in, qos, false, stored);
res = db__message_insert(db, context, mid, mosq_md_in, qos, false, stored, NULL);
}else{
res = 0;
}

View File

@ -34,6 +34,7 @@ int handle__subscribe(struct mosquitto_db *db, struct mosquitto *context)
uint16_t mid;
char *sub;
uint8_t subscription_options;
uint32_t subscription_identifier = 0;
uint8_t qos;
uint8_t retain_handling = 0;
uint8_t *payload = NULL, *tmp_payload;
@ -57,9 +58,20 @@ int handle__subscribe(struct mosquitto_db *db, struct mosquitto *context)
if(context->protocol == mosq_p_mqtt5){
rc = property__read_all(CMD_SUBSCRIBE, &context->in_packet, &properties);
if(rc) return rc;
if(mosquitto_property_read_varint(properties, MQTT_PROP_SUBSCRIPTION_IDENTIFIER,
&subscription_identifier, false)){
/* If the identifier was force set to 0, this is an error */
if(subscription_identifier == 0){
mosquitto_property_free_all(&properties);
return MOSQ_ERR_PROTOCOL;
}
}
mosquitto_property_free_all(&properties);
/* Note - User Property not handled */
}
mosquitto_property_free_all(&properties); /* FIXME - TEMPORARY UNTIL PROPERTIES PROCESSED */
while(context->in_packet.pos < context->in_packet.remaining_length){
sub = NULL;
@ -147,20 +159,20 @@ int handle__subscribe(struct mosquitto_db *db, struct mosquitto *context)
}
if(qos != 0x80){
rc2 = sub__add(db, context, sub, qos, subscription_options, &db->subs);
rc2 = sub__add(db, context, sub, qos, subscription_identifier, subscription_options, &db->subs);
if(rc2 > 0){
mosquitto__free(sub);
return rc2;
}
if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt31){
if(rc2 == MOSQ_ERR_SUCCESS || rc2 == MOSQ_ERR_SUB_EXISTS){
if(sub__retain_queue(db, context, sub, qos)) rc = 1;
if(sub__retain_queue(db, context, sub, qos, 0)) rc = 1;
}
}else{
if((retain_handling == MQTT_SUB_OPT_SEND_RETAIN_ALWAYS)
|| (rc2 == MOSQ_ERR_SUCCESS && retain_handling == MQTT_SUB_OPT_SEND_RETAIN_NEW)){
if(sub__retain_queue(db, context, sub, qos)) rc = 1;
if(sub__retain_queue(db, context, sub, qos, subscription_identifier)) rc = 1;
}
}

View File

@ -290,7 +290,8 @@ struct mosquitto__subleaf {
struct mosquitto__subleaf *prev;
struct mosquitto__subleaf *next;
struct mosquitto *context;
int qos;
uint32_t identifier;
uint8_t qos;
bool no_local;
bool retain_as_published;
};
@ -333,6 +334,7 @@ struct mosquitto_msg_store{
struct mosquitto_client_msg{
struct mosquitto_client_msg *next;
struct mosquitto_msg_store *store;
mosquitto_property *properties;
time_t timestamp;
uint16_t mid;
uint8_t qos;
@ -554,7 +556,7 @@ void db__limits_set(int inflight, unsigned long inflight_bytes, int queued, unsi
/* Return the number of in-flight messages in count. */
int db__message_count(int *count);
int db__message_delete(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir);
int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored);
int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties);
int db__message_release(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir);
int db__message_update(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, enum mosquitto_msg_state state);
int db__message_write(struct mosquitto_db *db, struct mosquitto *context);
@ -575,12 +577,12 @@ void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time);
/* ============================================================
* Subscription functions
* ============================================================ */
int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int qos, int options, struct mosquitto__subhier **root);
int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int qos, uint32_t identifier, int options, struct mosquitto__subhier **root);
struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent, struct mosquitto__subhier **sibling, const char *topic, size_t len);
int sub__remove(struct mosquitto_db *db, struct mosquitto *context, const char *sub, struct mosquitto__subhier *root);
void sub__tree_print(struct mosquitto__subhier *root, int level);
int sub__clean_session(struct mosquitto_db *db, struct mosquitto *context);
int sub__retain_queue(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos);
int sub__retain_queue(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos, uint32_t subscription_identifier);
int sub__messages_queue(struct mosquitto_db *db, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store **stored);
/* ============================================================

View File

@ -935,8 +935,8 @@ static int persist__restore_sub(struct mosquitto_db *db, const char *client_id,
context = persist__find_or_add_context(db, client_id, 0);
if(!context) return 1;
/* FIXME - retain_as_published needs saving */
return sub__add(db, context, sub, qos, false, &db->subs);
/* FIXME - identifer, options need saving */
return sub__add(db, context, sub, qos, 0, 0, &db->subs);
}
#endif

View File

@ -62,11 +62,6 @@ int send__connack(struct mosquitto_db *db, struct mosquitto *context, int ack, i
mosquitto__free(packet);
return rc;
}
rc = mosquitto_property_add_byte(&connack_props, MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE, 0);
if(rc){
mosquitto__free(packet);
return rc;
}
proplen = property__get_length_all(connack_props);
varbytes = packet__varint_bytes(proplen);
@ -80,7 +75,7 @@ int send__connack(struct mosquitto_db *db, struct mosquitto *context, int ack, i
packet__write_byte(packet, ack);
packet__write_byte(packet, reason_code);
if(context->protocol == mosq_p_mqtt5){
property__write_all(packet, connack_props);
property__write_all(packet, connack_props, true);
}
mosquitto_property_free_all(&connack_props);

View File

@ -52,7 +52,7 @@ int send__suback(struct mosquitto *context, uint16_t mid, uint32_t payloadlen, c
if(context->protocol == mosq_p_mqtt5){
/* We don't use Reason String or User Property yet. */
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
if(payloadlen){

View File

@ -53,7 +53,7 @@ int send__unsuback(struct mosquitto *mosq, uint16_t mid, const mosquitto_propert
packet__write_uint16(packet, mid);
if(mosq->protocol == mosq_p_mqtt5){
property__write_all(packet, properties);
property__write_all(packet, properties, true);
}
return packet__queue(mosq, packet);

View File

@ -70,6 +70,7 @@ static int subs__process(struct mosquitto_db *db, struct mosquitto__subhier *hie
uint16_t mid;
struct mosquitto__subleaf *leaf;
bool client_retain;
mosquitto_property *properties = NULL;
leaf = hier->subs;
@ -129,7 +130,10 @@ static int subs__process(struct mosquitto_db *db, struct mosquitto__subhier *hie
}else{
client_retain = false;
}
if(db__message_insert(db, leaf->context, mid, mosq_md_out, msg_qos, client_retain, stored) == 1) rc = 1;
if(leaf->identifier){
mosquitto_property_add_varint(&properties, MQTT_PROP_SUBSCRIPTION_IDENTIFIER, leaf->identifier);
}
if(db__message_insert(db, leaf->context, mid, mosq_md_out, msg_qos, client_retain, stored, properties) == 1) rc = 1;
}else{
return 1; /* Application error */
}
@ -241,7 +245,7 @@ static void sub__topic_tokens_free(struct sub__token *tokens)
}
}
static int sub__add_recurse(struct mosquitto_db *db, struct mosquitto *context, int qos, int options, struct mosquitto__subhier *subhier, struct sub__token *tokens)
static int sub__add_recurse(struct mosquitto_db *db, struct mosquitto *context, int qos, uint32_t identifier, int options, struct mosquitto__subhier *subhier, struct sub__token *tokens)
/* FIXME - this function has the potential to leak subhier, audit calling functions. */
{
struct mosquitto__subhier *branch;
@ -275,6 +279,7 @@ static int sub__add_recurse(struct mosquitto_db *db, struct mosquitto *context,
leaf->next = NULL;
leaf->context = context;
leaf->qos = qos;
leaf->identifier = identifier;
leaf->no_local = ((options & MQTT_SUB_OPT_NO_LOCAL) != 0);
leaf->retain_as_published = ((options & MQTT_SUB_OPT_RETAIN_AS_PUBLISHED) != 0);
for(i=0; i<context->sub_count; i++){
@ -309,13 +314,13 @@ static int sub__add_recurse(struct mosquitto_db *db, struct mosquitto *context,
HASH_FIND(hh, subhier->children, UHPA_ACCESS_TOPIC(tokens), tokens->topic_len, branch);
if(branch){
return sub__add_recurse(db, context, qos, options, branch, tokens->next);
return sub__add_recurse(db, context, qos, identifier, options, branch, tokens->next);
}else{
/* Not found */
branch = sub__add_hier_entry(subhier, &subhier->children, UHPA_ACCESS_TOPIC(tokens), tokens->topic_len);
if(!branch) return MOSQ_ERR_NOMEM;
return sub__add_recurse(db, context, qos, options, branch, tokens->next);
return sub__add_recurse(db, context, qos, identifier, options, branch, tokens->next);
}
}
@ -444,7 +449,7 @@ struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent
}
int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int qos, int options, struct mosquitto__subhier **root)
int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int qos, uint32_t identifier, int options, struct mosquitto__subhier **root)
{
int rc = 0;
struct mosquitto__subhier *subhier;
@ -466,7 +471,7 @@ int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub
}
}
rc = sub__add_recurse(db, context, qos, options, subhier, tokens);
rc = sub__add_recurse(db, context, qos, identifier, options, subhier, tokens);
sub__topic_tokens_free(tokens);
@ -517,7 +522,7 @@ int sub__messages_queue(struct mosquitto_db *db, const char *source_id, const ch
/* We have a message that needs to be retained, so ensure that the subscription
* tree for its topic exists.
*/
sub__add_recurse(db, NULL, 0, false, subhier, tokens);
sub__add_recurse(db, NULL, 0, 0, 0, subhier, tokens);
}
sub__search(db, subhier, tokens, source_id, topic, qos, retain, *stored, true);
}
@ -641,11 +646,12 @@ void sub__tree_print(struct mosquitto__subhier *root, int level)
}
}
static int retain__process(struct mosquitto_db *db, struct mosquitto_msg_store *retained, struct mosquitto *context, const char *sub, int sub_qos)
static int retain__process(struct mosquitto_db *db, struct mosquitto_msg_store *retained, struct mosquitto *context, const char *sub, int sub_qos, uint32_t subscription_identifier)
{
int rc = 0;
int qos;
uint16_t mid;
mosquitto_property *properties = NULL;
rc = mosquitto_acl_check(db, context, retained->topic, retained->payloadlen, UHPA_ACCESS(retained->payload, retained->payloadlen),
retained->qos, retained->retain, MOSQ_ACL_READ);
@ -666,10 +672,13 @@ static int retain__process(struct mosquitto_db *db, struct mosquitto_msg_store *
}else{
mid = 0;
}
return db__message_insert(db, context, mid, mosq_md_out, qos, true, retained);
if(subscription_identifier > 0){
mosquitto_property_add_varint(&properties, MQTT_PROP_SUBSCRIPTION_IDENTIFIER, subscription_identifier);
}
return db__message_insert(db, context, mid, mosq_md_out, qos, true, retained, properties);
}
static int retain__search(struct mosquitto_db *db, struct mosquitto__subhier *subhier, struct sub__token *tokens, struct mosquitto *context, const char *sub, int sub_qos, int level)
static int retain__search(struct mosquitto_db *db, struct mosquitto__subhier *subhier, struct sub__token *tokens, struct mosquitto *context, const char *sub, int sub_qos, uint32_t subscription_identifier, int level)
{
struct mosquitto__subhier *branch, *branch_tmp;
int flag = 0;
@ -685,25 +694,25 @@ static int retain__search(struct mosquitto_db *db, struct mosquitto__subhier *su
*/
flag = -1;
if(branch->retained){
retain__process(db, branch->retained, context, sub, sub_qos);
retain__process(db, branch->retained, context, sub, sub_qos, subscription_identifier);
}
if(branch->children){
retain__search(db, branch, tokens, context, sub, sub_qos, level+1);
retain__search(db, branch, tokens, context, sub, sub_qos, subscription_identifier, level+1);
}
}else if(strcmp(UHPA_ACCESS_TOPIC(branch), "+")
&& (!strcmp(UHPA_ACCESS_TOPIC(branch), UHPA_ACCESS_TOPIC(tokens))
|| !strcmp(UHPA_ACCESS_TOPIC(tokens), "+"))){
if(tokens->next){
if(retain__search(db, branch, tokens->next, context, sub, sub_qos, level+1) == -1
if(retain__search(db, branch, tokens->next, context, sub, sub_qos, subscription_identifier, level+1) == -1
|| (!branch_tmp && tokens->next && !strcmp(UHPA_ACCESS_TOPIC(tokens->next), "#") && level>0)){
if(branch->retained){
retain__process(db, branch->retained, context, sub, sub_qos);
retain__process(db, branch->retained, context, sub, sub_qos, subscription_identifier);
}
}
}else{
if(branch->retained){
retain__process(db, branch->retained, context, sub, sub_qos);
retain__process(db, branch->retained, context, sub, sub_qos, subscription_identifier);
}
}
}
@ -711,7 +720,7 @@ static int retain__search(struct mosquitto_db *db, struct mosquitto__subhier *su
return flag;
}
int sub__retain_queue(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos)
int sub__retain_queue(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos, uint32_t subscription_identifier)
{
struct mosquitto__subhier *subhier;
struct sub__token *tokens = NULL, *tail;
@ -725,7 +734,7 @@ int sub__retain_queue(struct mosquitto_db *db, struct mosquitto *context, const
HASH_FIND(hh, db->subs, UHPA_ACCESS_TOPIC(tokens), tokens->topic_len, subhier);
if(subhier){
retain__search(db, subhier, tokens, context, sub, sub_qos, 0);
retain__search(db, subhier, tokens, context, sub, sub_qos, subscription_identifier, 0);
}
while(tokens){
tail = tokens->next;

View File

@ -368,7 +368,6 @@ def gen_connect(client_id, clean_session=True, keepalive=60, username=None, pass
def gen_connack(resv=0, rc=0, proto_ver=4, properties=""):
if proto_ver == 5:
properties += mqtt5_props.gen_byte_prop(mqtt5_props.PROP_SHARED_SUB_AVAILABLE, 0)
properties += mqtt5_props.gen_byte_prop(mqtt5_props.PROP_SUBSCRIPTION_ID_AVAILABLE, 0)
properties = mqtt5_props.prop_finalise(properties)
packet = struct.pack('!BBBB', 32, 2+len(properties), resv, rc) + properties