From 99ace10dafa206a3370b6a390c015aaf18a6b7b1 Mon Sep 17 00:00:00 2001 From: Timo Gurr Date: Tue, 2 Jul 2019 18:36:41 +0200 Subject: [PATCH 01/39] Install pkg-config files into arch dependent locations also for CMake builds libmosquitto.pc and libmosquittopp.pc contain arch dependent information. The Makefile based build already does this correctly. Signed-off-by: Timo Gurr --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e707229b..63afe672 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,9 +108,9 @@ install(FILES mosquitto.conf aclfile.example pskfile.example pwfile.example DEST # ======================================== configure_file(libmosquitto.pc.in libmosquitto.pc @ONLY) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libmosquitto.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pkgconfig") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libmosquitto.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") configure_file(libmosquittopp.pc.in libmosquittopp.pc @ONLY) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libmosquittopp.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pkgconfig") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libmosquittopp.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") # ======================================== # Testing From 539c1b9bcb12ad4525e71f9ebbdc76245f2001ea Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 26 Sep 2019 11:13:18 +0100 Subject: [PATCH 02/39] Tests for zero length client id, plus fix for one case where it was allowed --- ChangeLog.txt | 4 + src/conf.c | 1 + test/broker/01-connect-invalid-id-0.py | 2 +- test/broker/01-connect-zero-length-id.py | 102 +++++++++++++++++++++++ test/broker/Makefile | 1 + test/broker/test.py | 1 + 6 files changed, 110 insertions(+), 1 deletion(-) create mode 100755 test/broker/01-connect-zero-length-id.py diff --git a/ChangeLog.txt b/ChangeLog.txt index 468ba715..65d94ad7 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +Broker: +- allow_zero_length_clientid wasn't being used by the default listener, making + it impossible to turn this option off. + 1.6.7 - 20190925 ================ diff --git a/src/conf.c b/src/conf.c index 53c622cf..1b9708d2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -529,6 +529,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config config->listeners[config->listener_count-1].security_options.auth_plugin_configs = config->default_listener.security_options.auth_plugin_configs; config->listeners[config->listener_count-1].security_options.auth_plugin_config_count = config->default_listener.security_options.auth_plugin_config_count; config->listeners[config->listener_count-1].security_options.allow_anonymous = config->default_listener.security_options.allow_anonymous; + config->listeners[config->listener_count-1].security_options.allow_zero_length_clientid = config->default_listener.security_options.allow_zero_length_clientid; } /* Default to drop to mosquitto user if we are privileged and no user specified. */ diff --git a/test/broker/01-connect-invalid-id-0.py b/test/broker/01-connect-invalid-id-0.py index 07dfcf74..39d580cd 100755 --- a/test/broker/01-connect-invalid-id-0.py +++ b/test/broker/01-connect-invalid-id-0.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Test whether a CONNECT with a zero length client id results in the correct CONNACK packet. - +# MQTT V3.1 only - zero length is invalid. from mosq_test_helper import * rc = 1 diff --git a/test/broker/01-connect-zero-length-id.py b/test/broker/01-connect-zero-length-id.py new file mode 100755 index 00000000..e9c6d8fe --- /dev/null +++ b/test/broker/01-connect-zero-length-id.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +# Test whether a CONNECT with a zero length client id results in the correct behaviour. + +# MQTT v3.1.1 - zero length is allowed, unless allow_zero_length_clientid is false, and unless clean_start is False. +# MQTT v5.0 - zero length is allowed, unless allow_zero_length_clientid is false + +from mosq_test_helper import * + +def write_config(filename, port1, port2, per_listener, allow_zero): + with open(filename, 'w') as f: + f.write("per_listener_settings %s\n" % (per_listener)) + f.write("port %d\n" % (port2)) + f.write("allow_zero_length_clientid %s\n" % (allow_zero)) + f.write("listener %d\n" % (port1)) + f.write("allow_zero_length_clientid %s\n" % (allow_zero)) + + +def do_test(per_listener, proto_ver, clean_start, allow_zero, client_port, expect_fail): + conf_file = os.path.basename(__file__).replace('.py', '.conf') + write_config(conf_file, port1, port2, per_listener, allow_zero) + + rc = 1 + keepalive = 10 + connect_packet = mosq_test.gen_connect("", keepalive=keepalive, proto_ver=proto_ver, clean_session=clean_start) + if proto_ver == 4: + if expect_fail == True: + connack_packet = mosq_test.gen_connack(rc=2, proto_ver=proto_ver) + else: + connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver) + else: + if expect_fail == True: + connack_packet = mosq_test.gen_connack(rc=128, proto_ver=proto_ver, properties=None) + else: + props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_ASSIGNED_CLIENT_IDENTIFIER, "auto-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") + connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver, properties=props) + # Remove the "xxxx" part - this means the front part of the packet + # is correct (so remaining length etc. is correct), but we don't + # need to match against the random id. + connack_packet = connack_packet[:-36] + + broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port1, use_conf=True) + + try: + sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=client_port) + sock.close() + rc = 0 + finally: + broker.terminate() + broker.wait() + (stdo, stde) = broker.communicate() + os.remove(conf_file) + if rc: + print(stde.decode('utf-8')) + print("per_listener:%s proto_ver:%d client_port:%d clean_start:%d allow_zero:%s" % (per_listener, proto_ver, client_port, clean_start, allow_zero)) + exit(rc) + + +(port1, port2) = mosq_test.get_port(2) + +test_v4 = True +test_v5 = True + +if test_v4 == True: + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=False, allow_zero="true", expect_fail=True) + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=False, allow_zero="true", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=False, allow_zero="false", expect_fail=True) + + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=False, allow_zero="true", expect_fail=True) + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=False, allow_zero="true", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + +if test_v5 == True: + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=False, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=False, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=False, allow_zero="false", expect_fail=True) + + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=False, allow_zero="true", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=True, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=True, allow_zero="false", expect_fail=True) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=False, allow_zero="true", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + +exit(0) diff --git a/test/broker/Makefile b/test/broker/Makefile index e4c32c63..3b78a1d2 100644 --- a/test/broker/Makefile +++ b/test/broker/Makefile @@ -44,6 +44,7 @@ ifeq ($(WITH_TLS),yes) else ./01-connect-uname-password-success-no-tls.py endif + ./01-connect-zero-length-id.py 02 : diff --git a/test/broker/test.py b/test/broker/test.py index 7a2f9f66..1fff9b7a 100755 --- a/test/broker/test.py +++ b/test/broker/test.py @@ -25,6 +25,7 @@ tests = [ (1, './01-connect-uname-password-denied.py'), (1, './01-connect-uname-password-success.py'), (1, './01-connect-uname-pwd-no-flag.py'), + (2, './01-connect-zero-length-id.py'), (1, './02-shared-qos0-v5.py'), (1, './02-subhier-crash.py'), From 4db1e80410979ac2fbd23ee231dd667b21a21822 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 26 Sep 2019 11:53:41 +0100 Subject: [PATCH 03/39] More allow_zero_length_clientid fixes. Closes #1429. Thanks to Dustin Sallings. --- ChangeLog.txt | 5 +++-- src/conf.c | 3 +++ test/broker/01-connect-zero-length-id.py | 27 ++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 65d94ad7..28fdc0ef 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,7 @@ Broker: -- allow_zero_length_clientid wasn't being used by the default listener, making - it impossible to turn this option off. +- Various fixes for `allow_zero_length_clientid` config, where this option was + not being set correctly. Closes #1429. + 1.6.7 - 20190925 ================ diff --git a/src/conf.c b/src/conf.c index 1b9708d2..9d30e30f 100644 --- a/src/conf.c +++ b/src/conf.c @@ -271,6 +271,7 @@ void config__init(struct mosquitto_db *db, struct mosquitto__config *config) config->default_listener.max_connections = -1; config->default_listener.protocol = mp_mqtt; config->default_listener.security_options.allow_anonymous = -1; + config->default_listener.security_options.allow_zero_length_clientid = true; config->default_listener.maximum_qos = 2; config->default_listener.max_topic_alias = 10; } @@ -471,6 +472,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config || config->default_listener.security_options.psk_file || config->default_listener.security_options.auth_plugin_config_count || config->default_listener.security_options.allow_anonymous != -1 + || config->default_listener.security_options.allow_zero_length_clientid != true ){ config->listener_count++; @@ -1389,6 +1391,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct } cur_listener->security_options.allow_anonymous = -1; + cur_listener->security_options.allow_zero_length_clientid = true; cur_listener->protocol = mp_mqtt; cur_listener->port = tmp_int; cur_listener->maximum_qos = 2; diff --git a/test/broker/01-connect-zero-length-id.py b/test/broker/01-connect-zero-length-id.py index e9c6d8fe..370199ab 100755 --- a/test/broker/01-connect-zero-length-id.py +++ b/test/broker/01-connect-zero-length-id.py @@ -11,9 +11,11 @@ def write_config(filename, port1, port2, per_listener, allow_zero): with open(filename, 'w') as f: f.write("per_listener_settings %s\n" % (per_listener)) f.write("port %d\n" % (port2)) - f.write("allow_zero_length_clientid %s\n" % (allow_zero)) + if allow_zero != "": + f.write("allow_zero_length_clientid %s\n" % (allow_zero)) f.write("listener %d\n" % (port1)) - f.write("allow_zero_length_clientid %s\n" % (allow_zero)) + if allow_zero != "": + f.write("allow_zero_length_clientid %s\n" % (allow_zero)) def do_test(per_listener, proto_ver, clean_start, allow_zero, client_port, expect_fail): @@ -53,6 +55,7 @@ def do_test(per_listener, proto_ver, clean_start, allow_zero, client_port, expec if rc: print(stde.decode('utf-8')) print("per_listener:%s proto_ver:%d client_port:%d clean_start:%d allow_zero:%s" % (per_listener, proto_ver, client_port, clean_start, allow_zero)) + print("port1:%d port2:%d" % (port1, port2)) exit(rc) @@ -80,6 +83,16 @@ if test_v4 == True: do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=False, allow_zero="true", expect_fail=True) do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="false", proto_ver=4, client_port=port1, clean_start=False, allow_zero="", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=4, client_port=port1, clean_start=False, allow_zero="", expect_fail=True) + + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="false", proto_ver=4, client_port=port2, clean_start=False, allow_zero="", expect_fail=True) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=4, client_port=port2, clean_start=False, allow_zero="", expect_fail=True) + if test_v5 == True: do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=True, allow_zero="true", expect_fail=False) do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=True, allow_zero="false", expect_fail=True) @@ -99,4 +112,14 @@ if test_v5 == True: do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=False, allow_zero="true", expect_fail=False) do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=False, allow_zero="false", expect_fail=True) + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port1, clean_start=False, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port1, clean_start=False, allow_zero="", expect_fail=False) + + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="false", proto_ver=5, client_port=port2, clean_start=False, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=True, allow_zero="", expect_fail=False) + do_test(per_listener="true", proto_ver=5, client_port=port2, clean_start=False, allow_zero="", expect_fail=False) + exit(0) From 093c8f90f5b46f5bbeceb2f6e470619c8050ca2e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 26 Sep 2019 16:47:34 +0100 Subject: [PATCH 04/39] Fix publish props not being passed to v5 msg callback for QoS 2 msgs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #1432. Thanks to Magnus GalÄen. --- ChangeLog.txt | 4 ++ lib/handle_publish.c | 2 +- lib/handle_pubrel.c | 2 +- test/lib/11-prop-recv-qos0.py | 58 ++++++++++++++++++++++++ test/lib/11-prop-recv-qos1.py | 62 +++++++++++++++++++++++++ test/lib/11-prop-recv-qos2.py | 66 +++++++++++++++++++++++++++ test/lib/Makefile | 3 ++ test/lib/c/11-prop-recv-qos0.c | 81 +++++++++++++++++++++++++++++++++ test/lib/c/11-prop-recv-qos1.c | 81 +++++++++++++++++++++++++++++++++ test/lib/c/11-prop-recv-qos2.c | 82 ++++++++++++++++++++++++++++++++++ test/lib/c/Makefile | 3 ++ 11 files changed, 442 insertions(+), 2 deletions(-) create mode 100755 test/lib/11-prop-recv-qos0.py create mode 100755 test/lib/11-prop-recv-qos1.py create mode 100755 test/lib/11-prop-recv-qos2.py create mode 100644 test/lib/c/11-prop-recv-qos0.c create mode 100644 test/lib/c/11-prop-recv-qos1.c create mode 100644 test/lib/c/11-prop-recv-qos2.c diff --git a/ChangeLog.txt b/ChangeLog.txt index 28fdc0ef..623099b4 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,10 @@ Broker: - Various fixes for `allow_zero_length_clientid` config, where this option was not being set correctly. Closes #1429. +Client library: +- Fix publish properties not being passed to on_message_v5 callback for QoS 2 + messages. Closes #1432. + 1.6.7 - 20190925 ================ diff --git a/lib/handle_publish.c b/lib/handle_publish.c index 909fbaf5..e06b3249 100644 --- a/lib/handle_publish.c +++ b/lib/handle_publish.c @@ -152,13 +152,13 @@ int handle__publish(struct mosquitto *mosq) mosquitto_property_free_all(&properties); return rc; case 2: + message->properties = properties; util__decrement_receive_quota(mosq); rc = send__pubrec(mosq, message->msg.mid, 0); pthread_mutex_lock(&mosq->msgs_in.mutex); message->state = mosq_ms_wait_for_pubrel; message__queue(mosq, message, mosq_md_in); pthread_mutex_unlock(&mosq->msgs_in.mutex); - mosquitto_property_free_all(&properties); return rc; default: message__cleanup(&message); diff --git a/lib/handle_pubrel.c b/lib/handle_pubrel.c index c33d4cbd..e7a36292 100644 --- a/lib/handle_pubrel.c +++ b/lib/handle_pubrel.c @@ -114,7 +114,7 @@ int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq) } if(mosq->on_message_v5){ mosq->in_callback = true; - mosq->on_message_v5(mosq, mosq->userdata, &message->msg, properties); + mosq->on_message_v5(mosq, mosq->userdata, &message->msg, message->properties); mosq->in_callback = false; } pthread_mutex_unlock(&mosq->callback_mutex); diff --git a/test/lib/11-prop-recv-qos0.py b/test/lib/11-prop-recv-qos0.py new file mode 100755 index 00000000..f3e22843 --- /dev/null +++ b/test/lib/11-prop-recv-qos0.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +# Check whether the v5 message callback gets the properties + +from mosq_test_helper import * + +port = mosq_test.get_lib_port() + +rc = 1 +keepalive = 60 +connect_packet = mosq_test.gen_connect("prop-test", keepalive=keepalive, proto_ver=5) +connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) + +props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_CONTENT_TYPE, "plain/text") +props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, "msg/123") +publish_packet = mosq_test.gen_publish("prop/test", qos=0, payload="message", proto_ver=5, properties=props) + +ok_packet = mosq_test.gen_publish("ok", qos=0, payload="ok", proto_ver=5) + +disconnect_packet = mosq_test.gen_disconnect(proto_ver=5) + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +sock.settimeout(10) +sock.bind(('', port)) +sock.listen(5) + +client_args = sys.argv[1:] +env = dict(os.environ) +env['LD_LIBRARY_PATH'] = '../../lib:../../lib/cpp' +try: + pp = env['PYTHONPATH'] +except KeyError: + pp = '' +env['PYTHONPATH'] = '../../lib/python:'+pp +client = mosq_test.start_client(filename=sys.argv[1].replace('/', '-'), cmd=client_args, env=env, port=port) + +try: + (conn, address) = sock.accept() + conn.settimeout(10) + + if mosq_test.expect_packet(conn, "connect", connect_packet): + conn.send(connack_packet) + + conn.send(publish_packet) + if mosq_test.expect_packet(conn, "ok", ok_packet): + rc = 0 + + conn.close() +finally: + client.terminate() + client.wait() + if rc: + (stdo, stde) = client.communicate() + print(stde) + sock.close() + +exit(rc) diff --git a/test/lib/11-prop-recv-qos1.py b/test/lib/11-prop-recv-qos1.py new file mode 100755 index 00000000..194a561c --- /dev/null +++ b/test/lib/11-prop-recv-qos1.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +# Check whether the v5 message callback gets the properties + +from mosq_test_helper import * + +port = mosq_test.get_lib_port() + +rc = 1 +keepalive = 60 +connect_packet = mosq_test.gen_connect("prop-test", keepalive=keepalive, proto_ver=5) +connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) + + +mid = 1 +props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_CONTENT_TYPE, "plain/text") +props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, "msg/123") +publish_packet = mosq_test.gen_publish("prop/test", mid=mid, qos=1, payload="message", proto_ver=5, properties=props) +puback_packet = mosq_test.gen_puback(mid=mid, proto_ver=5) + +ok_packet = mosq_test.gen_publish("ok", qos=0, payload="ok", proto_ver=5) + +disconnect_packet = mosq_test.gen_disconnect(proto_ver=5) + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +sock.settimeout(10) +sock.bind(('', port)) +sock.listen(5) + +client_args = sys.argv[1:] +env = dict(os.environ) +env['LD_LIBRARY_PATH'] = '../../lib:../../lib/cpp' +try: + pp = env['PYTHONPATH'] +except KeyError: + pp = '' +env['PYTHONPATH'] = '../../lib/python:'+pp +client = mosq_test.start_client(filename=sys.argv[1].replace('/', '-'), cmd=client_args, env=env, port=port) + +try: + (conn, address) = sock.accept() + conn.settimeout(10) + + if mosq_test.expect_packet(conn, "connect", connect_packet): + conn.send(connack_packet) + + conn.send(publish_packet) + if mosq_test.expect_packet(conn, "puback", puback_packet): + if mosq_test.expect_packet(conn, "ok", ok_packet): + rc = 0 + + conn.close() +finally: + client.terminate() + client.wait() + if rc: + (stdo, stde) = client.communicate() + print(stde) + sock.close() + +exit(rc) diff --git a/test/lib/11-prop-recv-qos2.py b/test/lib/11-prop-recv-qos2.py new file mode 100755 index 00000000..705bf0a9 --- /dev/null +++ b/test/lib/11-prop-recv-qos2.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +# Check whether the v5 message callback gets the properties + +from mosq_test_helper import * + +port = mosq_test.get_lib_port() + +rc = 1 +keepalive = 60 +connect_packet = mosq_test.gen_connect("prop-test", keepalive=keepalive, proto_ver=5) +connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) + + +mid = 1 +props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_CONTENT_TYPE, "plain/text") +props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_RESPONSE_TOPIC, "msg/123") +publish_packet = mosq_test.gen_publish("prop/test", mid=mid, qos=2, payload="message", proto_ver=5, properties=props) +pubrec_packet = mosq_test.gen_pubrec(mid=mid, proto_ver=5) +pubrel_packet = mosq_test.gen_pubrel(mid=mid, proto_ver=5) +pubcomp_packet = mosq_test.gen_pubcomp(mid=mid, proto_ver=5) + +ok_packet = mosq_test.gen_publish("ok", qos=0, payload="ok", proto_ver=5) + +disconnect_packet = mosq_test.gen_disconnect(proto_ver=5) + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +sock.settimeout(10) +sock.bind(('', port)) +sock.listen(5) + +client_args = sys.argv[1:] +env = dict(os.environ) +env['LD_LIBRARY_PATH'] = '../../lib:../../lib/cpp' +try: + pp = env['PYTHONPATH'] +except KeyError: + pp = '' +env['PYTHONPATH'] = '../../lib/python:'+pp +client = mosq_test.start_client(filename=sys.argv[1].replace('/', '-'), cmd=client_args, env=env, port=port) + +try: + (conn, address) = sock.accept() + conn.settimeout(10) + + if mosq_test.expect_packet(conn, "connect", connect_packet): + conn.send(connack_packet) + + conn.send(publish_packet) + if mosq_test.expect_packet(conn, "pubrec", pubrec_packet): + conn.send(pubrel_packet) + if mosq_test.expect_packet(conn, "pubcomp", pubcomp_packet): + if mosq_test.expect_packet(conn, "ok", ok_packet): + rc = 0 + + conn.close() +finally: + client.terminate() + client.wait() + if rc: + (stdo, stde) = client.communicate() + print(stde) + sock.close() + +exit(rc) diff --git a/test/lib/Makefile b/test/lib/Makefile index e02cc5c0..3462e252 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -68,6 +68,9 @@ endif ./11-prop-oversize-packet.py $@/11-prop-oversize-packet.test ./11-prop-send-content-type.py $@/11-prop-send-content-type.test ./11-prop-send-payload-format.py $@/11-prop-send-payload-format.test + ./11-prop-recv-qos0.py $@/11-prop-recv-qos0.test + ./11-prop-recv-qos1.py $@/11-prop-recv-qos1.test + ./11-prop-recv-qos2.py $@/11-prop-recv-qos2.test clean : $(MAKE) -C c clean diff --git a/test/lib/c/11-prop-recv-qos0.c b/test/lib/c/11-prop-recv-qos0.c new file mode 100644 index 00000000..257bc549 --- /dev/null +++ b/test/lib/c/11-prop-recv-qos0.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +static int run = -1; +static int sent_mid = -1; + +void on_connect(struct mosquitto *mosq, void *obj, int rc) +{ + int rc2; + mosquitto_property *proplist = NULL; + + if(rc){ + exit(1); + } +} + + +void on_message_v5(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg, const mosquitto_property *properties) +{ + int rc; + char *str; + + if(properties){ + if(mosquitto_property_read_string(properties, MQTT_PROP_CONTENT_TYPE, &str, false)){ + rc = strcmp(str, "plain/text"); + free(str); + + if(rc == 0){ + if(mosquitto_property_read_string(properties, MQTT_PROP_RESPONSE_TOPIC, &str, false)){ + rc = strcmp(str, "msg/123"); + free(str); + + if(rc == 0){ + if(msg->qos == 0){ + mosquitto_publish(mosq, NULL, "ok", 2, "ok", 0, 0); + return; + } + } + } + } + } + } + + /* No matching message, so quit with an error */ + exit(1); +} + + +void on_publish(struct mosquitto *mosq, void *obj, int mid) +{ + run = 0; +} + +int main(int argc, char *argv[]) +{ + int rc; + int tmp; + struct mosquitto *mosq; + + int port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("prop-test", true, NULL); + mosquitto_connect_callback_set(mosq, on_connect); + mosquitto_message_v5_callback_set(mosq, on_message_v5); + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5); + + rc = mosquitto_connect(mosq, "localhost", port, 60); + + while(run == -1){ + rc = mosquitto_loop(mosq, -1, 1); + } + + mosquitto_lib_cleanup(); + return run; +} diff --git a/test/lib/c/11-prop-recv-qos1.c b/test/lib/c/11-prop-recv-qos1.c new file mode 100644 index 00000000..e3db7745 --- /dev/null +++ b/test/lib/c/11-prop-recv-qos1.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +static int run = -1; +static int sent_mid = -1; + +void on_connect(struct mosquitto *mosq, void *obj, int rc) +{ + int rc2; + mosquitto_property *proplist = NULL; + + if(rc){ + exit(1); + } +} + + +void on_message_v5(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg, const mosquitto_property *properties) +{ + int rc; + char *str; + + if(properties){ + if(mosquitto_property_read_string(properties, MQTT_PROP_CONTENT_TYPE, &str, false)){ + rc = strcmp(str, "plain/text"); + free(str); + + if(rc == 0){ + if(mosquitto_property_read_string(properties, MQTT_PROP_RESPONSE_TOPIC, &str, false)){ + rc = strcmp(str, "msg/123"); + free(str); + + if(rc == 0){ + if(msg->qos == 1){ + mosquitto_publish(mosq, NULL, "ok", 2, "ok", 0, 0); + return; + } + } + } + } + } + } + + /* No matching message, so quit with an error */ + exit(1); +} + + +void on_publish(struct mosquitto *mosq, void *obj, int mid) +{ + run = 0; +} + +int main(int argc, char *argv[]) +{ + int rc; + int tmp; + struct mosquitto *mosq; + + int port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("prop-test", true, NULL); + mosquitto_connect_callback_set(mosq, on_connect); + mosquitto_message_v5_callback_set(mosq, on_message_v5); + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5); + + rc = mosquitto_connect(mosq, "localhost", port, 60); + + while(run == -1){ + rc = mosquitto_loop(mosq, -1, 1); + } + + mosquitto_lib_cleanup(); + return run; +} diff --git a/test/lib/c/11-prop-recv-qos2.c b/test/lib/c/11-prop-recv-qos2.c new file mode 100644 index 00000000..23527096 --- /dev/null +++ b/test/lib/c/11-prop-recv-qos2.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include + +static int run = -1; +static int sent_mid = -1; + +void on_connect(struct mosquitto *mosq, void *obj, int rc) +{ + int rc2; + mosquitto_property *proplist = NULL; + + if(rc){ + exit(1); + } +} + + +void on_message_v5(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg, const mosquitto_property *properties) +{ + int rc; + char *str; + + if(properties){ + if(mosquitto_property_read_string(properties, MQTT_PROP_CONTENT_TYPE, &str, false)){ + rc = strcmp(str, "plain/text"); + free(str); + + if(rc == 0){ + if(mosquitto_property_read_string(properties, MQTT_PROP_RESPONSE_TOPIC, &str, false)){ + rc = strcmp(str, "msg/123"); + free(str); + + if(rc == 0){ + if(msg->qos == 2){ + mosquitto_publish(mosq, NULL, "ok", 2, "ok", 0, 0); + return; + } + } + } + } + } + } + + /* No matching message, so quit with an error */ + exit(1); +} + + +void on_publish(struct mosquitto *mosq, void *obj, int mid) +{ + run = 0; +} + +int main(int argc, char *argv[]) +{ + int rc; + int tmp; + struct mosquitto *mosq; + + int port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("prop-test", true, NULL); + mosquitto_connect_callback_set(mosq, on_connect); + mosquitto_message_v5_callback_set(mosq, on_message_v5); + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5); + + rc = mosquitto_connect(mosq, "localhost", port, 60); + + while(run == -1){ + rc = mosquitto_loop(mosq, -1, 1); + } + + mosquitto_destroy(mosq); + mosquitto_lib_cleanup(); + return run; +} diff --git a/test/lib/c/Makefile b/test/lib/c/Makefile index b42a768f..79d1fc03 100644 --- a/test/lib/c/Makefile +++ b/test/lib/c/Makefile @@ -46,6 +46,9 @@ SRC = \ 08-ssl-fake-cacert.c \ 09-util-topic-tokenise.c \ 11-prop-oversize-packet.c \ + 11-prop-recv-qos0.c \ + 11-prop-recv-qos1.c \ + 11-prop-recv-qos2.c \ 11-prop-send-payload-format.c \ 11-prop-send-content-type.c From b942b73b6d49dee3e308505227073ddc97f82977 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 1 Oct 2019 16:57:54 +0100 Subject: [PATCH 05/39] Fix incorrect memory tracking causing problems with memory_limit option. Closes #1437. Thanks to Guillaume Bour. --- ChangeLog.txt | 2 ++ src/subs.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 623099b4..1b8e2355 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,8 @@ Broker: - Various fixes for `allow_zero_length_clientid` config, where this option was not being set correctly. Closes #1429. +- Fix incorrect memory tracking causing problems with memory_limit option. + Closes #1437. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/subs.c b/src/subs.c index c059874f..266669e8 100644 --- a/src/subs.c +++ b/src/subs.c @@ -684,7 +684,7 @@ struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent } child->parent = parent; child->topic_len = len; - child->topic = malloc(len+1); + child->topic = mosquitto__malloc(len+1); if(!child->topic){ child->topic_len = 0; mosquitto__free(child); From c471dfb201d77f96ab678564af2840249c0df184 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 2 Oct 2019 13:00:01 +0100 Subject: [PATCH 06/39] Fix sub topics being limited to 200 chars instead of 200 levels Closes #1441. Thanks to Christoph Krey. --- ChangeLog.txt | 2 + src/subs.c | 2 +- test/broker/02-subpub-qos0-long-topic.py | 50 ++++++++++++++++++++++++ test/broker/Makefile | 1 + test/broker/test.py | 1 + 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100755 test/broker/02-subpub-qos0-long-topic.py diff --git a/ChangeLog.txt b/ChangeLog.txt index 1b8e2355..bcf7c3c8 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -3,6 +3,8 @@ Broker: not being set correctly. Closes #1429. - Fix incorrect memory tracking causing problems with memory_limit option. Closes #1437. +- Fix subscription topics being limited to 200 characters instead of 200 + hierarchy levels. Closes #1441. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/subs.c b/src/subs.c index 266669e8..fc62bef8 100644 --- a/src/subs.c +++ b/src/subs.c @@ -243,9 +243,9 @@ static int sub__topic_tokenise(const char *subtopic, struct sub__token **topics) stop = 0; for(i=start; i Date: Wed, 2 Oct 2019 13:37:52 +0100 Subject: [PATCH 07/39] Only a single CRL could be loaded at once. This has been fixed. Closes #1442. Thanks to charlemagnelasse. --- ChangeLog.txt | 2 ++ src/net.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index bcf7c3c8..e62246a1 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -5,6 +5,8 @@ Broker: Closes #1437. - Fix subscription topics being limited to 200 characters instead of 200 hierarchy levels. Closes #1441. +- Only a single CRL could be loaded at once. This has been fixed. + Closes #1442. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/net.c b/src/net.c index 392972f8..cc115e55 100644 --- a/src/net.c +++ b/src/net.c @@ -426,7 +426,7 @@ int net__load_crl_file(struct mosquitto__listener *listener) } lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); rc = X509_load_crl_file(lookup, listener->crlfile, X509_FILETYPE_PEM); - if(rc != 1){ + if(rc < 1){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load certificate revocation file \"%s\". Check crlfile.", listener->crlfile); net__print_error(MOSQ_LOG_ERR, "Error: %s"); return 1; From ede9f2a51d753ab06c3d3ad0860c75f215fa6471 Mon Sep 17 00:00:00 2001 From: Marek Wodzinski Date: Sun, 6 Oct 2019 01:39:27 +0200 Subject: [PATCH 08/39] mosquitto_pub: split main loop. Main loop has two different logics inside: one for stdin input, second for all other cases. Exit loop condition is also different for both variants. This commit splits these two variants into two separate loops. Signed-off-by: Marek Wodzinski --- client/pub_client.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/client/pub_client.c b/client/pub_client.c index 0debcaee..aa435be8 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -223,7 +223,7 @@ int pub_shared_loop(struct mosquitto *mosq) { int read_len; int pos; - int rc, rc2; + int rc; char *buf2; int buf_len_actual; int mode; @@ -239,10 +239,7 @@ int pub_shared_loop(struct mosquitto *mosq) if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_start(mosq); stdin_finished = false; - } - - do{ - if(mode == MSGMODE_STDIN_LINE){ + do{ if(status == STATUS_CONNACK_RECVD){ pos = 0; read_len = line_buf_len; @@ -250,9 +247,9 @@ int pub_shared_loop(struct mosquitto *mosq) buf_len_actual = strlen(line_buf); if(line_buf[buf_len_actual-1] == '\n'){ line_buf[buf_len_actual-1] = '\0'; - rc2 = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); - if(rc2){ - err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc2); + rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); + if(rc){ + err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc); mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); } break; @@ -297,11 +294,13 @@ int pub_shared_loop(struct mosquitto *mosq) nanosleep(&ts, NULL); #endif } - rc = MOSQ_ERR_SUCCESS; - }else{ + }while(stdin_finished == false); + mosquitto_loop_stop(mosq, false); + }else{ + do{ rc = mosquitto_loop(mosq, loop_delay, 1); if(ready_for_repeat && check_repeat_time()){ - rc = 0; + rc = MOSQ_ERR_SUCCESS; switch(cfg.pub_mode){ case MSGMODE_CMD: case MSGMODE_FILE: @@ -311,19 +310,14 @@ int pub_shared_loop(struct mosquitto *mosq) case MSGMODE_NULL: rc = my_publish(mosq, &mid_sent, cfg.topic, 0, NULL, cfg.qos, cfg.retain); break; - case MSGMODE_STDIN_LINE: - break; } if(rc){ err_printf(&cfg, "Error sending repeat publish: %s", mosquitto_strerror(rc)); } } - } - }while(rc == MOSQ_ERR_SUCCESS && stdin_finished == false); - - if(mode == MSGMODE_STDIN_LINE){ - mosquitto_loop_stop(mosq, false); + }while(rc == MOSQ_ERR_SUCCESS); } + if(status == STATUS_DISCONNECTED){ return MOSQ_ERR_SUCCESS; }else{ From 8a4ae28fa926589e9891674ca4424dc703ad2d88 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 9 Oct 2019 14:01:44 +0100 Subject: [PATCH 09/39] Fix duplicate cfg definition in rr_client. Closes #1453. Thanks to jveber. --- ChangeLog.txt | 3 +++ client/rr_client.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index e62246a1..7bbfc626 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -12,6 +12,9 @@ Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 messages. Closes #1432. +Clients: +- Fix duplicate cfg definition in rr_client. Closes #1453. + 1.6.7 - 20190925 ================ diff --git a/client/rr_client.c b/client/rr_client.c index 44f105b0..9d5e9d1e 100644 --- a/client/rr_client.c +++ b/client/rr_client.c @@ -47,7 +47,8 @@ enum rr__state { static enum rr__state client_state = rr_s_new; -struct mosq_config cfg; +extern struct mosq_config cfg; + bool process_messages = true; int msg_count = 0; struct mosquitto *mosq = NULL; From 50c9a4b0b02249f2aa0903977878eae6dd5e5ef0 Mon Sep 17 00:00:00 2001 From: majekw Date: Sun, 6 Oct 2019 21:09:28 +0200 Subject: [PATCH 10/39] Fix `mosquitto_pub -l` hang when stdin stream ends. Closes #1448. Signed-off-by: Marek Wodzinski --- ChangeLog.txt | 1 + client/pub_client.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7bbfc626..36550d50 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -14,6 +14,7 @@ Client library: Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. +- Fix `mosquitto_pub -l` hang when stdin stream ends. Closes #1448. 1.6.7 - 20190925 diff --git a/client/pub_client.c b/client/pub_client.c index 0debcaee..e44c6db0 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -283,7 +283,8 @@ int pub_shared_loop(struct mosquitto *mosq) /* Not end of stdin, so we've lost our connection and must * reconnect */ } - }else if(status == STATUS_WAITING){ + } + if(status == STATUS_WAITING){ if(last_mid_sent == last_mid && disconnect_sent == false){ mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); disconnect_sent = true; From 253326dcc94b33e3a32f0321f07011a50cd6578d Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 15 Oct 2019 15:32:24 +0100 Subject: [PATCH 11/39] Fix problems with reloading config when `per_listener_settings` was true. Closes #1459. Thanks to Thomas Markin Klein. --- ChangeLog.txt | 2 ++ src/conf.c | 1 + 2 files changed, 3 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7bbfc626..11627703 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -7,6 +7,8 @@ Broker: hierarchy levels. Closes #1441. - Only a single CRL could be loaded at once. This has been fixed. Closes #1442. +- Fix problems with reloading config when `per_listener_settings` was true. + Closes #1459. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/conf.c b/src/conf.c index 9d30e30f..8b6eb59b 100644 --- a/src/conf.c +++ b/src/conf.c @@ -641,6 +641,7 @@ int config__read(struct mosquitto_db *db, struct mosquitto__config *config, bool config__init_reload(db, &config_reload); config_reload.listeners = config->listeners; config_reload.listener_count = config->listener_count; + cur_security_options = NULL; rc = config__read_file(&config_reload, reload, db->config_file, &cr, 0, &lineno); }else{ rc = config__read_file(config, reload, db->config_file, &cr, 0, &lineno); From 47dadb902dacb4d963ba9ec34803f62ea418e964 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 24 Oct 2019 22:57:05 +0100 Subject: [PATCH 12/39] Only call ERR_clear_error() after an error has occurred. --- lib/net_mosq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net_mosq.c b/lib/net_mosq.c index c2907452..051240dd 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -856,7 +856,6 @@ ssize_t net__read(struct mosquitto *mosq, void *buf, size_t count) errno = 0; #ifdef WITH_TLS if(mosq->ssl){ - ERR_clear_error(); ret = SSL_read(mosq->ssl, buf, count); if(ret <= 0){ err = SSL_get_error(mosq->ssl, ret); @@ -871,6 +870,7 @@ ssize_t net__read(struct mosquitto *mosq, void *buf, size_t count) net__print_ssl_error(mosq); errno = EPROTO; } + ERR_clear_error(); #ifdef WIN32 WSASetLastError(errno); #endif @@ -904,7 +904,6 @@ ssize_t net__write(struct mosquitto *mosq, void *buf, size_t count) #ifdef WITH_TLS if(mosq->ssl){ mosq->want_write = false; - ERR_clear_error(); ret = SSL_write(mosq->ssl, buf, count); if(ret < 0){ err = SSL_get_error(mosq->ssl, ret); @@ -919,6 +918,7 @@ ssize_t net__write(struct mosquitto *mosq, void *buf, size_t count) net__print_ssl_error(mosq); errno = EPROTO; } + ERR_clear_error(); #ifdef WIN32 WSASetLastError(errno); #endif From 1d468708de7fff69b97128a5b7bc1582b69ab677 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 29 Oct 2019 14:41:39 +0000 Subject: [PATCH 13/39] Fix mosquitto_rr.exe not being included in Windows installers. Closes #1463. Thanks to raisonchacko. --- ChangeLog.txt | 2 ++ installer/mosquitto.nsi | 2 ++ installer/mosquitto64.nsi | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 11627703..18218058 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -17,6 +17,8 @@ Client library: Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. +Installer: +- Fix mosquitto_rr.exe not being included in Windows installers. Closes #1463. 1.6.7 - 20190925 ================ diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index ee5c0450..73a165f8 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -45,6 +45,7 @@ Section "Files" SecInstall File "..\build\src\Release\mosquitto_passwd.exe" File "..\build\client\Release\mosquitto_pub.exe" File "..\build\client\Release\mosquitto_sub.exe" + File "..\build\client\Release\mosquitto_rr.exe" File "..\build\lib\Release\mosquitto.dll" File "..\build\lib\cpp\Release\mosquittopp.dll" File "..\aclfile.example" @@ -90,6 +91,7 @@ Section "Uninstall" Delete "$INSTDIR\mosquitto_passwd.exe" Delete "$INSTDIR\mosquitto_pub.exe" Delete "$INSTDIR\mosquitto_sub.exe" + Delete "$INSTDIR\mosquitto_rr.exe" Delete "$INSTDIR\mosquitto.dll" Delete "$INSTDIR\mosquittopp.dll" Delete "$INSTDIR\aclfile.example" diff --git a/installer/mosquitto64.nsi b/installer/mosquitto64.nsi index 7e8bf341..f797a387 100644 --- a/installer/mosquitto64.nsi +++ b/installer/mosquitto64.nsi @@ -46,6 +46,7 @@ Section "Files" SecInstall File "..\build64\src\Release\mosquitto_passwd.exe" File "..\build64\client\Release\mosquitto_pub.exe" File "..\build64\client\Release\mosquitto_sub.exe" + File "..\build64\client\Release\mosquitto_rr.exe" File "..\build64\lib\Release\mosquitto.dll" File "..\build64\lib\cpp\Release\mosquittopp.dll" File "..\aclfile.example" @@ -91,6 +92,7 @@ Section "Uninstall" Delete "$INSTDIR\mosquitto_passwd.exe" Delete "$INSTDIR\mosquitto_pub.exe" Delete "$INSTDIR\mosquitto_sub.exe" + Delete "$INSTDIR\mosquitto_rr.exe" Delete "$INSTDIR\mosquitto.dll" Delete "$INSTDIR\mosquittopp.dll" Delete "$INSTDIR\aclfile.example" From ba3d9969745b2186224b2ccfb1ceb7654cafe777 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 30 Oct 2019 15:53:43 +0000 Subject: [PATCH 14/39] Allow passing LDADD to broker, client, and passwd. --- config.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.mk b/config.mk index 4b869e6b..b37ff330 100644 --- a/config.mk +++ b/config.mk @@ -312,3 +312,7 @@ ifeq ($(WITH_COVERAGE),yes) CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -coverage CLIENT_LDFLAGS:=$(CLIENT_LDFLAGS) -coverage endif + +BROKER_LDADD:=${BROKER_LDADD} ${LDADD} +CLIENT_LDADD:=${CLIENT_LDADD} ${LDADD} +PASSWD_LDADD:=${PASSWD_LDADD} ${LDADD} From 463fe8fc6c831ea28872f196d06757a37bb31847 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 31 Oct 2019 11:58:54 +0000 Subject: [PATCH 15/39] Fix document issues in mosquitto.h. Closes #1478. Thanks to Liam Fry. --- ChangeLog.txt | 1 + lib/mosquitto.h | 287 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 194 insertions(+), 94 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 18218058..3ed84e05 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -13,6 +13,7 @@ Broker: Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 messages. Closes #1432. +- Fix documentation issues in mosquitto.h. Closes #1478. Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. diff --git a/lib/mosquitto.h b/lib/mosquitto.h index a868f995..62243f66 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -392,11 +392,9 @@ libmosq_EXPORT int mosquitto_will_clear(struct mosquitto *mosq); /* * Function: mosquitto_username_pw_set * - * Configure username and password for a mosquitton instance. This is only - * supported by brokers that implement the MQTT spec v3.1. By default, no - * username or password will be sent. - * If username is NULL, the password argument is ignored. - * This must be called before calling mosquitto_connect(). + * Configure username and password for a mosquitto instance. By default, no + * username or password will be sent. For v3.1 and v3.1.1 clients, if username + * is NULL, the password argument is ignored. * * This is must be called before calling . * @@ -480,8 +478,13 @@ libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *ho * Function: mosquitto_connect_bind_v5 * * Connect to an MQTT broker. This extends the functionality of - * by adding the bind_address parameter. Use this function - * if you need to restrict network communication over a particular interface. + * by adding the bind_address parameter and MQTT v5 + * properties. Use this function if you need to restrict network communication + * over a particular interface. + * + * Use e.g. and similar to create a list of + * properties, then attach them to this publish. Properties need freeing with + * . * * Parameters: * mosq - a valid mosquitto instance. @@ -695,8 +698,8 @@ libmosq_EXPORT int mosquitto_disconnect(struct mosquitto *mosq); * * Disconnect from the broker, with attached MQTT properties. * - * Use to create a list of properties, then attach - * them to this publish. Properties need freeing with + * Use e.g. and similar to create a list of + * properties, then attach them to this publish. Properties need freeing with * . * * Parameters: @@ -767,8 +770,8 @@ libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const cha * * Publish a message on a given topic, with attached MQTT properties. * - * Use to create a list of properties, then attach - * them to this publish. Properties need freeing with + * Use e.g. and similar to create a list of + * properties, then attach them to this publish. Properties need freeing with * . * * Requires the mosquitto instance to be connected with MQTT 5. @@ -849,8 +852,8 @@ libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const c * * Subscribe to a topic, with attached MQTT properties. * - * Use to create a list of properties, then attach - * them to this subscribe. Properties need freeing with + * Use e.g. and similar to create a list of + * properties, then attach them to this publish. Properties need freeing with * . * * Requires the mosquitto instance to be connected with MQTT 5. @@ -866,26 +869,26 @@ libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const c * qos - the requested Quality of Service for this subscription. * options - options to apply to this subscription, OR'd together. Set to 0 to * use the default options, otherwise choose from the list: - * MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client + * MQTT_SUB_OPT_NO_LOCAL: with this option set, if this client * publishes to a topic to which it is subscribed, the * broker will not publish the message back to the * client. - * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages + * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED: with this option set, messages * published for this subscription will keep the * retain flag as was set by the publishing client. * The default behaviour without this option set has * the retain flag indicating whether a message is * fresh/stale. - * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set, + * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS: with this option set, * pre-existing retained messages are sent as soon as * the subscription is made, even if the subscription * already exists. This is the default behaviour, so * it is not necessary to set this option. - * MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing + * MQTT_SUB_OPT_SEND_RETAIN_NEW: with this option set, pre-existing * retained messages for this subscription will be * sent when the subscription is made, but only if the * subscription does not already exist. - * MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set, + * MQTT_SUB_OPT_SEND_RETAIN_NEVER: with this option set, * pre-existing retained messages will never be sent * for this subscription. * properties - a valid mosquitto_property list, or NULL. @@ -924,26 +927,26 @@ libmosq_EXPORT int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, cons * options - options to apply to this subscription, OR'd together. This * argument is not used for MQTT v3 susbcriptions. Set to 0 to use * the default options, otherwise choose from the list: - * MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client + * MQTT_SUB_OPT_NO_LOCAL: with this option set, if this client * publishes to a topic to which it is subscribed, the * broker will not publish the message back to the * client. - * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages + * MQTT_SUB_OPT_RETAIN_AS_PUBLISHED: with this option set, messages * published for this subscription will keep the * retain flag as was set by the publishing client. * The default behaviour without this option set has * the retain flag indicating whether a message is * fresh/stale. - * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set, + * MQTT_SUB_OPT_SEND_RETAIN_ALWAYS: with this option set, * pre-existing retained messages are sent as soon as * the subscription is made, even if the subscription * already exists. This is the default behaviour, so * it is not necessary to set this option. - * MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing + * MQTT_SUB_OPT_SEND_RETAIN_NEW: with this option set, pre-existing * retained messages for this subscription will be * sent when the subscription is made, but only if the * subscription does not already exist. - * MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set, + * MQTT_SUB_OPT_SEND_RETAIN_NEVER: with this option set, * pre-existing retained messages will never be sent * for this subscription. * properties - a valid mosquitto_property list, or NULL. Only used with MQTT @@ -989,6 +992,10 @@ libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const * * Unsubscribe from a topic, with attached MQTT properties. * + * Use e.g. and similar to create a list of + * properties, then attach them to this publish. Properties need freeing with + * . + * * Parameters: * mosq - a valid mosquitto instance. * mid - a pointer to an int. If not NULL, the function will set this to @@ -1100,52 +1107,16 @@ libmosq_EXPORT void mosquitto_message_free_contents(struct mosquitto_message *me * * Section: Network loop (managed by libmosquitto) * + * The internal network loop must be called at a regular interval. The two + * recommended approaches are to use either or + * . is a blocking call and is + * suitable for the situation where you only want to handle incoming messages + * in callbacks. is a non-blocking call, it creates a + * separate thread to run the loop for you. Use this function when you have + * other tasks you need to run at the same time as the MQTT client, e.g. + * reading data from a sensor. + * * ====================================================================== */ -/* - * Function: mosquitto_loop - * - * The main network loop for the client. You must call this frequently in order - * to keep communications between the client and broker working. If incoming - * data is present it will then be processed. Outgoing commands, from e.g. - * , are normally sent immediately that their function is - * called, but this is not always possible. will also attempt - * to send any remaining outgoing messages, which also includes commands that - * are part of the flow for messages with QoS>0. - * - * An alternative approach is to use to run the client - * loop in its own thread. - * - * This calls select() to monitor the client network socket. If you want to - * integrate mosquitto client operation with your own select() call, use - * , , and - * . - * - * Threads: - * - * Parameters: - * mosq - a valid mosquitto instance. - * timeout - Maximum number of milliseconds to wait for network activity - * in the select() call before timing out. Set to 0 for instant - * return. Set negative to use the default of 1000ms. - * max_packets - this parameter is currently unused and should be set to 1 for - * future compatibility. - * - * Returns: - * MOSQ_ERR_SUCCESS - on success. - * MOSQ_ERR_INVAL - if the input parameters were invalid. - * MOSQ_ERR_NOMEM - if an out of memory condition occurred. - * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. - * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. - * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the - * broker. - * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno - * contains the error code, even on Windows. - * Use strerror_r() where available or FormatMessage() on - * Windows. - * See Also: - * , , - */ -libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets); /* * Function: mosquitto_loop_forever @@ -1227,6 +1198,52 @@ libmosq_EXPORT int mosquitto_loop_start(struct mosquitto *mosq); */ libmosq_EXPORT int mosquitto_loop_stop(struct mosquitto *mosq, bool force); +/* + * Function: mosquitto_loop + * + * The main network loop for the client. This must be called frequently + * to keep communications between the client and broker working. This is + * carried out by and , which + * are the recommended ways of handling the network loop. You may also use this + * function if you wish. It must not be called inside a callback. + * + * If incoming data is present it will then be processed. Outgoing commands, + * from e.g. , are normally sent immediately that their + * function is called, but this is not always possible. will + * also attempt to send any remaining outgoing messages, which also includes + * commands that are part of the flow for messages with QoS>0. + * + * This calls select() to monitor the client network socket. If you want to + * integrate mosquitto client operation with your own select() call, use + * , , and + * . + * + * Threads: + * + * Parameters: + * mosq - a valid mosquitto instance. + * timeout - Maximum number of milliseconds to wait for network activity + * in the select() call before timing out. Set to 0 for instant + * return. Set negative to use the default of 1000ms. + * max_packets - this parameter is currently unused and should be set to 1 for + * future compatibility. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. + * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. + * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the + * broker. + * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno + * contains the error code, even on Windows. + * Use strerror_r() where available or FormatMessage() on + * Windows. + * See Also: + * , , + */ +libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets); /* ====================================================================== * @@ -1301,7 +1318,8 @@ libmosq_EXPORT int mosquitto_loop_write(struct mosquitto *mosq, int max_packets) * monitoring the client network socket for activity yourself. * * This function deals with handling PINGs and checking whether messages need - * to be retried, so should be called fairly frequently. + * to be retried, so should be called fairly frequently, around once per second + * is sufficient. * * Parameters: * mosq - a valid mosquitto instance. @@ -1423,12 +1441,12 @@ libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t op * value - the option specific value. * * Options: - * MOSQ_OPT_PROTOCOL_VERSION + * MOSQ_OPT_PROTOCOL_VERSION - * Value must be set to either MQTT_PROTOCOL_V31, * MQTT_PROTOCOL_V311, or MQTT_PROTOCOL_V5. Must be set before the * client connects. Defaults to MQTT_PROTOCOL_V311. * - * MOSQ_OPT_RECEIVE_MAXIMUM + * MOSQ_OPT_RECEIVE_MAXIMUM - * Value can be set between 1 and 65535 inclusive, and represents * the maximum number of incoming QoS 1 and QoS 2 messages that this * client wants to process at once. Defaults to 20. This option is @@ -1438,7 +1456,7 @@ libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t op * will override this option. Using this option is the recommended * method however. * - * MOSQ_OPT_SEND_MAXIMUM + * MOSQ_OPT_SEND_MAXIMUM - * Value can be set between 1 and 65535 inclusive, and represents * the maximum number of outgoing QoS 1 and QoS 2 messages that this * client will attempt to have "in flight" at once. Defaults to 20. @@ -1447,7 +1465,7 @@ libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t op * MQTT_PROP_RECEIVE_MAXIMUM property that has a lower value than * this option, then the broker provided value will be used. * - * MOSQ_OPT_SSL_CTX_WITH_DEFAULTS + * MOSQ_OPT_SSL_CTX_WITH_DEFAULTS - * If value is set to a non zero value, then the user specified * SSL_CTX passed in using MOSQ_OPT_SSL_CTX will have the default * options applied to it. This means that you only need to change @@ -1456,7 +1474,8 @@ libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t op * use to configure the cafile/capath as a * minimum. * This option is only available for openssl 1.1.0 and higher. - * MOSQ_OPT_TLS_OCSP_REQUIRED + * + * MOSQ_OPT_TLS_OCSP_REQUIRED - * Set whether OCSP checking on TLS connections is required. Set to * 1 to enable checking, or 0 (the default) for no checking. */ @@ -1474,7 +1493,7 @@ libmosq_EXPORT int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t * value - the option specific value. * * Options: - * MOSQ_OPT_SSL_CTX + * MOSQ_OPT_SSL_CTX - * Pass an openssl SSL_CTX to be used when creating TLS connections * rather than libmosquitto creating its own. This must be called * before connecting to have any effect. If you use this option, the @@ -2215,26 +2234,26 @@ libmosq_EXPORT int mosquitto_string_to_command(const char *str, int *cmd); * * For example: * - * subtopic: "a/deep/topic/hierarchy" + * subtopic: "a/deep/topic/hierarchy" * - * Would result in: + * Would result in: * - * topics[0] = "a" - * topics[1] = "deep" - * topics[2] = "topic" - * topics[3] = "hierarchy" + * topics[0] = "a" + * topics[1] = "deep" + * topics[2] = "topic" + * topics[3] = "hierarchy" * - * and: + * and: * - * subtopic: "/a/deep/topic/hierarchy/" + * subtopic: "/a/deep/topic/hierarchy/" * - * Would result in: + * Would result in: * - * topics[0] = NULL - * topics[1] = "a" - * topics[2] = "deep" - * topics[3] = "topic" - * topics[4] = "hierarchy" + * topics[0] = NULL + * topics[1] = "a" + * topics[2] = "deep" + * topics[3] = "topic" + * topics[4] = "hierarchy" * * Parameters: * subtopic - the subscription/topic to tokenise @@ -2283,6 +2302,29 @@ libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count); /* * Function: mosquitto_topic_matches_sub + * + * Check whether a topic matches a subscription. + * + * For example: + * + * foo/bar would match the subscription foo/# or +/bar + * non/matching would not match the subscription non/+/+ + * + * Parameters: + * sub - subscription string to check topic against. + * topic - topic to check. + * result - bool pointer to hold result. Will be set to true if the topic + * matches the subscription. + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + */ +libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result); + + +/* * Function: mosquitto_topic_matches_sub2 * * Check whether a topic matches a subscription. @@ -2302,10 +2344,9 @@ libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count); * * Returns: * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if the input parameters were invalid. - * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. */ -libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result); libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result); /* @@ -2322,6 +2363,31 @@ libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, * * Parameters: * topic - the topic to check + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a #, or if it is too long. + * MOSQ_ERR_MALFORMED_UTF8 - if sub or topic is not valid UTF-8 + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_pub_topic_check(const char *topic); + +/* + * Function: mosquitto_pub_topic_check2 + * + * Check whether a topic to be used for publishing is valid. + * + * This searches for + or # in a topic and checks its length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. It + * may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check * topiclen - length of the topic in bytes * * Returns: @@ -2332,7 +2398,6 @@ libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, * See Also: * */ -libmosq_EXPORT int mosquitto_pub_topic_check(const char *topic); libmosq_EXPORT int mosquitto_pub_topic_check2(const char *topic, size_t topiclen); /* @@ -2351,6 +2416,34 @@ libmosq_EXPORT int mosquitto_pub_topic_check2(const char *topic, size_t topiclen * * Parameters: * topic - the topic to check + * + * Returns: + * MOSQ_ERR_SUCCESS - for a valid topic + * MOSQ_ERR_INVAL - if the topic contains a + or a # that is in an + * invalid position, or if it is too long. + * MOSQ_ERR_MALFORMED_UTF8 - if topic is not valid UTF-8 + * + * See Also: + * + */ +libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic); + +/* + * Function: mosquitto_sub_topic_check2 + * + * Check whether a topic to be used for subscribing is valid. + * + * This searches for + or # in a topic and checks that they aren't in invalid + * positions, such as with foo/#/bar, foo/+bar or foo/bar#, and checks its + * length. + * + * This check is already carried out in and + * , there is no need to call it directly before them. + * It may be useful if you wish to check the validity of a topic in advance of + * making a connection for example. + * + * Parameters: + * topic - the topic to check * topiclen - the length in bytes of the topic * * Returns: @@ -2362,10 +2455,16 @@ libmosq_EXPORT int mosquitto_pub_topic_check2(const char *topic, size_t topiclen * See Also: * */ -libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic); libmosq_EXPORT int mosquitto_sub_topic_check2(const char *topic, size_t topiclen); +/* ============================================================================= + * + * Section: One line client helper functions + * + * ============================================================================= + */ + struct libmosquitto_will { char *topic; void *payload; From e6e7fc961dc81e8112ecee2610519dfa95cfe508 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 31 Oct 2019 12:04:29 +0000 Subject: [PATCH 16/39] Fix function in wrong doc section. --- lib/mosquitto.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 62243f66..089d02b3 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -2458,6 +2458,24 @@ libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic); libmosq_EXPORT int mosquitto_sub_topic_check2(const char *topic, size_t topiclen); +/* + * Function: mosquitto_validate_utf8 + * + * Helper function to validate whether a UTF-8 string is valid, according to + * the UTF-8 spec and the MQTT additions. + * + * Parameters: + * str - a string to check + * len - the length of the string in bytes + * + * Returns: + * MOSQ_ERR_SUCCESS - on success + * MOSQ_ERR_INVAL - if str is NULL or len<0 or len>65536 + * MOSQ_ERR_MALFORMED_UTF8 - if str is not valid UTF-8 + */ +libmosq_EXPORT int mosquitto_validate_utf8(const char *str, int len); + + /* ============================================================================= * * Section: One line client helper functions @@ -2595,24 +2613,6 @@ libmosq_EXPORT int mosquitto_subscribe_callback( const struct libmosquitto_tls *tls); -/* - * Function: mosquitto_validate_utf8 - * - * Helper function to validate whether a UTF-8 string is valid, according to - * the UTF-8 spec and the MQTT additions. - * - * Parameters: - * str - a string to check - * len - the length of the string in bytes - * - * Returns: - * MOSQ_ERR_SUCCESS - on success - * MOSQ_ERR_INVAL - if str is NULL or len<0 or len>65536 - * MOSQ_ERR_MALFORMED_UTF8 - if str is not valid UTF-8 - */ -libmosq_EXPORT int mosquitto_validate_utf8(const char *str, int len); - - /* ============================================================================= * * Section: Properties From 06a27e799f117eac8b4dd7b8deec511719727ede Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 31 Oct 2019 12:54:20 +0000 Subject: [PATCH 17/39] Fix retained messages with an expiry interval not being expired. This happened after being restored from persistence. Closes #1464. Thanks to Dustin Sallings. --- ChangeLog.txt | 2 ++ src/persist_read.c | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 3ed84e05..acdaf0e4 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -9,6 +9,8 @@ Broker: Closes #1442. - Fix problems with reloading config when `per_listener_settings` was true. Closes #1459. +- Fix retained messages with an expiry interval not being expired after being + restored from persistence. Closes #1464. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/persist_read.c b/src/persist_read.c index 48437e46..9613b059 100644 --- a/src/persist_read.c +++ b/src/persist_read.c @@ -114,6 +114,12 @@ static int persist__client_msg_restore(struct mosquitto_db *db, struct P_client_ struct mosquitto *context; struct mosquitto_msg_data *msg_data; + HASH_FIND(hh, db->msg_store_load, &chunk->F.store_id, sizeof(dbid_t), load); + if(!load){ + /* Can't find message - probably expired */ + return MOSQ_ERR_SUCCESS; + } + cmsg = mosquitto__calloc(1, sizeof(struct mosquitto_client_msg)); if(!cmsg){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); @@ -131,12 +137,6 @@ static int persist__client_msg_restore(struct mosquitto_db *db, struct P_client_ cmsg->dup = chunk->F.retain_dup&0x0F; cmsg->properties = chunk->properties; - HASH_FIND(hh, db->msg_store_load, &chunk->F.store_id, sizeof(dbid_t), load); - if(!load){ - mosquitto__free(cmsg); - log__printf(NULL, MOSQ_LOG_ERR, "Error restoring persistent database, message store corrupt."); - return 1; - } cmsg->store = load->store; db__msg_store_ref_inc(cmsg->store); @@ -273,7 +273,13 @@ static int persist__msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fp if(chunk.F.expiry_time > 0){ message_expiry_interval64 = chunk.F.expiry_time - time(NULL); if(message_expiry_interval64 < 0 || message_expiry_interval64 > UINT32_MAX){ - message_expiry_interval = 0; + /* Expired message */ + mosquitto__free(chunk.source.id); + mosquitto__free(chunk.source.username); + mosquitto__free(chunk.topic); + UHPA_FREE(chunk.payload, chunk.F.payloadlen); + mosquitto__free(load); + return MOSQ_ERR_SUCCESS; }else{ message_expiry_interval = (uint32_t)message_expiry_interval64; } @@ -327,8 +333,7 @@ static int persist__retain_chunk_restore(struct mosquitto_db *db, FILE *db_fptr) if(load){ sub__messages_queue(db, NULL, load->store->topic, load->store->qos, load->store->retain, &load->store); }else{ - log__printf(NULL, MOSQ_LOG_ERR, "Error: Corrupt database whilst restoring a retained message."); - return MOSQ_ERR_INVAL; + /* Can't find the message - probably expired */ } return MOSQ_ERR_SUCCESS; } From b622aaeee48fd06e825ad04f35f30ff464586255 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 31 Oct 2019 12:56:13 +0000 Subject: [PATCH 18/39] Fix messages with an expiry interval missing the property. They would be be sent without an expiry interval property just before they were expired. Closes #1464. Thanks to Dustin Sallings. --- ChangeLog.txt | 2 ++ src/subs.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index acdaf0e4..8070f019 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -11,6 +11,8 @@ Broker: Closes #1459. - Fix retained messages with an expiry interval not being expired after being restored from persistence. Closes #1464. +- Fix messages with an expiry interval being sent without an expiry interval + property just before they were expired. Closes #1464. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/subs.c b/src/subs.c index fc62bef8..cf71a1fb 100644 --- a/src/subs.c +++ b/src/subs.c @@ -987,7 +987,7 @@ static int retain__process(struct mosquitto_db *db, struct mosquitto__subhier *b mosquitto_property *properties = NULL; struct mosquitto_msg_store *retained; - if(branch->retained->message_expiry_time > 0 && now > branch->retained->message_expiry_time){ + if(branch->retained->message_expiry_time > 0 && now >= branch->retained->message_expiry_time){ db__msg_store_ref_dec(db, &branch->retained); branch->retained = NULL; #ifdef WITH_SYS_TREE From d76e5fd199b3b3a06e549104efeffde2ceae4aae Mon Sep 17 00:00:00 2001 From: Jerome Malinge Date: Wed, 30 Oct 2019 16:07:20 +0100 Subject: [PATCH 19/39] Fix way of sending packets in compliance tests According to the documentation of python 3 socket::send method (https://docs.python.org/3/library/socket.html#socket.socket.send), the call to send must be retry until all data is sent while sending packet with a "large" amount of data. Signed-off-by: Jerome Malinge --- test/mosq_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/mosq_test.py b/test/mosq_test.py index 1669f566..c4b9808d 100644 --- a/test/mosq_test.py +++ b/test/mosq_test.py @@ -106,7 +106,13 @@ def packet_matches(name, recvd, expected): def do_send_receive(sock, send_packet, receive_packet, error_string="send receive error"): - sock.send(send_packet) + size = len(send_packet) + total_sent = 0 + while total_sent < size: + sent = sock.send(send_packet[total_sent:]) + if sent == 0: + raise RuntimeError("socket connection broken") + total_sent += sent if expect_packet(sock, error_string, receive_packet): return sock From ce0b0d23d6f6b763bb80e69af07ed4db55316274 Mon Sep 17 00:00:00 2001 From: Jerome Malinge Date: Wed, 30 Oct 2019 16:08:52 +0100 Subject: [PATCH 20/39] Add send of pubcomp in 02-subpub-qos2 script To keep the broker session working while launching several tests on the same broker, the last packet of this transaction must be sent. Signed-off-by: Jerome Malinge --- test/broker/02-subpub-qos2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/broker/02-subpub-qos2.py b/test/broker/02-subpub-qos2.py index 260e2eb9..1600a861 100755 --- a/test/broker/02-subpub-qos2.py +++ b/test/broker/02-subpub-qos2.py @@ -38,6 +38,7 @@ try: if mosq_test.expect_packet(sock, "publish2", publish_packet2): mosq_test.do_send_receive(sock, pubrec_packet2, pubrel_packet2, "pubrel2") + sock.send(pubcomp_packet2) # Broker side of flow complete so can quit here. rc = 0 From 11dc077d1534a4e5ab2914af81324bd136f6976b Mon Sep 17 00:00:00 2001 From: Jerome Malinge Date: Wed, 30 Oct 2019 17:30:58 +0100 Subject: [PATCH 21/39] Fix test on invalid reserved bit value in connect packet Signed-off-by: Jerome Malinge --- test/broker/01-connect-invalid-reserved.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/broker/01-connect-invalid-reserved.py b/test/broker/01-connect-invalid-reserved.py index 10f56c61..befbb2d8 100755 --- a/test/broker/01-connect-invalid-reserved.py +++ b/test/broker/01-connect-invalid-reserved.py @@ -3,6 +3,8 @@ # Test whether a CONNECT with reserved set to 1 results in a disconnect. MQTT-3.1.2-3 from mosq_test_helper import * +from socket import error as SocketError +import errno rc = 1 keepalive = 10 @@ -15,7 +17,11 @@ try: sock = mosq_test.do_client_connect(connect_packet, b"", port=port) sock.close() rc = 0 - +except SocketError as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer (very quickly). + # Fine, this is the expected behavior. + rc = 0 finally: broker.terminate() broker.wait() From fba1f6bc0acedfad28b498cf59b8b55cac8b12d2 Mon Sep 17 00:00:00 2001 From: Jerome Malinge Date: Wed, 30 Oct 2019 17:32:03 +0100 Subject: [PATCH 22/39] Fix test on invalid null will topic value in connect packet Signed-off-by: Jerome Malinge --- test/broker/07-will-null-topic.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/broker/07-will-null-topic.py b/test/broker/07-will-null-topic.py index b6007541..0172b48b 100755 --- a/test/broker/07-will-null-topic.py +++ b/test/broker/07-will-null-topic.py @@ -3,6 +3,8 @@ import struct from mosq_test_helper import * +from socket import error as SocketError +import errno rc = 1 keepalive = 60 @@ -16,6 +18,11 @@ try: sock = mosq_test.do_client_connect(connect_packet, b"", timeout=30, port=port) rc = 0 sock.close() +except SocketError as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer (very quickly). + # Fine, this is the expected behavior. + rc = 0 finally: broker.terminate() broker.wait() From 74e1f7731005f608aabea25c88d9d6c9842149af Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 10:50:30 +0000 Subject: [PATCH 23/39] Fix for previous commit Stdin mode wouldn't work with normal compiler optimisation levels. --- client/pub_client.c | 3 ++- client/pub_shared.c | 1 - client/pub_shared.h | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/pub_client.c b/client/pub_client.c index aa435be8..ba5b0eb3 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -45,6 +45,7 @@ static int line_buf_len = 1024; static bool disconnect_sent = false; static int publish_count = 0; static bool ready_for_repeat = false; +static volatile int status = STATUS_CONNECTING; #ifdef WIN32 static uint64_t next_publish_tv; @@ -223,7 +224,7 @@ int pub_shared_loop(struct mosquitto *mosq) { int read_len; int pos; - int rc; + int rc = MOSQ_ERR_SUCCESS; char *buf2; int buf_len_actual; int mode; diff --git a/client/pub_shared.c b/client/pub_shared.c index 008bef4e..65395f94 100644 --- a/client/pub_shared.c +++ b/client/pub_shared.c @@ -37,7 +37,6 @@ Contributors: /* Global variables for use in callbacks. See sub_client.c for an example of * using a struct to hold variables for use in callbacks. */ int mid_sent = -1; -int status = STATUS_CONNECTING; struct mosq_config cfg; void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str) diff --git a/client/pub_shared.h b/client/pub_shared.h index 94d5d11c..13796821 100644 --- a/client/pub_shared.h +++ b/client/pub_shared.h @@ -23,7 +23,6 @@ Contributors: #define STATUS_DISCONNECTED 4 extern int mid_sent; -extern int status; extern struct mosq_config cfg; From aabf850a62dd1dc59d092931ddb1ca1f054c8b00 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 11:26:58 +0000 Subject: [PATCH 24/39] Separate pub client loops for better readability. --- client/pub_client.c | 185 ++++++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 84 deletions(-) diff --git a/client/pub_client.c b/client/pub_client.c index ba5b0eb3..d396f83c 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -220,104 +220,74 @@ int pub_shared_init(void) } -int pub_shared_loop(struct mosquitto *mosq) +int pub_stdin_line_loop(struct mosquitto *mosq) { - int read_len; - int pos; - int rc = MOSQ_ERR_SUCCESS; char *buf2; int buf_len_actual; - int mode; - int loop_delay = 1000; + int pos; + int rc = MOSQ_ERR_SUCCESS; + int read_len; bool stdin_finished = false; - if(cfg.repeat_count > 1 && (cfg.repeat_delay.tv_sec == 0 || cfg.repeat_delay.tv_usec != 0)){ - loop_delay = cfg.repeat_delay.tv_usec / 2000; - } - - mode = cfg.pub_mode; - - if(mode == MSGMODE_STDIN_LINE){ - mosquitto_loop_start(mosq); - stdin_finished = false; - do{ - if(status == STATUS_CONNACK_RECVD){ - pos = 0; - read_len = line_buf_len; - while(status == STATUS_CONNACK_RECVD && fgets(&line_buf[pos], read_len, stdin)){ - buf_len_actual = strlen(line_buf); - if(line_buf[buf_len_actual-1] == '\n'){ - line_buf[buf_len_actual-1] = '\0'; - rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); - if(rc){ - err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc); - mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); - } - break; - }else{ - line_buf_len += 1024; - pos += 1023; - read_len = 1024; - buf2 = realloc(line_buf, line_buf_len); - if(!buf2){ - err_printf(&cfg, "Error: Out of memory.\n"); - return MOSQ_ERR_NOMEM; - } - line_buf = buf2; + mosquitto_loop_start(mosq); + stdin_finished = false; + do{ + if(status == STATUS_CONNACK_RECVD){ + pos = 0; + read_len = line_buf_len; + while(status == STATUS_CONNACK_RECVD && fgets(&line_buf[pos], read_len, stdin)){ + buf_len_actual = strlen(line_buf); + if(line_buf[buf_len_actual-1] == '\n'){ + line_buf[buf_len_actual-1] = '\0'; + rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); + if(rc){ + err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc); + mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); } - } - if(feof(stdin)){ - if(mid_sent == -1){ - /* Empty file */ - mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); - disconnect_sent = true; - status = STATUS_DISCONNECTING; - }else{ - last_mid = mid_sent; - status = STATUS_WAITING; + break; + }else{ + line_buf_len += 1024; + pos += 1023; + read_len = 1024; + buf2 = realloc(line_buf, line_buf_len); + if(!buf2){ + err_printf(&cfg, "Error: Out of memory.\n"); + return MOSQ_ERR_NOMEM; } - stdin_finished = true; - }else if(status == STATUS_DISCONNECTED){ - /* Not end of stdin, so we've lost our connection and must - * reconnect */ + line_buf = buf2; } - }else if(status == STATUS_WAITING){ - if(last_mid_sent == last_mid && disconnect_sent == false){ + } + if(feof(stdin)){ + if(mid_sent == -1){ + /* Empty file */ mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); disconnect_sent = true; + status = STATUS_DISCONNECTING; + }else{ + last_mid = mid_sent; + status = STATUS_WAITING; } + stdin_finished = true; + }else if(status == STATUS_DISCONNECTED){ + /* Not end of stdin, so we've lost our connection and must + * reconnect */ + } + }else if(status == STATUS_WAITING){ + if(last_mid_sent == last_mid && disconnect_sent == false){ + mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); + disconnect_sent = true; + } #ifdef WIN32 - Sleep(100); + Sleep(100); #else - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 100000000; - nanosleep(&ts, NULL); + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 100000000; + nanosleep(&ts, NULL); #endif - } - }while(stdin_finished == false); - mosquitto_loop_stop(mosq, false); - }else{ - do{ - rc = mosquitto_loop(mosq, loop_delay, 1); - if(ready_for_repeat && check_repeat_time()){ - rc = MOSQ_ERR_SUCCESS; - switch(cfg.pub_mode){ - case MSGMODE_CMD: - case MSGMODE_FILE: - case MSGMODE_STDIN_FILE: - rc = my_publish(mosq, &mid_sent, cfg.topic, cfg.msglen, cfg.message, cfg.qos, cfg.retain); - break; - case MSGMODE_NULL: - rc = my_publish(mosq, &mid_sent, cfg.topic, 0, NULL, cfg.qos, cfg.retain); - break; - } - if(rc){ - err_printf(&cfg, "Error sending repeat publish: %s", mosquitto_strerror(rc)); - } - } - }while(rc == MOSQ_ERR_SUCCESS); - } + } + }while(stdin_finished == false); + mosquitto_loop_stop(mosq, false); if(status == STATUS_DISCONNECTED){ return MOSQ_ERR_SUCCESS; @@ -327,6 +297,53 @@ int pub_shared_loop(struct mosquitto *mosq) } +int pub_other_loop(struct mosquitto *mosq) +{ + int rc; + int loop_delay = 1000; + + if(cfg.repeat_count > 1 && (cfg.repeat_delay.tv_sec == 0 || cfg.repeat_delay.tv_usec != 0)){ + loop_delay = cfg.repeat_delay.tv_usec / 2000; + } + + do{ + rc = mosquitto_loop(mosq, loop_delay, 1); + if(ready_for_repeat && check_repeat_time()){ + rc = MOSQ_ERR_SUCCESS; + switch(cfg.pub_mode){ + case MSGMODE_CMD: + case MSGMODE_FILE: + case MSGMODE_STDIN_FILE: + rc = my_publish(mosq, &mid_sent, cfg.topic, cfg.msglen, cfg.message, cfg.qos, cfg.retain); + break; + case MSGMODE_NULL: + rc = my_publish(mosq, &mid_sent, cfg.topic, 0, NULL, cfg.qos, cfg.retain); + break; + } + if(rc){ + err_printf(&cfg, "Error sending repeat publish: %s", mosquitto_strerror(rc)); + } + } + }while(rc == MOSQ_ERR_SUCCESS); + + if(status == STATUS_DISCONNECTED){ + return MOSQ_ERR_SUCCESS; + }else{ + return rc; + } +} + + +int pub_shared_loop(struct mosquitto *mosq) +{ + if(cfg.pub_mode == MSGMODE_STDIN_LINE){ + return pub_stdin_line_loop(mosq); + }else{ + return pub_other_loop(mosq); + } +} + + void pub_shared_cleanup(void) { free(line_buf); From cf1f4228a93dfb87cedd76df6de0f7647ebc7f1b Mon Sep 17 00:00:00 2001 From: Mario Vejlupek Date: Wed, 30 Oct 2019 06:50:28 +0100 Subject: [PATCH 25/39] Add ca-certificates to Docker to support root certificates Signed-off-by: Mario Vejlupek --- docker/1.4.12/Dockerfile | 2 +- docker/1.5/Dockerfile | 3 ++- docker/1.6/Dockerfile | 3 ++- docker/generic/Dockerfile | 3 ++- docker/local/Dockerfile | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docker/1.4.12/Dockerfile b/docker/1.4.12/Dockerfile index a8ab47d0..fb662061 100644 --- a/docker/1.4.12/Dockerfile +++ b/docker/1.4.12/Dockerfile @@ -3,7 +3,7 @@ MAINTAINER David Audet LABEL Description="Eclipse Mosquitto MQTT Broker" -RUN apk --no-cache add mosquitto=1.4.12-r0 && \ +RUN apk --no-cache add mosquitto=1.4.12-r0 ca-certificates && \ mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \ cp /etc/mosquitto/mosquitto.conf /mosquitto/config && \ chown -R mosquitto:mosquitto /mosquitto diff --git a/docker/1.5/Dockerfile b/docker/1.5/Dockerfile index 6e224636..28d4fe41 100644 --- a/docker/1.5/Dockerfile +++ b/docker/1.5/Dockerfile @@ -14,7 +14,8 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev && \ + util-linux-dev \ + ca-certificates && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ diff --git a/docker/1.6/Dockerfile b/docker/1.6/Dockerfile index 72c6b377..b1f63b10 100644 --- a/docker/1.6/Dockerfile +++ b/docker/1.6/Dockerfile @@ -14,7 +14,8 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev && \ + util-linux-dev \ + ca-certificates && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ diff --git a/docker/generic/Dockerfile b/docker/generic/Dockerfile index 01f8d266..6343af49 100644 --- a/docker/generic/Dockerfile +++ b/docker/generic/Dockerfile @@ -12,7 +12,8 @@ RUN apk --no-cache add \ util-linux-dev \ libwebsockets-dev \ libxslt \ - python2 + python2 \ + ca-certificates # This build procedure is based on: # https://github.com/alpinelinux/aports/blob/master/main/mosquitto/APKBUILD diff --git a/docker/local/Dockerfile b/docker/local/Dockerfile index 1d7517ab..5e699ad4 100644 --- a/docker/local/Dockerfile +++ b/docker/local/Dockerfile @@ -13,7 +13,8 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev && \ + util-linux-dev \ + ca-certificates && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ From aceabcdef25625ef089280bc9d351a5d891ab6a0 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 13:37:35 +0000 Subject: [PATCH 26/39] Tidy up async test outputs. --- test/lib/c/02-subscribe-qos1-async1.c | 25 ++++++++----------------- test/lib/c/02-subscribe-qos1-async2.c | 19 ++++++------------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/test/lib/c/02-subscribe-qos1-async1.c b/test/lib/c/02-subscribe-qos1-async1.c index 381dbd12..4b7a500b 100644 --- a/test/lib/c/02-subscribe-qos1-async1.c +++ b/test/lib/c/02-subscribe-qos1-async1.c @@ -42,33 +42,24 @@ int main(int argc, char *argv[]) mosquitto_connect_callback_set(mosq, on_connect); mosquitto_disconnect_callback_set(mosq, on_disconnect); mosquitto_subscribe_callback_set(mosq, on_subscribe); - printf("ok, about to call connect_async\n"); - // this only works if loop_start is first. with loop_start second, - // it fails on both 1.6.4 _and_ 1.6.5 - // in this order, 1.6.4 works and 1.6.5 fails. rc = mosquitto_loop_start(mosq); - printf("loop_start returned rc: %d\n", rc); - if (rc) { - printf("which is: %s\n", mosquitto_strerror(rc)); + if(rc){ + printf("loop_start failed: %s\n", mosquitto_strerror(rc)); + return rc; } - // not sure which rc you want to be returned.... rc = mosquitto_connect_async(mosq, "localhost", port, 60); - printf("connect async returned rc: %d\n", rc); - if (rc) { - printf("which is: %s\n", mosquitto_strerror(rc)); + if(rc){ + printf("connect_async failed: %s\n", mosquitto_strerror(rc)); + return rc; } - printf("ok, so we can start just waiting now, loop_start will run in it's thread\n"); - /* 10 millis to be system polite */ - //struct timespec tv = { 0, 10e6 }; - struct timespec tv = { 1, 0 }; + /* 50 millis to be system polite */ + struct timespec tv = { 0, 50e6 }; while(should_run){ nanosleep(&tv, NULL); - printf("...waiting...\n"); } - printf("Already exited should_run....\n"); mosquitto_disconnect(mosq); mosquitto_loop_stop(mosq, false); diff --git a/test/lib/c/02-subscribe-qos1-async2.c b/test/lib/c/02-subscribe-qos1-async2.c index ffcfaff9..80cf70c6 100644 --- a/test/lib/c/02-subscribe-qos1-async2.c +++ b/test/lib/c/02-subscribe-qos1-async2.c @@ -42,29 +42,22 @@ int main(int argc, char *argv[]) mosquitto_connect_callback_set(mosq, on_connect); mosquitto_disconnect_callback_set(mosq, on_disconnect); mosquitto_subscribe_callback_set(mosq, on_subscribe); - printf("ok, about to call connect_async\n"); rc = mosquitto_connect_async(mosq, "localhost", port, 60); - printf("connect async returned rc: %d\n", rc); - if (rc) { - printf("which is: %s\n", mosquitto_strerror(rc)); + if(rc){ + printf("connect_async failed: %s\n", mosquitto_strerror(rc)); } rc = mosquitto_loop_start(mosq); - printf("loop_start returned rc: %d\n", rc); - if (rc) { - printf("which is: %s\n", mosquitto_strerror(rc)); + if(rc){ + printf("loop_start failed: %s\n", mosquitto_strerror(rc)); } - printf("ok, so we can start just waiting now, loop_start will run in it's thread\n"); - /* 10 millis to be system polite */ - //struct timespec tv = { 0, 10e6 }; - struct timespec tv = { 1, 0 }; + /* 50 millis to be system polite */ + struct timespec tv = { 0, 50e6 }; while(should_run){ nanosleep(&tv, NULL); - printf("...waiting...\n"); } - printf("Already exited should_run....\n"); mosquitto_disconnect(mosq); mosquitto_loop_stop(mosq, false); From 28c11f4ccee25c317972514e64e66cca101ee262 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 14:07:07 +0000 Subject: [PATCH 27/39] Fix tests where broker suddenly disconnects client This seems to be required just on more modern Python versions. --- test/broker/01-connect-bad-packet.py | 6 ++++-- test/broker/01-connect-invalid-reserved.py | 7 ++----- test/broker/02-subpub-qos1-bad-pubcomp.py | 4 ++++ test/broker/02-subpub-qos1-bad-pubrec.py | 4 ++++ test/broker/02-subpub-qos2-bad-puback-1.py | 4 ++++ test/broker/02-subpub-qos2-bad-puback-2.py | 4 ++++ test/broker/02-subpub-qos2-bad-pubcomp.py | 4 ++++ test/broker/07-will-null-topic.py | 7 ++----- test/broker/08-ssl-connect-cert-auth-without.py | 1 - test/broker/mosq_test_helper.py | 1 + 10 files changed, 29 insertions(+), 13 deletions(-) diff --git a/test/broker/01-connect-bad-packet.py b/test/broker/01-connect-bad-packet.py index 87300ad8..50e4ee2f 100755 --- a/test/broker/01-connect-bad-packet.py +++ b/test/broker/01-connect-bad-packet.py @@ -22,8 +22,10 @@ try: sock.close() if len(data) == 0: rc = 0 -except socket.error: - rc = 0 +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/01-connect-invalid-reserved.py b/test/broker/01-connect-invalid-reserved.py index befbb2d8..1aa35131 100755 --- a/test/broker/01-connect-invalid-reserved.py +++ b/test/broker/01-connect-invalid-reserved.py @@ -3,8 +3,6 @@ # Test whether a CONNECT with reserved set to 1 results in a disconnect. MQTT-3.1.2-3 from mosq_test_helper import * -from socket import error as SocketError -import errno rc = 1 keepalive = 10 @@ -17,10 +15,9 @@ try: sock = mosq_test.do_client_connect(connect_packet, b"", port=port) sock.close() rc = 0 -except SocketError as e: +except socket.error as e: if e.errno == errno.ECONNRESET: - # Connection has been closed by peer (very quickly). - # Fine, this is the expected behavior. + # Connection has been closed by peer, this is the expected behaviour rc = 0 finally: broker.terminate() diff --git a/test/broker/02-subpub-qos1-bad-pubcomp.py b/test/broker/02-subpub-qos1-bad-pubcomp.py index 30000da1..93dde6fa 100755 --- a/test/broker/02-subpub-qos1-bad-pubcomp.py +++ b/test/broker/02-subpub-qos1-bad-pubcomp.py @@ -51,6 +51,10 @@ try: rc = 0 sock.close() +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/02-subpub-qos1-bad-pubrec.py b/test/broker/02-subpub-qos1-bad-pubrec.py index f7d416e4..5421beeb 100755 --- a/test/broker/02-subpub-qos1-bad-pubrec.py +++ b/test/broker/02-subpub-qos1-bad-pubrec.py @@ -47,6 +47,10 @@ try: rc = 0 sock.close() +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/02-subpub-qos2-bad-puback-1.py b/test/broker/02-subpub-qos2-bad-puback-1.py index dd4bb7fd..5a983103 100755 --- a/test/broker/02-subpub-qos2-bad-puback-1.py +++ b/test/broker/02-subpub-qos2-bad-puback-1.py @@ -50,6 +50,10 @@ try: rc = 0 sock.close() +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/02-subpub-qos2-bad-puback-2.py b/test/broker/02-subpub-qos2-bad-puback-2.py index 41bcc77b..3813abc9 100755 --- a/test/broker/02-subpub-qos2-bad-puback-2.py +++ b/test/broker/02-subpub-qos2-bad-puback-2.py @@ -53,6 +53,10 @@ try: rc = 0 sock.close() +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/02-subpub-qos2-bad-pubcomp.py b/test/broker/02-subpub-qos2-bad-pubcomp.py index 0b841be8..fa909aa7 100755 --- a/test/broker/02-subpub-qos2-bad-pubcomp.py +++ b/test/broker/02-subpub-qos2-bad-pubcomp.py @@ -50,6 +50,10 @@ try: rc = 0 sock.close() +except socket.error as e: + if e.errno == errno.ECONNRESET: + # Connection has been closed by peer, this is the expected behaviour + rc = 0 finally: broker.terminate() broker.wait() diff --git a/test/broker/07-will-null-topic.py b/test/broker/07-will-null-topic.py index 0172b48b..122a1f5f 100755 --- a/test/broker/07-will-null-topic.py +++ b/test/broker/07-will-null-topic.py @@ -3,8 +3,6 @@ import struct from mosq_test_helper import * -from socket import error as SocketError -import errno rc = 1 keepalive = 60 @@ -18,10 +16,9 @@ try: sock = mosq_test.do_client_connect(connect_packet, b"", timeout=30, port=port) rc = 0 sock.close() -except SocketError as e: +except socket.error as e: if e.errno == errno.ECONNRESET: - # Connection has been closed by peer (very quickly). - # Fine, this is the expected behavior. + # Connection has been closed by peer, this is the expected behaviour rc = 0 finally: broker.terminate() diff --git a/test/broker/08-ssl-connect-cert-auth-without.py b/test/broker/08-ssl-connect-cert-auth-without.py index c28ab5d9..cf8cb692 100755 --- a/test/broker/08-ssl-connect-cert-auth-without.py +++ b/test/broker/08-ssl-connect-cert-auth-without.py @@ -3,7 +3,6 @@ # Test whether a client can connect without an SSL certificate if one is required. from mosq_test_helper import * -import errno if sys.version < '2.7': print("WARNING: SSL not supported on Python 2.6") diff --git a/test/broker/mosq_test_helper.py b/test/broker/mosq_test_helper.py index 73548396..52c0ed51 100644 --- a/test/broker/mosq_test_helper.py +++ b/test/broker/mosq_test_helper.py @@ -15,3 +15,4 @@ import ssl import struct import subprocess import time +import errno From 678131e393936860c087a6a0146df048dea1eb52 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 14:12:36 +0000 Subject: [PATCH 28/39] Docker - ca-certificates must not be installed in build-deps --- docker/1.5/Dockerfile | 5 ++--- docker/1.6/Dockerfile | 5 +++-- docker/local/Dockerfile | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docker/1.5/Dockerfile b/docker/1.5/Dockerfile index 28d4fe41..00fed0b9 100644 --- a/docker/1.5/Dockerfile +++ b/docker/1.5/Dockerfile @@ -14,8 +14,7 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev \ - ca-certificates && \ + util-linux-dev && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ @@ -76,7 +75,7 @@ RUN set -x && \ install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \ chown -R mosquitto:mosquitto /mosquitto && \ apk --no-cache add \ - libuuid && \ + libuuid ca-certificates && \ apk del build-deps && \ rm -rf /build diff --git a/docker/1.6/Dockerfile b/docker/1.6/Dockerfile index b1f63b10..da2da3b8 100644 --- a/docker/1.6/Dockerfile +++ b/docker/1.6/Dockerfile @@ -14,8 +14,7 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev \ - ca-certificates && \ + util-linux-dev && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ @@ -79,6 +78,8 @@ RUN set -x && \ install -s -m755 /build/mosq/src/mosquitto_passwd /usr/bin/mosquitto_passwd && \ install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \ chown -R mosquitto:mosquitto /mosquitto && \ + apk --no-cache add \ + ca-certificates && \ apk del build-deps && \ rm -rf /build diff --git a/docker/local/Dockerfile b/docker/local/Dockerfile index 5e699ad4..ffb17c21 100644 --- a/docker/local/Dockerfile +++ b/docker/local/Dockerfile @@ -13,8 +13,7 @@ RUN set -x && \ cmake \ gnupg \ libressl-dev \ - util-linux-dev \ - ca-certificates && \ + util-linux-dev && \ wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \ mkdir -p /build/lws && \ tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \ @@ -60,6 +59,8 @@ RUN set -x && \ install -s -m755 /build/mosq/src/mosquitto_passwd /usr/bin/mosquitto_passwd && \ install -m644 /build/mosq/mosquitto.conf /mosquitto/config/mosquitto.conf && \ chown -R mosquitto:mosquitto /mosquitto && \ + apk --no-cache add \ + ca-certificates && \ apk del build-deps && \ rm -rf /build From 6bde2097992f7d672e4c2c36168bfb5c73579bc3 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 15:04:54 +0000 Subject: [PATCH 29/39] Added `CLIENT_STATIC_LDADD` to makefile builds This allow more libraries to be linked when compiling the clients with a static libmosquitto, as required for e.g. openssl on some systems. Closes #1371. Thanks to Fabrice Fontaine. --- ChangeLog.txt | 5 +++++ client/Makefile | 6 +++--- config.mk | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 4c5da4a2..ce053895 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -23,6 +23,11 @@ Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. - Fix `mosquitto_pub -l` hang when stdin stream ends. Closes #1448. +Build: +- Added `CLIENT_STATIC_LDADD` to makefile builds to allow more libraries to be + linked when compiling the clients with a static libmosquitto, as required + for e.g. openssl on some systems. + Installer: - Fix mosquitto_rr.exe not being included in Windows installers. Closes #1463. diff --git a/client/Makefile b/client/Makefile index 54bb9edd..034db49b 100644 --- a/client/Makefile +++ b/client/Makefile @@ -21,13 +21,13 @@ static : static_pub static_sub static_rr # libmosquitto only. static_pub : pub_client.o pub_shared.o client_props.o client_shared.o ../lib/libmosquitto.a - ${CROSS_COMPILE}${CC} $^ -o mosquitto_pub ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} + ${CROSS_COMPILE}${CC} $^ -o mosquitto_pub ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} ${CLIENT_STATIC_LDADD} static_sub : sub_client.o sub_client_output.o client_props.o client_shared.o ../lib/libmosquitto.a - ${CROSS_COMPILE}${CC} $^ -o mosquitto_sub ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} + ${CROSS_COMPILE}${CC} $^ -o mosquitto_sub ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} ${CLIENT_STATIC_LDADD} static_rr : rr_client.o client_props.o client_shared.o pub_shared.o sub_client_output.o ../lib/libmosquitto.a - ${CROSS_COMPILE}${CC} $^ -o mosquitto_rr ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} + ${CROSS_COMPILE}${CC} $^ -o mosquitto_rr ${CLIENT_LDFLAGS} ${STATIC_LIB_DEPS} ${CLIENT_STATIC_LDADD} mosquitto_pub : pub_client.o pub_shared.o client_shared.o client_props.o ${CROSS_COMPILE}${CC} $(CLIENT_LDFLAGS) $^ -o $@ $(CLIENT_LDADD) diff --git a/config.mk b/config.mk index b37ff330..18a3dd26 100644 --- a/config.mk +++ b/config.mk @@ -82,6 +82,11 @@ WITH_STRIP:=no # Build static libraries WITH_STATIC_LIBRARIES:=no +# Use this variable to add extra library dependencies when building the clients +# with the static libmosquitto library. This may be required on some systems +# where e.g. -lz or -latomic are needed for openssl. +CLIENT_STATIC_LDADD:= + # Build shared libraries WITH_SHARED_LIBRARIES:=yes From 05171b266d71b791ff592f97dd58682e22e0a45e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 6 Nov 2019 22:25:33 +0000 Subject: [PATCH 30/39] Fix TLS Websockets clients not receiving messages. This can occurs after one client takes over a previous connection. Closes #1489. Thanks to Bas Verhoeven. --- ChangeLog.txt | 2 ++ src/handle_connect.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index ce053895..22edb4c6 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -13,6 +13,8 @@ Broker: restored from persistence. Closes #1464. - Fix messages with an expiry interval being sent without an expiry interval property just before they were expired. Closes #1464. +- Fix TLS Websockets clients not receiving messages after taking over a + previous connection. Closes #1489. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/handle_connect.c b/src/handle_connect.c index 17434b2b..695ce2aa 100644 --- a/src/handle_connect.c +++ b/src/handle_connect.c @@ -160,6 +160,9 @@ int connect__on_authorised(struct mosquitto_db *db, struct mosquitto *context, v } } + if(context->clean_start == true){ + sub__clean_session(db, found_context); + } session_expiry__remove(found_context); will_delay__remove(found_context); will__clear(found_context); From 1e04b22833597acae79dbe479a22c6cc84266e9e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 7 Nov 2019 18:25:56 +0000 Subject: [PATCH 31/39] Fix `mosquitto_pub -l` not sending the final line of stdin This would happen if the final line did not end with a new line. Closes #1473. Thanks to majekw. --- ChangeLog.txt | 2 ++ client/pub_client.c | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 22edb4c6..231458ff 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -24,6 +24,8 @@ Client library: Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. - Fix `mosquitto_pub -l` hang when stdin stream ends. Closes #1448. +- Fix `mosquitto_pub -l` not sending the final line of stdin if it does not + end with a new line. Closes #1473. Build: - Added `CLIENT_STATIC_LDADD` to makefile builds to allow more libraries to be diff --git a/client/pub_client.c b/client/pub_client.c index 217b6ce9..993e8128 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -223,7 +223,7 @@ int pub_shared_init(void) int pub_stdin_line_loop(struct mosquitto *mosq) { char *buf2; - int buf_len_actual; + int buf_len_actual = 0; int pos; int rc = MOSQ_ERR_SUCCESS; int read_len; @@ -240,6 +240,7 @@ int pub_stdin_line_loop(struct mosquitto *mosq) if(line_buf[buf_len_actual-1] == '\n'){ line_buf[buf_len_actual-1] = '\0'; rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); + pos = 0; if(rc){ err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc); mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); @@ -257,6 +258,13 @@ int pub_stdin_line_loop(struct mosquitto *mosq) line_buf = buf2; } } + if(pos != 0){ + rc = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual, line_buf, cfg.qos, cfg.retain); + if(rc){ + err_printf(&cfg, "Error: Publish returned %d, disconnecting.\n", rc); + mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); + } + } if(feof(stdin)){ if(mid_sent == -1){ /* Empty file */ From 3d92dcbbd945760c49c60919e2e2e8c4cbc2e9ea Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 7 Nov 2019 20:49:59 +0000 Subject: [PATCH 32/39] Make documentation for `mosquitto_pub -l` match reality Blank lines are sent as empty messages. Closes #1474. Thanks to majekw. --- ChangeLog.txt | 2 ++ man/mosquitto_pub.1.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 231458ff..f0871c87 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -26,6 +26,8 @@ Clients: - Fix `mosquitto_pub -l` hang when stdin stream ends. Closes #1448. - Fix `mosquitto_pub -l` not sending the final line of stdin if it does not end with a new line. Closes #1473. +- Make documentation for `mosquitto_pub -l` match reality - blank lines are + sent as empty messages. Closes #1474. Build: - Added `CLIENT_STATIC_LDADD` to makefile builds to allow more libraries to be diff --git a/man/mosquitto_pub.1.xml b/man/mosquitto_pub.1.xml index 88cd3041..a05a938f 100644 --- a/man/mosquitto_pub.1.xml +++ b/man/mosquitto_pub.1.xml @@ -338,7 +338,7 @@ - Send messages read from stdin, splitting separate lines into separate messages. Note that blank lines won't be sent. + Send messages read from stdin, splitting separate lines into separate messages. From 7c34ed2eeb66cd44792466090fa9754b82388811 Mon Sep 17 00:00:00 2001 From: Basavesh Shivakumar Date: Sat, 16 Nov 2019 21:39:18 -0500 Subject: [PATCH 33/39] Delete duplicate 'Returns' messages in the comments. Signed-off-by: Basavesh Shivakumar --- lib/mosquitto.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/mosquitto.h b/lib/mosquitto.h index a868f995..7fbb2370 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -630,10 +630,6 @@ libmosq_EXPORT int mosquitto_connect_srv(struct mosquitto *mosq, const char *hos * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. - * - * Returns: - * MOSQ_ERR_SUCCESS - on success. - * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on @@ -661,10 +657,6 @@ libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq); * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. - * - * Returns: - * MOSQ_ERR_SUCCESS - on success. - * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on From c37251c53df560d6016261fe8b0e216fa048a6e2 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 22 Nov 2019 11:16:53 +0000 Subject: [PATCH 34/39] Document `mosquitto_connect_srv()`. Closes #1499. Thanks to Basavesh Shivakumar. --- ChangeLog.txt | 1 + lib/mosquitto.h | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index f0871c87..d150fc12 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -20,6 +20,7 @@ Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 messages. Closes #1432. - Fix documentation issues in mosquitto.h. Closes #1478. +- Document `mosquitto_connect_srv()`. Closes #1499. Clients: - Fix duplicate cfg definition in rr_client. Closes #1453. diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 6f52239a..71357ef8 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -583,20 +583,18 @@ libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const ch /* * Function: mosquitto_connect_srv * - * Connect to an MQTT broker. This is a non-blocking call. If you use - * your client must use the threaded interface - * . If you need to use , you must use - * to connect the client. + * Connect to an MQTT broker. * - * This extends the functionality of by adding the - * bind_address parameter. Use this function if you need to restrict network - * communication over a particular interface. + * If you set `host` to `example.com`, then this call will attempt to retrieve + * the DNS SRV record for `_secure-mqtt._tcp.example.com` or + * `_mqtt._tcp.example.com` to discover which actual host to connect to. * - * May be called before or after . + * DNS SRV support is not usually compiled in to libmosquitto, use of this call + * is not recommended. * * Parameters: * mosq - a valid mosquitto instance. - * host - the hostname or ip address of the broker to connect to. + * host - the hostname to search for an SRV record. * keepalive - the number of seconds after which the broker should send a PING * message to the client if no other messages have been exchanged * in that time. From 9bebab46ca96f309f2148dec90c7ac8a109c60cd Mon Sep 17 00:00:00 2001 From: Basavesh Shivakumar Date: Wed, 27 Nov 2019 16:09:06 -0500 Subject: [PATCH 35/39] In sub_client.c, call mosquitto_destroy() Fixes: #1513 and frees resources when someone terminates via SIGTERM or SIGINT. Signed-off-by: Basavesh Shivakumar --- client/sub_client.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/sub_client.c b/client/sub_client.c index faa68ebd..8894ca05 100644 --- a/client/sub_client.c +++ b/client/sub_client.c @@ -44,7 +44,7 @@ int last_mid = 0; #ifndef WIN32 void my_signal_handler(int signum) { - if(signum == SIGALRM){ + if(signum == SIGALRM || signum == SIGTERM || signum == SIGINT){ process_messages = false; mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); } @@ -344,6 +344,16 @@ int main(int argc, char *argv[]) goto cleanup; } + if(sigaction(SIGTERM, &sigact, NULL) == -1){ + perror("sigaction"); + goto cleanup; + } + + if(sigaction(SIGINT, &sigact, NULL) == -1){ + perror("sigaction"); + goto cleanup; + } + if(cfg.timeout){ alarm(cfg.timeout); } @@ -364,6 +374,7 @@ int main(int argc, char *argv[]) return rc; cleanup: + mosquitto_destroy(mosq); mosquitto_lib_cleanup(); client_config_cleanup(&cfg); return 1; From a46b45b006b83b745775f37b617cce1a6f53dd16 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 28 Nov 2019 16:17:41 +0000 Subject: [PATCH 36/39] Fix persistent_client_expiration not being used Closes #1494. Thanks to Christoph Krey. --- ChangeLog.txt | 3 +++ src/context.c | 2 +- src/session_expiry.c | 24 +++++++++++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index d150fc12..4c1480c8 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -15,6 +15,9 @@ Broker: property just before they were expired. Closes #1464. - Fix TLS Websockets clients not receiving messages after taking over a previous connection. Closes #1489. +- Fix MQTT 3.1.1 clients using clean session false, or MQTT 5.0 clients using + session-expiry-interval set to infinity never expiring, even when the global + `persistent_client_expiration` option was set. Closes #1494. Client library: - Fix publish properties not being passed to on_message_v5 callback for QoS 2 diff --git a/src/context.c b/src/context.c index 35e57310..9483ef0c 100644 --- a/src/context.c +++ b/src/context.c @@ -230,7 +230,7 @@ void context__disconnect(struct mosquitto_db *db, struct mosquitto *context) context__send_will(db, context); if(context->session_expiry_interval == 0){ - + /* Client session is due to be expired now */ #ifdef WITH_BRIDGE if(!context->bridge) #endif diff --git a/src/session_expiry.c b/src/session_expiry.c index e720b703..5732c106 100644 --- a/src/session_expiry.c +++ b/src/session_expiry.c @@ -38,17 +38,32 @@ int session_expiry__add(struct mosquitto_db *db, struct mosquitto *context) { struct session_expiry_list *item; + if(db->config->persistent_client_expiration == 0){ + if(context->session_expiry_interval == UINT32_MAX){ + /* There isn't a global expiry set, and the client has asked to + * never expire, so we don't add it to the list. */ + return MOSQ_ERR_SUCCESS; + } + } + item = mosquitto__calloc(1, sizeof(struct session_expiry_list)); if(!item) return MOSQ_ERR_NOMEM; item->context = context; item->context->session_expiry_time = time(NULL); - if(db->config->persistent_client_expiration == 0 || - db->config->persistent_client_expiration < item->context->session_expiry_interval){ + if(db->config->persistent_client_expiration == 0){ + /* No global expiry, so use the client expiration interval */ item->context->session_expiry_time += item->context->session_expiry_interval; }else{ - item->context->session_expiry_time += db->config->persistent_client_expiration; + /* We have a global expiry interval */ + if(db->config->persistent_client_expiration < item->context->session_expiry_interval){ + /* The client expiry is longer than the global expiry, so use the global */ + item->context->session_expiry_time += db->config->persistent_client_expiration; + }else{ + /* The global expiry is longer than the client expiry, so use the client */ + item->context->session_expiry_time += item->context->session_expiry_interval; + } } context->expiry_list_item = item; @@ -95,8 +110,7 @@ void session_expiry__check(struct mosquitto_db *db, time_t now) last_check = now; DL_FOREACH_SAFE(expiry_list, item, tmp){ - if(item->context->session_expiry_interval != UINT32_MAX - && item->context->session_expiry_time < now){ + if(item->context->session_expiry_time < now){ context = item->context; session_expiry__remove(context); From 6dec2b468bca5f4df3bccf4854811d6dc1146672 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 28 Nov 2019 16:19:57 +0000 Subject: [PATCH 37/39] Remove redundant expiry checks This is all now handled in session_expiry.c, through session expiry interval/time. --- src/loop.c | 31 ------------------------------- src/session_expiry.c | 6 ++++++ 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/loop.c b/src/loop.c index 92673db2..2fee9ac7 100644 --- a/src/loop.c +++ b/src/loop.c @@ -138,8 +138,6 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li int err; socklen_t len; #endif - time_t expiration_check_time = 0; - char *id; #if defined(WITH_WEBSOCKETS) && LWS_LIBRARY_VERSION_NUMBER == 3002000 @@ -169,10 +167,6 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li } #endif - if(db->config->persistent_client_expiration > 0){ - expiration_check_time = time(NULL) + 3600; - } - #ifdef WITH_EPOLL db->epollfd = 0; if ((db->epollfd = epoll_create(MAX_EVENTS)) == -1) { @@ -471,31 +465,6 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li } } #endif - now = time(NULL); - if(db->config->persistent_client_expiration > 0 && now > expiration_check_time){ - HASH_ITER(hh_id, db->contexts_by_id, context, ctxt_tmp){ - if(context->sock == INVALID_SOCKET && context->session_expiry_interval > 0 && context->session_expiry_interval != UINT32_MAX){ - /* This is a persistent client, check to see if the - * last time it connected was longer than - * persistent_client_expiration seconds ago. If so, - * expire it and clean up. - */ - if(now > context->session_expiry_time){ - if(context->id){ - id = context->id; - }else{ - id = ""; - } - log__printf(NULL, MOSQ_LOG_NOTICE, "Expiring persistent client %s due to timeout.", id); - G_CLIENTS_EXPIRED_INC(); - context->session_expiry_interval = 0; - mosquitto__set_state(context, mosq_cs_expiring); - do_disconnect(db, context, MOSQ_ERR_SUCCESS); - } - } - } - expiration_check_time = time(NULL) + 3600; - } #ifndef WIN32 sigprocmask(SIG_SETMASK, &sigblock, &origsig); diff --git a/src/session_expiry.c b/src/session_expiry.c index 5732c106..59e4c2f6 100644 --- a/src/session_expiry.c +++ b/src/session_expiry.c @@ -22,6 +22,7 @@ Contributors: #include "mosquitto_broker_internal.h" #include "memory_mosq.h" +#include "sys_tree.h" #include "time_mosq.h" static struct session_expiry_list *expiry_list = NULL; @@ -115,6 +116,11 @@ void session_expiry__check(struct mosquitto_db *db, time_t now) context = item->context; session_expiry__remove(context); + if(context->id){ + log__printf(NULL, MOSQ_LOG_NOTICE, "Expiring client %s due to timeout.", context->id); + } + G_CLIENTS_EXPIRED_INC(); + /* Session has now expired, so clear interval */ context->session_expiry_interval = 0; /* Session has expired, so will delay should be cleared. */ From b96739341d22f8e524dfbd6fec14e9c7f10995f8 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 28 Nov 2019 16:41:16 +0000 Subject: [PATCH 38/39] Update changelog for last pull request. Closes #1513. --- ChangeLog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 4c1480c8..d4bb6dc4 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -32,6 +32,8 @@ Clients: end with a new line. Closes #1473. - Make documentation for `mosquitto_pub -l` match reality - blank lines are sent as empty messages. Closes #1474. +- Free memory in `mosquitto_sub` when quiting without having made a successful + connection. Closes #1513. Build: - Added `CLIENT_STATIC_LDADD` to makefile builds to allow more libraries to be From b41056829932bc55c53e97f65fccefb3c1db44a6 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 28 Nov 2019 17:08:11 +0000 Subject: [PATCH 39/39] Bump version, add release post. --- CMakeLists.txt | 2 +- ChangeLog.txt | 3 + config.mk | 2 +- installer/mosquitto.nsi | 2 +- installer/mosquitto64.nsi | 2 +- lib/mosquitto.h | 2 +- set-version.sh | 2 +- snap/snapcraft.yaml | 2 +- www/posts/2019/11/version-1-6-8-released.md | 75 +++++++++++++++++++++ 9 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 www/posts/2019/11/version-1-6-8-released.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 19d4814a..e11959c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ project(mosquitto) cmake_minimum_required(VERSION 2.8) # Only for version 3 and up. cmake_policy(SET CMP0042 NEW) -set (VERSION 1.6.7) +set (VERSION 1.6.8) add_definitions (-DCMAKE -DVERSION=\"${VERSION}\") diff --git a/ChangeLog.txt b/ChangeLog.txt index d4bb6dc4..1f01ebe8 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,6 @@ +1.6.8 - 20191128 +================ + Broker: - Various fixes for `allow_zero_length_clientid` config, where this option was not being set correctly. Closes #1429. diff --git a/config.mk b/config.mk index 18a3dd26..51e36e0d 100644 --- a/config.mk +++ b/config.mk @@ -109,7 +109,7 @@ WITH_COVERAGE:=no # Also bump lib/mosquitto.h, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto64.nsi -VERSION=1.6.7 +VERSION=1.6.8 # Client library SO version. Bump if incompatible API/ABI changes are made. SOVERSION=1 diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index 73a165f8..95c6d447 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "Eclipse Mosquitto" -!define VERSION 1.6.7 +!define VERSION 1.6.8 OutFile "mosquitto-${VERSION}-install-windows-x86.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/installer/mosquitto64.nsi b/installer/mosquitto64.nsi index f797a387..22a67abe 100644 --- a/installer/mosquitto64.nsi +++ b/installer/mosquitto64.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "Eclipse Mosquitto" -!define VERSION 1.6.7 +!define VERSION 1.6.8 OutFile "mosquitto-${VERSION}-install-windows-x64.exe" !include "x64.nsh" diff --git a/lib/mosquitto.h b/lib/mosquitto.h index 71357ef8..97e34809 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -48,7 +48,7 @@ extern "C" { #define LIBMOSQUITTO_MAJOR 1 #define LIBMOSQUITTO_MINOR 6 -#define LIBMOSQUITTO_REVISION 7 +#define LIBMOSQUITTO_REVISION 8 /* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */ #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) diff --git a/set-version.sh b/set-version.sh index 45db2b74..073fe262 100755 --- a/set-version.sh +++ b/set-version.sh @@ -2,7 +2,7 @@ MAJOR=1 MINOR=6 -REVISION=7 +REVISION=8 sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f662f04f..d5ce592b 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: mosquitto -version: 1.6.7 +version: 1.6.8 summary: Eclipse Mosquitto MQTT broker description: This is a message broker that supports version 3.1 and 3.1.1 of the MQTT protocol. diff --git a/www/posts/2019/11/version-1-6-8-released.md b/www/posts/2019/11/version-1-6-8-released.md new file mode 100644 index 00000000..585490f8 --- /dev/null +++ b/www/posts/2019/11/version-1-6-8-released.md @@ -0,0 +1,75 @@ + + +Mosquitto 1.6.8 has been released, this is a bugfix release. + +# Broker +- Various fixes for `allow_zero_length_clientid` config, where this option was + not being set correctly. Closes [#1429]. +- Fix incorrect memory tracking causing problems with `memory_limit` option. + Closes [#1437]. +- Fix subscription topics being limited to 200 characters instead of 200 + hierarchy levels. Closes [#1441]. +- Only a single CRL could be loaded at once. This has been fixed. + Closes [#1442]. +- Fix problems with reloading config when `per_listener_settings` was true. + Closes [#1459]. +- Fix retained messages with an expiry interval not being expired after being + restored from persistence. Closes [#1464]. +- Fix messages with an expiry interval being sent without an expiry interval + property just before they were expired. Closes [#1464]. +- Fix TLS Websockets clients not receiving messages after taking over a + previous connection. Closes [#1489]. +- Fix MQTT 3.1.1 clients using clean session false, or MQTT 5.0 clients using + session-expiry-interval set to infinity never expiring, even when the global + `persistent_client_expiration` option was set. Closes [#1494]. + +# Client library +- Fix publish properties not being passed to `on_message_v5()` callback for QoS 2 + messages. Closes [#1432]. +- Fix documentation issues in mosquitto.h. Closes [#1478]. +- Document `mosquitto_connect_srv()`. Closes [#1499]. + +# Clients +- Fix duplicate cfg definition in rr_client. Closes [#1453]. +- Fix `mosquitto_pub -l` hang when stdin stream ends. Closes [#1448]. +- Fix `mosquitto_pub -l` not sending the final line of stdin if it does not + end with a new line. Closes [#1473]. +- Make documentation for `mosquitto_pub -l` match reality - blank lines are + sent as empty messages. Closes [#1474]. +- Free memory in `mosquitto_sub` when quiting without having made a successful + connection. Closes [#1513]. + +# Build +- Added `CLIENT_STATIC_LDADD` to makefile builds to allow more libraries to be + linked when compiling the clients with a static libmosquitto, as required + for e.g. openssl on some systems. + +# Installer +- Fix `mosquitto_rr.exe` not being included in Windows installers. Closes [#1463]. + +[#1429]: https://github.com/eclipse/mosquitto/issues/1429 +[#1432]: https://github.com/eclipse/mosquitto/issues/1432 +[#1437]: https://github.com/eclipse/mosquitto/issues/1437 +[#1441]: https://github.com/eclipse/mosquitto/issues/1441 +[#1442]: https://github.com/eclipse/mosquitto/issues/1442 +[#1448]: https://github.com/eclipse/mosquitto/issues/1448 +[#1453]: https://github.com/eclipse/mosquitto/issues/1453 +[#1459]: https://github.com/eclipse/mosquitto/issues/1459 +[#1463]: https://github.com/eclipse/mosquitto/issues/1463 +[#1464]: https://github.com/eclipse/mosquitto/issues/1464 +[#1473]: https://github.com/eclipse/mosquitto/issues/1473 +[#1474]: https://github.com/eclipse/mosquitto/issues/1474 +[#1478]: https://github.com/eclipse/mosquitto/issues/1478 +[#1489]: https://github.com/eclipse/mosquitto/issues/1489 +[#1494]: https://github.com/eclipse/mosquitto/issues/1494 +[#1499]: https://github.com/eclipse/mosquitto/issues/1499 +[#1513]: https://github.com/eclipse/mosquitto/issues/1513