Crate tcptotcp

Crate tcptotcp 

Source
Expand description

§tcptotcp

A tiny, dependency-free TCP bridge that relays bytes bidirectionally between two std::net::TcpStream connections.

This crate is useful when you already have two established TCP streams (e.g. client socket and upstream socket) and you want to forward traffic between them with a simple, blocking implementation.

§What it does

  • Spawns two threads:
    • Thread A: reads from stream1 and writes to stream2
    • Thread B: reads from stream2 and writes to stream1
  • Tracks activity (traffic) in both directions.
  • Runs a periodic check loop on the calling thread:
    • If both directions had traffic recently, the idle counter resets.
    • If idle persists beyond the configured threshold, both streams are shut down and connect() returns.

§Important notes

  • This is not OS-level TCP keepalive (it does not send keepalive probes). “Alive” here means traffic passed through the bridge.
  • connect() is blocking: it returns when either side closes, an I/O error occurs, or the traffic-based idle timeout triggers.
  • The implementation uses blocking I/O + std::thread.

§Parameters

  • rate_check_seconds: how often the calling thread checks for traffic (seconds). Values < 1 are clamped to 1.
  • keep_alive_delay_time_seconds: max allowed idle time without traffic (seconds). Values < 2 are clamped to 2.

Internally the idle limit is roughly: max_delay = keep_alive_delay_time_seconds / rate_check_seconds (floor).

§Example: accept local clients and forward to an upstream

use std::net::{TcpListener, TcpStream};
use std::thread;
use tcptotcp::connect;

fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:9000")?;
    println!("Listening on 127.0.0.1:9000");

    for incoming in listener.incoming() {
        let client = incoming?;
        let upstream = TcpStream::connect("example.com:80")?;

        // Check every 5s, close if there is no bridged traffic for 2 hours.
        let rate_check_seconds: u8 = 5;
        let idle_timeout_seconds: u64 = 7_200;

        thread::spawn(move || {
            let _ = connect(client, upstream, rate_check_seconds, idle_timeout_seconds);
        });
    }

    Ok(())
}

Functions§

connect
Bridge (relay) bytes bidirectionally between two TcpStreams.