Updates: a download that breaks is carried on
CI / build (pull_request) Successful in 2m6s
Site / build (pull_request) Successful in 11s

When the connection breaks during a release download (issue #54), the
device waits up to a minute for Wi-Fi, asks for the rest of the file
with a Range request and carries on: the slot and the hash so far are
kept. It gives up after three tries in a row that bring nothing.
Nothing is kept across a restart.

Carrying on asks for 64 KB free, not 80: between two connections of an
install 78 KB is free, and the first attempt on the device was refused
for that. update damage cut now breaks every connection after n bytes.

Tried on the device: v0.23.0 installed over four connections, and a
download that brought nothing given up with nothing switched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
2026-10-11 18:26:39 +02:00
co-authored by Claude Opus 5.5
parent 468dc0dc0d
commit 472f13260f
12 changed files with 155 additions and 21 deletions
+11
View File
@@ -20,12 +20,22 @@ class HttpsGet {
// checking the certificate); with Q86's 20 KB to spare, it starts with at least this much free.
static constexpr size_t kNeedFree = 80 * 1024;
// Carrying on a download (issue #54) happens in the middle of an install, whose own buffers
// (about 8 KB, measured: 78 KB free between two connections) are already taken out of what is
// free, and with the screen taken over nothing else will ask for memory: the peak and 12 KB.
static constexpr size_t kNeedFreeToCarryOn = 64 * 1024;
explicit HttpsGet(net::User user) : tls_(user) {}
~HttpsGet() { close(); }
// Connects and reads the head. "" when a 200 is on its way, or why not, in words for the screen.
std::string open(const std::string& host, const std::string& path, const char* accept);
// The same, for the rest of a file from byte `from` (issue #54): asks for that range, with
// `ifRange` (an ETag, or "") so that a file that changed comes whole. The answer, a 206 or
// not, is for the caller to judge with head(): "" here only says a head was read.
std::string openFrom(const std::string& host, const std::string& path, const char* accept, long from, const std::string& ifRange);
long contentLength() const { return head_.contentLength; } // -1: not known
const release::HttpHead& head() const { return head_; }
// Body bytes into `buf`: how many, 0 at the end, -1 when the connection broke or stalled
// before the end.
@@ -37,6 +47,7 @@ class HttpsGet {
static constexpr uint32_t kStallMs = 10000;
int readRaw(uint8_t* into, size_t len); // from the connection, waiting up to kStallMs
std::string request(const std::string& host, const std::string& path, const char* accept, const std::string& more, size_t needFree);
Counted<NetworkClientSecure> tls_;
release::HttpHead head_;