use std::net::SocketAddr;
use indexmap::IndexSet;
use memberlist_core::proto::CIDRsPolicy;
use nodecraft::resolver::AddressResolver;
use crate::StreamLayer;
#[viewit::viewit(
vis_all = "pub(crate)",
getters(vis_all = "pub"),
setters(vis_all = "pub", prefix = "with")
)]
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "I: serde::Serialize, A: AddressResolver, A::Address: serde::Serialize, A::ResolvedAddress: serde::Serialize, A::Options: serde::Serialize, S::Options: serde::Serialize",
deserialize = "I: serde::Deserialize<'de>, A: AddressResolver, A::Address: serde::Deserialize<'de>, A::ResolvedAddress: serde::Deserialize<'de>, A::Options: serde::Deserialize<'de>, S::Options: serde::Deserialize<'de>"
))
)]
pub struct NetTransportOptions<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
{
#[viewit(
getter(const, style = "ref", attrs(doc = "Get the id of the node."),),
setter(attrs(doc = "Set the id of the node. (Builder pattern)"),)
)]
id: I,
#[viewit(
getter(
style = "ref",
const,
attrs(doc = "Get a set of addresses to bind to for both TCP and UDP communications."),
),
setter(attrs(
doc = "Set the set of addresses to bind to for both TCP and UDP communications. (Builder pattern)"
),)
)]
bind_addresses: IndexSet<A::Address>,
#[viewit(
getter(
const,
style = "ref",
result(converter(fn = "Option::as_ref"), type = "Option<&A::ResolvedAddress>"),
attrs(doc = "Get the address to advertise to other nodes."),
),
setter(
rename = "maybe_advertise_address",
attrs(
doc = "Set the address to advertise to other nodes. This address is not bound or listened on. (Builder pattern)"
),
)
)]
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
advertise_address: Option<A::ResolvedAddress>,
#[viewit(
getter(const, style = "ref", attrs(doc = "Get the address resolver options."),),
setter(attrs(doc = "Set the address resolver options. (Builder pattern)"),)
)]
resolver: A::Options,
#[viewit(
getter(const, style = "ref", attrs(doc = "Get the stream layer options."),),
setter(attrs(doc = "Set the stream layer options. (Builder pattern)"),)
)]
stream_layer: S::Options,
#[cfg_attr(feature = "serde", serde(default))]
#[viewit(
getter(
const,
style = "ref",
attrs(doc = "Get the policy for Classless Inter-Domain Routing (CIDR)."),
),
setter(attrs(
doc = "Set the policy for Classless Inter-Domain Routing (CIDR). (Builder pattern)"
),)
)]
cidrs_policy: CIDRsPolicy,
#[viewit(
getter(
const,
attrs(doc = "Get the maximum payload size can be sent by UDP. Default is `1472` bytes."),
),
setter(attrs(
doc = "Set the maximum payload size can be sent by UDP. Default is `1472` bytes. (Builder pattern)"
),)
)]
max_packet_size: usize,
#[viewit(
getter(const, attrs(doc = "Get the UDP receive window. Default is `2MB`."),),
setter(attrs(doc = "Set the UDP receive window. Default is `2MB`. (Builder pattern)"),)
)]
recv_buffer_size: usize,
#[cfg(feature = "metrics")]
#[cfg_attr(docsrs, doc(cfg(feature = "metrics")))]
#[viewit(
getter(
style = "ref",
result(
converter(fn = "Option::as_deref"),
type = "Option<&memberlist_core::proto::MetricLabels>"
),
attrs(
doc = "Get the metrics labels.",
cfg(feature = "metrics"),
cfg_attr(docsrs, doc(cfg(feature = "metrics")))
),
),
setter(attrs(
doc = "Set the metrics labels. (Builder pattern)",
cfg(feature = "metrics"),
cfg_attr(docsrs, doc(cfg(feature = "metrics")))
))
)]
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
metric_labels: Option<std::sync::Arc<memberlist_core::proto::MetricLabels>>,
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer> Clone
for NetTransportOptions<I, A, S>
where
I: Clone,
A::Options: Clone,
A::ResolvedAddress: Clone,
S::Options: Clone,
{
fn clone(&self) -> Self {
Self {
id: self.id.clone(),
bind_addresses: self.bind_addresses.clone(),
advertise_address: self.advertise_address,
stream_layer: self.stream_layer.clone(),
resolver: self.resolver.clone(),
cidrs_policy: self.cidrs_policy.clone(),
max_packet_size: self.max_packet_size,
recv_buffer_size: self.recv_buffer_size,
#[cfg(feature = "metrics")]
metric_labels: self.metric_labels.clone(),
}
}
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
NetTransportOptions<I, A, S>
where
A::Options: Default,
S::Options: Default,
{
#[inline]
pub fn new(id: I) -> Self {
Self::with_resolver_options_and_stream_layer_options(id, Default::default(), Default::default())
}
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
NetTransportOptions<I, A, S>
where
S::Options: Default,
{
#[inline]
pub fn with_resolver_options(id: I, resolver_options: A::Options) -> Self {
Self::with_resolver_options_and_stream_layer_options(id, resolver_options, Default::default())
}
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
NetTransportOptions<I, A, S>
where
A::Options: Default,
{
#[inline]
pub fn with_stream_layer_options(id: I, stream_layer_options: S::Options) -> Self {
Self::with_resolver_options_and_stream_layer_options(
id,
Default::default(),
stream_layer_options,
)
}
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
NetTransportOptions<I, A, S>
{
pub fn with_resolver_options_and_stream_layer_options(
id: I,
resolver_options: A::Options,
stream_layer_opts: S::Options,
) -> Self {
Self {
id,
bind_addresses: IndexSet::new(),
advertise_address: None,
resolver: resolver_options,
stream_layer: stream_layer_opts,
cidrs_policy: CIDRsPolicy::allow_all(),
max_packet_size: 1472,
recv_buffer_size: super::DEFAULT_UDP_RECV_BUF_SIZE,
#[cfg(feature = "metrics")]
metric_labels: None,
}
}
pub fn add_bind_address(&mut self, addr: A::Address) -> &mut Self {
self.bind_addresses.insert(addr);
self
}
pub fn with_advertise_address(mut self, addr: A::ResolvedAddress) -> Self {
self.advertise_address = Some(addr);
self
}
}
impl<I, A: AddressResolver<ResolvedAddress = SocketAddr>, S: StreamLayer>
From<NetTransportOptions<I, A, S>> for (A::Options, S::Options, Options<I, A>)
{
fn from(opts: NetTransportOptions<I, A, S>) -> (A::Options, S::Options, Options<I, A>) {
(
opts.resolver,
opts.stream_layer,
Options {
id: opts.id,
bind_addresses: opts.bind_addresses,
advertise_address: opts.advertise_address,
cidrs_policy: opts.cidrs_policy,
max_packet_size: opts.max_packet_size,
recv_buffer_size: opts.recv_buffer_size,
#[cfg(feature = "metrics")]
metric_labels: opts.metric_labels,
},
)
}
}
#[viewit::viewit(getters(skip), setters(skip))]
pub(crate) struct Options<I, A: AddressResolver<ResolvedAddress = SocketAddr>> {
id: I,
bind_addresses: IndexSet<A::Address>,
advertise_address: Option<A::ResolvedAddress>,
cidrs_policy: CIDRsPolicy,
max_packet_size: usize,
recv_buffer_size: usize,
#[cfg(feature = "metrics")]
metric_labels: Option<std::sync::Arc<memberlist_core::proto::MetricLabels>>,
}