Issue
I'm trying to port the file_serving example to use HTTPS.
I've attempted to move the spiff file server functionality to the existing https_server example inside esp-idf but I get the error: httpd_server_init: error in creating ctrl socket (112)
I realize that this is probably not the easiest way to do it and instead I should work on re-writing the original file_serving example code to use https instead. The function to start the server is in the file_server.c:
/* Function to start the file server */
esp_err_t start_file_server(const char *base_path)
{
static struct file_server_data *server_data = NULL;
/* Validate file storage base path */
if (!base_path || strcmp(base_path, "/spiffs") != 0) {
ESP_LOGE(TAG, "File server presently supports only '/spiffs' as base path");
return ESP_ERR_INVALID_ARG;
}
if (server_data) {
ESP_LOGE(TAG, "File server already started");
return ESP_ERR_INVALID_STATE;
}
/* Allocate memory for server data */
server_data = calloc(1, sizeof(struct file_server_data));
if (!server_data) {
ESP_LOGE(TAG, "Failed to allocate memory for server data");
return ESP_ERR_NO_MEM;
}
strlcpy(server_data->base_path, base_path,
sizeof(server_data->base_path));
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
/* Use the URI wildcard matching function in order to
* allow the same handler to respond to multiple different
* target URIs which match the wildcard scheme */
config.uri_match_fn = httpd_uri_match_wildcard;
ESP_LOGI(TAG, "Starting HTTP Server");
if (httpd_start(&server, &config) != ESP_OK) {
ESP_LOGE(TAG, "Failed to start file server!");
return ESP_FAIL;
}
/* URI handler for getting uploaded files */
httpd_uri_t file_download = {
.uri = "/*", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = download_get_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_download);
/* URI handler for uploading files to server */
httpd_uri_t file_upload = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_upload);
/* URI handler for deleting files from server */
httpd_uri_t file_delete = {
.uri = "/delete/*", // Match all URIs of type /delete/path/to/file
.method = HTTP_POST,
.handler = delete_post_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_delete);
return ESP_OK;
}
The main function references the start_file_server and that is shown below as well:
void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* 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());
/* Initialize file storage */
ESP_ERROR_CHECK(init_spiffs());
/* Start the file server */
ESP_ERROR_CHECK(start_file_server("/spiffs"));
}
I have the https_server example running and I have https_mbedtls client connecting to it and not authenticating the validity of my self-signed cert. This same https_mbedtls client would be used to connect the the file_server (https).
the original file_server example includes esp_http_server.h. I assume that I need to instead include esp_https_server.h
Below are the changes that I have made to it:
/* Function to start the file server */
esp_err_t start_file_server(const char *base_path)
{
static struct file_server_data *server_data = NULL;
/* Validate file storage base path */
if (!base_path || strcmp(base_path, "/spiffs") != 0) {
ESP_LOGE(TAG, "File server presently supports only '/spiffs' as base path");
return ESP_ERR_INVALID_ARG;
}
if (server_data) {
ESP_LOGE(TAG, "File server already started");
return ESP_ERR_INVALID_STATE;
}
/* Allocate memory for server data */
server_data = calloc(1, sizeof(struct file_server_data));
if (!server_data) {
ESP_LOGE(TAG, "Failed to allocate memory for server data");
return ESP_ERR_NO_MEM;
}
strlcpy(server_data->base_path, base_path,
sizeof(server_data->base_path));
//***********
httpd_handle_t server = NULL;
httpd_ssl_config_t config = HTTPD_SSL_CONFIG_DEFAULT();
//***********
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
conf.cacert_pem = cacert_pem_start;
conf.cacert_len = cacert_pem_end - cacert_pem_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;
//***********
/* Use the URI wildcard matching function in order to
* allow the same handler to respond to multiple different
* target URIs which match the wildcard scheme */
config.uri_match_fn = httpd_uri_match_wildcard;
ESP_LOGI(TAG, "Starting HTTPS Server");
//***********
if (httpd_ssl_start(&server, &config) != ESP_OK) {
ESP_LOGE(TAG, "Failed to start file server!");
return ESP_FAIL;
}
/* URI handler for getting uploaded files */
httpd_uri_t file_download = {
.uri = "/*", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = download_get_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_download);
/* URI handler for uploading files to server */
httpd_uri_t file_upload = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_upload);
/* URI handler for deleting files from server */
httpd_uri_t file_delete = {
.uri = "/delete/*", // Match all URIs of type /delete/path/to/file
.method = HTTP_POST,
.handler = delete_post_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_delete);
return ESP_OK;
}
When I go flash through ESP-IDF command line I get the following error:
../main/file_server.c:22:10: fatal error: esp_https_server.h: No such file or directory #include "esp_https_server.h" ^~~~~~~~~~~~~~~~~~~~ compilation terminated.
To fix this, I try to add "REQUIRES esp_https_server" to the CMakeLists.txt in the main directory. This replaces the previous error with
../main/main.c:16:10: fatal error: esp_spiffs.h: No such file or directory #include "esp_spiffs.h" ^~~~~~~~~~~~~~ compilation terminated.
The same thing happens where it can't find additional requirements until my CMakeLists.txt looks like this:
idf_component_register(SRCS "main.c" "file_server.c"
INCLUDE_DIRS "."
EMBED_FILES "favicon.ico" "upload_script.html"
EMBED_TXTFILES "certs/cacert.pem"
"certs/prvtkey.pem"
REQUIRES esp_https_server spiffs nvs_flash protocol_examples_common)
And the error I get at this point is once again unable to find esp_https_server.h
../main/file_server.c:22:10: fatal error: esp_https_server.h: No such file or directory #include "esp_https_server.h" ^~~~~~~~~~~~~~~~~~~~ compilation terminated.
I hope you understand the frustrating predicament that I'm in and I would greatly appreciate any input on how to fix this "No such file or directory" error or any tips on how to port this example to https as well. Thank you.
Solution
My supervising professor had a look at the problem and found the solution. Here are the changes that were needed to be made:
Include the following line in the sdkconfig file: CONFIG_ESP_HTTPS_SERVER_ENABLE=y
“config” instead of “conf” in the file file_server.c and the configuration for the http server is a subcomponent of the https configuration and needs a "httpd.” after the “config.”:
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
config.cacert_pem = cacert_pem_start;
config.cacert_len = cacert_pem_end - cacert_pem_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");
config.prvtkey_pem = prvtkey_pem_start;
config.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
//***********
/* Use the URI wildcard matching function in order to
* allow the same handler to respond to multiple different
* target URIs which match the wildcard scheme */
config.httpd.uri_match_fn = httpd_uri_match_wildcard;
Answered By - MuxD