pub struct ClientTunnel {
circ: ClientCirc,
}Expand description
A low-level client tunnel API.
This is a communication channel to the tunnel reactor, which manages 1 or more circuits.
Note: the tor-circmgr crates wrap this type in specialized *Tunnel types exposing only the desired subset of functionality depending on purpose and path size.
Some API calls are for single path and some for multi path. A check with the underlying reactor is done preventing for instance multi path calls to be used on a single path. Top level types should prevent this and thus this object should never be used directly.
Fields§
§circ: ClientCircThe underlying handle to the reactor.
Implementations§
Source§impl ClientTunnel
impl ClientTunnel
Sourcepub fn as_single_circ(&self) -> Result<&ClientCirc>
pub fn as_single_circ(&self) -> Result<&ClientCirc>
Return a handle to the ClientCirc of this ClientTunnel, if the tunnel is a single
circuit tunnel.
Returns an error if the tunnel has more than one circuit.
Sourcepub fn first_hop(&self) -> Result<OwnedChanTarget>
pub fn first_hop(&self) -> Result<OwnedChanTarget>
Return the channel target of the first hop.
Can only be used for single path tunnel.
Sourcepub fn is_closed(&self) -> bool
pub fn is_closed(&self) -> bool
Return true if the circuit reactor is closed meaning the circuit is unusable for both receiving or sending.
Sourcepub fn last_hop(&self) -> Result<TargetHop>
pub fn last_hop(&self) -> Result<TargetHop>
Return a TargetHop representing precisely the last hop of the circuit as in set as a
HopLocation with its id and hop number.
Return an error if there is no last hop.
Sourcepub fn last_hop_info(&self) -> Result<Option<OwnedChanTarget>>
pub fn last_hop_info(&self) -> Result<Option<OwnedChanTarget>>
Return a description of the last hop of the tunnel.
Return None if the last hop is virtual; return an error if the tunnel has no circuits, or all of its circuits are zero length.
§Panics
Panics if there is no last hop. (This should be impossible outside of the tor-proto crate, but within the crate it’s possible to have a circuit with no hops.)
Sourcepub fn n_hops(&self) -> Result<usize>
pub fn n_hops(&self) -> Result<usize>
Return the number of hops this tunnel as. Fail for a multi path.
Sourcepub fn all_paths(&self) -> Vec<Arc<Path>>
pub fn all_paths(&self) -> Vec<Arc<Path>>
Return the Path objects describing all the hops
of all the circuits in this tunnel.
Sourcepub fn unique_id(&self) -> UniqId
pub fn unique_id(&self) -> UniqId
Return a process-unique identifier for this tunnel.
Returns the reactor unique ID of the main reactor.
Sourcepub async fn disused_since(&self) -> Result<Option<Instant>>
pub async fn disused_since(&self) -> Result<Option<Instant>>
Return the time at which this tunnel last had any open streams.
Returns None if this tunnel has never had any open streams,
or if it currently has open streams.
NOTE that the Instant returned by this method is not affected by
any runtime mocking; it is the output of an ordinary call to
Instant::now().
Sourcepub fn wait_for_close(
self: &Arc<Self>,
) -> impl Future<Output = ()> + Send + Sync + 'static + use<>
pub fn wait_for_close( self: &Arc<Self>, ) -> impl Future<Output = ()> + Send + Sync + 'static + use<>
Return a future that will resolve once the underlying circuit reactor has closed.
Note that this method does not itself cause the tunnel to shut down.
Sourcepub async fn allow_stream_requests<'a, FILT>(
self: &Arc<Self>,
allow_commands: &'a [RelayCmd],
hop: TargetHop,
filter: FILT,
) -> Result<impl Stream<Item = IncomingStream> + use<'a, FILT>>where
FILT: IncomingStreamRequestFilter + 'a,
Available on crate feature hs-service only.
pub async fn allow_stream_requests<'a, FILT>(
self: &Arc<Self>,
allow_commands: &'a [RelayCmd],
hop: TargetHop,
filter: FILT,
) -> Result<impl Stream<Item = IncomingStream> + use<'a, FILT>>where
FILT: IncomingStreamRequestFilter + 'a,
hs-service only.Single-path tunnel only. Multi path onion service is not supported yet.
Tell this tunnel to begin allowing the final hop of the tunnel to try to create new Tor streams, and to return those pending requests in an asynchronous stream.
Ordinarily, these requests are rejected.
There can only be one Stream of this type created on a given tunnel.
If a such a Stream already exists, this method will return
an error.
After this method has been called on a tunnel, the tunnel is expected
to receive requests of this type indefinitely, until it is finally closed.
If the Stream is dropped, the next request on this tunnel will cause it to close.
Only onion services (and eventually) exit relays should call this method.
Sourceasync fn begin_stream_impl(
self: &Arc<Self>,
begin_msg: AnyRelayMsg,
cmd_checker: Box<dyn CmdChecker + Send + 'static>,
) -> Result<StreamComponents>
async fn begin_stream_impl( self: &Arc<Self>, begin_msg: AnyRelayMsg, cmd_checker: Box<dyn CmdChecker + Send + 'static>, ) -> Result<StreamComponents>
Single and Multi path helper, used to begin a stream.
This function allocates a stream ID, and sends the message (like a BEGIN or RESOLVE), but doesn’t wait for a response.
The caller will typically want to see the first cell in response, to see whether it is e.g. an END or a CONNECTED.
Sourcepub async fn start_padding_at_hop(
self: &Arc<Self>,
hop: HopLocation,
padder: CircuitPadder,
) -> Result<()>
Available on crate feature circ-padding-manual only.
pub async fn start_padding_at_hop( self: &Arc<Self>, hop: HopLocation, padder: CircuitPadder, ) -> Result<()>
circ-padding-manual only.Install a CircuitPadder at the listed hop.
Replaces any previous padder installed at that hop.
Sourcepub async fn stop_padding_at_hop(
self: &Arc<Self>,
hop: HopLocation,
) -> Result<()>
Available on crate feature circ-padding-manual only.
pub async fn stop_padding_at_hop( self: &Arc<Self>, hop: HopLocation, ) -> Result<()>
circ-padding-manual only.Remove any CircuitPadder at the listed hop.
Does nothing if there was not a padder installed there.
Sourceasync fn begin_data_stream(
self: &Arc<Self>,
msg: AnyRelayMsg,
optimistic: bool,
) -> Result<DataStream>
async fn begin_data_stream( self: &Arc<Self>, msg: AnyRelayMsg, optimistic: bool, ) -> Result<DataStream>
Start a DataStream (anonymized connection) to the given address and port, using a BEGIN cell.
Sourcepub async fn begin_stream(
self: &Arc<Self>,
target: &str,
port: u16,
parameters: Option<StreamParameters>,
) -> Result<DataStream>
pub async fn begin_stream( self: &Arc<Self>, target: &str, port: u16, parameters: Option<StreamParameters>, ) -> Result<DataStream>
Single and multi path helper.
Start a stream to the given address and port, using a BEGIN cell.
The use of a string for the address is intentional: you should let the remote Tor relay do the hostname lookup for you.
Sourcepub async fn begin_dir_stream(self: Arc<Self>) -> Result<DataStream>
pub async fn begin_dir_stream(self: Arc<Self>) -> Result<DataStream>
Start a new stream to the last relay in the tunnel, using a BEGIN_DIR cell.
Sourcepub async fn resolve(self: &Arc<Self>, hostname: &str) -> Result<Vec<IpAddr>>
pub async fn resolve(self: &Arc<Self>, hostname: &str) -> Result<Vec<IpAddr>>
Perform a DNS lookup, using a RESOLVE cell with the last relay in this tunnel.
Note that this function does not check for timeouts; that’s the caller’s responsibility.
Sourcepub async fn resolve_ptr(self: &Arc<Self>, addr: IpAddr) -> Result<Vec<String>>
pub async fn resolve_ptr(self: &Arc<Self>, addr: IpAddr) -> Result<Vec<String>>
Perform a reverse DNS lookup, by sending a RESOLVE cell with the last relay on this tunnel.
Note that this function does not check for timeouts; that’s the caller’s responsibility.
Sourcepub async fn send_raw_msg(&self, msg: AnyRelayMsg, hop: TargetHop) -> Result<()>
Available on crate feature send-control-msg only.
pub async fn send_raw_msg(&self, msg: AnyRelayMsg, hop: TargetHop) -> Result<()>
send-control-msg only.Send an ad-hoc message to a given hop on the circuit, without expecting a reply.
(If you want to handle one or more possible replies, see
ClientTunnel::start_conversation.)
Sourcepub async fn start_conversation(
&self,
msg: Option<AnyRelayMsg>,
reply_handler: impl MsgHandler + Send + 'static,
hop: TargetHop,
) -> Result<Conversation<'_>>
Available on crate feature send-control-msg only.
pub async fn start_conversation( &self, msg: Option<AnyRelayMsg>, reply_handler: impl MsgHandler + Send + 'static, hop: TargetHop, ) -> Result<Conversation<'_>>
send-control-msg only.Start an ad-hoc protocol exchange to the specified hop on this tunnel.
To use this:
-
Create an inter-task channel you’ll use to receive the outcome of your conversation, and bundle it into a
UserMsgHandler. -
Call
start_conversation. This will install a your handler, for incoming messages, and send the outgoing message (if you provided one). After that, each message on the circuit that isn’t handled by the core machinery is passed to your providedreply_handler. -
Possibly call
send_msgon theConversation, from the call site ofstart_conversation, possibly multiple times, from time to time, to send further desired messages to the peer. -
In your
UserMsgHandler, process the incoming messages. You may respond by sending additional messages When the protocol exchange is finished,UserMsgHandler::handle_msgshould returnConversationFinished.
If you don’t need the Conversation to send followup messages,
you may simply drop it,
and rely on the responses you get from your handler,
on the channel from step 0 above.
Your handler will remain installed and able to process incoming messages
until it returns ConversationFinished.
(If you don’t want to accept any replies at all, it may be
simpler to use ClientTunnel::send_raw_msg.)
Note that it is quite possible to use this function to violate the tor protocol; most users of this API will not need to call it. It is used to implement most of the onion service handshake.
§Limitations
Only one conversation may be active at any one time, for any one circuit. This generally means that this function should not be called on a tunnel which might be shared with anyone else.
Likewise, it is forbidden to try to extend the tunnel, while the conversation is in progress.
After the conversation has finished, the tunnel may be extended.
Or, start_conversation may be called again;
but, in that case there will be a gap between the two conversations,
during which no UserMsgHandler is installed,
and unexpected incoming messages would close the tunnel.
If these restrictions are violated, the tunnel will be closed with an error.
§Precise definition of the lifetime of a conversation
A conversation is in progress from entry to start_conversation,
until entry to the body of the UserMsgHandler::handle_msg
call which returns ConversationFinished.
(Entry since handle_msg is synchronously embedded
into the incoming message processing.)
So you may start a new conversation as soon as you have the final response
via your inter-task channel from (0) above.
The lifetime relationship of the Conversation,
vs the handler returning ConversationFinished
is not enforced by the type system.
Sourcepub fn terminate(&self)
pub fn terminate(&self)
Shut down this tunnel, along with all streams that are using it. Happens asynchronously (i.e. the tunnel won’t necessarily be done shutting down immediately after this function returns!).
Note that other references to this tunnel may exist. If they do, they will stop working after you call this function.
It’s not necessary to call this method if you’re just done with a tunnel: the tunnel should close on its own once nothing is using it any more.
Sourceasync fn try_resolve(self: &Arc<Self>, msg: Resolve) -> Result<Resolved>
async fn try_resolve(self: &Arc<Self>, msg: Resolve) -> Result<Resolved>
Helper: Send the resolve message, and read resolved message from resolve stream.
Source§impl ClientTunnel
impl ClientTunnel
Sourcepub(crate) fn close_pending(
&self,
stream_id: StreamId,
hop: Option<HopLocation>,
message: CloseStreamBehavior,
) -> Result<Receiver<Result<()>>>
Available on crate feature hs-service only.
pub(crate) fn close_pending( &self, stream_id: StreamId, hop: Option<HopLocation>, message: CloseStreamBehavior, ) -> Result<Receiver<Result<()>>>
hs-service only.Close the pending stream that owns this StreamTarget, delivering the specified END message (if any)
Sourcepub(crate) fn send_sendme(
&self,
stream_id: StreamId,
hop: Option<HopLocation>,
) -> Result<()>
pub(crate) fn send_sendme( &self, stream_id: StreamId, hop: Option<HopLocation>, ) -> Result<()>
Request to send a SENDME cell for this stream.
Sourcepub(crate) fn drain_rate_update(
&self,
stream_id: StreamId,
hop: Option<HopLocation>,
rate: XonKbpsEwma,
) -> Result<()>
pub(crate) fn drain_rate_update( &self, stream_id: StreamId, hop: Option<HopLocation>, rate: XonKbpsEwma, ) -> Result<()>
Inform the circuit reactor that there has been a change in the drain rate for this stream.
Trait Implementations§
Source§impl Debug for ClientTunnel
impl Debug for ClientTunnel
Source§impl TryFrom<ClientCirc> for ClientTunnel
impl TryFrom<ClientCirc> for ClientTunnel
Auto Trait Implementations§
impl Freeze for ClientTunnel
impl !RefUnwindSafe for ClientTunnel
impl Send for ClientTunnel
impl Sync for ClientTunnel
impl Unpin for ClientTunnel
impl !UnwindSafe for ClientTunnel
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PossiblyOption<T> for T
impl<T> PossiblyOption<T> for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.