Loading src/httpd.cpp +54 −8 Original line number Diff line number Diff line Loading @@ -557,7 +557,38 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, uint64_t stream_id, const std::vector<uint8_t> &data, bool fin) { if (!fin || data.empty()) { std::cerr << "[H3-STREAM] stream_id=" << stream_id << " data_size=" << data.size() << " fin=" << fin << std::endl; if (data.empty() && !fin) { return; } // Accumulate stream data until fin is received { std::lock_guard<std::mutex> lock(_h3BufferMutex); auto &buf = _h3StreamBuffers[stream_id]; if (!data.empty()) { buf.data.insert(buf.data.end(), data.begin(), data.end()); } if (!fin) { return; // Wait for more data } } // fin received — extract the complete buffered data and remove entry std::vector<uint8_t> completeData; { std::lock_guard<std::mutex> lock(_h3BufferMutex); auto it = _h3StreamBuffers.find(stream_id); if (it != _h3StreamBuffers.end()) { completeData = std::move(it->second.data); _h3StreamBuffers.erase(it); } } if (completeData.empty()) { return; } Loading @@ -573,39 +604,54 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, std::string bodyData; size_t offset = 0; while (offset < data.size()) { int frame_idx = 0; while (offset < completeData.size()) { size_t bytes = 0; uint64_t frame_type = h3DecodeVarInt(&data[offset], data.size() - offset, bytes); uint64_t frame_type = h3DecodeVarInt(&completeData[offset], completeData.size() - offset, bytes); if (bytes == 0) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " type varint decode failed at offset=" << offset << std::endl; break; } offset += bytes; if (offset >= data.size()) { if (offset >= completeData.size()) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " offset=" << offset << " >= size=" << completeData.size() << " after type" << std::endl; break; } uint64_t frame_len = h3DecodeVarInt(&data[offset], data.size() - offset, bytes); uint64_t frame_len = h3DecodeVarInt(&completeData[offset], completeData.size() - offset, bytes); if (bytes == 0) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " len varint decode failed at offset=" << offset << std::endl; break; } offset += bytes; if (offset + frame_len > data.size()) { if (offset + frame_len > completeData.size()) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " type=0x" << std::hex << frame_type << std::dec << " len=" << frame_len << " offset=" << offset << " exceeds size=" << completeData.size() << std::endl; break; } std::cerr << "[H3-FRAME] frame#" << frame_idx << " type=0x" << std::hex << frame_type << std::dec << " len=" << frame_len << " offset=" << offset << std::endl; if (frame_type == 0x01) { // HEADERS frame headersPayload.assign(&data[offset], &data[offset + frame_len]); headersPayload.assign(&completeData[offset], &completeData[offset + frame_len]); } else if (frame_type == 0x00) { // DATA frame bodyData.append(reinterpret_cast<const char*>(&data[offset]), frame_len); bodyData.append(reinterpret_cast<const char*>(&completeData[offset]), frame_len); } offset += frame_len; frame_idx++; } if (headersPayload.empty()) { std::cerr << "[H3-STREAM] No HEADERS frame found in " << completeData.size() << " bytes" << std::endl; return; } std::cerr << "[H3-STREAM] HEADERS=" << headersPayload.size() << " BODY=" << bodyData.size() << std::endl; // Decode QPACK headers auto decoded = libhttppp::qpack::Decoder::decode( headersPayload.data(), headersPayload.size()); Loading src/httpd.h +7 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <cstdint> #include <map> #include <memory> #include <mutex> #include <string> #include <vector> Loading Loading @@ -66,6 +67,12 @@ namespace libhttppp { void CreateConnection(std::shared_ptr<netplus::con> &res); std::string _altSvcH3; // Alt-Svc value for HTTP/3 advertisement private: // Per-stream buffer for HTTP/3: accumulates data until fin struct H3StreamBuffer { std::vector<uint8_t> data; }; std::mutex _h3BufferMutex; std::map<uint64_t, H3StreamBuffer> _h3StreamBuffers; void _dispatchH2Stream(HttpRequest &cureq, std::string &out, uint32_t sid, const std::vector<hpack::HeaderField> &decoded, Loading Loading
src/httpd.cpp +54 −8 Original line number Diff line number Diff line Loading @@ -557,7 +557,38 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, uint64_t stream_id, const std::vector<uint8_t> &data, bool fin) { if (!fin || data.empty()) { std::cerr << "[H3-STREAM] stream_id=" << stream_id << " data_size=" << data.size() << " fin=" << fin << std::endl; if (data.empty() && !fin) { return; } // Accumulate stream data until fin is received { std::lock_guard<std::mutex> lock(_h3BufferMutex); auto &buf = _h3StreamBuffers[stream_id]; if (!data.empty()) { buf.data.insert(buf.data.end(), data.begin(), data.end()); } if (!fin) { return; // Wait for more data } } // fin received — extract the complete buffered data and remove entry std::vector<uint8_t> completeData; { std::lock_guard<std::mutex> lock(_h3BufferMutex); auto it = _h3StreamBuffers.find(stream_id); if (it != _h3StreamBuffers.end()) { completeData = std::move(it->second.data); _h3StreamBuffers.erase(it); } } if (completeData.empty()) { return; } Loading @@ -573,39 +604,54 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, std::string bodyData; size_t offset = 0; while (offset < data.size()) { int frame_idx = 0; while (offset < completeData.size()) { size_t bytes = 0; uint64_t frame_type = h3DecodeVarInt(&data[offset], data.size() - offset, bytes); uint64_t frame_type = h3DecodeVarInt(&completeData[offset], completeData.size() - offset, bytes); if (bytes == 0) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " type varint decode failed at offset=" << offset << std::endl; break; } offset += bytes; if (offset >= data.size()) { if (offset >= completeData.size()) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " offset=" << offset << " >= size=" << completeData.size() << " after type" << std::endl; break; } uint64_t frame_len = h3DecodeVarInt(&data[offset], data.size() - offset, bytes); uint64_t frame_len = h3DecodeVarInt(&completeData[offset], completeData.size() - offset, bytes); if (bytes == 0) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " len varint decode failed at offset=" << offset << std::endl; break; } offset += bytes; if (offset + frame_len > data.size()) { if (offset + frame_len > completeData.size()) { std::cerr << "[H3-FRAME] frame#" << frame_idx << " type=0x" << std::hex << frame_type << std::dec << " len=" << frame_len << " offset=" << offset << " exceeds size=" << completeData.size() << std::endl; break; } std::cerr << "[H3-FRAME] frame#" << frame_idx << " type=0x" << std::hex << frame_type << std::dec << " len=" << frame_len << " offset=" << offset << std::endl; if (frame_type == 0x01) { // HEADERS frame headersPayload.assign(&data[offset], &data[offset + frame_len]); headersPayload.assign(&completeData[offset], &completeData[offset + frame_len]); } else if (frame_type == 0x00) { // DATA frame bodyData.append(reinterpret_cast<const char*>(&data[offset]), frame_len); bodyData.append(reinterpret_cast<const char*>(&completeData[offset]), frame_len); } offset += frame_len; frame_idx++; } if (headersPayload.empty()) { std::cerr << "[H3-STREAM] No HEADERS frame found in " << completeData.size() << " bytes" << std::endl; return; } std::cerr << "[H3-STREAM] HEADERS=" << headersPayload.size() << " BODY=" << bodyData.size() << std::endl; // Decode QPACK headers auto decoded = libhttppp::qpack::Decoder::decode( headersPayload.data(), headersPayload.size()); Loading
src/httpd.h +7 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <cstdint> #include <map> #include <memory> #include <mutex> #include <string> #include <vector> Loading Loading @@ -66,6 +67,12 @@ namespace libhttppp { void CreateConnection(std::shared_ptr<netplus::con> &res); std::string _altSvcH3; // Alt-Svc value for HTTP/3 advertisement private: // Per-stream buffer for HTTP/3: accumulates data until fin struct H3StreamBuffer { std::vector<uint8_t> data; }; std::mutex _h3BufferMutex; std::map<uint64_t, H3StreamBuffer> _h3StreamBuffers; void _dispatchH2Stream(HttpRequest &cureq, std::string &out, uint32_t sid, const std::vector<hpack::HeaderField> &decoded, Loading