diff options
Diffstat (limited to 'spec/tor-spec/closing-streams.md')
-rw-r--r-- | spec/tor-spec/closing-streams.md | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/spec/tor-spec/closing-streams.md b/spec/tor-spec/closing-streams.md new file mode 100644 index 0000000..1d65b6d --- /dev/null +++ b/spec/tor-spec/closing-streams.md @@ -0,0 +1,100 @@ +<a id="tor-spec.txt-6.3"></a> + +# Closing streams{#closing-streams} + +When an anonymized TCP connection is closed, or an edge node +encounters error on any stream, it sends a 'RELAY_END' message along the +circuit (if possible) and closes the TCP connection immediately. If +an edge node receives a 'RELAY_END' message for any stream, it closes +the TCP connection completely, and sends nothing more along the +circuit for that stream. + +The body of a RELAY_END message begins with a single 'reason' byte to +describe why the stream is closing. For some reasons, it contains +additional data (depending on the reason.) The values are: + +```text + 1 -- REASON_MISC (catch-all for unlisted reasons) + 2 -- REASON_RESOLVEFAILED (couldn't look up hostname) + 3 -- REASON_CONNECTREFUSED (remote host refused connection) [*] + 4 -- REASON_EXITPOLICY (OR refuses to connect to host or port) + 5 -- REASON_DESTROY (Circuit is being destroyed) + 6 -- REASON_DONE (Anonymized TCP connection was closed) + 7 -- REASON_TIMEOUT (Connection timed out, or OR timed out + while connecting) + 8 -- REASON_NOROUTE (Routing error while attempting to + contact destination) + 9 -- REASON_HIBERNATING (OR is temporarily hibernating) + 10 -- REASON_INTERNAL (Internal error at the OR) + 11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill request) + 12 -- REASON_CONNRESET (Connection was unexpectedly reset) + 13 -- REASON_TORPROTOCOL (Sent when closing connection because of + Tor protocol violations.) + 14 -- REASON_NOTDIRECTORY (Client sent RELAY_BEGIN_DIR to a + non-directory relay.) + + [*] Older versions of Tor also send this reason when connections are + reset. +``` + +OPs and ORs MUST accept reasons not on the above list, since future +versions of Tor may provide more fine-grained reasons. + +For most reasons, the format of RELAY_END is: + +Reason \[1 byte\] + +For REASON_EXITPOLICY, the format of RELAY_END is: + +```text + Reason [1 byte] + IPv4 or IPv6 address [4 bytes or 16 bytes] + TTL [4 bytes] +``` + +(If the TTL is absent, it should be treated as if it were 0xffffffff. +If the address is absent or is the wrong length, the RELAY_END message +should be processed anyway.) + +Tors SHOULD NOT send any reason except REASON_MISC for a stream that they +have originated. + +Implementations SHOULD accept empty RELAY_END messages, and treat them +as if they specified REASON_MISC. + +Upon receiving a RELAY_END message, the recipient may be sure that no further +messages will arrive on that stream, and can treat such messages as a protocol +violation. + +After sending a RELAY_END message, the sender needs to give the recipient +time to receive that message. In the meantime, the sender SHOULD remember +how many messages of which types (CONNECTED, SENDME, DATA) it would have +accepted on that stream, and SHOULD kill the circuit if it receives more +than permitted. + +--- \[The rest of this section describes unimplemented functionality.\] + +Because TCP connections can be half-open, we follow an equivalent +to TCP's FIN/FIN-ACK/ACK protocol to close streams. + +An exit (or onion service) connection can have a TCP stream in one of +three states: 'OPEN', 'DONE_PACKAGING', and 'DONE_DELIVERING'. For the +purposes of modeling transitions, we treat 'CLOSED' as a fourth state, +although connections in this state are not, in fact, tracked by the +onion router. + +A stream begins in the 'OPEN' state. Upon receiving a 'FIN' from +the corresponding TCP connection, the edge node sends a 'RELAY_FIN' +message along the circuit and changes its state to 'DONE_PACKAGING'. +Upon receiving a 'RELAY_FIN' message, an edge node sends a 'FIN' to +the corresponding TCP connection (e.g., by calling +shutdown(SHUT_WR)) and changing its state to 'DONE_DELIVERING'. + +When a stream in already in 'DONE_DELIVERING' receives a 'FIN', it +also sends a 'RELAY_FIN' along the circuit, and changes its state +to 'CLOSED'. When a stream already in 'DONE_PACKAGING' receives a +'RELAY_FIN' message, it sends a 'FIN' and changes its state to +'CLOSED'. + +If an edge node encounters an error on any stream, it sends a +'RELAY_END' message (if possible) and closes the stream immediately. |