Commit 88f00074 authored by jan.koester's avatar jan.koester
Browse files

http2 post fixed

parent 3403a481
Loading
Loading
Loading
Loading
+46 −4
Original line number Diff line number Diff line
@@ -88,10 +88,21 @@ static std::string h2BuildFrame(uint8_t type, uint8_t flags, uint32_t stream_id,
    return f;
}

// RFC 7540: SETTINGS_INITIAL_WINDOW_SIZE applies per-stream.
// Use 16 MB so large POST bodies don't stall.
static constexpr uint32_t H2_INITIAL_WINDOW_SIZE = 16u * 1024 * 1024;

static std::string h2BuildSettings() {
    std::string p(6, '\0');
    // SETTINGS_MAX_CONCURRENT_STREAMS (0x03) = 100
    // SETTINGS_INITIAL_WINDOW_SIZE    (0x04) = H2_INITIAL_WINDOW_SIZE
    std::string p(12, '\0');
    p[0]  = 0x00; p[1]  = 0x03;
    p[2]  = 0x00; p[3]  = 0x00; p[4]  = 0x00; p[5]  = 0x64;
    p[6]  = 0x00; p[7]  = 0x04;
    p[8]  = static_cast<char>((H2_INITIAL_WINDOW_SIZE >> 24) & 0xff);
    p[9]  = static_cast<char>((H2_INITIAL_WINDOW_SIZE >> 16) & 0xff);
    p[10] = static_cast<char>((H2_INITIAL_WINDOW_SIZE >>  8) & 0xff);
    p[11] = static_cast<char>((H2_INITIAL_WINDOW_SIZE      ) & 0xff);
    return h2BuildFrame(H2_FRAME_SETTINGS, 0, 0, p);
}

@@ -99,6 +110,25 @@ static std::string h2BuildSettingsAck() {
    return h2BuildFrame(H2_FRAME_SETTINGS, H2_FLAG_ACK, 0, "");
}

// Build a WINDOW_UPDATE frame (RFC 7540 §6.9).
// stream_id==0 updates the connection window.
static std::string h2BuildWindowUpdate(uint32_t stream_id, uint32_t increment) {
    std::string p(4, '\0');
    p[0] = static_cast<char>((increment >> 24) & 0x7f);
    p[1] = static_cast<char>((increment >> 16) & 0xff);
    p[2] = static_cast<char>((increment >>  8) & 0xff);
    p[3] = static_cast<char>((increment      ) & 0xff);
    return h2BuildFrame(H2_FRAME_WINDOW_UPDATE, 0, stream_id, p);
}

// Connection-level WINDOW_UPDATE to raise the default 65535 window
// to match the per-stream INITIAL_WINDOW_SIZE.
static std::string h2ConnectionWindowBoost() {
    uint32_t boost = H2_INITIAL_WINDOW_SIZE - 65535u;
    if (boost == 0) return "";
    return h2BuildWindowUpdate(0, boost);
}

// Append DATA frames chunked to H2_MAX_FRAME_SIZE
static void h2AppendDataFrames(std::string &out, uint32_t stream_id,
                               const std::string &body, bool end_stream) {
@@ -261,7 +291,8 @@ libhttppp::HttpEvent::HttpEvent(std::vector<netplus::socket*> serversocket, int
                                           const std::string& /*body*/,
                                           const std::string& /*content_type*/) -> std::string {
                if (alpn == "h2" && stream_id == 0) {
                    return h2BuildSettings();
                    // SETTINGS + connection-level WINDOW_UPDATE
                    return h2BuildSettings() + h2ConnectionWindowBoost();
                }
                return "";
            });
@@ -451,6 +482,7 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon,
    // Send server SETTINGS if not already sent (e.g. ConnectEvent already sent it)
    if (cureq.SendData.empty()) {
        out += h2BuildSettings();
        out += h2ConnectionWindowBoost();
    }

    // Process all complete frames in RecvData
@@ -507,6 +539,14 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon,
            auto it = cureq.h2state().pendingIncoming.find(sid);
            if (it != cureq.h2state().pendingIncoming.end()) {
                it->second.body.append(data + off, flen);

                // Replenish flow-control windows so the client
                // can keep sending (both stream and connection).
                if (flen > 0) {
                    out += h2BuildWindowUpdate(sid, flen);
                    out += h2BuildWindowUpdate(0,   flen);
                }

                if (fflags & H2_FLAG_END_STREAM) {
                    // All body data received — dispatch the request
                    _dispatchH2Stream(cureq, out, sid,
@@ -785,6 +825,8 @@ REQUESTHANDLING:
                break;
            case POSTREQUEST: {
                size_t clen = cureq.getContentLength();
                std::cerr << "[H1-POST] clen=" << clen
                          << " recv=" << cureq.RecvData.size() << std::endl;
                if(clen == 0){
                    RequestEvent(cureq,tid,args);
                    cureq._RequestType=PARSEREQUEST;