aboutsummaryrefslogtreecommitdiff
path: root/spec/tor-spec/closing-streams.md
diff options
context:
space:
mode:
Diffstat (limited to 'spec/tor-spec/closing-streams.md')
-rw-r--r--spec/tor-spec/closing-streams.md100
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.