|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The panel asking GitHub for its newest release, and fetching it. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "fw_image.h"#include "fw_release.h"#include "fw_upload.h"#include "wa_session.h"Go to the source code of this file.
Data Structures | |
| struct | wa_fetch_t |
| struct | wa_fetch_res_t |
| struct | wa_http_head_t |
| struct | wa_http_t |
| struct | wa_run_t |
Macros | |
| #define | WA_FETCH_CHECK_MS 30000u |
| #define | WA_FETCH_JOIN_MS 30000u |
| #define | WA_FETCH_DOWNLOAD_MS 180000u |
| #define | WA_FETCH_OP_MS 10000u |
Enumerations | |
| enum | wa_job_t { WA_JOB_CHECK = 0 , WA_JOB_DOWNLOAD } |
| enum | wa_channel_t { WA_CH_STABLE = 0 , WA_CH_TESTING } |
| enum | wa_phase_t { WA_PH_IDLE = 0 , WA_PH_JOINING , WA_PH_ASKING , WA_PH_SUMS , WA_PH_IMAGE , WA_PH_CHECKING , WA_PH_ENDED } |
| enum | wa_got_t { WA_GOT_NONE = 0 , WA_GOT_NEWER , WA_GOT_CURRENT , WA_GOT_STAGED , WA_GOT_NO_NET , WA_GOT_BLOCKED , WA_GOT_ABORTED , WA_GOT_JOIN , WA_GOT_RADIO , WA_GOT_TIMEOUT , WA_GOT_CONNECT , WA_GOT_REFUSED , WA_GOT_UNEXPECTED , WA_GOT_SUMS , WA_GOT_HASH , WA_GOT_IMAGE , WA_GOT_MEMORY , WA_GOT_LIMIT , WA_GOT_UNVERSIONED , WA_GOT_PAST_LINE } |
| enum | wa_why_t { WA_WHY_NONE = 0 , WA_WHY_ARMED , WA_WHY_SUPPLY , WA_WHY_RUN , WA_WHY_STOP , WA_WHY_FILES , WA_WHY_COPROC , WA_WHY_INSTALL , WA_WHY_CANCEL , WA_WHY_BUSY , WA_WHY_DRAWING } |
Functions | |
| void | wa_fetch_init (wa_fetch_t *f, fw_version_t running) |
| wa_why_t | wa_fetch_gate (bool armed, bool supply, bool run, bool coproc, bool installing) |
| wa_why_t | wa_fetch_start_gate (wa_why_t gate, bool taken, bool task_alive, bool other) |
| The gate a job's start takes, past the bench's own. | |
| wa_got_t | wa_fetch_start (wa_fetch_t *f, wa_job_t job, fw_version_t want, wa_channel_t ch, bool have_net, wa_why_t gate, uint32_t now_ms) |
| bool | wa_fetch_offers (const wa_fetch_t *f, wa_channel_t now) |
| bool | wa_fetch_stale (const wa_fetch_t *f, wa_channel_t now) |
| bool | wa_fetch_busy (const wa_fetch_t *f) |
| bool | wa_fetch_has_found (const wa_fetch_t *f) |
| Whether the last job names a release in wa_fetch_t.found. | |
| void | wa_fetch_tick (wa_fetch_t *f, uint32_t now_ms, wa_why_t abort, const wa_t *w) |
| void | wa_fetch_abort (wa_fetch_t *f, wa_why_t why) |
| uint32_t | wa_fetch_left (const wa_fetch_t *f, uint32_t now_ms) |
| bool | wa_fetch_take_off (wa_fetch_t *f) |
| bool | wa_fetch_take_run (wa_fetch_t *f) |
| void | wa_fetch_on_phase (wa_fetch_t *f, uint32_t gen, wa_phase_t ph) |
| void | wa_fetch_on_bytes (wa_fetch_t *f, uint32_t gen, uint32_t done, uint32_t total) |
| void | wa_fetch_on_end (wa_fetch_t *f, uint32_t gen, const wa_fetch_res_t *r) |
| void | wa_run_check (const wa_run_t *r, wa_fetch_res_t *out) |
| void | wa_run_download (const wa_run_t *r, fw_version_t v, wa_fetch_res_t *out) |
The panel asking GitHub for its newest release, and fetching it.
Two jobs, each on the home network the panel keeps (wa_session.h, WA_MODE_FETCH: no page, no name), each with the radio on only for its length:
CHECK join, then one HTTPS (HTTP over TLS, transport layer security) GET for the newest release of the job's channel. STABLE: FW_REL_LATEST_URL, whose redirect's Location names it (fw_release_parse_tag()); when that release is past the panel's release line and newer than the running build, one request of FW_REL_API_URL more, whose highest release of the line is offered in its place when it is newer than the running build, and which leaves the result as it was when it fails. TESTING: FW_REL_API_URL with GitHub's API headers, whose answer's 10 newest releases by date name it, the highest version among them that is no draft (fw_release_scan_feed()), read up to the 10th release's end and no further, with a Content-Length or in chunks; 403 and 429, GitHub's request limit, end as LIMIT. Where the highest is past the panel's release line, the highest of the line among them stands in for it when it is offered. Either way a release is NEWER only when fw_release_offered() says so; one newer than the running build and past the line is PAST_LINE. Join, address and request take WA_FETCH_CHECK_MS at most, together. DOWNLOAD join within WA_FETCH_JOIN_MS, then SHA256SUMS and the panel image of one release, each through at most FW_REL_HOPS_MAX redirects to the hosts fw_release.h allows, the image into memory; its SHA-256 against its SHA256SUMS line, then every fw_image_check(); WA_FETCH_DOWNLOAD_MS at most from the start. What it leaves is an image staged as an upload would leave it, for the existing installer. No flash is written here.
Two halves. The job (wa_fetch_t) lives with the session under the platform's lock: started and ticked by the UI loop, which holds the budget, the gate and every abort, and told by the radio and by the runner what happened. The runner (wa_run_check(), wa_run_download()) runs on a task of its own against an HTTP client the platform passes in (wa_http_t), so the host suite runs it against a scripted one. A job ended from outside – the budget, STOP, ARMED, the supply, a log run, WI-FI, CANCEL – stays ended: what the runner reports after it is dropped (the job's generation).
Pure C, no ESP-IDF (Espressif Internet-of-Things Development Framework).
SPDX-License-Identifier: MIT
| #define WA_FETCH_CHECK_MS 30000u |
CHECK: join, address and the request, together.
| #define WA_FETCH_DOWNLOAD_MS 180000u |
DOWNLOAD: from the start to a checked image.
| #define WA_FETCH_JOIN_MS 30000u |
DOWNLOAD: join and address.
| #define WA_FETCH_OP_MS 10000u |
One connection or one read waits this long at most, and never past the job's budget.
| enum wa_channel_t |
| enum wa_got_t |
How a job ended.
| Enumerator | |
|---|---|
| WA_GOT_NONE | under way, or none ran |
| WA_GOT_NEWER | CHECK: a newer release, wa_fetch_t.found |
| WA_GOT_CURRENT | CHECK: none newer than the running build |
| WA_GOT_STAGED | DOWNLOAD: the image waits, checked |
| WA_GOT_NO_NET | no home network kept: nothing started |
| WA_GOT_BLOCKED | the gate: nothing started; see why |
| WA_GOT_ABORTED | ended from outside; see why |
| WA_GOT_JOIN | the join failed; see join |
| WA_GOT_RADIO | the radio did not come up |
| WA_GOT_TIMEOUT | the budget ran out |
| WA_GOT_CONNECT | no connection: name, TCP or TLS failed |
| WA_GOT_REFUSED | an HTTP status the step does not take |
| WA_GOT_UNEXPECTED | an answer out of form; see rel |
| WA_GOT_SUMS | SHA256SUMS missing, out of form or without the image's line; see rel |
| WA_GOT_HASH | the image's SHA-256 is not SHA256SUMS' |
| WA_GOT_IMAGE | the image checks refused it; see img |
| WA_GOT_MEMORY | no memory for the image |
| WA_GOT_LIMIT | CHECK on TESTING: 403 or 429, GitHub's limit of requests without an account; see status |
| WA_GOT_UNVERSIONED | CHECK: the running version did not parse, so nothing is offered; wa_fetch_t.found |
| WA_GOT_PAST_LINE | CHECK: the newest release is newer than the running build and past the panel's release line (fw_release_in_line()): not offered; wa_fetch_t.found |
| enum wa_phase_t |
| enum wa_why_t |
Why a job did not start, or was ended from outside.
| void wa_fetch_abort | ( | wa_fetch_t * | f, |
| wa_why_t | why ) |
End the job now for why; nothing when none runs.
| bool wa_fetch_busy | ( | const wa_fetch_t * | f | ) |
Whether a job runs: joining to checking.
| wa_why_t wa_fetch_gate | ( | bool | armed, |
| bool | supply, | ||
| bool | run, | ||
| bool | coproc, | ||
| bool | installing ) |
The gate as wa_gate() takes it, plus the panel's own two.
| bool wa_fetch_has_found | ( | const wa_fetch_t * | f | ) |
Whether the last job names a release in wa_fetch_t.found.
| f | the job; NULL reads as none |
| void wa_fetch_init | ( | wa_fetch_t * | f, |
| fw_version_t | running ) |
No job; running is the build that runs.
| uint32_t wa_fetch_left | ( | const wa_fetch_t * | f, |
| uint32_t | now_ms ) |
ms of the budget left at now_ms for the phase under way; 0 when it is spent or no job runs.
| bool wa_fetch_offers | ( | const wa_fetch_t * | f, |
| wa_channel_t | now ) |
Whether the last job is a CHECK that found a release to offer on channel now: ended NEWER, and run on now. A check on the other channel offers nothing: RELEASES changed after it.
| bool wa_fetch_stale | ( | const wa_fetch_t * | f, |
| wa_channel_t | now ) |
Whether the last job is a CHECK that ended on another channel than now: its result is not shown, as if no check had run.
| wa_got_t wa_fetch_start | ( | wa_fetch_t * | f, |
| wa_job_t | job, | ||
| fw_version_t | want, | ||
| wa_channel_t | ch, | ||
| bool | have_net, | ||
| wa_why_t | gate, | ||
| uint32_t | now_ms ) |
Start job at now_ms for release want (DOWNLOAD; ignored by CHECK) on channel ch (CHECK; kept by DOWNLOAD too). WA_GOT_NONE and JOINING: the platform starts the radio in WA_MODE_FETCH. Otherwise the job has ended at once: NO_NET without have_net, BLOCKED for gate or for a job already running (why).
The gate a job's start takes, past the bench's own.
The radio goes off without waiting for the last job's task: a name lookup under way when the radio goes ends only when lwIP gives up on it, up to about 7s per DNS (Domain Name System) server. Until that task has ended no job starts, so it never runs beside the next job's; a session (WI-FI) starts without waiting for it.
| gate | the bench's gate (wa_fetch_gate()), or WA_WHY_NONE |
| taken | an image is taken for the install |
| task_alive | the last job's task has not ended |
| other | a session other than WA_MODE_FETCH asks for the radio |
gate when it is set; WA_WHY_BUSY for any of the other three; WA_WHY_NONE otherwise | bool wa_fetch_take_off | ( | wa_fetch_t * | f | ) |
True once after the job ended: the radio goes off.
| bool wa_fetch_take_run | ( | wa_fetch_t * | f | ) |
True once after the join: the runner starts.
| void wa_fetch_tick | ( | wa_fetch_t * | f, |
| uint32_t | now_ms, | ||
| wa_why_t | abort, | ||
| const wa_t * | w ) |
Once a frame, after wa_tick(): abort as the UI loop sees it now (WA_WHY_NONE for none), w the session. Ends the job for an abort, for the session going off under it and for the budget; moves JOINING on once the session has its address. The platform reads owe_off and owe_run after it.
| void wa_run_check | ( | const wa_run_t * | r, |
| wa_fetch_res_t * | out ) |
CHECK, from the join on. NEWER, CURRENT, UNVERSIONED, or why not.
| void wa_run_download | ( | const wa_run_t * | r, |
| fw_version_t | v, | ||
| wa_fetch_res_t * | out ) |
DOWNLOAD of release v, from the join on. STAGED with the image in r->up, or why not with r->up not staged.