diff --git a/src/handle_unsubscribe.c b/src/handle_unsubscribe.c index 03d4025a..075bde44 100644 --- a/src/handle_unsubscribe.c +++ b/src/handle_unsubscribe.c @@ -31,6 +31,7 @@ int handle__unsubscribe(struct mosquitto_db *db, struct mosquitto *context) char *sub; int slen; int rc; + uint8_t reason; int reason_code_count = 0; int reason_code_max; uint8_t *reason_codes = NULL, *reason_tmp; @@ -89,11 +90,12 @@ int handle__unsubscribe(struct mosquitto_db *db, struct mosquitto *context) } log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub); - sub__remove(db, context, sub, db->subs); + rc = sub__remove(db, context, sub, db->subs, &reason); log__printf(NULL, MOSQ_LOG_UNSUBSCRIBE, "%s %s", context->id, sub); mosquitto__free(sub); + if(rc) return rc; - reason_codes[reason_code_count] = 0; + reason_codes[reason_code_count] = reason; reason_code_count++; if(reason_code_count == reason_code_max){ reason_tmp = mosquitto__realloc(reason_codes, reason_code_max*2); diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 3a2ac517..7d02f432 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -584,7 +584,7 @@ void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time); * ============================================================ */ 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); +int sub__remove(struct mosquitto_db *db, struct mosquitto *context, const char *sub, struct mosquitto__subhier *root, uint8_t *reason); 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, uint32_t subscription_identifier); diff --git a/src/subs.c b/src/subs.c index 3a7480ee..9fe52d52 100644 --- a/src/subs.c +++ b/src/subs.c @@ -324,7 +324,7 @@ static int sub__add_recurse(struct mosquitto_db *db, struct mosquitto *context, } } -static int sub__remove_recurse(struct mosquitto_db *db, struct mosquitto *context, struct mosquitto__subhier *subhier, struct sub__token *tokens) +static int sub__remove_recurse(struct mosquitto_db *db, struct mosquitto *context, struct mosquitto__subhier *subhier, struct sub__token *tokens, uint8_t *reason) { struct mosquitto__subhier *branch; struct mosquitto__subleaf *leaf; @@ -357,6 +357,7 @@ static int sub__remove_recurse(struct mosquitto_db *db, struct mosquitto *contex break; } } + *reason = 0; return MOSQ_ERR_SUCCESS; } leaf = leaf->next; @@ -366,7 +367,7 @@ static int sub__remove_recurse(struct mosquitto_db *db, struct mosquitto *contex HASH_FIND(hh, subhier->children, UHPA_ACCESS_TOPIC(tokens), tokens->topic_len, branch); if(branch){ - sub__remove_recurse(db, context, branch, tokens->next); + sub__remove_recurse(db, context, branch, tokens->next, reason); if(!branch->children && !branch->subs && !branch->retained){ HASH_DELETE(hh, subhier->children, branch); UHPA_FREE_TOPIC(branch); @@ -478,7 +479,7 @@ int sub__add(struct mosquitto_db *db, struct mosquitto *context, const char *sub return rc; } -int sub__remove(struct mosquitto_db *db, struct mosquitto *context, const char *sub, struct mosquitto__subhier *root) +int sub__remove(struct mosquitto_db *db, struct mosquitto *context, const char *sub, struct mosquitto__subhier *root, uint8_t *reason) { int rc = 0; struct mosquitto__subhier *subhier; @@ -491,7 +492,8 @@ int sub__remove(struct mosquitto_db *db, struct mosquitto *context, const char * HASH_FIND(hh, root, UHPA_ACCESS_TOPIC(tokens), tokens->topic_len, subhier); if(subhier){ - rc = sub__remove_recurse(db, context, subhier, tokens); + *reason = MQTT_RC_NO_SUBSCRIPTION_EXISTED; + rc = sub__remove_recurse(db, context, subhier, tokens, reason); } sub__topic_tokens_free(tokens); diff --git a/test/broker/02-unsubscribe-qos2-multiple-v5.py b/test/broker/02-unsubscribe-qos2-multiple-v5.py index 1e6c3f53..bbbc40cd 100755 --- a/test/broker/02-unsubscribe-qos2-multiple-v5.py +++ b/test/broker/02-unsubscribe-qos2-multiple-v5.py @@ -1,23 +1,29 @@ #!/usr/bin/env python -# Test whether a v5 UNSUBSCRIBE to multiple topics with QoS 2 results in the correct UNSUBACK packet. +# Test whether a v5 UNSUBSCRIBE to multiple topics with QoS 2 results in the +# correct UNSUBACK packet, when one subscription exists and the other does not. from mosq_test_helper import * rc = 1 -mid = 3 keepalive = 60 connect_packet = mosq_test.gen_connect("unsubscribe-qos2-test", keepalive=keepalive, proto_ver=5) connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) +mid = 1 +subscribe_packet = mosq_test.gen_subscribe(mid, "qos2/two", 2, proto_ver=5) +suback_packet = mosq_test.gen_suback(mid, 2, proto_ver=5) + +mid = 3 unsubscribe_packet = mosq_test.gen_unsubscribe_multiple(mid, ["qos2/one", "qos2/two"], proto_ver=5) -unsuback_packet = mosq_test.gen_unsuback(mid, proto_ver=5, reason_code=[0, 0]) +unsuback_packet = mosq_test.gen_unsuback(mid, proto_ver=5, reason_code=[17, 0]) port = mosq_test.get_port() broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port) try: sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port) + mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback") mosq_test.do_send_receive(sock, unsubscribe_packet, unsuback_packet, "unsuback") rc = 0 diff --git a/test/broker/02-unsubscribe-qos2-v5.py b/test/broker/02-unsubscribe-qos2-v5.py index a05a1539..2936c33b 100755 --- a/test/broker/02-unsubscribe-qos2-v5.py +++ b/test/broker/02-unsubscribe-qos2-v5.py @@ -12,7 +12,7 @@ connect_packet = mosq_test.gen_connect("unsubscribe-qos2-test", keepalive=keepal connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) unsubscribe_packet = mosq_test.gen_unsubscribe(mid, "qos2/test", proto_ver=5) -unsuback_packet = mosq_test.gen_unsuback(mid, proto_ver=5) +unsuback_packet = mosq_test.gen_unsuback(mid, proto_ver=5, reason_code=17) port = mosq_test.get_port() broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port)