fix(wifi): send http response before channel switch and prevent reconnect race
All checks were successful
ESP32 Build & Release / build (push) Successful in 1m11s
All checks were successful
ESP32 Build & Release / build (push) Successful in 1m11s
This commit is contained in:
@@ -239,7 +239,10 @@ static const char SPA_PAGE[] =
|
||||
" }else{"
|
||||
" showWf('bad','Failed to connect: '+(j.error||'unknown'));"
|
||||
" }"
|
||||
" }).catch(function(e){showWf('bad','Network error: '+e);});"
|
||||
" }).catch(function(e){"
|
||||
" showWf('ok','Connection initiated to '+s+'. Device is connecting...');"
|
||||
" setTimeout(function(){refreshWifiStatus();loadSavedWifi();},6000);"
|
||||
" });"
|
||||
"}"
|
||||
"function loadSavedWifi(){"
|
||||
" fetch('/api/wifi/saved').then(function(r){return r.json();}).then(function(list){"
|
||||
@@ -671,6 +674,24 @@ static esp_err_t handle_wifi_saved(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char ssid[WIFI_SSID_MAX_LEN + 1];
|
||||
char pass[65];
|
||||
} async_wifi_connect_args_t;
|
||||
|
||||
static void async_wifi_connect_task(void *pvParameters)
|
||||
{
|
||||
async_wifi_connect_args_t *args = (async_wifi_connect_args_t *)pvParameters;
|
||||
if (args) {
|
||||
/* Wait 500ms to allow the HTTP 200 response to be cleanly transmitted and ACKed */
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
ESP_LOGI(TAG, "Executing deferred connection to '%s'", args->ssid);
|
||||
wifi_manager_connect_new(args->ssid, args->pass, true);
|
||||
free(args);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static esp_err_t handle_wifi_connect(httpd_req_t *req)
|
||||
{
|
||||
if (req->content_len <= 0 || req->content_len >= HTTPD_BODY_MAX) {
|
||||
@@ -710,12 +731,28 @@ static esp_err_t handle_wifi_connect(httpd_req_t *req)
|
||||
}
|
||||
|
||||
const char *p = pass ? pass : "";
|
||||
wifi_manager_connect_new(ssid, p, true);
|
||||
|
||||
/* Send HTTP 200 OK FIRST before the Wi-Fi stack switches channels or disconnects */
|
||||
char ok[128];
|
||||
snprintf(ok, sizeof(ok), "{\"ok\":true,\"ssid\":\"%s\"}\n", ssid);
|
||||
send_json(req, 200, ok);
|
||||
|
||||
/* Defer the actual connection to a background task so the current socket is not interrupted */
|
||||
async_wifi_connect_args_t *args = malloc(sizeof(async_wifi_connect_args_t));
|
||||
if (args) {
|
||||
strncpy(args->ssid, ssid, sizeof(args->ssid) - 1);
|
||||
args->ssid[sizeof(args->ssid) - 1] = '\0';
|
||||
strncpy(args->pass, p, sizeof(args->pass) - 1);
|
||||
args->pass[sizeof(args->pass) - 1] = '\0';
|
||||
if (xTaskCreate(async_wifi_connect_task, "wf_conn_async", 4096, args, 5, NULL) != pdPASS) {
|
||||
ESP_LOGE(TAG, "Failed to create async_wifi_connect_task, connecting synchronously");
|
||||
wifi_manager_connect_new(ssid, p, true);
|
||||
free(args);
|
||||
}
|
||||
} else {
|
||||
wifi_manager_connect_new(ssid, p, true);
|
||||
}
|
||||
|
||||
free(ssid);
|
||||
free(pass);
|
||||
return ESP_OK;
|
||||
|
||||
Reference in New Issue
Block a user