#317·rathole

Data channel commands aren't flushed, so the check to see if the connection is healthy doesn't always work

Author: RyanADCreated Dec 21, 2023Updated Sep 8, 2026
Labelsbug

I've run into issues where the data channel was unhealthy, but it wasn't detected with this check:

if ch.write_all(&cmd).await.is_ok() {
    tokio::spawn(async move {
        let _ = copy_bidirectional(&mut ch, &mut visitor).await;
    });
    break;
} else {
    // Current data channel is broken. Request for a new one
    if data_ch_req_tx.send(true).is_err() {
        break 'pool;
    }
}

Ultimately it was because the ch.write_all(&cmd) may not cause the buffer to be flushed. The cause of this is that the connection is assumed healthy, but then fails during copy_bidirectional. It also means the TCP connection pool won't always be the correct size.

I've implemented the fix that is working for me in this PR: https://github.com/rapiz1/rathole/pull/316