diff --git a/ChangeLog.txt b/ChangeLog.txt index 6601a1d29f..a5fd7eb67d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -20,10 +20,15 @@ Client library: - `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. 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. diff --git a/client/pub_client.c b/client/pub_client.c index 69cea64216..0debcaee39 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -168,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); } } } diff --git a/client/rr_client.c b/client/rr_client.c index 02801e829a..44f105b02f 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); } @@ -356,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 a279b2491c..68b0e79084 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); @@ -353,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/lib/handle_connack.c b/lib/handle_connack.c index 19b6a66160..60780f6ca1 100644 --- a/lib/handle_connack.c +++ b/lib/handle_connack.c @@ -28,6 +28,29 @@ and the Eclipse Distribution License is available at #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/loop.c b/lib/loop.c index 2342c945aa..36763e06c3 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; }