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.
Almost every networking question comes down to which of these two worlds you’re in.
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.
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.
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.
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.
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:
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.
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.
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.”
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:
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.
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.
Two cases, and they behave completely differently:
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.
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.
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.