These aren't called "close" because they're more destructive than
that: they can be called even if other parties are using the circuit
or channel.
This is for arti#21.
Now, a Relay is always valid. This required some changes to the
API: all_relays() has to return a new UncheckedRelay type that might
or might not be valid, and the functions on Relay and ChanTarget
that return ed25519 identities need to return an Ed25519Identity,
not an ed25519::PublicKey.
This change required some new encoding/decoding/conversion functions
on Ed25519Identity.
"M3" is for "milestone 3" -- my target to fix the technical debt
that I think will be bad if we ship even a pre-alpha with it.
These aren't necessarily _all_ must-resolve, but they're all
must-look-at.
Closes#15
This wraps exactly the ChanMsg values that are valid on open client
circuits, so that we can be sure that only those cells are sent to a
ClientCirc's reactor.
CreateResponse includes exactly those cells that are a correct
response to a CREATE2/CREATE_FAST, so we can be sure that only those
cells are actually passed to a PendingClientCirc.
This reuses a lot of mechanism from the circuit code that sends END
cells when streams are dropped.
There is a problem here: Circuits and channels won't actually get
dropped, because we should be using a weak reference from the
reactor.
We already handled the case okay when we were reading on streams,
since the reactor's going away would drop the sender side of their
mpsc channels. But if the reactor went away, nothing would tell
_writing_ streams that they needed to close.
Now we handle that case, as well as anybody who is waiting on
a meta-cell to get back to them.
When a stream is closed and we haven't adjusted its state in the
stream map yet, remember how many cells we've dropped so we can
decrement them from the window later on.
This is the first step along the line to handling Tor issue
tor#27557. We want to remember streams that we've ended and treat
them as distinct from streams that have never existed
The problem is that we would count begin and end cells towards
towards window totals when we are only supposed to count DATA
cells, *and* that we would we send our sendmes one cell too early
(or maybe late?).
Closes#1.
Previously the circuit object owned not only the outbound crypto,
but also the inbound crypto and the stream maps. That's not so
great, since the reactor needs to use the inbound crypto and the
stream maps all the time, whereas the circuit doesn't need them much
(or at all).
Moving these objects to the reactor-owned structure should let us
fix the deadlock case in stream sendme handling, since the circuit
reactor no longer needs to lock the circuit in order to do crypto
and demultiplexing. It should also speed up the code a bit, since
it doesn't need to grab the circuit lock nearly so often as before.
This change forced me to add a couple of new reactor CtrlMsg values,
since the circuit can no longer add streams and layers directly. I
think it will still be a performance win, though.
This code deviates from current tor in that it allows missing
sendme authentications only when we know we're talking to an old
relay, or when we don't know the version of the relay we're talking
to.
There's a problem, though: this code assumes that tags are 20 bytes
long whereas actually the tag type is part of the crypto layer info.
So maybe in the long term we need to move the queue of tags from the
send window into being part of the crypto layers.
This is incomplete because the cell crypto code doesn't actually
expose tags yet, and because it demands tags unconditionally,
without caring about the linkspec protocol version.
This was a hard one. I need to make sure that we send an END cell
when the stream is dropped. But we can't call an .await from inside
the drop() function, since drop() isn't async, and we don't have an
executor.
Fortunately, you can call send() on a oneshot::Sender without having
to await on it, so that's the obvious thing to put in drop(). But
we need some way to make sure that the oneshot::Receiver is given to
the reactor, and is .awaited. For that, we needed a control
channel. And the reactor needs to treat the control channel and the
close messages as equally important.
So that's how I wound up with a
Fuse<Select<mpsc::Receiver<Result<Foo>>,
SelectAll<Once<oneshot::Receiver<Foo>>>>>.
I doubt that this is actually the best way to handle any of this!
By putting the cell-sink in a box, we can get rid of the need for
having everything that uses a channel or a circuit know what kind
of underlying TLS implementation it has.
This is not a production-ready implementation: it will break if a
circuit is used for anything while an extend is pending.
Client-demo can now build 3-hop circuits.
The protocol is now based around a message-oriented scheme intended
to use futures_codec, which in turn uses BytesMut. The transition
to BytesMut is incomplete, and we're not nearly so zero-copy as
intended. We should think about that.
Arti is a rust tor implementation. It's project I've been working
on for a few months now, in weekends and in spare time. It doesn't
speak the tor protocol yet, and it doesn't connect to the network at
all.
It needs much more documentation and testing, but I'm just about
ready to show it to others. See the README.md for a description of
what is there and what isn't.