summaryrefslogtreecommitdiff
path: root/crates/tor-proto
diff options
context:
space:
mode:
Diffstat (limited to 'crates/tor-proto')
-rw-r--r--crates/tor-proto/README.md2
-rw-r--r--crates/tor-proto/semver.md1
-rw-r--r--crates/tor-proto/src/channel.rs2
-rw-r--r--crates/tor-proto/src/channel/reactor.rs2
-rw-r--r--crates/tor-proto/src/channel/unique_id.rs4
-rw-r--r--crates/tor-proto/src/circuit.rs8
-rw-r--r--crates/tor-proto/src/circuit/unique_id.rs (renamed from crates/tor-proto/src/client/circuit/unique_id.rs)0
-rw-r--r--crates/tor-proto/src/client.rs53
-rw-r--r--crates/tor-proto/src/client/circuit.rs8
-rw-r--r--crates/tor-proto/src/client/reactor.rs5
-rw-r--r--crates/tor-proto/src/client/reactor/circuit.rs19
-rw-r--r--crates/tor-proto/src/client/reactor/circuit/circhop.rs5
-rw-r--r--crates/tor-proto/src/client/reactor/circuit/extender.rs6
-rw-r--r--crates/tor-proto/src/client/reactor/conflux.rs8
-rw-r--r--crates/tor-proto/src/client/reactor/control.rs5
-rw-r--r--crates/tor-proto/src/client/stream/incoming.rs2
-rw-r--r--crates/tor-proto/src/crypto/cell/cgo.rs2
-rw-r--r--crates/tor-proto/src/crypto/cell/tor1.rs2
-rw-r--r--crates/tor-proto/src/lib.rs4
-rw-r--r--crates/tor-proto/src/relay/channel_provider.rs2
-rw-r--r--crates/tor-proto/src/relay/reactor.rs4
-rw-r--r--crates/tor-proto/src/tunnel.rs54
22 files changed, 106 insertions, 92 deletions
diff --git a/crates/tor-proto/README.md b/crates/tor-proto/README.md
index 937af1427..644ea0a0d 100644
--- a/crates/tor-proto/README.md
+++ b/crates/tor-proto/README.md
@@ -26,7 +26,7 @@ circuits. Finally, each circuit multiplexes a number of "streams",
each corresponding roughly to an application-level request.
This crate implements the logic, protocols, and cryptography that
-implement these [`channel::Channel`]s, [`circuit::ClientCirc`]s, and
+implement these [`channel::Channel`]s, [`client::circuit::ClientCirc`]s, and
[`client::stream::DataStream`]s. It uses rust async code and
future-related traits, and is intended to work with (nearly) any
executor implementation that complies with the futures API.
diff --git a/crates/tor-proto/semver.md b/crates/tor-proto/semver.md
index 33d8be55b..9c4c1168b 100644
--- a/crates/tor-proto/semver.md
+++ b/crates/tor-proto/semver.md
@@ -1 +1,2 @@
BREAKING: `tor_proto::stream` module moved under `tor_proto::client`
+BREAKING: `tor_proto::circuit` moved under `tor_proto::client`
diff --git a/crates/tor-proto/src/channel.rs b/crates/tor-proto/src/channel.rs
index de5b7f319..c43882a0b 100644
--- a/crates/tor-proto/src/channel.rs
+++ b/crates/tor-proto/src/channel.rs
@@ -68,7 +68,7 @@ mod unique_id;
pub use crate::channel::params::*;
use crate::channel::reactor::{BoxedChannelSink, BoxedChannelStream, Reactor};
pub use crate::channel::unique_id::UniqId;
-use crate::circuit::PendingClientTunnel;
+use crate::client::circuit::PendingClientTunnel;
use crate::memquota::{ChannelAccount, CircuitAccount, SpecificAccount as _};
use crate::util::err::ChannelClosed;
use crate::util::oneshot_broadcast;
diff --git a/crates/tor-proto/src/channel/reactor.rs b/crates/tor-proto/src/channel/reactor.rs
index f618fa5d4..5e7ccdb7b 100644
--- a/crates/tor-proto/src/channel/reactor.rs
+++ b/crates/tor-proto/src/channel/reactor.rs
@@ -71,7 +71,7 @@ pub enum CtrlMsg {
/// Channel to send other messages from this circuit down.
sender: CircuitRxSender,
/// Oneshot channel to send the new circuit's identifiers down.
- tx: ReactorResultChannel<(CircId, crate::client::circuit::UniqId)>,
+ tx: ReactorResultChannel<(CircId, crate::circuit::UniqId)>,
},
/// Enable/disable/reconfigure channel padding
///
diff --git a/crates/tor-proto/src/channel/unique_id.rs b/crates/tor-proto/src/channel/unique_id.rs
index 307d240bb..5d1fbfdfd 100644
--- a/crates/tor-proto/src/channel/unique_id.rs
+++ b/crates/tor-proto/src/channel/unique_id.rs
@@ -48,14 +48,14 @@ impl CircUniqIdContext {
CircUniqIdContext { next_circ_id: 0 }
}
/// Construct a new, unique-ish circuit UniqId
- pub(super) fn next(&mut self, unique_id: UniqId) -> crate::client::circuit::UniqId {
+ pub(super) fn next(&mut self, unique_id: UniqId) -> crate::circuit::UniqId {
let circ_unique_id = self.next_circ_id;
self.next_circ_id += 1;
assert!(
self.next_circ_id != 0,
"Exhausted the unique circuit ID namespace on a channel"
);
- crate::client::circuit::UniqId::new(unique_id.0, circ_unique_id)
+ crate::circuit::UniqId::new(unique_id.0, circ_unique_id)
}
}
diff --git a/crates/tor-proto/src/circuit.rs b/crates/tor-proto/src/circuit.rs
new file mode 100644
index 000000000..efd38c896
--- /dev/null
+++ b/crates/tor-proto/src/circuit.rs
@@ -0,0 +1,8 @@
+//! Circuit-related types and helpers.
+//!
+//! This code is shared between the client and relay implementations.
+
+pub(crate) mod unique_id;
+
+pub use crate::memquota::StreamAccount;
+pub use unique_id::UniqId;
diff --git a/crates/tor-proto/src/client/circuit/unique_id.rs b/crates/tor-proto/src/circuit/unique_id.rs
index c8778f36e..c8778f36e 100644
--- a/crates/tor-proto/src/client/circuit/unique_id.rs
+++ b/crates/tor-proto/src/circuit/unique_id.rs
diff --git a/crates/tor-proto/src/client.rs b/crates/tor-proto/src/client.rs
index aebae337b..398cd2e9c 100644
--- a/crates/tor-proto/src/client.rs
+++ b/crates/tor-proto/src/client.rs
@@ -10,14 +10,13 @@ pub(crate) mod reactor;
mod streammap;
use derive_deftly::Deftly;
-use derive_more::Display;
use futures::SinkExt as _;
use oneshot_fused_workaround as oneshot;
use std::net::IpAddr;
use std::pin::Pin;
use std::sync::Arc;
-use std::sync::atomic::{AtomicU64, Ordering};
+use crate::circuit::UniqId;
use crate::client::stream::queue::stream_queue;
use crate::client::stream::xon_xoff::XonXoffReaderCtrl;
use crate::client::stream::{
@@ -29,7 +28,7 @@ use crate::crypto::cell::HopNum;
use crate::memquota::{SpecificAccount as _, StreamAccount};
use crate::util::notify::NotifySender;
use crate::{Error, ResolveError, Result};
-use circuit::{CIRCUIT_BUFFER_SIZE, ClientCirc, Path, StreamMpscSender, UniqId};
+use circuit::{CIRCUIT_BUFFER_SIZE, ClientCirc, Path, StreamMpscSender};
use reactor::{
CtrlCmd, CtrlMsg, FlowCtrlMsg, MetaCellHandler, RECV_WINDOW_INIT, STREAM_READER_BUFFER,
};
@@ -53,54 +52,6 @@ use {
#[cfg(feature = "send-control-msg")]
use msghandler::{MsgHandler, UserMsgHandler};
-/// The unique identifier of a tunnel.
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display)]
-#[display("{}", _0)]
-#[cfg_attr(feature = "relay", visibility::make(pub))]
-#[allow(unreachable_pub)] // TODO(#1447): use in ChanMgr's ChannelProvider impl
-pub(crate) struct TunnelId(u64);
-
-impl TunnelId {
- /// Create a new TunnelId.
- ///
- /// # Panics
- ///
- /// Panics if we have exhausted the possible space of u64 IDs.
- pub(crate) fn next() -> TunnelId {
- /// The next unique tunnel ID.
- static NEXT_TUNNEL_ID: AtomicU64 = AtomicU64::new(1);
- let id = NEXT_TUNNEL_ID.fetch_add(1, Ordering::Relaxed);
- assert!(id != 0, "Exhausted Tunnel ID space?!");
- TunnelId(id)
- }
-}
-
-/// The identifier of a circuit [`UniqId`] within a tunnel.
-///
-/// This type is only needed for logging purposes: a circuit's [`UniqId`] is
-/// process-unique, but in the logs it's often useful to display the
-/// owning tunnel's ID alongside the circuit identifier.
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display)]
-#[display("Circ {}.{}", tunnel_id, circ_id.display_chan_circ())]
-pub(crate) struct TunnelScopedCircId {
- /// The identifier of the owning tunnel
- tunnel_id: TunnelId,
- /// The process-unique identifier of the circuit
- circ_id: UniqId,
-}
-
-impl TunnelScopedCircId {
- /// Create a new [`TunnelScopedCircId`] from the specified identifiers.
- pub(crate) fn new(tunnel_id: TunnelId, circ_id: UniqId) -> Self {
- Self { tunnel_id, circ_id }
- }
-
- /// Return the [`UniqId`].
- pub(crate) fn unique_id(&self) -> UniqId {
- self.circ_id
- }
-}
-
/// Handle to use during an ongoing protocol exchange with a circuit's last hop
///
/// This is obtained from [`ClientTunnel::start_conversation`],
diff --git a/crates/tor-proto/src/client/circuit.rs b/crates/tor-proto/src/client/circuit.rs
index c9a55813a..b45e003da 100644
--- a/crates/tor-proto/src/client/circuit.rs
+++ b/crates/tor-proto/src/client/circuit.rs
@@ -44,10 +44,8 @@ pub mod handshake;
pub(crate) mod handshake;
pub(super) mod path;
-pub(crate) mod unique_id;
use crate::channel::Channel;
-use crate::circuit::handshake::RelayCryptLayerProtocol;
use crate::client::circuit::celltypes::*;
use crate::client::reactor::{CircuitHandshake, CtrlCmd, CtrlMsg, Reactor};
use crate::congestion::params::CongestionControlParams;
@@ -58,6 +56,7 @@ use crate::util::skew::ClockSkew;
use crate::{Error, Result};
use cfg_if::cfg_if;
use educe::Educe;
+use handshake::RelayCryptLayerProtocol;
use path::HopDetail;
use tor_cell::chancell::CircId;
use tor_cell::relaycell::RelayCellFormat;
@@ -66,9 +65,7 @@ use tor_linkspec::{CircTarget, LinkSpecType, OwnedChanTarget, RelayIdType};
use tor_protover::named;
use tor_rtcompat::DynTimeProvider;
-pub use crate::client::circuit::unique_id::UniqId;
-pub use crate::crypto::binding::CircuitBinding;
-pub use crate::memquota::StreamAccount;
+use crate::circuit::UniqId;
use super::{ClientTunnel, TargetHop};
@@ -82,6 +79,7 @@ use tor_memquota::mq_queue::{self, MpscSpec};
use crate::crypto::handshake::ntor::NtorPublicKey;
+pub use crate::crypto::binding::CircuitBinding;
pub use path::{Path, PathEntry};
/// The size of the buffer for communication between `ClientCirc` and its reactor.
diff --git a/crates/tor-proto/src/client/reactor.rs b/crates/tor-proto/src/client/reactor.rs
index bd4f4dab1..fd9d2f3a8 100644
--- a/crates/tor-proto/src/client/reactor.rs
+++ b/crates/tor-proto/src/client/reactor.rs
@@ -21,17 +21,18 @@ mod conflux;
mod control;
pub(super) mod syncview;
+use crate::circuit::UniqId;
use crate::client::circuit::CircuitRxReceiver;
use crate::client::circuit::celltypes::ClientCircChanMsg;
-use crate::client::circuit::unique_id::UniqId;
use crate::client::stream::queue::StreamQueueReceiver;
use crate::client::stream::{AnyCmdChecker, StreamRateLimit};
#[cfg(feature = "hs-service")]
use crate::client::stream::{DrainRateRequest, IncomingStreamRequest, IncomingStreamRequestFilter};
-use crate::client::{HopLocation, TargetHop, TunnelId, TunnelScopedCircId, streammap};
+use crate::client::{HopLocation, TargetHop, streammap};
use crate::crypto::cell::HopNum;
use crate::crypto::handshake::ntor_v3::NtorV3PublicKey;
use crate::memquota::{CircuitAccount, StreamAccount};
+use crate::tunnel::{TunnelId, TunnelScopedCircId};
use crate::util::err::ReactorError;
use crate::util::notify::NotifyReceiver;
use crate::util::skew::ClockSkew;
diff --git a/crates/tor-proto/src/client/reactor/circuit.rs b/crates/tor-proto/src/client/reactor/circuit.rs
index 36445c388..944fe1a93 100644
--- a/crates/tor-proto/src/client/reactor/circuit.rs
+++ b/crates/tor-proto/src/client/reactor/circuit.rs
@@ -5,15 +5,13 @@ pub(super) mod create;
pub(super) mod extender;
use crate::channel::{Channel, ChannelSender};
-use crate::circuit::HopSettings;
-#[cfg(feature = "counter-galois-onion")]
-use crate::circuit::handshake::RelayCryptLayerProtocol;
-use crate::client::TunnelScopedCircId;
+use crate::circuit::UniqId;
use crate::client::circuit::celltypes::{ClientCircChanMsg, CreateResponse};
+#[cfg(feature = "counter-galois-onion")]
+use crate::client::circuit::handshake::RelayCryptLayerProtocol;
use crate::client::circuit::handshake::{BoxedClientLayer, HandshakeRole};
-use crate::client::circuit::path;
-use crate::client::circuit::unique_id::UniqId;
use crate::client::circuit::{CircuitRxReceiver, MutableState, StreamMpscReceiver};
+use crate::client::circuit::{HopSettings, path};
use crate::client::reactor::MetaCellDisposition;
use crate::client::stream::queue::{StreamQueueSender, stream_queue};
use crate::client::stream::{AnyCmdChecker, DrainRateRequest, StreamRateLimit, StreamStatus};
@@ -30,6 +28,7 @@ use crate::crypto::handshake::ntor::{NtorClient, NtorPublicKey};
use crate::crypto::handshake::ntor_v3::{NtorV3Client, NtorV3PublicKey};
use crate::crypto::handshake::{ClientHandshake, KeyGenerator};
use crate::memquota::{CircuitAccount, SpecificAccount as _, StreamAccount};
+use crate::tunnel::TunnelScopedCircId;
use crate::util::SinkExt as _;
use crate::util::err::ReactorError;
use crate::util::notify::NotifySender;
@@ -81,8 +80,8 @@ use {
use {
super::conflux::ConfluxMsgHandler,
super::conflux::{ConfluxAction, OooRelayMsg},
- crate::client::TunnelId,
crate::client::reactor::RemoveLegReason,
+ crate::tunnel::TunnelId,
};
pub(super) use circhop::{CircHop, CircHopList};
@@ -334,7 +333,7 @@ impl Circuit {
// TODO-CGO: Take HopSettings instead of CircParams.
// (Do this after we've got the virtual-hop refactorings done for
// virtual extending.)
- params: &crate::circuit::CircParameters,
+ params: &crate::client::circuit::CircParameters,
done: ReactorResultChannel<()>,
) {
use tor_protover::{Protocols, named};
@@ -350,7 +349,7 @@ impl Circuit {
let settings = HopSettings::from_params_and_caps(
// This is for testing only, so we'll assume full negotiation took place.
- crate::circuit::HopNegotiationType::Full,
+ crate::client::circuit::HopNegotiationType::Full,
params,
&[named::FLOWCTRL_CC].into_iter().collect::<Protocols>(),
)
@@ -798,7 +797,7 @@ impl Circuit {
use tor_error::into_internal;
use tor_log_ratelim::log_ratelim;
- use crate::{circuit::CIRCUIT_BUFFER_SIZE, client::reactor::StreamReqInfo};
+ use crate::client::{circuit::CIRCUIT_BUFFER_SIZE, reactor::StreamReqInfo};
// We need to construct this early so that we don't double-borrow &mut self
diff --git a/crates/tor-proto/src/client/reactor/circuit/circhop.rs b/crates/tor-proto/src/client/reactor/circuit/circhop.rs
index 34fb76534..298b4da2f 100644
--- a/crates/tor-proto/src/client/reactor/circuit/circhop.rs
+++ b/crates/tor-proto/src/client/reactor/circuit/circhop.rs
@@ -2,9 +2,7 @@
use super::CircuitCmd;
use super::{CloseStreamBehavior, SEND_WINDOW_INIT, SendRelayCell};
-use crate::circuit::HopSettings;
-use crate::client::TunnelScopedCircId;
-use crate::client::circuit::StreamMpscReceiver;
+use crate::client::circuit::{HopSettings, StreamMpscReceiver};
use crate::client::stream::queue::StreamQueueSender;
use crate::client::stream::{
AnyCmdChecker, DrainRateRequest, StreamFlowControl, StreamRateLimit, StreamStatus,
@@ -15,6 +13,7 @@ use crate::client::streammap::{
use crate::congestion::CongestionControl;
use crate::congestion::sendme;
use crate::crypto::cell::HopNum;
+use crate::tunnel::TunnelScopedCircId;
use crate::util::notify::NotifySender;
use crate::{Error, Result};
diff --git a/crates/tor-proto/src/client/reactor/circuit/extender.rs b/crates/tor-proto/src/client/reactor/circuit/extender.rs
index 0a88a9555..b30ad91ec 100644
--- a/crates/tor-proto/src/client/reactor/circuit/extender.rs
+++ b/crates/tor-proto/src/client/reactor/circuit/extender.rs
@@ -1,13 +1,13 @@
//! Module providing [`CircuitExtender`].
use super::{Circuit, ReactorResultChannel};
-use crate::circuit::HopSettings;
-use crate::circuit::handshake::HandshakeRole;
-use crate::client::TunnelScopedCircId;
+use crate::client::circuit::HopSettings;
+use crate::client::circuit::handshake::HandshakeRole;
use crate::client::reactor::MetaCellDisposition;
use crate::crypto::cell::HopNum;
use crate::crypto::handshake::fast::CreateFastClient;
use crate::crypto::handshake::ntor_v3::NtorV3Client;
+use crate::tunnel::TunnelScopedCircId;
use crate::{Error, Result};
use crate::{HopLocation, congestion};
use oneshot_fused_workaround as oneshot;
diff --git a/crates/tor-proto/src/client/reactor/conflux.rs b/crates/tor-proto/src/client/reactor/conflux.rs
index aeaa0a7d4..29d6b1ba3 100644
--- a/crates/tor-proto/src/client/reactor/conflux.rs
+++ b/crates/tor-proto/src/client/reactor/conflux.rs
@@ -22,11 +22,13 @@ use tor_cell::relaycell::{AnyRelayMsgOuter, RelayCmd};
use tor_error::{Bug, bad_api_usage, internal};
use tor_linkspec::HasRelayIds as _;
-use crate::circuit::path::HopDetail;
-use crate::circuit::{TunnelMutableState, UniqId};
+use crate::circuit::UniqId;
+use crate::client::circuit::TunnelMutableState;
+use crate::client::circuit::path::HopDetail;
use crate::client::reactor::circuit::ConfluxStatus;
-use crate::client::{TunnelId, streammap};
+use crate::client::streammap;
use crate::crypto::cell::HopNum;
+use crate::tunnel::TunnelId;
use crate::util::err::ReactorError;
use super::circuit::CircHop;
diff --git a/crates/tor-proto/src/client/reactor/control.rs b/crates/tor-proto/src/client/reactor/control.rs
index 1ed358acd..6ed91250f 100644
--- a/crates/tor-proto/src/client/reactor/control.rs
+++ b/crates/tor-proto/src/client/reactor/control.rs
@@ -6,9 +6,8 @@ use super::{
RunOnceCmdInner, SendRelayCell,
};
use crate::Result;
-use crate::circuit::HopSettings;
use crate::client::circuit::celltypes::CreateResponse;
-use crate::client::circuit::path;
+use crate::client::circuit::{HopSettings, path};
use crate::client::reactor::circuit::circ_extensions_from_settings;
use crate::client::reactor::{NoJoinPointError, NtorClient, ReactorError};
use crate::client::stream::queue::StreamQueueSender;
@@ -20,7 +19,7 @@ use crate::crypto::handshake::ntor_v3::{NtorV3Client, NtorV3PublicKey};
use crate::util::notify::NotifySender;
use crate::util::skew::ClockSkew;
#[cfg(test)]
-use crate::{circuit::CircParameters, circuit::UniqId, crypto::cell::HopNum};
+use crate::{circuit::UniqId, client::circuit::CircParameters, crypto::cell::HopNum};
use postage::watch;
use tor_cell::chancell::msg::HandshakeType;
use tor_cell::relaycell::flow_ctrl::XonKbpsEwma;
diff --git a/crates/tor-proto/src/client/stream/incoming.rs b/crates/tor-proto/src/client/stream/incoming.rs
index de5159f4e..a4e6040ff 100644
--- a/crates/tor-proto/src/client/stream/incoming.rs
+++ b/crates/tor-proto/src/client/stream/incoming.rs
@@ -3,8 +3,8 @@
use bitvec::prelude::*;
use super::{AnyCmdChecker, DataStream, StreamStatus};
-use crate::circuit::ClientCircSyncView;
use crate::client::StreamComponents;
+use crate::client::circuit::ClientCircSyncView;
use crate::client::reactor::CloseStreamBehavior;
use crate::{Error, Result};
use derive_deftly::Deftly;
diff --git a/crates/tor-proto/src/crypto/cell/cgo.rs b/crates/tor-proto/src/crypto/cell/cgo.rs
index 314b1e83f..2851d006e 100644
--- a/crates/tor-proto/src/crypto/cell/cgo.rs
+++ b/crates/tor-proto/src/crypto/cell/cgo.rs
@@ -31,7 +31,7 @@ use tor_error::internal;
use zeroize::Zeroizing;
use super::{CryptInit, RelayCellBody};
-use crate::{circuit::CircuitBinding, util::ct};
+use crate::{client::circuit::CircuitBinding, util::ct};
/// Size of CGO tag, in bytes.
const CGO_TAG_LEN: usize = 16;
diff --git a/crates/tor-proto/src/crypto/cell/tor1.rs b/crates/tor-proto/src/crypto/cell/tor1.rs
index 25d86ccbd..4e5cf7687 100644
--- a/crates/tor-proto/src/crypto/cell/tor1.rs
+++ b/crates/tor-proto/src/crypto/cell/tor1.rs
@@ -8,7 +8,7 @@
//! I am calling this design `tor1`; it does not have a generally recognized
//! name.
-use crate::{Error, Result, circuit::CircuitBinding, crypto::binding::CIRC_BINDING_LEN};
+use crate::{Error, Result, client::circuit::CircuitBinding, crypto::binding::CIRC_BINDING_LEN};
use cipher::{KeyIvInit, StreamCipher};
use digest::Digest;
diff --git a/crates/tor-proto/src/lib.rs b/crates/tor-proto/src/lib.rs
index c15191694..0ca1d8626 100644
--- a/crates/tor-proto/src/lib.rs
+++ b/crates/tor-proto/src/lib.rs
@@ -56,10 +56,12 @@
#[cfg(feature = "bench")]
pub mod bench_utils;
pub mod channel;
+pub mod circuit;
pub mod client;
mod congestion;
mod crypto;
pub mod memquota;
+pub(crate) mod tunnel;
mod util;
#[cfg(feature = "relay")]
@@ -69,7 +71,7 @@ pub use util::err::{Error, ResolveError};
pub use util::skew::ClockSkew;
pub use channel::params::ChannelPaddingInstructions;
-pub use client::{ClientTunnel, HopLocation, TargetHop, circuit};
+pub use client::{ClientTunnel, HopLocation, TargetHop};
pub use congestion::params as ccparams;
pub use crypto::cell::{HopNum, HopNumDisplay};
#[cfg(feature = "send-control-msg")]
diff --git a/crates/tor-proto/src/relay/channel_provider.rs b/crates/tor-proto/src/relay/channel_provider.rs
index 5bb16e557..1289ca239 100644
--- a/crates/tor-proto/src/relay/channel_provider.rs
+++ b/crates/tor-proto/src/relay/channel_provider.rs
@@ -4,7 +4,7 @@
use crate::Result;
use crate::channel::Channel;
-use crate::client::TunnelId;
+use crate::tunnel::TunnelId;
use futures::channel::mpsc;
diff --git a/crates/tor-proto/src/relay/reactor.rs b/crates/tor-proto/src/relay/reactor.rs
index 3d5bd4473..8a6a21008 100644
--- a/crates/tor-proto/src/relay/reactor.rs
+++ b/crates/tor-proto/src/relay/reactor.rs
@@ -3,9 +3,9 @@
use crate::DynTimeProvider;
use crate::Result;
use crate::channel::Channel;
-use crate::client::circuit::unique_id::UniqId;
-use crate::client::{TunnelId, TunnelScopedCircId};
+use crate::circuit::UniqId;
use crate::memquota::CircuitAccount;
+use crate::tunnel::{TunnelId, TunnelScopedCircId};
use crate::util::err::ReactorError;
use tor_cell::chancell::CircId;
diff --git a/crates/tor-proto/src/tunnel.rs b/crates/tor-proto/src/tunnel.rs
new file mode 100644
index 000000000..f02b5794c
--- /dev/null
+++ b/crates/tor-proto/src/tunnel.rs
@@ -0,0 +1,54 @@
+//! Module exposing tunnel-related types shared by clients and relays.
+
+use std::sync::atomic::{AtomicU64, Ordering};
+
+use crate::circuit::UniqId;
+use derive_more::Display;
+
+/// The unique identifier of a tunnel.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display)]
+#[display("{}", _0)]
+#[cfg_attr(feature = "relay", visibility::make(pub))]
+#[allow(unreachable_pub)] // TODO(#1447): use in ChanMgr's ChannelProvider impl
+pub(crate) struct TunnelId(u64);
+
+impl TunnelId {
+ /// Create a new TunnelId.
+ ///
+ /// # Panics
+ ///
+ /// Panics if we have exhausted the possible space of u64 IDs.
+ pub(crate) fn next() -> TunnelId {
+ /// The next unique tunnel ID.
+ static NEXT_TUNNEL_ID: AtomicU64 = AtomicU64::new(1);
+ let id = NEXT_TUNNEL_ID.fetch_add(1, Ordering::Relaxed);
+ assert!(id != 0, "Exhausted Tunnel ID space?!");
+ TunnelId(id)
+ }
+}
+
+/// The identifier of a circuit [`UniqId`] within a tunnel.
+///
+/// This type is only needed for logging purposes: a circuit's [`UniqId`] is
+/// process-unique, but in the logs it's often useful to display the
+/// owning tunnel's ID alongside the circuit identifier.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display)]
+#[display("Circ {}.{}", tunnel_id, circ_id.display_chan_circ())]
+pub(crate) struct TunnelScopedCircId {
+ /// The identifier of the owning tunnel
+ tunnel_id: TunnelId,
+ /// The process-unique identifier of the circuit
+ circ_id: UniqId,
+}
+
+impl TunnelScopedCircId {
+ /// Create a new [`TunnelScopedCircId`] from the specified identifiers.
+ pub(crate) fn new(tunnel_id: TunnelId, circ_id: UniqId) -> Self {
+ Self { tunnel_id, circ_id }
+ }
+
+ /// Return the [`UniqId`].
+ pub(crate) fn unique_id(&self) -> UniqId {
+ self.circ_id
+ }
+}