1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
//! Module exposing the [`ChannelProvider`] trait.
//!
//! Relay circuit reactors use a [`ChannelProvider`] to open outgoing channels.
use crate::Result;
use crate::channel::Channel;
use crate::circuit::UniqId;
use async_trait::async_trait;
use futures::channel::mpsc;
use std::sync::Arc;
use tor_linkspec::HasRelayIds;
/// A channel result returned by a [`ChannelProvider`].
pub type ChannelResult = Result<Arc<Channel>>;
/// A sender for returning an outgoing relay channel
/// requested via [`ChannelProvider::get_or_launch`].
//
// Note: this channel is unbounded, because the limit should be imposed
// by the [`ChannelProvider`].
pub struct OutboundChanSender(pub(crate) mpsc::UnboundedSender<ChannelResult>);
impl OutboundChanSender {
/// Create a new [`OutboundChanSender`] from an [`mpsc`] sender.
///
/// This should remain crate-private, as these senders
/// should only ever be created by the relay circuit reactor
/// to request a new outbound channel.
#[allow(dead_code)] // TODO(relay)
pub(crate) fn new(tx: mpsc::UnboundedSender<ChannelResult>) -> Self {
Self(tx)
}
/// Send the specified channel result to the requester.
///
/// See [`ChannelProvider::get_or_launch`].
pub fn send(self, result: ChannelResult) {
// Don't care if the receiver goes away
let _ = self.0.unbounded_send(result);
}
}
/// An object that can fulfill outbound channel requests
/// issued by the relay circuit reactor.
///
/// The implementor is responsible for imposing a limit on the
/// number of outbound channels that can be opened on a given circuit.
#[async_trait]
pub trait ChannelProvider {
/// Type that explains how to build an outgoing channel.
type BuildSpec: HasRelayIds;
/// Get a channel corresponding to the identities of `target`, for the circuit reactor with the
/// specified `reactor_id` which should only be used for logging purposes.
///
/// Returns the requested channel via the specified [`OutboundChanSender`].
fn get_or_launch(
self: Arc<Self>,
reactor_id: UniqId,
target: Self::BuildSpec,
tx: OutboundChanSender,
) -> Result<()>;
}
/// A no-op channel provider to be used in testing.
///
/// Always returns an error.
#[cfg(test)]
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct NoOpChannelProvider;
#[cfg(test)]
impl ChannelProvider for NoOpChannelProvider {
// We choose this because it's needed by the relay circuit reactor constructor.
type BuildSpec = tor_linkspec::OwnedChanTarget;
fn get_or_launch(
self: Arc<Self>,
_reactor_id: UniqId,
_target: Self::BuildSpec,
_tx: OutboundChanSender,
) -> Result<()> {
Err(tor_error::internal!("NoOpChannelProvider cannot launch channels").into())
}
}
|