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

This commit is contained in:
yuanjm 2021-01-06 16:58:39 +08:00 committed by bot
parent a395f3592b
commit f946e296a2
8 changed files with 153 additions and 5 deletions

View File

@ -148,6 +148,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;
@ -186,6 +214,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

@ -101,6 +101,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
* *
@ -188,7 +198,7 @@ typedef struct esp_tls_cfg {
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 */
tls_keep_alive_cfg_t *keep_alive_cfg; /*!< Enable TCP keep-alive timeout for SSL connection */
} esp_tls_cfg_t; } esp_tls_cfg_t;
#ifdef CONFIG_ESP_TLS_SERVER #ifdef CONFIG_ESP_TLS_SERVER

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;
@ -313,8 +323,22 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl
*/ */
esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t); esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t);
/**
* @brief Set keep-alive configuration
*
* @param[in] t The transport handle
* @param[in] keep_alive_cfg The keep-alive config
*/
void esp_transport_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg);
/**
* @brief Get keep-alive config of this transport
*
* @param[in] t The transport handle
*
* @return The keep-alive configuration
*/
void *esp_transport_get_keep_alive(esp_transport_handle_t t);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -146,6 +146,13 @@ void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t);
*/ */
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,14 @@
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

@ -44,7 +44,7 @@ struct esp_transport_item_t {
connect_async_func _connect_async; /*!< non-blocking connect function of this transport */ connect_async_func _connect_async; /*!< non-blocking connect function of this transport */
payload_transfer_func _parent_transfer; /*!< Function returning underlying transport layer */ payload_transfer_func _parent_transfer; /*!< Function returning underlying transport layer */
esp_tls_error_handle_t error_handle; /*!< Pointer to esp-tls error handle */ esp_tls_error_handle_t error_handle; /*!< Pointer to esp-tls error handle */
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;
}; };
@ -305,4 +305,19 @@ void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_hand
if (t) { if (t) {
memcpy(t->error_handle, error_handle, sizeof(esp_tls_last_error_t)); memcpy(t->error_handle, error_handle, sizeof(esp_tls_last_error_t));
} }
} }
void esp_transport_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;
}
}
void *esp_transport_get_keep_alive(esp_transport_handle_t t)
{
if (t) {
return t->keep_alive_cfg;
}
return NULL;
}

View File

@ -282,6 +282,14 @@ void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
} }
} }
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

@ -51,11 +51,40 @@ 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;
struct timeval tv = { 0 }; struct timeval tv = { 0 };
transport_tcp_t *tcp = esp_transport_get_context_data(t); transport_tcp_t *tcp = esp_transport_get_context_data(t);
esp_transport_keep_alive_t *keep_alive_cfg = esp_transport_get_keep_alive(t);
bzero(&remote_ip, sizeof(struct sockaddr_in)); bzero(&remote_ip, sizeof(struct sockaddr_in));
@ -80,7 +109,15 @@ 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 (keep_alive_cfg && keep_alive_cfg->keep_alive_enable) {
if (tcp_enable_keep_alive(tcp->sock, keep_alive_cfg) < 0) {
ESP_LOGE(TAG, "Error to set tcp [socket=%d] keep-alive", tcp->sock);
close(tcp->sock);
tcp->sock = -1;
return -1;
}
}
ESP_LOGD(TAG, "[sock=%d],connecting to server IP:%s,Port:%d...", ESP_LOGD(TAG, "[sock=%d],connecting to server IP:%s,Port:%d...",
tcp->sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port); tcp->sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port);
if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) { if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) {
@ -180,6 +217,11 @@ static esp_err_t tcp_destroy(esp_transport_handle_t t)
return 0; return 0;
} }
void esp_transport_tcp_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg)
{
esp_transport_set_keep_alive(t, 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();