Stopping server inside handler using httpd_stop(*server);
Posted: Mon Mar 21, 2022 4:25 pm
Hello. I use file_serving example from http_server.
I would like to achieve a very simple logic: When the client connects to the AP, start the webserver and serve client webpage. As soon as the last client disconnects from the AP (no more clients connected), I want to stop the webserver and stop the wifi interface.
My functions:
WIFI INIT function:
START/STOP WEBSERVER FUNCTION:
Notice in the start webserver I create a wifi_event_handler and pass httpd_handle_t server as a parameter
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, &server));
WIFI EVENT HANDLER:
Inside the wifi_event handler I keep track of connected and disconnect clients. When there are no more connected clients (wifi_connected_clients = 0), I would like to stop the webserver by calling stop_webserver(*server). However, the program immediately crashes:
Could someone help me understand what could cause this?
Am I not accessing the httpd_handle_t variable correctly through the handle? Is below not corrrect?:
httpd_handle_t* server = (httpd_handle_t*) arg; ?
Any ideas are appreciated
I would like to achieve a very simple logic: When the client connects to the AP, start the webserver and serve client webpage. As soon as the last client disconnects from the AP (no more clients connected), I want to stop the webserver and stop the wifi interface.
My functions:
WIFI INIT function:
Code: Select all
void WIFI_INIT_AP_STA(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID_AP,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID_AP),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS_AP,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS_AP) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI("WIFI AP", "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID_AP, EXAMPLE_ESP_WIFI_PASS_AP, EXAMPLE_ESP_WIFI_CHANNEL);
return ESP_OK;
}
START/STOP WEBSERVER FUNCTION:
Code: Select all
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("START_SERVER", "File server presently supports only '/spiffs' as base path");
return ESP_ERR_INVALID_ARG;
}
if (server_data) {
ESP_LOGE("START_SERVER", "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("START_SERVER", "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_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));
ESP_LOGI("START_SERVER", "Starting HTTP Server on port: '%d'", config.server_port);
if (httpd_start(&server, &config) != ESP_OK) {
ESP_LOGE("START_SERVER", "Failed to start file server!");
return ESP_FAIL;
}
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, &server));
//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);
return ESP_OK;
}
void stop_webserver(httpd_handle_t server)
{
ESP_LOGI(TAG_WEBSERVER, "Stopping webserver");
httpd_stop(server);
}
Notice in the start webserver I create a wifi_event_handler and pass httpd_handle_t server as a parameter
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, &server));
WIFI EVENT HANDLER:
Code: Select all
static void wifi_event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG_WEBSERVER, "station "MACSTR" join, AID=%d",MAC2STR(event->mac), event->aid);
wifi_connected_clients += 1;
printf("connected clients = %u \n",wifi_connected_clients);
httpd_handle_t* server = (httpd_handle_t*) arg;
if (server == NULL) {
ESP_LOGI(TAG_WEBSERVER, "Starting webserver");
start_file_server("/spiffs");
}
}
else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG_WEBSERVER, "station "MACSTR" leave, AID=%d",MAC2STR(event->mac), event->aid);
wifi_connected_clients -= 1;
printf("connected clients = %u \n",wifi_connected_clients);
if(wifi_connected_clients == 0){
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server) {
ESP_LOGI(TAG_WEBSERVER, "Stopping webserver");
stop_webserver(*server);
*server = NULL;
STOP_WIFI_AP_STA();
}
}
}
}
Code: Select all
connected clients = 0
I (14800) webserver: Stopping webserver
I (14800) webserver: Stopping webserver
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x401083f3 PS : 0x00060530 A0 : 0x800daab4 A1 : 0x3ffb9d70
0x401083f3: httpd_stop at C:/Users/petrikas.lu/esp/esp-idf/components/esp_http_server/src/httpd_main.c:453
A2 : 0x000002f7 A3 : 0x3f41b974 A4 : 0x3f41b980 A5 : 0x000039d0
A6 : 0x3f41b974 A7 : 0x0000000c A8 : 0x00000000 A9 : 0x3ffb9d20
A10 : 0x4014e3c8 A11 : 0x3f41b974 A12 : 0x3ffb9d70 A13 : 0x0000000c
0x4014e3c8: vprintf at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdio/vprintf.c:30
A14 : 0x3ffb9d60 A15 : 0x0000000c SAR : 0x00000004 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000305 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffd
Backtrace:0x401083f0:0x3ffb9d700x400daab1:0x3ffb9da0 0x400dab96:0x3ffb9dc0 0x40157ea1:0x3ffb9e00 0x40157a06:0x3ffb9e30 0x40157ad9:0x3ffb9e70 0x40089251:0x3ffb9e90
0x401083f0: httpd_stop at C:/Users/petrikas.lu/esp/esp-idf/components/esp_http_server/src/httpd_main.c:453
0x400daab1: stop_webserver at C:\Users\petrikas.lu\Work\Projects\test\test\build/../components/WIFI/WIFI.c:333
0x400dab96: wifi_event_handler at C:\Users\petrikas.lu\Work\Projects\test\test\build/../components/WIFI/WIFI.c:1023 (discriminator 13)
0x40157ea1: handler_execute at C:/Users/petrikas.lu/esp/esp-idf/components/esp_event/esp_event.c:145
0x40157a06: esp_event_loop_run at C:/Users/petrikas.lu/esp/esp-idf/components/esp_event/esp_event.c:590 (discriminator 3)
0x40157ad9: esp_event_loop_run_task at C:/Users/petrikas.lu/esp/esp-idf/components/esp_event/esp_event.c:115 (discriminator 15)
0x40089251: vPortTaskWrapper at C:/Users/petrikas.lu/esp/esp-idf/components/freertos/port/xtensa/port.c:131
ELF file SHA256: b79e6e2195ab2e5b
Rebooting...
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:6604
ho 0 tail 12 room 4
load:0x40078000,len:14808
ho 0 tail 12 room 4
load:0x40080400,len:3792
0x40080400: _init at ??:?
entry 0x40080694
I (30) boot: ESP-IDF v4.4 2nd stage bootloader
I (31) boot: compile time 14:43:07
I (31) boot: chip revision: 3
I (33) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (40) boot.esp32: SPI Speed : 80MHz
I (45) boot.esp32: SPI Mode : DIO
I (50) boot.esp32: SPI Flash Size : 8MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label Usage Type ST Offset Length
I (71) boot: 0 nvs WiFi data 01 02 00009000 00004000
I (78) boot: 1 otadata OTA data 01 00 0000d000 00002000
I (85) boot: 2 phy_init RF data 01 01 0000f000 00001000
I (93) boot: 3 factory factory app 00 00 00010000 00190000
I (100) boot: 4 ota_0 OTA app 00 10 001a0000 00190000
I (108) boot: 5 ota_1 OTA app 00 11 00330000 00190000
I (115) boot: 6 storage Unknown data 01 82 004c0000 00190000
Could someone help me understand what could cause this?
Am I not accessing the httpd_handle_t variable correctly through the handle? Is below not corrrect?:
httpd_handle_t* server = (httpd_handle_t*) arg; ?
Any ideas are appreciated