mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-09 23:54:33 +02:00
tcp_transport/esp_tls: Use common TCP transport to reduce code duplication
For high level review of the changes.
This commit is contained in:
@@ -276,7 +276,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
|
|||||||
switch (tls->conn_state) {
|
switch (tls->conn_state) {
|
||||||
case ESP_TLS_INIT:
|
case ESP_TLS_INIT:
|
||||||
tls->sockfd = -1;
|
tls->sockfd = -1;
|
||||||
if (cfg != NULL) {
|
if (cfg != NULL && cfg->is_plain_tcp == false) {
|
||||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||||
mbedtls_net_init(&tls->server_fd);
|
mbedtls_net_init(&tls->server_fd);
|
||||||
#endif
|
#endif
|
||||||
@@ -286,7 +286,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
|
|||||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
|
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!cfg) {
|
if (tls->is_tls == false) {
|
||||||
tls->read = tcp_read;
|
tls->read = tcp_read;
|
||||||
tls->write = tcp_write;
|
tls->write = tcp_write;
|
||||||
ESP_LOGD(TAG, "non-tls connection established");
|
ESP_LOGD(TAG, "non-tls connection established");
|
||||||
|
@@ -170,6 +170,7 @@ typedef struct esp_tls_cfg {
|
|||||||
bundle for server verification, must be enabled in menuconfig */
|
bundle for server verification, must be enabled in menuconfig */
|
||||||
|
|
||||||
void *ds_data; /*!< Pointer for digital signature peripheral context */
|
void *ds_data; /*!< Pointer for digital signature peripheral context */
|
||||||
|
bool is_plain_tcp;
|
||||||
} esp_tls_cfg_t;
|
} esp_tls_cfg_t;
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_TLS_SERVER
|
#ifdef CONFIG_ESP_TLS_SERVER
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
idf_component_register(SRCS "transport.c"
|
idf_component_register(SRCS "transport.c"
|
||||||
"transport_ssl.c"
|
"transport_ssl.c"
|
||||||
"transport_tcp.c"
|
|
||||||
"transport_ws.c"
|
"transport_ws.c"
|
||||||
"transport_utils.c"
|
"transport_utils.c"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
typedef int (*get_socket_func)(esp_transport_handle_t t);
|
typedef int (*get_socket_func)(esp_transport_handle_t t);
|
||||||
|
|
||||||
|
struct transport_esp_tls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transport layer structure, which will provide functions, basic properties for transport types
|
* Transport layer structure, which will provide functions, basic properties for transport types
|
||||||
*/
|
*/
|
||||||
@@ -40,6 +42,7 @@ struct esp_transport_item_t {
|
|||||||
struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle)
|
struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle)
|
||||||
* extended with transport's specific errors */
|
* extended with transport's specific errors */
|
||||||
esp_transport_keep_alive_t *keep_alive_cfg; /*!< TCP keep-alive config */
|
esp_transport_keep_alive_t *keep_alive_cfg; /*!< TCP keep-alive config */
|
||||||
|
struct transport_esp_tls *foundation_transport;
|
||||||
|
|
||||||
STAILQ_ENTRY(esp_transport_item_t) next;
|
STAILQ_ENTRY(esp_transport_item_t) next;
|
||||||
};
|
};
|
||||||
@@ -86,4 +89,6 @@ int esp_transport_get_socket(esp_transport_handle_t t);
|
|||||||
*/
|
*/
|
||||||
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno);
|
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno);
|
||||||
|
|
||||||
|
struct transport_esp_tls* esp_transport_init_foundation(void);
|
||||||
|
|
||||||
#endif //_ESP_TRANSPORT_INTERNAL_H_
|
#endif //_ESP_TRANSPORT_INTERNAL_H_
|
||||||
|
@@ -23,7 +23,6 @@
|
|||||||
#include "esp_transport.h"
|
#include "esp_transport.h"
|
||||||
#include "esp_transport_internal.h"
|
#include "esp_transport_internal.h"
|
||||||
#include "esp_transport_utils.h"
|
#include "esp_transport_utils.h"
|
||||||
#include "esp_tls_errors.h"
|
|
||||||
|
|
||||||
static const char *TAG = "TRANSPORT";
|
static const char *TAG = "TRANSPORT";
|
||||||
|
|
||||||
@@ -43,12 +42,15 @@ struct esp_transport_error_s {
|
|||||||
*/
|
*/
|
||||||
STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t);
|
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
|
* Internal transport structure holding list of transports and other data common to all transports
|
||||||
*/
|
*/
|
||||||
typedef struct esp_transport_internal {
|
typedef struct esp_transport_internal {
|
||||||
struct esp_transport_list_t list; /*!< List of transports */
|
struct esp_transport_list_t list; /*!< List of transports */
|
||||||
struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */
|
struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */
|
||||||
|
struct transport_esp_tls *foundation_transport;
|
||||||
} esp_transport_internal_t;
|
} esp_transport_internal_t;
|
||||||
|
|
||||||
static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
|
static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
|
||||||
@@ -65,6 +67,7 @@ esp_transport_list_handle_t esp_transport_list_init(void)
|
|||||||
ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
|
ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
|
||||||
STAILQ_INIT(&transport->list);
|
STAILQ_INIT(&transport->list);
|
||||||
transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s));
|
transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s));
|
||||||
|
transport->foundation_transport = esp_transport_init_foundation();
|
||||||
return transport;
|
return transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +82,7 @@ esp_err_t esp_transport_list_add(esp_transport_list_handle_t h, esp_transport_ha
|
|||||||
STAILQ_INSERT_TAIL(&h->list, t, next);
|
STAILQ_INSERT_TAIL(&h->list, t, next);
|
||||||
// Each transport in a list to share the same error tracker
|
// Each transport in a list to share the same error tracker
|
||||||
t->error_handle = h->error_handle;
|
t->error_handle = h->error_handle;
|
||||||
|
t->foundation_transport = h->foundation_transport;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +107,7 @@ esp_err_t esp_transport_list_destroy(esp_transport_list_handle_t h)
|
|||||||
{
|
{
|
||||||
esp_transport_list_clean(h);
|
esp_transport_list_clean(h);
|
||||||
free(h->error_handle);
|
free(h->error_handle);
|
||||||
|
free(h->foundation_transport); // TODO: make it destroy foundation
|
||||||
free(h);
|
free(h);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* mbedtls specific transport data
|
* mbedtls specific transport data
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct transport_esp_tls {
|
||||||
esp_tls_t *tls;
|
esp_tls_t *tls;
|
||||||
esp_tls_cfg_t cfg;
|
esp_tls_cfg_t cfg;
|
||||||
bool ssl_initialized;
|
bool ssl_initialized;
|
||||||
@@ -48,7 +48,7 @@ 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 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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (ssl->conn_state == TRANS_SSL_INIT) {
|
if (ssl->conn_state == TRANS_SSL_INIT) {
|
||||||
ssl->cfg.timeout_ms = timeout_ms;
|
ssl->cfg.timeout_ms = timeout_ms;
|
||||||
ssl->cfg.non_block = true;
|
ssl->cfg.non_block = true;
|
||||||
@@ -67,7 +67,7 @@ static int ssl_connect_async(esp_transport_handle_t t, const char *host, int por
|
|||||||
|
|
||||||
static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
|
|
||||||
ssl->cfg.timeout_ms = timeout_ms;
|
ssl->cfg.timeout_ms = timeout_ms;
|
||||||
ssl->ssl_initialized = true;
|
ssl->ssl_initialized = true;
|
||||||
@@ -83,9 +83,29 @@ static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||||
|
{
|
||||||
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
|
|
||||||
|
ssl->cfg.timeout_ms = timeout_ms;
|
||||||
|
ssl->cfg.is_plain_tcp = true;
|
||||||
|
ssl->ssl_initialized = true;
|
||||||
|
ssl->tls = esp_tls_init();
|
||||||
|
if (esp_tls_conn_new_sync(host, strlen(host), port, &ssl->cfg, ssl->tls) <= 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open a new connection");
|
||||||
|
esp_transport_set_errors(t, ssl->tls->error_handle);
|
||||||
|
esp_tls_conn_destroy(ssl->tls);
|
||||||
|
ssl->tls = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
|
static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int remain = 0;
|
int remain = 0;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
@@ -114,7 +134,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)
|
static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set writeset;
|
fd_set writeset;
|
||||||
@@ -138,7 +158,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)
|
static int ssl_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
int poll, ret;
|
int poll, ret;
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
|
|
||||||
if ((poll = esp_transport_poll_write(t, timeout_ms)) <= 0) {
|
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);
|
ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->tls->sockfd, timeout_ms);
|
||||||
@@ -155,7 +175,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)
|
static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
int poll, ret;
|
int poll, ret;
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
|
|
||||||
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
||||||
return poll;
|
return poll;
|
||||||
@@ -178,7 +198,7 @@ static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout
|
|||||||
static int ssl_close(esp_transport_handle_t t)
|
static int ssl_close(esp_transport_handle_t t)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (ssl->ssl_initialized) {
|
if (ssl->ssl_initialized) {
|
||||||
ret = esp_tls_conn_destroy(ssl->tls);
|
ret = esp_tls_conn_destroy(ssl->tls);
|
||||||
ssl->conn_state = TRANS_SSL_INIT;
|
ssl->conn_state = TRANS_SSL_INIT;
|
||||||
@@ -189,7 +209,7 @@ static int ssl_close(esp_transport_handle_t t)
|
|||||||
|
|
||||||
static int ssl_destroy(esp_transport_handle_t t)
|
static int ssl_destroy(esp_transport_handle_t t)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
esp_transport_close(t);
|
esp_transport_close(t);
|
||||||
free(ssl);
|
free(ssl);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -197,7 +217,7 @@ static int ssl_destroy(esp_transport_handle_t t)
|
|||||||
|
|
||||||
void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
|
void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.use_global_ca_store = true;
|
ssl->cfg.use_global_ca_store = true;
|
||||||
}
|
}
|
||||||
@@ -205,7 +225,7 @@ void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
|
|||||||
|
|
||||||
void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key)
|
void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.psk_hint_key = psk_hint_key;
|
ssl->cfg.psk_hint_key = psk_hint_key;
|
||||||
}
|
}
|
||||||
@@ -213,7 +233,7 @@ void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint
|
|||||||
|
|
||||||
void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, int len)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.cacert_pem_buf = (void *)data;
|
ssl->cfg.cacert_pem_buf = (void *)data;
|
||||||
ssl->cfg.cacert_pem_bytes = len + 1;
|
ssl->cfg.cacert_pem_bytes = len + 1;
|
||||||
@@ -222,7 +242,7 @@ void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data,
|
|||||||
|
|
||||||
void esp_transport_ssl_set_cert_data_der(esp_transport_handle_t t, const char *data, int len)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.cacert_buf = (void *)data;
|
ssl->cfg.cacert_buf = (void *)data;
|
||||||
ssl->cfg.cacert_bytes = len;
|
ssl->cfg.cacert_bytes = len;
|
||||||
@@ -231,7 +251,7 @@ void esp_transport_ssl_set_cert_data_der(esp_transport_handle_t t, const char *d
|
|||||||
|
|
||||||
void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int 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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.clientcert_pem_buf = (void *)data;
|
ssl->cfg.clientcert_pem_buf = (void *)data;
|
||||||
ssl->cfg.clientcert_pem_bytes = len + 1;
|
ssl->cfg.clientcert_pem_bytes = len + 1;
|
||||||
@@ -240,7 +260,7 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char
|
|||||||
|
|
||||||
void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.clientcert_buf = (void *)data;
|
ssl->cfg.clientcert_buf = (void *)data;
|
||||||
ssl->cfg.clientcert_bytes = len;
|
ssl->cfg.clientcert_bytes = len;
|
||||||
@@ -249,7 +269,7 @@ void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const
|
|||||||
|
|
||||||
void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char *data, int 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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.clientkey_pem_buf = (void *)data;
|
ssl->cfg.clientkey_pem_buf = (void *)data;
|
||||||
ssl->cfg.clientkey_pem_bytes = len + 1;
|
ssl->cfg.clientkey_pem_bytes = len + 1;
|
||||||
@@ -258,7 +278,7 @@ void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char
|
|||||||
|
|
||||||
void esp_transport_ssl_set_client_key_password(esp_transport_handle_t t, const char *password, int password_len)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.clientkey_password = (void *)password;
|
ssl->cfg.clientkey_password = (void *)password;
|
||||||
ssl->cfg.clientkey_password_len = password_len;
|
ssl->cfg.clientkey_password_len = password_len;
|
||||||
@@ -267,7 +287,7 @@ void esp_transport_ssl_set_client_key_password(esp_transport_handle_t t, const c
|
|||||||
|
|
||||||
void esp_transport_ssl_set_client_key_data_der(esp_transport_handle_t t, const char *data, int 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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.clientkey_buf = (void *)data;
|
ssl->cfg.clientkey_buf = (void *)data;
|
||||||
ssl->cfg.clientkey_bytes = len;
|
ssl->cfg.clientkey_bytes = len;
|
||||||
@@ -276,7 +296,7 @@ void esp_transport_ssl_set_client_key_data_der(esp_transport_handle_t t, const c
|
|||||||
|
|
||||||
void esp_transport_ssl_set_alpn_protocol(esp_transport_handle_t t, const char **alpn_protos)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.alpn_protos = alpn_protos;
|
ssl->cfg.alpn_protos = alpn_protos;
|
||||||
}
|
}
|
||||||
@@ -284,7 +304,7 @@ void esp_transport_ssl_set_alpn_protocol(esp_transport_handle_t t, const char **
|
|||||||
|
|
||||||
void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
|
void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.skip_common_name = true;
|
ssl->cfg.skip_common_name = true;
|
||||||
}
|
}
|
||||||
@@ -292,7 +312,7 @@ void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
|
|||||||
|
|
||||||
void esp_transport_ssl_use_secure_element(esp_transport_handle_t t)
|
void esp_transport_ssl_use_secure_element(esp_transport_handle_t t)
|
||||||
{
|
{
|
||||||
transport_ssl_t *ssl = esp_transport_get_context_data(t);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) {
|
||||||
ssl->cfg.use_secure_element = true;
|
ssl->cfg.use_secure_element = true;
|
||||||
}
|
}
|
||||||
@@ -311,8 +331,8 @@ static int ssl_get_socket(esp_transport_handle_t t)
|
|||||||
|
|
||||||
void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data)
|
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);
|
transport_ssl_t *ssl = t->foundation_transport;
|
||||||
if (t && ssl) {
|
if (t && ssl) { // TODO: check t NULL first!
|
||||||
ssl->cfg.ds_data = ds_data;
|
ssl->cfg.ds_data = ds_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,14 +348,25 @@ void esp_transport_ssl_set_keep_alive(esp_transport_handle_t t, esp_transport_ke
|
|||||||
esp_transport_handle_t esp_transport_ssl_init(void)
|
esp_transport_handle_t esp_transport_ssl_init(void)
|
||||||
{
|
{
|
||||||
esp_transport_handle_t t = esp_transport_init();
|
esp_transport_handle_t t = esp_transport_init();
|
||||||
transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t));
|
esp_transport_set_context_data(t, NULL);
|
||||||
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_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);
|
esp_transport_set_async_connect_func(t, ssl_connect_async);
|
||||||
t->_get_socket = ssl_get_socket;
|
t->_get_socket = ssl_get_socket;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct transport_esp_tls* esp_transport_init_foundation(void)
|
||||||
|
{
|
||||||
|
transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t));
|
||||||
|
return ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_transport_handle_t esp_transport_tcp_init(void)
|
||||||
|
{
|
||||||
|
esp_transport_handle_t t = esp_transport_init();
|
||||||
|
esp_transport_set_context_data(t, NULL);
|
||||||
|
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, ssl_connect_async); // TODO: tcp_connect_async()
|
||||||
|
t->_get_socket = ssl_get_socket;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
@@ -1,323 +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"
|
|
||||||
#include "esp_tls_errors.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) {
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME);
|
|
||||||
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));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED);
|
|
||||||
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));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED);
|
|
||||||
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);
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_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));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else if (sockerr) {
|
|
||||||
esp_transport_capture_errno(t, sockerr);
|
|
||||||
ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_FAILED);
|
|
||||||
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));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED);
|
|
||||||
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));
|
|
||||||
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED);
|
|
||||||
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) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
Reference in New Issue
Block a user