Loading src/httpd.cpp +46 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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) { Loading Loading @@ -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 ""; }); Loading Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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; Loading Loading
src/httpd.cpp +46 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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) { Loading Loading @@ -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 ""; }); Loading Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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; Loading