Commit 5b6ab140 authored by jan.koester's avatar jan.koester
Browse files

test

parent 89bd12b0
Loading
Loading
Loading
Loading
+64 −14
Changes for src/httpd.cpp: 64 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -683,32 +683,77 @@ void libhttppp::HttpEvent::_finishH2Dispatch(HttpRequest &cureq,
}

bool libhttppp::HttpEvent::_flushSendDataNow(HttpRequest &cureq) {
    if (!(cureq.SendData.pos < cureq.SendData.size() && cureq.slots[0].csock))
        return cureq.SendData.pos >= cureq.SendData.size();
    auto &slot = cureq.slots[0];

    if (!slot.csock) {
        return false;
    }

    bool blocked = false;

    try {
        while (cureq.SendData.pos < cureq.SendData.size()) {
            size_t remaining = cureq.SendData.size() - cureq.SendData.pos;
            size_t sendlen = std::min(remaining, static_cast<size_t>(16384));
            netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos, sendlen);
            size_t sent = cureq.slots[0].csock->sendData(buf, 0);
            if (sent > 0) {
            const size_t remaining = cureq.SendData.size() - cureq.SendData.pos;
            const size_t sendlen = std::min<size_t>(remaining, 16 * 1024);

            netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos,
                                sendlen);
            const size_t sent = slot.csock->sendData(buf, 0);

            if (sent == 0) {
                blocked = true;
                break;
            }

            cureq.SendData.pos += sent;
                if (cureq.slots[0].csock->hasPendingWrite())
                    cureq.slots[0].csock->flush_out();
            } else {

            // sendData() may only enqueue encrypted TLS records. Try to
            // push them immediately, but retain the write interest when the
            // transport cannot drain the complete output buffer right now.
            if (slot.csock->hasPendingWrite()) {
                slot.csock->flush_out();
                if (slot.csock->hasPendingWrite()) {
                    blocked = true;
                    break;
                }
            }
        }
    } catch (const std::exception &e) {
        std::cerr << "[HTTP-WRITE] deferred: " << e.what()
                  << " pos=" << cureq.SendData.pos
                  << " size=" << cureq.SendData.size()
                  << std::endl;
        blocked = true;
    } catch (...) {
        // Socket busy or error — remaining data will be flushed
        // by IoEventHandler's send loop after we return.
        std::cerr << "[HTTP-WRITE] deferred: unknown exception"
                  << " pos=" << cureq.SendData.pos
                  << " size=" << cureq.SendData.size()
                  << std::endl;
        blocked = true;
    }
    if (cureq.SendData.pos >= cureq.SendData.size()) {

    const bool appDataDone = cureq.SendData.pos >= cureq.SendData.size();
    const bool transportDone = !slot.csock->hasPendingWrite();

    if (appDataDone) {
        // sendData() has taken ownership of all plaintext bytes. It is safe
        // to release that buffer even when encrypted transport bytes are
        // still queued inside the socket implementation.
        cureq.SendData.clear();
        cureq.SendData.pos = 0;
    }
    return cureq.SendData.pos >= cureq.SendData.size();

    if (appDataDone && transportDone && !blocked) {
        slot.ResponsePending.store(false, std::memory_order_release);
        return true;
    }

    // A short write, EAGAIN, or queued TLS output must explicitly re-arm
    // EPOLLOUT/EVFILT_WRITE. Merely leaving bytes in SendData is not enough
    // with an edge-triggered or one-shot event loop.
    slot.ResponsePending.store(true, std::memory_order_release);
    netplus::requestWritablePoll(cureq);
    return false;
}

void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq,
@@ -1875,6 +1920,11 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON
                    Http2RequestEvent(curcon, tid, args, "h2c", nullCb);
                }
            }

            // DATA generated above must be handed to the socket now. If the
            // socket is temporarily blocked, _flushSendDataNow() re-arms the
            // writable event so the response cannot remain parked forever.
            _flushSendDataNow(cureq);
            return;
        }