Commit 172ddb03 authored by jan.koester's avatar jan.koester
Browse files

teset

parent 7f9fa43c
Loading
Loading
Loading
Loading
+33 −6
Changes for src/httpd.cpp: 33 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -398,6 +398,21 @@ bool libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq,
              << " activeAlready=" << had_active
              << std::endl;

    // Seed this stream's flow-control window now, synchronously, while we
    // hold the connection's event_mutex (see epoll.cpp's per-event lock
    // around dispatch). Offloaded requests hand the actual response off to
    // a background pool and don't call _finishH2Dispatch — which is what
    // normally sets this up — until the render completes; a fast peer can
    // send a WINDOW_UPDATE for this stream before that happens. Without an
    // entry here yet, that WINDOW_UPDATE finds nothing in peerStreamWindows
    // to credit (see the H2_FRAME_WINDOW_UPDATE case below) and is silently
    // discarded — permanently, since a well-behaved peer never repeats a
    // credit grant it believes already landed. The stream is then capped at
    // whatever the default window covers and stalls forever once that's
    // exhausted, with no further WINDOW_UPDATE ever coming to unstick it.
    cureq.h2state().peerStreamWindows.try_emplace(
        sid, cureq.h2state().peerInitialStreamWindow);

    // Store POST body in RecvData so HttpForm::parse() can access it
    if (!reqBody.empty()) {
        tempreq.RecvData.append(reqBody.data(), reqBody.size());
@@ -503,9 +518,13 @@ void libhttppp::HttpEvent::_finishH2Dispatch(HttpRequest &cureq,
            tempreq.h2state().expectedContentLength = content_length;
            tempreq.SendData.pos = 0;

            // Initialise per-stream peer window
            cureq.h2state().peerStreamWindows[sid] =
                cureq.h2state().peerInitialStreamWindow;
            // Per-stream peer window was already seeded in
            // _dispatchH2Stream. Don't overwrite it here — a WINDOW_UPDATE
            // for this stream may have already arrived (and been credited
            // to that entry) while an offloaded render was in flight; an
            // unconditional reassignment here would silently discard it.
            cureq.h2state().peerStreamWindows.try_emplace(
                sid, cureq.h2state().peerInitialStreamWindow);

            // Collect extra :res-* headers
            std::vector<libhttppp::hpack::HeaderField> extra;
@@ -634,9 +653,12 @@ void libhttppp::HttpEvent::_finishH2Dispatch(HttpRequest &cureq,
        std::string hpack_out = libhttppp::hpack::Encoder::encodeResponseHeaders(
            status_code, content_type, body.size(), extra);

        // Initialise per-stream peer window for flow control
        cureq.h2state().peerStreamWindows[sid] =
            cureq.h2state().peerInitialStreamWindow;
        // Per-stream peer window was already seeded in _dispatchH2Stream —
        // see the comment there. Don't overwrite it here; it may already
        // carry credit from a WINDOW_UPDATE that arrived while an offloaded
        // render was in flight.
        cureq.h2state().peerStreamWindows.try_emplace(
            sid, cureq.h2state().peerInitialStreamWindow);

        // HEADERS frame
        uint8_t hdr_flags = H2_FLAG_END_HEADERS;
@@ -689,6 +711,11 @@ void libhttppp::HttpEvent::_finishH2Dispatch(HttpRequest &cureq,
        uint8_t rst[4] = {0, 0, 0, 0x02}; // INTERNAL_ERROR
        out += h2BuildFrame(H2_FRAME_RST_STREAM, 0, sid,
            std::string(reinterpret_cast<char*>(rst), 4));
        // This stream's window (seeded in _dispatchH2Stream) never got
        // used since no response body was ever sent — drop it rather than
        // leaking one stale entry per failed dispatch on a long-lived
        // connection.
        cureq.h2state().peerStreamWindows.erase(sid);
    }
}