diff --git a/CMakeLists.txt b/CMakeLists.txt
index e707229b..c670628d 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.3)
+set (VERSION 1.6.4)
add_definitions (-DCMAKE -DVERSION=\"${VERSION}\")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3707fd56..df7e1f4d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,7 +11,7 @@ implementation, of an MQTT broker to allow new, existing, and emerging
applications for Machine-to-Machine (M2M) and Internet of Things (IoT).
-
--
+-
Source
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 6b3f8716..ba660d80 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,41 @@
+1.6.4 - 20190801
+================
+
+Broker:
+- Fix persistent clients being incorrectly expired on Raspberry Pis.
+ Closes #1272.
+- Windows: Allow other applications access to the log file when running.
+ Closes #515.
+- Fix incoming QoS 2 messages being blocked when `max_inflight_messages` was
+ set to 1. Closes #1332.
+- Fix incoming messages not being removed for a client if the topic being
+ published to does not have any subscribers. Closes #1322.
+
+Client library:
+- Fix MQTT v5 subscription options being incorrectly set for MQTT v3
+ subscriptions. Closes #1353.
+- Make behaviour of `mosquitto_connect_async()` consistent with
+ `mosquitto_connect()` when connecting to a non-existent server.
+ Closes #1345.
+- `mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, ...)` was incorrectly
+ returning `MOSQ_ERR_INVAL` with valid input. This has been fixed.
+ Closes #1360.
+- on_connect callback is now called with the correct v5 reason code if a v5
+ client connects to a v3.x broker and is sent a CONNACK with the
+ "unacceptable protocol version" connack reason code.
+- Fix memory leak when setting v5 properties in mosquitto_connect_v5().
+- Fix properties not being sent on QoS>0 PUBLISH messages.
+
+Clients:
+- mosquitto_pub: fix error codes not being returned when mosquitto_pub exits.
+ Closes #1354.
+- All clients: improve error messages when connecting to a v3.x broker when in
+ v5 mode. Closes #1344.
+
+Other:
+- Various documentation fixes.
+
+
1.6.3 - 20190618
================
diff --git a/client/client_shared.c b/client/client_shared.c
index 7d3ba773..205245a2 100644
--- a/client/client_shared.c
+++ b/client/client_shared.c
@@ -1427,11 +1427,11 @@ static int mosquitto__parse_socks_url(struct mosq_config *cfg, char *url)
return 0;
cleanup:
- if(username_or_host) free(username_or_host);
- if(username) free(username);
- if(password) free(password);
- if(host) free(host);
- if(port) free(port);
+ free(username_or_host);
+ free(username);
+ free(password);
+ free(host);
+ free(port);
return 1;
}
#endif
diff --git a/client/pub_client.c b/client/pub_client.c
index 31740391..0debcaee 100644
--- a/client/pub_client.c
+++ b/client/pub_client.c
@@ -103,7 +103,9 @@ void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc, const mos
UNUSED(rc);
UNUSED(properties);
- status = STATUS_DISCONNECTED;
+ if(rc == 0){
+ status = STATUS_DISCONNECTED;
+ }
}
int my_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, void *payload, int qos, bool retain)
@@ -166,10 +168,15 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
}else{
if(result){
if(cfg.protocol_version == MQTT_PROTOCOL_V5){
- err_printf(&cfg, "%s\n", mosquitto_reason_string(result));
+ if(result == MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION){
+ err_printf(&cfg, "Connection error: %s. Try connecting to an MQTT v5 broker, or use MQTT v3.x mode.\n", mosquitto_reason_string(result));
+ }else{
+ err_printf(&cfg, "Connection error: %s\n", mosquitto_reason_string(result));
+ }
}else{
- err_printf(&cfg, "%s\n", mosquitto_connack_string(result));
+ err_printf(&cfg, "Connection error: %s\n", mosquitto_connack_string(result));
}
+ mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props);
}
}
}
@@ -443,7 +450,6 @@ int main(int argc, char *argv[])
if(pub_shared_init()) return 1;
- memset(&cfg, 0, sizeof(struct mosq_config));
rc = client_config_load(&cfg, CLIENT_PUB, argc, argv);
if(rc){
if(rc == 2){
diff --git a/client/rr_client.c b/client/rr_client.c
index 6444c28e..44f105b0 100644
--- a/client/rr_client.c
+++ b/client/rr_client.c
@@ -122,7 +122,11 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
}else{
client_state = rr_s_disconnect;
if(result){
- err_printf(&cfg, "%s\n", mosquitto_connack_string(result));
+ if(result == MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION){
+ err_printf(&cfg, "Connection error: %s. mosquitto_rr only supports connecting to an MQTT v5 broker\n", mosquitto_reason_string(result));
+ }else{
+ err_printf(&cfg, "Connection error: %s\n", mosquitto_reason_string(result));
+ }
}
mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props);
}
@@ -252,8 +256,6 @@ int main(int argc, char *argv[])
#ifndef WIN32
struct sigaction sigact;
#endif
-
- memset(&cfg, 0, sizeof(struct mosq_config));
mosquitto_lib_init();
@@ -358,7 +360,7 @@ int main(int argc, char *argv[])
}
client_config_cleanup(&cfg);
if(rc){
- fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
+ err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));
}
return rc;
diff --git a/client/sub_client.c b/client/sub_client.c
index f57a48cc..68b0e790 100644
--- a/client/sub_client.c
+++ b/client/sub_client.c
@@ -126,9 +126,13 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
}else{
if(result){
if(cfg.protocol_version == MQTT_PROTOCOL_V5){
- err_printf(&cfg, "%s\n", mosquitto_reason_string(result));
+ if(result == MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION){
+ err_printf(&cfg, "Connection error: %s. Try connecting to an MQTT v5 broker, or use MQTT v3.x mode.\n", mosquitto_reason_string(result));
+ }else{
+ err_printf(&cfg, "Connection error: %s\n", mosquitto_reason_string(result));
+ }
}else{
- err_printf(&cfg, "%s\n", mosquitto_connack_string(result));
+ err_printf(&cfg, "Connection error: %s\n", mosquitto_connack_string(result));
}
}
mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props);
@@ -278,8 +282,6 @@ int main(int argc, char *argv[])
#ifndef WIN32
struct sigaction sigact;
#endif
-
- memset(&cfg, 0, sizeof(struct mosq_config));
mosquitto_lib_init();
@@ -355,7 +357,7 @@ int main(int argc, char *argv[])
}
client_config_cleanup(&cfg);
if(rc){
- fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
+ err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));
}
return rc;
diff --git a/config.h b/config.h
index f717d00c..5cce39ee 100644
--- a/config.h
+++ b/config.h
@@ -16,7 +16,10 @@
# define _POSIX_C_SOURCE 200809L
#endif
-#define _GNU_SOURCE
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
#define OPENSSL_LOAD_CONF
diff --git a/config.mk b/config.mk
index e305d0cd..6c23bef9 100644
--- a/config.mk
+++ b/config.mk
@@ -104,7 +104,7 @@ WITH_COVERAGE:=no
# Also bump lib/mosquitto.h, CMakeLists.txt,
# installer/mosquitto.nsi, installer/mosquitto64.nsi
-VERSION=1.6.3
+VERSION=1.6.4
# Client library SO version. Bump if incompatible API/ABI changes are made.
SOVERSION=1
diff --git a/docker/1.5/README.md b/docker/1.5/README.md
index 27b05904..ce91cd03 100644
--- a/docker/1.5/README.md
+++ b/docker/1.5/README.md
@@ -15,7 +15,7 @@ Two docker volumes have been created in the image to be used for persistent stor
## User/Group
-The image runs mosqutto under the mosquitto user and group, which are created
+The image runs mosquitto under the mosquitto user and group, which are created
with a uid and gid of 1883.
## Configuration
diff --git a/docker/1.6/README.md b/docker/1.6/README.md
index 27b05904..ce91cd03 100644
--- a/docker/1.6/README.md
+++ b/docker/1.6/README.md
@@ -15,7 +15,7 @@ Two docker volumes have been created in the image to be used for persistent stor
## User/Group
-The image runs mosqutto under the mosquitto user and group, which are created
+The image runs mosquitto under the mosquitto user and group, which are created
with a uid and gid of 1883.
## Configuration
diff --git a/docker/local/README.md b/docker/local/README.md
index eb830604..f11086aa 100644
--- a/docker/local/README.md
+++ b/docker/local/README.md
@@ -17,7 +17,7 @@ Two docker volumes have been created in the image to be used for persistent stor
## User/Group
-The image runs mosqutto under the mosquitto user and group, which are created
+The image runs mosquitto under the mosquitto user and group, which are created
with a uid and gid of 1883.
## Configuration
diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi
index 15cd507d..2190683d 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.3
+!define VERSION 1.6.4
OutFile "mosquitto-${VERSION}-install-windows-x86.exe"
InstallDir "$PROGRAMFILES\mosquitto"
diff --git a/installer/mosquitto64.nsi b/installer/mosquitto64.nsi
index 6027fc89..12a98b84 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.3
+!define VERSION 1.6.4
OutFile "mosquitto-${VERSION}-install-windows-x64.exe"
!include "x64.nsh"
diff --git a/lib/actions.c b/lib/actions.c
index a5bf673f..99d03f29 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -40,6 +40,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
uint16_t local_mid;
const mosquitto_property *p;
const mosquitto_property *outgoing_properties = NULL;
+ mosquitto_property *properties_copy = NULL;
mosquitto_property local_property;
bool have_topic_alias;
int rc;
@@ -109,8 +110,15 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
if(qos == 0){
return send__publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false, outgoing_properties, NULL, 0);
}else{
+ if(outgoing_properties){
+ rc = mosquitto_property_copy_all(&properties_copy, outgoing_properties);
+ if(rc) return rc;
+ }
message = mosquitto__calloc(1, sizeof(struct mosquitto_message_all));
- if(!message) return MOSQ_ERR_NOMEM;
+ if(!message){
+ mosquitto_property_free_all(&properties_copy);
+ return MOSQ_ERR_NOMEM;
+ }
message->next = NULL;
message->timestamp = mosquitto_time();
@@ -119,6 +127,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
message->msg.topic = mosquitto__strdup(topic);
if(!message->msg.topic){
message__cleanup(&message);
+ mosquitto_property_free_all(&properties_copy);
return MOSQ_ERR_NOMEM;
}
}
@@ -127,6 +136,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
message->msg.payload = mosquitto__malloc(payloadlen*sizeof(uint8_t));
if(!message->msg.payload){
message__cleanup(&message);
+ mosquitto_property_free_all(&properties_copy);
return MOSQ_ERR_NOMEM;
}
memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t));
@@ -137,6 +147,7 @@ int mosquitto_publish_v5(struct mosquitto *mosq, int *mid, const char *topic, in
message->msg.qos = qos;
message->msg.retain = retain;
message->dup = false;
+ message->properties = properties_copy;
pthread_mutex_lock(&mosq->msgs_out.mutex);
message->state = mosq_ms_invalid;
@@ -200,6 +211,9 @@ int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count
return MOSQ_ERR_OVERSIZE_PACKET;
}
}
+ if(mosq->protocol == mosq_p_mqtt311 || mosq->protocol == mosq_p_mqtt31){
+ options = 0;
+ }
return send__subscribe(mosq, mid, sub_count, sub, qos|options, outgoing_properties);
}
diff --git a/lib/connect.c b/lib/connect.c
index 7543d4af..8559cd72 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -163,7 +163,6 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos
const mosquitto_property *outgoing_properties = NULL;
mosquitto_property local_property;
int rc;
- struct mosquitto__packet *packet;
if(!mosq) return MOSQ_ERR_INVAL;
if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL;
if(mosq->protocol != mosq_p_mqtt5 && properties) return MOSQ_ERR_NOT_SUPPORTED;
@@ -201,27 +200,7 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos
packet__cleanup(&mosq->in_packet);
- pthread_mutex_lock(&mosq->current_out_packet_mutex);
- pthread_mutex_lock(&mosq->out_packet_mutex);
-
- if(mosq->out_packet && !mosq->current_out_packet){
- mosq->current_out_packet = mosq->out_packet;
- mosq->out_packet = mosq->out_packet->next;
- }
-
- while(mosq->current_out_packet){
- packet = mosq->current_out_packet;
- /* Free data and reset values */
- mosq->current_out_packet = mosq->out_packet;
- if(mosq->out_packet){
- mosq->out_packet = mosq->out_packet->next;
- }
-
- packet__cleanup(packet);
- mosquitto__free(packet);
- }
- pthread_mutex_unlock(&mosq->out_packet_mutex);
- pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ packet__cleanup_all(mosq);
message__reconnect_reset(mosq);
@@ -250,7 +229,15 @@ static int mosquitto__reconnect(struct mosquitto *mosq, bool blocking, const mos
}else
#endif
{
- return send__connect(mosq, mosq->keepalive, mosq->clean_start, outgoing_properties);
+ rc = send__connect(mosq, mosq->keepalive, mosq->clean_start, outgoing_properties);
+ if(rc){
+ packet__cleanup_all(mosq);
+ net__socket_close(mosq);
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_new;
+ pthread_mutex_unlock(&mosq->state_mutex);
+ }
+ return rc;
}
}
diff --git a/lib/handle_connack.c b/lib/handle_connack.c
index 19b6a661..60780f6c 100644
--- a/lib/handle_connack.c
+++ b/lib/handle_connack.c
@@ -28,6 +28,29 @@ Contributors:
#include "property_mosq.h"
#include "read_handle.h"
+static void connack_callback(struct mosquitto *mosq, uint8_t reason_code, uint8_t connect_flags, const mosquitto_property *properties)
+{
+ log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code);
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_connect){
+ mosq->in_callback = true;
+ mosq->on_connect(mosq, mosq->userdata, reason_code);
+ mosq->in_callback = false;
+ }
+ if(mosq->on_connect_with_flags){
+ mosq->in_callback = true;
+ mosq->on_connect_with_flags(mosq, mosq->userdata, reason_code, connect_flags);
+ mosq->in_callback = false;
+ }
+ if(mosq->on_connect_v5){
+ mosq->in_callback = true;
+ mosq->on_connect_v5(mosq, mosq->userdata, reason_code, connect_flags, properties);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+
int handle__connack(struct mosquitto *mosq)
{
uint8_t connect_flags;
@@ -44,7 +67,17 @@ int handle__connack(struct mosquitto *mosq)
if(mosq->protocol == mosq_p_mqtt5){
rc = property__read_all(CMD_CONNACK, &mosq->in_packet, &properties);
- if(rc) return rc;
+
+ if(rc == MOSQ_ERR_PROTOCOL && reason_code == CONNACK_REFUSED_PROTOCOL_VERSION){
+ /* This could occur because we are connecting to a v3.x broker and
+ * it has replied with "unacceptable protocol version", but with a
+ * v3 CONNACK. */
+
+ connack_callback(mosq, MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION, connect_flags, NULL);
+ return rc;
+ }else if(rc){
+ return rc;
+ }
}
mosquitto_property_read_string(properties, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, &clientid, false);
@@ -68,24 +101,7 @@ int handle__connack(struct mosquitto *mosq)
mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum;
- log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code);
- pthread_mutex_lock(&mosq->callback_mutex);
- if(mosq->on_connect){
- mosq->in_callback = true;
- mosq->on_connect(mosq, mosq->userdata, reason_code);
- mosq->in_callback = false;
- }
- if(mosq->on_connect_with_flags){
- mosq->in_callback = true;
- mosq->on_connect_with_flags(mosq, mosq->userdata, reason_code, connect_flags);
- mosq->in_callback = false;
- }
- if(mosq->on_connect_v5){
- mosq->in_callback = true;
- mosq->on_connect_v5(mosq, mosq->userdata, reason_code, connect_flags, properties);
- mosq->in_callback = false;
- }
- pthread_mutex_unlock(&mosq->callback_mutex);
+ connack_callback(mosq, reason_code, connect_flags, properties);
mosquitto_property_free_all(&properties);
switch(reason_code){
diff --git a/lib/handle_pubrel.c b/lib/handle_pubrel.c
index d4a90652..209a3e0d 100644
--- a/lib/handle_pubrel.c
+++ b/lib/handle_pubrel.c
@@ -78,11 +78,11 @@ int handle__pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
mosquitto_property_free_all(&properties);
rc = db__message_release_incoming(db, mosq, mid);
- if(rc == MOSQ_ERR_PROTOCOL){
- return rc;
- }else if(rc != MOSQ_ERR_SUCCESS){
+ if(rc == MOSQ_ERR_NOT_FOUND){
/* Message not found. Still send a PUBCOMP anyway because this could be
* due to a repeated PUBREL after a client has reconnected. */
+ }else if(rc != MOSQ_ERR_SUCCESS){
+ return rc;
}
rc = send__pubcomp(mosq, mid);
diff --git a/lib/loop.c b/lib/loop.c
index 2342c945..36763e06 100644
--- a/lib/loop.c
+++ b/lib/loop.c
@@ -314,7 +314,6 @@ static int mosquitto__loop_rc_handle(struct mosquitto *mosq, int rc)
mosq->in_callback = false;
}
pthread_mutex_unlock(&mosq->callback_mutex);
- return rc;
}
return rc;
}
diff --git a/lib/messages_mosq.c b/lib/messages_mosq.c
index bf77f5e6..75e4f860 100644
--- a/lib/messages_mosq.c
+++ b/lib/messages_mosq.c
@@ -39,6 +39,7 @@ void message__cleanup(struct mosquitto_message_all **message)
mosquitto__free(msg->msg.topic);
mosquitto__free(msg->msg.payload);
+ mosquitto_property_free_all(&msg->properties);
mosquitto__free(msg);
}
@@ -199,7 +200,7 @@ int message__release_to_inflight(struct mosquitto *mosq, enum mosquitto_msg_dire
}else if(cur->msg.qos == 2){
cur->state = mosq_ms_wait_for_pubrec;
}
- rc = send__publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup, NULL, NULL, 0);
+ rc = send__publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup, cur->properties, NULL, 0);
if(rc){
return rc;
}
@@ -286,7 +287,7 @@ void message__retry_check(struct mosquitto *mosq)
case mosq_ms_publish_qos2:
msg->timestamp = now;
msg->dup = true;
- send__publish(mosq, msg->msg.mid, msg->msg.topic, msg->msg.payloadlen, msg->msg.payload, msg->msg.qos, msg->msg.retain, msg->dup, NULL, NULL, 0);
+ send__publish(mosq, msg->msg.mid, msg->msg.topic, msg->msg.payloadlen, msg->msg.payload, msg->msg.qos, msg->msg.retain, msg->dup, msg->properties, NULL, 0);
break;
case mosq_ms_wait_for_pubrel:
msg->timestamp = now;
diff --git a/lib/mosquitto.h b/lib/mosquitto.h
index 09bba66e..6957b619 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 3
+#define LIBMOSQUITTO_REVISION 4
/* 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)
@@ -921,8 +921,9 @@ libmosq_EXPORT int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, cons
* familiar with this, just think of it as a safer "char **",
* equivalent to "const char *" for a simple string pointer.
* qos - the requested Quality of Service for each subscription.
- * options - options to apply to this subscription, OR'd together. Set to 0 to
- * use the default options, otherwise choose from the list:
+ * 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
* publishes to a topic to which it is subscribed, the
* broker will not publish the message back to the
diff --git a/lib/net_mosq.c b/lib/net_mosq.c
index f207e32a..9fd75856 100644
--- a/lib/net_mosq.c
+++ b/lib/net_mosq.c
@@ -607,12 +607,14 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
if(!engine){
log__printf(mosq, MOSQ_LOG_ERR, "Error loading %s engine\n", mosq->tls_engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
return MOSQ_ERR_TLS;
}
if(!ENGINE_init(engine)){
log__printf(mosq, MOSQ_LOG_ERR, "Failed engine initialisation\n");
ENGINE_free(engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
return MOSQ_ERR_TLS;
}
ENGINE_set_default(engine, ENGINE_METHOD_ALL);
@@ -698,6 +700,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha1");
ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
net__print_ssl_error(mosq);
return MOSQ_ERR_TLS;
}
@@ -705,6 +708,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine pin");
ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
net__print_ssl_error(mosq);
return MOSQ_ERR_TLS;
}
@@ -715,6 +719,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", mosq->tls_keyfile);
ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
net__print_ssl_error(mosq);
return MOSQ_ERR_TLS;
}
@@ -722,6 +727,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to use engine private key file \"%s\".", mosq->tls_keyfile);
ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
net__print_ssl_error(mosq);
return MOSQ_ERR_TLS;
}
@@ -948,12 +954,14 @@ int net__socket_nonblock(mosq_sock_t *sock)
if(fcntl(*sock, F_SETFL, opt | O_NONBLOCK) == -1){
/* If either fcntl fails, don't want to allow this client to connect. */
COMPAT_CLOSE(*sock);
+ *sock = INVALID_SOCKET;
return MOSQ_ERR_ERRNO;
}
#else
unsigned long opt = 1;
if(ioctlsocket(*sock, FIONBIO, &opt)){
COMPAT_CLOSE(*sock);
+ *sock = INVALID_SOCKET;
return MOSQ_ERR_ERRNO;
}
#endif
diff --git a/lib/options.c b/lib/options.c
index 7bab7366..483edbb2 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -289,6 +289,7 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
}else{
return MOSQ_ERR_INVAL;
}
+ return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
@@ -322,8 +323,6 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
default:
return MOSQ_ERR_INVAL;
}
-
- return MOSQ_ERR_INVAL;
}
diff --git a/lib/packet_mosq.c b/lib/packet_mosq.c
index 0f7af742..22df79e5 100644
--- a/lib/packet_mosq.c
+++ b/lib/packet_mosq.c
@@ -98,6 +98,38 @@ void packet__cleanup(struct mosquitto__packet *packet)
packet->pos = 0;
}
+
+void packet__cleanup_all(struct mosquitto *mosq)
+{
+ struct mosquitto__packet *packet;
+
+ pthread_mutex_lock(&mosq->current_out_packet_mutex);
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+
+ /* Out packet cleanup */
+ if(mosq->out_packet && !mosq->current_out_packet){
+ mosq->current_out_packet = mosq->out_packet;
+ mosq->out_packet = mosq->out_packet->next;
+ }
+ while(mosq->current_out_packet){
+ packet = mosq->current_out_packet;
+ /* Free data and reset values */
+ mosq->current_out_packet = mosq->out_packet;
+ if(mosq->out_packet){
+ mosq->out_packet = mosq->out_packet->next;
+ }
+
+ packet__cleanup(packet);
+ mosquitto__free(packet);
+ }
+
+ packet__cleanup(&mosq->in_packet);
+
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+}
+
+
int packet__queue(struct mosquitto *mosq, struct mosquitto__packet *packet)
{
#ifndef WITH_BROKER
diff --git a/lib/packet_mosq.h b/lib/packet_mosq.h
index 5967f094..01b7d148 100644
--- a/lib/packet_mosq.h
+++ b/lib/packet_mosq.h
@@ -25,6 +25,7 @@ struct mosquitto_db;
int packet__alloc(struct mosquitto__packet *packet);
void packet__cleanup(struct mosquitto__packet *packet);
+void packet__cleanup_all(struct mosquitto *mosq);
int packet__queue(struct mosquitto *mosq, struct mosquitto__packet *packet);
int packet__check_oversize(struct mosquitto *mosq, uint32_t remaining_length);
diff --git a/lib/property_mosq.c b/lib/property_mosq.c
index 76158e58..d3854cff 100644
--- a/lib/property_mosq.c
+++ b/lib/property_mosq.c
@@ -1064,7 +1064,10 @@ const mosquitto_property *mosquitto_property_read_string_pair(const mosquitto_pr
if(value){
*value = calloc(1, p->value.s.len+1);
if(!(*value)){
- if(name) free(*name);
+ if(name){
+ free(*name);
+ *name = NULL;
+ }
return NULL;
}
memcpy(*value, p->value.s.v, p->value.s.len);
diff --git a/lib/send_connect.c b/lib/send_connect.c
index 210f125a..e35e6332 100644
--- a/lib/send_connect.c
+++ b/lib/send_connect.c
@@ -168,6 +168,7 @@ int send__connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session
property__write_all(packet, properties, false);
property__write_all(packet, local_props, false);
}
+ mosquitto_property_free_all(&local_props);
/* Payload */
if(clientid){
diff --git a/lib/util_mosq.c b/lib/util_mosq.c
index 5e1065e7..65fc2215 100644
--- a/lib/util_mosq.c
+++ b/lib/util_mosq.c
@@ -248,7 +248,7 @@ FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read)
sec.bInheritHandle = FALSE;
sec.lpSecurityDescriptor = &sd;
- hfile = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, 0,
+ hfile = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
&sec,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index 3a9bb7f7..bcc88bc6 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -1741,7 +1741,7 @@ topic clients/total in 0 test/mosquitto/org $SYS/broker/
file path
One of or
- must be provided to
+ must be provided to
allow SSL/TLS support.
bridge_capath is used to define the path to a
directory containing the PEM encoded CA
diff --git a/readme-windows.txt b/readme-windows.txt
index 9325a4c9..7bf0d954 100644
--- a/readme-windows.txt
+++ b/readme-windows.txt
@@ -61,3 +61,11 @@ command line as follows:
C:\Program Files\mosquitto\mosquitto install
C:\Program Files\mosquitto\mosquitto uninstall
+
+Logging
+-------
+
+If you use `log_dest file ...` in your configuration, the log file will be
+created with security permissions for the current user only. If running as a
+service, this means the SYSTEM user. You will only be able to view the log file
+if you add permissions for yourself or whatever user you wish to view the logs.
diff --git a/readme.md b/readme.md
index 2dce0f84..95cc4dbf 100644
--- a/readme.md
+++ b/readme.md
@@ -58,7 +58,7 @@ To build from source the recommended route for end users is to download the
archive from .
On Windows and Mac, use `cmake` to build. On other platforms, just run `make`
-to build. For Windows, see also `readme-windows.md`.
+to build. For Windows, see also `readme-windows.txt`.
If you are building from the git repository then the documentation will not
already be built. Use `make binary` to skip building the man pages, or install
diff --git a/set-version.sh b/set-version.sh
index 0e99da2f..5fe6c80c 100755
--- a/set-version.sh
+++ b/set-version.sh
@@ -2,7 +2,7 @@
MAJOR=1
MINOR=6
-REVISION=3
+REVISION=4
sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index cae454fa..95a4eb1f 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,5 +1,5 @@
name: mosquitto
-version: 1.6.3
+version: 1.6.4
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/src/database.c b/src/database.c
index 87daf68c..715c1690 100644
--- a/src/database.c
+++ b/src/database.c
@@ -893,6 +893,7 @@ int db__message_release_incoming(struct mosquitto_db *db, struct mosquitto *cont
char *source_id;
int msg_index = 0;
bool deleted = false;
+ int rc;
if(!context) return MOSQ_ERR_INVAL;
@@ -910,11 +911,17 @@ int db__message_release_incoming(struct mosquitto_db *db, struct mosquitto *cont
* denied/dropped and is being processed so the client doesn't
* keep resending it. That means we don't send it to other
* clients. */
- if(!topic || !sub__messages_queue(db, source_id, topic, 2, retain, &tail->store)){
+ if(!topic){
db__message_remove(db, &context->msgs_in, tail);
deleted = true;
}else{
- return 1;
+ rc = sub__messages_queue(db, source_id, topic, 2, retain, &tail->store);
+ if(rc == MOSQ_ERR_SUCCESS || rc == MOSQ_ERR_NO_SUBSCRIBERS){
+ db__message_remove(db, &context->msgs_in, tail);
+ deleted = true;
+ }else{
+ return 1;
+ }
}
}
}
@@ -936,7 +943,7 @@ int db__message_release_incoming(struct mosquitto_db *db, struct mosquitto *cont
if(deleted){
return MOSQ_ERR_SUCCESS;
}else{
- return 1;
+ return MOSQ_ERR_NOT_FOUND;
}
}
diff --git a/src/handle_publish.c b/src/handle_publish.c
index 8b76fd5e..a13160fa 100644
--- a/src/handle_publish.c
+++ b/src/handle_publish.c
@@ -331,7 +331,6 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
break;
case 2:
if(dup == 0){
- util__decrement_receive_quota(context);
res = db__message_insert(db, context, mid, mosq_md_in, qos, retain, stored, NULL);
}else{
res = 0;
diff --git a/src/mosquitto_passwd.c b/src/mosquitto_passwd.c
index afe3e199..00e048fb 100644
--- a/src/mosquitto_passwd.c
+++ b/src/mosquitto_passwd.c
@@ -339,13 +339,15 @@ int gets_quiet(char *s, int len)
#endif
}
-int get_password(char *password, int len)
+int get_password(char *password, size_t len)
{
char pw1[MAX_BUFFER_LEN], pw2[MAX_BUFFER_LEN];
+ size_t minLen;
+ minLen = len < MAX_BUFFER_LEN ? len : MAX_BUFFER_LEN;
printf("Password: ");
fflush(stdout);
- if(gets_quiet(pw1, MAX_BUFFER_LEN)){
+ if(gets_quiet(pw1, minLen)){
fprintf(stderr, "Error: Empty password.\n");
return 1;
}
@@ -353,7 +355,7 @@ int get_password(char *password, int len)
printf("Reenter password: ");
fflush(stdout);
- if(gets_quiet(pw2, MAX_BUFFER_LEN)){
+ if(gets_quiet(pw2, minLen)){
fprintf(stderr, "Error: Empty password.\n");
return 1;
}
@@ -364,7 +366,7 @@ int get_password(char *password, int len)
return 1;
}
- strncpy(password, pw1, len);
+ strncpy(password, pw1, minLen);
return 0;
}
@@ -526,7 +528,7 @@ int main(int argc, char *argv[])
#endif
if(create_new){
- rc = get_password(password, 1024);
+ rc = get_password(password, MAX_BUFFER_LEN);
if(rc){
free(password_file);
return rc;
@@ -581,7 +583,7 @@ int main(int argc, char *argv[])
/* Update password for individual user */
rc = update_pwuser(fptr, ftmp, username, password_cmd);
}else{
- rc = get_password(password, 1024);
+ rc = get_password(password, MAX_BUFFER_LEN);
if(rc){
fclose(fptr);
fclose(ftmp);
diff --git a/src/session_expiry.c b/src/session_expiry.c
index 057e032c..68540a71 100644
--- a/src/session_expiry.c
+++ b/src/session_expiry.c
@@ -94,7 +94,9 @@ 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_time < now){
+ if(item->context->session_expiry_interval != UINT32_MAX
+ && item->context->session_expiry_time < now){
+
context = item->context;
session_expiry__remove(context);
diff --git a/test/broker/02-subpub-qos2-1322.py b/test/broker/02-subpub-qos2-1322.py
new file mode 100755
index 00000000..00720be5
--- /dev/null
+++ b/test/broker/02-subpub-qos2-1322.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+
+# Test for issue 1322:
+
+## restart mosquitto
+#sudo systemctl restart mosquitto.service
+#
+## listen on topic1
+#mosquitto_sub -t "topic1"
+#
+## publish to topic1 without clean session
+#mosquitto_pub -t "topic1" -q 2 -c --id "foobar" -m "message1"
+## message1 on topic1 is received as expected
+#
+## publish to topic2 without clean session
+## IMPORTANT: no subscription to this topic is present on broker!
+#mosquitto_pub -t "topic2" -q 2 -c --id "foobar" -m "message2"
+## this goes nowhere, as no subscriber present
+#
+## publish to topic1 without clean session
+#mosquitto_pub -t "topic1" -q 2 -c --id "foobar" -m "message3"
+## message3 on topic1 IS NOT RECEIVED
+#
+## listen on topic2
+#mosquitto_sub -t "topic2"
+#
+## publish to topic1 without clean session
+#mosquitto_pub -t "topic1" -q 2 -c --id "foobar" -m "message4"
+## message2 on topic2 is received incorrectly
+#
+## publish to topic1 without clean session
+#mosquitto_pub -t "topic1" -q 2 -c --id "foobar" -m "message5"
+## message5 on topic1 is received as expected (message4 was dropped)
+
+
+
+from mosq_test_helper import *
+
+rc = 1
+keepalive = 60
+pub_connect_packet = mosq_test.gen_connect("pub", keepalive=keepalive, clean_session=False)
+pub_connack1_packet = mosq_test.gen_connack(rc=0)
+pub_connack2_packet = mosq_test.gen_connack(rc=0, flags=1)
+
+sub1_connect_packet = mosq_test.gen_connect("sub1", keepalive=keepalive)
+sub1_connack_packet = mosq_test.gen_connack(rc=0)
+
+sub2_connect_packet = mosq_test.gen_connect("sub2", keepalive=keepalive)
+sub2_connack_packet = mosq_test.gen_connack(rc=0)
+
+mid = 1
+subscribe1_packet = mosq_test.gen_subscribe(mid, "topic1", 0)
+suback1_packet = mosq_test.gen_suback(mid, 0)
+
+mid = 1
+subscribe2_packet = mosq_test.gen_subscribe(mid, "topic2", 0)
+suback2_packet = mosq_test.gen_suback(mid, 0)
+
+# All publishes have the same mid
+mid = 1
+pubrec_packet = mosq_test.gen_pubrec(mid)
+pubrel_packet = mosq_test.gen_pubrel(mid)
+pubcomp_packet = mosq_test.gen_pubcomp(mid)
+
+publish1s_packet = mosq_test.gen_publish("topic1", qos=2, mid=mid, payload="message1")
+publish2s_packet = mosq_test.gen_publish("topic2", qos=2, mid=mid, payload="message2")
+publish3s_packet = mosq_test.gen_publish("topic1", qos=2, mid=mid, payload="message3")
+publish4s_packet = mosq_test.gen_publish("topic1", qos=2, mid=mid, payload="message4")
+publish5s_packet = mosq_test.gen_publish("topic1", qos=2, mid=mid, payload="message5")
+
+publish1r_packet = mosq_test.gen_publish("topic1", qos=0, payload="message1")
+publish2r_packet = mosq_test.gen_publish("topic2", qos=0, payload="message2")
+publish3r_packet = mosq_test.gen_publish("topic1", qos=0, payload="message3")
+publish4r_packet = mosq_test.gen_publish("topic1", qos=0, payload="message4")
+publish5r_packet = mosq_test.gen_publish("topic1", qos=0, payload="message5")
+
+port = mosq_test.get_port()
+broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port)
+
+try:
+ sub1 = mosq_test.do_client_connect(sub1_connect_packet, sub1_connack_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(sub1, subscribe1_packet, suback1_packet, "suback1")
+
+ pub = mosq_test.do_client_connect(pub_connect_packet, pub_connack1_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(pub, publish1s_packet, pubrec_packet, "pubrec1")
+ mosq_test.do_send_receive(pub, pubrel_packet, pubcomp_packet, "pubcomp1")
+ pub.close()
+
+ if mosq_test.expect_packet(sub1, "publish1", publish1r_packet):
+ pub = mosq_test.do_client_connect(pub_connect_packet, pub_connack2_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(pub, publish2s_packet, pubrec_packet, "pubrec2")
+ mosq_test.do_send_receive(pub, pubrel_packet, pubcomp_packet, "pubcomp2")
+ pub.close()
+
+ # We expect nothing on sub1
+ mosq_test.do_ping(sub1, error_string="pingresp1")
+
+ pub = mosq_test.do_client_connect(pub_connect_packet, pub_connack2_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(pub, publish3s_packet, pubrec_packet, "pubrec3")
+ mosq_test.do_send_receive(pub, pubrel_packet, pubcomp_packet, "pubcomp3")
+ pub.close()
+
+ if mosq_test.expect_packet(sub1, "publish3", publish3r_packet):
+ sub2 = mosq_test.do_client_connect(sub2_connect_packet, sub2_connack_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(sub2, subscribe2_packet, suback2_packet, "suback2")
+
+ pub = mosq_test.do_client_connect(pub_connect_packet, pub_connack2_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(pub, publish4s_packet, pubrec_packet, "pubrec4")
+ mosq_test.do_send_receive(pub, pubrel_packet, pubcomp_packet, "pubcomp4")
+ pub.close()
+
+ # We expect nothing on sub2
+ mosq_test.do_ping(sub2, error_string="pingresp2")
+
+ if mosq_test.expect_packet(sub1, "publish4", publish4r_packet):
+ pub = mosq_test.do_client_connect(pub_connect_packet, pub_connack2_packet, timeout=10, port=port)
+ mosq_test.do_send_receive(pub, publish5s_packet, pubrec_packet, "pubrec5")
+ mosq_test.do_send_receive(pub, pubrel_packet, pubcomp_packet, "pubcomp5")
+ pub.close()
+
+ # We expect nothing on sub2
+ mosq_test.do_ping(sub2, error_string="pingresp2")
+
+ if mosq_test.expect_packet(sub1, "publish5", publish5r_packet):
+ rc = 0
+
+ sub2.close()
+ sub1.close()
+finally:
+ broker.terminate()
+ broker.wait()
+ (stdo, stde) = broker.communicate()
+ if rc:
+ print(stde.decode('utf-8'))
+
+exit(rc)
+
diff --git a/test/broker/03-publish-qos1-max-inflight.py b/test/broker/03-publish-qos1-max-inflight.py
new file mode 100755
index 00000000..6d18cad8
--- /dev/null
+++ b/test/broker/03-publish-qos1-max-inflight.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+# Test whether a PUBLISH to a topic with QoS 1 results in the correct packet flow.
+# With max_inflight_messages set to 1
+
+from mosq_test_helper import *
+
+def write_config(filename, port):
+ with open(filename, 'w') as f:
+ f.write("port %d\n" % (port))
+ f.write("max_inflight_messages 1\n")
+
+port = mosq_test.get_port()
+conf_file = os.path.basename(__file__).replace('.py', '.conf')
+write_config(conf_file, port)
+
+
+rc = 1
+keepalive = 60
+connect_packet = mosq_test.gen_connect("pub-qos1-test", keepalive=keepalive)
+connack_packet = mosq_test.gen_connack(rc=0)
+
+mid = 311
+publish_packet = mosq_test.gen_publish("pub/qos1/test", qos=1, mid=mid, payload="message")
+puback_packet = mosq_test.gen_puback(mid)
+
+port = mosq_test.get_port()
+broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
+
+try:
+ sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port, timeout=10)
+ mosq_test.do_send_receive(sock, publish_packet, puback_packet, "puback")
+
+ rc = 0
+
+ sock.close()
+finally:
+ os.remove(conf_file)
+ broker.terminate()
+ broker.wait()
+ (stdo, stde) = broker.communicate()
+ if rc:
+ print(stde.decode('utf-8'))
+
+exit(rc)
+
diff --git a/test/broker/03-publish-qos2-max-inflight.py b/test/broker/03-publish-qos2-max-inflight.py
new file mode 100755
index 00000000..3b4f608c
--- /dev/null
+++ b/test/broker/03-publish-qos2-max-inflight.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+
+# Test whether a PUBLISH to a topic with QoS 2 results in the correct packet flow.
+# With max_inflight_messages set to 1
+
+from mosq_test_helper import *
+
+def write_config(filename, port):
+ with open(filename, 'w') as f:
+ f.write("port %d\n" % (port))
+ f.write("max_inflight_messages 1\n")
+
+port = mosq_test.get_port()
+conf_file = os.path.basename(__file__).replace('.py', '.conf')
+write_config(conf_file, port)
+
+
+rc = 1
+keepalive = 60
+connect_packet = mosq_test.gen_connect("pub-qos2-test", keepalive=keepalive)
+connack_packet = mosq_test.gen_connack(rc=0)
+
+mid = 312
+publish_packet = mosq_test.gen_publish("pub/qos2/test", qos=2, mid=mid, payload="message")
+pubrec_packet = mosq_test.gen_pubrec(mid)
+pubrel_packet = mosq_test.gen_pubrel(mid)
+pubcomp_packet = mosq_test.gen_pubcomp(mid)
+
+port = mosq_test.get_port()
+broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
+
+try:
+ sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port, timeout=10)
+ mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "pubrec")
+ mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "pubcomp")
+
+ rc = 0
+
+ sock.close()
+finally:
+ os.remove(conf_file)
+ broker.terminate()
+ broker.wait()
+ (stdo, stde) = broker.communicate()
+ if rc:
+ print(stde.decode('utf-8'))
+
+exit(rc)
+
diff --git a/test/broker/Makefile b/test/broker/Makefile
index ba91fb8a..8da4d7fa 100644
--- a/test/broker/Makefile
+++ b/test/broker/Makefile
@@ -64,6 +64,7 @@ endif
./02-subpub-qos1-nolocal.py
./02-subpub-qos1-v5.py
./02-subpub-qos1.py
+ ./02-subpub-qos2-1322.py
./02-subpub-qos2-bad-puback-1.py
./02-subpub-qos2-bad-puback-2.py
./02-subpub-qos2-bad-pubcomp.py
@@ -101,6 +102,7 @@ endif
./03-publish-qos1-no-subscribers-v5.py
./03-publish-qos1-retain-disabled.py
./03-publish-qos1.py
+ ./03-publish-qos2-max-inflight.py
./03-publish-qos2.py
04 :
diff --git a/test/broker/test.py b/test/broker/test.py
index 497e3627..afaa5388 100755
--- a/test/broker/test.py
+++ b/test/broker/test.py
@@ -43,6 +43,7 @@ tests = [
(1, './02-subpub-qos1-nolocal.py'),
(1, './02-subpub-qos1-v5.py'),
(1, './02-subpub-qos1.py'),
+ (1, './02-subpub-qos2-1322.py'),
(1, './02-subpub-qos2-bad-puback-1.py'),
(1, './02-subpub-qos2-bad-puback-2.py'),
(1, './02-subpub-qos2-bad-pubcomp.py'),
@@ -79,6 +80,7 @@ tests = [
(1, './03-publish-qos1-no-subscribers-v5.py'),
(1, './03-publish-qos1-retain-disabled.py'),
(1, './03-publish-qos1.py'),
+ (1, './03-publish-qos2-max-inflight.py'),
(1, './03-publish-qos2.py'),
(1, './04-retain-check-source-persist.py'),
diff --git a/test/unit/property_user_read.c b/test/unit/property_user_read.c
index d458eb7a..902296bc 100644
--- a/test/unit/property_user_read.c
+++ b/test/unit/property_user_read.c
@@ -451,14 +451,19 @@ static void missing_read_helper(mosquitto_property *proplist)
CU_ASSERT_EQUAL(int32_value, 1800);
/* MISSING */
+ value = NULL;
prop = mosquitto_property_read_string(proplist, MQTT_PROP_CONTENT_TYPE, &value, false);
CU_ASSERT_PTR_NULL(prop);
/* NOT MISSING */
+ value = NULL;
prop = mosquitto_property_read_string(proplist, MQTT_PROP_RESPONSE_TOPIC, &value, false);
CU_ASSERT_PTR_NOT_NULL(prop);
- CU_ASSERT_STRING_EQUAL(value, "response/topic");
- free(value);
+ CU_ASSERT_PTR_NOT_NULL(value);
+ if(value){
+ CU_ASSERT_STRING_EQUAL(value, "response/topic");
+ free(value);
+ }
/* MISSING */
prop = mosquitto_property_read_binary(proplist, MQTT_PROP_CORRELATION_DATA, (void **)&value, &length, false);
@@ -474,21 +479,29 @@ static void missing_read_helper(mosquitto_property *proplist)
CU_ASSERT_PTR_NULL(prop);
/* NOT MISSING */
+ value = NULL;
prop = mosquitto_property_read_string(proplist, MQTT_PROP_SERVER_REFERENCE, &value, false);
CU_ASSERT_PTR_NOT_NULL(prop);
- CU_ASSERT_STRING_EQUAL(value, "localhost");
- free(value);
+ CU_ASSERT_PTR_NOT_NULL(value);
+ if(value){
+ CU_ASSERT_STRING_EQUAL(value, "localhost");
+ free(value);
+ }
/* MISSING */
prop = mosquitto_property_read_int32(proplist, MQTT_PROP_SESSION_EXPIRY_INTERVAL, &int32_value, false);
CU_ASSERT_PTR_NULL(prop);
/* NOT MISSING */
+ value = NULL;
prop = mosquitto_property_read_binary(proplist, MQTT_PROP_AUTHENTICATION_DATA, (void **)&value, &length, false);
CU_ASSERT_PTR_NOT_NULL(prop);
- CU_ASSERT_NSTRING_EQUAL(value, "password", strlen("password"));
- CU_ASSERT_EQUAL(length, strlen("password"));
- free(value);
+ CU_ASSERT_PTR_NOT_NULL(value);
+ if(value){
+ CU_ASSERT_NSTRING_EQUAL(value, "password", strlen("password"));
+ CU_ASSERT_EQUAL(length, strlen("password"));
+ free(value);
+ }
/* MISSING */
prop = mosquitto_property_read_int16(proplist, MQTT_PROP_SERVER_KEEP_ALIVE, &int16_value, false);
diff --git a/www/pages/download.md b/www/pages/download.md
index 13aa8ddc..a2acb0e2 100644
--- a/www/pages/download.md
+++ b/www/pages/download.md
@@ -1,7 +1,7 @@
+
+This is a bugfix release.
+
+## Broker
+- Fix persistent clients being incorrectly expired on Raspberry Pis.
+ Closes [#1272].
+- Windows: Allow other applications access to the log file when running.
+ Closes [#515].
+- Fix incoming QoS 2 messages being blocked when `max_inflight_messages` was
+ set to 1. Closes [#1332].
+- Fix incoming messages not being removed for a client if the topic being
+ published to does not have any subscribers. Closes [#1322].
+
+## Client library
+- Fix MQTT v5 subscription options being incorrectly set for MQTT v3
+ subscriptions. Closes [#1353].
+- Make behaviour of `mosquitto_connect_async()` consistent with
+ `mosquitto_connect()` when connecting to a non-existent server.
+ Closes [#1345].
+- `mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, ...)` was incorrectly
+ returning `MOSQ_ERR_INVAL` with valid input. This has been fixed.
+ Closes [#1360].
+- `on_connect` callback is now called with the correct v5 reason code if a v5
+ client connects to a v3.x broker and is sent a CONNACK with the
+ "unacceptable protocol version" connack reason code.
+- Fix memory leak when setting v5 properties in `mosquitto_connect_v5()`.
+- Fix properties not being sent on QoS>0 PUBLISH messages.
+
+## Clients
+- `mosquitto_pub`: fix error codes not being returned when `mosquitto_pub` exits.
+ Closes [#1354].
+- All clients: improve error messages when connecting to a v3.x broker when in
+ v5 mode. Closes [#1344].
+
+## Other
+- Various documentation fixes.
+
+[#515]: https://github.com/eclipse/mosquitto/issues/515
+[#1272]: https://github.com/eclipse/mosquitto/issues/1272
+[#1322]: https://github.com/eclipse/mosquitto/issues/1322
+[#1332]: https://github.com/eclipse/mosquitto/issues/1332
+[#1344]: https://github.com/eclipse/mosquitto/issues/1344
+[#1345]: https://github.com/eclipse/mosquitto/issues/1345
+[#1353]: https://github.com/eclipse/mosquitto/issues/1353
+[#1354]: https://github.com/eclipse/mosquitto/issues/1354
+[#1360]: https://github.com/eclipse/mosquitto/issues/1360