#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum TransportConfidentiality {
EndToEnd,
HopByHop,
}
tokio::task_local! {
static CONFIDENTIALITY: TransportConfidentiality;
}
pub(crate) async fn with_confidentiality<F, T>(level: TransportConfidentiality, f: F) -> T
where
F: std::future::Future<Output = T>,
{
CONFIDENTIALITY.scope(level, f).await
}
pub(crate) fn current() -> TransportConfidentiality {
CONFIDENTIALITY
.try_with(|c| *c)
.unwrap_or(TransportConfidentiality::HopByHop)
}
tokio::task_local! {
static BINDING: &'static str;
}
pub(crate) async fn with_binding<F, T>(binding: &'static str, f: F) -> T
where
F: std::future::Future<Output = T>,
{
BINDING.scope(binding, f).await
}
pub(crate) fn audit_channel() -> &'static str {
match BINDING.try_with(|b| *b) {
Ok("https") => "trust-task/https",
Ok("didcomm") => "trust-task/didcomm",
Ok("tsp") => "trust-task/tsp",
_ => super::helpers::TRANSPORT_TRUST_TASK,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_to_hop_by_hop_outside_a_scope() {
assert_eq!(current(), TransportConfidentiality::HopByHop);
}
#[tokio::test]
async fn reports_what_the_scope_set() {
let seen =
with_confidentiality(TransportConfidentiality::EndToEnd, async { current() }).await;
assert_eq!(seen, TransportConfidentiality::EndToEnd);
assert_eq!(current(), TransportConfidentiality::HopByHop);
}
#[tokio::test]
async fn audit_channel_names_the_binding_only_inside_a_scope() {
assert_eq!(audit_channel(), "trust-task");
for (binding, channel) in [
("https", "trust-task/https"),
("didcomm", "trust-task/didcomm"),
("tsp", "trust-task/tsp"),
] {
assert_eq!(
with_binding(binding, async { audit_channel() }).await,
channel
);
}
}
}