Commit 3403a481 authored by jan.koester's avatar jan.koester
Browse files

http3 upload fixed

parent 4a4641e0
Loading
Loading
Loading
Loading
+54 −8
Original line number Diff line number Diff line
@@ -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;
    }

@@ -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());
+7 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>

@@ -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,