Commit 13fe040e authored by jan.koester's avatar jan.koester
Browse files

test

parent 4ce7bac9
Loading
Loading
Loading
Loading
+22 −0
Changes for src/http/WebSocketProxy.cpp: 22 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -234,25 +234,47 @@ void relayLoop(std::unique_ptr<netplus::socket> client,
        time_t lastActivity = std::time(nullptr);

        for (;;) {
            // A TLS socket may already hold one or more decrypted records in its own receive
            // buffer even though the kernel fd is no longer readable. Waiting only in
            // socketwait in that state strands those records forever: no new edge has to
            // arrive, and Home Assistant's tiny auth_ok/auth_invalid frame is a particularly
            // easy victim. Check transport-owned buffering before polling the fds.
            ready.assign(socks.size(), false);
            ready[0] = client->hasBufferedData();
            ready[1] = upstream->hasBufferedData();

            if (!ready[0] && !ready[1]) {
                int n = sw.waitReadMulti(socks, ready, /*timeout_ms=*/60000);
                if (n <= 0) {
                    if (std::time(nullptr) - lastActivity > kWsIdleTimeoutSeconds) break;
                    continue; // timeout -- keep waiting, WebSocket pings keep this alive
                }
            }

            if (ready[0]) {
                try {
                    netplus::buffer buf(16384);
                    size_t r = client->recvData(buf, 0);
                    if (r == 0) break; // client closed
                    sendAll(*upstream, std::string(buf.data.buf, r));
                    lastActivity = std::time(nullptr);
                } catch (const netplus::NetException &e) {
                    // TLS recvData() uses Note for a live connection whose readable record was
                    // control traffic (e.g. KeyUpdate/NewSessionTicket) rather than application
                    // data. That is a retry condition, not a tunnel disconnect.
                    if (e.getErrorType() != netplus::NetException::Note) break;
                }
            }
            if (ready[1]) {
                try {
                    netplus::buffer buf(16384);
                    size_t r = upstream->recvData(buf, 0);
                    if (r == 0) break; // upstream closed
                    sendAll(*client, std::string(buf.data.buf, r));
                    lastActivity = std::time(nullptr);
                } catch (const netplus::NetException &e) {
                    if (e.getErrorType() != netplus::NetException::Note) break;
                }
            }
        }
    } catch (const netplus::NetException &) {