Skip to content

Latest commit

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

jktcp

A userspace TCP stack that runs over any async read/write transport.

Designed for reliable, ordered transports: such as CDTunnel from idevice or a Unix socket carrying raw IP frames where real packet loss is rare but correctness still matters. The stack handles the TCP handshake, ACK tracking, and retransmission so that the rest of your code can work with ordinary AsyncRead / AsyncWrite streams.

Features

  • 3-way handshake with SYN retransmission on timeout
  • Stop-and-wait reliability: a segment is retransmitted with exponential back-off (200 ms -> 400 ms -> … → 6.4 s) until acknowledged
  • Connection timeout: after 5 failed retransmissions the connection is closed with ErrorKind::TimedOut
  • In-order delivery: out-of-order segments are dropped; duplicate segments are re-ACKed without re-buffering
  • IPv4 and IPv6 transports
  • PCAP capture for Wireshark debugging
  • Two usage patterns to match your lifetime and threading needs (see below)

Two usage patterns

1. AdapterStream - single-task, lifetime-bound

AdapterStream<'a> holds a &'a mut Adapter. While the stream exists it has exclusive access to the adapter; there can only be one open stream at a time.

Use this when:

  • You open one connection at a time.
  • The stream lives entirely within a single async task.
  • You don't need to store the stream in a struct or send it across tasks.
use jktcp::adapter::Adapter;use jktcp::stream::AdapterStream;use tokio::io::{AsyncReadExt,AsyncWriteExt};use std::net::IpAddr;letmut adapter = Adapter::new(Box::new(transport), host_ip, peer_ip);// Optional: write a .pcap for Wireshark
adapter.pcap("capture.pcap").await?;letmut stream = AdapterStream::connect(&mut adapter,1234).await?;
stream.write_all(b"hello").await?;letmut buf = [0u8;1024];let n = stream.read(&mut buf).await?;println!("got: {:?}",&buf[..n]);
stream.close().await?;

2. AdapterHandle / StreamHandle: multi-task, 'static

AdapterHandle::new (or Adapter::to_async_handle) spawns the adapter's I/O loop onto the Tokio runtime. Streams are created by calling handle.connect(port) and the returned StreamHandle is Send + Sync + 'static.

A 1 ms internal tick drives retransmission and write-buffer flushing even when no callers are actively awaiting, so retransmit timeouts are accurate regardless of what the caller is doing.

Use this when:

  • You need multiple concurrent connections on the same adapter.
  • The stream must cross a tokio::spawn boundary.
  • You store the stream in a struct (no lifetime parameter needed).
  • You expose the stream through a 'static trait object or FFI boundary.
use jktcp::adapter::Adapter;use tokio::io::{AsyncReadExt,AsyncWriteExt};use std::net::IpAddr;let adapter = Adapter::new(Box::new(transport), host_ip, peer_ip);letmut handle = adapter.to_async_handle();// Optional PCAP
handle.pcap("capture.pcap").await?;// Open two connections concurrentlyletmut s1 = handle.connect(1234).await?;letmut s2 = handle.connect(5678).await?;// StreamHandle is Send, move it into another task
tokio::spawn(asyncmove{
s1.write_all(b"from task").await.unwrap();letmut buf = [0u8;64];
s1.read(&mut buf).await.unwrap();});
s2.write_all(b"direct").await?;

Choosing between the two

AdapterStreamAdapterHandle / StreamHandle
Concurrent connectionsOne at a timeMany
Cross-task (tokio::spawn)NoYes
'static boundNoYes
Store in struct without lifetimeNoYes
OverheadMinimal (direct &mut)Small channel round-trip per write
Retransmit timerFires on next process_tcp_packet timeout (≤500 ms)1 ms background tick

Transport requirements

The transport passed to Adapter::new must implement AsyncRead + AsyncWrite + Unpin + Send + Sync + Debug (the [jktcp::ReadWrite] trait). It must carry framed IPv4 or IPv6 packets, jktcp does not add its own framing. TUN devices, CDTunnel connections, and in-process pipes (e.g. tokio::io::duplex) all work.

PCAP debugging

Call adapter.pcap("out.pcap") (or handle.pcap(…)) before opening any connections. The file is a standard libpcap capture and can be opened directly in Wireshark.

Retransmission details

RetryRTO
1st200 ms
2nd400 ms
3rd800 ms
4th1.6 s
5th3.2 s
(killed)after 6.4 s without ACK

After the 5th retry the connection is marked Error(TimedOut). The next read or write on the stream will return that error.

About

A userspace TCP/IP stack for use in tokio programs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages