mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/transport_tcp_connection_errors' into 'master'
tcp_transport/esp_tls: Use common TCP transport to reduce code duplication Closes IDFGH-4405 See merge request espressif/esp-idf!12136
This commit is contained in:
commit
e615d10b4f
@ -24,3 +24,8 @@ if(CONFIG_ESP_TLS_USE_SE)
|
||||
idf_component_get_property(cryptoauthlib esp-cryptoauthlib COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${cryptoauthlib})
|
||||
endif()
|
||||
|
||||
# Increase link multiplicity to get some lwip symbols correctly resolved by the linker
|
||||
# due to cyclic dependencies present in IDF for lwip/esp_netif/mbedtls
|
||||
idf_component_get_property(lwip lwip COMPONENT_LIB)
|
||||
set_property(TARGET ${lwip} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 5)
|
||||
|
@ -45,6 +45,7 @@ static const char *TAG = "esp-tls";
|
||||
#define _esp_tls_read esp_mbedtls_read
|
||||
#define _esp_tls_write esp_mbedtls_write
|
||||
#define _esp_tls_conn_delete esp_mbedtls_conn_delete
|
||||
#define _esp_tls_net_init esp_mbedtls_net_init
|
||||
#ifdef CONFIG_ESP_TLS_SERVER
|
||||
#define _esp_tls_server_session_create esp_mbedtls_server_session_create
|
||||
#define _esp_tls_server_session_delete esp_mbedtls_server_session_delete
|
||||
@ -60,6 +61,7 @@ static const char *TAG = "esp-tls";
|
||||
#define _esp_tls_read esp_wolfssl_read
|
||||
#define _esp_tls_write esp_wolfssl_write
|
||||
#define _esp_tls_conn_delete esp_wolfssl_conn_delete
|
||||
#define _esp_tls_net_init esp_wolfssl_net_init
|
||||
#ifdef CONFIG_ESP_TLS_SERVER
|
||||
#define _esp_tls_server_session_create esp_wolfssl_server_session_create
|
||||
#define _esp_tls_server_session_delete esp_wolfssl_server_session_delete
|
||||
@ -126,15 +128,14 @@ esp_tls_t *esp_tls_init(void)
|
||||
free(tls);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
tls->server_fd.fd = -1;
|
||||
#endif
|
||||
_esp_tls_net_init(tls);
|
||||
tls->sockfd = -1;
|
||||
return tls;
|
||||
}
|
||||
|
||||
static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addrinfo **address_info)
|
||||
static esp_err_t esp_tls_hostname_to_fd(const char *host, size_t hostlen, int port, struct sockaddr_storage *address, int* fd)
|
||||
{
|
||||
struct addrinfo *address_info;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
@ -146,12 +147,40 @@ static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addr
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "host:%s: strlen %lu", use_host, (unsigned long)hostlen);
|
||||
if (getaddrinfo(use_host, NULL, &hints, address_info)) {
|
||||
ESP_LOGE(TAG, "couldn't get hostname for :%s:", use_host);
|
||||
int res = getaddrinfo(use_host, NULL, &hints, &address_info);
|
||||
if (res != 0 || address_info == NULL) {
|
||||
ESP_LOGE(TAG, "couldn't get hostname for :%s: "
|
||||
"getaddrinfo() returns %d, addrinfo=%p", use_host, res, address_info);
|
||||
free(use_host);
|
||||
return ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME;
|
||||
}
|
||||
free(use_host);
|
||||
*fd = socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
|
||||
if (*fd < 0) {
|
||||
ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
|
||||
freeaddrinfo(address_info);
|
||||
return ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET;
|
||||
}
|
||||
|
||||
if (address_info->ai_family == AF_INET) {
|
||||
struct sockaddr_in *p = (struct sockaddr_in *)address_info->ai_addr;
|
||||
p->sin_port = htons(port);
|
||||
ESP_LOGD(TAG, "[sock=%d] Resolved IPv4 address: %s", *fd, ipaddr_ntoa((const ip_addr_t*)&p->sin_addr.s_addr));
|
||||
memcpy(address, p, sizeof(struct sockaddr ));
|
||||
} else if (address_info->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *p = (struct sockaddr_in6 *)address_info->ai_addr;
|
||||
p->sin6_port = htons(port);
|
||||
p->sin6_family = AF_INET6;
|
||||
ESP_LOGD(TAG, "[sock=%d] Resolved IPv6 address: %s", *fd, ip6addr_ntoa((const ip6_addr_t*)&p->sin6_addr));
|
||||
memcpy(address, p, sizeof(struct sockaddr_in6 ));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported protocol family %d", address_info->ai_family);
|
||||
close(*fd);
|
||||
freeaddrinfo(address_info);
|
||||
return ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY;
|
||||
}
|
||||
|
||||
freeaddrinfo(address_info);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -161,106 +190,153 @@ static void ms_to_timeval(int timeout_ms, struct timeval *tv)
|
||||
tv->tv_usec = (timeout_ms % 1000) * 1000;
|
||||
}
|
||||
|
||||
static int esp_tls_tcp_enable_keep_alive(int fd, tls_keep_alive_cfg_t *cfg)
|
||||
static esp_err_t esp_tls_set_socket_options(int fd, const esp_tls_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;
|
||||
if (cfg && cfg->timeout_ms >= 0) {
|
||||
struct timeval tv;
|
||||
ms_to_timeval(cfg->timeout_ms, &tv);
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt SO_RCVTIMEO");
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt SO_SNDTIMEO");
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
if (cfg->keep_alive_cfg && cfg->keep_alive_cfg->keep_alive_enable) {
|
||||
int keep_alive_enable = 1;
|
||||
int keep_alive_idle = cfg->keep_alive_cfg->keep_alive_idle;
|
||||
int keep_alive_interval = cfg->keep_alive_cfg->keep_alive_interval;
|
||||
int keep_alive_count = cfg->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;
|
||||
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 ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_alive_enable, sizeof(keep_alive_enable)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPIDLE");
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keep_alive_interval, sizeof(keep_alive_interval)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPINTVL");
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keep_alive_count, sizeof(keep_alive_count)) != 0) {
|
||||
ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPCNT");
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_tls_set_socket_non_blocking(int fd, bool non_blocking)
|
||||
{
|
||||
int flags;
|
||||
if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] get file flags error: %s", fd, strerror(errno));
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (non_blocking) {
|
||||
flags |= O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ~O_NONBLOCK;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] set blocking/nonblocking error: %s", fd, strerror(errno));
|
||||
return ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
struct addrinfo *addrinfo;
|
||||
if ((ret = resolve_host_name(host, hostlen, &addrinfo)) != ESP_OK) {
|
||||
struct sockaddr_storage address;
|
||||
int fd;
|
||||
esp_err_t ret = esp_tls_hostname_to_fd(host, hostlen, port, &address, &fd);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
|
||||
if (fd < 0) {
|
||||
ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
|
||||
ret = ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET;
|
||||
goto err_freeaddr;
|
||||
// Set timeout options and keep-alive options if configured
|
||||
ret = esp_tls_set_socket_options(fd, cfg);
|
||||
if (ret != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
void *addr_ptr;
|
||||
if (addrinfo->ai_family == AF_INET) {
|
||||
struct sockaddr_in *p = (struct sockaddr_in *)addrinfo->ai_addr;
|
||||
p->sin_port = htons(port);
|
||||
addr_ptr = p;
|
||||
} else if (addrinfo->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *p = (struct sockaddr_in6 *)addrinfo->ai_addr;
|
||||
p->sin6_port = htons(port);
|
||||
p->sin6_family = AF_INET6;
|
||||
addr_ptr = p;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported protocol family %d", addrinfo->ai_family);
|
||||
ret = ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY;
|
||||
goto err_freesocket;
|
||||
// Set to non block before connecting to better control connection timeout
|
||||
ret = esp_tls_set_socket_non_blocking(fd, true);
|
||||
if (ret != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cfg) {
|
||||
if (cfg->timeout_ms >= 0) {
|
||||
struct timeval tv;
|
||||
ms_to_timeval(cfg->timeout_ms, &tv);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &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;
|
||||
ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
|
||||
ESP_LOGD(TAG, "[sock=%d] Connecting to server. HOST: %s, Port: %d", fd, host, port);
|
||||
if (connect(fd, (struct sockaddr *)&address, sizeof(struct sockaddr)) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
fd_set fdset;
|
||||
struct timeval tv = { .tv_usec = 0, .tv_sec = 10 }; // Default connection timeout is 10 s
|
||||
|
||||
if (cfg && cfg->non_block) {
|
||||
// Non-blocking mode -> just return successfully at this stage
|
||||
*sockfd = fd;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if ( cfg && cfg->timeout_ms > 0 ) {
|
||||
ms_to_timeval(cfg->timeout_ms, &tv);
|
||||
}
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
|
||||
int res = select(fd+1, NULL, &fdset, NULL, &tv);
|
||||
if (res < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] select() error: %s", fd, strerror(errno));
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
|
||||
goto err;
|
||||
}
|
||||
else if (res == 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] select() timeout", fd);
|
||||
ret = ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT;
|
||||
goto err;
|
||||
} else {
|
||||
int sockerr;
|
||||
socklen_t len = (socklen_t)sizeof(int);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)(&sockerr), &len) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] getsockopt() error: %s", fd, strerror(errno));
|
||||
ret = ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
goto err;
|
||||
}
|
||||
else if (sockerr) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, sockerr);
|
||||
ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", fd, strerror(sockerr));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->non_block) {
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "Failed to configure the socket as non-blocking (errno %d)", errno);
|
||||
goto err_freesocket;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "[sock=%d] connect() error: %s", fd, strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = connect(fd, addr_ptr, addrinfo->ai_addrlen);
|
||||
if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) {
|
||||
|
||||
ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
|
||||
ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
|
||||
goto err_freesocket;
|
||||
if (cfg && cfg->non_block == false) {
|
||||
// reset back to blocking mode (unless non_block configured)
|
||||
ret = esp_tls_set_socket_non_blocking(fd, false);
|
||||
if (ret != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
*sockfd = fd;
|
||||
freeaddrinfo(addrinfo);
|
||||
return ESP_OK;
|
||||
|
||||
err_freesocket:
|
||||
err:
|
||||
close(fd);
|
||||
err_freeaddr:
|
||||
freeaddrinfo(addrinfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -276,23 +352,21 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
|
||||
switch (tls->conn_state) {
|
||||
case ESP_TLS_INIT:
|
||||
tls->sockfd = -1;
|
||||
if (cfg != NULL) {
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
mbedtls_net_init(&tls->server_fd);
|
||||
#endif
|
||||
if (cfg != NULL && cfg->is_plain_tcp == false) {
|
||||
_esp_tls_net_init(tls);
|
||||
tls->is_tls = true;
|
||||
}
|
||||
if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
|
||||
return -1;
|
||||
}
|
||||
if (!cfg) {
|
||||
if (tls->is_tls == false) {
|
||||
tls->read = tcp_read;
|
||||
tls->write = tcp_write;
|
||||
ESP_LOGD(TAG, "non-tls connection established");
|
||||
return 1;
|
||||
}
|
||||
if (cfg->non_block) {
|
||||
if (cfg && cfg->non_block) {
|
||||
FD_ZERO(&tls->rset);
|
||||
FD_SET(tls->sockfd, &tls->rset);
|
||||
tls->wset = tls->rset;
|
||||
@ -300,7 +374,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
|
||||
tls->conn_state = ESP_TLS_CONNECTING;
|
||||
/* falls through */
|
||||
case ESP_TLS_CONNECTING:
|
||||
if (cfg->non_block) {
|
||||
if (cfg && cfg->non_block) {
|
||||
ESP_LOGD(TAG, "connecting...");
|
||||
struct timeval tv;
|
||||
ms_to_timeval(cfg->timeout_ms, &tv);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_tls_errors.h"
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
@ -36,71 +37,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */
|
||||
#define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */
|
||||
#define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */
|
||||
#define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */
|
||||
#define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */
|
||||
#define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set socket option */
|
||||
#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */
|
||||
#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */
|
||||
#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */
|
||||
|
||||
#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ
|
||||
#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT
|
||||
#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */
|
||||
#define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ
|
||||
#define ESP_TLS_ERR_SSL_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE
|
||||
#define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT
|
||||
#endif /*CONFIG_ESP_TLS_USING_WOLFSSL */
|
||||
|
||||
/**
|
||||
* Definition of different types/sources of error codes reported
|
||||
* from different components
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_TLS_ERR_TYPE_UNKNOWN = 0,
|
||||
ESP_TLS_ERR_TYPE_SYSTEM, /*!< System error -- errno */
|
||||
ESP_TLS_ERR_TYPE_MBEDTLS, /*!< Error code from mbedTLS library */
|
||||
ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, /*!< Certificate flags defined in mbedTLS */
|
||||
ESP_TLS_ERR_TYPE_ESP, /*!< ESP-IDF error type -- esp_err_t */
|
||||
ESP_TLS_ERR_TYPE_WOLFSSL, /*!< Error code from wolfSSL library */
|
||||
ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, /*!< Certificate flags defined in wolfSSL */
|
||||
ESP_TLS_ERR_TYPE_MAX, /*!< Last err type -- invalid entry */
|
||||
} esp_tls_error_type_t;
|
||||
|
||||
typedef struct esp_tls_last_error* esp_tls_error_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Error structure containing relevant errors in case tls error occurred
|
||||
*/
|
||||
typedef struct esp_tls_last_error {
|
||||
esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */
|
||||
int esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */
|
||||
int esp_tls_flags; /*!< last certification verification flags */
|
||||
} esp_tls_last_error_t;
|
||||
|
||||
/**
|
||||
* @brief ESP-TLS Connection State
|
||||
*/
|
||||
@ -234,6 +170,8 @@ typedef struct esp_tls_cfg {
|
||||
bundle for server verification, must be enabled in menuconfig */
|
||||
|
||||
void *ds_data; /*!< Pointer for digital signature peripheral context */
|
||||
bool is_plain_tcp; /*!< Use non-TLS connection: When set to true, the esp-tls uses
|
||||
plain TCP transport rather then TLS/SSL connection */
|
||||
} esp_tls_cfg_t;
|
||||
|
||||
#ifdef CONFIG_ESP_TLS_SERVER
|
||||
|
100
components/esp-tls/esp_tls_errors.h
Normal file
100
components/esp-tls/esp_tls_errors.h
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_TLS_ERRORS_H_
|
||||
#define _ESP_TLS_ERRORS_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */
|
||||
#define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */
|
||||
#define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */
|
||||
#define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */
|
||||
#define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */
|
||||
#define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set/get socket option */
|
||||
#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */
|
||||
#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */
|
||||
#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */
|
||||
#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */
|
||||
#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */
|
||||
#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */
|
||||
#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */
|
||||
|
||||
#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */
|
||||
#define ESP_ERR_ESP_TLS_TCP_CLOSED_FIN (ESP_ERR_ESP_TLS_BASE + 0x1C) /*< esp-tls's TPC transport connection has benn closed (in a clean way) */
|
||||
|
||||
/**
|
||||
* Definition of errors reported from IO API (potentially non-blocking) in case of error:
|
||||
* - esp_tls_conn_read()
|
||||
* - esp_tls_conn_write()
|
||||
*/
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ
|
||||
#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT
|
||||
#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */
|
||||
#define ESP_TLS_ERR_SSL_WANT_READ -0x6900
|
||||
#define ESP_TLS_ERR_SSL_WANT_WRITE -0x6880
|
||||
#define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT
|
||||
#endif /*CONFIG_ESP_TLS_USING_WOLFSSL */
|
||||
|
||||
/**
|
||||
* Definition of different types/sources of error codes reported
|
||||
* from different components
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_TLS_ERR_TYPE_UNKNOWN = 0,
|
||||
ESP_TLS_ERR_TYPE_SYSTEM, /*!< System error -- errno */
|
||||
ESP_TLS_ERR_TYPE_MBEDTLS, /*!< Error code from mbedTLS library */
|
||||
ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, /*!< Certificate flags defined in mbedTLS */
|
||||
ESP_TLS_ERR_TYPE_ESP, /*!< ESP-IDF error type -- esp_err_t */
|
||||
ESP_TLS_ERR_TYPE_WOLFSSL, /*!< Error code from wolfSSL library */
|
||||
ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, /*!< Certificate flags defined in wolfSSL */
|
||||
ESP_TLS_ERR_TYPE_MAX, /*!< Last err type -- invalid entry */
|
||||
} esp_tls_error_type_t;
|
||||
|
||||
typedef struct esp_tls_last_error* esp_tls_error_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Error structure containing relevant errors in case tls error occurred
|
||||
*/
|
||||
typedef struct esp_tls_last_error {
|
||||
esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */
|
||||
int esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */
|
||||
int esp_tls_flags; /*!< last certification verification flags */
|
||||
} esp_tls_last_error_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ESP_TLS_ERRORS_H_
|
@ -62,6 +62,20 @@ typedef enum x509_file_type {
|
||||
FILE_TYPE_SELF_KEY, /* Private key in the self cert-key pair */
|
||||
} x509_file_type_t;
|
||||
|
||||
/* Error type conversion utility so that esp-tls read/write API to return negative number on error */
|
||||
static inline ssize_t esp_tls_convert_wolfssl_err_to_ssize(int wolfssl_error)
|
||||
{
|
||||
switch (wolfssl_error) {
|
||||
case WOLFSSL_ERROR_WANT_READ:
|
||||
return ESP_TLS_ERR_SSL_WANT_READ;
|
||||
case WOLFSSL_ERROR_WANT_WRITE:
|
||||
return ESP_TLS_ERR_SSL_WANT_WRITE;
|
||||
default:
|
||||
// Make sure we return a negative number
|
||||
return wolfssl_error>0 ? -wolfssl_error: wolfssl_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks whether the certificate provided is in pem format or not */
|
||||
static esp_err_t esp_load_wolfssl_verify_buffer(esp_tls_t *tls, const unsigned char *cert_buf, unsigned int cert_len, x509_file_type_t type, int *err_ret)
|
||||
{
|
||||
@ -332,9 +346,9 @@ int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
|
||||
return 1;
|
||||
} else {
|
||||
int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret);
|
||||
if (err != ESP_TLS_ERR_SSL_WANT_READ && err != ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
|
||||
if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
ESP_LOGE(TAG, "wolfSSL_connect returned %d, error code: 0x%x", ret, err);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -err);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED);
|
||||
if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) {
|
||||
/* This is to check whether handshake failed due to invalid certificate*/
|
||||
@ -359,10 +373,11 @@ ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
|
||||
ESP_LOGE(TAG, "read error :%d:", ret);
|
||||
}
|
||||
return esp_tls_convert_wolfssl_err_to_ssize(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -372,12 +387,13 @@ ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen)
|
||||
ssize_t ret = wolfSSL_write( (WOLFSSL *)tls->priv_ssl, (unsigned char *) data, datalen);
|
||||
if (ret < 0) {
|
||||
ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret);
|
||||
if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED);
|
||||
ESP_LOGE(TAG, "write error :%d:", ret);
|
||||
|
||||
}
|
||||
return esp_tls_convert_wolfssl_err_to_ssize(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -447,11 +463,12 @@ int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
|
||||
tls->write = esp_wolfssl_write;
|
||||
int ret;
|
||||
while ((ret = wolfSSL_accept((WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) {
|
||||
if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
ret = wolfSSL_get_error((WOLFSSL *)tls->priv_ssl, ret);
|
||||
if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
|
||||
ESP_LOGE(TAG, "wolfSSL_handshake_server returned %d", ret);
|
||||
tls->conn_state = ESP_TLS_FAIL;
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -55,6 +55,14 @@ ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls);
|
||||
*/
|
||||
esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls);
|
||||
|
||||
/**
|
||||
* mbedTLS function for Initializing socket wrappers
|
||||
*/
|
||||
static inline void esp_mbedtls_net_init(esp_tls_t *tls)
|
||||
{
|
||||
mbedtls_net_init(&tls->server_fd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_TLS_SERVER
|
||||
/**
|
||||
* Internal Callback for set_server_config
|
||||
|
@ -71,6 +71,13 @@ void esp_wolfssl_free_global_ca_store(void);
|
||||
*/
|
||||
esp_err_t esp_wolfssl_init_global_ca_store(void);
|
||||
|
||||
/**
|
||||
* wolfSSL function for Initializing socket wrappers (no-operation for wolfSSL)
|
||||
*/
|
||||
static inline void esp_wolfssl_net_init(esp_tls_t *tls)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_TLS_SERVER
|
||||
|
||||
/**
|
||||
|
@ -50,8 +50,8 @@
|
||||
#if __has_include("esp_supplicant/esp_wps.h")
|
||||
#include "esp_supplicant/esp_wps.h"
|
||||
#endif
|
||||
#if __has_include("esp_tls.h")
|
||||
#include "esp_tls.h"
|
||||
#if __has_include("esp_tls_errors.h")
|
||||
#include "esp_tls_errors.h"
|
||||
#endif
|
||||
#if __has_include("esp_wifi.h")
|
||||
#include "esp_wifi.h"
|
||||
@ -588,7 +588,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||
# ifdef ESP_ERR_HTTP_EAGAIN
|
||||
ERR_TBL_IT(ESP_ERR_HTTP_EAGAIN), /* 28679 0x7007 Mapping of errno EAGAIN to esp_err_t */
|
||||
# endif
|
||||
// components/esp-tls/esp_tls.h
|
||||
// components/esp-tls/esp_tls_errors.h
|
||||
# ifdef ESP_ERR_ESP_TLS_BASE
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_BASE), /* 32768 0x8000 Starting number of ESP-TLS error codes */
|
||||
# endif
|
||||
@ -606,7 +606,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST), /* 32772 0x8004 Failed to connect to host */
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED), /* 32773 0x8005 failed to set socket option */
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED), /* 32773 0x8005 failed to set/get socket option */
|
||||
# endif
|
||||
# ifdef ESP_ERR_MBEDTLS_CERT_PARTLY_OK
|
||||
ERR_TBL_IT(ESP_ERR_MBEDTLS_CERT_PARTLY_OK), /* 32774 0x8006 mbedtls parse certificates was partly successful */
|
||||
@ -674,6 +674,9 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_TLS_SE_FAILED
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_SE_FAILED), /* 32795 0x801b */
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_TLS_TCP_CLOSED_FIN
|
||||
ERR_TBL_IT(ESP_ERR_ESP_TLS_TCP_CLOSED_FIN), /* 32796 0x801c */
|
||||
# endif
|
||||
// components/esp_https_ota/include/esp_https_ota.h
|
||||
# ifdef ESP_ERR_HTTPS_OTA_BASE
|
||||
|
@ -5,4 +5,4 @@ idf_component_register(SRCS "esp_http_client.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_INCLUDE_DIRS "lib/include"
|
||||
REQUIRES nghttp
|
||||
PRIV_REQUIRES lwip esp-tls tcp_transport)
|
||||
PRIV_REQUIRES tcp_transport)
|
||||
|
@ -329,8 +329,8 @@ 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
|
||||
esp_transport_tcp_set_keep_alive(tcp, &client->keep_alive_cfg);
|
||||
|
||||
|
||||
esp_transport_handle_t ws = esp_transport_ws_init(tcp);
|
||||
@ -347,6 +347,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
ESP_WS_CLIENT_MEM_CHECK(TAG, ssl, goto _websocket_init_fail);
|
||||
|
||||
esp_transport_set_default_port(ssl, WEBSOCKET_SSL_DEFAULT_PORT);
|
||||
esp_transport_list_add(client->transport_list, ssl, "_ssl"); // need to save to transport list, for cleanup
|
||||
if (config->use_global_ca_store == true) {
|
||||
esp_transport_ssl_enable_global_ca_store(ssl);
|
||||
} else if (config->cert_pem) {
|
||||
@ -374,7 +375,6 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
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);
|
||||
ESP_WS_CLIENT_MEM_CHECK(TAG, wss, goto _websocket_init_fail);
|
||||
|
@ -1,8 +1,7 @@
|
||||
idf_component_register(SRCS "transport.c"
|
||||
"transport_ssl.c"
|
||||
"transport_tcp.c"
|
||||
"transport_ws.c"
|
||||
"transport_utils.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_INCLUDE_DIRS "private_include"
|
||||
REQUIRES lwip esp-tls)
|
||||
REQUIRES esp-tls)
|
||||
|
@ -20,6 +20,11 @@
|
||||
|
||||
typedef int (*get_socket_func)(esp_transport_handle_t t);
|
||||
|
||||
typedef struct esp_foundation_transport {
|
||||
struct esp_transport_error_storage *error_handle; /*!< Pointer to the transport error container */
|
||||
struct transport_esp_tls *transport_esp_tls; /*!< Pointer to the base transport which uses esp-tls */
|
||||
} esp_foundation_transport_t;
|
||||
|
||||
/**
|
||||
* Transport layer structure, which will provide functions, basic properties for transport types
|
||||
*/
|
||||
@ -37,13 +42,35 @@ struct esp_transport_item_t {
|
||||
connect_async_func _connect_async; /*!< non-blocking connect function of this transport */
|
||||
payload_transfer_func _parent_transfer; /*!< Function returning underlying transport layer */
|
||||
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)
|
||||
* extended with transport's specific errors */
|
||||
esp_transport_keep_alive_t *keep_alive_cfg; /*!< TCP keep-alive config */
|
||||
struct esp_foundation_transport *base; /*!< Foundation transport pointer available from each transport */
|
||||
|
||||
STAILQ_ENTRY(esp_transport_item_t) next;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Internal error types for TCP connection issues not covered in socket's errno
|
||||
*/
|
||||
enum tcp_transport_errors {
|
||||
ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT,
|
||||
ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME,
|
||||
ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN,
|
||||
ERR_TCP_TRANSPORT_CONNECTION_FAILED,
|
||||
ERR_TCP_TRANSPORT_SETOPT_FAILED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Captures internal tcp connection error
|
||||
*
|
||||
* This is internally translated to esp-tls return codes of esp_err_t type, since the esp-tls
|
||||
* will be used as TCP transport layer
|
||||
*
|
||||
* @param[in] t The transport handle
|
||||
* @param[in] error Internal tcp-transport's error
|
||||
*
|
||||
*/
|
||||
void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error);
|
||||
|
||||
/**
|
||||
* @brief Returns underlying socket for the supplied transport handle
|
||||
*
|
||||
@ -63,4 +90,29 @@ int esp_transport_get_socket(esp_transport_handle_t t);
|
||||
*/
|
||||
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno);
|
||||
|
||||
/**
|
||||
* @brief Creates esp-tls transport used in the foundation transport
|
||||
*
|
||||
* @return transport esp-tls handle
|
||||
*/
|
||||
struct transport_esp_tls* esp_transport_esp_tls_create(void);
|
||||
|
||||
/**
|
||||
* @brief Destroys esp-tls transport used in the foundation transport
|
||||
*
|
||||
* @param[in] transport esp-tls handle
|
||||
*/
|
||||
void esp_transport_esp_tls_destroy(struct transport_esp_tls* transport_esp_tls);
|
||||
|
||||
/**
|
||||
* @brief Sets error to common transport handle
|
||||
*
|
||||
* Note: This function copies the supplied error handle object to tcp_transport's internal
|
||||
* error handle object
|
||||
*
|
||||
* @param[in] A transport handle
|
||||
*
|
||||
*/
|
||||
void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle);
|
||||
|
||||
#endif //_ESP_TRANSPORT_INTERNAL_H_
|
||||
|
@ -1,30 +0,0 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_TRANSPORT_SSL_INTERNAL_H_
|
||||
#define _ESP_TRANSPORT_SSL_INTERNAL_H_
|
||||
|
||||
/**
|
||||
* @brief Sets error to common transport handle
|
||||
*
|
||||
* Note: This function copies the supplied error handle object to tcp_transport's internal
|
||||
* error handle object
|
||||
*
|
||||
* @param[in] A transport handle
|
||||
*
|
||||
*/
|
||||
void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle);
|
||||
|
||||
|
||||
#endif /* _ESP_TRANSPORT_SSL_INTERNAL_H_ */
|
@ -14,6 +14,9 @@
|
||||
|
||||
#define TCP_CONNECT_DONE (1)
|
||||
#define TCP_LISTENER_DONE (2)
|
||||
#define TCP_ACCEPTOR_DONE (4)
|
||||
#define TCP_LISTENER_ACCEPTED (8)
|
||||
#define TCP_LISTENER_READY (16)
|
||||
|
||||
struct tcp_connect_task_params {
|
||||
int timeout_ms;
|
||||
@ -21,8 +24,12 @@ struct tcp_connect_task_params {
|
||||
EventGroupHandle_t tcp_connect_done;
|
||||
int ret;
|
||||
int listen_sock;
|
||||
int accepted_sock;
|
||||
int last_connect_sock;
|
||||
bool tcp_listener_failed;
|
||||
esp_transport_handle_t transport_under_test;
|
||||
bool accept_connection;
|
||||
bool consume_sock_backlog;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -51,8 +58,12 @@ static void connect_once(struct tcp_connect_task_params *params)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a listener (without and acceptor) and connect to as many times as possible
|
||||
* to prepare an endpoint which would make the client block but not complete TCP handshake
|
||||
* @brief creates a listener (and an acceptor if configured)
|
||||
*
|
||||
* if consume_sock_backlog set: connect as many times as possible to prepare an endpoint which
|
||||
* would make the client block but not complete TCP handshake
|
||||
*
|
||||
* if accept_connection set: waiting normally for connection creating an acceptor to mimic tcp-transport endpoint
|
||||
*/
|
||||
static void localhost_listener(void *pvParameters)
|
||||
{
|
||||
@ -63,6 +74,9 @@ static void localhost_listener(void *pvParameters)
|
||||
.sin_port = htons(params->port) };
|
||||
// Create listener socket and bind it to ANY address
|
||||
params->listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||
int opt = 1;
|
||||
setsockopt(params->listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
|
||||
if (params->listen_sock < 0) {
|
||||
ESP_LOGE(TAG, "Unable to create socket");
|
||||
params->tcp_listener_failed = true;
|
||||
@ -83,11 +97,27 @@ static void localhost_listener(void *pvParameters)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// Ideally we would set backlog to 0, but since this is an implementation specific recommendation parameter,
|
||||
// we recursively create sockets and try to connect to this listener in order to consume the backlog. After
|
||||
// the backlog is consumed, the last connection blocks (waiting for accept), but at that point we are sure
|
||||
// that any other connection would also block
|
||||
connect_once(params);
|
||||
// Listener is ready at this point
|
||||
xEventGroupSetBits(params->tcp_connect_done, TCP_LISTENER_READY);
|
||||
|
||||
if (params->consume_sock_backlog) {
|
||||
// Ideally we would set backlog to 0, but since this is an implementation specific recommendation parameter,
|
||||
// we recursively create sockets and try to connect to this listener in order to consume the backlog. After
|
||||
// the backlog is consumed, the last connection blocks (waiting for accept), but at that point we are sure
|
||||
// that any other connection would also block
|
||||
connect_once(params);
|
||||
} else if (params->accept_connection) {
|
||||
struct sockaddr_storage source_addr;
|
||||
socklen_t addr_len = sizeof(source_addr);
|
||||
params->accepted_sock = accept(params->listen_sock, (struct sockaddr *)&source_addr, &addr_len);
|
||||
if (params->accepted_sock < 0) {
|
||||
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
|
||||
goto failed;
|
||||
}
|
||||
xEventGroupSetBits(params->tcp_connect_done, TCP_LISTENER_ACCEPTED); // Mark the socket as accepted
|
||||
// ...and wait for the "acceptor" tests to finish
|
||||
xEventGroupWaitBits(params->tcp_connect_done, TCP_ACCEPTOR_DONE, true, true, params->timeout_ms * 10);
|
||||
}
|
||||
|
||||
failed:
|
||||
xEventGroupSetBits(params->tcp_connect_done, TCP_LISTENER_DONE);
|
||||
@ -98,14 +128,12 @@ static void tcp_connect_task(void *pvParameters)
|
||||
{
|
||||
struct tcp_connect_task_params *params = pvParameters;
|
||||
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
esp_transport_list_add(transport_list, tcp, "tcp");
|
||||
|
||||
params->ret = esp_transport_connect(tcp, "localhost", params->port, params->timeout_ms);
|
||||
params->ret = esp_transport_connect(params->transport_under_test, "localhost", params->port, params->timeout_ms);
|
||||
if (params->accept_connection) {
|
||||
// If we test the accepted connection, need to wait until the test completes
|
||||
xEventGroupWaitBits(params->tcp_connect_done, TCP_ACCEPTOR_DONE, true, true, params->timeout_ms * 10);
|
||||
}
|
||||
xEventGroupSetBits(params->tcp_connect_done, TCP_CONNECT_DONE);
|
||||
esp_transport_close(tcp);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
@ -132,7 +160,7 @@ TEST_CASE("tcp_transport: using ws transport separately", "[tcp_transport][leaks
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_transport_destroy(tcp));
|
||||
}
|
||||
|
||||
TEST_CASE("tcp_transport: connect timeout", "[tcp_transport]")
|
||||
static void transport_connection_timeout_test(esp_transport_handle_t transport_under_test)
|
||||
{
|
||||
// This case simulates connection timeout running tcp connect asynchronously with other socket connection
|
||||
// consuming entire socket listener backlog.
|
||||
@ -142,7 +170,9 @@ TEST_CASE("tcp_transport: connect timeout", "[tcp_transport]")
|
||||
|
||||
struct tcp_connect_task_params params = { .tcp_connect_done = xEventGroupCreate(),
|
||||
.timeout_ms = 200,
|
||||
.port = 80 };
|
||||
.port = 80,
|
||||
.consume_sock_backlog = true,
|
||||
.transport_under_test = transport_under_test };
|
||||
TickType_t max_wait = pdMS_TO_TICKS(params.timeout_ms * 10);
|
||||
TaskHandle_t localhost_listener_task_handle = NULL;
|
||||
TaskHandle_t tcp_connect_task_handle = NULL;
|
||||
@ -160,7 +190,7 @@ TEST_CASE("tcp_transport: connect timeout", "[tcp_transport]")
|
||||
EventBits_t bits = xEventGroupWaitBits(params.tcp_connect_done, TCP_CONNECT_DONE, true, true, max_wait);
|
||||
TickType_t end = xTaskGetTickCount();
|
||||
|
||||
TEST_ASSERT_EQUAL(TCP_CONNECT_DONE, bits); // Connection has finished
|
||||
TEST_ASSERT_EQUAL(TCP_CONNECT_DONE, TCP_CONNECT_DONE & bits); // Connection has finished
|
||||
TEST_ASSERT_EQUAL(-1, params.ret); // Connection failed with -1
|
||||
|
||||
// Test connection attempt took expected timeout value
|
||||
@ -177,3 +207,226 @@ TEST_CASE("tcp_transport: connect timeout", "[tcp_transport]")
|
||||
test_utils_task_delete(localhost_listener_task_handle);
|
||||
test_utils_task_delete(tcp_connect_task_handle);
|
||||
}
|
||||
|
||||
TEST_CASE("tcp_transport: connect timeout", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
esp_transport_list_add(transport_list, tcp, "tcp");
|
||||
|
||||
transport_connection_timeout_test(tcp);
|
||||
esp_transport_close(tcp);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
}
|
||||
|
||||
TEST_CASE("ssl_transport: connect timeout", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
esp_transport_list_add(transport_list, tcp, "tcp");
|
||||
esp_transport_handle_t ssl = esp_transport_ssl_init();
|
||||
esp_transport_list_add(transport_list, ssl, "ssl");
|
||||
|
||||
transport_connection_timeout_test(ssl);
|
||||
esp_transport_close(tcp);
|
||||
esp_transport_close(ssl);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
}
|
||||
|
||||
TEST_CASE("transport: init and deinit multiple transport items", "[tcp_transport][leaks=0]")
|
||||
{
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
esp_transport_list_add(transport_list, tcp, "tcp");
|
||||
esp_transport_handle_t ssl = esp_transport_ssl_init();
|
||||
esp_transport_list_add(transport_list, ssl, "ssl");
|
||||
esp_transport_handle_t ws = esp_transport_ws_init(tcp);
|
||||
esp_transport_list_add(transport_list, ws, "ws");
|
||||
esp_transport_handle_t wss = esp_transport_ws_init(ssl);
|
||||
esp_transport_list_add(transport_list, wss, "wss");
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_transport_list_destroy(transport_list));
|
||||
}
|
||||
|
||||
// This is a private API of the tcp transport, but needed for socket operation tests
|
||||
int esp_transport_get_socket(esp_transport_handle_t t);
|
||||
|
||||
// Structures and types for passing socket options
|
||||
enum expected_sock_option_types {
|
||||
SOCK_OPT_TYPE_BOOL,
|
||||
SOCK_OPT_TYPE_INT,
|
||||
};
|
||||
|
||||
struct expected_sock_option {
|
||||
int level;
|
||||
int optname;
|
||||
int optval;
|
||||
enum expected_sock_option_types opttype;
|
||||
};
|
||||
|
||||
static void socket_operation_test(esp_transport_handle_t transport_under_test,
|
||||
const struct expected_sock_option expected_opts[], size_t sock_options_len)
|
||||
{
|
||||
struct tcp_connect_task_params params = { .tcp_connect_done = xEventGroupCreate(),
|
||||
.timeout_ms = 200,
|
||||
.port = 80,
|
||||
.accept_connection = true,
|
||||
.transport_under_test = transport_under_test };
|
||||
TickType_t max_wait = pdMS_TO_TICKS(params.timeout_ms * 10);
|
||||
TaskHandle_t localhost_listener_task_handle = NULL;
|
||||
TaskHandle_t tcp_connect_task_handle = NULL;
|
||||
|
||||
test_case_uses_tcpip();
|
||||
|
||||
// Create a listener and wait for it to be ready
|
||||
xTaskCreatePinnedToCore(localhost_listener, "localhost_listener", 4096, (void*)¶ms, 5, &localhost_listener_task_handle, 0);
|
||||
xEventGroupWaitBits(params.tcp_connect_done, TCP_LISTENER_READY, true, true, max_wait);
|
||||
// Perform tcp-connect in a separate task
|
||||
xTaskCreatePinnedToCore(tcp_connect_task, "tcp_connect_task", 4096, (void*)¶ms, 6, &tcp_connect_task_handle, 0);
|
||||
|
||||
// Wait till the connection gets accepted to get the client's socket
|
||||
xEventGroupWaitBits(params.tcp_connect_done, TCP_LISTENER_ACCEPTED, true, true, max_wait);
|
||||
int sock = esp_transport_get_socket(params.transport_under_test);
|
||||
for (int i=0; i<sock_options_len; ++i) {
|
||||
int value = -1;
|
||||
socklen_t optlen = (socklen_t)sizeof(value);
|
||||
TEST_ASSERT_EQUAL(getsockopt(sock, expected_opts[i].level, expected_opts[i].optname,
|
||||
(void*)&value, &optlen), 0);
|
||||
if (expected_opts[i].opttype == SOCK_OPT_TYPE_BOOL) {
|
||||
TEST_ASSERT_EQUAL((bool)value, (bool) expected_opts[i].optval);
|
||||
} else if (expected_opts[i].opttype == SOCK_OPT_TYPE_INT) {
|
||||
TEST_ASSERT_EQUAL(value, expected_opts[i].optval);
|
||||
} else {
|
||||
TEST_FAIL_MESSAGE("Unsupported socket option type");
|
||||
}
|
||||
}
|
||||
|
||||
close(sock); // close the tcp_transport's socket so we don't have to wait for connection timeout
|
||||
xEventGroupSetBits(params.tcp_connect_done, TCP_ACCEPTOR_DONE);
|
||||
xEventGroupWaitBits(params.tcp_connect_done, TCP_CONNECT_DONE, true, true, max_wait);
|
||||
// Closing the listener and acceptor sockets
|
||||
close(params.listen_sock);
|
||||
close(params.accepted_sock);
|
||||
|
||||
// Cleanup
|
||||
TEST_ASSERT_EQUAL(false, params.tcp_listener_failed);
|
||||
vEventGroupDelete(params.tcp_connect_done);
|
||||
test_utils_task_delete(localhost_listener_task_handle);
|
||||
test_utils_task_delete(tcp_connect_task_handle);
|
||||
}
|
||||
|
||||
static void tcp_transport_keepalive_test(esp_transport_handle_t transport_under_test, esp_transport_keep_alive_t *config)
|
||||
{
|
||||
static struct expected_sock_option expected_opts[4] = {
|
||||
{ .level = SOL_SOCKET, .optname = SO_KEEPALIVE, .optval = 1, .opttype = SOCK_OPT_TYPE_BOOL },
|
||||
{ .level = IPPROTO_TCP },
|
||||
{ .level = IPPROTO_TCP },
|
||||
{ .level = IPPROTO_TCP }
|
||||
};
|
||||
|
||||
expected_opts[1].optname = TCP_KEEPIDLE;
|
||||
expected_opts[1].optval = config->keep_alive_idle;
|
||||
expected_opts[2].optname = TCP_KEEPINTVL;
|
||||
expected_opts[2].optval = config->keep_alive_interval;
|
||||
expected_opts[3].optname = TCP_KEEPCNT;
|
||||
expected_opts[3].optval = config->keep_alive_count;
|
||||
|
||||
socket_operation_test(transport_under_test, expected_opts, sizeof(expected_opts)/sizeof(struct expected_sock_option));
|
||||
}
|
||||
|
||||
TEST_CASE("tcp_transport: Keep alive test", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
esp_transport_list_add(transport_list, tcp, "tcp");
|
||||
|
||||
// Perform the test
|
||||
esp_transport_keep_alive_t keep_alive_cfg = {
|
||||
.keep_alive_interval = 5,
|
||||
.keep_alive_idle = 4,
|
||||
.keep_alive_enable = true,
|
||||
.keep_alive_count = 3 };
|
||||
esp_transport_tcp_set_keep_alive(tcp, &keep_alive_cfg);
|
||||
|
||||
tcp_transport_keepalive_test(tcp, &keep_alive_cfg);
|
||||
|
||||
// Cleanup
|
||||
esp_transport_close(tcp);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
}
|
||||
|
||||
TEST_CASE("ssl_transport: Keep alive test", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t ssl = esp_transport_ssl_init();
|
||||
esp_transport_list_add(transport_list, ssl, "ssl");
|
||||
esp_tls_init_global_ca_store();
|
||||
esp_transport_ssl_enable_global_ca_store(ssl);
|
||||
|
||||
// Perform the test
|
||||
esp_transport_keep_alive_t keep_alive_cfg = {
|
||||
.keep_alive_interval = 2,
|
||||
.keep_alive_idle = 3,
|
||||
.keep_alive_enable = true,
|
||||
.keep_alive_count = 4 };
|
||||
esp_transport_ssl_set_keep_alive(ssl, &keep_alive_cfg);
|
||||
|
||||
tcp_transport_keepalive_test(ssl, &keep_alive_cfg);
|
||||
|
||||
// Cleanup
|
||||
esp_transport_close(ssl);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
}
|
||||
|
||||
TEST_CASE("ws_transport: Keep alive test", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_list_handle_t transport_list = esp_transport_list_init();
|
||||
esp_transport_handle_t ssl = esp_transport_ssl_init();
|
||||
esp_transport_list_add(transport_list, ssl, "ssl");
|
||||
esp_tls_init_global_ca_store();
|
||||
esp_transport_ssl_enable_global_ca_store(ssl);
|
||||
esp_transport_handle_t ws = esp_transport_ws_init(ssl);
|
||||
esp_transport_list_add(transport_list, ws, "wss");
|
||||
|
||||
// Perform the test
|
||||
esp_transport_keep_alive_t keep_alive_cfg = {
|
||||
.keep_alive_interval = 1,
|
||||
.keep_alive_idle = 2,
|
||||
.keep_alive_enable = true,
|
||||
.keep_alive_count = 3 };
|
||||
esp_transport_tcp_set_keep_alive(ssl, &keep_alive_cfg);
|
||||
|
||||
tcp_transport_keepalive_test(ws, &keep_alive_cfg);
|
||||
|
||||
// Cleanup
|
||||
esp_transport_close(ssl);
|
||||
esp_transport_list_destroy(transport_list);
|
||||
}
|
||||
|
||||
// Note: This functionality is tested and kept only for compatibility reasons with IDF <= 4.x
|
||||
// It is strongly encouraged to use transport within lists only
|
||||
TEST_CASE("ssl_transport: Check that parameters (keepalive) are set independently on the list", "[tcp_transport]")
|
||||
{
|
||||
// Init the transport under test
|
||||
esp_transport_handle_t ssl = esp_transport_ssl_init();
|
||||
esp_tls_init_global_ca_store();
|
||||
esp_transport_ssl_enable_global_ca_store(ssl);
|
||||
|
||||
// Perform the test
|
||||
esp_transport_keep_alive_t keep_alive_cfg = {
|
||||
.keep_alive_interval = 2,
|
||||
.keep_alive_idle = 4,
|
||||
.keep_alive_enable = true,
|
||||
.keep_alive_count = 3 };
|
||||
esp_transport_ssl_set_keep_alive(ssl, &keep_alive_cfg);
|
||||
|
||||
tcp_transport_keepalive_test(ssl, &keep_alive_cfg);
|
||||
|
||||
// Cleanup
|
||||
esp_transport_close(ssl);
|
||||
esp_transport_destroy(ssl);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ static const char *TAG = "TRANSPORT";
|
||||
* * esp-tls last error storage
|
||||
* * sock-errno
|
||||
*/
|
||||
struct esp_transport_error_s {
|
||||
struct esp_transport_error_storage {
|
||||
struct esp_tls_last_error esp_tls_err_h_base; /*!< esp-tls last error container */
|
||||
// additional fields
|
||||
int sock_errno; /*!< last socket error captured for this transport */
|
||||
@ -42,14 +42,39 @@ struct esp_transport_error_s {
|
||||
*/
|
||||
STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t);
|
||||
|
||||
struct transport_esp_tls;
|
||||
|
||||
/**
|
||||
* Internal transport structure holding list of transports and other data common to all transports
|
||||
*/
|
||||
typedef struct esp_transport_internal {
|
||||
struct esp_transport_list_t list; /*!< List of transports */
|
||||
struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */
|
||||
struct esp_foundation_transport *base; /*!< Base transport pointer shared for each list item */
|
||||
} esp_transport_internal_t;
|
||||
|
||||
static esp_foundation_transport_t * esp_transport_init_foundation_transport(void)
|
||||
{
|
||||
esp_foundation_transport_t *foundation = calloc(1, sizeof(esp_foundation_transport_t));
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, foundation, return NULL);
|
||||
foundation->error_handle = calloc(1, sizeof(struct esp_transport_error_storage));
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, foundation->error_handle,
|
||||
free(foundation);
|
||||
return NULL);
|
||||
foundation->transport_esp_tls = esp_transport_esp_tls_create();
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, foundation->transport_esp_tls,
|
||||
free(foundation->error_handle);
|
||||
free(foundation);
|
||||
return NULL);
|
||||
return foundation;
|
||||
}
|
||||
|
||||
static void esp_transport_destroy_foundation_transport(esp_foundation_transport_t *foundation)
|
||||
{
|
||||
esp_transport_esp_tls_destroy(foundation->transport_esp_tls);
|
||||
free(foundation->error_handle);
|
||||
free(foundation);
|
||||
}
|
||||
|
||||
static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
|
||||
{
|
||||
/*
|
||||
@ -63,7 +88,10 @@ esp_transport_list_handle_t esp_transport_list_init(void)
|
||||
esp_transport_list_handle_t transport = calloc(1, sizeof(esp_transport_internal_t));
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
|
||||
STAILQ_INIT(&transport->list);
|
||||
transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s));
|
||||
transport->base = esp_transport_init_foundation_transport();
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, transport->base,
|
||||
free(transport);
|
||||
return NULL);
|
||||
return transport;
|
||||
}
|
||||
|
||||
@ -77,7 +105,7 @@ esp_err_t esp_transport_list_add(esp_transport_list_handle_t h, esp_transport_ha
|
||||
strcpy(t->scheme, scheme);
|
||||
STAILQ_INSERT_TAIL(&h->list, t, next);
|
||||
// Each transport in a list to share the same error tracker
|
||||
t->error_handle = h->error_handle;
|
||||
t->base = h->base;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -101,7 +129,7 @@ esp_transport_handle_t esp_transport_list_get_transport(esp_transport_list_handl
|
||||
esp_err_t esp_transport_list_destroy(esp_transport_list_handle_t h)
|
||||
{
|
||||
esp_transport_list_clean(h);
|
||||
free(h->error_handle);
|
||||
esp_transport_destroy_foundation_transport(h->base);
|
||||
free(h);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -283,36 +311,58 @@ 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)
|
||||
{
|
||||
if (t) {
|
||||
return &t->error_handle->esp_tls_err_h_base;
|
||||
return &t->base->error_handle->esp_tls_err_h_base;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int esp_transport_get_errno(esp_transport_handle_t t)
|
||||
{
|
||||
if (t && t->error_handle) {
|
||||
int actual_errno = t->error_handle->sock_errno;
|
||||
t->error_handle->sock_errno = 0;
|
||||
if (t && t->base && t->base->error_handle) {
|
||||
int actual_errno = t->base->error_handle->sock_errno;
|
||||
t->base->error_handle->sock_errno = 0;
|
||||
return actual_errno;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error)
|
||||
{
|
||||
esp_tls_last_error_t *err_handle = esp_transport_get_error_handle(t);
|
||||
switch (error) {
|
||||
case ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT:
|
||||
err_handle->last_error = ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT;
|
||||
break;
|
||||
case ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME:
|
||||
err_handle->last_error = ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME;
|
||||
break;
|
||||
case ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN:
|
||||
err_handle->last_error = ESP_ERR_ESP_TLS_TCP_CLOSED_FIN;
|
||||
break;
|
||||
case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
|
||||
err_handle->last_error = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
|
||||
break;
|
||||
case ERR_TCP_TRANSPORT_SETOPT_FAILED:
|
||||
err_handle->last_error = ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle)
|
||||
{
|
||||
if (t && t->error_handle) {
|
||||
memcpy(&t->error_handle->esp_tls_err_h_base, error_handle, sizeof(esp_tls_last_error_t));
|
||||
if (t && t->base && t->base->error_handle) {
|
||||
memcpy(&t->base->error_handle->esp_tls_err_h_base, error_handle, sizeof(esp_tls_last_error_t));
|
||||
int sock_error;
|
||||
if (esp_tls_get_and_clear_error_type(error_handle, ESP_TLS_ERR_TYPE_SYSTEM, &sock_error) == ESP_OK) {
|
||||
t->error_handle->sock_errno = sock_error;
|
||||
t->base->error_handle->sock_errno = sock_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno)
|
||||
{
|
||||
if (t && t->error_handle) {
|
||||
t->error_handle->sock_errno = sock_errno;
|
||||
if (t && t->base && t->base->error_handle) {
|
||||
t->base->error_handle->sock_errno = sock_errno;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,19 +15,19 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_tls.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "esp_transport.h"
|
||||
#include "esp_transport_ssl.h"
|
||||
#include "esp_transport_utils.h"
|
||||
#include "esp_transport_ssl_internal.h"
|
||||
#include "esp_transport_internal.h"
|
||||
|
||||
static const char *TAG = "TRANS_SSL";
|
||||
#define GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t) \
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t); \
|
||||
if (!ssl) { return; }
|
||||
|
||||
static const char *TAG = "TRANSPORT_BASE";
|
||||
|
||||
typedef enum {
|
||||
TRANS_SSL_INIT = 0,
|
||||
@ -37,20 +37,40 @@ typedef enum {
|
||||
/**
|
||||
* mbedtls specific transport data
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct transport_esp_tls {
|
||||
esp_tls_t *tls;
|
||||
esp_tls_cfg_t cfg;
|
||||
bool ssl_initialized;
|
||||
transport_ssl_conn_state_t conn_state;
|
||||
} transport_ssl_t;
|
||||
} transport_esp_tls_t;
|
||||
|
||||
static inline struct transport_esp_tls * ssl_get_context_data(esp_transport_handle_t t)
|
||||
{
|
||||
if (!t) {
|
||||
return NULL;
|
||||
}
|
||||
if (t->data) { // Prefer internal ssl context (independent from the list)
|
||||
return (transport_esp_tls_t*)t->data;
|
||||
}
|
||||
if (t->base && t->base->transport_esp_tls) { // Next one is the lists inherent context
|
||||
t->data = t->base->transport_esp_tls; // Optimize: if we have base context, use it as internal
|
||||
return t->base->transport_esp_tls;
|
||||
}
|
||||
// If we don't have a valid context, let's to create one
|
||||
transport_esp_tls_t *ssl = esp_transport_esp_tls_create();
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, ssl, return NULL)
|
||||
t->data = ssl;
|
||||
return ssl;
|
||||
}
|
||||
|
||||
static int ssl_close(esp_transport_handle_t t);
|
||||
|
||||
static int ssl_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
static int esp_tls_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms, bool is_plain_tcp)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
if (ssl->conn_state == TRANS_SSL_INIT) {
|
||||
ssl->cfg.timeout_ms = timeout_ms;
|
||||
ssl->cfg.is_plain_tcp = is_plain_tcp;
|
||||
ssl->cfg.non_block = true;
|
||||
ssl->ssl_initialized = true;
|
||||
ssl->tls = esp_tls_init();
|
||||
@ -65,11 +85,23 @@ static int ssl_connect_async(esp_transport_handle_t t, const char *host, int por
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
static inline int ssl_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
return esp_tls_connect_async(t, host, port, timeout_ms, false);
|
||||
}
|
||||
|
||||
static inline int tcp_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
{
|
||||
return esp_tls_connect_async(t, host, port, timeout_ms, true);
|
||||
}
|
||||
|
||||
static int esp_tls_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms, bool is_plain_tcp)
|
||||
{
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
|
||||
ssl->cfg.timeout_ms = timeout_ms;
|
||||
ssl->cfg.is_plain_tcp = is_plain_tcp;
|
||||
|
||||
ssl->ssl_initialized = true;
|
||||
ssl->tls = esp_tls_init();
|
||||
if (esp_tls_conn_new_sync(host, strlen(host), port, &ssl->cfg, ssl->tls) <= 0) {
|
||||
@ -79,13 +111,22 @@ static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int
|
||||
ssl->tls = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
{
|
||||
return esp_tls_connect(t, host, port, timeout_ms, false);
|
||||
}
|
||||
|
||||
static inline int tcp_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
{
|
||||
return esp_tls_connect(t, host, port, timeout_ms, true);
|
||||
}
|
||||
|
||||
static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
int ret = -1;
|
||||
int remain = 0;
|
||||
struct timeval timeout;
|
||||
@ -114,7 +155,7 @@ static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
|
||||
|
||||
static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
int ret = -1;
|
||||
struct timeval timeout;
|
||||
fd_set writeset;
|
||||
@ -138,7 +179,7 @@ static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
|
||||
static int ssl_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
|
||||
{
|
||||
int poll, ret;
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
|
||||
if ((poll = esp_transport_poll_write(t, timeout_ms)) <= 0) {
|
||||
ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->tls->sockfd, timeout_ms);
|
||||
@ -155,7 +196,7 @@ static int ssl_write(esp_transport_handle_t t, const char *buffer, int len, int
|
||||
static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
||||
{
|
||||
int poll, ret;
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
|
||||
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
||||
return poll;
|
||||
@ -166,6 +207,10 @@ static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout
|
||||
esp_transport_set_errors(t, ssl->tls->error_handle);
|
||||
}
|
||||
if (ret == 0) {
|
||||
if (poll > 0) {
|
||||
// no error, socket reads 0 while previously detected as readable -> connection has been closed cleanly
|
||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN);
|
||||
}
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
@ -174,8 +219,8 @@ static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout
|
||||
static int ssl_close(esp_transport_handle_t t)
|
||||
{
|
||||
int ret = -1;
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (ssl->ssl_initialized) {
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
if (ssl && ssl->ssl_initialized) {
|
||||
ret = esp_tls_conn_destroy(ssl->tls);
|
||||
ssl->conn_state = TRANS_SSL_INIT;
|
||||
ssl->ssl_initialized = false;
|
||||
@ -185,153 +230,151 @@ static int ssl_close(esp_transport_handle_t t)
|
||||
|
||||
static int ssl_destroy(esp_transport_handle_t t)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
esp_transport_close(t);
|
||||
free(ssl);
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
if (ssl) {
|
||||
esp_transport_close(t);
|
||||
if (t->base && t->base->transport_esp_tls &&
|
||||
t->data == t->base->transport_esp_tls) {
|
||||
// if internal ssl the same as the foundation transport,
|
||||
// just zero out, it will be freed on list destroy
|
||||
t->data = NULL;
|
||||
}
|
||||
esp_transport_esp_tls_destroy(t->data); // okay to pass NULL
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.use_global_ca_store = true;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.use_global_ca_store = true;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.psk_hint_key = psk_hint_key;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.psk_hint_key = psk_hint_key;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.cacert_pem_buf = (void *)data;
|
||||
ssl->cfg.cacert_pem_bytes = len + 1;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.cacert_pem_buf = (void *)data;
|
||||
ssl->cfg.cacert_pem_bytes = len + 1;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_cert_data_der(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.cacert_buf = (void *)data;
|
||||
ssl->cfg.cacert_bytes = len;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.cacert_buf = (void *)data;
|
||||
ssl->cfg.cacert_bytes = len;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.clientcert_pem_buf = (void *)data;
|
||||
ssl->cfg.clientcert_pem_bytes = len + 1;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.clientcert_pem_buf = (void *)data;
|
||||
ssl->cfg.clientcert_pem_bytes = len + 1;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.clientcert_buf = (void *)data;
|
||||
ssl->cfg.clientcert_bytes = len;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.clientcert_buf = (void *)data;
|
||||
ssl->cfg.clientcert_bytes = len;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.clientkey_pem_buf = (void *)data;
|
||||
ssl->cfg.clientkey_pem_bytes = len + 1;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.clientkey_pem_buf = (void *)data;
|
||||
ssl->cfg.clientkey_pem_bytes = len + 1;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_client_key_password(esp_transport_handle_t t, const char *password, int password_len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.clientkey_password = (void *)password;
|
||||
ssl->cfg.clientkey_password_len = password_len;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.clientkey_password = (void *)password;
|
||||
ssl->cfg.clientkey_password_len = password_len;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_client_key_data_der(esp_transport_handle_t t, const char *data, int len)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.clientkey_buf = (void *)data;
|
||||
ssl->cfg.clientkey_bytes = len;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.clientkey_buf = (void *)data;
|
||||
ssl->cfg.clientkey_bytes = len;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_alpn_protocol(esp_transport_handle_t t, const char **alpn_protos)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.alpn_protos = alpn_protos;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.alpn_protos = alpn_protos;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.skip_common_name = true;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.skip_common_name = true;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_use_secure_element(esp_transport_handle_t t)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.use_secure_element = true;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.use_secure_element = true;
|
||||
}
|
||||
|
||||
static int ssl_get_socket(esp_transport_handle_t t)
|
||||
{
|
||||
if (t) {
|
||||
transport_ssl_t *ssl = t->data;
|
||||
if (ssl && ssl->tls) {
|
||||
return ssl->tls->sockfd;
|
||||
}
|
||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||
if (ssl && ssl->tls) {
|
||||
return ssl->tls->sockfd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data)
|
||||
{
|
||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
||||
if (t && ssl) {
|
||||
ssl->cfg.ds_data = ds_data;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
ssl->cfg.ds_data = 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;
|
||||
}
|
||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||
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 t = esp_transport_init();
|
||||
transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t));
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, ssl, {
|
||||
esp_transport_destroy(t);
|
||||
return NULL;
|
||||
});
|
||||
esp_transport_set_context_data(t, ssl);
|
||||
esp_transport_set_func(t, ssl_connect, ssl_read, ssl_write, ssl_close, ssl_poll_read, ssl_poll_write, ssl_destroy);
|
||||
esp_transport_set_async_connect_func(t, ssl_connect_async);
|
||||
t->_get_socket = ssl_get_socket;
|
||||
return t;
|
||||
}
|
||||
|
||||
struct transport_esp_tls* esp_transport_esp_tls_create(void)
|
||||
{
|
||||
transport_esp_tls_t *transport_esp_tls = calloc(1, sizeof(transport_esp_tls_t));
|
||||
return transport_esp_tls;
|
||||
}
|
||||
|
||||
void esp_transport_esp_tls_destroy(struct transport_esp_tls* transport_esp_tls)
|
||||
{
|
||||
free(transport_esp_tls);
|
||||
}
|
||||
|
||||
esp_transport_handle_t esp_transport_tcp_init(void)
|
||||
{
|
||||
esp_transport_handle_t t = esp_transport_init();
|
||||
esp_transport_set_func(t, tcp_connect, ssl_read, ssl_write, ssl_close, ssl_poll_read, ssl_poll_write, ssl_destroy);
|
||||
esp_transport_set_async_connect_func(t, tcp_connect_async);
|
||||
t->_get_socket = ssl_get_socket;
|
||||
return t;
|
||||
}
|
||||
|
||||
void esp_transport_tcp_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg)
|
||||
{
|
||||
return esp_transport_ssl_set_keep_alive(t, keep_alive_cfg);
|
||||
}
|
||||
|
@ -1,310 +0,0 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp_transport_utils.h"
|
||||
#include "esp_transport.h"
|
||||
#include "esp_transport_internal.h"
|
||||
|
||||
static const char *TAG = "TRANS_TCP";
|
||||
|
||||
typedef struct {
|
||||
int sock;
|
||||
} transport_tcp_t;
|
||||
|
||||
static int resolve_dns(const char *host, struct sockaddr_in *ip)
|
||||
{
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
struct addrinfo *res;
|
||||
|
||||
int err = getaddrinfo(host, NULL, &hints, &res);
|
||||
if(err != 0 || res == NULL) {
|
||||
ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ip->sin_family = AF_INET;
|
||||
memcpy(&ip->sin_addr, &((struct sockaddr_in *)(res->ai_addr))->sin_addr, sizeof(ip->sin_addr));
|
||||
freeaddrinfo(res);
|
||||
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)
|
||||
{
|
||||
struct sockaddr_in remote_ip;
|
||||
struct timeval tv = { 0 };
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
|
||||
bzero(&remote_ip, sizeof(struct sockaddr_in));
|
||||
|
||||
//if stream_host is not ip address, resolve it AF_INET,servername,&serveraddr.sin_addr
|
||||
if (inet_pton(AF_INET, host, &remote_ip.sin_addr) != 1) {
|
||||
if (resolve_dns(host, &remote_ip) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tcp->sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (tcp->sock < 0) {
|
||||
ESP_LOGE(TAG, "Error create socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
remote_ip.sin_family = AF_INET;
|
||||
remote_ip.sin_port = htons(port);
|
||||
|
||||
esp_transport_utils_ms_to_timeval(timeout_ms, &tv); // if timeout=-1, tv is unchanged, 0, i.e. waits forever
|
||||
|
||||
setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &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
|
||||
int flags;
|
||||
if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] get file flags error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (fcntl(tcp->sock, F_SETFL, flags |= O_NONBLOCK) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] set nonblocking error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
fd_set fdset;
|
||||
|
||||
esp_transport_utils_ms_to_timeval(timeout_ms, &tv);
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(tcp->sock, &fdset);
|
||||
|
||||
int res = select(tcp->sock+1, NULL, &fdset, NULL, &tv);
|
||||
if (res < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] select() error: %s", tcp->sock, strerror(errno));
|
||||
esp_transport_capture_errno(t, errno);
|
||||
goto error;
|
||||
}
|
||||
else if (res == 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] select() timeout", tcp->sock);
|
||||
esp_transport_capture_errno(t, EINPROGRESS); // errno=EINPROGRESS indicates connection timeout
|
||||
goto error;
|
||||
} else {
|
||||
int sockerr;
|
||||
socklen_t len = (socklen_t)sizeof(int);
|
||||
|
||||
if (getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, (void*)(&sockerr), &len) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] getsockopt() error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
else if (sockerr) {
|
||||
esp_transport_capture_errno(t, sockerr);
|
||||
ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "[sock=%d] connect() error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
// Reset socket to blocking
|
||||
if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] get file flags error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (fcntl(tcp->sock, F_SETFL, flags & ~O_NONBLOCK) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] reset blocking error: %s", tcp->sock, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
return tcp->sock;
|
||||
error:
|
||||
close(tcp->sock);
|
||||
tcp->sock = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tcp_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
|
||||
{
|
||||
int poll;
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
if ((poll = esp_transport_poll_write(t, timeout_ms)) <= 0) {
|
||||
return poll;
|
||||
}
|
||||
return write(tcp->sock, buffer, len);
|
||||
}
|
||||
|
||||
static int tcp_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
||||
{
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
int poll = -1;
|
||||
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
||||
return poll;
|
||||
}
|
||||
int read_len = read(tcp->sock, buffer, len);
|
||||
if (read_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
return read_len;
|
||||
}
|
||||
|
||||
static int tcp_poll_read(esp_transport_handle_t t, int timeout_ms)
|
||||
{
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
int ret = -1;
|
||||
struct timeval timeout;
|
||||
fd_set readset;
|
||||
fd_set errset;
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(tcp->sock, &readset);
|
||||
FD_SET(tcp->sock, &errset);
|
||||
|
||||
ret = select(tcp->sock + 1, &readset, NULL, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
|
||||
if (ret > 0 && FD_ISSET(tcp->sock, &errset)) {
|
||||
int sock_errno = 0;
|
||||
uint32_t optlen = sizeof(sock_errno);
|
||||
getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
|
||||
esp_transport_capture_errno(t, sock_errno);
|
||||
ESP_LOGE(TAG, "tcp_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock);
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcp_poll_write(esp_transport_handle_t t, int timeout_ms)
|
||||
{
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
int ret = -1;
|
||||
struct timeval timeout;
|
||||
fd_set writeset;
|
||||
fd_set errset;
|
||||
FD_ZERO(&writeset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(tcp->sock, &writeset);
|
||||
FD_SET(tcp->sock, &errset);
|
||||
|
||||
ret = select(tcp->sock + 1, NULL, &writeset, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
|
||||
if (ret > 0 && FD_ISSET(tcp->sock, &errset)) {
|
||||
int sock_errno = 0;
|
||||
uint32_t optlen = sizeof(sock_errno);
|
||||
getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
|
||||
esp_transport_capture_errno(t, sock_errno);
|
||||
ESP_LOGE(TAG, "tcp_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock);
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcp_close(esp_transport_handle_t t)
|
||||
{
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
int ret = -1;
|
||||
if (tcp->sock >= 0) {
|
||||
ret = close(tcp->sock);
|
||||
tcp->sock = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tcp_destroy(esp_transport_handle_t t)
|
||||
{
|
||||
transport_tcp_t *tcp = esp_transport_get_context_data(t);
|
||||
esp_transport_close(t);
|
||||
free(tcp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcp_get_socket(esp_transport_handle_t t)
|
||||
{
|
||||
if (t) {
|
||||
transport_tcp_t *tcp = t->data;
|
||||
if (tcp) {
|
||||
return tcp->sock;
|
||||
}
|
||||
}
|
||||
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 t = esp_transport_init();
|
||||
transport_tcp_t *tcp = calloc(1, sizeof(transport_tcp_t));
|
||||
ESP_TRANSPORT_MEM_CHECK(TAG, tcp, {
|
||||
esp_transport_destroy(t);
|
||||
return NULL;
|
||||
});
|
||||
|
||||
tcp->sock = -1;
|
||||
esp_transport_set_func(t, tcp_connect, tcp_read, tcp_write, tcp_close, tcp_poll_read, tcp_poll_write, tcp_destroy);
|
||||
esp_transport_set_context_data(t, tcp);
|
||||
t->_get_socket = tcp_get_socket;
|
||||
|
||||
return t;
|
||||
}
|
@ -144,8 +144,7 @@ void app_main(void)
|
||||
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -194,8 +194,7 @@ void app_main(void)
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -133,8 +133,7 @@ void app_main(void)
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -121,8 +121,7 @@ void app_main(void)
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
@ -152,8 +152,8 @@ void app_main(void)
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -125,8 +125,7 @@ void app_main(void)
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_WS", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
@ -117,8 +117,7 @@ void app_main(void)
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -94,7 +94,7 @@ def test_examples_pppos_client(env, extra_data):
|
||||
'pppos_example: GOT ip event!!!',
|
||||
'pppos_example: MQTT other event id: 7',
|
||||
# There are no fake DNS server and MQTT server set up so the example fails at this point
|
||||
'TRANS_TCP: DNS lookup failed err=202 res=0x0',
|
||||
'esp-tls: couldn\'t get hostname',
|
||||
'MQTT_CLIENT: Error transport connect',
|
||||
'pppos_example: MQTT_EVENT_ERROR',
|
||||
'pppos_example: MQTT_EVENT_DISCONNECTED')
|
||||
|
@ -46,8 +46,7 @@ void app_main(void)
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
@ -44,8 +44,7 @@ void app_main(void)
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("OPENSSL_CLIENT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user