G1 step 3: the Gemini fetcher (TOFU, redirects, floors, pages via the card)

GeminiService fetches on a short-lived task and hands the App a
GeminiPage: header, the body as lines in 4 KB chunks (TextBuffer: no
large block, no doubling copies), the final URL after up to 5
redirects. Certificates are pinned on first use per host and port; a
change comes back as its own outcome with both fingerprints. No fetch
starts below 55 KB free (Q86).

With a card, the body streams to /gemini/cache/page.gmi in 1 KB pieces
while the connection is open, then loads into RAM once its memory is
back (Q87); StorageService::runAndWait (moved from the Debug Console)
keeps every card access on the storage task. Without a card: RAM, with
the steady and transient floors.

Measured with IRC connected: Cosmos (31.6 KB) went from 4.6 KB to the
whole page on the card and 20 KB on screen; lowest free heap 19.5 KB
in transfer, 43 KB once loaded. `gemini get` and `gemini trust` on the
console. 14 Gemini tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-05 00:58:01 +02:00
co-authored by Claude Opus 5.5
parent babb1d114e
commit 7b8d9391a4
12 changed files with 552 additions and 130 deletions
+2
View File
@@ -14,6 +14,8 @@ struct GemLine {
std::string text, url;
};
// One line; `preformatted` carries the ``` state from line to line (start with false).
GemLine parseGemLine(const std::string& line, bool& preformatted);
std::vector<GemLine> parseGemtext(const std::string& document);
// For the Latin-1 fonts (Q79): valid UTF-8 up to U+00FF kept, anything else '?', and tabs