Skip to content

Commit 19891d8

Browse files
feat(websocket): add ability to reconnect after close
Needed to support protocols like Socket.IO, where some websocket closes issued by the server are reconnectable.
1 parent 85a8dac commit 19891d8

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

components/esp_websocket_client/esp_websocket_client.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -80,6 +80,7 @@ typedef struct {
8080
char *auth;
8181
int port;
8282
bool auto_reconnect;
83+
bool close_reconnect;
8384
void *user_context;
8485
int network_timeout_ms;
8586
char *subprotocol;
@@ -376,6 +377,7 @@ static esp_err_t esp_websocket_client_set_config(esp_websocket_client_handle_t c
376377
if (config->disable_auto_reconnect) {
377378
cfg->auto_reconnect = false;
378379
}
380+
cfg->close_reconnect = config->enable_close_reconnect;
379381

380382
if (config->disable_pingpong_discon) {
381383
cfg->pingpong_timeout_sec = 0;
@@ -1127,10 +1129,21 @@ static void esp_websocket_client_task(void *pv)
11271129
} else if (ret < 0) {
11281130
ESP_LOGW(TAG, "Connection terminated while waiting for clean TCP close");
11291131
}
1130-
client->run = false;
1131-
client->state = WEBSOCKET_STATE_UNKNOW;
1132-
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CLOSED, NULL, 0);
1133-
break;
1132+
if (client->config->close_reconnect && xSemaphoreTakeRecursive(client->lock, lock_timeout) == pdPASS) {
1133+
client->state = WEBSOCKET_STATE_WAIT_TIMEOUT;
1134+
client->error_handle.error_type = WEBSOCKET_ERROR_TYPE_SERVER_CLOSE;
1135+
esp_transport_close(client->transport);
1136+
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CLOSED, NULL, 0);
1137+
client->reconnect_tick_ms = _tick_get_ms();
1138+
ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms);
1139+
xEventGroupClearBits(client->status_bits, STOPPED_BIT | CLOSE_FRAME_SENT_BIT);
1140+
xSemaphoreGiveRecursive(client->lock);
1141+
} else {
1142+
client->run = false;
1143+
client->state = WEBSOCKET_STATE_UNKNOW;
1144+
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CLOSED, NULL, 0);
1145+
break;
1146+
}
11341147
}
11351148
}
11361149

components/esp_websocket_client/include/esp_websocket_client.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ typedef enum {
4848
WEBSOCKET_ERROR_TYPE_NONE = 0,
4949
WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT,
5050
WEBSOCKET_ERROR_TYPE_PONG_TIMEOUT,
51-
WEBSOCKET_ERROR_TYPE_HANDSHAKE
51+
WEBSOCKET_ERROR_TYPE_HANDSHAKE,
52+
WEBSOCKET_ERROR_TYPE_SERVER_CLOSE
5253
} esp_websocket_error_type_t;
5354

5455
/**
@@ -101,6 +102,7 @@ typedef struct {
101102
const char *password; /*!< Using for Http authentication */
102103
const char *path; /*!< HTTP Path, if not set, default is `/` */
103104
bool disable_auto_reconnect; /*!< Disable the automatic reconnect function when disconnected */
105+
bool enable_close_reconnect; /*!< Enable reconnect after server close */
104106
void *user_context; /*!< HTTP user data context */
105107
int task_prio; /*!< Websocket task priority */
106108
const char *task_name; /*!< Websocket task name */

0 commit comments

Comments
 (0)