channel padding: Send negotiation cells
This commit is contained in:
parent
0a1bffb047
commit
50ca64218e
|
@ -3476,6 +3476,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tor-basic-utils",
|
"tor-basic-utils",
|
||||||
|
"tor-cell",
|
||||||
"tor-config",
|
"tor-config",
|
||||||
"tor-error",
|
"tor-error",
|
||||||
"tor-linkspec",
|
"tor-linkspec",
|
||||||
|
|
|
@ -25,6 +25,7 @@ rand = "0.8"
|
||||||
serde = { version = "1.0.103", features = ["derive"] }
|
serde = { version = "1.0.103", features = ["derive"] }
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tor-basic-utils = { path = "../tor-basic-utils", version = "0.3.3" }
|
tor-basic-utils = { path = "../tor-basic-utils", version = "0.3.3" }
|
||||||
|
tor-cell = { path = "../tor-cell", version = "0.5.0" }
|
||||||
tor-config = { path = "../tor-config", version = "0.5.0" }
|
tor-config = { path = "../tor-config", version = "0.5.0" }
|
||||||
tor-error = { path = "../tor-error", version = "0.3.2" }
|
tor-error = { path = "../tor-error", version = "0.3.2" }
|
||||||
tor-linkspec = { path = "../tor-linkspec", version = "0.4.0" }
|
tor-linkspec = { path = "../tor-linkspec", version = "0.4.0" }
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{ChannelConfig, Dormancy, Error, Result};
|
||||||
use std::collections::{hash_map, HashMap};
|
use std::collections::{hash_map, HashMap};
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use tor_cell::chancell::msg::PaddingNegotiate;
|
||||||
use tor_config::PaddingLevel;
|
use tor_config::PaddingLevel;
|
||||||
use tor_error::{internal, into_internal};
|
use tor_error::{internal, into_internal};
|
||||||
use tor_netdir::{params::CHANNEL_PADDING_TIMEOUT_UPPER_BOUND, NetDir};
|
use tor_netdir::{params::CHANNEL_PADDING_TIMEOUT_UPPER_BOUND, NetDir};
|
||||||
|
@ -337,8 +338,6 @@ impl<C: AbstractChannel> ChannelMap<C> {
|
||||||
netdir: tor_netdir::Result<Arc<NetDir>>,
|
netdir: tor_netdir::Result<Arc<NetDir>>,
|
||||||
) -> StdResult<(), tor_error::Bug> {
|
) -> StdResult<(), tor_error::Bug> {
|
||||||
use ChannelState as CS;
|
use ChannelState as CS;
|
||||||
// TODO when entering/leaving dormant mode, send CELL_PADDING_NEGOTIATE to peers
|
|
||||||
// TODO with reduced padding, send CELL_PADDING_NEGOTIATE
|
|
||||||
|
|
||||||
// TODO when we support operation as a relay, inter-relay channels ought
|
// TODO when we support operation as a relay, inter-relay channels ought
|
||||||
// not to get padding.
|
// not to get padding.
|
||||||
|
@ -423,16 +422,61 @@ fn parameterize(
|
||||||
dormancy: Dormancy,
|
dormancy: Dormancy,
|
||||||
netdir: StdResult<&NetDirExtract, &()>,
|
netdir: StdResult<&NetDirExtract, &()>,
|
||||||
) -> StdResult<Option<ChannelsParamsUpdates>, tor_error::Bug> {
|
) -> StdResult<Option<ChannelsParamsUpdates>, tor_error::Bug> {
|
||||||
let padding_parameters = padding_parameters(config.padding, netdir)?;
|
// Everything in this calculation applies to *all* channels, disregarding
|
||||||
|
// channel usage. Usage is handled downstream, in the channel frontend.
|
||||||
|
// See the module doc in `crates/tor-proto/src/channel/padding.rs`.
|
||||||
|
|
||||||
|
let padding_of_level = |level| padding_parameters(level, netdir);
|
||||||
|
let padding_parameters = padding_of_level(config.padding)?;
|
||||||
|
let padding_default = padding_of_level(PaddingLevel::default())?;
|
||||||
|
|
||||||
let send_padding = (match dormancy {
|
let send_padding = (match dormancy {
|
||||||
Dormancy::Active => true,
|
Dormancy::Active => true,
|
||||||
Dormancy::Dormant => false,
|
Dormancy::Dormant => false,
|
||||||
}) && padding_parameters != PaddingParameters::all_zeroes();
|
}) && padding_parameters != PaddingParameters::all_zeroes();
|
||||||
|
|
||||||
|
let recv_padding = match config.padding {
|
||||||
|
PaddingLevel::Reduced => false,
|
||||||
|
PaddingLevel::Normal => send_padding,
|
||||||
|
PaddingLevel::None => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Whether the inbound padding approach we are to use, is the same as the default
|
||||||
|
// derived from the netdir (disregarding our config and dormancy).
|
||||||
|
//
|
||||||
|
// Ie, whether the parameters we want are precisely those that a peer would
|
||||||
|
// use by default (assuming they have the same view of the netdir as us).
|
||||||
|
let recv_equals_default = if padding_default == PaddingParameters::all_zeroes() {
|
||||||
|
// The netdir has padding disabled by setting the parameters to zero.
|
||||||
|
// That means our peers won't do padding unless we ask it to.
|
||||||
|
// Or to put it another way, our desired peer padding approach is the same as our
|
||||||
|
// peers' default iff we also think padding should be disabled.
|
||||||
|
!recv_padding
|
||||||
|
} else {
|
||||||
|
// Peers are going to do padding. That is the same approach as we want
|
||||||
|
// if we want to receive padding, with the same parameters.
|
||||||
|
recv_padding && padding_parameters == padding_default
|
||||||
|
};
|
||||||
|
|
||||||
|
let padding_negotiate = if recv_equals_default {
|
||||||
|
// Our padding approach is the same as peers' defaults. So the PADDING_NEGOTIATE
|
||||||
|
// message we need to send is the START(0,0). (The channel frontend elides an
|
||||||
|
// initial message of this form, - see crates/tor-proto/src/channel.rs::note_usage.)
|
||||||
|
//p
|
||||||
|
// If the netdir default is no padding, and we previously negotiated
|
||||||
|
// padding being enabled, and now want to disable it, we would send
|
||||||
|
// START(0,0) rather than STOP. That is OK (even, arguably, right).
|
||||||
|
PaddingNegotiate::start_default()
|
||||||
|
} else if !recv_padding {
|
||||||
|
PaddingNegotiate::stop()
|
||||||
|
} else {
|
||||||
|
padding_parameters.padding_negotiate_cell()?
|
||||||
|
};
|
||||||
|
|
||||||
let mut update = channels_params
|
let mut update = channels_params
|
||||||
.start_update()
|
.start_update()
|
||||||
.padding_enable(send_padding);
|
.padding_enable(send_padding)
|
||||||
|
.padding_negotiate(padding_negotiate);
|
||||||
if send_padding {
|
if send_padding {
|
||||||
update = update.padding_parameters(padding_parameters);
|
update = update.padding_parameters(padding_parameters);
|
||||||
}
|
}
|
||||||
|
@ -721,7 +765,8 @@ mod test {
|
||||||
"ChannelsParamsUpdates { padding_enable: None, \
|
"ChannelsParamsUpdates { padding_enable: None, \
|
||||||
padding_parameters: Some(Parameters { \
|
padding_parameters: Some(Parameters { \
|
||||||
low_ms: IntegerMilliseconds { value: 1500 }, \
|
low_ms: IntegerMilliseconds { value: 1500 }, \
|
||||||
high_ms: IntegerMilliseconds { value: 9500 } }) }"
|
high_ms: IntegerMilliseconds { value: 9500 } }), \
|
||||||
|
padding_negotiate: None }"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
eprintln!();
|
eprintln!();
|
||||||
|
|
|
@ -75,7 +75,7 @@ use crate::{Error, Result};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use std::sync::{Mutex, MutexGuard};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tor_cell::chancell::{msg, ChanCell, CircId};
|
use tor_cell::chancell::{msg, msg::PaddingNegotiate, ChanCell, CircId};
|
||||||
use tor_error::internal;
|
use tor_error::internal;
|
||||||
use tor_linkspec::{HasRelayIds, OwnedChanTarget};
|
use tor_linkspec::{HasRelayIds, OwnedChanTarget};
|
||||||
use tor_rtcompat::SleepProvider;
|
use tor_rtcompat::SleepProvider;
|
||||||
|
@ -212,8 +212,6 @@ enum PaddingControlState {
|
||||||
/// (which is fine since this timer is not enabled).
|
/// (which is fine since this timer is not enabled).
|
||||||
/// * We don't send any PADDING_NEGOTIATE cells. The peer is supposed to come to the
|
/// * We don't send any PADDING_NEGOTIATE cells. The peer is supposed to come to the
|
||||||
/// same conclusions as us, based on channel usage: it should also not send padding.
|
/// same conclusions as us, based on channel usage: it should also not send padding.
|
||||||
/// (Note: sending negotiation cells is not yet done at this point in the branch,
|
|
||||||
/// but it will be organised via `ChannelsParamsUpdates`.)
|
|
||||||
#[educe(Default)]
|
#[educe(Default)]
|
||||||
UsageDoesNotImplyPadding {
|
UsageDoesNotImplyPadding {
|
||||||
/// The last padding parameters (from reparameterize)
|
/// The last padding parameters (from reparameterize)
|
||||||
|
@ -448,7 +446,13 @@ impl Channel {
|
||||||
// Well, apparently the channel usage *does* imply padding now,
|
// Well, apparently the channel usage *does* imply padding now,
|
||||||
// so we need to (belatedly) enable the timer,
|
// so we need to (belatedly) enable the timer,
|
||||||
// send the padding negotiation cell, etc.
|
// send the padding negotiation cell, etc.
|
||||||
let params = params.clone();
|
let mut params = params.clone();
|
||||||
|
|
||||||
|
// Except, maybe the padding we would be requesting is precisely default,
|
||||||
|
// so we wouldn't actually want to send that cell.
|
||||||
|
if params.padding_negotiate == Some(PaddingNegotiate::start_default()) {
|
||||||
|
params.padding_negotiate = None;
|
||||||
|
}
|
||||||
|
|
||||||
match self.send_control(CtrlMsg::ConfigUpdate(Arc::new(params))) {
|
match self.send_control(CtrlMsg::ConfigUpdate(Arc::new(params))) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use educe::Educe;
|
use educe::Educe;
|
||||||
|
|
||||||
|
use tor_cell::chancell::msg::PaddingNegotiate;
|
||||||
|
|
||||||
use super::padding;
|
use super::padding;
|
||||||
|
|
||||||
/// Generate most of the module: things which contain or process all params fields (or each one)
|
/// Generate most of the module: things which contain or process all params fields (or each one)
|
||||||
|
@ -133,6 +135,9 @@ define_channels_params_and_automatic_impls! {
|
||||||
/// rather than the parameters changing,
|
/// rather than the parameters changing,
|
||||||
/// so the padding timer always keeps parameters, even when disabled.
|
/// so the padding timer always keeps parameters, even when disabled.
|
||||||
padding_parameters: padding::Parameters,
|
padding_parameters: padding::Parameters,
|
||||||
|
|
||||||
|
/// Channel padding negotiation cell
|
||||||
|
padding_negotiate: PaddingNegotiate,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placeholder function for saying whether to enable channel padding
|
/// Placeholder function for saying whether to enable channel padding
|
||||||
|
|
|
@ -263,6 +263,7 @@ impl<S: SleepProvider> Reactor<S> {
|
||||||
// if one is added and we fail to handle it here.
|
// if one is added and we fail to handle it here.
|
||||||
padding_enable,
|
padding_enable,
|
||||||
padding_parameters,
|
padding_parameters,
|
||||||
|
padding_negotiate,
|
||||||
} = &*updates;
|
} = &*updates;
|
||||||
if let Some(parameters) = padding_parameters {
|
if let Some(parameters) = padding_parameters {
|
||||||
self.padding_timer.as_mut().reconfigure(parameters);
|
self.padding_timer.as_mut().reconfigure(parameters);
|
||||||
|
@ -274,6 +275,9 @@ impl<S: SleepProvider> Reactor<S> {
|
||||||
self.padding_timer.as_mut().disable();
|
self.padding_timer.as_mut().disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(padding_negotiate) = padding_negotiate {
|
||||||
|
self.special_outgoing.padding_negotiate = Some(padding_negotiate.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue