Add tls_conn field to ArtiHttpConnector (and argument to constructor).
Introduce MaybeHttpsStream and use it in ArtiHttpConnection.
Have the example program pass the native TLS connector.
Currently the TLS connector and the HTTPS variant are not used, but
this commit is very noisy and fomrulaic, so I have split out the code
to use them into a separate commit for easier preparation and review.
arti-hyper wants to be able to have a kind for TLS failure.
Given that arti-hyper is above arti-client, this shows that callers
above arti-client might need to invent kinds for their own errors.
Possibly this means we need other Other errors for other locations.
If we have pluggable components we might even want OtherTorError.
Fixes#365
Inspection of the code and logs shows that:
* One of the plan futures' oneshots must be returning Cancelled
* This means that the corresponding sender must have been dropped
* The sender is owned by the task spawned by spawn_launch
Presumably that entire task gets dropped as part of executor shutdown,
or something.
The correct response in this situation is to declare that we are
shutting down, and stop trying to do stuff.
Unfortunately, despite trying quite hard by putting sleeps in various
strategic places, I have not been able to reproduce the problem. So I
can't be 100% sure that the new behaviour is correct.
But I am reasonably confident that this ought not to be able to occur
unless either 1. the task from spawn_launch is dropped, or 2. that
task somehow panics despite its attempts to trap panics and report
them as errors through the oneshot.
So this "burn it all down" action ought only to occur in actually
serious situations.
I observe that
3ff9b187ea
Handle panics from circuit construction.
changed the EK for PendingCanceled to EK::ReactorShuttingDown,
and there's From impl. I think, therefore, that it is right
to reuse this Error variant.
I don't quite understand why when take_action gets an actual error it
doesn't push it, but just logs it. But I am not changing that for
now.
Arguably the two instances of retry_error.push are a sign of an
inferior flow control pattern - maybe the loop body including the code
I am adding ought to be an IEFE returning
`Result<Option<circ>, crate::Error>`.
I wanted this while debugging something.
The ad-hoc impl Debug with f.debug_struct is getting repetitive
and I've already perpetrated one copy-paste mistake.
We should consider using something like the `educe` crate's Clone.
`PreferredRuntime` is now an opaque wrapper struct that contains the
"actual" preferred runtime as a type alias. The `current_user_runtime`
and `create_runtime` functions become `PreferredRuntime::current` and
`PreferredRuntime::create`, respectively.
This removes the dependence on `impl Trait`, meaning we can now name the
returned runtime (yay!).
In addition, the documentation was cleaned up a bit to make it
(hopefully) flow better. Items that don't make sense to publicize, like
testing implementation details, have been marked #[doc(hidden)] and
semver warnings added.
Previously coarsetime and the traffic-timestamp feature were
enabled, since they were only required for a small corner of the
guardmgr algorithm.
But in 1.0 and beyond we'll be adding a bunch of other features (eg,
netflow padding, DoS prevention) that will need coarsetime all over
the place.
And since we're going to be doing coarsetime all over the place, the
previous justification for making traffic-timestamping optional (the
tiny performance hit) is no longer relevant.
`StateMgr` got a new `unlock()` method that does what it says on the
tin. We now call it from `bootstrap()` using the new
`util::StateMgrUnlockGuard`, which works in a manner similar to the
`BoolResetter` from `tor_dirmgr`.
(A decent small little task in future might be to unify these types in
some sort of general arti utility crate?)
closes arti#335
This lint is IMO inherently ill-conceived.
I have looked for the reasons why this might be thought to be a good
idea and there were basically two (and they are sort of contradictory):
I. "Calling ‘.clone()` on an Rc, Arc, or Weak can obscure the fact
that only the pointer is being cloned, not the underlying data."
This is the wording from
https://rust-lang.github.io/rust-clippy/v0.0.212/#clone_on_ref_ptr
It is a bit terse; we are left to infer why it is a bad idea to
obscure this fact. It seems to me that if it is bad to obscure some
fact, that must be because the fact is a hazard. But why would it be
a hazard to not copy the underlying data ?
In other languages, faliing to copy the underlying data is a serious
correctness hazard. There is a whose class of bugs where things were
not copied, and then mutated and/or reused in multiple places in ways
that were not what the programmer intended. In my experience, this is
a very common bug when writing Python and Javascript. I'm told it's
common in golang too.
But in Rust this bug is much much harder to write. The data inside an
Arc is immutable. To have this bug you'd have use interior mutability
- ie mess around with Mutex or RefCell. That provides a good barrier
to these kind of accidents.
II. "The reason for writing Rc::clone and Arc::clone [is] to make it
clear that only the pointer is being cloned, as opposed to the
underlying data. The former is always fast, while the latter can
be very expensive depending on what is being cloned."
This is the reasoning found here
https://github.com/rust-lang/rust-clippy/issues/2048
This is saying that *not* using Arc::clone is hazardous.
Specifically, that a deep clone is a performance hazard.
But for this argument, the lint is precisely backwards. It's linting
the "good" case and asking for it to be written in a more explicit
way; while the supposedly bad case can be written conveniently.
Also, many objects (in our codebase, and in all the libraries we use)
that are Clone are in fact simply handles. They contain Arc(s) (or
similar) and are cheap to clone. Indeed, that is the usual case.
It does not make sense to distinguish in the syntax we use to clone
such a handle, whether the handle is a transparent Arc, or an opaque
struct containing one or more other handles.
Forcing Arc::clone to be written as such makes for code churn when a
type is changed from Arc<Something> to Something: Clone, or vice
versa.
My proximate motivation is that tls-api wants its inner streams to be
Debug. But in general, I agree with the Rust API Guidelines notion
that almost everything should be Debug.
I have gone for the "dump all the things" approach. A more nuanced
approach would be possible too.
Now all of the runtime types we provide all
impl<S> TlsProvider<S> where S: ...
rather than merely TlsProvider<Self::TcpStream>.
And we document and intent to perhaps require this in the future.
This helps the user distinguish between protocol violations that
happen when connecting to the tor network from those that happen
while connected.
Closes#358.
Try to make the `hook-tcp` example a bit easier to read by
adding/changing comments, and renaming the lifetimes for
`async_trait`-generated trait methods.
To implement this, we had to refactor the tor_circmgr api for
flushing state changes to disk, so that it checks if it has the lock,
and only then tries to store.
There was only one use of this, and it was in as-yet-unused relay-only
code.
Removing this type required refactoring the relay onion handshake code
to use its own error type, which is probably clever anyway.
We handle them by reporting them to task that's waiting for the
circuit, then relaying the panic.
Doing so allows the waiting task to distinguish panics
(EK::Internal) from cases where the reactor dropped the task
entirely (EK::ReactorShuttingDown). And doing _that_ removes one
case of EK::Canceled, which helps us on our goals towards #348.
Closes#347.