Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions components/esp_websocket_client/esp_websocket_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,37 @@ esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
return stop_wait_task(client);
}

esp_err_t esp_websocket_client_request_stop(esp_websocket_client_handle_t client)
{
if (client == NULL) {
return ESP_ERR_INVALID_ARG;
}

if (xEventGroupGetBits(client->status_bits) & STOPPED_BIT) {
return ESP_OK;
}

/* A running client cannot be stopped from the websocket task/event handler */
if (xTaskGetCurrentTaskHandle() == client->task_handle) {
ESP_LOGE(TAG, "Client cannot be stopped from websocket task");
return ESP_FAIL;
}

client->run = false;
/* REQUESTED_STOP_BIT also wakes a WEBSOCKET_STATE_WAIT_TIMEOUT wait early,
* so a task idling between reconnect attempts exits immediately */
xEventGroupSetBits(client->status_bits, REQUESTED_STOP_BIT);
return ESP_OK;
}

bool esp_websocket_client_wait_stopped(esp_websocket_client_handle_t client, TickType_t timeout)
{
if (client == NULL) {
return false;
}
return (STOPPED_BIT & xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, timeout)) != 0;
}

static int esp_websocket_client_send_close(esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout)
{
uint8_t *close_status_data = NULL;
Expand Down
45 changes: 45 additions & 0 deletions components/esp_websocket_client/include/esp_websocket_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,51 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client);
*/
esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client);

/**
* @brief Request the client task to stop, without waiting for it
*
* This is the non-blocking half of esp_websocket_client_stop(): it flags the
* client task to exit (and wakes it early if it is idling between reconnect
* attempts), then returns immediately. The task still finishes any blocking
* call it is currently inside (transport connect, read poll) before it
* notices the request. Pair with esp_websocket_client_wait_stopped() to
* bound the join, and call esp_websocket_client_destroy() only once the
* client is stopped.
*
* This allows an application tearing down several clients to request all
* stops first so the task exits overlap, then wait for each against a single
* deadline — instead of serializing the full teardown time of every client
* as back-to-back esp_websocket_client_stop() calls would.
*
* Notes:
* - Safe to call when the client is already stopped (returns ESP_OK)
* - Cannot be called from the websocket event handler
*
* @param[in] client The client
*
* @return esp_err_t
*/
esp_err_t esp_websocket_client_request_stop(esp_websocket_client_handle_t client);

/**
* @brief Wait, bounded, for the client task to have stopped
*
* Notes:
* - Passing portMAX_DELAY reproduces the unbounded wait of
* esp_websocket_client_stop()
*
* @param[in] client The client
* @param[in] timeout Maximum number of ticks to wait for the client task
* to reach its stopped state
*
* @return
* - true when the client task is stopped; esp_websocket_client_destroy()
* will then complete without blocking on the task
* - false on timeout: the client task is still winding down — do not
* destroy the client yet (destroy would block unboundedly), retry later
*/
bool esp_websocket_client_wait_stopped(esp_websocket_client_handle_t client, TickType_t timeout);

/**
* @brief Destroy the WebSocket connection and free all resources.
* This function must be the last function to call for an session.
Expand Down