Modify esp-tls and tcp_transport to support keep alive for tcp and ssl connection

Closes IDFGH-4543
This commit is contained in:
yuanjm
2021-01-06 16:58:39 +08:00
committed by bot
parent cf9ac2ef9e
commit 044c3e3e74
8 changed files with 124 additions and 1 deletions

View File

@@ -161,6 +161,34 @@ static void ms_to_timeval(int timeout_ms, struct timeval *tv)
tv->tv_usec = (timeout_ms % 1000) * 1000; tv->tv_usec = (timeout_ms % 1000) * 1000;
} }
static int esp_tls_tcp_enable_keep_alive(int fd, tls_keep_alive_cfg_t *cfg)
{
int keep_alive_enable = 1;
int keep_alive_idle = cfg->keep_alive_idle;
int keep_alive_interval = cfg->keep_alive_interval;
int keep_alive_count = cfg->keep_alive_count;
ESP_LOGD(TAG, "Enable TCP keep alive. idle: %d, interval: %d, count: %d", keep_alive_idle, keep_alive_interval, keep_alive_count);
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive_enable, sizeof(keep_alive_enable)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt SO_KEEPALIVE");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_alive_idle, sizeof(keep_alive_idle)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPIDLE");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keep_alive_interval, sizeof(keep_alive_interval)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPINTVL");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keep_alive_count, sizeof(keep_alive_count)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPCNT");
return -1;
}
return 0;
}
static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, const esp_tls_t *tls, const esp_tls_cfg_t *cfg) static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, const esp_tls_t *tls, const esp_tls_cfg_t *cfg)
{ {
esp_err_t ret; esp_err_t ret;
@@ -199,6 +227,12 @@ static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *s
ms_to_timeval(cfg->timeout_ms, &tv); ms_to_timeval(cfg->timeout_ms, &tv);
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if (cfg->keep_alive_cfg && cfg->keep_alive_cfg->keep_alive_enable) {
if (esp_tls_tcp_enable_keep_alive(fd, cfg->keep_alive_cfg) < 0) {
ESP_LOGE(TAG, "Error setting keep-alive");
goto err_freesocket;
}
}
} }
if (cfg->non_block) { if (cfg->non_block) {
int flags = fcntl(fd, F_GETFL, 0); int flags = fcntl(fd, F_GETFL, 0);

View File

@@ -126,6 +126,16 @@ typedef struct psk_key_hint {
const char* hint; /*!< hint in PSK authentication mode in string format */ const char* hint; /*!< hint in PSK authentication mode in string format */
} psk_hint_key_t; } psk_hint_key_t;
/**
* @brief Keep alive parameters structure
*/
typedef struct tls_keep_alive_cfg {
bool keep_alive_enable; /*!< Enable keep-alive timeout */
int keep_alive_idle; /*!< Keep-alive idle time (second) */
int keep_alive_interval; /*!< Keep-alive interval time (second) */
int keep_alive_count; /*!< Keep-alive packet retry send count */
} tls_keep_alive_cfg_t;
/** /**
* @brief ESP-TLS configuration parameters * @brief ESP-TLS configuration parameters
* *
@@ -213,6 +223,8 @@ typedef struct esp_tls_cfg {
bool skip_common_name; /*!< Skip any validation of server certificate CN field */ bool skip_common_name; /*!< Skip any validation of server certificate CN field */
tls_keep_alive_cfg_t *keep_alive_cfg; /*!< Enable TCP keep-alive timeout for SSL connection */
const psk_hint_key_t* psk_hint_key; /*!< Pointer to PSK hint and key. if not NULL (and certificates are NULL) const psk_hint_key_t* psk_hint_key; /*!< Pointer to PSK hint and key. if not NULL (and certificates are NULL)
then PSK authentication is enabled with configured setup. then PSK authentication is enabled with configured setup.
Important note: the pointer must be valid for connection */ Important note: the pointer must be valid for connection */

View File

@@ -16,11 +16,21 @@
#define _ESP_TRANSPORT_H_ #define _ESP_TRANSPORT_H_
#include <esp_err.h> #include <esp_err.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* @brief Keep alive parameters structure
*/
typedef struct esp_transport_keepalive {
bool keep_alive_enable; /*!< Enable keep-alive timeout */
int keep_alive_idle; /*!< Keep-alive idle time (second) */
int keep_alive_interval; /*!< Keep-alive interval time (second) */
int keep_alive_count; /*!< Keep-alive packet retry send count */
} esp_transport_keep_alive_t;
typedef struct esp_transport_internal* esp_transport_list_handle_t; typedef struct esp_transport_internal* esp_transport_list_handle_t;
typedef struct esp_transport_item_t* esp_transport_handle_t; typedef struct esp_transport_item_t* esp_transport_handle_t;

View File

@@ -165,6 +165,14 @@ void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data);
*/ */
void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key); void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key);
/**
* @brief Set keep-alive status in current ssl context
*
* @param[in] t ssl transport
* @param[in] keep_alive_cfg The handle for keep-alive configuration
*/
void esp_transport_ssl_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -21,6 +21,15 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Set TCP keep-alive configuration
*
* @param[in] t The transport handle
* @param[in] keep_alive_cfg The keep-alive config
*
*/
void esp_transport_tcp_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg);
/** /**
* @brief Create TCP transport, the transport handle must be release esp_transport_destroy callback * @brief Create TCP transport, the transport handle must be release esp_transport_destroy callback
* *

View File

@@ -39,6 +39,7 @@ struct esp_transport_item_t {
get_socket_func _get_socket; /*!< Function returning the transport's socket */ get_socket_func _get_socket; /*!< Function returning the transport's socket */
struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle) struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle)
* extended with transport's specific errors */ * extended with transport's specific errors */
esp_transport_keep_alive_t *keep_alive_cfg; /*!< TCP keep-alive config */
STAILQ_ENTRY(esp_transport_item_t) next; STAILQ_ENTRY(esp_transport_item_t) next;
}; };

View File

@@ -313,6 +313,14 @@ void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data)
} }
} }
void esp_transport_ssl_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg)
{
transport_ssl_t *ssl = esp_transport_get_context_data(t);
if (t && ssl) {
ssl->cfg.keep_alive_cfg = (tls_keep_alive_cfg_t *)keep_alive_cfg;
}
}
esp_transport_handle_t esp_transport_ssl_init(void) esp_transport_handle_t esp_transport_ssl_init(void)
{ {
esp_transport_handle_t t = esp_transport_init(); esp_transport_handle_t t = esp_transport_init();

View File

@@ -52,6 +52,34 @@ static int resolve_dns(const char *host, struct sockaddr_in *ip)
return ESP_OK; return ESP_OK;
} }
static int tcp_enable_keep_alive(int fd, esp_transport_keep_alive_t *keep_alive_cfg)
{
int keep_alive_enable = 1;
int keep_alive_idle = keep_alive_cfg->keep_alive_idle;
int keep_alive_interval = keep_alive_cfg->keep_alive_interval;
int keep_alive_count = keep_alive_cfg->keep_alive_count;
ESP_LOGD(TAG, "Enable TCP keep alive. idle: %d, interval: %d, count: %d", keep_alive_idle, keep_alive_interval, keep_alive_count);
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive_enable, sizeof(keep_alive_enable)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt SO_KEEPALIVE");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_alive_idle, sizeof(keep_alive_idle)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPIDLE");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keep_alive_interval, sizeof(keep_alive_interval)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPINTVL");
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keep_alive_count, sizeof(keep_alive_count)) != 0) {
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPCNT");
return -1;
}
return 0;
}
static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms) static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
{ {
struct sockaddr_in remote_ip; struct sockaddr_in remote_ip;
@@ -81,7 +109,13 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int
setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(tcp->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); setsockopt(tcp->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
// Set socket keep-alive option
if (t->keep_alive_cfg && t->keep_alive_cfg->keep_alive_enable) {
if (tcp_enable_keep_alive(tcp->sock, t->keep_alive_cfg) < 0) {
ESP_LOGE(TAG, "Error to set tcp [socket=%d] keep-alive", tcp->sock);
goto error;
}
}
// Set socket to non-blocking // Set socket to non-blocking
int flags; int flags;
if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) { if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) {
@@ -251,6 +285,13 @@ static int tcp_get_socket(esp_transport_handle_t t)
return -1; return -1;
} }
void esp_transport_tcp_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg)
{
if (t && keep_alive_cfg) {
t->keep_alive_cfg = keep_alive_cfg;
}
}
esp_transport_handle_t esp_transport_tcp_init(void) esp_transport_handle_t esp_transport_tcp_init(void)
{ {
esp_transport_handle_t t = esp_transport_init(); esp_transport_handle_t t = esp_transport_init();