#pragma once #include #include #include #include "http_head.h" #include "platform/counted_client.h" namespace roro { // One HTTPS GET, read as a stream: the connection checks the server's chain and name against the // roots in ca_roots.h, the head is parsed, and the body comes out whole whether the server sent it // with a length or in chunks. Used by the Update Service to read Gitea's answers and to download a // release. Redirects aren't followed: the device only goes where it was told to (Q163). class HttpsGet { public: // A TLS connection to Gitea peaks at about 52 KB of heap (measured: the same with or without // 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; 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); long contentLength() const { return head_.contentLength; } // -1: not known // Body bytes into `buf`: how many, 0 at the end, -1 when the connection broke or stalled // before the end. int read(uint8_t* buf, size_t len); void close(); private: static constexpr size_t kRaw = 1024; static constexpr uint32_t kStallMs = 10000; int readRaw(uint8_t* into, size_t len); // from the connection, waiting up to kStallMs Counted tls_; release::HttpHead head_; release::ChunkedDecoder chunks_; std::unique_ptr raw_; std::string early_; // body bytes that arrived with the head size_t earlyAt_ = 0; long left_ = -1; // body bytes still to come, if the server said how many bool done_ = false; }; } // namespace roro