Commit d566cfe2 authored by jan.koester's avatar jan.koester
Browse files

phase 3 completed

parent 57cc954b
Loading
Loading
Loading
Loading
+299 −428

File changed.

Preview size limit exceeded, changes collapsed.

+16 −0
Changes for src/http.h: 16 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -185,6 +185,22 @@ namespace libhttppp {
      size_t _streamReadChunked(char *buf, size_t bufsize, bool blocking);
      size_t _streamReadEof(char *buf, size_t bufsize, bool blocking);

      // Same idea for STREAM_H2: readBodyChunk() and
      // readBodyChunkNonBlocking() previously carried two independently
      // hand-copied H2 frame-dispatch switches, which had already drifted
      // (the non-blocking copy had gained an explicit
      // H2C_FRAME_WINDOW_UPDATE case the blocking one lacked). The frame
      // dispatch itself is now written once; only how bytes are pulled off
      // the wire (wait vs. one non-blocking attempt) differs by `blocking`.
      size_t _streamReadH2(char *buf, size_t bufsize, bool blocking);

      // Same idea for STREAM_H3: the QUIC varint frame-parsing loop (partial
      // DATA-frame continuation handling included) was duplicated verbatim
      // between readBodyChunk() and readBodyChunkNonBlocking(); now written
      // once and shared, with only the "wait for more data vs. try once and
      // return" difference kept per-mode.
      size_t _streamReadH3(char *buf, size_t bufsize, bool blocking);

      // Shared Get/Post/Put/Delete implementation: builds+sends the request
      // over whichever transport is active (H1/H2/H3), follows redirects
      // per RFC 7231 §6.4 (303 always converts to a bodyless GET; 307/308
+54 −0
Changes for test/http2_checksum_test.cpp: 54 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -478,6 +478,60 @@ int main() {
                          "HttpClient POST " + label + ": server-reported sha256 matches client's");
                }
            }

            // ---- Streaming download via GetStream()/readBodyChunk() and
            // readBodyChunkNonBlocking(), both over the real H2 client path
            // (_streamReadH2()) -- 1MB guarantees the response spans several
            // real DATA frames (H2C_MAX_FRAME_SIZE=16384) and at least one
            // WINDOW_UPDATE round trip, unlike the buffered Get() sweep above
            // which never touches this code at all. ----
            {
                const size_t size = 1048576;
                libhttppp::HttpRequest req;
                req.setRequestURL("/gen/" + std::to_string(size));
                libhttppp::HttpResponse res = httpClt.GetStream(req);
                std::string want = headerValue(res, "x-sha256");

                std::vector<char> collected;
                collected.reserve(size);
                char buf[4096];
                for (;;) {
                    size_t n = httpClt.readBodyChunk(buf, sizeof(buf));
                    if (n == 0) break;
                    collected.insert(collected.end(), buf, buf + n);
                }
                std::string got = sha256Hex(collected);
                check(res.getStatusCode() == 200, "HTTP/2 streaming GET (blocking): 200 response");
                check(collected.size() == size, "HTTP/2 streaming GET (blocking): total bytes match");
                check(got == want, "HTTP/2 streaming GET (blocking): incrementally-hashed sha256 matches header");
            }

            {
                const size_t size = 1048576;
                libhttppp::HttpRequest req;
                req.setRequestURL("/gen/" + std::to_string(size));
                libhttppp::HttpResponse res = httpClt.GetStream(req);
                std::string want = headerValue(res, "x-sha256");

                std::vector<char> collected;
                collected.reserve(size);
                char buf[4096];
                auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(10);
                for (;;) {
                    if (std::chrono::steady_clock::now() > deadline) break;
                    size_t n = httpClt.readBodyChunkNonBlocking(buf, sizeof(buf));
                    if (n == static_cast<size_t>(-1)) break;
                    if (n == 0) {
                        std::this_thread::sleep_for(std::chrono::milliseconds(1));
                        continue;
                    }
                    collected.insert(collected.end(), buf, buf + n);
                }
                std::string got = sha256Hex(collected);
                check(res.getStatusCode() == 200, "HTTP/2 streaming GET (non-blocking): 200 response");
                check(collected.size() == size, "HTTP/2 streaming GET (non-blocking): total bytes match");
                check(got == want, "HTTP/2 streaming GET (non-blocking): incrementally-hashed sha256 matches header");
            }
        }

        // shutdownGuard stops and joins the server thread here (its
+28 −0
Changes for test/http3_checksum_test.cpp: 28 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -183,6 +183,34 @@ int main() {
            check(got == want, "streaming GET: incrementally-hashed sha256 matches header");
        }

        // ---- Same, via readBodyChunkNonBlocking() (_streamReadH3(blocking=false)) ----
        {
            const size_t size = 1048576;
            libhttppp::HttpRequest req;
            req.setRequestURL("/gen/" + std::to_string(size));
            libhttppp::HttpResponse res = clt.GetStream(req);
            std::string want = headerValue(res, "x-sha256");

            std::vector<char> collected;
            collected.reserve(size);
            char buf[4096];
            auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(10);
            for (;;) {
                if (std::chrono::steady_clock::now() > deadline) break;
                size_t n = clt.readBodyChunkNonBlocking(buf, sizeof(buf));
                if (n == static_cast<size_t>(-1)) break;
                if (n == 0) {
                    std::this_thread::sleep_for(std::chrono::milliseconds(1));
                    continue;
                }
                collected.insert(collected.end(), buf, buf + n);
            }
            std::string got = sha256Hex(collected);
            check(res.getStatusCode() == 200, "streaming GET (non-blocking): 200 response");
            check(collected.size() == size, "streaming GET (non-blocking): total bytes match");
            check(got == want, "streaming GET (non-blocking): incrementally-hashed sha256 matches header");
        }

        // shutdownGuard stops and joins the server thread here.

    } catch (libhttppp::HTTPException &e) {