Commit baf849bf authored by Franco (nextime) Lanza's avatar Franco (nextime) Lanza

Merge branch 'certificate_chain' into 'master'

Certificate chain

See merge request !1
parents 711bf969 24d7b83d
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h" #include "mbedtls/error.h"
#include "mbedtls/certs.h" #include "mbedtls/certs.h"
#include "mbedtls/ssl_ticket.h"
#if defined(MBEDTLS_SSL_CACHE_C) #if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h" #include "mbedtls/ssl_cache.h"
...@@ -110,10 +111,10 @@ struct http_context_ { ...@@ -110,10 +111,10 @@ struct http_context_ {
}; };
struct http_server_context_ { struct http_server_context_ {
int port; int port;
err_t server_task_err;
TaskHandle_t task; TaskHandle_t task;
EventGroupHandle_t start_done; EventGroupHandle_t start_done;
err_t server_task_err;
SLIST_HEAD(, http_handler_t) handlers; SLIST_HEAD(, http_handler_t) handlers;
_lock_t handlers_lock; _lock_t handlers_lock;
struct http_context_ connection_context; struct http_context_ connection_context;
...@@ -125,13 +126,15 @@ struct http_server_context_ { ...@@ -125,13 +126,15 @@ struct http_server_context_ {
mbedtls_x509_crt *srvcert; mbedtls_x509_crt *srvcert;
mbedtls_pk_context *pkey; mbedtls_pk_context *pkey;
mbedtls_ssl_cache_context *cache; mbedtls_ssl_cache_context *cache;
mbedtls_ssl_ticket_context *ticket_ctx;
#else #else
struct netconn* server_conn; struct netconn* server_conn;
#endif #endif
}; };
#define SERVER_STARTED_BIT BIT(0) #define SERVER_STARTED_BIT BIT(0)
#define SERVER_DONE_BIT BIT(1) #define SERVER_DONE_BIT BIT(1)
#define SERVER_ERR_NO_MEM BIT(2)
static const char* http_response_code_to_str(int code); static const char* http_response_code_to_str(int code);
...@@ -139,24 +142,6 @@ static esp_err_t add_keyval_pair(http_header_list_t *list, const char* name, con ...@@ -139,24 +142,6 @@ static esp_err_t add_keyval_pair(http_header_list_t *list, const char* name, con
static const char* TAG = "http_server"; static const char* TAG = "http_server";
const static char index_html[] = "<!DOCTYPE html>"
"<html>\n"
"<head>\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
" <style type=\"text/css\">\n"
" html, body, iframe { margin: 0; padding: 0; height: 100%; }\n"
" iframe { display: block; width: 100%; border: none; }\n"
" </style>\n"
"<title>HELLO ESP32</title>\n"
"</head>\n"
"<body>\n"
"<h1>Hello World, from ESP32!</h1>\n"
"</body>\n"
"</html>\n";
const static char response_OK[] =
"OK!\n";
esp_err_t http_register_handler(http_server_t server, esp_err_t http_register_handler(http_server_t server,
const char* uri_pattern, int method, const char* uri_pattern, int method,
...@@ -879,11 +864,11 @@ static void http_handle_connection(http_server_t server, void *arg_conn) ...@@ -879,11 +864,11 @@ static void http_handle_connection(http_server_t server, void *arg_conn)
if (ret > 0) { if (ret > 0) {
ctx->state = HTTP_COLLECTING_RESPONSE_HEADERS; ctx->state = HTTP_COLLECTING_RESPONSE_HEADERS;
if (ctx->handler == NULL) { if (ctx->handler == NULL) {
ESP_LOGD(TAG, "No registered Handler!") ESP_LOGD(TAG, "No registered Handler!");
http_send_not_found_response(ctx); http_send_not_found_response(ctx);
} else { } else {
ESP_LOGD(TAG, "Registered Handler Found!") ESP_LOGD(TAG, "Registered Handler Found!");
invoke_handler(ctx, HTTP_HANDLE_RESPONSE); invoke_handler(ctx, HTTP_HANDLE_RESPONSE);
} }
} }
...@@ -891,10 +876,10 @@ static void http_handle_connection(http_server_t server, void *arg_conn) ...@@ -891,10 +876,10 @@ static void http_handle_connection(http_server_t server, void *arg_conn)
if (err == ERR_OK) { if (err == ERR_OK) {
ctx->state = HTTP_COLLECTING_RESPONSE_HEADERS; ctx->state = HTTP_COLLECTING_RESPONSE_HEADERS;
if (ctx->handler == NULL) { if (ctx->handler == NULL) {
ESP_LOGD(TAG, "No registered Handler!") ESP_LOGD(TAG, "No registered Handler!");
http_send_not_found_response(ctx); http_send_not_found_response(ctx);
} else { } else {
ESP_LOGD(TAG, "Registered Handler Found!") ESP_LOGD(TAG, "Registered Handler Found!");
invoke_handler(ctx, HTTP_HANDLE_RESPONSE); invoke_handler(ctx, HTTP_HANDLE_RESPONSE);
} }
} }
...@@ -933,274 +918,338 @@ static void http_handle_connection(http_server_t server, void *arg_conn) ...@@ -933,274 +918,338 @@ static void http_handle_connection(http_server_t server, void *arg_conn)
static void http_server(void *arg) static void http_server(void *arg)
{ {
uint8_t bits;
http_server_t ctx = (http_server_t) arg; http_server_t ctx = (http_server_t) arg;
#ifdef HTTPS_SERVER do{
char *error_buf; ESP_LOGV(TAG, "Checking Server Status...");
ESP_LOGV(TAG, "Declaring local mbedTLS context on task..."); bits = xEventGroupWaitBits(ctx->start_done, SERVER_STARTED_BIT | SERVER_DONE_BIT, 0, pdTRUE, 1000 / portTICK_PERIOD_MS);
int ret;
mbedtls_net_context listen_fd; //If server had already been successfully started but it has crashed,
mbedtls_entropy_context entropy; if ((bits & SERVER_STARTED_BIT) && (bits & SERVER_DONE_BIT)) {
mbedtls_ctr_drbg_context ctr_drbg; ESP_LOGE(TAG, "Server has closed. Restarting server...");
mbedtls_ssl_context ssl_conn; xEventGroupClearBits(ctx->start_done, SERVER_STARTED_BIT | SERVER_DONE_BIT);
mbedtls_ssl_config conf; memset(&(ctx->connection_context), 0, sizeof(*ctx) - (size_t)((int)&(ctx->connection_context) - (int)ctx) );
mbedtls_x509_crt srvcert; bits = pdFALSE;
mbedtls_pk_context pkey; }
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache; //If server has not successfully been started yet,
(ctx->cache) = &cache; if (!(bits & SERVER_STARTED_BIT)) {
#endif #ifdef HTTPS_SERVER
(ctx->listen_fd) = &listen_fd; char *error_buf;
(ctx->entropy) = &entropy; ESP_LOGV(TAG, "Declaring local mbedTLS context on task...");
(ctx->ctr_drbg) = &ctr_drbg; int ret;
(ctx->connection_context.ssl_conn) = &ssl_conn; mbedtls_net_context listen_fd;
(ctx->conf) = &conf; mbedtls_net_context client_fd;
(ctx->srvcert) = &srvcert; mbedtls_entropy_context entropy;
(ctx->pkey) = &pkey; mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl_conn;
ESP_LOGV(TAG, "Reading CA certificate......"); mbedtls_ssl_config conf;
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); mbedtls_x509_crt srvcert;
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); mbedtls_pk_context pkey;
const unsigned int cacert_pem_bytes = cacert_pem_end - cacert_pem_start; #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache;
ESP_LOGV(TAG, "Reading Private Key......"); (ctx->cache) = &cache;
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); #endif
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); #if defined(MBEDTLS_SSL_SESSION_TICKETS)
const unsigned int prvtkey_pem_bytes = prvtkey_pem_end - prvtkey_pem_start; mbedtls_ssl_ticket_context ticket_ctx;
(ctx->ticket_ctx) = &ticket_ctx;
ESP_LOGV(TAG, "Setting mbedTLS context......"); #endif
mbedtls_net_init( ctx->listen_fd ); (ctx->listen_fd) = &listen_fd;
ESP_LOGV(TAG, "OK"); (ctx->connection_context.client_fd) = &client_fd;
(ctx->entropy) = &entropy;
ESP_LOGV(TAG, "SSL server context create ......"); (ctx->ctr_drbg) = &ctr_drbg;
mbedtls_ssl_init( ctx->connection_context.ssl_conn ); (ctx->connection_context.ssl_conn) = &ssl_conn;
ESP_LOGV(TAG, "OK"); (ctx->conf) = &conf;
(ctx->srvcert) = &srvcert;
ESP_LOGV(TAG, "SSL conf context create ......"); (ctx->pkey) = &pkey;
mbedtls_ssl_config_init( ctx->conf );
ESP_LOGV(TAG, "OK"); ESP_LOGV(TAG, "Reading Root CA certificate......");
extern const unsigned char rootcacert_pem_start[] asm("_binary_rootcacert_pem_start");
extern const unsigned char rootcacert_pem_end[] asm("_binary_rootcacert_pem_end");
const unsigned int rootcacert_pem_bytes = rootcacert_pem_end - rootcacert_pem_start;
ESP_LOGV(TAG, "Reading Intermediate CA certificate......");
extern const unsigned char intermediatecacert_pem_start[] asm("_binary_intermediatecacert_pem_start");
extern const unsigned char intermediatecacert_pem_end[] asm("_binary_intermediatecacert_pem_end");
const unsigned int intermediatecacert_pem_bytes = intermediatecacert_pem_end - intermediatecacert_pem_start;
ESP_LOGV(TAG, "Reading Server certificate......");
extern const unsigned char servercert_pem_start[] asm("_binary_servercert_pem_start");
extern const unsigned char servercert_pem_end[] asm("_binary_servercert_pem_end");
const unsigned int servercert_pem_bytes = servercert_pem_end - servercert_pem_start;
ESP_LOGV(TAG, "Reading Server Private Key......");
extern const unsigned char serverprvtkey_pem_start[] asm("_binary_serverprvtkey_pem_start");
extern const unsigned char serverprvtkey_pem_end[] asm("_binary_serverprvtkey_pem_end");
const unsigned int serverprvtkey_pem_bytes = serverprvtkey_pem_end - serverprvtkey_pem_start;
ESP_LOGV(TAG, "Setting server_fd......");
mbedtls_net_init( ctx->listen_fd );
ESP_LOGV(TAG, "OK");
ESP_LOGV(TAG, "Setting client fd......");
mbedtls_net_init( ctx->connection_context.client_fd );
ESP_LOGV(TAG, "OK");
ESP_LOGV(TAG, "SSL server context create ......");
mbedtls_ssl_init( ctx->connection_context.ssl_conn );
ESP_LOGV(TAG, "OK");
ESP_LOGV(TAG, "SSL conf context create ......");
mbedtls_ssl_config_init( ctx->conf );
ESP_LOGV(TAG, "OK");
#if defined(MBEDTLS_SSL_CACHE_C) #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_init( &cache ); mbedtls_ssl_cache_init( ctx->cache );
#endif #endif
mbedtls_x509_crt_init( ctx->srvcert ); #if defined(MBEDTLS_SSL_SESSION_TICKETS)
mbedtls_pk_init( ctx->pkey ); mbedtls_ssl_ticket_init( ctx->ticket_ctx );
mbedtls_entropy_init( ctx->entropy ); #endif
mbedtls_ctr_drbg_init( ctx->ctr_drbg ); mbedtls_x509_crt_init( ctx->srvcert );
mbedtls_pk_init( ctx->pkey );
/* mbedtls_entropy_init( ctx->entropy );
* 1. Load the certificates and private RSA key mbedtls_ctr_drbg_init( ctx->ctr_drbg );
*/
ESP_LOGD(TAG, "Loading the server cert. and key..." ); /*
/* * 1. Load the certificates and private RSA key
* This demonstration program uses embedded test certificates. */
* Instead, you may want to use mbedtls_x509_crt_parse_file() to read the ESP_LOGD(TAG, "Loading the server cert. and key..." );
* server and CA certificates, as well as mbedtls_pk_parse_keyfile(). /*
*/ * This demonstration program uses embedded test certificates.
ESP_LOGV(TAG, "SSL server context set own certification......"); * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the
ESP_LOGV(TAG, "Parsing test srv_crt......"); * server and CA certificates, as well as mbedtls_pk_parse_keyfile().
ret = mbedtls_x509_crt_parse( ctx->srvcert, (const unsigned char *) cacert_pem_start, */
cacert_pem_bytes ); ESP_LOGV(TAG, "SSL server context set own certification......");
if( ret != ERR_OK ) ESP_LOGV(TAG, "Parsing test srv_crt......");
{ ret = mbedtls_x509_crt_parse( ctx->srvcert, (const unsigned char *) servercert_pem_start,
ESP_LOGE(TAG, "ERROR: mbedtls_x509_crt_parse returned %d", ret ); servercert_pem_bytes );
goto exit; if( ret != ERR_OK )
} {
ESP_LOGV(TAG, "OK"); ESP_LOGE(TAG, "ERROR: mbedtls_x509_crt_parse returned %d", ret );
goto exit;
ESP_LOGV(TAG, "SSL server context set private key......"); }
ret = mbedtls_pk_parse_key( ctx->pkey, (const unsigned char *) prvtkey_pem_start, ESP_LOGV(TAG, "OK");
prvtkey_pem_bytes, NULL, 0 );
if( ret != ERR_OK )
{
ESP_LOGE(TAG, "ERROR: mbedtls_pk_parse_key returned %d", ret );
goto exit;
}
ESP_LOGV(TAG, "OK");
/* ESP_LOGV(TAG, "Parsing Intermediate CA crt......");
* 3. Seed the RNG ret = mbedtls_x509_crt_parse( ctx->srvcert, (const unsigned char *) intermediatecacert_pem_start,
*/ intermediatecacert_pem_bytes );
ESP_LOGV(TAG, "Seeding the random number generator..." ); if( ret != ERR_OK )
if( ( ret = mbedtls_ctr_drbg_seed( ctx->ctr_drbg, mbedtls_entropy_func, ctx->entropy, {
(const unsigned char *) TAG, ESP_LOGE(TAG, "ERROR: mbedtls_x509_crt_parse returned %d", ret );
strlen( TAG ) ) ) != 0 ) goto exit;
{ }
ESP_LOGE(TAG, "ERROR: mbedtls_ctr_drbg_seed returned %d", ret ); ESP_LOGV(TAG, "OK");
goto exit;
}
ESP_LOGV(TAG, "OK");
/* ESP_LOGV(TAG, "Parsing Root CA crt......");
* 2. Setup the listening TCP socket ret = mbedtls_x509_crt_parse( ctx->srvcert, (const unsigned char *) rootcacert_pem_start,
*/ rootcacert_pem_bytes );
char *port = malloc(sizeof(char) * 6); if( ret != ERR_OK )
ESP_LOGV(TAG, "SSL server socket bind at localhost: %s ......", itoa(ctx->port, port,10)); {
if( ( ret = mbedtls_net_bind( ctx->listen_fd, NULL, itoa(ctx->port, port,10), MBEDTLS_NET_PROTO_TCP ) ) != 0 ) ESP_LOGE(TAG, "ERROR: mbedtls_x509_crt_parse returned %d", ret );
{ goto exit;
ESP_LOGE(TAG, "ERROR: mbedtls_net_bind returned %d", ret ); }
goto exit; ESP_LOGV(TAG, "OK");
}
free(port);
ESP_LOGV(TAG, "OK");
/* ESP_LOGV(TAG, "SSL server context set private key......");
* 4. Setup stuff ret = mbedtls_pk_parse_key( ctx->pkey, (const unsigned char *) serverprvtkey_pem_start,
*/ serverprvtkey_pem_bytes, NULL, 0 );
ESP_LOGV(TAG, "Setting up the SSL conf data...." ); if( ret != ERR_OK )
#ifdef CONFIG_MBEDTLS_DEBUG {
mbedtls_esp_enable_debug_log(ctx->conf, 4); ESP_LOGE(TAG, "ERROR: mbedtls_pk_parse_key returned %d", ret );
#endif goto exit;
if( ( ret = mbedtls_ssl_config_defaults( ctx->conf, }
MBEDTLS_SSL_IS_SERVER, ESP_LOGV(TAG, "OK");
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) /*
{ * 3. Seed the RNG
ESP_LOGE(TAG, "ERROR: mbedtls_ssl_config_defaults returned %d", ret ); */
goto exit; ESP_LOGV(TAG, "Seeding the random number generator..." );
} if( ( ret = mbedtls_ctr_drbg_seed( ctx->ctr_drbg, mbedtls_entropy_func, ctx->entropy,
(const unsigned char *) TAG,
strlen( TAG ) ) ) != 0 )
{
ESP_LOGE(TAG, "ERROR: mbedtls_ctr_drbg_seed returned %d", ret );
goto exit;
}
ESP_LOGV(TAG, "OK");
/*
* 2. Setup the listening TCP socket
*/
char *port = malloc(sizeof(char) * 6);
ESP_LOGV(TAG, "SSL server socket bind at localhost: %s ......", itoa(ctx->port, port,10));
if( ( ret = mbedtls_net_bind( ctx->listen_fd, NULL, itoa(ctx->port, port,10), MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
ESP_LOGE(TAG, "ERROR: mbedtls_net_bind returned %d", ret );
goto exit;
}
free(port);
ESP_LOGV(TAG, "OK");
/*
* 4. Setup stuff
*/
ESP_LOGV(TAG, "Setting up the SSL conf data...." );
#ifdef CONFIG_MBEDTLS_DEBUG
mbedtls_esp_enable_debug_log(ctx->conf, 4);
#endif
if( ( ret = mbedtls_ssl_config_defaults( ctx->conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
ESP_LOGE(TAG, "ERROR: mbedtls_ssl_config_defaults returned %d", ret );
goto exit;
}
mbedtls_ssl_conf_rng( ctx->conf, mbedtls_ctr_drbg_random, ctx->ctr_drbg ); mbedtls_ssl_conf_rng( ctx->conf, mbedtls_ctr_drbg_random, ctx->ctr_drbg );
#if defined(MBEDTLS_SSL_CACHE_C) #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_conf_session_cache( ctx->conf, ctx->cache, mbedtls_ssl_conf_session_cache( ctx->conf, ctx->cache,
mbedtls_ssl_cache_get, mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set ); mbedtls_ssl_cache_set );
#endif #endif
mbedtls_ssl_conf_ca_chain( ctx->conf, (*ctx->srvcert).next, NULL ); ESP_LOGV(TAG, "Setting up the SSL Session Tickets...." );
if( ( ret = mbedtls_ssl_conf_own_cert( ctx->conf, ctx->srvcert, ctx->pkey ) ) != 0 ) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
{ if( ( ret = mbedtls_ssl_ticket_setup( ctx->ticket_ctx ,
ESP_LOGE(TAG, "ERROR: mbedtls_ssl_conf_own_cert returned %d", ret ); mbedtls_ctr_drbg_random, &ctr_drbg,
goto exit; MBEDTLS_CIPHER_AES_256_GCM,
} 86400 ) ) != 0 )
{
if( ( ret = mbedtls_ssl_setup( ctx->connection_context.ssl_conn, ctx->conf ) ) != 0 ) ESP_LOGE(TAG, "ERROR: mbedtls_ssl_ticket_setup returned %d", ret );
{ goto exit;
ESP_LOGE(TAG, "ERROR: mbedtls_ssl_setup returned %d", ret ); }
goto exit;
}
ESP_LOGV(TAG, "OK");
xEventGroupSetBits(ctx->start_done, SERVER_STARTED_BIT);
reset:
ESP_LOGI(TAG, "mbedTLS HTTPS server is running! Waiting for new connection...");
do {
mbedtls_net_context client_fd;
(ctx->connection_context.client_fd) = &client_fd;
mbedtls_net_init( ctx->connection_context.client_fd );
#ifdef MBEDTLS_ERROR_C mbedtls_ssl_conf_session_tickets_cb( &conf,
if( ret != ERR_OK ) mbedtls_ssl_ticket_write,
{ mbedtls_ssl_ticket_parse,
error_buf = malloc(sizeof(char)*ERROR_BUF_LENGTH); ctx->ticket_ctx );
mbedtls_strerror( ctx->server_task_err, error_buf, sizeof(char)*ERROR_BUF_LENGTH );
ESP_LOGE(TAG, "Error %d: %s", ret, error_buf );
free(error_buf);
}
#endif #endif
mbedtls_net_free( ctx->connection_context.client_fd ); mbedtls_ssl_conf_ca_chain( ctx->conf, (*ctx->srvcert).next, NULL );
if( ( ret = mbedtls_ssl_conf_own_cert( ctx->conf, ctx->srvcert, ctx->pkey ) ) != 0 )
mbedtls_ssl_session_reset( ctx->connection_context.ssl_conn );
/*
* 3. Wait until a client connects
*/
ESP_LOGV(TAG, "Wait until a client connects..." );
if( ( ret = mbedtls_net_accept( ctx->listen_fd, ctx->connection_context.client_fd,
NULL, 0, NULL ) ) != 0 )
{
ESP_LOGE(TAG, "ERROR: mbedtls_net_accept returned %d", ret );
goto exit;
}
mbedtls_ssl_set_bio( ctx->connection_context.ssl_conn, ctx->connection_context.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
ESP_LOGV(TAG, "OK");
/*
* 5. Handshake
*/
ESP_LOGV(TAG, "Performing the SSL/TLS handshake..." );
while( ( ret = mbedtls_ssl_handshake( ctx->connection_context.ssl_conn ) ) != ERR_OK )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{ {
ESP_LOGE(TAG, "ERROR: bedtls_ssl_handshake returned %d", ret ); ESP_LOGE(TAG, "ERROR: mbedtls_ssl_conf_own_cert returned %d", ret );
goto reset; goto exit;
} }
}
ESP_LOGV(TAG, "OK");
ESP_LOGV(TAG, "Handling connection..." ); if( ( ret = mbedtls_ssl_setup( ctx->connection_context.ssl_conn, ctx->conf ) ) != 0 )
if (ret == ERR_OK) { {
http_handle_connection(ctx, NULL); ESP_LOGE(TAG, "ERROR: mbedtls_ssl_setup returned %d", ret );
} goto exit;
ESP_LOGV(TAG, "OK"); }
} while (ret == ERR_OK); ESP_LOGV(TAG, "OK");
exit: xEventGroupSetBits(ctx->start_done, SERVER_STARTED_BIT);
if (ret != ERR_OK) { reset:
error_buf = malloc(sizeof(char)*ERROR_BUF_LENGTH); ESP_LOGI(TAG, "mbedTLS HTTPS server is running! Waiting for new connection...");
mbedtls_strerror( ctx->server_task_err, error_buf, sizeof(char)*ERROR_BUF_LENGTH ); do {
ESP_LOGE(TAG, "Error %d: %s", ret, error_buf ); mbedtls_net_free( ctx->connection_context.client_fd );
free(error_buf);
ctx->server_task_err = ret; mbedtls_ssl_session_reset( ctx->connection_context.ssl_conn );
xEventGroupSetBits(ctx->start_done, SERVER_DONE_BIT); /*
} * 3. Wait until a client connects
*/
ESP_LOGV(TAG, "Wait until a client connects..." );
if( ( ret = mbedtls_net_accept( ctx->listen_fd, ctx->connection_context.client_fd,
NULL, 0, NULL ) ) != 0 )
{
ESP_LOGE(TAG, "ERROR: mbedtls_net_accept returned %d", ret );
goto exit;
}
mbedtls_ssl_set_bio( ctx->connection_context.ssl_conn, ctx->connection_context.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
ESP_LOGV(TAG, "OK");
/*
* 5. Handshake
*/
ESP_LOGV(TAG, "Performing the SSL/TLS handshake..." );
while( ( ret = mbedtls_ssl_handshake( ctx->connection_context.ssl_conn ) ) != ERR_OK )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
ESP_LOGE(TAG, "ERROR: bedtls_ssl_handshake returned %d", ret );
goto reset;
}
}
ESP_LOGV(TAG, "OK");
ESP_LOGV(TAG, "Handling connection..." );
if (ret == ERR_OK) {
http_handle_connection(ctx, NULL);
}
ESP_LOGV(TAG, "OK");
} while (ret == ERR_OK);
exit:
if (ret != ERR_OK) {
error_buf = malloc(sizeof(char)*ERROR_BUF_LENGTH);
mbedtls_strerror( ret, error_buf, sizeof(char)*ERROR_BUF_LENGTH );
ESP_LOGE(TAG, "Error %d: %s", ret, error_buf );
free(error_buf);
//Set SERVER_DONE_BIT and save error at http_server_t struct
ctx->server_task_err = ret;
xEventGroupSetBits(ctx->start_done, SERVER_DONE_BIT);
}
mbedtls_net_free( ctx->connection_context.client_fd ); mbedtls_net_free( ctx->connection_context.client_fd );
mbedtls_net_free( ctx->listen_fd ); mbedtls_net_free( ctx->listen_fd );
mbedtls_x509_crt_free( ctx->srvcert ); mbedtls_x509_crt_free( ctx->srvcert );
mbedtls_pk_free( ctx->pkey ); mbedtls_pk_free( ctx->pkey );
mbedtls_ssl_free( ctx->connection_context.ssl_conn ); mbedtls_ssl_free( ctx->connection_context.ssl_conn );
mbedtls_ssl_config_free( ctx->conf ); mbedtls_ssl_config_free( ctx->conf );
#if defined(MBEDTLS_SSL_CACHE_C) #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_free( ctx->cache ); mbedtls_ssl_cache_free( ctx->cache );
#endif #endif
mbedtls_ctr_drbg_free( ctx->ctr_drbg ); #if defined(MBEDTLS_SSL_SESSION_TICKETS)
mbedtls_entropy_free( ctx->entropy ); mbedtls_ssl_ticket_free( ctx->ticket_ctx );
#endif
ESP_LOGE(TAG, "Closing Task"); mbedtls_ctr_drbg_free( ctx->ctr_drbg );
vTaskDelete(NULL); mbedtls_entropy_free( ctx->entropy );
#else #else
struct netconn *client_conn; struct netconn *client_conn;
err_t err; err_t err;
ctx->server_conn = netconn_new(NETCONN_TCP); ctx->server_conn = netconn_new(NETCONN_TCP);
if (ctx->server_conn == NULL) { if (ctx->server_conn == NULL) {
err = ERR_MEM; err = ERR_MEM;
goto out; goto out;
} }
err = netconn_bind(ctx->server_conn, NULL, ctx->port);
if (err != ERR_OK) {
goto out;
}
err = netconn_listen(ctx->server_conn); err = netconn_bind(ctx->server_conn, NULL, ctx->port);
if (err != ERR_OK) { if (err != ERR_OK) {
goto out; goto out;
} }
xEventGroupSetBits(ctx->start_done, SERVER_STARTED_BIT);
do { err = netconn_listen(ctx->server_conn);
err = netconn_accept(ctx->server_conn, &client_conn); if (err != ERR_OK) {
if (err == ERR_OK) { goto out;
http_handle_connection(ctx, client_conn); }
netconn_delete(client_conn); xEventGroupSetBits(ctx->start_done, SERVER_STARTED_BIT);
}
} while (err == ERR_OK); do {
out: err = netconn_accept(ctx->server_conn, &client_conn);
if (ctx->server_conn) { if (err == ERR_OK) {
netconn_close(ctx->server_conn); http_handle_connection(ctx, client_conn);
netconn_delete(ctx->server_conn); netconn_delete(client_conn);
} }
if (err != ERR_OK) { } while (err == ERR_OK);
ctx->server_task_err = err; out:
xEventGroupSetBits(ctx->start_done, SERVER_DONE_BIT); if (ctx->server_conn) {
} netconn_close(ctx->server_conn);
vTaskDelete(NULL); netconn_delete(ctx->server_conn);
#endif }
if (err != ERR_OK) {
ctx->server_task_err = err;
xEventGroupSetBits(ctx->start_done, SERVER_DONE_BIT);
}
vTaskDelete(NULL);
#endif
}
}while(1);
} }
esp_err_t http_server_start(const http_server_options_t* options, http_server_t* out_server) esp_err_t http_server_start(const http_server_options_t* options, http_server_t* out_server)
...@@ -1217,38 +1266,26 @@ esp_err_t http_server_start(const http_server_options_t* options, http_server_t* ...@@ -1217,38 +1266,26 @@ esp_err_t http_server_start(const http_server_options_t* options, http_server_t*
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
//Start http_server task if it had not been started before
ESP_LOGV(TAG, "Creating http_server task..."); ESP_LOGV(TAG, "Creating http_server task...");
int ret = xTaskCreatePinnedToCore(&http_server, "httpd", int ret = xTaskCreatePinnedToCore(&http_server, "http_server",
options->task_stack_size, ctx, options->task_stack_size, ctx,
options->task_priority, options->task_priority,
&ctx->task, &ctx->task,
options->task_affinity); options->task_affinity);
if (ret != pdPASS) { if (ret != pdPASS) {
vEventGroupDelete(ctx->start_done); vEventGroupDelete(ctx->start_done);
free(ctx); free(ctx);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
ESP_LOGI(TAG, "Task has been created!"); ESP_LOGI(TAG, "http_server task has been created!");
//Check server status by checking SERVER_STARTED_BIT (it server has been succesfully started) or SERVER_DONE_BIT (if it has crashed)
ESP_LOGV(TAG, "Checking server status..."); ESP_LOGV(TAG, "Checking server status...");
int bits = xEventGroupWaitBits(ctx->start_done, SERVER_STARTED_BIT | SERVER_DONE_BIT, 0, 0, portMAX_DELAY); xEventGroupWaitBits(ctx->start_done, SERVER_STARTED_BIT, 0, 0, portMAX_DELAY);
if (bits & SERVER_DONE_BIT) {
ESP_LOGE(TAG, "SERVER_DONE_BIT Error...");
#ifdef HTTPS_SERVER
char *error_buf = malloc(sizeof(char)*ERROR_BUF_LENGTH);
mbedtls_strerror( ctx->server_task_err, error_buf, 100 );
ESP_LOGE(TAG, "Error %d: %s", ret, error_buf );
free(error_buf);
#endif
esp_err_t err = lwip_err_to_esp_err(ctx->server_task_err);
vEventGroupDelete(ctx->start_done);
free(ctx);
return err;
}
ESP_LOGI(TAG, "Server started!"); ESP_LOGI(TAG, "Server started!");
*out_server = ctx; *out_server = ctx;
return ESP_OK; return ESP_OK;
} }
esp_err_t http_server_stop(http_server_t server) esp_err_t http_server_stop(http_server_t server)
......
...@@ -81,6 +81,24 @@ typedef struct { ...@@ -81,6 +81,24 @@ typedef struct {
.task_priority = 8, \ .task_priority = 8, \
} }
const static char index_html[] = "<!DOCTYPE html>"
"<html>\n"
"<head>\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
" <style type=\"text/css\">\n"
" html, body, iframe { margin: 0; padding: 0; height: 100%; }\n"
" iframe { display: block; width: 100%; border: none; }\n"
" </style>\n"
"<title>HELLO ESP32</title>\n"
"</head>\n"
"<body>\n"
"<h1>Hello World, from ESP32!</h1>\n"
"</body>\n"
"</html>\n";
const static char response_OK[] =
"OK!\n";
/** /**
* @brief initialize HTTP server, start listening * @brief initialize HTTP server, start listening
* @param options pointer to http server options, can point to a temporary * @param options pointer to http server options, can point to a temporary
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment