cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
provision.cpp File Reference

The config portal: a SoftAP and a captive portal, for setup and for administration alike, one page for both. See provision.h for the why. More...

#include "provision.h"
#include <atomic>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "CW_Utils.h"
#include "lwip/sockets.h"
#include "esp_heap_caps.h"
#include "esp_http_server.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "esp_random.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "nvs.h"
#include "mbedtls/sha256.h"
#include "addr_check.h"
#include "eth_addr.h"
#include "form_parse.h"
#include "json_out.h"
#include "net.h"
#include "ota.h"
#include "portal_page.h"
#include "settings.h"
#include "settings_rules.h"
#include "civil_time.h"
Include dependency graph for provision.cpp:

Go to the source code of this file.

Macros

#define AP_PASS_LEN   10U /* ~50 bits out of the 32-char alphabet below */
#define NS_PROV   "prov"
#define K_AP_PASS   "ap_pass"
#define K_TLS_CRT   "tls_crt"
#define K_TLS_KEY   "tls_key"
#define UPLOAD_CHUNK   4096U
#define UPLOAD_MAX_STALLS   4U
#define TOKEN_HEX_LEN   32U /* 128 bits of session token */
#define PROV_MAX_APS   16U

Functions

static void ap_pass_draw (void)
 Fill s_pass with AP_PASS_LEN characters of hardware entropy.
static void ap_pass_load (void)
 The AP passphrase: drawn once, then kept until a factory reset.
static void ap_ssid_build (void)
 SSID from the SoftAP MAC, so two terminals in a room are tellable apart.
static void dns_task (void *arg)
 Answer every A query with the portal address.
static bool read_body (httpd_req_t *req, char *out, size_t n)
 Read a request body into out.
static bool expired (void)
 True once the portal's own window has closed.
static bool has_token (httpd_req_t *req)
 Whether the request carries the token of the authorised session.
static bool authed (httpd_req_t *req)
 Whether the request is the browser that was let in.
static esp_err_t reply (httpd_req_t *req, const char *status, const char *msg)
 Send a plain-text status line; the page shows it verbatim.
static esp_err_t ok (httpd_req_t *req, const char *msg)
 200 with a plain-text message.
static bool uri_is (const httpd_req_t *req, const char *path)
 Whether the request's path is path — req->uri carries any query string, which routing ignores and this must too.
static bool gate (httpd_req_t *req, esp_err_t *rc)
 The gate every mutating endpoint runs first.
static esp_err_t page_get (httpd_req_t *req)
static const char * ask_label (prov_ask_t k)
 Label the panel and the page both use for a pending proposal.
static const char * step_name (prov_step_t s)
static bool addr_plausible (bool tron, const char *addr)
 Reject an address that is obviously not one, before it is proposed.
static esp_err_t state_get (httpd_req_t *req)
static esp_err_t scan_get (httpd_req_t *req)
static esp_err_t auth_post (httpd_req_t *req)
static esp_err_t value_post (httpd_req_t *req, bool contract)
 Shared body of /api/payout and /api/contract.
static esp_err_t payout_post (httpd_req_t *req)
static esp_err_t contract_post (httpd_req_t *req)
static esp_err_t fees_post (httpd_req_t *req)
 Store the EIP-1559 gas caps (Gwei).
static esp_err_t clock_post (httpd_req_t *req)
 Store the panel clock's standard offset from UTC and its DST rule.
static esp_err_t network_post (httpd_req_t *req)
 Switch the terminal between the production and the test networks.
static esp_err_t card_post (httpd_req_t *req)
 The browser asks the terminal to read the addresses off a card.
static esp_err_t wifi_post (httpd_req_t *req)
static esp_err_t rescan_post (httpd_req_t *req)
static esp_err_t next_post (httpd_req_t *req)
static esp_err_t ota_post (httpd_req_t *req)
 Stream a firmware image into the idle slot, without booting it.
static esp_err_t redirect (httpd_req_t *req)
 Send every probe and stray URL to the portal.
static esp_err_t redirect_404 (httpd_req_t *req, httpd_err_code_t err)
 404 handler — the catch-all for probe URLs not listed below.
static esp_err_t apple_probe (httpd_req_t *req)
static void register_handlers (void)
bool prov_start (prov_mode_t mode, ui_event_cb_t cb)
 Raise the portal.
void prov_stop (void)
 Stop the portal, drop the AP, and withdraw anything unaccepted.
prov_mode_t prov_mode (void)
 Which mode is running, or PROV_MODE_OFF.
void prov_set_step (prov_step_t step)
 Tell the portal which wizard step is current.
prov_step_t prov_step (void)
 The current step.
unsigned prov_window_left_min (void)
 Minutes left before the portal closes itself, 0 once it has.
const char * prov_ap_ssid (void)
 AP SSID, or "" while no portal is up.
const char * prov_ap_pass (void)
 AP passphrase, or "" while no portal is up.
const char * prov_qr_payload (void)
 What the panel's QR code should carry.
bool prov_auth_pending (void)
 Whether a browser has asked to be authorised.
void prov_auth_resolve (bool grant)
 Answer a pending authorisation request from the panel.
bool prov_authed (void)
 Whether the browser session is authorised to change anything.
bool prov_pair_code (char *out, size_t out_size)
 The 4-digit pairing code of the browser asking to be let in.
void prov_set_wifi_only (void)
 Cut the wizard down to the Wi-Fi step, with no admin code.
bool prov_wifi_only (void)
 Whether the portal is the cut-down Wi-Fi-only flow.
void prov_set_note (const char *note)
 Put a one-line message on the page.
void prov_set_scan (const net_wifi_ap_t *aps, uint16_t n)
 Hand the portal a Wi-Fi scan for the browser to choose from.
bool prov_propose (prov_ask_t kind, const char *addr)
 Propose a value on behalf of the panel itself.
bool prov_pending (prov_ask_t *kind, char *label, size_t label_n, char *value, size_t value_n)
 Fetch the value a browser proposed but nobody has accepted.
bool prov_pending_commit (bool accept)
 Resolve a pending proposal from the panel.

Variables

static const char *const TAG = "prov"
static const char AP_PASS_ALPHABET [] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
static httpd_handle_t s_httpd = NULL
static TaskHandle_t s_dns_task = NULL
static volatile bool s_dns_run = false
static ui_event_cb_t s_cb = NULL
static std::atomic< prov_mode_t > s_mode {PROV_MODE_OFF}
static volatile prov_step_t s_step = PROV_STEP_IDLE
static int64_t s_deadline_us = 0
static char s_ssid [33] = ""
static char s_pass [AP_PASS_LEN+1U] = ""
static char s_qr [96] = ""
static uint8_t s_upload [UPLOAD_CHUNK]
static char s_token [TOKEN_HEX_LEN+1U] = ""
static volatile bool s_auth_pending = false
static volatile bool s_authed = false
static volatile bool s_wifi_only = false
static char s_note [128] = ""
static portMUX_TYPE s_share_mux = portMUX_INITIALIZER_UNLOCKED
static net_wifi_ap_t s_aps [PROV_MAX_APS]
static uint16_t s_ap_count = 0U
static std::atomic< uint32_t > s_scan_gen {0U}
static SemaphoreHandle_t s_ask_lock = NULL
static prov_ask_t s_ask = PROV_ASK_NONE
static char s_ask_val [SETTINGS_PAYOUT_MAX] = ""
static const char *const PROBE_URIS []

Detailed Description

The config portal: a SoftAP and a captive portal, for setup and for administration alike, one page for both. See provision.h for the why.

Definition in file provision.cpp.

Macro Definition Documentation

◆ AP_PASS_LEN

#define AP_PASS_LEN   10U /* ~50 bits out of the 32-char alphabet below */

Definition at line 66 of file provision.cpp.

Referenced by ap_pass_draw(), and ap_pass_load().

◆ K_AP_PASS

#define K_AP_PASS   "ap_pass"

Definition at line 78 of file provision.cpp.

Referenced by ap_pass_load().

◆ K_TLS_CRT

#define K_TLS_CRT   "tls_crt"

Definition at line 81 of file provision.cpp.

Referenced by ap_pass_load().

◆ K_TLS_KEY

#define K_TLS_KEY   "tls_key"

Definition at line 82 of file provision.cpp.

Referenced by ap_pass_load().

◆ NS_PROV

#define NS_PROV   "prov"

Definition at line 75 of file provision.cpp.

Referenced by ap_pass_load().

◆ PROV_MAX_APS

#define PROV_MAX_APS   16U

Definition at line 105 of file provision.cpp.

Referenced by prov_set_scan().

◆ TOKEN_HEX_LEN

#define TOKEN_HEX_LEN   32U /* 128 bits of session token */

Definition at line 103 of file provision.cpp.

Referenced by auth_post(), and has_token().

◆ UPLOAD_CHUNK

#define UPLOAD_CHUNK   4096U

Definition at line 94 of file provision.cpp.

Referenced by ota_post().

◆ UPLOAD_MAX_STALLS

#define UPLOAD_MAX_STALLS   4U

Definition at line 101 of file provision.cpp.

Referenced by ota_post().

Function Documentation

◆ addr_plausible()

bool addr_plausible ( bool tron,
const char * addr )
static

Reject an address that is obviously not one, before it is proposed.

Ethereum gets the real check: eth_addr_parse() verifies the EIP-55 checksum, so a single mistyped character in a mixed-case address is caught here.

Tron gets the real check too: base58-decoded (addr_check.h) and its 4-byte checksum verified as double SHA-256 of the first 21 bytes. A mistyped address that only looked right used to be stored, fail at boot, and — before that was fixed — pay the config.h recipient instead.

Definition at line 724 of file provision.cpp.

References addr_tron_decode(), ETH_ADDR_LEN, and eth_addr_parse().

Referenced by state_get(), and value_post().

◆ ap_pass_draw()

void ap_pass_draw ( void )
static

Fill s_pass with AP_PASS_LEN characters of hardware entropy.

Definition at line 181 of file provision.cpp.

References AP_PASS_ALPHABET, AP_PASS_LEN, and s_pass.

Referenced by ap_pass_load().

◆ ap_pass_load()

void ap_pass_load ( void )
static

The AP passphrase: drawn once, then kept until a factory reset.

It used to be redrawn per session, so a photograph of the panel expired with the session that showed it. That cost more than it bought: the operator retypes ten characters every single time they open the page, and the passphrase they had written down is wrong every time.

What the redraw actually defended is the wifi_only portal, which asks for no admin code — so somebody who once photographed the passphrase can join the setup AP again and change which network the terminal joins. That still needs the terminal to have opened that portal by itself (it only does so when the venue network fails) and needs them standing inside its ~10 m of SoftAP, in front of the panel that is displaying the current passphrase to anyone looking anyway. Everything that moves money is behind the admin code, which is typed on the panel and never on the page.

Stored in NS_PROV, which settings_factory_reset() erases by name — so "reset the terminal" is the way to retire a passphrase that has got out.

Definition at line 214 of file provision.cpp.

References ap_pass_draw(), AP_PASS_LEN, K_AP_PASS, K_TLS_CRT, K_TLS_KEY, NS_PROV, and s_pass.

Referenced by prov_start().

◆ ap_ssid_build()

void ap_ssid_build ( void )
static

SSID from the SoftAP MAC, so two terminals in a room are tellable apart.

Definition at line 250 of file provision.cpp.

References s_ssid.

Referenced by prov_start().

◆ apple_probe()

esp_err_t apple_probe ( httpd_req_t * req)
static

Definition at line 1167 of file provision.cpp.

References PORTAL_URL.

Referenced by register_handlers().

◆ ask_label()

const char * ask_label ( prov_ask_t k)
static

Label the panel and the page both use for a pending proposal.

Definition at line 486 of file provision.cpp.

References PROV_ASK_CONTRACT_ETH, PROV_ASK_CONTRACT_TRON, PROV_ASK_PAYOUT_ETH, and PROV_ASK_PAYOUT_TRON.

Referenced by prov_pending(), prov_propose(), and state_get().

◆ auth_post()

esp_err_t auth_post ( httpd_req_t * req)
static

◆ authed()

bool authed ( httpd_req_t * req)
static

Whether the request is the browser that was let in.

Definition at line 399 of file provision.cpp.

References has_token(), and s_authed.

Referenced by build_prov(), gate(), and state_get().

◆ card_post()

esp_err_t card_post ( httpd_req_t * req)
static

The browser asks the terminal to read the addresses off a card.

Definition at line 951 of file provision.cpp.

References gate(), ok(), s_cb, TAG, and UI_EVENT_PROV_CARD.

Referenced by register_handlers().

◆ clock_post()

esp_err_t clock_post ( httpd_req_t * req)
static

Store the panel clock's standard offset from UTC and its DST rule.

Written straight through like the gas fees, and for the same reason: it cannot send money anywhere. The worst a wrong one does is put the wrong hour in the corner of the screen, which announces itself to the first person who looks.

The page sends both from one region list; dst is a civil_dst_t and a missing one means none, so a fixed offset is still a valid request.

The value is validated against the same bounds settings_set_tz_offset_min enforces, so a hand-rolled POST cannot store an offset the picker could not express — and it is rejected rather than clamped, since a clamped offset is a clock that is silently wrong by whatever the clamp moved it.

Definition at line 853 of file provision.cpp.

References form_field(), gate(), ok(), read_body(), reply(), settings_set_tz_dst(), settings_set_tz_offset_min(), TAG, tz_dst_valid(), tz_offset_valid(), and ui_clock_changed().

Referenced by register_handlers().

◆ contract_post()

esp_err_t contract_post ( httpd_req_t * req)
static

Definition at line 778 of file provision.cpp.

References value_post().

Referenced by register_handlers().

◆ dns_task()

void dns_task ( void * arg)
static

Answer every A query with the portal address.

Not a DNS server — it does not parse the question beyond finding where it ends, and it answers identically regardless of what was asked. That is the whole job: the phone's connectivity probe has to resolve to us before the HTTP half can fail it on purpose.

Definition at line 269 of file provision.cpp.

References s_dns_run, s_dns_task, and TAG.

Referenced by prov_start().

◆ expired()

bool expired ( void )
static

True once the portal's own window has closed.

Definition at line 370 of file provision.cpp.

References s_deadline_us.

Referenced by auth_post(), gate(), and settle_inflight().

◆ fees_post()

esp_err_t fees_post ( httpd_req_t * req)
static

Store the EIP-1559 gas caps (Gwei).

The one setting this page writes straight through instead of proposing it on the panel. An address decides who gets the money and so has to be read back by a human; a fee cap only decides how much gas the terminal will pay for its own transaction, and a wrong one is self-announcing — the sale is priced out of a block and the panel says so. Bounds are the ones the panel's steppers used to enforce, so a stored value cannot become something the old UI could not express.

Definition at line 790 of file provision.cpp.

References fee_pair_check(), FEE_PAIR_OUT_OF_RANGE, FEE_PAIR_TIP_ABOVE_MAX, form_field(), gate(), ok(), read_body(), reply(), settings_set_fees_gwei(), TAG, and ui_fees_changed().

Referenced by register_handlers().

◆ gate()

bool gate ( httpd_req_t * req,
esp_err_t * rc )
static

The gate every mutating endpoint runs first.

Parameters
[out]rcSet to the response already sent when this returns false.
Returns
true if the request may proceed.

Definition at line 433 of file provision.cpp.

References authed(), expired(), reply(), s_wifi_only, and uri_is().

Referenced by card_post(), clock_post(), fees_post(), network_post(), next_post(), ota_post(), rescan_post(), scan_get(), value_post(), and wifi_post().

◆ has_token()

bool has_token ( httpd_req_t * req)
static

Whether the request carries the token of the authorised session.

There is no admin code to check here — the code was typed on the panel, which is what turned s_authed on. So this only asks "are you the browser that was let in", and a wrong token is not a guessing attempt worth rate-limiting: it is 128 random bits, and guessing it does not get anybody past the on-screen confirmation that guards every value that matters anyway.

Definition at line 384 of file provision.cpp.

References s_token, and TOKEN_HEX_LEN.

Referenced by auth_post(), and authed().

◆ network_post()

esp_err_t network_post ( httpd_req_t * req)
static

Switch the terminal between the production and the test networks.

Written straight through and followed by a restart, which is the whole of the mechanism: the RPC endpoints, the chain ids and the token contracts are resolved once at boot into the dual stores that every signature is reconciled against, so there is no point at which a running terminal can be moved between networks without a boot. Trying would mean a payment whose nonce came from one chain and whose contract came from the other.

Not proposed on the panel like an address, for the reason the gas caps are not: this cannot send money anywhere. It decides where the operator's own payout address is paid — the same address on both — and it announces itself loudly, on the Tx tab and in the asset picker, the moment the terminal comes back up. It is behind the admin code either way, like everything else on this page.

The answer goes out before the reboot, with a pause long enough for it to reach the browser: the phone is on this device's own AP, so a restart with the reply still queued reads to the operator as the page having crashed.

Definition at line 914 of file provision.cpp.

References form_field(), gate(), ok(), read_body(), reply(), settings_get_mainnet(), settings_set_mainnet(), and TAG.

Referenced by register_handlers().

◆ next_post()

esp_err_t next_post ( httpd_req_t * req)
static

Definition at line 1015 of file provision.cpp.

References gate(), ok(), s_cb, and UI_EVENT_PROV_NEXT.

Referenced by register_handlers().

◆ ok()

◆ ota_post()

esp_err_t ota_post ( httpd_req_t * req)
static

Stream a firmware image into the idle slot, without booting it.

Straight to flash: the image is bigger than the heap, so there is no version of this that buffers it first. What makes that safe is ota.h's contract — nothing written here can run until the image's SHA-256 has been verified — and its signature too, on a build with Secure Boot (sdkconfig.defaults.release / .flash_encryption); the plain defaults check structure and self-hash only — AND somebody has accepted it on the panel.

Definition at line 1040 of file provision.cpp.

References gate(), ok(), ota_abort(), ota_begin(), ota_end(), ota_receiving(), ota_staged(), ota_write(), reply(), s_cb, s_upload, TAG, UI_EVENT_OTA_STAGED, UPLOAD_CHUNK, and UPLOAD_MAX_STALLS.

Referenced by register_handlers().

◆ page_get()

esp_err_t page_get ( httpd_req_t * req)
static

Definition at line 470 of file provision.cpp.

References PAGE_HTML, and PAGE_JS.

Referenced by register_handlers().

◆ payout_post()

esp_err_t payout_post ( httpd_req_t * req)
static

Definition at line 777 of file provision.cpp.

References value_post().

Referenced by register_handlers().

◆ prov_ap_pass()

const char * prov_ap_pass ( void )

AP passphrase, or "" while no portal is up.

Definition at line 1452 of file provision.cpp.

References s_pass.

Referenced by build_prov(), and open_portal_window().

◆ prov_ap_ssid()

const char * prov_ap_ssid ( void )

AP SSID, or "" while no portal is up.

Definition at line 1451 of file provision.cpp.

References s_ssid.

Referenced by build_prov(), and open_portal_window().

◆ prov_auth_pending()

bool prov_auth_pending ( void )

Whether a browser has asked to be authorised.

Set by POST /api/auth. The panel answers by taking the admin code and calling prov_auth_resolve. Reported as UI_EVENT_PROV_AUTH.

Definition at line 1455 of file provision.cpp.

References s_auth_pending.

◆ prov_auth_resolve()

void prov_auth_resolve ( bool grant)

Answer a pending authorisation request from the panel.

Parameters
[in]granttrue if the operator entered the correct admin code.

Definition at line 1457 of file provision.cpp.

References s_auth_pending, s_authed, s_cb, s_token, TAG, and UI_EVENT_PROV_NEXT.

Referenced by admin_submit(), and btn_event_cb().

◆ prov_authed()

bool prov_authed ( void )

Whether the browser session is authorised to change anything.

Definition at line 1475 of file provision.cpp.

References s_authed.

Referenced by build_prov(), and run_wizard().

◆ prov_mode()

prov_mode_t prov_mode ( void )

Which mode is running, or PROV_MODE_OFF.

Definition at line 1436 of file provision.cpp.

References s_mode.

Referenced by admin_submit(), app_main(), btn_event_cb(), run_wizard(), and ui_task().

◆ prov_pair_code()

bool prov_pair_code ( char * out,
size_t out_size )

The 4-digit pairing code of the browser asking to be let in.

Derived from the session token (its first 16 bits, mod 10000), so the page can compute the same number from the token it holds. Shown on the panel's admin prompt and on the page, so the operator approves the browser in their hand and not whichever one on the access point asked first.

Parameters
[out]outNUL-terminated code on success.
[in]out_size>= 5.
Returns
false when no browser has asked.

Definition at line 1477 of file provision.cpp.

References s_token.

Referenced by build_admin_unlock().

◆ prov_pending()

bool prov_pending ( prov_ask_t * kind,
char * label,
size_t label_n,
char * value,
size_t value_n )

Fetch the value a browser proposed but nobody has accepted.

Parameters
[out]kindWhat is being asked, may be NULL.
[out]labelHuman name for the panel ("Ethereum payout"), may be NULL.
[in]label_nCapacity of label.
[out]valueThe proposed address, may be NULL.
[in]value_nCapacity of value.
Returns
true if a proposal is pending.

Definition at line 1547 of file provision.cpp.

References ask_label(), PROV_ASK_NONE, s_ask, s_ask_lock, and s_ask_val.

Referenced by build_prov_confirm(), and state_get().

◆ prov_pending_commit()

bool prov_pending_commit ( bool accept)

Resolve a pending proposal from the panel.

Parameters
[in]accepttrue to commit it to NVS, false to discard it.
Returns
true if a value was committed — the caller then has to restart to apply it, since the recipient and contract dual stores are built at boot.

Definition at line 1569 of file provision.cpp.

References POS_CHAIN_ETH_USDC, POS_CHAIN_TRON_USDT, PROV_ASK_CONTRACT_ETH, PROV_ASK_CONTRACT_TRON, PROV_ASK_NONE, PROV_ASK_PAYOUT_ETH, PROV_ASK_PAYOUT_TRON, s_ask, s_ask_lock, s_ask_val, s_cb, settings_set_contract(), settings_set_payout(), UI_EVENT_PROV_VALUE_NO, and UI_EVENT_PROV_VALUE_SET.

Referenced by btn_event_cb().

◆ prov_propose()

bool prov_propose ( prov_ask_t kind,
const char * addr )

Propose a value on behalf of the panel itself.

Used by the card-derived route: the terminal reads an address off a Cryptnox card, then puts it through the very same accept-on-the-panel handshake a browser submission goes through, so there is one code path that stores an address and one screen that approves one.

Parameters
[in]kindWhat the value is.
[in]addrThe address; checked by the caller.
Returns
false if another proposal is already waiting.

Definition at line 1527 of file provision.cpp.

References ask_label(), PROV_ASK_NONE, s_ask, s_ask_lock, s_ask_val, s_cb, TAG, and UI_EVENT_PROV_VALUE.

Referenced by app_main(), run_wizard(), and value_post().

◆ prov_qr_payload()

const char * prov_qr_payload ( void )

What the panel's QR code should carry.

"WIFI:T:WPA;S:<ssid>;P:<pass>;;" — a camera joins the AP from it and the captive portal takes over, so one code is enough and there is no URL to read off the panel. Empty while no portal is up.

Definition at line 1453 of file provision.cpp.

References s_qr.

Referenced by build_prov(), and open_portal_window().

◆ prov_set_note()

void prov_set_note ( const char * note)

Put a one-line message on the page.

For the things only the device can know — a Wi-Fi network that would not join, a step that cannot be left yet. The browser is where the operator is looking, so that is where the reason has to appear; the panel is showing a QR code.

Parameters
[in]noteMessage, copied. NULL or "" clears it.

Definition at line 1493 of file provision.cpp.

References s_note, and s_share_mux.

Referenced by app_main(), and run_wizard().

◆ prov_set_scan()

void prov_set_scan ( const net_wifi_ap_t * aps,
uint16_t n )

Hand the portal a Wi-Fi scan for the browser to choose from.

The scan itself stays on the main task — scanning makes the radio hop channels, which briefly drops anyone joined to the SoftAP, so it happens deliberately at known moments (entering the Wi-Fi step, or a rescan the browser asked for) and never inside an HTTP handler.

Parameters
[in]apsScanned networks; copied.
[in]nHow many.

Definition at line 1516 of file provision.cpp.

References PROV_MAX_APS, s_ap_count, s_aps, s_scan_gen, and s_share_mux.

Referenced by app_main(), and run_wizard().

◆ prov_set_step()

void prov_set_step ( prov_step_t step)

Tell the portal which wizard step is current.

Definition at line 1438 of file provision.cpp.

References s_step.

Referenced by run_wizard().

◆ prov_set_wifi_only()

void prov_set_wifi_only ( void )

Cut the wizard down to the Wi-Fi step, with no admin code.

For a terminal that is already configured and has only lost its network. Call it right after prov_start (which clears it) and before any browser arrives; the first browser to ask is then let in without the panel demanding the code, and the panel drops the step numbering, since steps 1 and 3-4 do not happen.

The relaxation is bounded: the perimeter here is the AP's per-device passphrase, which is on the panel in front of whoever is asking, and everything that decides where money goes still has to be accepted on that panel. What it buys is an operator whose till has moved venues typing a password instead of walking three screens to be allowed to.

Definition at line 1489 of file provision.cpp.

References s_wifi_only.

Referenced by run_wizard().

◆ prov_start()

bool prov_start ( prov_mode_t mode,
ui_event_cb_t cb )

Raise the portal.

Idempotent for the same mode; a different mode is refused rather than silently switched, since the two serve different steps to the same page. Stop it first.

Raising the portal takes the terminal off its network for the duration (see above); prov_stop puts it back.

A new AP passphrase is drawn on every call and never stored: it is shown on a screen a customer can see, so a photograph of it must not still open the wifi_only portal — which asks for no admin code — weeks later. prov_stop() wipes it, and a reboot mid-setup simply shows the next one.

Parameters
[in]modeWhich portal to run.
[in]cbWhere submissions are reported; the same callback the UI task uses, so a form and a screen tap are indistinguishable to the main task. Must outlive the call.
Returns
true if the portal is up and reachable; false if the SoftAP or the HTTP server would not start.

Definition at line 1221 of file provision.cpp.

References ap_pass_load(), ap_ssid_build(), dns_task(), net_ap_start(), net_ap_stop(), net_wifi_init(), PORTAL_URL, PROV_MODE_ADMIN, PROV_MODE_OFF, PROV_MODE_WIZARD, PROV_STEP_ADMIN, PROV_STEP_AUTH, PROV_WINDOW_MIN, register_handlers(), s_ask_lock, s_auth_pending, s_authed, s_cb, s_deadline_us, s_dns_run, s_dns_task, s_httpd, s_mode, s_pass, s_qr, s_ssid, s_step, s_token, s_wifi_only, and TAG.

Referenced by open_portal_window(), and run_wizard().

◆ prov_step()

prov_step_t prov_step ( void )

The current step.

Definition at line 1440 of file provision.cpp.

References s_step.

Referenced by run_wizard().

◆ prov_stop()

void prov_stop ( void )

Stop the portal, drop the AP, and withdraw anything unaccepted.

Also re-joins the network the AP displaced, so a configured terminal is back online when the page closes rather than at the next reboot.

Definition at line 1374 of file provision.cpp.

References net_ap_stop(), ota_abort(), PROV_ASK_NONE, PROV_MODE_OFF, PROV_STEP_IDLE, s_ask, s_ask_lock, s_ask_val, s_auth_pending, s_authed, s_deadline_us, s_dns_run, s_dns_task, s_httpd, s_mode, s_pass, s_qr, s_step, s_token, s_wifi_only, and TAG.

Referenced by app_main(), and run_wizard().

◆ prov_wifi_only()

bool prov_wifi_only ( void )

Whether the portal is the cut-down Wi-Fi-only flow.

Definition at line 1491 of file provision.cpp.

References s_wifi_only.

Referenced by build_prov().

◆ prov_window_left_min()

unsigned prov_window_left_min ( void )

Minutes left before the portal closes itself, 0 once it has.

Definition at line 1442 of file provision.cpp.

References s_deadline_us, and s_httpd.

Referenced by open_portal_window(), state_get(), and ui_task().

◆ read_body()

bool read_body ( httpd_req_t * req,
char * out,
size_t n )
static

Read a request body into out.

Returns
false if it did not fit.

Definition at line 355 of file provision.cpp.

Referenced by clock_post(), fees_post(), network_post(), value_post(), and wifi_post().

◆ redirect()

esp_err_t redirect ( httpd_req_t * req)
static

Send every probe and stray URL to the portal.

This is the half that makes the browser open by itself. Each OS fetches a known URL after joining and only raises the portal UI if the answer is not what it expects, so answering correctly here would be the bug.

Definition at line 1135 of file provision.cpp.

References PORTAL_URL.

Referenced by redirect_404(), and register_handlers().

◆ redirect_404()

esp_err_t redirect_404 ( httpd_req_t * req,
httpd_err_code_t err )
static

404 handler — the catch-all for probe URLs not listed below.

Definition at line 1144 of file provision.cpp.

References redirect().

Referenced by register_handlers().

◆ register_handlers()

◆ reply()

esp_err_t reply ( httpd_req_t * req,
const char * status,
const char * msg )
static

Send a plain-text status line; the page shows it verbatim.

Definition at line 405 of file provision.cpp.

Referenced by auth_post(), clock_post(), fees_post(), gate(), network_post(), ok(), ota_post(), value_post(), and wifi_post().

◆ rescan_post()

esp_err_t rescan_post ( httpd_req_t * req)
static

Definition at line 1007 of file provision.cpp.

References gate(), ok(), s_cb, and UI_EVENT_PROV_SCAN.

Referenced by register_handlers().

◆ scan_get()

esp_err_t scan_get ( httpd_req_t * req)
static

◆ state_get()

◆ step_name()

const char * step_name ( prov_step_t s)
static

Definition at line 500 of file provision.cpp.

References PROV_STEP_ADDR, PROV_STEP_ADMIN, PROV_STEP_AUTH, PROV_STEP_DONE, and PROV_STEP_WIFI.

Referenced by state_get().

◆ uri_is()

bool uri_is ( const httpd_req_t * req,
const char * path )
static

Whether the request's path is path — req->uri carries any query string, which routing ignores and this must too.

Definition at line 421 of file provision.cpp.

Referenced by gate().

◆ value_post()

esp_err_t value_post ( httpd_req_t * req,
bool contract )
static

◆ wifi_post()

esp_err_t wifi_post ( httpd_req_t * req)
static

Definition at line 965 of file provision.cpp.

References form_field(), gate(), ok(), read_body(), reply(), s_cb, TAG, UI_EVENT_WIFI_TRY, and ui_stage_wifi_creds().

Referenced by register_handlers().

Variable Documentation

◆ AP_PASS_ALPHABET

const char AP_PASS_ALPHABET[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
static

Definition at line 70 of file provision.cpp.

Referenced by ap_pass_draw().

◆ PROBE_URIS

const char* const PROBE_URIS[]
static
Initial value:
= {
"/generate_204",
"/gen_204",
"/connecttest.txt",
"/ncsi.txt",
"/canonical.html",
"/success.txt",
"/chat",
}

Definition at line 1157 of file provision.cpp.

Referenced by register_handlers().

◆ s_ap_count

uint16_t s_ap_count = 0U
static

◆ s_aps

◆ s_ask

prov_ask_t s_ask = PROV_ASK_NONE
static

Definition at line 173 of file provision.cpp.

Referenced by prov_pending(), prov_pending_commit(), prov_propose(), and prov_stop().

◆ s_ask_lock

SemaphoreHandle_t s_ask_lock = NULL
static

Definition at line 172 of file provision.cpp.

Referenced by prov_pending(), prov_pending_commit(), prov_propose(), prov_start(), and prov_stop().

◆ s_ask_val

char s_ask_val[SETTINGS_PAYOUT_MAX] = ""
static

Definition at line 174 of file provision.cpp.

Referenced by prov_pending(), prov_pending_commit(), prov_propose(), and prov_stop().

◆ s_auth_pending

volatile bool s_auth_pending = false
static

◆ s_authed

volatile bool s_authed = false
static

Definition at line 144 of file provision.cpp.

Referenced by auth_post(), authed(), prov_auth_resolve(), prov_authed(), prov_start(), and prov_stop().

◆ s_cb

◆ s_deadline_us

int64_t s_deadline_us = 0
static

Definition at line 131 of file provision.cpp.

Referenced by expired(), prov_start(), prov_stop(), and prov_window_left_min().

◆ s_dns_run

volatile bool s_dns_run = false
static

Definition at line 120 of file provision.cpp.

Referenced by dns_task(), prov_start(), and prov_stop().

◆ s_dns_task

TaskHandle_t s_dns_task = NULL
static

Definition at line 119 of file provision.cpp.

Referenced by dns_task(), prov_start(), and prov_stop().

◆ s_httpd

httpd_handle_t s_httpd = NULL
static

Definition at line 118 of file provision.cpp.

Referenced by prov_start(), prov_stop(), prov_window_left_min(), and register_handlers().

◆ s_mode

std::atomic<prov_mode_t> s_mode {PROV_MODE_OFF}
static

Definition at line 129 of file provision.cpp.

Referenced by prov_mode(), prov_start(), prov_stop(), and state_get().

◆ s_note

char s_note[128] = ""
static

Definition at line 151 of file provision.cpp.

Referenced by prov_set_note(), and state_get().

◆ s_pass

char s_pass[AP_PASS_LEN+1U] = ""
static

Definition at line 134 of file provision.cpp.

Referenced by ap_pass_draw(), ap_pass_load(), prov_ap_pass(), prov_start(), and prov_stop().

◆ s_qr

char s_qr[96] = ""
static

Definition at line 135 of file provision.cpp.

Referenced by prov_qr_payload(), prov_start(), and prov_stop().

◆ s_scan_gen

std::atomic<uint32_t> s_scan_gen {0U}
static

Definition at line 166 of file provision.cpp.

Referenced by prov_set_scan(), and state_get().

◆ s_share_mux

portMUX_TYPE s_share_mux = portMUX_INITIALIZER_UNLOCKED
static

Definition at line 158 of file provision.cpp.

Referenced by prov_set_note(), prov_set_scan(), scan_get(), and state_get().

◆ s_ssid

char s_ssid[33] = ""
static

Definition at line 133 of file provision.cpp.

Referenced by ap_ssid_build(), prov_ap_ssid(), and prov_start().

◆ s_step

volatile prov_step_t s_step = PROV_STEP_IDLE
static

Definition at line 130 of file provision.cpp.

Referenced by prov_set_step(), prov_start(), prov_step(), prov_stop(), and state_get().

◆ s_token

char s_token[TOKEN_HEX_LEN+1U] = ""
static

Definition at line 142 of file provision.cpp.

◆ s_upload

uint8_t s_upload[UPLOAD_CHUNK]
static

Definition at line 137 of file provision.cpp.

Referenced by ota_post().

◆ s_wifi_only

volatile bool s_wifi_only = false
static

◆ TAG

const char* const TAG = "prov"
static

Definition at line 56 of file provision.cpp.