Refactor subscription structs

pull/2735/head
Roger A. Light 3 years ago
parent 86ec8c6169
commit 3634f18bc9

@ -24,7 +24,7 @@ FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read) {
int retain__store(const char *topic, struct mosquitto__base_msg *base_msg, char **split_topics, bool persist) { UNUSED(topic); UNUSED(base_msg); UNUSED(split_topics); UNUSED(persist); return 0; }
int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options) { UNUSED(context); UNUSED(sub); UNUSED(qos); UNUSED(identifier); UNUSED(options); return 0; }
int sub__add(struct mosquitto *context, const struct mosquitto_subscription *sub) { UNUSED(context); UNUSED(sub); return 0; }
void db__msg_add_to_inflight_stats(struct mosquitto_msg_data *msg_data, struct mosquitto_client_msg *msg) { UNUSED(msg_data); UNUSED(msg); }

@ -264,18 +264,22 @@ struct mosquitto_evt_persist_client {
};
struct mosquitto_subscription {
char *client_id;
char *topic;
mosquitto_property *properties;
uint32_t identifier;
uint8_t options;
uint8_t padding[3];
void *future2[8];
};
/* Data for the MOSQ_EVT_PERSIST_SUBSCRIPTION_ADD/_DELETE event */
/* NOTE: The persistence interface is currently marked as unstable, which means
* it may change in a future minor release. */
struct mosquitto_evt_persist_subscription {
void *future;
const char *client_id;
const char *topic;
char *plugin_client_id;
char *plugin_topic;
uint32_t subscription_identifier;
uint8_t subscription_options;
uint8_t padding[3];
struct mosquitto_subscription sub;
void *future2[8];
};
@ -1092,18 +1096,18 @@ mosq_EXPORT int mosquitto_persist_base_msg_delete(uint64_t store_id);
* Use to add a new subscription for a client
*
* Parameters:
* client_id - the client id of the client the new subscription is for
* topic - the topic filter for the subscription
* subscription_options - the QoS and other flags for this subscription
* subscription_identifier - the MQTT v5 subscription id, or 0
* sub->client_id - the client id of the client the new subscription is for
* sub->topic - the topic filter for the subscription
* sub->subscription_options - the QoS and other flags for this subscription
* sub->subscription_identifier - the MQTT v5 subscription id, or 0
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if client_id or topic are NULL, or are zero length
* MOSQ_ERR_INVAL - if sub, client_id, or topic are NULL, or are zero length
* MOSQ_ERR_NOT_FOUND - the referenced client was not found
* MOSQ_ERR_NOMEM - on out of memory
*/
mosq_EXPORT int mosquitto_subscription_add(const char *client_id, const char *topic, uint8_t subscription_options, uint32_t subscription_identifier);
mosq_EXPORT int mosquitto_subscription_add(const struct mosquitto_subscription *sub);
/* Function: mosquitto_persist_subscription_delete

@ -234,11 +234,8 @@ static int client_restore(struct mosquitto_sqlite *ms)
static int subscription_restore(struct mosquitto_sqlite *ms)
{
sqlite3_stmt *stmt;
uint8_t subscription_options;
uint32_t subscription_identifier;
struct mosquitto_subscription sub;
int rc;
const char *client_id;
const char *topic;
long count = 0, failed = 0;
rc = sqlite3_prepare_v2(ms->db,
@ -252,12 +249,13 @@ static int subscription_restore(struct mosquitto_sqlite *ms)
}
while(sqlite3_step(stmt) == SQLITE_ROW){
client_id = (const char *)sqlite3_column_text(stmt, 0);
topic = (const char *)sqlite3_column_text(stmt, 1);
subscription_options = (uint8_t)sqlite3_column_int(stmt, 2);
subscription_identifier = (uint32_t)sqlite3_column_int(stmt, 3);
memset(&sub, 0, sizeof(sub));
sub.client_id = (char *)sqlite3_column_text(stmt, 0);
sub.topic = (char *)sqlite3_column_text(stmt, 1);
sub.options = (uint8_t)sqlite3_column_int(stmt, 2);
sub.identifier = (uint32_t)sqlite3_column_int(stmt, 3);
rc = mosquitto_subscription_add(client_id, topic, subscription_options, subscription_identifier);
rc = mosquitto_subscription_add(&sub);
if(rc == MOSQ_ERR_SUCCESS){
count++;
}else{

@ -32,16 +32,16 @@ int persist_sqlite__subscription_add_cb(int event, void *event_data, void *userd
UNUSED(event);
if(sqlite3_bind_text(ms->subscription_add_stmt, 1,
ed->client_id, (int)strlen(ed->client_id), SQLITE_STATIC) == SQLITE_OK){
ed->sub.client_id, (int)strlen(ed->sub.client_id), SQLITE_STATIC) == SQLITE_OK){
if(sqlite3_bind_text(ms->subscription_add_stmt, 2,
ed->topic, (int)strlen(ed->topic), SQLITE_STATIC) == SQLITE_OK){
ed->sub.topic, (int)strlen(ed->sub.topic), SQLITE_STATIC) == SQLITE_OK){
if(sqlite3_bind_int(ms->subscription_add_stmt, 3,
ed->subscription_options) == SQLITE_OK){
ed->sub.options) == SQLITE_OK){
if(sqlite3_bind_int(ms->subscription_add_stmt, 4,
(int)ed->subscription_identifier) == SQLITE_OK){
(int)ed->sub.identifier) == SQLITE_OK){
ms->event_count++;
rc = sqlite3_step(ms->subscription_add_stmt);
@ -68,10 +68,10 @@ int persist_sqlite__subscription_remove_cb(int event, void *event_data, void *us
UNUSED(event);
if(sqlite3_bind_text(ms->subscription_remove_stmt, 1,
ed->client_id, (int)strlen(ed->client_id), SQLITE_STATIC) == SQLITE_OK){
ed->sub.client_id, (int)strlen(ed->sub.client_id), SQLITE_STATIC) == SQLITE_OK){
if(sqlite3_bind_text(ms->subscription_remove_stmt, 2,
ed->topic, (int)strlen(ed->topic), SQLITE_STATIC) == SQLITE_OK){
ed->sub.topic, (int)strlen(ed->sub.topic), SQLITE_STATIC) == SQLITE_OK){
ms->event_count++;
rc = sqlite3_step(ms->subscription_remove_stmt);

@ -491,13 +491,11 @@ int bridge__connect(struct mosquitto *context)
}else{
qos = cur_topic->qos;
}
if(sub__add(context,
cur_topic->local_topic,
qos,
0,
MQTT_SUB_OPT_NO_LOCAL | MQTT_SUB_OPT_RETAIN_AS_PUBLISHED
) > 0){
struct mosquitto_subscription sub;
sub.topic = cur_topic->local_topic;
sub.identifier = 0;
sub.options = MQTT_SUB_OPT_NO_LOCAL | MQTT_SUB_OPT_RETAIN_AS_PUBLISHED | qos;
if(sub__add(context, &sub) > 0){
return 1;
}
}
@ -694,16 +692,17 @@ int bridge__on_connect(struct mosquitto *context)
}
}
}
struct mosquitto_subscription sub;
memset(&sub, 0, sizeof(sub));
LL_FOREACH(context->bridge->topics, cur_topic){
sub.topic = cur_topic->local_topic;
if(cur_topic->direction == bd_out || cur_topic->direction == bd_both){
if(cur_topic->qos > context->max_qos){
qos = context->max_qos;
sub.options = context->max_qos;
}else{
qos = cur_topic->qos;
sub.options = cur_topic->qos;
}
retain__queue(context,
cur_topic->local_topic,
qos, 0);
retain__queue(context, &sub);
}
}

@ -34,9 +34,6 @@ int handle__subscribe(struct mosquitto *context)
int rc = 0;
int rc2;
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;
@ -46,6 +43,8 @@ int handle__subscribe(struct mosquitto *context)
char *sub_mount;
mosquitto_property *properties = NULL;
bool allowed;
struct mosquitto_subscription sub;
uint32_t subscription_identifier = 0;
if(!context) return MOSQ_ERR_INVAL;
@ -94,53 +93,55 @@ int handle__subscribe(struct mosquitto *context)
}
while(context->in_packet.pos < context->in_packet.remaining_length){
sub = NULL;
if(packet__read_string(&context->in_packet, &sub, &slen)){
memset(&sub, 0, sizeof(sub));
sub.identifier = subscription_identifier;
sub.properties = properties;
if(packet__read_string(&context->in_packet, &sub.topic, &slen)){
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
if(sub){
if(sub.topic){
if(!slen){
log__printf(NULL, MOSQ_LOG_INFO,
"Empty subscription string from %s, disconnecting.",
context->address);
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
if(mosquitto_sub_topic_check(sub)){
if(mosquitto_sub_topic_check(sub.topic)){
log__printf(NULL, MOSQ_LOG_INFO,
"Invalid subscription string from %s, disconnecting.",
context->address);
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
if(packet__read_byte(&context->in_packet, &subscription_options)){
mosquitto__FREE(sub);
if(packet__read_byte(&context->in_packet, &sub.options)){
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
if(subscription_options & MQTT_SUB_OPT_NO_LOCAL && !strncmp(sub, "$share/", strlen("$share/"))){
mosquitto__FREE(sub);
if(sub.options & MQTT_SUB_OPT_NO_LOCAL && !strncmp(sub.topic, "$share/", strlen("$share/"))){
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_PROTOCOL;
}
if(context->protocol == mosq_p_mqtt31 || context->protocol == mosq_p_mqtt311){
qos = subscription_options;
qos = sub.options;
if(context->is_bridge){
subscription_options = MQTT_SUB_OPT_RETAIN_AS_PUBLISHED | MQTT_SUB_OPT_NO_LOCAL;
sub.options |= MQTT_SUB_OPT_RETAIN_AS_PUBLISHED | MQTT_SUB_OPT_NO_LOCAL;
}
}else{
qos = subscription_options & 0x03;
subscription_options &= 0xFC;
qos = sub.options & 0x03;
sub.options &= 0xFC;
retain_handling = (subscription_options & 0x30);
if(retain_handling == 0x30 || (subscription_options & 0xC0) != 0){
mosquitto__FREE(sub);
retain_handling = (sub.options & 0x30);
if(retain_handling == 0x30 || (sub.options & 0xC0) != 0){
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
@ -149,7 +150,7 @@ int handle__subscribe(struct mosquitto *context)
log__printf(NULL, MOSQ_LOG_INFO,
"Invalid QoS in subscription command from %s, disconnecting.",
context->address);
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_MALFORMED_PACKET;
}
@ -162,21 +163,21 @@ int handle__subscribe(struct mosquitto *context)
len = strlen(context->listener->mount_point) + slen + 1;
sub_mount = mosquitto__malloc(len+1);
if(!sub_mount){
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(payload);
return MOSQ_ERR_NOMEM;
}
snprintf(sub_mount, len, "%s%s", context->listener->mount_point, sub);
snprintf(sub_mount, len, "%s%s", context->listener->mount_point, sub.topic);
sub_mount[len] = '\0';
mosquitto__FREE(sub);
sub = sub_mount;
mosquitto__FREE(sub.topic);
sub.topic = sub_mount;
}
log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s (QoS %d)", sub, qos);
log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s (QoS %d)", sub.topic, qos);
allowed = true;
rc2 = mosquitto_acl_check(context, sub, 0, NULL, qos, false, MOSQ_ACL_SUBSCRIBE);
rc2 = mosquitto_acl_check(context, sub.topic, 0, NULL, qos, false, MOSQ_ACL_SUBSCRIBE);
switch(rc2){
case MOSQ_ERR_SUCCESS:
break;
@ -189,34 +190,35 @@ int handle__subscribe(struct mosquitto *context)
}
break;
default:
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
return rc2;
}
if(allowed){
rc2 = sub__add(context, sub, qos, subscription_identifier, subscription_options);
sub.options |= qos;
rc2 = sub__add(context, &sub);
if(rc2 > 0){
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
return rc2;
}
if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt31){
if(rc2 == MOSQ_ERR_SUCCESS || rc2 == MOSQ_ERR_SUB_EXISTS){
if(retain__queue(context, sub, qos, 0)) rc = 1;
if(retain__queue(context, &sub)) 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(retain__queue(context, sub, qos, subscription_identifier)) rc = 1;
if(retain__queue(context, &sub)) rc = 1;
}
}
log__printf(NULL, MOSQ_LOG_SUBSCRIBE, "%s %d %s", context->id, qos, sub);
log__printf(NULL, MOSQ_LOG_SUBSCRIBE, "%s %d %s", context->id, qos, sub.topic);
plugin__handle_subscribe(context, sub, qos, subscription_options, subscription_identifier, properties);
plugin_persist__handle_subscription_add(context, sub, qos | subscription_options, subscription_identifier);
plugin__handle_subscribe(context, &sub);
plugin_persist__handle_subscription_add(context, &sub);
}
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
tmp_payload = mosquitto__realloc(payload, payloadlen + 1);
if(tmp_payload){
@ -253,5 +255,3 @@ int handle__subscribe(struct mosquitto *context)
return rc;
}

@ -30,7 +30,6 @@ Contributors:
int handle__unsubscribe(struct mosquitto *context)
{
uint16_t mid;
char *sub;
uint16_t slen;
int rc;
uint8_t reason = 0;
@ -39,6 +38,7 @@ int handle__unsubscribe(struct mosquitto *context)
uint8_t *reason_codes = NULL, *reason_tmp;
mosquitto_property *properties = NULL;
bool allowed;
struct mosquitto_subscription sub;
if(!context) return MOSQ_ERR_INVAL;
@ -88,8 +88,9 @@ int handle__unsubscribe(struct mosquitto *context)
}
while(context->in_packet.pos < context->in_packet.remaining_length){
sub = NULL;
if(packet__read_string(&context->in_packet, &sub, &slen)){
memset(&sub, 0, sizeof(sub));
sub.properties = properties;
if(packet__read_string(&context->in_packet, &sub.topic, &slen)){
mosquitto__FREE(reason_codes);
return MOSQ_ERR_MALFORMED_PACKET;
}
@ -98,22 +99,22 @@ int handle__unsubscribe(struct mosquitto *context)
log__printf(NULL, MOSQ_LOG_INFO,
"Empty unsubscription string from %s, disconnecting.",
context->id);
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(reason_codes);
return MOSQ_ERR_MALFORMED_PACKET;
}
if(mosquitto_sub_topic_check(sub)){
if(mosquitto_sub_topic_check(sub.topic)){
log__printf(NULL, MOSQ_LOG_INFO,
"Invalid unsubscription string from %s, disconnecting.",
context->id);
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(reason_codes);
return MOSQ_ERR_MALFORMED_PACKET;
}
/* ACL check */
allowed = true;
rc = mosquitto_acl_check(context, sub, 0, NULL, 0, false, MOSQ_ACL_UNSUBSCRIBE);
rc = mosquitto_acl_check(context, sub.topic, 0, NULL, 0, false, MOSQ_ACL_UNSUBSCRIBE);
switch(rc){
case MOSQ_ERR_SUCCESS:
break;
@ -122,21 +123,21 @@ int handle__unsubscribe(struct mosquitto *context)
reason = MQTT_RC_NOT_AUTHORIZED;
break;
default:
mosquitto__FREE(sub);
mosquitto__FREE(sub.topic);
mosquitto__FREE(reason_codes);
return rc;
}
log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub);
log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub.topic);
if(allowed){
rc = sub__remove(context, sub, &reason);
plugin__handle_unsubscribe(context, sub, properties);
plugin_persist__handle_subscription_delete(context, sub);
rc = sub__remove(context, sub.topic, &reason);
plugin__handle_unsubscribe(context, &sub);
plugin_persist__handle_subscription_delete(context, sub.topic);
}else{
rc = MOSQ_ERR_SUCCESS;
}
log__printf(NULL, MOSQ_LOG_UNSUBSCRIBE, "%s %s", context->id, sub);
mosquitto__FREE(sub);
log__printf(NULL, MOSQ_LOG_UNSUBSCRIBE, "%s %s", context->id, sub.topic);
mosquitto__FREE(sub.topic);
if(rc){
mosquitto__FREE(reason_codes);
return rc;

@ -753,7 +753,7 @@ void db__expire_all_messages(struct mosquitto *context);
/* ============================================================
* Subscription functions
* ============================================================ */
int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options);
int sub__add(struct mosquitto *context, const struct mosquitto_subscription *sub);
struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent, struct mosquitto__subhier **sibling, const char *topic, uint16_t len);
int sub__remove(struct mosquitto *context, const char *sub, uint8_t *reason);
void sub__tree_print(struct mosquitto__subhier *root, int level);
@ -858,8 +858,8 @@ int acl__pre_check(mosquitto_plugin_id_t *plugin, struct mosquitto *context, int
void plugin__handle_connect(struct mosquitto *context);
void plugin__handle_disconnect(struct mosquitto *context, int reason);
int plugin__handle_message(struct mosquitto *context, struct mosquitto__base_msg *base_msg);
int plugin__handle_subscribe(struct mosquitto *context, const char *topic, uint8_t qos, uint8_t subscription_options, uint32_t subscription_identifier, const mosquitto_property *properties);
int plugin__handle_unsubscribe(struct mosquitto *context, const char *topic, const mosquitto_property *properties);
int plugin__handle_subscribe(struct mosquitto *context, const struct mosquitto_subscription *sub);
int plugin__handle_unsubscribe(struct mosquitto *context, const struct mosquitto_subscription *sub);
void LIB_ERROR(void);
void plugin__handle_tick(void);
int plugin__callback_unregister_all(mosquitto_plugin_id_t *identifier);
@ -867,8 +867,8 @@ void plugin_persist__handle_restore(void);
void plugin_persist__handle_client_add(struct mosquitto *context);
void plugin_persist__handle_client_delete(struct mosquitto *context);
void plugin_persist__handle_client_update(struct mosquitto *context);
void plugin_persist__handle_subscription_add(struct mosquitto *context, const char *sub, uint8_t subscription_options, uint32_t subscription_identifier);
void plugin_persist__handle_subscription_delete(struct mosquitto *context, const char *sub);
void plugin_persist__handle_subscription_add(struct mosquitto *context, const struct mosquitto_subscription *sub);
void plugin_persist__handle_subscription_delete(struct mosquitto *context, char *sub);
void plugin_persist__handle_client_msg_add(struct mosquitto *context, const struct mosquitto_client_msg *cmsg);
void plugin_persist__handle_client_msg_delete(struct mosquitto *context, const struct mosquitto_client_msg *cmsg);
void plugin_persist__handle_client_msg_update(struct mosquitto *context, const struct mosquitto_client_msg *cmsg);
@ -899,7 +899,7 @@ int property__process_disconnect(struct mosquitto *context, mosquitto_property *
* ============================================================ */
int retain__init(void);
void retain__clean(struct mosquitto__retainhier **retainhier);
int retain__queue(struct mosquitto *context, const char *sub, uint8_t sub_qos, uint32_t subscription_identifier);
int retain__queue(struct mosquitto *context, const struct mosquitto_subscription *sub);
int retain__store(const char *topic, struct mosquitto__base_msg *base_msg, char **split_topics, bool persist);
/* ============================================================

@ -48,7 +48,7 @@ static long client_count = 0;
static long subscription_count = 0;
static long client_msg_count = 0;
static int persist__restore_sub(const char *client_id, const char *sub, uint8_t qos, uint32_t identifier, int options);
static int persist__restore_sub(const struct mosquitto_subscription *sub);
static struct mosquitto *persist__find_or_add_context(const char *client_id, uint16_t last_mid)
{
@ -362,6 +362,7 @@ static int persist__sub_chunk_restore(FILE *db_fptr)
{
struct P_sub chunk;
int rc;
struct mosquitto_subscription sub;
memset(&chunk, 0, sizeof(struct P_sub));
@ -374,7 +375,11 @@ static int persist__sub_chunk_restore(FILE *db_fptr)
return rc;
}
rc = persist__restore_sub(chunk.client_id, chunk.topic, chunk.F.qos, chunk.F.identifier, chunk.F.options);
sub.client_id = chunk.client_id;
sub.topic = chunk.topic;
sub.options = chunk.F.qos | chunk.F.options;
sub.identifier = chunk.F.identifier;
rc = persist__restore_sub(&sub);
mosquitto__FREE(chunk.client_id);
mosquitto__FREE(chunk.topic);
@ -537,16 +542,17 @@ error:
return 1;
}
static int persist__restore_sub(const char *client_id, const char *sub, uint8_t qos, uint32_t identifier, int options)
static int persist__restore_sub(const struct mosquitto_subscription *sub)
{
struct mosquitto *context;
assert(client_id);
assert(sub);
assert(sub->client_id);
assert(sub->topic);
context = persist__find_or_add_context(client_id, 0);
context = persist__find_or_add_context(sub->client_id, 0);
if(!context) return 1;
return sub__add(context, sub, qos, identifier, options);
return sub__add(context, sub);
}
#endif

@ -142,7 +142,7 @@ void plugin_persist__handle_client_delete(struct mosquitto *context)
}
void plugin_persist__handle_subscription_add(struct mosquitto *context, const char *sub, uint8_t subscription_options, uint32_t subscription_identifier)
void plugin_persist__handle_subscription_add(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
struct mosquitto_evt_persist_subscription event_data;
struct mosquitto__callback *cb_base;
@ -152,10 +152,10 @@ void plugin_persist__handle_subscription_add(struct mosquitto *context, const ch
opts = &db.config->security_options;
memset(&event_data, 0, sizeof(event_data));
event_data.client_id = context->id;
event_data.topic = sub;
event_data.subscription_identifier = subscription_identifier;
event_data.subscription_options = subscription_options;
event_data.sub.client_id = context->id;
event_data.sub.topic = sub->topic;
event_data.sub.identifier = sub->identifier;
event_data.sub.options = sub->options;
DL_FOREACH(opts->plugin_callbacks.persist_subscription_add, cb_base){
cb_base->cb(MOSQ_EVT_PERSIST_SUBSCRIPTION_ADD, &event_data, cb_base->userdata);
@ -163,18 +163,19 @@ void plugin_persist__handle_subscription_add(struct mosquitto *context, const ch
}
void plugin_persist__handle_subscription_delete(struct mosquitto *context, const char *sub)
void plugin_persist__handle_subscription_delete(struct mosquitto *context, char *sub)
{
struct mosquitto_evt_persist_subscription event_data;
struct mosquitto__callback *cb_base;
struct mosquitto__security_options *opts;
if(db.shutdown || context->is_persisted == false) return;
if(!sub) return;
opts = &db.config->security_options;
memset(&event_data, 0, sizeof(event_data));
event_data.client_id = context->id;
event_data.topic = sub;
event_data.sub.client_id = context->id;
event_data.sub.topic = sub;
DL_FOREACH(opts->plugin_callbacks.persist_subscription_delete, cb_base){
cb_base->cb(MOSQ_EVT_PERSIST_SUBSCRIPTION_DELETE, &event_data, cb_base->userdata);

@ -708,18 +708,18 @@ BROKER_EXPORT int mosquitto_persist_client_msg_clear(struct mosquitto_evt_persis
}
BROKER_EXPORT int mosquitto_subscription_add(const char *client_id, const char *topic, uint8_t subscription_options, uint32_t subscription_identifier)
BROKER_EXPORT int mosquitto_subscription_add(const struct mosquitto_subscription *sub)
{
struct mosquitto *context;
if(client_id == NULL || topic == NULL || client_id[0] == '\0' || topic[0] == '\0'){
if(sub == NULL || sub->client_id == NULL || sub->topic == NULL || sub->client_id[0] == '\0' || sub->topic[0] == '\0'){
return MOSQ_ERR_INVAL;
}
HASH_FIND(hh_id, db.contexts_by_id, client_id, strlen(client_id), context);
HASH_FIND(hh_id, db.contexts_by_id, sub->client_id, strlen(sub->client_id), context);
if(context){
return sub__add(context, topic, subscription_options&0x03, subscription_identifier, subscription_options);
return sub__add(context, sub);
}else{
return MOSQ_ERR_NOT_FOUND;
}

@ -24,7 +24,7 @@ Contributors:
#include "utlist.h"
static int plugin__handle_subscribe_single(struct mosquitto__security_options *opts, struct mosquitto *context, const char *topic, uint8_t qos, uint8_t subscription_options, uint32_t subscription_identifier, const mosquitto_property *properties)
static int plugin__handle_subscribe_single(struct mosquitto__security_options *opts, struct mosquitto *context, const struct mosquitto_subscription *sub)
{
struct mosquitto_evt_subscribe event_data;
struct mosquitto__callback *cb_base;
@ -32,11 +32,11 @@ static int plugin__handle_subscribe_single(struct mosquitto__security_options *o
memset(&event_data, 0, sizeof(event_data));
event_data.client = context;
event_data.topic = topic;
event_data.qos = qos;
event_data.subscription_options = subscription_options;
event_data.subscription_identifier = subscription_identifier;
event_data.properties = properties;
event_data.topic = sub->topic;
event_data.qos = sub->options & 0x03;
event_data.subscription_options = sub->options;
event_data.subscription_identifier = sub->identifier;
event_data.properties = sub->properties;
DL_FOREACH(opts->plugin_callbacks.subscribe, cb_base){
rc = cb_base->cb(MOSQ_EVT_SUBSCRIBE, &event_data, cb_base->userdata);
@ -49,18 +49,18 @@ static int plugin__handle_subscribe_single(struct mosquitto__security_options *o
}
int plugin__handle_subscribe(struct mosquitto *context, const char *topic, uint8_t qos, uint8_t subscription_options, uint32_t subscription_identifier, const mosquitto_property *properties)
int plugin__handle_subscribe(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
int rc = MOSQ_ERR_SUCCESS;
/* Global plugins */
rc = plugin__handle_subscribe_single(&db.config->security_options,
context, topic, qos, subscription_options, subscription_identifier, properties);
context, sub);
if(rc) return rc;
if(db.config->per_listener_settings && context->listener){
rc = plugin__handle_subscribe_single(context->listener->security_options,
context, topic, qos, subscription_options, subscription_identifier, properties);
context, sub);
}
return rc;

@ -24,7 +24,7 @@ Contributors:
#include "utlist.h"
static int plugin__handle_unsubscribe_single(struct mosquitto__security_options *opts, struct mosquitto *context, const char *topic, const mosquitto_property *properties)
static int plugin__handle_unsubscribe_single(struct mosquitto__security_options *opts, struct mosquitto *context, const struct mosquitto_subscription *sub)
{
struct mosquitto_evt_unsubscribe event_data;
struct mosquitto__callback *cb_base;
@ -32,8 +32,8 @@ static int plugin__handle_unsubscribe_single(struct mosquitto__security_options
memset(&event_data, 0, sizeof(event_data));
event_data.client = context;
event_data.topic = topic;
event_data.properties = properties;
event_data.topic = sub->topic;
event_data.properties = sub->properties;
DL_FOREACH(opts->plugin_callbacks.unsubscribe, cb_base){
rc = cb_base->cb(MOSQ_EVT_UNSUBSCRIBE, &event_data, cb_base->userdata);
@ -46,18 +46,18 @@ static int plugin__handle_unsubscribe_single(struct mosquitto__security_options
}
int plugin__handle_unsubscribe(struct mosquitto *context, const char *topic, const mosquitto_property *properties)
int plugin__handle_unsubscribe(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
int rc = MOSQ_ERR_SUCCESS;
/* Global plugins */
rc = plugin__handle_unsubscribe_single(&db.config->security_options,
context, topic, properties);
context, sub);
if(rc) return rc;
if(db.config->per_listener_settings && context->listener){
rc = plugin__handle_unsubscribe_single(context->listener->security_options,
context, topic, properties);
context, sub);
}
return rc;

@ -194,10 +194,10 @@ int retain__store(const char *topic, struct mosquitto__base_msg *base_msg, char
}
static int retain__process(struct mosquitto__retainhier *branch, struct mosquitto *context, uint8_t sub_qos, uint32_t subscription_identifier)
static int retain__process(struct mosquitto__retainhier *branch, struct mosquitto *context, const struct mosquitto_subscription *sub)
{
int rc = 0;
uint8_t qos;
uint8_t qos, sub_qos;
uint16_t mid;
struct mosquitto__base_msg *retained;
@ -242,6 +242,7 @@ static int retain__process(struct mosquitto__retainhier *branch, struct mosquitt
}
}
sub_qos = sub->options & 0x03;
if (db.config->upgrade_outgoing_qos){
qos = sub_qos;
} else {
@ -253,11 +254,11 @@ static int retain__process(struct mosquitto__retainhier *branch, struct mosquitt
}else{
mid = 0;
}
return db__message_insert_outgoing(context, 0, mid, qos, true, retained, subscription_identifier, false, true);
return db__message_insert_outgoing(context, 0, mid, qos, true, retained, sub->identifier, false, true);
}
static int retain__search(struct mosquitto__retainhier *retainhier, char **split_topics, struct mosquitto *context, const char *sub, uint8_t sub_qos, uint32_t subscription_identifier, int level)
static int retain__search(struct mosquitto__retainhier *retainhier, char **split_topics, struct mosquitto *context, const struct mosquitto_subscription *sub, int level)
{
struct mosquitto__retainhier *branch, *branch_tmp;
int flag = 0;
@ -270,26 +271,26 @@ static int retain__search(struct mosquitto__retainhier *retainhier, char **split
*/
flag = -1;
if(branch->retained){
retain__process(branch, context, sub_qos, subscription_identifier);
retain__process(branch, context, sub);
}
if(branch->children){
retain__search(branch, split_topics, context, sub, sub_qos, subscription_identifier, level+1);
retain__search(branch, split_topics, context, sub, level+1);
}
}
}else{
if(!strcmp(split_topics[0], "+")){
HASH_ITER(hh, retainhier->children, branch, branch_tmp){
if(split_topics[1] != NULL){
if(retain__search(branch, &(split_topics[1]), context, sub, sub_qos, subscription_identifier, level+1) == -1
if(retain__search(branch, &(split_topics[1]), context, sub, level+1) == -1
|| (split_topics[1] != NULL && !strcmp(split_topics[1], "#") && level>0)){
if(branch->retained){
retain__process(branch, context, sub_qos, subscription_identifier);
retain__process(branch, context, sub);
}
}
}else{
if(branch->retained){
retain__process(branch, context, sub_qos, subscription_identifier);
retain__process(branch, context, sub);
}
}
}
@ -297,16 +298,16 @@ static int retain__search(struct mosquitto__retainhier *retainhier, char **split
HASH_FIND(hh, retainhier->children, split_topics[0], strlen(split_topics[0]), branch);
if(branch){
if(split_topics[1] != NULL){
if(retain__search(branch, &(split_topics[1]), context, sub, sub_qos, subscription_identifier, level+1) == -1
if(retain__search(branch, &(split_topics[1]), context, sub, level+1) == -1
|| (split_topics[1] != NULL && !strcmp(split_topics[1], "#") && level>0)){
if(branch->retained){
retain__process(branch, context, sub_qos, subscription_identifier);
retain__process(branch, context, sub);
}
}
}else{
if(branch->retained){
retain__process(branch, context, sub_qos, subscription_identifier);
retain__process(branch, context, sub);
}
}
}
@ -316,7 +317,7 @@ static int retain__search(struct mosquitto__retainhier *retainhier, char **split
}
int retain__queue(struct mosquitto *context, const char *sub, uint8_t sub_qos, uint32_t subscription_identifier)
int retain__queue(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
struct mosquitto__retainhier *retainhier;
char *local_sub;
@ -326,17 +327,17 @@ int retain__queue(struct mosquitto *context, const char *sub, uint8_t sub_qos, u
assert(context);
assert(sub);
if(!strncmp(sub, "$share/", strlen("$share/"))){
if(!strncmp(sub->topic, "$share/", strlen("$share/"))){
return MOSQ_ERR_SUCCESS;
}
rc = sub__topic_tokenise(sub, &local_sub, &split_topics, NULL);
rc = sub__topic_tokenise(sub->topic, &local_sub, &split_topics, NULL);
if(rc) return rc;
HASH_FIND(hh, db.retains, split_topics[0], strlen(split_topics[0]), retainhier);
if(retainhier){
retain__search(retainhier, split_topics, context, sub, sub_qos, subscription_identifier, 0);
retain__search(retainhier, split_topics, context, sub, 0);
}
mosquitto__FREE(local_sub);
mosquitto__FREE(split_topics);

@ -150,7 +150,7 @@ static int subs__process(struct mosquitto__subhier *hier, const char *source_id,
}
static int sub__add_leaf(struct mosquitto *context, const char *topic_filter, uint8_t qos, uint32_t identifier, int options, struct mosquitto__subleaf **head, struct mosquitto__subleaf **newleaf)
static int sub__add_leaf(struct mosquitto *context, const struct mosquitto_subscription *sub, struct mosquitto__subleaf **head, struct mosquitto__subleaf **newleaf)
{
struct mosquitto__subleaf *leaf;
@ -162,22 +162,22 @@ static int sub__add_leaf(struct mosquitto *context, const char *topic_filter, ui
/* Client making a second subscription to same topic. Only
* need to update QoS. Return MOSQ_ERR_SUB_EXISTS to
* indicate this to the calling function. */
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);
leaf->qos = sub->options & 0x03;
leaf->identifier = sub->identifier;
leaf->no_local = ((sub->options & MQTT_SUB_OPT_NO_LOCAL) != 0);
leaf->retain_as_published = ((sub->options & MQTT_SUB_OPT_RETAIN_AS_PUBLISHED) != 0);
return MOSQ_ERR_SUB_EXISTS;
}
leaf = leaf->next;
}
leaf = mosquitto__calloc(1, sizeof(struct mosquitto__subleaf) + strlen(topic_filter) + 1);
leaf = mosquitto__calloc(1, sizeof(struct mosquitto__subleaf) + strlen(sub->topic) + 1);
if(!leaf) return MOSQ_ERR_NOMEM;
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);
strcpy(leaf->topic_filter, topic_filter);
leaf->qos = sub->options & 0x03;
leaf->identifier = sub->identifier;
leaf->no_local = ((sub->options & MQTT_SUB_OPT_NO_LOCAL) != 0);
leaf->retain_as_published = ((sub->options & MQTT_SUB_OPT_RETAIN_AS_PUBLISHED) != 0);
strcpy(leaf->topic_filter, sub->topic);
DL_APPEND(*head, leaf);
*newleaf = leaf;
@ -196,7 +196,7 @@ static void sub__remove_shared_leaf(struct mosquitto__subhier *subhier, struct m
}
static int sub__add_shared(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options, struct mosquitto__subhier *subhier, const char *sharename)
static int sub__add_shared(struct mosquitto *context, const struct mosquitto_subscription *sub, struct mosquitto__subhier *subhier, const char *sharename)
{
struct mosquitto__subleaf *newleaf;
struct mosquitto__subshared *shared = NULL;
@ -218,7 +218,7 @@ static int sub__add_shared(struct mosquitto *context, const char *sub, uint8_t q
HASH_ADD(hh, subhier->shared, name, slen, shared);
}
rc = sub__add_leaf(context, sub, qos, identifier, options, &shared->subs, &newleaf);
rc = sub__add_leaf(context, sub, &shared->subs, &newleaf);
if(rc > 0){
if(shared->subs == NULL){
HASH_DELETE(hh, subhier->shared, shared);
@ -267,14 +267,14 @@ static int sub__add_shared(struct mosquitto *context, const char *sub, uint8_t q
}
static int sub__add_normal(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options, struct mosquitto__subhier *subhier)
static int sub__add_normal(struct mosquitto *context, const struct mosquitto_subscription *sub, struct mosquitto__subhier *subhier)
{
struct mosquitto__subleaf *newleaf = NULL;
struct mosquitto__subleaf **subs;
int i;
int rc;
rc = sub__add_leaf(context, sub, qos, identifier, options, &subhier->subs, &newleaf);
rc = sub__add_leaf(context, sub, &subhier->subs, &newleaf);
if(rc > 0){
return rc;
}
@ -319,7 +319,7 @@ static int sub__add_normal(struct mosquitto *context, const char *sub, uint8_t q
}
static int sub__add_context(struct mosquitto *context, const char *topic_filter, uint8_t qos, uint32_t identifier, int options, struct mosquitto__subhier *subhier, char *const *const topics, const char *sharename)
static int sub__add_context(struct mosquitto *context, const struct mosquitto_subscription *sub, struct mosquitto__subhier *subhier, char *const *const topics, const char *sharename)
{
struct mosquitto__subhier *branch;
int topic_index = 0;
@ -344,9 +344,9 @@ static int sub__add_context(struct mosquitto *context, const char *topic_filter,
/* Add add our context */
if(context && context->id){
if(sharename){
return sub__add_shared(context, topic_filter, qos, identifier, options, subhier, sharename);
return sub__add_shared(context, sub, subhier, sharename);
}else{
return sub__add_normal(context, topic_filter, qos, identifier, options, subhier);
return sub__add_normal(context, sub, subhier);
}
}else{
return MOSQ_ERR_SUCCESS;
@ -549,7 +549,7 @@ struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent
}
int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options)
int sub__add(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
int rc = 0;
struct mosquitto__subhier *subhier;
@ -559,8 +559,9 @@ int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t i
size_t topiclen;
assert(sub);
assert(sub->topic);
rc = sub__topic_tokenise(sub, &local_sub, &topics, &sharename);
rc = sub__topic_tokenise(sub->topic, &local_sub, &topics, &sharename);
if(rc) return rc;
topiclen = strlen(topics[0]);
@ -580,7 +581,7 @@ int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t i
}
}
rc = sub__add_context(context, sub, qos, identifier, options, subhier, topics, sharename);
rc = sub__add_context(context, sub, subhier, topics, sharename);
mosquitto__FREE(local_sub);
mosquitto__FREE(topics);

@ -148,14 +148,13 @@ int acl__find_acls(struct mosquitto *context)
}
int sub__add(struct mosquitto *context, const char *sub, uint8_t qos, uint32_t identifier, int options)
int sub__add(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
UNUSED(context);
UNUSED(options);
last_sub = strdup(sub);
last_qos = qos;
last_identifier = identifier;
last_sub = strdup(sub->topic);
last_qos = sub->options & 0x03;
last_identifier = sub->identifier;
return MOSQ_ERR_SUCCESS;
}

@ -225,7 +225,7 @@ void plugin_persist__handle_retain_msg_delete(struct mosquitto__base_msg *msg)
{
UNUSED(msg);
}
void plugin_persist__handle_subscription_delete(struct mosquitto *context, const char *sub)
void plugin_persist__handle_subscription_delete(struct mosquitto *context, char *sub)
{
UNUSED(context);
UNUSED(sub);

@ -134,12 +134,10 @@ void retain__clean(struct mosquitto__retainhier **retainhier)
UNUSED(retainhier);
}
int retain__queue(struct mosquitto *context, const char *sub, uint8_t sub_qos, uint32_t subscription_identifier)
int retain__queue(struct mosquitto *context, const struct mosquitto_subscription *sub)
{
UNUSED(context);
UNUSED(sub);
UNUSED(sub_qos);
UNUSED(subscription_identifier);
return MOSQ_ERR_SUCCESS;
}
@ -224,7 +222,7 @@ void plugin_persist__handle_retain_msg_delete(struct mosquitto__base_msg *msg)
{
UNUSED(msg);
}
void plugin_persist__handle_subscription_delete(struct mosquitto *context, const char *sub)
void plugin_persist__handle_subscription_delete(struct mosquitto *context, char *sub)
{
UNUSED(context);
UNUSED(sub);

@ -35,13 +35,15 @@ static void TEST_sub_add_single(void)
struct mosquitto__config config;
struct mosquitto__listener listener;
struct mosquitto context;
struct mosquitto__subhier *sub;
struct mosquitto__subhier *subhier;
struct mosquitto_subscription sub;
int rc;
memset(&db, 0, sizeof(struct mosquitto_db));
memset(&config, 0, sizeof(struct mosquitto__config));
memset(&listener, 0, sizeof(struct mosquitto__listener));
memset(&context, 0, sizeof(struct mosquitto));
memset(&sub, 0, sizeof(sub));
context.id = "client";
@ -52,20 +54,21 @@ static void TEST_sub_add_single(void)
db__open(&config);
rc = sub__add(&context, "a/b/c/d/e", 0, 0, 0);
sub.topic = "a/b/c/d/e";
rc = sub__add(&context, &sub);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_PTR_NOT_NULL(db.subs);
if(db.subs){
sub = db.subs;
hier_quick_check(&sub, NULL, "");
hier_quick_check(&sub, NULL, "");
hier_quick_check(&sub, NULL, "a");
hier_quick_check(&sub, NULL, "b");
hier_quick_check(&sub, NULL, "c");
hier_quick_check(&sub, NULL, "d");
hier_quick_check(&sub, &context, "e");
CU_ASSERT_PTR_NULL(sub);
subhier = db.subs;
hier_quick_check(&subhier, NULL, "");
hier_quick_check(&subhier, NULL, "");
hier_quick_check(&subhier, NULL, "a");
hier_quick_check(&subhier, NULL, "b");
hier_quick_check(&subhier, NULL, "c");
hier_quick_check(&subhier, NULL, "d");
hier_quick_check(&subhier, &context, "e");
CU_ASSERT_PTR_NULL(subhier);
}
mosquitto__free(context.subs);
db__close();

Loading…
Cancel
Save