Commit 7b39fcb5 authored by jan.koester's avatar jan.koester
Browse files

test

parent bfdf5d4b
Loading
Loading
Loading
Loading
+32 −1
Changes for src/httpd.cpp: 32 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -679,6 +679,16 @@ void libhttppp::HttpEvent::_finishH2Dispatch(HttpRequest &cureq,
                cureq.h2state().peerStreamWindows.erase(sid);
            }
        }
    } else {
        // Application never produced a response (forgot to call
        // HttpResponse::send / equivalent, or an internal handler path
        // returned without answering). Previously this left the stream
        // open with nothing ever sent -- no HEADERS, no DATA, no
        // RST_STREAM -- so the client just hangs forever. Cancel the
        // stream instead so the client sees a definitive failure.
        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));
    }
}

@@ -1306,7 +1316,8 @@ done:
    // waiting on responses).
    // Guard: limit reprocessing iterations to prevent infinite spin when
    // frames continuously generate output (e.g. ACKs) without consuming data.
    if (reprocess_count < 16 && (!out.empty() || off > 0 || anyOffloaded) && cureq.RecvData.size() >= H2_FRAME_HEADER_LEN) {
    if ((!out.empty() || off > 0 || anyOffloaded) && cureq.RecvData.size() >= H2_FRAME_HEADER_LEN) {
        if (reprocess_count < 16) {
            ++reprocess_count;
            out.clear();
            out.reserve(4096);
@@ -1314,6 +1325,21 @@ done:
            goto reprocess;
        }

        // Fairness cap hit while frames for further streams are still
        // buffered (e.g. a client bursting >17 simple GET/HEAD requests
        // over one multiplexed connection in a single read). SendData was
        // already flushed synchronously above, so epoll's own writable
        // check sees nothing queued and won't call ResponseEvent on its
        // own -- and the client won't send more bytes, it's waiting on
        // responses already dispatched. Without an explicit rearm here,
        // the remaining request(s) are stranded in RecvData forever.
        // ResponseEvent's H2 branch unconditionally reprocesses leftover
        // frames, so requesting a writable poll gets them handled with a
        // fresh reprocess budget.
        cureq.slots[0].ResponsePending.store(true, std::memory_order_release);
        netplus::requestWritablePoll(cureq);
    }

    return true;
}

@@ -1687,6 +1713,11 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock,
        tempreq.deldata(":res-content-type");
        tempreq.deldata(":res-content-length");
    } else {
        // The application never produced a response for this H3 request
        // (mirrors the H2 case in _finishH2Dispatch). Without this, the
        // stream is left open with nothing ever sent, and the client
        // hangs forever waiting for a reply that will never arrive.
        q->resetStream(stream_id, 0x0102); // H3_INTERNAL_ERROR
    }
}