mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
194 lines
6.0 KiB
C
194 lines
6.0 KiB
C
/* Simple HTTP + SSL Server Example
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
|
|
#include <esp_wifi.h>
|
|
#include <esp_event.h>
|
|
#include <esp_log.h>
|
|
#include <esp_system.h>
|
|
#include <nvs_flash.h>
|
|
#include <sys/param.h>
|
|
#include "esp_netif.h"
|
|
#include "esp_eth.h"
|
|
#include "protocol_examples_common.h"
|
|
|
|
#include <esp_https_server.h>
|
|
#include "esp_tls.h"
|
|
|
|
/* A simple example that demonstrates how to create GET and POST
|
|
* handlers and start an HTTPS server.
|
|
*/
|
|
|
|
static const char *TAG = "example";
|
|
|
|
/* An HTTP GET handler */
|
|
static esp_err_t root_get_handler(httpd_req_t *req)
|
|
{
|
|
httpd_resp_set_type(req, "text/html");
|
|
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
#if CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK
|
|
|
|
static void print_peer_cert_info(const mbedtls_ssl_context *ssl)
|
|
{
|
|
const mbedtls_x509_crt *cert;
|
|
const size_t buf_size = 1024;
|
|
char *buf = calloc(buf_size, sizeof(char));
|
|
if (buf == NULL) {
|
|
ESP_LOGE(TAG, "Out of memory - Callback execution failed!");
|
|
return;
|
|
}
|
|
|
|
// Logging the peer certificate info
|
|
cert = mbedtls_ssl_get_peer_cert(ssl);
|
|
if (cert != NULL) {
|
|
mbedtls_x509_crt_info((char *) buf, buf_size - 1, " ", cert);
|
|
ESP_LOGI(TAG, "Peer certificate info:\n%s", buf);
|
|
} else {
|
|
ESP_LOGW(TAG, "Could not obtain the peer certificate!");
|
|
}
|
|
|
|
free(buf);
|
|
}
|
|
|
|
/**
|
|
* Example callback function to get the certificate of connected clients,
|
|
* whenever a new SSL connection is created and closed
|
|
*
|
|
* Can also be used to other information like Socket FD, Connection state, etc.
|
|
*
|
|
* NOTE: This callback will not be able to obtain the client certificate if the
|
|
* following config `Set minimum Certificate Verification mode to Optional` is
|
|
* not enabled (enabled by default in this example).
|
|
*
|
|
* The config option is found here - Component config → ESP-TLS
|
|
*
|
|
*/
|
|
static void https_server_user_callback(esp_https_server_user_cb_arg_t *user_cb)
|
|
{
|
|
ESP_LOGI(TAG, "User callback invoked!");
|
|
|
|
switch(user_cb->user_cb_state) {
|
|
case HTTPD_SSL_USER_CB_SESS_CREATE:
|
|
ESP_LOGD(TAG, "At session creation");
|
|
|
|
// Logging the socket FD
|
|
ESP_LOGI(TAG, "Socket FD: %d", user_cb->tls->sockfd);
|
|
|
|
// Logging the current ciphersuite
|
|
ESP_LOGI(TAG, "Current Ciphersuite: %s", mbedtls_ssl_get_ciphersuite(&user_cb->tls->ssl));
|
|
break;
|
|
case HTTPD_SSL_USER_CB_SESS_CLOSE:
|
|
ESP_LOGD(TAG, "At session close");
|
|
|
|
// Logging the peer certificate
|
|
print_peer_cert_info(&user_cb->tls->ssl);
|
|
break;
|
|
default:
|
|
ESP_LOGE(TAG, "Illegal state!");
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static const httpd_uri_t root = {
|
|
.uri = "/",
|
|
.method = HTTP_GET,
|
|
.handler = root_get_handler
|
|
};
|
|
|
|
static httpd_handle_t start_webserver(void)
|
|
{
|
|
httpd_handle_t server = NULL;
|
|
|
|
// Start the httpd server
|
|
ESP_LOGI(TAG, "Starting server");
|
|
|
|
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
|
|
|
|
extern const unsigned char servercert_start[] asm("_binary_servercert_pem_start");
|
|
extern const unsigned char servercert_end[] asm("_binary_servercert_pem_end");
|
|
conf.servercert = servercert_start;
|
|
conf.servercert_len = servercert_end - servercert_start;
|
|
|
|
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
|
|
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
|
|
conf.prvtkey_pem = prvtkey_pem_start;
|
|
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
|
|
|
|
#if CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK
|
|
conf.user_cb = https_server_user_callback;
|
|
#endif
|
|
esp_err_t ret = httpd_ssl_start(&server, &conf);
|
|
if (ESP_OK != ret) {
|
|
ESP_LOGI(TAG, "Error starting server!");
|
|
return NULL;
|
|
}
|
|
|
|
// Set URI handlers
|
|
ESP_LOGI(TAG, "Registering URI handlers");
|
|
httpd_register_uri_handler(server, &root);
|
|
return server;
|
|
}
|
|
|
|
static esp_err_t stop_webserver(httpd_handle_t server)
|
|
{
|
|
// Stop the httpd server
|
|
return httpd_ssl_stop(server);
|
|
}
|
|
|
|
static void disconnect_handler(void* arg, esp_event_base_t event_base,
|
|
int32_t event_id, void* event_data)
|
|
{
|
|
httpd_handle_t* server = (httpd_handle_t*) arg;
|
|
if (*server) {
|
|
if (stop_webserver(*server) == ESP_OK)
|
|
*server = NULL;
|
|
}
|
|
}
|
|
|
|
static void connect_handler(void* arg, esp_event_base_t event_base,
|
|
int32_t event_id, void* event_data)
|
|
{
|
|
httpd_handle_t* server = (httpd_handle_t*) arg;
|
|
if (*server == NULL) {
|
|
*server = start_webserver();
|
|
}
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
static httpd_handle_t server = NULL;
|
|
|
|
ESP_ERROR_CHECK(nvs_flash_init());
|
|
ESP_ERROR_CHECK(esp_netif_init());
|
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
|
|
|
/* Register event handlers to start server when Wi-Fi or Ethernet is connected,
|
|
* and stop server when disconnection happens.
|
|
*/
|
|
|
|
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
|
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
|
|
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
|
|
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
|
|
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
|
|
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
|
|
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
|
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
|
* examples/protocols/README.md for more information about this function.
|
|
*/
|
|
ESP_ERROR_CHECK(example_connect());
|
|
}
|