use crate::util::{AssociationIdGenerator, RandomAssociationIdGenerator};
use alloc::boxed::Box;
use alloc::sync::Arc;
use bytes::Bytes;
use core::fmt;
pub(crate) const RECEIVE_MTU: usize = 8192;
pub(crate) const INITIAL_MTU: u32 = 1228;
pub(crate) const INITIAL_RECV_BUF_SIZE: u32 = 1024 * 1024;
pub(crate) const COMMON_HEADER_SIZE: u32 = 12;
pub(crate) const DATA_CHUNK_HEADER_SIZE: u32 = 16;
pub(crate) const DEFAULT_MAX_MESSAGE_SIZE: u32 = 65536;
pub(crate) const RTO_INITIAL: u64 = 3000;
pub(crate) const RTO_MIN: u64 = 1000;
pub(crate) const RTO_MAX: u64 = 60000;
const DEFAULT_MAX_INIT_RETRANS: usize = 8;
#[derive(Debug)]
pub struct TransportConfig {
max_receive_buffer_size: u32,
max_num_outbound_streams: u16,
max_num_inbound_streams: u16,
max_send_message_size: u32,
max_receive_message_size: u32,
max_init_retransmits: Option<usize>,
max_data_retransmits: Option<usize>,
rto_initial_ms: u64,
rto_min_ms: u64,
rto_max_ms: u64,
}
impl Default for TransportConfig {
fn default() -> Self {
TransportConfig {
max_receive_buffer_size: INITIAL_RECV_BUF_SIZE,
max_send_message_size: DEFAULT_MAX_MESSAGE_SIZE,
max_receive_message_size: DEFAULT_MAX_MESSAGE_SIZE,
max_num_outbound_streams: u16::MAX,
max_num_inbound_streams: u16::MAX,
max_init_retransmits: Some(DEFAULT_MAX_INIT_RETRANS),
max_data_retransmits: None,
rto_initial_ms: RTO_INITIAL,
rto_min_ms: RTO_MIN,
rto_max_ms: RTO_MAX,
}
}
}
impl TransportConfig {
pub fn with_max_receive_buffer_size(mut self, value: u32) -> Self {
self.max_receive_buffer_size = value;
self
}
pub fn with_max_send_message_size(mut self, value: u32) -> Self {
self.max_send_message_size = value;
self
}
pub fn with_max_receive_message_size(mut self, value: u32) -> Self {
self.max_receive_message_size = value;
self
}
#[deprecated(note = "Use with_max_send_message_size instead")]
pub fn with_max_message_size(self, value: u32) -> Self {
self.with_max_send_message_size(value)
}
pub fn with_max_num_outbound_streams(mut self, value: u16) -> Self {
self.max_num_outbound_streams = value;
self
}
pub fn with_max_num_inbound_streams(mut self, value: u16) -> Self {
self.max_num_inbound_streams = value;
self
}
pub(crate) fn max_receive_buffer_size(&self) -> u32 {
self.max_receive_buffer_size
}
pub(crate) fn max_send_message_size(&self) -> u32 {
self.max_send_message_size
}
pub(crate) fn max_receive_message_size(&self) -> u32 {
self.max_receive_message_size
}
pub(crate) fn max_num_outbound_streams(&self) -> u16 {
self.max_num_outbound_streams
}
pub(crate) fn max_num_inbound_streams(&self) -> u16 {
self.max_num_inbound_streams
}
pub fn with_max_init_retransmits(mut self, value: Option<usize>) -> Self {
self.max_init_retransmits = value;
self
}
pub fn with_max_data_retransmits(mut self, value: Option<usize>) -> Self {
self.max_data_retransmits = value;
self
}
pub fn with_rto_initial_ms(mut self, value: u64) -> Self {
self.rto_initial_ms = value;
self
}
pub fn with_rto_min_ms(mut self, value: u64) -> Self {
self.rto_min_ms = value;
self
}
pub fn with_rto_max_ms(mut self, value: u64) -> Self {
self.rto_max_ms = value;
self
}
pub(crate) fn max_init_retransmits(&self) -> Option<usize> {
self.max_init_retransmits
}
pub(crate) fn max_data_retransmits(&self) -> Option<usize> {
self.max_data_retransmits
}
pub(crate) fn rto_initial_ms(&self) -> u64 {
self.rto_initial_ms
}
pub(crate) fn rto_min_ms(&self) -> u64 {
self.rto_min_ms
}
pub(crate) fn rto_max_ms(&self) -> u64 {
self.rto_max_ms
}
}
#[derive(Clone)]
pub struct EndpointConfig {
pub(crate) max_payload_size: u32,
pub(crate) aid_generator_factory:
Arc<dyn Fn() -> Box<dyn AssociationIdGenerator> + Send + Sync>,
}
impl Default for EndpointConfig {
fn default() -> Self {
Self::new()
}
}
impl EndpointConfig {
pub fn new() -> Self {
let aid_factory: fn() -> Box<dyn AssociationIdGenerator> =
|| Box::<RandomAssociationIdGenerator>::default();
Self {
max_payload_size: INITIAL_MTU - (COMMON_HEADER_SIZE + DATA_CHUNK_HEADER_SIZE),
aid_generator_factory: Arc::new(aid_factory),
}
}
pub fn aid_generator<F: Fn() -> Box<dyn AssociationIdGenerator> + Send + Sync + 'static>(
&mut self,
factory: F,
) -> &mut Self {
self.aid_generator_factory = Arc::new(factory);
self
}
pub fn max_payload_size(&mut self, value: u32) -> &mut Self {
self.max_payload_size = value;
self
}
#[doc(hidden)]
pub fn get_max_payload_size(&self) -> u32 {
self.max_payload_size
}
}
impl fmt::Debug for EndpointConfig {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("EndpointConfig")
.field("max_payload_size", &self.max_payload_size)
.field("aid_generator_factory", &"[ elided ]")
.finish()
}
}
#[derive(Debug, Clone)]
pub struct ServerConfig {
pub transport: Arc<TransportConfig>,
pub(crate) concurrent_associations: u32,
}
impl Default for ServerConfig {
fn default() -> Self {
ServerConfig {
transport: Arc::new(TransportConfig::default()),
concurrent_associations: 100_000,
}
}
}
impl ServerConfig {
pub fn new() -> Self {
ServerConfig::default()
}
}
pub const DEFAULT_SCTP_PORT: u16 = 5000;
pub const MAX_SNAP_INIT_BYTES: usize = 2048;
#[derive(Debug, Clone)]
pub struct ClientConfig {
pub transport: Arc<TransportConfig>,
pub(crate) local_sctp_init: Option<Bytes>,
pub(crate) remote_sctp_init: Option<Bytes>,
}
impl Default for ClientConfig {
fn default() -> Self {
ClientConfig {
transport: Arc::new(TransportConfig::default()),
local_sctp_init: None,
remote_sctp_init: None,
}
}
}
impl ClientConfig {
pub fn new() -> Self {
ClientConfig::default()
}
pub fn with_snap(mut self, local_sctp_init: Bytes, remote_sctp_init: Bytes) -> Self {
self.local_sctp_init = Some(local_sctp_init);
self.remote_sctp_init = Some(remote_sctp_init);
self
}
}
pub fn generate_snap_token(config: &TransportConfig) -> Result<Bytes, crate::error::Error> {
use crate::chunk::{Chunk, chunk_init::ChunkInit};
use core::num::NonZeroU32;
use rand::random;
let mut init = ChunkInit {
initiate_tag: random::<NonZeroU32>().get(),
initial_tsn: random::<NonZeroU32>().get(),
num_outbound_streams: u16::MAX,
num_inbound_streams: u16::MAX,
advertised_receiver_window_credit: config.max_receive_buffer_size(),
..Default::default()
};
init.set_supported_extensions();
init.check()?;
init.marshal()
}