mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			336 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			336 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <esp_tls.h>
 | |
| 
 | |
| #include "sys/queue.h"
 | |
| #include "esp_log.h"
 | |
| 
 | |
| #include "esp_transport_internal.h"
 | |
| #include "esp_transport.h"
 | |
| 
 | |
| static const char *TAG = "transport";
 | |
| 
 | |
| /**
 | |
|  * This list will hold all transport available
 | |
|  */
 | |
| STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t);
 | |
| 
 | |
| struct transport_esp_tls;
 | |
| 
 | |
| static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
 | |
| {
 | |
|     /*
 | |
|     * By default, the underlying transport layer handle is the handle itself
 | |
|     */
 | |
|     return t;
 | |
| }
 | |
| 
 | |
| esp_transport_list_handle_t esp_transport_list_init(void)
 | |
| {
 | |
|     esp_transport_list_handle_t transport_list = calloc(1, sizeof(struct esp_transport_list_t));
 | |
|     ESP_TRANSPORT_MEM_CHECK(TAG, transport_list, return NULL);
 | |
|     STAILQ_INIT(transport_list);
 | |
|     return transport_list;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_list_add(esp_transport_list_handle_t h, esp_transport_handle_t t, const char *scheme)
 | |
| {
 | |
|     if (h == NULL || t == NULL) {
 | |
|         return ESP_ERR_INVALID_ARG;
 | |
|     }
 | |
|     t->scheme = calloc(1, strlen(scheme) + 1);
 | |
|     ESP_TRANSPORT_MEM_CHECK(TAG, t->scheme, return ESP_ERR_NO_MEM);
 | |
|     strcpy(t->scheme, scheme);
 | |
|     STAILQ_INSERT_TAIL(h, t, next);
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_transport_handle_t esp_transport_list_get_transport(esp_transport_list_handle_t h, const char *scheme)
 | |
| {
 | |
|     if (!h) {
 | |
|         return NULL;
 | |
|     }
 | |
|     if (scheme == NULL) {
 | |
|         return STAILQ_FIRST(h);
 | |
|     }
 | |
|     esp_transport_handle_t item;
 | |
|     STAILQ_FOREACH(item, h, next) {
 | |
|         if (strcasecmp(item->scheme, scheme) == 0) {
 | |
|             return item;
 | |
|         }
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_list_destroy(esp_transport_list_handle_t h)
 | |
| {
 | |
|     esp_transport_list_clean(h);
 | |
|     free(h);
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_list_clean(esp_transport_list_handle_t h)
 | |
| {
 | |
|     esp_transport_handle_t item = STAILQ_FIRST(h);
 | |
|     esp_transport_handle_t tmp;
 | |
|     while (item != NULL) {
 | |
|         tmp = STAILQ_NEXT(item, next);
 | |
|         esp_transport_destroy(item);
 | |
|         item = tmp;
 | |
|     }
 | |
|     STAILQ_INIT(h);
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_transport_handle_t esp_transport_init(void)
 | |
| {
 | |
|     esp_transport_handle_t transport = calloc(1, sizeof(struct esp_transport_item_t));
 | |
|     ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
 | |
|     return transport;
 | |
| }
 | |
| 
 | |
| esp_transport_handle_t esp_transport_get_payload_transport_handle(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->_read) {
 | |
|         return t->_parent_transfer(t);
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_destroy(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->_destroy) {
 | |
|         t->_destroy(t);
 | |
|     }
 | |
|     if (t && t->scheme) {
 | |
|         free(t->scheme);
 | |
|     }
 | |
|     free(t);
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| int esp_transport_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
 | |
| {
 | |
|     int ret = -1;
 | |
|     if (t && t->_connect) {
 | |
|         return t->_connect(t, host, port, timeout_ms);
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| int esp_transport_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
 | |
| {
 | |
|     int ret = -1;
 | |
|     if (t && t->_connect_async) {
 | |
|         return t->_connect_async(t, host, port, timeout_ms);
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| int esp_transport_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
 | |
| {
 | |
|     if (t && t->_read) {
 | |
|         return t->_read(t, buffer, len, timeout_ms);
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| int esp_transport_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
 | |
| {
 | |
|     if (t && t->_write) {
 | |
|         return t->_write(t, buffer, len, timeout_ms);
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| int esp_transport_poll_read(esp_transport_handle_t t, int timeout_ms)
 | |
| {
 | |
|     if (t && t->_poll_read) {
 | |
|         return t->_poll_read(t, timeout_ms);
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| int esp_transport_poll_write(esp_transport_handle_t t, int timeout_ms)
 | |
| {
 | |
|     if (t && t->_poll_write) {
 | |
|         return t->_poll_write(t, timeout_ms);
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| int esp_transport_close(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->_close) {
 | |
|         return t->_close(t);
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void *esp_transport_get_context_data(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t) {
 | |
|         return t->data;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_set_context_data(esp_transport_handle_t t, void *data)
 | |
| {
 | |
|     if (t) {
 | |
|         t->data = data;
 | |
|         return ESP_OK;
 | |
|     }
 | |
|     return ESP_FAIL;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_set_func(esp_transport_handle_t t,
 | |
|                              connect_func _connect,
 | |
|                              io_read_func _read,
 | |
|                              io_func _write,
 | |
|                              trans_func _close,
 | |
|                              poll_func _poll_read,
 | |
|                              poll_func _poll_write,
 | |
|                              trans_func _destroy)
 | |
| {
 | |
|     if (t == NULL) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     t->_connect = _connect;
 | |
|     t->_read = _read;
 | |
|     t->_write = _write;
 | |
|     t->_close = _close;
 | |
|     t->_poll_read = _poll_read;
 | |
|     t->_poll_write = _poll_write;
 | |
|     t->_destroy = _destroy;
 | |
|     t->_connect_async = NULL;
 | |
|     t->_parent_transfer = esp_transport_get_default_parent;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| int esp_transport_get_default_port(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t == NULL) {
 | |
|         return -1;
 | |
|     }
 | |
|     return t->port;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_set_default_port(esp_transport_handle_t t, int port)
 | |
| {
 | |
|     if (t == NULL) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     t->port = port;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_set_async_connect_func(esp_transport_handle_t t, connect_async_func _connect_async_func)
 | |
| {
 | |
|     if (t == NULL) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     t->_connect_async = _connect_async_func;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payload_transfer_func _parent_transport)
 | |
| {
 | |
|     if (t == NULL) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     t->_parent_transfer = _parent_transport;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->foundation && t->foundation->error_handle) {
 | |
|         return &t->foundation->error_handle->esp_tls_err_h_base;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| int esp_transport_get_errno(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->foundation && t->foundation->error_handle) {
 | |
|         int actual_errno = t->foundation->error_handle->sock_errno;
 | |
|         t->foundation->error_handle->sock_errno = 0;
 | |
|         return actual_errno;
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| void capture_tcp_transport_error(esp_transport_handle_t t, enum esp_tcp_transport_err_t error)
 | |
| {
 | |
|     esp_tls_last_error_t *err_handle = esp_transport_get_error_handle(t);
 | |
|     switch (error) {
 | |
|         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_TIMEOUT:
 | |
|             err_handle->last_error = ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT;
 | |
|             break;
 | |
|         case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
 | |
|             err_handle->last_error = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
 | |
|             break;
 | |
|         case ERR_TCP_TRANSPORT_NO_MEM:
 | |
|             err_handle->last_error = ESP_ERR_NO_MEM;
 | |
|             break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle)
 | |
| {
 | |
|     if (t && t->foundation && t->foundation->error_handle) {
 | |
|         memcpy(&t->foundation->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->foundation->error_handle->sock_errno = sock_error;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno)
 | |
| {
 | |
|     if (t && t->foundation && t->foundation->error_handle) {
 | |
|         t->foundation->error_handle->sock_errno = sock_errno;
 | |
|     }
 | |
| }
 | |
| 
 | |
| int esp_transport_get_socket(esp_transport_handle_t t)
 | |
| {
 | |
|     if (t && t->_get_socket)  {
 | |
|         return  t->_get_socket(t);
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| esp_err_t esp_transport_translate_error(enum esp_tcp_transport_err_t error)
 | |
| {
 | |
|     esp_err_t err = ESP_FAIL;
 | |
|     switch (error) {
 | |
|         case ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN:
 | |
|             err = ESP_ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN;
 | |
|             break;
 | |
|         case ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT:
 | |
|             err = ESP_ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
 | |
|             break;
 | |
|         case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
 | |
|             err = ESP_ERR_TCP_TRANSPORT_CONNECTION_FAILED;
 | |
|             break;
 | |
|         case ERR_TCP_TRANSPORT_NO_MEM:
 | |
|             err = ESP_ERR_TCP_TRANSPORT_NO_MEM;
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     return err;
 | |
| }
 | 
