Commit 982ec948 authored by jan.koester's avatar jan.koester
Browse files

test

parent 8bd8611f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ enable_testing ()

set(LIBV "1.0.0")
set(Upstream_VERSION 1.0.0)
set (BLOCKSIZE 65536 CACHE STRING "Block size from Network Packages")

set (DEFAULT_UPLOADSIZE 4e+6 CACHE STRING "Block size for Uploads")

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+2 −2
Original line number Diff line number Diff line
@@ -6,14 +6,14 @@

#define EVENT_HEADER ${EVENT_HEADER}

#define BLOCKSIZE ${BLOCKSIZE}

#define PATHSIZE 1024

#define MAXDEFAULTCONN 1024

#define MAXHEADERSIZE 16384

#define CHUNKSIZE 65536

#define NEWLINE "\r\n"

//#define DEBUG
+2 −2
Original line number Diff line number Diff line
@@ -251,12 +251,12 @@ public:
    void ResponseEvent(libhttppp::HttpRequest& curreq, const int tid,ULONG_PTR args){
        if (curreq.getRequestURL()=="/images/header.png") {
            size_t rem = header_png_size - curreq.SendData.pos;
            size_t si  = (rem > BLOCKSIZE) ? BLOCKSIZE : rem;
            size_t si  = (rem > CHUNKSIZE) ? CHUNKSIZE : rem;
            curreq.SendData.append((const char*)header_png + curreq.SendData.pos, si);
            curreq.SendData.pos += si;
        } else if(curreq.getRequestURL()=="/favicon.ico"){
            if(curreq.SendData.pos < favicon_ico_size){
                size_t si = BLOCKSIZE < (favicon_ico_size-curreq.SendData.pos) ? BLOCKSIZE : (favicon_ico_size-curreq.SendData.pos);
                size_t si = CHUNKSIZE < (favicon_ico_size-curreq.SendData.pos) ? CHUNKSIZE : (favicon_ico_size-curreq.SendData.pos);
                curreq.SendData.append((const char*)favicon_ico+curreq.SendData.pos, si);
                curreq.SendData.pos+=si;
            }
+124 −20
Original line number Diff line number Diff line
@@ -540,7 +540,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
        if (header_end != std::string::npos)
            break;

        netplus::buffer buf(BLOCKSIZE);
        netplus::buffer buf(CHUNKSIZE);
        // Short timeout for initial server response — if the server doesn't
        // start responding within 10s, the connection is likely dead.
        size_t n = _recvBlocking(buf, 10);
@@ -607,7 +607,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
        remaining -= can;

        while (remaining > 0) {
            netplus::buffer buf(BLOCKSIZE);
            netplus::buffer buf(CHUNKSIZE);
            size_t n = _recvBlocking(buf);
            if (n == 0) {
                netplus::NetException ne;
@@ -627,7 +627,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe

        auto ensure_bytes = [&](size_t need) {
            while (raw.size() - pos < need) {
                netplus::buffer buf(BLOCKSIZE);
                netplus::buffer buf(CHUNKSIZE);
                size_t n = _recvBlocking(buf);
                if (n == 0) {
                    netplus::NetException ne;
@@ -648,7 +648,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
                        return line;
                    }
                }
                netplus::buffer buf(BLOCKSIZE);
                netplus::buffer buf(CHUNKSIZE);
                size_t n = _recvBlocking(buf);
                if (n == 0) {
                    netplus::NetException ne;
@@ -706,7 +706,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
            ret.insert(ret.end(), raw.begin() + (ptrdiff_t)pos, raw.end());
        }
        for (;;) {
            netplus::buffer buf(BLOCKSIZE);
            netplus::buffer buf(CHUNKSIZE);
            size_t n = 0;
            try {
                n = _recvBlocking(buf);
@@ -985,7 +985,7 @@ libhttppp::HttpResponse libhttppp::HttpClient::GetStream(libhttppp::HttpRequest

            auto h2_ensure_bytes = [&](size_t need) {
                while (_streamH2Raw.size() < need) {
                    netplus::buffer buf(BLOCKSIZE);
                    netplus::buffer buf(CHUNKSIZE);
                    size_t n = _recvBlocking(buf, 15);
                    if (n == 0) {
                        HTTPException he;
@@ -1115,7 +1115,7 @@ libhttppp::HttpResponse libhttppp::HttpClient::GetStream(libhttppp::HttpRequest
            if (header_end != std::string::npos)
                break;

            netplus::buffer buf(BLOCKSIZE);
            netplus::buffer buf(CHUNKSIZE);
            size_t n = _recvBlocking(buf, 10);
            if (n == 0) {
                netplus::NetException ne;
@@ -1214,7 +1214,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {

    // Helper: receive more data into internal buffer
    auto recvMore = [&]() -> size_t {
        netplus::buffer nb(BLOCKSIZE);
        netplus::buffer nb(CHUNKSIZE);
        size_t n = _recvBlocking(nb);
        if (n > 0) {
            if (_streamBufPos > 0 && _streamBufPos < _streamBuf.size()) {
@@ -1246,7 +1246,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {
        }

        // Read from socket
        netplus::buffer nb(BLOCKSIZE);
        netplus::buffer nb(CHUNKSIZE);
        size_t n = _recvBlocking(nb);
        if (n == 0) {
            _streamMode = STREAM_NONE;
@@ -1309,7 +1309,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {
                return got;
            }
            // Read from socket directly
            netplus::buffer nb(BLOCKSIZE);
            netplus::buffer nb(CHUNKSIZE);
            size_t n = _recvBlocking(nb);
            if (n == 0) {
                _streamChunkDone = true;
@@ -1373,7 +1373,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {
        if (got > 0) return got;

        // Read from socket; EOF signals end of body
        netplus::buffer nb(BLOCKSIZE);
        netplus::buffer nb(CHUNKSIZE);
        size_t n = 0;
        try {
            n = _recvBlocking(nb);
@@ -1408,7 +1408,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {
        // Read more H2 frames until we get DATA for our stream
        auto h2_ensure_bytes = [&](size_t need) {
            while (_streamH2Raw.size() < need) {
                netplus::buffer fbuf(BLOCKSIZE);
                netplus::buffer fbuf(CHUNKSIZE);
                size_t n = _recvBlocking(fbuf);
                if (n == 0) {
                    _streamH2EndStream = true;
@@ -1447,8 +1447,13 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) {
                }
                case H2C_FRAME_DATA: {
                    if (frame_stream == _streamH2Sid) {
                        _streamBuf.insert(_streamBuf.end(), payload, payload + frame_len);
                        // Compact buffer before appending: remove already-consumed bytes
                        if (_streamBufPos > 0) {
                            _streamBuf.erase(_streamBuf.begin(),
                                _streamBuf.begin() + static_cast<ptrdiff_t>(_streamBufPos));
                            _streamBufPos = 0;
                        }
                        _streamBuf.insert(_streamBuf.end(), payload, payload + frame_len);
                        if (frame_len > 0) {
                            _sendAll(h2cBuildWindowUpdate(0, frame_len));
                            _sendAll(h2cBuildWindowUpdate(_streamH2Sid, frame_len));
@@ -1672,7 +1677,7 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize
        }

        // Non-blocking read from socket
        netplus::buffer nb(BLOCKSIZE);
        netplus::buffer nb(CHUNKSIZE);
        size_t n = _recvNonBlocking(nb);
        if (n == 0)
            return 0;  // No data yet — caller should retry later
@@ -1733,8 +1738,8 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize
                _streamH3Raw.insert(_streamH3Raw.end(), rbuf, rbuf + n);
                got_any = true;
            }
            if (!got_any) {
                if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty()
            if (!got_any && _streamH3Raw.empty() && !_streamH3InDataFrame) {
                if (q->isStreamComplete(_streamH3Sid)
                    && !q->hasStreamData(_streamH3Sid)) {
                    _streamH3EndStream = true;
                    _streamMode = STREAM_NONE;
@@ -1807,7 +1812,106 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize
        return 0;
    }

    // For chunked/EOF/H2 modes, fall back to blocking readBodyChunk
    // ── HTTP/2 non-blocking streaming ──
    if (_streamMode == STREAM_H2) {
        // First drain any body data buffered during GetStream / previous reads
        size_t got = drainBuf(bufsize);
        if (got > 0) return got;

        if (_streamH2EndStream) {
            _streamMode = STREAM_NONE;
            return static_cast<size_t>(-1);
        }

        // Non-blocking read from socket — always try, append to _streamH2Raw
        {
            netplus::buffer nbuf(CHUNKSIZE);
            size_t n = _recvNonBlocking(nbuf);
            if (n > 0) {
                _streamH2Raw.insert(_streamH2Raw.end(),
                    reinterpret_cast<uint8_t*>(nbuf.data.buf),
                    reinterpret_cast<uint8_t*>(nbuf.data.buf) + n);
            }
        }

        // Process all complete H2 frames in _streamH2Raw
        while (_streamH2Raw.size() >= H2C_FRAME_HEADER_LEN) {
            uint32_t frame_len = (static_cast<uint32_t>(_streamH2Raw[0]) << 16)
                               | (static_cast<uint32_t>(_streamH2Raw[1]) << 8)
                               | static_cast<uint32_t>(_streamH2Raw[2]);
            uint8_t frame_type = _streamH2Raw[3];
            uint8_t frame_flags = _streamH2Raw[4];
            uint32_t frame_stream = ((static_cast<uint32_t>(_streamH2Raw[5]) & 0x7f) << 24)
                                  | (static_cast<uint32_t>(_streamH2Raw[6]) << 16)
                                  | (static_cast<uint32_t>(_streamH2Raw[7]) << 8)
                                  | static_cast<uint32_t>(_streamH2Raw[8]);

            if (_streamH2Raw.size() < H2C_FRAME_HEADER_LEN + frame_len)
                break;  // incomplete frame, wait for more data

            const uint8_t *payload = _streamH2Raw.data() + H2C_FRAME_HEADER_LEN;

            switch (frame_type) {
                case H2C_FRAME_SETTINGS: {
                    if (!(frame_flags & H2C_FLAG_ACK))
                        _sendAll(h2cBuildSettingsAck());
                    break;
                }
                case H2C_FRAME_DATA: {
                    if (frame_stream == _streamH2Sid) {
                        if (_streamBufPos > 0) {
                            _streamBuf.erase(_streamBuf.begin(),
                                _streamBuf.begin() + static_cast<ptrdiff_t>(_streamBufPos));
                            _streamBufPos = 0;
                        }
                        _streamBuf.insert(_streamBuf.end(), payload, payload + frame_len);
                        if (frame_len > 0) {
                            _sendAll(h2cBuildWindowUpdate(0, frame_len));
                            _sendAll(h2cBuildWindowUpdate(_streamH2Sid, frame_len));
                        }
                        if (frame_flags & H2C_FLAG_END_STREAM)
                            _streamH2EndStream = true;
                    }
                    break;
                }
                case H2C_FRAME_HEADERS: {
                    if (frame_stream == _streamH2Sid && (frame_flags & H2C_FLAG_END_STREAM))
                        _streamH2EndStream = true;
                    break;
                }
                case H2C_FRAME_WINDOW_UPDATE:
                    // Server-side window update: nothing to do for client reads
                    break;
                case H2C_FRAME_PING: {
                    if (!(frame_flags & H2C_FLAG_ACK)) {
                        std::string ping_payload(reinterpret_cast<const char*>(payload), frame_len);
                        _sendAll(h2cBuildFrame(H2C_FRAME_PING, H2C_FLAG_ACK, 0, ping_payload));
                    }
                    break;
                }
                case H2C_FRAME_GOAWAY:
                    _streamH2EndStream = true;
                    break;
                default:
                    break;
            }

            _streamH2Raw.erase(_streamH2Raw.begin(),
                _streamH2Raw.begin() + H2C_FRAME_HEADER_LEN + frame_len);
        }

        // Drain newly received body data
        got = drainBuf(bufsize);
        if (got > 0) return got;

        if (_streamH2EndStream) {
            _streamMode = STREAM_NONE;
            return static_cast<size_t>(-1);
        }
        return 0;
    }

    // For chunked/EOF modes, fall back to blocking readBodyChunk
    return readBodyChunk(buf, bufsize);
}

@@ -2142,7 +2246,7 @@ const std::vector<char> libhttppp::HttpClient::_h2Request(
            // Try a non-blocking read to pick up the server's SETTINGS
            // (which usually arrives right after TLS handshake).
            {
                netplus::buffer nbuf(BLOCKSIZE);
                netplus::buffer nbuf(CHUNKSIZE);
                size_t n = 0;
                try { n = _cltsock->recvData(nbuf, 0); } catch (...) {}
                if (n > 0) {
@@ -2159,7 +2263,7 @@ const std::vector<char> libhttppp::HttpClient::_h2Request(

                // If window exhausted, block-read for WINDOW_UPDATE
                while (allowed <= 0) {
                    netplus::buffer nbuf(BLOCKSIZE);
                    netplus::buffer nbuf(CHUNKSIZE);
                    size_t n = recv_blocking(nbuf);
                    if (n == 0) {
                        HTTPException he;
@@ -2197,7 +2301,7 @@ const std::vector<char> libhttppp::HttpClient::_h2Request(
        // Read enough data into raw buffer
        auto ensure_bytes = [&](size_t need) {
            while (raw.size() < need) {
                netplus::buffer buf(BLOCKSIZE);
                netplus::buffer buf(CHUNKSIZE);
                size_t n = recv_blocking(buf);
                if (n == 0) {
                    HTTPException he;
+1 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ namespace libhttppp {
      // Peer flow-control windows (RFC 7540 §6.9)
      int32_t peerConnWindow = 65535;     // connection-level
      int32_t peerInitialStreamWindow = 65535; // from peer SETTINGS
      size_t  peerMaxFrameSize = 16384;        // from peer SETTINGS_MAX_FRAME_SIZE (0x05)
      std::map<uint32_t, int32_t> peerStreamWindows; // per-stream
      // Active streaming responses (one per stream)
      std::map<uint32_t, std::shared_ptr<H2StreamingResponse>> activeStreams;
Loading