From b53e46a68e8671c73e8aafe2602de5ff5a77e3db Mon Sep 17 00:00:00 2001 From: Shubham Kulkarni Date: Mon, 11 Jan 2021 16:24:48 +0530 Subject: [PATCH] Add options for esp_http_client and esp_websocket_client to support keepalive --- components/esp_http_client/esp_http_client.c | 19 +++++++++++++++++-- .../esp_http_client/include/esp_http_client.h | 4 ++++ .../esp_websocket_client.c | 13 +++++++++++++ .../include/esp_websocket_client.h | 4 ++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index e698fc991f..e1c5edc39f 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -121,6 +121,7 @@ struct esp_http_client { bool first_line_prepared; int header_index; bool is_async; + esp_transport_keep_alive_t keep_alive_cfg; }; typedef struct esp_http_client esp_http_client_t; @@ -142,6 +143,9 @@ static const char *DEFAULT_HTTP_PATH = "/"; static const int DEFAULT_MAX_REDIRECT = 10; static const int DEFAULT_MAX_AUTH_RETRIES = 10; static const int DEFAULT_TIMEOUT_MS = 5000; +static const int DEFAULT_KEEP_ALIVE_IDLE = 5; +static const int DEFAULT_KEEP_ALIVE_INTERVAL= 5; +static const int DEFAULT_KEEP_ALIVE_COUNT= 3; static const char *HTTP_METHOD_MAPPING[] = { "GET", @@ -532,7 +536,7 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co { esp_http_client_handle_t client; - esp_transport_handle_t tcp; + esp_transport_handle_t tcp = NULL; char *host_name; bool _success; @@ -564,8 +568,15 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co ESP_LOGE(TAG, "Error initialize transport"); goto error; } + if (config->keep_alive_enable == true) { + client->keep_alive_cfg.keep_alive_enable = true; + client->keep_alive_cfg.keep_alive_idle = (config->keep_alive_idle == 0) ? DEFAULT_KEEP_ALIVE_IDLE : config->keep_alive_idle; + client->keep_alive_cfg.keep_alive_interval = (config->keep_alive_interval == 0) ? DEFAULT_KEEP_ALIVE_INTERVAL : config->keep_alive_interval; + client->keep_alive_cfg.keep_alive_count = (config->keep_alive_count == 0) ? DEFAULT_KEEP_ALIVE_COUNT : config->keep_alive_count; + esp_transport_tcp_set_keep_alive(tcp, &client->keep_alive_cfg); + } #ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS - esp_transport_handle_t ssl; + esp_transport_handle_t ssl = NULL; _success = ( (ssl = esp_transport_ssl_init()) && (esp_transport_set_default_port(ssl, DEFAULT_HTTPS_PORT) == ESP_OK) && @@ -594,6 +605,10 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co if (config->skip_cert_common_name_check) { esp_transport_ssl_skip_common_name_check(ssl); } + + if (config->keep_alive_enable == true) { + esp_transport_ssl_set_keep_alive(ssl, &client->keep_alive_cfg); + } #endif if (_set_config(client, config) != ESP_OK) { diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 017ee5d5ac..4884a74e0f 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -131,6 +131,10 @@ typedef struct { bool is_async; /*!< Set asynchronous mode, only supported with HTTPS for now */ bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */ bool skip_cert_common_name_check; /*!< Skip any validation of server certificate CN field */ + bool keep_alive_enable; /*!< Enable keep-alive timeout */ + int keep_alive_idle; /*!< Keep-alive idle time. Default is 5 (second) */ + int keep_alive_interval; /*!< Keep-alive interval time. Default is 5 (second) */ + int keep_alive_count; /*!< Keep-alive packet retry send count. Default is 3 counts */ } esp_http_client_config_t; /** diff --git a/components/esp_websocket_client/esp_websocket_client.c b/components/esp_websocket_client/esp_websocket_client.c index e396c3fb0f..1e4aa2a148 100644 --- a/components/esp_websocket_client/esp_websocket_client.c +++ b/components/esp_websocket_client/esp_websocket_client.c @@ -40,6 +40,9 @@ static const char *TAG = "WEBSOCKET_CLIENT"; #define WEBSOCKET_PING_TIMEOUT_MS (10*1000) #define WEBSOCKET_EVENT_QUEUE_SIZE (1) #define WEBSOCKET_PINGPONG_TIMEOUT_SEC (120) +#define WEBSOCKET_KEEP_ALIVE_IDLE (5) +#define WEBSOCKET_KEEP_ALIVE_INTERVAL (5) +#define WEBSOCKET_KEEP_ALIVE_COUNT (3) #define ESP_WS_CLIENT_MEM_CHECK(TAG, a, action) if (!(a)) { \ ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, "Memory exhausted"); \ @@ -108,6 +111,7 @@ struct esp_websocket_client { ws_transport_opcodes_t last_opcode; int payload_len; int payload_offset; + esp_transport_keep_alive_t keep_alive_cfg; }; static uint64_t _tick_get_ms(void) @@ -290,6 +294,13 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie return NULL; } + if (config->keep_alive_enable == true) { + client->keep_alive_cfg.keep_alive_enable = true; + client->keep_alive_cfg.keep_alive_idle = (config->keep_alive_idle == 0) ? WEBSOCKET_KEEP_ALIVE_IDLE : config->keep_alive_idle; + client->keep_alive_cfg.keep_alive_interval = (config->keep_alive_interval == 0) ? WEBSOCKET_KEEP_ALIVE_INTERVAL : config->keep_alive_interval; + client->keep_alive_cfg.keep_alive_count = (config->keep_alive_count == 0) ? WEBSOCKET_KEEP_ALIVE_COUNT : config->keep_alive_count; + } + client->lock = xSemaphoreCreateRecursiveMutex(); ESP_WS_CLIENT_MEM_CHECK(TAG, client->lock, goto _websocket_init_fail); @@ -303,6 +314,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie ESP_WS_CLIENT_MEM_CHECK(TAG, tcp, goto _websocket_init_fail); esp_transport_set_default_port(tcp, WEBSOCKET_TCP_DEFAULT_PORT); + esp_transport_tcp_set_keep_alive(tcp, &client->keep_alive_cfg); esp_transport_list_add(client->transport_list, tcp, "_tcp"); // need to save to transport list, for cleanup @@ -346,6 +358,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie if (config->skip_cert_common_name_check) { esp_transport_ssl_skip_common_name_check(ssl); } + esp_transport_ssl_set_keep_alive(ssl, &client->keep_alive_cfg); esp_transport_list_add(client->transport_list, ssl, "_ssl"); // need to save to transport list, for cleanup esp_transport_handle_t wss = esp_transport_ws_init(ssl); diff --git a/components/esp_websocket_client/include/esp_websocket_client.h b/components/esp_websocket_client/include/esp_websocket_client.h index 62a0d53f09..c50184565a 100644 --- a/components/esp_websocket_client/include/esp_websocket_client.h +++ b/components/esp_websocket_client/include/esp_websocket_client.h @@ -95,6 +95,10 @@ typedef struct { bool disable_pingpong_discon; /*!< Disable auto-disconnect due to no PONG received within pingpong_timeout_sec */ bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */ bool skip_cert_common_name_check;/*!< Skip any validation of server certificate CN field */ + bool keep_alive_enable; /*!< Enable keep-alive timeout */ + int keep_alive_idle; /*!< Keep-alive idle time. Default is 5 (second) */ + int keep_alive_interval; /*!< Keep-alive interval time. Default is 5 (second) */ + int keep_alive_count; /*!< Keep-alive packet retry send count. Default is 3 counts */ } esp_websocket_client_config_t; /**