diff --git a/apps/mosquitto_ctrl/client.c b/apps/mosquitto_ctrl/client.c index 26d62a5136..905e73817e 100644 --- a/apps/mosquitto_ctrl/client.c +++ b/apps/mosquitto_ctrl/client.c @@ -106,12 +106,8 @@ static void on_connect(struct mosquitto *mosq, void *obj, int reason_code, int f ctrl->response_topic = NULL; } }else{ - if(ctrl->cfg.protocol_version == MQTT_PROTOCOL_V5){ - if(reason_code == MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION){ - fprintf(stderr, "Connection error: %s. Try connecting to an MQTT v5 broker, or use MQTT v3.x mode.\n", mosquitto_reason_string(reason_code)); - }else{ - fprintf(stderr, "Connection error: %s\n", mosquitto_reason_string(reason_code)); - } + if(ctrl->cfg.protocol_version == MQTT_PROTOCOL_V5 && reason_code == MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION){ + fprintf(stderr, "Connection error: %s. Try connecting to an MQTT v5 broker, or use MQTT v3.x mode.\n", mosquitto_connack_string(reason_code)); }else{ fprintf(stderr, "Connection error: %s\n", mosquitto_connack_string(reason_code)); } diff --git a/client/pub_client.c b/client/pub_client.c index ff5ac22475..346bde7447 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -173,12 +173,8 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag } }else{ if(result){ - if(cfg.protocol_version == MQTT_PROTOCOL_V5){ - 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)); - } + if(cfg.protocol_version == MQTT_PROTOCOL_V5 && 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_connack_string(result)); }else{ err_printf(&cfg, "Connection error: %s\n", mosquitto_connack_string(result)); } diff --git a/client/rr_client.c b/client/rr_client.c index 23333034a6..8bd21b08e3 100644 --- a/client/rr_client.c +++ b/client/rr_client.c @@ -119,7 +119,7 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag }else{ client_state = rr_s_disconnect; if(result){ - err_printf(&cfg, "Connection error: %s\n", mosquitto_reason_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/sub_client.c b/client/sub_client.c index 9caed63648..d10ef76eb8 100644 --- a/client/sub_client.c +++ b/client/sub_client.c @@ -154,12 +154,8 @@ static void my_connect_callback(struct mosquitto *mosq, void *obj, int result, i } }else{ if(result){ - if(cfg.protocol_version == MQTT_PROTOCOL_V5){ - 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)); - } + if(cfg.protocol_version == MQTT_PROTOCOL_V5 && 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_connack_string(result)); }else{ err_printf(&cfg, "Connection error: %s\n", mosquitto_connack_string(result)); } diff --git a/examples/publish/basic-1.c b/examples/publish/basic-1.c index 955fcff613..3ee9981bde 100644 --- a/examples/publish/basic-1.c +++ b/examples/publish/basic-1.c @@ -17,10 +17,6 @@ void on_connect(struct mosquitto *mosq, void *obj, int reason_code) { UNUSED(obj); - /* Print out the connection result. mosquitto_connack_string() produces an - * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 - * clients is mosquitto_reason_string(). - */ printf("on_connect: %s\n", mosquitto_connack_string(reason_code)); if(reason_code != 0){ /* If the connection fails for any reason, we don't want to keep on diff --git a/examples/publish/basic-websockets-1.c b/examples/publish/basic-websockets-1.c index a72a1a1a2a..94874a5146 100644 --- a/examples/publish/basic-websockets-1.c +++ b/examples/publish/basic-websockets-1.c @@ -19,10 +19,6 @@ void on_connect(struct mosquitto *mosq, void *obj, int reason_code) { UNUSED(obj); - /* Print out the connection result. mosquitto_connack_string() produces an - * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 - * clients is mosquitto_reason_string(). - */ printf("on_connect: %s\n", mosquitto_connack_string(reason_code)); if(reason_code != 0){ /* If the connection fails for any reason, we don't want to keep on diff --git a/examples/subscribe/basic-1.c b/examples/subscribe/basic-1.c index 613e29b8b5..1016117494 100644 --- a/examples/subscribe/basic-1.c +++ b/examples/subscribe/basic-1.c @@ -14,10 +14,6 @@ void on_connect(struct mosquitto *mosq, void *obj, int reason_code) { int rc; - /* Print out the connection result. mosquitto_connack_string() produces an - * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 - * clients is mosquitto_reason_string(). - */ printf("on_connect: %s\n", mosquitto_connack_string(reason_code)); if(reason_code != 0){ /* If the connection fails for any reason, we don't want to keep on diff --git a/include/mosquitto/libcommon_string.h b/include/mosquitto/libcommon_string.h index 118b3451aa..526d08a8cb 100644 --- a/include/mosquitto/libcommon_string.h +++ b/include/mosquitto/libcommon_string.h @@ -53,9 +53,24 @@ libmosqcommon_EXPORT const char *mosquitto_strerror(int mosq_errno); * * Returns: * A constant string describing the result. + * Codes 0-5 are the standard MQTT v3.x connection results, while others codes are MQTT v5 connection results. */ libmosqcommon_EXPORT const char *mosquitto_connack_string(int connack_code); +/* + * Function: mosquitto_disconnect_string + * + * Call to obtain a const string description of an MQTT disconnect result. + * + * Parameters: + * disconnect_code - an MQTT disconnect result. + * + * Returns: + * A constant string describing the result. + * Codes 0 is a normal disconnection + */ +libmosqcommon_EXPORT const char *mosquitto_disconnect_string(int disconnect_code); + /* * Function: mosquitto_reason_string * diff --git a/include/mosquitto/libmosquitto_callbacks.h b/include/mosquitto/libmosquitto_callbacks.h index fc74ae8659..6a6cac3080 100644 --- a/include/mosquitto/libmosquitto_callbacks.h +++ b/include/mosquitto/libmosquitto_callbacks.h @@ -53,8 +53,9 @@ extern "C" { * Callback Parameters: * mosq - the mosquitto instance making the callback. * obj - the user data provided in - * rc - the return code of the connection response. The values are defined by - * the MQTT protocol version in use. + * rc - the return code of the connection response. + * Decodable with . + * The values are defined by the MQTT protocol version in use. * For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html * For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html * @@ -78,8 +79,9 @@ libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, LIBMO * Callback Parameters: * mosq - the mosquitto instance making the callback. * obj - the user data provided in - * rc - the return code of the connection response. The values are defined by - * the MQTT protocol version in use. + * rc - the return code of the connection response. + * Decodable with . + * The values are defined by the MQTT protocol version in use. * For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html * For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html * flags - the connect flags. @@ -108,8 +110,9 @@ libmosq_EXPORT void mosquitto_connect_with_flags_callback_set(struct mosquitto * * Callback Parameters: * mosq - the mosquitto instance making the callback. * obj - the user data provided in - * rc - the return code of the connection response. The values are defined by - * the MQTT protocol version in use. + * rc - the return code of the connection response. + * Decodable with . + * The values are defined by the MQTT protocol version in use. * For MQTT v5.0, look at section 3.2.2.2 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html * For MQTT v3.1.1, look at section 3.2.2.3 Connect Return code: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html * flags - the connect flags. @@ -155,9 +158,12 @@ libmosq_EXPORT void mosquitto_pre_connect_callback_set(struct mosquitto *mosq, L * Callback Parameters: * mosq - the mosquitto instance making the callback. * obj - the user data provided in - * rc - integer value indicating the reason for the disconnect. A value of 0 - * means the client has called . Any other value - * indicates that the disconnect is unexpected. + * rc - integer value indicating the reason for the disconnect. + * Decodable with . + * A value of 0 means the client has called . + * Any other value indicates that the disconnect is unexpected. + * For MQTT v5.0, look at section 3.14.2.1 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html + * For MQTT v3.1.1, look at section 3.14 Disconnect notification: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html */ typedef void (*LIBMOSQ_CB_disconnect)(struct mosquitto *mosq, void *obj, int rc); libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, LIBMOSQ_CB_disconnect on_disconnect); @@ -180,9 +186,12 @@ libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, LI * Callback Parameters: * mosq - the mosquitto instance making the callback. * obj - the user data provided in - * rc - integer value indicating the reason for the disconnect. A value of 0 - * means the client has called . Any other value - * indicates that the disconnect is unexpected. + * rc - integer value indicating the reason for the disconnect. + * Decodable with . + * A value of 0 means the client has called . + * Any other value indicates that the disconnect is unexpected. + * For MQTT v5.0, look at section 3.14.2.1 Connect Reason code: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html + * For MQTT v3.1.1, look at section 3.14 Disconnect notification: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html * props - list of MQTT 5 properties, or NULL */ typedef void (*LIBMOSQ_CB_disconnect_v5)(struct mosquitto *mosq, void *obj, int rc, const mosquitto_property *props); @@ -246,6 +255,7 @@ libmosq_EXPORT void mosquitto_publish_callback_set(struct mosquitto *mosq, LIBMO * obj - the user data provided in * mid - the message id of the sent message. * reason_code - the MQTT 5 reason code + * Decodable with . * props - list of MQTT 5 properties, or NULL */ typedef void (*LIBMOSQ_CB_publish_v5)(struct mosquitto *mosq, void *obj, int mid, int reason_code, const mosquitto_property *props); diff --git a/lib/cpp/mosquittopp.cpp b/lib/cpp/mosquittopp.cpp index 683e88caf4..2fe4e550ae 100644 --- a/lib/cpp/mosquittopp.cpp +++ b/lib/cpp/mosquittopp.cpp @@ -168,6 +168,11 @@ const char* connack_string(int connack_code) return mosquitto_connack_string(connack_code); } +const char* disconnect_string(int connack_code) +{ + return mosquitto_disconnect_string(connack_code); +} + int property_check_command(int command, int identifier) { return mosquitto_property_check_command(command, identifier); diff --git a/lib/linker.version b/lib/linker.version index 7f8dbd0a0d..aedfe5f177 100644 --- a/lib/linker.version +++ b/lib/linker.version @@ -41,6 +41,7 @@ MOSQ_1.0 { mosquitto_user_data_set; mosquitto_strerror; mosquitto_connack_string; + mosquitto_disconnect_string; mosquitto_tls_set; mosquitto_tls_opts_set; mosquitto_tls_psk_set; diff --git a/lib/srv_mosq.c b/lib/srv_mosq.c index ba22b6b57c..46f42c2110 100644 --- a/lib/srv_mosq.c +++ b/lib/srv_mosq.c @@ -48,7 +48,7 @@ static void srv_callback(void *arg, int status, int timeouts, unsigned char *abu } }else{ log__printf(mosq, MOSQ_LOG_ERR, "Error: SRV lookup failed (%d).", status); - /* FIXME - calling on_disconnect here isn't correct. */ + /* FIXME - calling on_disconnect here isn't correct. Error code is also incorrect*/ callback__on_disconnect(mosq, MOSQ_ERR_LOOKUP, NULL); } } diff --git a/libcommon/strings_common.c b/libcommon/strings_common.c index b958104471..149bbde46d 100644 --- a/libcommon/strings_common.c +++ b/libcommon/strings_common.c @@ -160,11 +160,169 @@ const char *mosquitto_connack_string(int connack_code) return "Connection Refused: bad user name or password"; case 5: return "Connection Refused: not authorised"; + case 128: + // The Server does not wish to reveal the reason for the failure, or none of the other Reason Codes apply. + return "Connection Refused: Unspecified error"; + case 129: + // Data within the CONNECT packet could not be correctly parsed. + return "Connection Refused: Malformed Packet"; + case 130: + // Data in the CONNECT packet does not conform to this specification. + return "Connection Refused: Protocol Error"; + case 131: + // The CONNECT is valid but is not accepted by this Server. + return "Connection Refused: Implementation specific error"; + case 132: + // The Server does not support the version of the MQTT protocol requested by the Client. + return "Connection Refused: Unsupported Protocol Version"; + case 133: + // The Client Identifier is a valid string but is not allowed by the Server. + return "Connection Refused: Client Identifier not valid"; + case 134: + // The Server does not accept the User Name or Password specified by the Client + return "Connection Refused: Bad User Name or Password"; + case 135: + // The Client is not authorized to connect. + return "Connection Refused: Not authorized"; + case 136: + // The MQTT Server is not available. + return "Connection Refused: Server unavailable"; + case 137: + // The Server is busy. Try again later. + return "Connection Refused: Server busy"; + case 138: + // This Client has been banned by administrative action. Contact the server administrator. + return "Connection Refused: Banned"; + case 140: + // The authentication method is not supported or does not match the authentication method currently in use. + return "Connection Refused: Bad authentication method"; + case 144: + // The Will Topic Name is not malformed, but is not accepted by this Server. + return "Connection Refused: Topic Name invalid"; + case 149: + // The CONNECT packet exceeded the maximum permissible size. + return "Connection Refused: Packet too large"; + case 151: + // An implementation or administrative imposed limit has been exceeded. + return "Connection Refused: Quota exceeded"; + case 153: + // The Will Payload does not match the specified Payload Format Indicator. + return "Connection Refused: Payload format invalid"; + case 154: + // The Server does not support retained messages, and Will Retain was set to 1. + return "Connection Refused: Retain not supported"; + case 155: + // The Server does not support the QoS set in Will QoS. + return "Connection Refused: QoS not supported"; + case 156: + // The Client should temporarily use another server. + return "Connection Refused: Use another server"; + case 157: + // The Client should permanently use another server. + return "Connection Refused: Server moved"; + case 159: + // The connection rate limit has been exceeded. + return "Connection Refused: Connection rate exceeded"; default: return "Connection Refused: unknown reason"; } } +const char *mosquitto_disconnect_string(int disconnect_code) { + switch (disconnect_code) { + case 0: + // Close the connection normally. Do not send the Will Message. + return "Disconnected: Normal disconnection"; + case 4: + // The Client wishes to disconnect but requires that the Server also publishes its Will Message. + return "Disconnected: Disconnect with Will Message"; + case 128: + // The Connection is closed but the sender either does not wish to reveal the reason, or none of the other Reason Codes apply. + return "Disconnected: Unspecified error"; + case 129: + // The received packet does not conform to this specification. + return "Disconnected: Malformed Packet"; + case 130: + // An unexpected or out of order packet was received. + return "Disconnected: Protocol Error"; + case 131: + // The packet received is valid but cannot be processed by this implementation. + return "Disconnected: Implementation specific error"; + case 135: + // The request is not authorized. + return "Disconnected: Not authorized"; + case 137: + // The Server is busy and cannot continue processing requests from this Client. + return "Disconnected: Server busy"; + case 139: + // The Server is shutting down. + return "Disconnected: Server shutting down"; + case 141: + // The Connection is closed because no packet has been received for 1.5 times the Keepalive time. + return "Disconnected: Keep Alive timeout"; + case 142: + // Another Connection using the same ClientID has connected causing this Connection to be closed. + return "Disconnected: Session taken over"; + case 143: + // The Topic Filter is correctly formed, but is not accepted by this Sever. + return "Disconnected: Topic Filter invalid"; + case 144: + // The Topic Name is correctly formed, but is not accepted by this Client or Server. + return "Disconnected: Topic Name invalid"; + case 147: + // The Client or Server has received more than Receive Maximum publication for which it has not sent PUBACK or PUBCOMP. + return "Disconnected: Receive Maximum exceeded"; + case 148: + // The Client or Server has received a PUBLISH packet containing a Topic Alias which is greater than the Maximum Topic Alias it sent in the CONNECT or CONNACK packet. + return "Disconnected: Topic Alias invalid"; + case 149: + // The packet size is greater than Maximum Packet Size for this Client or Server. + return "Disconnected: Packet too large"; + case 150: + // The received data rate is too high. + return "Disconnected: Message rate too high"; + case 151: + // An implementation or administrative imposed limit has been exceeded. + return "Disconnected: Quota exceeded"; + case 152: + // The Connection is closed due to an administrative action. + return "Disconnected: Administrative action"; + case 153: + // The payload format does not match the one specified by the Payload Format Indicator. + return "Disconnected: Payload format invalid"; + case 154: + // The Server has does not support retained messages. + return "Disconnected: Retain not supported"; + case 155: + // The Client specified a QoS greater than the QoS specified in a Maximum QoS in the CONNACK. + return "Disconnected: QoS not supported"; + case 156: + // The Client should temporarily change its Server. + return "Disconnected: Use another server"; + case 157: + // The Server is moved and the Client should permanently change its server location. + return "Disconnected: Server moved"; + case 158: + // The Server does not support Shared Subscriptions. + return "Disconnected: Shared Subscriptions not supported"; + case 159: + // This connection is closed because the connection rate is too high. + return "Disconnected: Connection rate exceeded"; + case 160: + // The maximum connection time authorized for this connection has been exceeded. + return "Disconnected: Maximum connect time exceeded"; + case 161: + // The Server does not support Subscription Identifiers; the subscription is not accepted. + return "Disconnected: Subscription Identifiers not supported"; + case 162: + // The Server does not support Wildcard Subscriptions; the subscription is not accepted. + return "Disconnected: Wildcard Subscriptions not supported"; + default: + // Unknown reason + return "Disconnected: unknown reason"; + } +} + const char *mosquitto_reason_string(int reason_code) { switch(reason_code){ diff --git a/test/unit/libcommon/strings_test.c b/test/unit/libcommon/strings_test.c index 06121dc80a..2d6f4a1874 100644 --- a/test/unit/libcommon/strings_test.c +++ b/test/unit/libcommon/strings_test.c @@ -125,7 +125,9 @@ static void TEST_mosquitto_strerror(void) static void TEST_mosquitto_connack_string(void) { const char *str; - uint8_t used[] = {0, 1, 2, 3, 4, 5}; + uint8_t used[] = {0, 1, 2, 3, 4, 5, 128,129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 140, + 144, 149, 151, 153, 154, 155, 156, 157, 159}; /* Iterate over all possible codes, checking we have a place holder for all * unused codes, and that all used codes do not have place holder text. */ @@ -155,6 +157,43 @@ static void TEST_mosquitto_connack_string(void) } } +static void TEST_mosquitto_disconnect_string(void) +{ + const char *str; + uint8_t used[] = {0, 4, + 128, 129, 130, 131, 135, 137, 139, 141, 142, + 143, 144, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162}; + + /* Iterate over all possible codes, checking we have a place holder for all + * unused codes, and that all used codes do not have place holder text. */ + for(int code=0; code<256; code++){ + str = mosquitto_disconnect_string(code); + CU_ASSERT_PTR_NOT_NULL(str); + if(str){ + bool is_used = false; + for(size_t i=0; i