Interactive primer

TCP, TLS & why the legacy web
isn’t delay-tolerant

A scroll-through, click-through tour of how a connection actually gets made and secured, and exactly where the “must be live right now” assumption is baked in. Everything below is interactive: press the buttons, drag the sliders, break things.

01, the core idea

Two ways to move a message

Almost every networking question comes down to which of these two worlds you’re in.

① Circuit (TCP / TLS)

A live, two-way conversation. Both ends keep state (sequence numbers, buffers, keys) and assume the other side is reachable continuously. Silence past a timeout = the line is dead.

Like a phone call: if the other person stops talking for 30s, you hang up.

② Store-and-forward (DTN / Hop)

A sealed message is handed node-to-node, held when there’s no onward path, and forwarded later. No end-to-end liveness required. Minutes, hours, or a walk across town are fine.

Like passing a sealed letter through whoever’s headed the right way.

TCP and TLS are firmly world ①. The rest of this page shows where that liveness is enforced, so the boundary with world ② is unmistakable.

02, opening a connection

TCP’s 3-way handshake

Before any data moves, TCP must establish a connection: three packets, each carrying SEQ/ACK numbers so both sides agree where the byte-stream starts. Step through it.

💻
Client
CLOSED
🖥️
Server
LISTEN
step 0 / 3
Press Next step to send the first SYN.

What the three packets mean

Only now can a single byte of your actual request travel. That’s one full round-trip (1 RTT) spent just agreeing to begin, and it requires the peer to answer right now.

03, why TCP feels reliable

Sequence numbers & retransmission

TCP turns an unreliable packet network into an ordered, lossless byte-stream with two tricks: every byte is numbered, and the receiver ACKs what it has. Anything not ACKed before a timer (the RTO) fires gets resent. Try dropping a segment:

💻
Sender
🖥️
Receiver
Send a data segment. Tick the box first to watch it get lost and re-sent.

This is real delay tolerance, but only of the small kind: jitter, a dropped packet, a few seconds of congestion. The RTO backs off (1s, 2s, 4s, 8s…) and retries a bounded number of times. Cross that bound and the connection doesn’t wait, it dies. Which is the next demo.

04, the hard wall

Timeouts: where “delay-tolerant” ends

Every TCP connection is on a clock. Drag the round-trip delay up and watch the same handshake succeed… until the delay crosses the socket’s connect timeout, where it simply fails.

💻
Client
CLOSED
🖥️
Server
LISTEN
timeout budget: 5 s
idle
Set a delay, then call connect(). Push past ~2.5 s one-way and the 5 s budget blows.

Real numbers: an app-set connect timeout is typically 2-10 seconds; the OS default is tens of seconds. After the connection is up, idle TCP is torn down by the OS or middleboxes (NATs, load balancers) in minutes unless keepalives are sent. There is no setting that means “hold this connection open across a 3-hour subway tunnel.”

VERDICT
TCP is not delay-tolerant. It tolerates milliseconds-to-seconds of loss and jitter via retransmission, but it’s a live circuit: a hard connect timeout to start, bounded retransmission once running, and idle teardown by the OS/middleboxes. A multi-minute partition kills it. You cannot store-and-forward a TCP connection, the state (sequence numbers, windows, the open socket) lives at both ends and expires.
05, adding encryption

TLS rides on top of TCP

This is the key structural fact: TLS is not its own transport. It’s a handshake that runs inside an already-established TCP connection. So step ① is always “TCP connects” (everything above), and only then does TLS begin. Here’s a TLS 1.3 handshake (1-RTT) over that pipe:

💻
Client
TCP up
🖥️
Server
TCP up
step 0 / 4
Assume TCP is already connected. Press Next step for the ClientHello.

The TLS 1.3 flow

TLS 1.2 needs 2 round-trips here; 1.3 needs 1. Either way it’s a stateful, ordered, timeout-bound conversation, layered on a transport that was already a stateful, timeout-bound conversation.

VERDICT
TLS is even less delay-tolerant than TCP, it inherits every TCP timeout (it can’t start until TCP is up) and adds its own: a stalled handshake fails, and the negotiated keys/session live only in the two endpoints’ memory for that connection. Plus certificates have validity windows. End-to-end TLS to the legacy web fundamentally needs a live, continuous path for the life of the session.

The “connect timeout” starter problem you flagged

You’re right that this is the hard part. To talk to https://anything.com you need: (1) a TCP socket that connects within seconds, and (2) a TLS handshake that completes within seconds, and (3) the socket to stay alive for the whole exchange. A store-and-forward mesh can’t satisfy any of the three for the origin server, because the origin is a dumb legacy box that will RST a half-open socket in seconds. The delay-tolerance has to live somewhere the legacy timeouts don’t reach.

06, so what does Hop do

Where Hop puts the liveness

Two cases, and they behave completely differently:

LIVE CIRCUIT

Reaching the legacy TLS web

No way around it: a gateway opens the real TCP+TLS connection, and the bytes are tunneled across the mesh as a live circuit, every hop must be up simultaneously for the session’s lifetime (HTTP CONNECT semantics, so TLS still terminates end-to-end at your device, not the gateway = no man-in-the-middle). It traverses the connected mesh; it is not DTN. This is purely a tax for talking to legacy boxes with legacy timeouts.

DELAY-TOLERANT

Hop endpoint → Hop endpoint

Here there’s no socket in the middle that can expire. A message is a sealed, signed bundle addressed to a public key. Session state (the X3DH/double-ratchet keys) lives only at the two endpoints, nothing between them holds a timer. So it store-and-forwards across minutes, hours, or a partition, and still arrives ordered and encrypted. This is the world Hop is native to.

The one-line takeaway

Delay-tolerance can’t be added to TCP/TLS, it has to live at the endpoints. So Hop is delay-tolerant between Hop-aware peers, and only falls back to a live circuit when it has to speak to the legacy, timeout-bound web.

That’s the fork in the road for hops://: anything Hop-native is free and delay-tolerant; anything that has to reach a classic TLS origin drags the live-circuit requirement in with it.

client → server server → client lost / timed out