488 lines
21 KiB
C++
488 lines
21 KiB
C++
#pragma once
|
|
|
|
|
|
// Shared browser configuration portal for ESP32 infrastructure and WiFi
|
|
// companion builds. The UI removes MQTT controls when no bridge is present.
|
|
//
|
|
// Two modes:
|
|
// - SETUP: admin-password SoftAP + captive portal, raised on first boot
|
|
// when no WiFi is configured (wifi_ssid empty), or manually via
|
|
// `start webconfig ap`. A credential save joins in AP+STA mode, reports the
|
|
// assigned LAN IP, then reboots; the AP auto-stops after an idle timeout.
|
|
// Legacy short/non-ASCII admin credentials use open WiFi plus HTTP login.
|
|
// - LAN: bound to an existing or portal-owned STA connection. Infrastructure
|
|
// roles use the committed node admin password. Explicit legacy passwordless
|
|
// configurations retain their local no-password policy.
|
|
//
|
|
// Concurrency model: AsyncWebServer handlers run on the async_tcp task and
|
|
// must never touch the CLI, prefs persistence, or the radio. Config writes
|
|
// and browser-terminal commands are marshaled to tick() - called from
|
|
// MyMesh::loop() on the Arduino loop task - and run through the existing CLI
|
|
// handlers there. Request state is guarded by _mux; authentication uses the
|
|
// separately published committed credential generation, never temporary prefs.
|
|
//
|
|
// The master switch and standalone WiFi credentials use independent NVS
|
|
// namespaces, so role-specific prefs-file layouts remain untouched.
|
|
|
|
#if defined(ESP_PLATFORM) && !defined(WEBCONFIG_DISABLED)
|
|
|
|
#define WITH_WEBCONFIG 1
|
|
|
|
#include <helpers/esp32/WiFiCredentials.h>
|
|
|
|
#include <Arduino.h>
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/semphr.h>
|
|
#include <helpers/CompanionWiFiStatus.h>
|
|
#include <helpers/WebConfigBatch.h>
|
|
#include <helpers/TerminalSession.h>
|
|
#include <helpers/RoomWebMailbox.h>
|
|
#include <helpers/WiFiPowerSave.h>
|
|
#include <helpers/WiFiReconnectPolicy.h>
|
|
#include <helpers/WebConfigLoginThrottle.h>
|
|
#include <helpers/WiFiNetworkPowerPolicy.h>
|
|
#include <helpers/ui/DisplayBuildFlags.h>
|
|
#include "WebConfigJsonAllocator.h"
|
|
|
|
class AsyncWebServer;
|
|
class AsyncWebServerRequest;
|
|
class DNSServer;
|
|
class WebTerminalStream;
|
|
|
|
#ifndef WEBCONFIG_AP_IDLE_TIMEOUT_MS
|
|
#if defined(MESHCORE_EXPANDED_PARTITION_PROFILE)
|
|
#define WEBCONFIG_AP_IDLE_TIMEOUT_MS WebConfigBatch::kFullSetupApWindowMs
|
|
#else
|
|
#define WEBCONFIG_AP_IDLE_TIMEOUT_MS (10UL * 60UL * 1000UL)
|
|
#endif
|
|
#endif
|
|
#ifndef WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS
|
|
#if defined(MESHCORE_EXPANDED_PARTITION_PROFILE)
|
|
#define WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS WebConfigBatch::kFullSetupApWindowMs
|
|
#else
|
|
#define WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS 0UL
|
|
#endif
|
|
#endif
|
|
#ifndef WEBCONFIG_SESSION_TTL_MS
|
|
#define WEBCONFIG_SESSION_TTL_MS (20UL * 60UL * 1000UL)
|
|
#endif
|
|
#ifndef WEBCONFIG_AP_PREFIX
|
|
#if defined(MESHCORE_HAS_REAL_DISPLAY)
|
|
// Keeps an open-network WiFi QR in Version 1 on 64-pixel-high screens.
|
|
#define WEBCONFIG_AP_PREFIX "MC"
|
|
#else
|
|
#define WEBCONFIG_AP_PREFIX "MeshCore-Setup"
|
|
#endif
|
|
#endif
|
|
|
|
class WebConfigServer {
|
|
using DynamicJsonDocument = mesh::webconfig::DynamicJsonDocument;
|
|
template<size_t Capacity>
|
|
using StaticJsonDocument = mesh::webconfig::StaticJsonDocument<Capacity>;
|
|
public:
|
|
enum Mode : uint8_t { MODE_OFF = 0, MODE_SETUP, MODE_CONNECTING, MODE_LAN };
|
|
|
|
enum Capability : uint32_t {
|
|
CAP_LOCATION = 1UL << 0,
|
|
CAP_AIRTIME = 1UL << 1,
|
|
CAP_RX_DELAY = 1UL << 2,
|
|
CAP_CAD = 1UL << 3,
|
|
CAP_RX_GAIN = 1UL << 4,
|
|
CAP_REPEAT = 1UL << 5,
|
|
CAP_ADVERT = 1UL << 6,
|
|
CAP_FLOOD = 1UL << 7,
|
|
CAP_LOOP = 1UL << 8,
|
|
CAP_TX_DELAY = 1UL << 9,
|
|
CAP_WIFI_POWER_SAVE = 1UL << 10,
|
|
CAP_FEM_RX_GAIN = 1UL << 11,
|
|
CAP_RX_POWER_SAVING = 1UL << 12,
|
|
CAP_POWER_SAVING = 1UL << 13,
|
|
CAP_BLUETOOTH_NAME = 1UL << 14,
|
|
CAP_ESPNOW_CHANNEL = 1UL << 15,
|
|
CAP_BLUETOOTH_MAC = 1UL << 16,
|
|
CAP_BLUETOOTH_STEALTH = 1UL << 17,
|
|
CAP_LOST_REPLY = 1UL << 18,
|
|
CAP_DELAYS = CAP_RX_DELAY | CAP_TX_DELAY,
|
|
};
|
|
|
|
// Role-neutral snapshot. Infrastructure and companion builds have different
|
|
// persisted NodePrefs layouts, so the portal never casts either one or
|
|
// assumes their member offsets match.
|
|
struct NodeSnapshot {
|
|
char name[32];
|
|
char bluetooth_name[32]; // empty = transport's default device name
|
|
char bluetooth_mac[24]; // empty = chipset factory address
|
|
bool bluetooth_stealth; // independent of the address policy
|
|
uint8_t lost_reply; // 0=off, 1=no, 2=yes (Companion only)
|
|
char admin_password[32]; // empty = trusted LAN/no login prompt
|
|
double lat;
|
|
double lon;
|
|
float freq;
|
|
float bw;
|
|
float airtime_factor;
|
|
float rx_delay;
|
|
float tx_delay;
|
|
int8_t tx_power;
|
|
uint8_t sf;
|
|
uint8_t cr;
|
|
uint8_t cad;
|
|
uint8_t rx_gain;
|
|
uint8_t fem_rx_gain;
|
|
uint8_t rx_ps_enabled;
|
|
uint8_t rx_ps_level;
|
|
uint8_t rx_ps_preamble;
|
|
uint32_t rx_ps_rx_us;
|
|
uint32_t rx_ps_sleep_us;
|
|
uint8_t power_saving;
|
|
uint16_t cpu_freq_mhz; // 0 = automatic device policy
|
|
uint16_t cpu_actual_mhz;
|
|
uint8_t cpu_supported_mask; // bits 0/1/2 = 80/160/240 MHz
|
|
bool display_rotation_supported;
|
|
uint16_t display_rotation_degrees;
|
|
bool mqtt_enabled;
|
|
uint8_t repeat;
|
|
uint16_t advert_interval;
|
|
uint8_t flood_advert_interval;
|
|
uint8_t flood_max;
|
|
uint8_t flood_max_advert;
|
|
uint8_t flood_max_unscoped;
|
|
uint8_t loop_detect;
|
|
uint32_t capabilities;
|
|
};
|
|
|
|
class Callbacks {
|
|
public:
|
|
virtual void getNodeSnapshot(NodeSnapshot& snapshot) = 0;
|
|
// Run one CLI command. Called from tick() only (loop task); reply is 160 bytes.
|
|
virtual void execCommand(char* cmd, char* reply) = 0;
|
|
// Authenticated LAN commands have local-console access, like a direct
|
|
// USB/Ethernet connection. LoRa access is handled separately by each role.
|
|
virtual bool supportsCliTerminal() const { return false; }
|
|
virtual void execAdminCommand(char* cmd, char* reply) {
|
|
execCommand(cmd, reply);
|
|
}
|
|
// Companion's browser uses the same stateful Stream terminal as USB/TCP.
|
|
// All session callbacks run on the mesh loop, never the HTTP task.
|
|
virtual bool supportsStreamTerminal() const { return false; }
|
|
virtual bool beginStreamTerminal(Stream& output) { return false; }
|
|
virtual bool ownsStreamTerminal(const Stream& output) const { return false; }
|
|
virtual void runStreamTerminal(char* command) {}
|
|
virtual bool streamTerminalBusy() const { return false; }
|
|
virtual void endStreamTerminal(Stream& output) {}
|
|
virtual void rebootNow() = 0;
|
|
// Bracket a config batch so bridge restarts triggered by individual
|
|
// `set` handlers can be coalesced into one.
|
|
virtual void onConfigBatchStart() {}
|
|
virtual void onConfigBatchEnd() {}
|
|
// Fill buf with the stats JSON snapshot. Called from tick() (loop task).
|
|
virtual void buildStatsJson(char* buf, size_t buf_size) = 0;
|
|
// Teardown finished (server + DNS freed, WiFi mode restored).
|
|
virtual void onWebConfigStopped() {}
|
|
virtual bool supportsRoomService() const { return false; }
|
|
// The role owns its page resource. Keeping it out of this shared server
|
|
// lets repeaters/companions omit the Room UI without disabling a feature.
|
|
virtual const uint8_t* roomPageGzip(size_t& length) const {
|
|
length = 0;
|
|
return nullptr;
|
|
}
|
|
// Input may be parsed in place. Authentication, storage and radio work
|
|
// happen only on tick(), never on async_tcp.
|
|
virtual void processRoomRequest(const uint8_t* token, uint32_t sequence,
|
|
char* request, char* response, size_t capacity) {}
|
|
virtual bool roomRequestAuthenticated() const { return false; }
|
|
};
|
|
|
|
// mqtt_prefs is an MQTTPrefs* on WITH_MQTT_BRIDGE builds and NULL otherwise.
|
|
// owns_wifi is true when the portal itself brought up STA/AP (normal
|
|
// repeater/room-server builds), false when the companion/MQTT runtime owns it.
|
|
WebConfigServer(Callbacks* callbacks, void* mqtt_prefs, bool owns_wifi,
|
|
const uint8_t* pub_key, const char* fw_ver,
|
|
const char* build_date,
|
|
const char* role, const char* board_name,
|
|
bool standalone_wifi = false);
|
|
~WebConfigServer();
|
|
|
|
// Infrastructure roles refresh this from actual MQTT/UDP station owners.
|
|
// A compiled-in but stopped/unconfigured bridge cannot reconnect WiFi.
|
|
// Companion runtimes retain their own station ownership. Loop task only.
|
|
void updateWiFiOwnership(bool owns_wifi) {
|
|
_runtime_wifi_ownership_managed = true;
|
|
if (_owns_wifi == owns_wifi) return;
|
|
_owns_wifi = owns_wifi;
|
|
// Discard only our attempt state. Never disconnect another owner's STA.
|
|
_connect_deadline = 0;
|
|
_setup_reconnect_in_progress = false;
|
|
_setup_reconnect_deadline = 0;
|
|
}
|
|
// A station-only owner may reclaim an idle automatic recovery AP. Explicit
|
|
// setup APs and active browser/OTA work keep their link until released.
|
|
// Returns true when that owner may manage STA. Loop task only.
|
|
bool prepareStationOwner();
|
|
|
|
// For the device display: true while a setup-mode portal is active.
|
|
// Fills the AP SSID and portal IP; either buffer may be NULL to just poll.
|
|
// Call from the loop task only (same task that changes the mode).
|
|
static bool getSetupInfo(char* ssid, size_t ssid_len, char* ip, size_t ip_len);
|
|
|
|
// For the device display: true once a config save completed and the node is
|
|
// about to reboot - ground truth for the user even if the browser lost its
|
|
// connection before the confirmation arrived. Loop task only.
|
|
static bool isRebootPending();
|
|
|
|
// Persistent master switch and standalone WiFi credentials use separate NVS
|
|
// namespaces. This avoids changing NodePrefs or MQTTPrefs file layouts.
|
|
static bool loadEnabled(bool default_value = false);
|
|
static bool saveEnabled(bool enabled);
|
|
static bool loadCliEnabled(bool default_value = true);
|
|
static bool saveCliEnabled(bool enabled);
|
|
static bool loadStandaloneWiFi(char* ssid, size_t ssid_len,
|
|
char* password, size_t password_len,
|
|
uint8_t* power_save = NULL, const void* legacy_prefs = NULL);
|
|
static bool hasConfiguredWiFi(const void* legacy_prefs = NULL);
|
|
static mesh::wifi::CredentialState resolveWiFi(mesh::wifi::Credentials& out,
|
|
const void* legacy_prefs = NULL);
|
|
static bool saveStandaloneWiFi(const char* ssid, const char* password,
|
|
uint8_t power_save);
|
|
static bool setStandaloneWiFiSSID(const char* value, char* reply,
|
|
size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool setStandaloneWiFiPassword(const char* value, char* reply,
|
|
size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool setStandaloneWiFiPowerSave(const char* value, char* reply,
|
|
size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool setWiFiCliEnabled(const char* value, char* reply,
|
|
size_t reply_len);
|
|
static bool formatWiFiSSID(char* reply, size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool formatWiFiPassword(char* reply, size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool formatWiFiStatus(
|
|
char* reply, size_t reply_len,
|
|
const mesh::wifi::CompanionWiFiRuntimeState* companion_runtime = NULL,
|
|
const void* legacy_prefs = NULL);
|
|
static bool formatWiFiPowerSave(char* reply, size_t reply_len, const void* legacy_prefs = NULL);
|
|
static bool formatWiFiCliStatus(char* reply, size_t reply_len);
|
|
|
|
// UI tasks use an otherwise-unused multi-click gesture without reaching into
|
|
// MyMesh directly. The mesh loop consumes the request and performs the NVS /
|
|
// WiFi transition on its own task.
|
|
static void requestToggleFromButton();
|
|
static bool takeButtonToggleRequest();
|
|
|
|
bool startSetupMode(char reply[]); // open SoftAP + DNS captive portal
|
|
bool startLanMode(char reply[]); // bind to existing STA connection
|
|
bool startAutoMode(char reply[]); // use saved WiFi, or setup AP when absent
|
|
// Accept a start through asynchronous teardown or a transient SDK failure.
|
|
bool requestStart(bool force_ap, char reply[]);
|
|
void requestRestart(); // coalesce saved credential changes
|
|
bool isStartPending() const { return _start_mode != MODE_OFF; }
|
|
bool reloadStandaloneWiFi();
|
|
void requestStop(); // stop listening and detach this session
|
|
// Release HTTP/DNS for the updater without delayed teardown taking its
|
|
// WiFi down. Existing HTTP request objects still drain through tick().
|
|
bool stopForOTA(char reply[]);
|
|
void tick(uint32_t now); // call every loop iteration
|
|
|
|
// A listening LAN portal is not itself a reason to keep a failed background
|
|
// network awake. Explicit starts and real browser activity get a bounded
|
|
// window; AP setup and in-flight work retain the radio until they complete.
|
|
void requestNetworkAccess();
|
|
bool isNetworkForegroundActive(uint32_t now) const;
|
|
|
|
Mode mode() const { return _mode; }
|
|
bool isRunning() const { return _mode != MODE_OFF; }
|
|
bool isStopping() const { return _stopping; }
|
|
bool isSavedWiFiRecoveryActive() const {
|
|
return _mode == MODE_SETUP && _retry_saved_wifi_in_setup && !_stopping;
|
|
}
|
|
|
|
private:
|
|
static const int MAX_BATCH = WebConfigBatch::kMaxBatch;
|
|
static const size_t MAX_BODY = 4096;
|
|
static const uint32_t STOP_WARN_MS = WebConfigBatch::kStopWarnMs;
|
|
enum BatchState : uint8_t { BATCH_IDLE = 0, BATCH_PENDING, BATCH_DONE };
|
|
// What filled the shared slot. A config save comes from allowlisted form
|
|
// fields; a CLI sequence is arbitrary commands typed into the terminal. They
|
|
// share the slot (see WebConfigBatch.h) but differ in how results are read
|
|
// and in whether `key` means anything, so every reader checks the kind.
|
|
enum BatchKind : uint8_t { BATCH_CONFIG = 0, BATCH_CLI };
|
|
|
|
// BatchState and WebConfigBatch::State are deliberately kept as separate
|
|
// types (the enum is stored in a volatile member and used in prints); this
|
|
// is the one conversion point.
|
|
static WebConfigBatch::State toSpecState(BatchState s) {
|
|
switch (s) {
|
|
case BATCH_PENDING: return WebConfigBatch::State::Pending;
|
|
case BATCH_DONE: return WebConfigBatch::State::Done;
|
|
default: return WebConfigBatch::State::Idle;
|
|
}
|
|
}
|
|
struct BatchEntry {
|
|
char key[24]; // allowlisted config key (echoed back to the UI); empty for CLI entries
|
|
char cmd[160]; // full CLI command (may contain secrets - never echoed)
|
|
char reply[160]; // CLI reply budget, same 160 bytes the serial console gets
|
|
};
|
|
|
|
Callbacks* _cb;
|
|
void* _mqtt_prefs;
|
|
bool _owns_wifi;
|
|
// Legacy Companion/manual portals preserve their original start behavior;
|
|
// infrastructure opts into worker ownership through updateWiFiOwnership.
|
|
bool _runtime_wifi_ownership_managed = false;
|
|
// Credential storage is fixed at construction, independently of which
|
|
// runtime currently owns the station. Async UI handlers read this flag.
|
|
const bool _standalone_wifi;
|
|
const uint8_t* _pub_key;
|
|
const char* _fw_ver;
|
|
const char* _build_date;
|
|
const char* _role;
|
|
const char* _board_name;
|
|
|
|
AsyncWebServer* _server = NULL;
|
|
DNSServer* _dns = NULL;
|
|
SemaphoreHandle_t _mux;
|
|
Mode _mode = MODE_OFF;
|
|
bool _stopping = false;
|
|
Mode _start_mode = MODE_OFF;
|
|
uint32_t _start_retry_at = 0;
|
|
uint32_t _start_retry_delay = 5000;
|
|
bool _start_retryable = false;
|
|
bool _keep_wifi_on_stop = false;
|
|
bool _was_setup_ap = false;
|
|
bool _initial_setup = false;
|
|
bool _setup_provisioning_privilege = false;
|
|
uint32_t _setup_started_at = 0;
|
|
uint32_t _connect_deadline = 0;
|
|
char _wifi_ssid[32] = {0};
|
|
// 63-character passphrase + NUL, or 64-hex raw WPA/WPA2 PSK + NUL.
|
|
char _wifi_password[65] = {0};
|
|
uint8_t _wifi_power_save = mesh::wifi::kDefaultPowerSave;
|
|
bool _cli_enabled = true;
|
|
// A `password` command has succeeded this session. Lets the CLI satisfy the
|
|
// initial-setup invariant across separate submissions; the form batch always
|
|
// sends the password with the rest, so it never needed the memory.
|
|
bool _admin_pwd_set = false;
|
|
char _ap_ssid[33] = {0};
|
|
uint32_t _ap_auth_generation = 0;
|
|
uint32_t _ap_rekey_generation = 0;
|
|
uint32_t _ap_rekey_after = 0;
|
|
uint32_t _ap_rekey_deadline = 0;
|
|
WiFiReconnectPolicy::Tracker _wifi_reconnect_tracker;
|
|
bool _retry_saved_wifi_in_setup = false;
|
|
bool _setup_reconnect_in_progress = false;
|
|
uint32_t _setup_reconnect_deadline = 0;
|
|
|
|
// Currently attached session, also used by the display's setup-info poll.
|
|
static WebConfigServer* _active;
|
|
// Process-lifetime listener and route table. Async requests retain their
|
|
// server pointer until disconnect, so this object is not deleted on stop.
|
|
static AsyncWebServer* _host;
|
|
|
|
// Command batch: filled by async_tcp under _mux, drained by tick().
|
|
volatile BatchState _batch_state = BATCH_IDLE;
|
|
volatile BatchKind _batch_kind = BATCH_CONFIG;
|
|
uint8_t _batch_count = 0;
|
|
uint8_t _batch_next = 0; // drain progress (one command per tick)
|
|
uint32_t _batch_last_cmd = 0;
|
|
bool _batch_reboot = false;
|
|
bool _batch_reboot_armed = false;
|
|
bool _batch_all_ok = true;
|
|
bool _batch_started = false;
|
|
char _batch_reqid[24] = {0};
|
|
uint32_t _batch_auth_generation = 0;
|
|
char _batch_owner_token[33] = {0};
|
|
bool _batch_reauth_required = false;
|
|
bool _batch_reauth_delivered = false;
|
|
uint32_t _batch_reauth_until = 0;
|
|
bool _standalone_wifi_dirty = false;
|
|
bool _setup_wifi_handoff_pending = false;
|
|
uint32_t _setup_wifi_handoff_deadline = 0;
|
|
char _setup_wifi_handoff_ip[16] = {0};
|
|
BatchEntry _batch[MAX_BATCH];
|
|
WebTerminalStream* _terminal = NULL;
|
|
mesh::RoomWebMailbox* _room_mailbox = NULL;
|
|
|
|
// Browser login session, bound to the committed credential generation.
|
|
// One slot: a new login evicts the old session in LAN or recovery AP mode.
|
|
char _session_token[33] = {0};
|
|
uint32_t _session_last_seen = 0;
|
|
uint32_t _session_generation = 0;
|
|
uint32_t _terminal_auth_generation = 0;
|
|
WebConfigLoginThrottle::Tracker _login_throttle;
|
|
|
|
// Once set (via /api/portal/exit), OS captive probes get native "success"
|
|
// replies so the phone's sign-in sheet can be dismissed without dropping the
|
|
// WiFi, letting the user continue in their real browser. async_tcp-task only.
|
|
volatile bool _captive_release = false;
|
|
|
|
// Save-path diagnostics: 1 Hz serial trace for 60 s after each config POST
|
|
// (AP station count, heap, batch state) to pinpoint client drops on hardware.
|
|
volatile uint32_t _diag_until = 0;
|
|
uint32_t _diag_last = 0;
|
|
|
|
volatile uint32_t _last_activity = 0;
|
|
volatile uint32_t _network_activity_until = 0;
|
|
uint32_t _reboot_at = 0; // 0 = none scheduled
|
|
uint32_t _stop_warn_at = 0;
|
|
bool _stop_warned = false;
|
|
uint32_t _handler_refs = 0;
|
|
volatile uint32_t _stats_wanted_until = 0;
|
|
uint32_t _stats_built_at = 0;
|
|
char _stats_json[1024] = {0};
|
|
uint8_t _board_cmds = 0;
|
|
bool _board_cmds_probed = false;
|
|
|
|
void createServer();
|
|
void noteNetworkActivity();
|
|
void refreshNetworkPowerHold(uint32_t now);
|
|
bool beginSavedStation(uint32_t now);
|
|
void serviceStartRetry(uint32_t now);
|
|
void registerRoutes();
|
|
typedef void (WebConfigServer::*RequestHandler)(AsyncWebServerRequest*);
|
|
static void dispatchRequest(AsyncWebServerRequest* req, RequestHandler handler);
|
|
void attachRoutes();
|
|
void detachRoutes();
|
|
uint32_t handlerRefCount() const;
|
|
void drainBatch(uint32_t now);
|
|
void probeBoardCommands();
|
|
void serviceTerminal(uint32_t now);
|
|
void serviceRoom(uint32_t now);
|
|
void closeTerminal();
|
|
void serviceSetupWiFiHandoff(uint32_t now);
|
|
void serviceSetupPassword(uint32_t now);
|
|
void finishBatch(uint32_t now);
|
|
void finalizeTeardown();
|
|
void initializeManagementPassword();
|
|
void clearSessionLocked();
|
|
bool checkAuth(AsyncWebServerRequest* req);
|
|
bool checkAuthLocked(AsyncWebServerRequest* req, uint32_t* generation = nullptr);
|
|
bool resultReceiptAllowedLocked(AsyncWebServerRequest* req, const char* reqid,
|
|
BatchKind kind, uint32_t now);
|
|
void beginBatchAuthorizationLocked(uint32_t generation);
|
|
void cancelStaleBatchLocked(uint32_t now);
|
|
static void collectBody(AsyncWebServerRequest* req, uint8_t* data, size_t len,
|
|
size_t index, size_t total);
|
|
|
|
void handleRoot(AsyncWebServerRequest* req);
|
|
void handleUi(AsyncWebServerRequest* req);
|
|
void handleStatus(AsyncWebServerRequest* req);
|
|
void handleLogin(AsyncWebServerRequest* req);
|
|
void handleLogout(AsyncWebServerRequest* req);
|
|
void handleConfigGet(AsyncWebServerRequest* req);
|
|
void handleConfigPost(AsyncWebServerRequest* req);
|
|
void handleConfigResult(AsyncWebServerRequest* req);
|
|
void handleCliPost(AsyncWebServerRequest* req);
|
|
void handleCliResult(AsyncWebServerRequest* req);
|
|
void handleTerminalPost(AsyncWebServerRequest* req);
|
|
void handleTerminalOutput(AsyncWebServerRequest* req);
|
|
bool checkTerminalAccess(AsyncWebServerRequest* req);
|
|
void handleStats(AsyncWebServerRequest* req);
|
|
void handleScan(AsyncWebServerRequest* req);
|
|
void handlePresets(AsyncWebServerRequest* req);
|
|
void handleReboot(AsyncWebServerRequest* req);
|
|
void handlePortalExit(AsyncWebServerRequest* req);
|
|
void handleRoomPage(AsyncWebServerRequest* req);
|
|
void handleRoomPost(AsyncWebServerRequest* req);
|
|
void handleRoomResult(AsyncWebServerRequest* req);
|
|
void handleNotFound(AsyncWebServerRequest* req);
|
|
};
|
|
|
|
#endif // ESP_PLATFORM && !WEBCONFIG_DISABLED
|