use super::*;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SocketOptions {
pub connect: Connect,
pub session: Session,
pub encryption: Encryption,
pub sender: Sender,
pub receiver: Receiver,
}
impl SocketOptions {
pub fn new() -> Valid<Self> {
Self::default().try_validate().unwrap()
}
}
impl Validation for SocketOptions {
type Error = OptionsError;
fn is_valid(&self) -> Result<(), Self::Error> {
self.connect.is_valid()?;
self.session.is_valid()?;
self.encryption.is_valid()?;
self.sender.is_valid()?;
self.receiver.is_valid()?;
self.is_valid_composite()
}
}
impl CompositeValidation for SocketOptions {
fn is_valid_composite(&self) -> Result<(), <Self as Validation>::Error> {
if self.receiver.buffer_size
> self.sender.flow_control_window_size * self.session.max_segment_size
{
return Err(OptionsError::ReceiveBufferTooLarge {
buffer: self.receiver.buffer_size,
max_segment: self.session.max_segment_size,
flow_control_window: self.sender.flow_control_window_size,
});
}
if self.connect.udp_recv_buffer_size
> self.sender.flow_control_window_size * self.session.max_segment_size
{
return Err(OptionsError::UdpReceiveBufferTooLarge {
udp_buffer: self.connect.udp_recv_buffer_size,
max_segment: self.session.max_segment_size,
flow_control_window: self.sender.flow_control_window_size,
});
}
if self.connect.udp_send_buffer_size
> self.sender.flow_control_window_size * self.session.max_segment_size
{
return Err(OptionsError::UdpSenderBufferTooLarge {
udp_buffer: self.connect.udp_send_buffer_size,
max_segment: self.session.max_segment_size,
flow_control_window: self.sender.flow_control_window_size,
});
}
Ok(())
}
}
impl OptionsOf<Connect> for SocketOptions {
fn set_options(&mut self, value: Connect) {
self.connect = value;
}
}
impl OptionsOf<Session> for SocketOptions {
fn set_options(&mut self, value: Session) {
self.session = value;
}
}
impl OptionsOf<Encryption> for SocketOptions {
fn set_options(&mut self, value: Encryption) {
self.encryption = value;
}
}
impl OptionsOf<Sender> for SocketOptions {
fn set_options(&mut self, value: Sender) {
self.sender = value;
}
}
impl OptionsOf<Receiver> for SocketOptions {
fn set_options(&mut self, value: Receiver) {
self.receiver = value;
}
}
#[cfg(test)]
mod test {
use std::convert::TryInto;
use std::time::Duration;
use super::*;
use assert_matches::assert_matches;
#[test]
fn test() -> Result<(), OptionsError> {
let _ = SocketOptions::new()
.with(Connect {
timeout: Duration::from_secs(1),
..Default::default()
})?
.with(Session {
peer_idle_timeout: Duration::from_secs(20),
..Default::default()
})?
.with(Encryption {
key_size: KeySize::AES192,
passphrase: "this is a passphrase".try_into().ok(),
..Default::default()
})?
.with(Sender {
buffer_size: ByteCount(1000000),
..Default::default()
})?
.with(Receiver {
buffer_size: ByteCount(1000000),
..Default::default()
})?;
let _ = SocketOptions {
connect: Connect {
timeout: Duration::from_secs(1),
..Default::default()
},
session: Session {
peer_idle_timeout: Duration::from_secs(20),
..Default::default()
},
encryption: Encryption {
key_size: KeySize::AES192,
passphrase: "this is a passphrase".try_into().ok(),
..Default::default()
},
sender: Sender {
buffer_size: ByteCount(1000000),
..Default::default()
},
receiver: Receiver {
buffer_size: ByteCount(1000000),
..Default::default()
},
}
.try_validate()?;
assert_eq!(
SocketOptions::new().set(|op| {
op.connect.udp_recv_buffer_size = ByteCount(1500 * 10_000 + 1);
op.session.max_segment_size = PacketSize(1500);
op.sender.flow_control_window_size = PacketCount(10_000);
}),
Err(OptionsError::UdpReceiveBufferTooLarge {
udp_buffer: ByteCount(1500 * 10_000 + 1),
max_segment: PacketSize(1500),
flow_control_window: PacketCount(10_000),
})
);
assert_matches!(
SocketOptions::new().set(|op| {
op.connect.udp_recv_buffer_size = ByteCount(1500 * 10_000);
op.session.max_segment_size = PacketSize(1500);
op.sender.flow_control_window_size = PacketCount(10_000);
}),
Ok(_)
);
assert_eq!(
SocketOptions::new().set(|op| {
op.connect.udp_send_buffer_size = ByteCount(1500 * 10_000 + 1);
op.session.max_segment_size = PacketSize(1500);
op.sender.flow_control_window_size = PacketCount(10_000);
}),
Err(OptionsError::UdpSenderBufferTooLarge {
udp_buffer: ByteCount(1500 * 10_000 + 1),
max_segment: PacketSize(1500),
flow_control_window: PacketCount(10_000),
})
);
assert_matches!(
SocketOptions::new().set(|op| {
op.connect.udp_send_buffer_size = ByteCount(1500 * 10_000);
op.session.max_segment_size = PacketSize(1500);
op.sender.flow_control_window_size = PacketCount(10_000);
}),
Ok(_)
);
Ok(())
}
}