Extended error structure to be used in mqtt library and include mqtt

specific errors.
Corrected typos in comments and log messages
This commit is contained in:
David Cermak
2019-09-30 14:19:43 +02:00
parent 67042a1315
commit e3b013e2db
2 changed files with 68 additions and 21 deletions

View File

@ -37,7 +37,7 @@ typedef struct esp_mqtt_client *esp_mqtt_client_handle_t;
*
*/
typedef enum {
MQTT_EVENT_ERROR = 0, /*!< on error event, additional context: error handle from esp_tls (if supported) */
MQTT_EVENT_ERROR = 0, /*!< on error event, additional context: connection return code, error handle from esp_tls (if supported) */
MQTT_EVENT_CONNECTED, /*!< connected event, additional context: session_present flag */
MQTT_EVENT_DISCONNECTED, /*!< disconnected event */
MQTT_EVENT_SUBSCRIBED, /*!< subscribed event, additional context: msg_id */
@ -57,7 +57,6 @@ typedef enum {
and current data offset updating.
*/
MQTT_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */
MQTT_EVENT_CONNECTION_REFUSED, /*!< The event occurs if connection is refused by the broker, additional context: connect_return_code */
} esp_mqtt_event_id_t;
/**
@ -72,6 +71,15 @@ typedef enum {
MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED /*!< MQTT connection refused reason: Wrong username or password */
} esp_mqtt_connect_return_code_t;
/**
* MQTT connection error codes propagated via ERROR event
*/
typedef enum {
MQTT_ERROR_TYPE_NONE = 0,
MQTT_ERROR_TYPE_ESP_TLS,
MQTT_ERROR_TYPE_CONNECTION_REFUSED,
} esp_mqtt_error_type_t;
typedef enum {
MQTT_TRANSPORT_UNKNOWN = 0x0,
MQTT_TRANSPORT_OVER_TCP, /*!< MQTT over TCP, using scheme: ``mqtt`` */
@ -80,6 +88,28 @@ typedef enum {
MQTT_TRANSPORT_OVER_WSS /*!< MQTT over Websocket Secure, using scheme: ``wss`` */
} esp_mqtt_transport_t;
/**
* @brief MQTT error code structure to be passed as a contextual information into ERROR event
*
* Important: This structure extends `esp_tls_last_error` error structure and is backward compatible with it
* (so might be down-casted and treated as `esp_tls_last_error` error, but recommended to update applications if used this way previously)
*
* Use this structure directly checking error_type first and then appropriate error code depending on the source of the error:
*
* | error_type | related member variables | note |
* | MQTT_ERROR_TYPE_ESP_TLS | esp_tls_last_esp_err, esp_tls_stack_err, esp_tls_cert_verify_flags | Error reported from esp-tls |
* | MQTT_ERROR_TYPE_CONNECTION_REFUSED | connect_return_code | Internal error reported from MQTT broker on connection |
*/
typedef struct esp_mqtt_error_codes {
/* compatible portion of the struct corresponding to struct esp_tls_last_error */
esp_err_t esp_tls_last_esp_err; /*!< last esp_err code reported from esp-tls component */
int esp_tls_stack_err; /*!< tls specific error code reported from underlying tls stack */
int esp_tls_cert_verify_flags; /*!< tls flags reported from underlying tls stack during certificate verification */
/* esp-mqtt specific structure extension */
esp_mqtt_error_type_t error_type; /*!< error type referring to the source of the error */
esp_mqtt_connect_return_code_t connect_return_code; /*!< connection refused error code reported from MQTT broker on connection */
} esp_mqtt_error_codes_t;
/**
* MQTT event configuration structure
*/
@ -87,16 +117,15 @@ typedef struct {
esp_mqtt_event_id_t event_id; /*!< MQTT event type */
esp_mqtt_client_handle_t client; /*!< MQTT client handle for this event */
void *user_context; /*!< User context passed from MQTT client config */
char *data; /*!< Data asociated with this event */
int data_len; /*!< Lenght of the data for this event */
char *data; /*!< Data associated with this event */
int data_len; /*!< Length of the data for this event */
int total_data_len; /*!< Total length of the data (longer data are supplied with multiple events) */
int current_data_offset; /*!< Actual offset for the data asociated with this event */
char *topic; /*!< Topic asociated with this event */
int topic_len; /*!< Length of the topic for this event asociated with this event */
int current_data_offset; /*!< Actual offset for the data associated with this event */
char *topic; /*!< Topic associated with this event */
int topic_len; /*!< Length of the topic for this event associated with this event */
int msg_id; /*!< MQTT messaged id of message */
int session_present; /*!< MQTT session_present flag for connection event */
void* error_handle; /*!< esp-tls error handle referencing last error/flags captured in transports */
esp_mqtt_connect_return_code_t connect_return_code; /*!< MQTT connection return code. Only written on a connection */
esp_mqtt_error_codes_t *error_handle; /*!< esp-mqtt error handle including esp-tls errors as well as internal mqtt errors */
} esp_mqtt_event_t;
typedef esp_mqtt_event_t *esp_mqtt_event_handle_t;
@ -152,7 +181,7 @@ esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *co
* @brief Sets mqtt connection URI. This API is usually used to overrides the URI
* configured in esp_mqtt_client_init
*
* @param client mqtt client hanlde
* @param client mqtt client handle
* @param uri
*
* @return ESP_FAIL if URI parse error, ESP_OK on success
@ -237,7 +266,7 @@ int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *top
* @param data payload string (set to NULL, sending empty payload message)
* @param len data length, if set to 0, length is calculated from payload string
* @param qos qos of publish message
* @param retain ratain flag
* @param retain retain flag
*
* @return message_id of the publish message (for QoS 0 message_id will always be zero) on success.
* -1 on failure.
@ -270,7 +299,7 @@ esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_cl
*
* @param client mqtt client handle
* @param event event type
* @param event_handler hanlder callback
* @param event_handler handler callback
* @param event_handler_arg handlers context
*
* @return ESP_ERR_NO_MEM if failed to allocate

View File

@ -339,8 +339,12 @@ static esp_err_t esp_mqtt_connect(esp_mqtt_client_handle_t client, int timeout_m
break;
}
/* propagate event with connection refused error */
client->event.event_id = MQTT_EVENT_CONNECTION_REFUSED;
client->event.connect_return_code = connect_rsp_code;
client->event.event_id = MQTT_EVENT_ERROR;
client->event.error_handle->error_type = MQTT_ERROR_TYPE_CONNECTION_REFUSED;
client->event.error_handle->connect_return_code = connect_rsp_code;
client->event.error_handle->esp_tls_stack_err = 0;
client->event.error_handle->esp_tls_last_esp_err = 0;
client->event.error_handle->esp_tls_cert_verify_flags = 0;
esp_mqtt_dispatch_event_with_msgid(client);
return ESP_FAIL;
@ -363,6 +367,11 @@ esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *co
{
esp_mqtt_client_handle_t client = calloc(1, sizeof(struct esp_mqtt_client));
ESP_MEM_CHECK(TAG, client, return NULL);
client->event.error_handle = calloc(1, sizeof(esp_mqtt_error_codes_t));
if (!client->event.error_handle) {
free(client);
return NULL;
}
client->api_lock = xSemaphoreCreateMutex();
if (!client->api_lock) {
free(client);
@ -502,6 +511,7 @@ esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client)
free(client->mqtt_state.in_buffer);
free(client->mqtt_state.out_buffer);
vSemaphoreDelete(client->api_lock);
free(client->event.error_handle);
free(client);
return ESP_OK;
}
@ -580,8 +590,12 @@ static esp_err_t mqtt_write_data(esp_mqtt_client_handle_t client)
// client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data);
if (write_len <= 0) {
client->event.event_id = MQTT_EVENT_ERROR;
client->event.error_handle->error_type = MQTT_ERROR_TYPE_ESP_TLS;
client->event.error_handle->connect_return_code = 0;
#ifdef MQTT_SUPPORTED_FEATURE_TRANSPORT_ERR_REPORTING
client->event.error_handle = esp_transport_get_error_handle(client->transport);
client->event.error_handle->esp_tls_last_esp_err = esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport),
&client->event.error_handle->esp_tls_stack_err,
&client->event.error_handle->esp_tls_cert_verify_flags);
#endif
esp_mqtt_dispatch_event_with_msgid(client);
ESP_LOGE(TAG, "Error write data or timeout, written len = %d, errno=%d", write_len, errno);
@ -976,7 +990,7 @@ static esp_err_t mqtt_resend_queued(esp_mqtt_client_handle_t client, outbox_item
// try to resend the data
if (mqtt_write_data(client) != ESP_OK) {
ESP_LOGE(TAG, "Error to public data ");
ESP_LOGE(TAG, "Error to resend data ");
esp_mqtt_abort_connection(client);
return ESP_FAIL;
}
@ -1013,7 +1027,7 @@ static void esp_mqtt_task(void *pv)
esp_mqtt_dispatch_event_with_msgid(client);
if (client->transport == NULL) {
ESP_LOGE(TAG, "There are no transport");
ESP_LOGE(TAG, "There is no transport");
client->run = false;
}
@ -1023,8 +1037,12 @@ static void esp_mqtt_task(void *pv)
client->config->network_timeout_ms) < 0) {
ESP_LOGE(TAG, "Error transport connect");
client->event.event_id = MQTT_EVENT_ERROR;
client->event.error_handle->error_type = MQTT_ERROR_TYPE_ESP_TLS;
client->event.error_handle->connect_return_code = 0;
#ifdef MQTT_SUPPORTED_FEATURE_TRANSPORT_ERR_REPORTING
client->event.error_handle = esp_transport_get_error_handle(client->transport);
client->event.error_handle->esp_tls_last_esp_err = esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport),
&client->event.error_handle->esp_tls_stack_err,
&client->event.error_handle->esp_tls_cert_verify_flags);
#endif
esp_mqtt_dispatch_event_with_msgid(client);
esp_mqtt_abort_connection(client);
@ -1090,7 +1108,7 @@ static void esp_mqtt_task(void *pv)
client->state = MQTT_STATE_INIT;
}
//Delete mesaage after 30 senconds
//Delete message after 30 seconds
int deleted = outbox_delete_expired(client->outbox, platform_tick_get_ms(), OUTBOX_EXPIRED_TIMEOUT_MS);
client->mqtt_state.pending_msg_count -= deleted;
if (client->mqtt_state.pending_msg_count < 0) {
@ -1115,7 +1133,7 @@ static void esp_mqtt_task(void *pv)
MQTT_API_UNLOCK(client);
xEventGroupWaitBits(client->status_bits, RECONNECT_BIT, false, true,
client->wait_timeout_ms / 2 / portTICK_RATE_MS);
// continue the while loop insted of break, as the mutex is unlocked
// continue the while loop instead of break, as the mutex is unlocked
continue;
}
MQTT_API_UNLOCK(client);
@ -1371,7 +1389,7 @@ int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic,
cannot_publish:
if (qos == 0) {
ESP_LOGW(TAG, "Publish: Loosing qos0 data when client not connected");
ESP_LOGW(TAG, "Publish: Losing qos0 data when client not connected");
}
MQTT_API_UNLOCK_FROM_OTHER_TASK(client);
return 0;