use core::convert::TryFrom;
use core::ops::Range;
use crate::time::{Duration, Expiration, Instant};
use crate::wire::{ip::Address, tcp};
use super::endpoint::{
Entry,
EntryKey,
FourTuple,
Slot,
SlotKey};
#[derive(Clone, Copy, Debug, Hash)]
pub struct Connection {
pub current: State,
pub previous: State,
pub flow_control: Flow,
pub receive_window: u32,
pub sender_maximum_segment_size: u16,
pub receiver_maximum_segment_size: u16,
pub last_ack_receive_offset: tcp::SeqNumber,
pub ack_timer: Expiration,
pub ack_timeout: Duration,
pub retransmission_timer: Instant,
pub retransmission_timeout: Duration,
pub restart_timeout: Duration,
pub selective_acknowledgements: bool,
pub duplicate_ack: u8,
pub send: Send,
pub recv: Receive,
}
#[derive(Clone, Copy, Debug, Hash)]
pub struct Send {
pub unacked: tcp::SeqNumber,
pub next: tcp::SeqNumber,
pub last_time: Instant,
pub unsent: usize,
pub window: u16,
pub window_scale: u8,
pub initial_seq: tcp::SeqNumber,
}
#[derive(Clone, Copy, Debug, Hash)]
pub struct Receive {
pub next: tcp::SeqNumber,
pub acked: tcp::SeqNumber,
pub last_time: Instant,
pub window: u16,
pub window_scale: u8,
pub initial_seq: tcp::SeqNumber,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum State {
Closed,
Listen,
SynSent,
SynReceived,
Established,
FinWait,
Closing,
TimeWait,
CloseWait,
LastAck,
}
#[derive(Clone, Copy, Debug, Hash)]
pub struct Flow {
pub ssthresh: u32,
pub congestion_window: u32,
pub recover: tcp::SeqNumber,
}
#[derive(Clone, Copy, Default, Debug)]
#[must_use = "Doesn't do anything on its own, make sure any answer is actually sent."]
pub struct Signals {
pub delete: bool,
pub reset: bool,
pub receive: Option<ReceivedSegment>,
pub may_send: bool,
pub answer: Option<tcp::Repr>,
}
#[derive(Clone, Copy, Debug)]
pub struct AvailableBytes {
pub fin: bool,
pub total: usize,
}
#[derive(Clone, Copy, Debug)]
#[must_use = "Pass this to `Connection::set_recv_ack` after read the segment."]
pub struct ReceivedSegment {
pub syn: bool,
pub fin: bool,
pub data_len: usize,
pub begin: tcp::SeqNumber,
pub timestamp: Instant,
}
#[derive(Debug)]
pub struct InPacket {
pub segment: tcp::Repr,
pub from: Address,
pub time: Instant,
}
#[derive(Clone, Debug)]
pub struct Segment {
pub repr: tcp::Repr,
pub range: Range<usize>,
}
#[derive(Clone, Default, Debug)]
#[must_use = "Doesn't do anything on its own, make sure any answer is actually sent."]
pub struct OutSignals {
pub delete: bool,
pub segment: Option<Segment>,
}
pub trait Endpoint {
fn get(&self, index: SlotKey) -> Option<&Slot>;
fn get_mut(&mut self, index: SlotKey) -> Option<&mut Slot>;
fn entry(&mut self, index: SlotKey) -> Option<Entry>;
fn remove(&mut self, index: SlotKey);
fn find_tuple(&mut self, tuple: FourTuple) -> Option<Entry>;
fn source_port(&mut self, addr: Address) -> Option<u16>;
fn listen(&mut self, ip: Address, port: u16) -> Option<SlotKey>;
fn open(&mut self, tuple: FourTuple) -> Option<SlotKey>;
fn initial_seq_num(&mut self, id: FourTuple, time: Instant) -> tcp::SeqNumber;
}
pub(crate) struct Operator<'a> {
pub(crate) endpoint: &'a mut dyn Endpoint,
pub(crate) connection_key: SlotKey,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum AckUpdate {
TooLow,
Duplicate,
Updated {
new_bytes: u32
},
Unsent,
}
#[derive(Clone, Copy, Debug)]
struct InnerRepr {
flags: tcp::Flags,
seq_number: tcp::SeqNumber,
ack_number: Option<tcp::SeqNumber>,
window_len: u16,
window_scale: Option<u8>,
max_seg_size: Option<u16>,
sack_permitted: bool,
sack_ranges: [Option<(u32, u32)>; 3],
payload_len: u16,
}
impl Connection {
pub fn zeroed() -> Self {
Connection {
current: State::Closed,
previous: State::Closed,
flow_control: Flow {
ssthresh: 0,
congestion_window: 0,
recover: tcp::SeqNumber::default(),
},
receive_window: 0,
sender_maximum_segment_size: 0,
receiver_maximum_segment_size: 0,
last_ack_receive_offset: tcp::SeqNumber::default(),
ack_timer: Expiration::Never,
ack_timeout: Duration::from_millis(0),
retransmission_timer: Instant::from_millis(0),
retransmission_timeout: Duration::from_millis(0),
restart_timeout: Duration::from_millis(0),
selective_acknowledgements: false,
duplicate_ack: 0,
send: Send {
unacked: tcp::SeqNumber::default(),
next: tcp::SeqNumber::default(),
last_time: Instant::from_millis(0),
unsent: 0,
window: 0,
window_scale: 0,
initial_seq: tcp::SeqNumber::default(),
},
recv: Receive {
next: tcp::SeqNumber::default(),
acked: tcp::SeqNumber::default(),
last_time: Instant::from_millis(0),
window: 0,
window_scale: 0,
initial_seq: tcp::SeqNumber::default(),
},
}
}
pub fn arrives(&mut self, incoming: &InPacket, entry: EntryKey) -> Signals {
match self.current {
State::Closed => self.arrives_closed(incoming),
State::Listen => self.arrives_listen(incoming, entry),
State::SynSent => self.arrives_syn_sent(incoming, entry),
State::Established | State::FinWait => self.arrives_established(incoming, entry),
_ => unimplemented!(),
}
}
pub fn open(&mut self, time: Instant, entry: EntryKey)
-> Result<(), crate::layer::Error>
{
match self.current {
State::Closed | State::Listen => (),
_ => return Err(crate::layer::Error::Illegal),
}
self.change_state(State::SynSent);
self.send.initial_seq = entry.initial_seq_num(time);
self.send.unacked = self.send.initial_seq;
self.send.next = self.send.initial_seq + 1;
self.retransmission_timer = time;
Ok(())
}
fn arrives_closed(&mut self, incoming: &InPacket) -> Signals {
let segment = &incoming.segment;
let mut signals = Signals::default();
if segment.flags.rst() {
return signals;
}
if let Some(ack_number) = segment.ack_number {
signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: ack_number,
ack_number: None,
window_len: 0,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_back(segment));
} else {
signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: tcp::SeqNumber(0),
ack_number: Some(segment.seq_number + segment.sequence_len()),
window_len: 0,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_back(segment));
}
return signals;
}
fn arrives_listen(&mut self, incoming: &InPacket, mut entry: EntryKey)
-> Signals
{
let InPacket { segment, from, time, } = incoming;
let mut signals = Signals::default();
if segment.flags.rst() {
return signals;
}
if let Some(ack_number) = segment.ack_number { signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: ack_number,
ack_number: None,
window_len: 0,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_back(segment));
return signals;
}
if !segment.flags.syn() {
return signals;
}
let current_four = entry.four_tuple();
let new_four = FourTuple {
remote: *from,
.. current_four
};
entry.set_four_tuple(new_four);
self.recv.next = segment.seq_number + 1;
self.recv.initial_seq = segment.seq_number;
let isn = entry.initial_seq_num(*time);
self.send.next = isn + 1;
self.send.unacked = isn;
self.send.initial_seq = isn;
signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: isn,
ack_number: Some(self.ack_all()),
window_len: self.recv.window,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_to(new_four));
signals
}
fn arrives_syn_sent(&mut self, incoming: &InPacket, entry: EntryKey)
-> Signals
{
let InPacket { segment, from: _, time, } = incoming;
if let Some(ack) = segment.ack_number {
if ack <= self.send.initial_seq || ack > self.send.next {
if segment.flags.rst() { return Signals::default();
}
let mut signals = Signals::default();
signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: ack,
ack_number: Some(segment.seq_number),
window_len: 0,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_back(segment));
return signals;
}
}
if segment.flags.rst() {
if segment.ack_number.is_none() {
return Signals::default();
}
return self.remote_reset_connection();
}
if !segment.flags.syn() {
return Signals::default();
}
self.recv.initial_seq = segment.seq_number;
self.recv.next = segment.seq_number + 1;
self.send.window = segment.window_len;
self.send.window_scale = segment.window_scale.unwrap_or(0);
self.sender_maximum_segment_size = segment.max_seg_size
.unwrap_or(536)
.max(536);
self.receiver_maximum_segment_size = self.sender_maximum_segment_size;
if let Some(ack) = segment.ack_number {
self.send.unacked = ack;
}
if self.send.unacked == self.send.initial_seq {
self.change_state(State::SynReceived);
let mut signals = Signals::default();
signals.answer = Some(self.send_open(true, entry.four_tuple()));
return signals;
}
self.change_state(State::Established);
self.ack_timer = Expiration::When(*time);
return Signals::default();
}
fn arrives_established(&mut self, incoming: &InPacket, entry: EntryKey) -> Signals {
let InPacket { segment, from: _, time, } = incoming;
let acceptable = self.ingress_acceptable(segment);
if !acceptable {
if segment.flags.rst() {
return self.remote_reset_connection();
}
return self.signal_ack_all(entry.four_tuple());
}
if segment.flags.syn() {
debug_assert!(self.recv.in_window(segment.seq_number));
return self.signal_reset_connection(segment, entry);
}
let ack = match segment.ack_number {
None => return Signals::default(),
Some(ack) => ack,
};
match self.send.incoming_ack(ack) {
AckUpdate::Unsent => {
return self.signal_ack_all(entry.four_tuple());
},
AckUpdate::Duplicate => {
self.duplicate_ack = self.duplicate_ack.saturating_add(1);
},
AckUpdate::TooLow => (),
AckUpdate::Updated { new_bytes } => {
if self.duplicate_ack > 0 {
self.flow_control.congestion_window = self.flow_control.ssthresh;
self.duplicate_ack = 0;
}
self.send.window = segment.window_len;
self.window_update(segment, new_bytes);
},
}
let segment_ack = ReceivedSegment {
syn: segment.flags.syn(),
fin: segment.flags.fin(),
data_len: usize::from(segment.payload_len),
begin: segment.seq_number,
timestamp: *time,
};
if segment_ack.data_len == 0 {
self.set_recv_ack(segment_ack);
return Signals::default();
}
let mut signals = Signals::default();
signals.receive = Some(segment_ack);
signals
}
fn ingress_acceptable(&self, repr: &tcp::Repr) -> bool {
match (repr.payload_len, self.recv.window) {
(0, 0) => repr.seq_number == self.recv.next,
(0, _) => self.recv.in_window(repr.seq_number),
(_, 0) => false,
(_, _) => self.recv.in_window(repr.seq_number)
|| self.recv.in_window(repr.seq_number + repr.payload_len.into() - 1),
}
}
fn remote_reset_connection(&mut self) -> Signals {
self.change_state(State::Closed);
let mut signals = Signals::default();
signals.reset = true;
signals.delete = true;
return signals;
}
fn signal_reset_connection(&mut self, _segment: &tcp::Repr, entry: EntryKey) -> Signals {
self.change_state(State::Closed);
let mut signals = Signals::default();
signals.reset = true;
signals.delete = true;
signals.answer = Some(InnerRepr {
flags: tcp::Flags::RST,
seq_number: self.send.next,
ack_number: Some(self.ack_all()),
window_len: 0,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_to(entry.four_tuple()));
signals
}
fn signal_ack_all(&mut self, remote: FourTuple) -> Signals {
let mut signals = Signals::default();
signals.answer = Some(self.repr_ack_all(remote));
return signals;
}
fn segment_ack_all(&mut self, remote: FourTuple) -> Segment {
Segment {
repr: self.repr_ack_all(remote),
range: 0..0,
}
}
fn repr_ack_all(&mut self, remote: FourTuple) -> tcp::Repr {
InnerRepr {
flags: tcp::Flags::default(),
seq_number: self.send.next,
ack_number: Some(self.ack_all()),
window_len: self.recv.window,
window_scale: None,
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_to(remote)
}
fn send_open(&mut self, ack: bool, to: FourTuple) -> tcp::Repr {
let ack_number = if ack { Some(self.ack_all()) } else { None };
InnerRepr {
flags: tcp::Flags::SYN,
seq_number: self.send.initial_seq,
ack_number,
window_len: 0,
window_scale: Some(self.send.window_scale),
max_seg_size: None,
sack_permitted: false,
sack_ranges: [None; 3],
payload_len: 0,
}.send_to(to)
}
pub fn next_send_segment(&mut self, mut available: AvailableBytes, time: Instant, entry: EntryKey)
-> OutSignals
{
match self.current {
State::Established | State::CloseWait => {
self.select_send_segment(available, time, entry)
.map(OutSignals::segment)
.unwrap_or_else(OutSignals::none)
},
State::FinWait | State::Closing | State::LastAck => {
available.total = available.total.min(self.send.next - self.send.unacked);
self.select_send_segment(available, time, entry)
.map(OutSignals::segment)
.unwrap_or_else(OutSignals::none)
},
State::Closed => {
self.ensure_closed_ack(entry.four_tuple())
.map(OutSignals::segment)
.unwrap_or_else(OutSignals::none)
},
State::TimeWait => self.ensure_time_wait(time, entry),
State::SynSent | State::SynReceived => {
self.select_syn_retransmit(time, entry)
.map(OutSignals::segment)
.unwrap_or_else(OutSignals::none)
},
State::Listen => OutSignals::none(),
}
}
fn select_send_segment(&mut self, available: AvailableBytes, time: Instant, entry: EntryKey)
-> Option<Segment>
{
let byte_window = u32::try_from(available.total)
.ok().unwrap_or_else(u32::max_value);
let last_time = self.recv.last_time.max(self.send.last_time);
if time > last_time + self.restart_timeout {
self.flow_control.congestion_window = self.restart_window();
}
if self.duplicate_ack >= 2 {
return self.fast_retransmit(available, time, entry);
}
if self.retransmission_timer < time {
return self.timeout_retransmit(available, time, entry);
}
let window = self.send.window();
let sent = self.send.in_flight();
let max_sent = window.min(byte_window);
if sent < max_sent {
let end = sent.saturating_add(self.sender_maximum_segment_size.into()).min(max_sent);
let sent = usize::try_from(sent).unwrap();
let end = usize::try_from(end).unwrap();
let range = sent..end;
assert!(range.len() > 0);
let is_fin = available.fin && end as usize == available.total;
if is_fin {
match self.current {
State::Established => self.change_state(State::FinWait),
State::CloseWait => self.change_state(State::LastAck),
_ => (),
}
}
let mut repr = self.repr_ack_all(entry.four_tuple());
repr.payload_len = range.len() as u16;
if is_fin {
repr.flags = tcp::Flags::FIN;
}
self.send.next = self.send.next + range.len() + usize::from(is_fin);
return Some(Segment {
repr,
range,
});
}
if self.should_ack() || Expiration::When(time) >= self.ack_timer {
self.rearm_ack_timer(time);
return Some(self.segment_ack_all(entry.four_tuple()));
}
None
}
fn select_syn_retransmit(&mut self, time: Instant, entry: EntryKey)
-> Option<Segment>
{
if self.retransmission_timer > time {
return None;
}
let ack = match self.current {
State::SynReceived => true,
State::SynSent => false,
_ => unreachable!(),
};
self.rearm_retransmission_timer(time);
Some(Segment {
repr: self.send_open(ack, entry.four_tuple()),
range: 0..0,
})
}
fn fast_retransmit(&mut self, available: AvailableBytes, _: Instant, entry: EntryKey)
-> Option<Segment>
{
self.segment_retransmit(available, entry.four_tuple())
}
fn timeout_retransmit(&mut self, available: AvailableBytes, time: Instant, entry: EntryKey)
-> Option<Segment>
{
self.rearm_retransmission_timer(time);
self.segment_retransmit(available, entry.four_tuple())
}
fn segment_retransmit(&mut self, available: AvailableBytes, tuple: FourTuple) -> Option<Segment> {
let in_flight = self.send.in_flight();
let byte_window = u32::try_from(available.total)
.ok().unwrap_or_else(u32::max_value);
if in_flight == 0 {
return None;
}
let to_send = self.send.window()
.min(u32::from(self.sender_maximum_segment_size))
.min(byte_window);
if to_send == 0 {
return None;
}
let range = 0..usize::try_from(to_send).unwrap();
let is_fin = available.fin && range.end == available.total;
let mut repr = self.repr_ack_all(tuple);
repr.flags.set_fin(is_fin);
repr.seq_number = self.send.unacked;
repr.payload_len = to_send as u16;
Some(Segment {
repr,
range,
})
}
fn ensure_closed_ack(&mut self, tuple: FourTuple) -> Option<Segment> {
if self.recv.acked == self.recv.next {
return None;
}
Some(self.segment_ack_all(tuple))
}
fn ensure_time_wait(&mut self, time: Instant, entry: EntryKey) -> OutSignals {
match self.ensure_closed_ack(entry.four_tuple()) {
Some(segment) => OutSignals {
segment: Some(segment),
delete: false,
},
None => OutSignals {
delete: time >= self.retransmission_timer,
segment: None,
},
}
}
fn window_update(&mut self, _segment: &tcp::Repr, new_bytes: u32) {
let flow = &mut self.flow_control;
if self.duplicate_ack > 0 {
flow.congestion_window = flow.ssthresh;
} else if flow.congestion_window <= flow.ssthresh {
flow.congestion_window = flow.congestion_window.saturating_mul(2);
} else {
let update = u32::from(self.sender_maximum_segment_size).min(new_bytes);
flow.congestion_window = flow.congestion_window.saturating_add(update);
}
}
pub fn set_recv_ack(&mut self, meta: ReceivedSegment) {
let end = meta.sequence_end();
let acked_all = self.send.next == self.send.unacked;
match (self.current, meta.fin, acked_all) {
(State::Established, true, _) | (State::SynReceived, true, _) => {
self.change_state(State::CloseWait);
},
(State::FinWait, true, true) | (State::Closing, _, true) => {
self.change_state(State::TimeWait);
self.retransmission_timer = meta.timestamp + 2*self.retransmission_timeout;
},
(State::FinWait, true, false) => {
self.change_state(State::Closing);
},
_ => (),
}
self.recv.next = end;
let new_timer = Expiration::When(meta.timestamp + self.ack_timeout);
self.ack_timer = self.ack_timer.min(new_timer);
}
pub fn get_send_ack(&self) -> tcp::SeqNumber {
match self.current {
State::SynSent => self.send.unacked + 1,
State::FinWait | State::Closing | State::TimeWait | State::LastAck
if self.send.unacked == self.send.next
=> self.send.unacked - 1,
_ => self.send.unacked,
}
}
fn ack_all(&mut self) -> tcp::SeqNumber {
self.recv.acked = self.recv.next;
self.ack_timer = Expiration::Never;
self.recv.next
}
fn should_ack(&self) -> bool {
self.recv.acked < self.recv.next
}
fn rearm_ack_timer(&mut self, time: Instant) {
self.ack_timer = match self.ack_timer {
Expiration::When(_) => Expiration::When(time + self.ack_timeout),
Expiration::Never => Expiration::Never,
}
}
fn rearm_retransmission_timer(&mut self, time: Instant) {
self.retransmission_timer = time + self.retransmission_timeout;
}
pub(crate) fn change_state(&mut self, new: State) {
self.previous = self.current;
self.current = new;
}
fn restart_window(&self) -> u32 {
self.flow_control.congestion_window.min(self.send.window.into())
}
}
impl Receive {
fn in_window(&self, seq: tcp::SeqNumber) -> bool {
self.next.contains_in_window(seq, self.window.into())
}
pub fn update_window(&mut self, window: usize) {
let max = u32::from(u16::max_value()) << self.window_scale;
let capped = u32::try_from(window)
.unwrap_or_else(|_| u32::max_value())
.min(max);
let scaled_down = (capped >> self.window_scale)
+ u32::from(capped % (1 << self.window_scale) != 0);
self.window = u16::try_from(scaled_down).unwrap();
}
}
impl Send {
fn incoming_ack(&mut self, seq: tcp::SeqNumber) -> AckUpdate {
if seq < self.unacked {
AckUpdate::TooLow
} else if seq == self.unacked {
AckUpdate::Duplicate
} else if seq <= self.next {
let new_bytes = (seq - self.unacked) as u32;
self.unacked = seq;
AckUpdate::Updated { new_bytes }
} else {
AckUpdate::Unsent
}
}
fn window(&self) -> u32 {
u32::from(self.window) << self.window_scale
}
fn in_flight(&self) -> u32 {
assert!(self.unacked <= self.next);
(self.next - self.unacked) as u32
}
}
impl ReceivedSegment {
pub fn sequence_len(&self) -> usize {
self.data_len
+ usize::from(self.syn)
+ usize::from(self.fin)
}
pub fn acked_until(&self, ack: tcp::SeqNumber) -> Self {
ReceivedSegment {
syn: self.syn,
fin: self.fin && ack + 1 >= self.sequence_end(),
begin: self.begin,
data_len: self.data_len,
timestamp: self.timestamp,
}
}
pub fn data_begin(&self) -> tcp::SeqNumber {
self.begin + usize::from(self.syn)
}
pub fn data_end(&self) -> tcp::SeqNumber {
self.begin + usize::from(self.syn) + self.data_len
}
pub fn contains_in_window(&self, seq: tcp::SeqNumber) -> bool {
self.begin.contains_in_window(seq, self.sequence_len())
}
pub fn sequence_end(&self) -> tcp::SeqNumber {
self.begin + self.sequence_len()
}
}
impl OutSignals {
pub fn none() -> Self {
OutSignals::default()
}
pub fn segment(segment: Segment) -> Self {
OutSignals {
segment: Some(segment),
delete: false,
}
}
}
impl Operator<'_> {
pub(crate) fn key(&self) -> SlotKey {
self.connection_key
}
pub(crate) fn four_tuple(&self) -> FourTuple {
self.slot().four_tuple()
}
pub(crate) fn connection(&self) -> &Connection {
self.slot().connection()
}
pub(crate) fn connection_mut(&mut self) -> &mut Connection {
self.entry().into_key_value().1
}
}
impl<'a> Operator<'a> {
pub(crate) fn new(endpoint: &'a mut dyn Endpoint, key: SlotKey) -> Option<Self> {
let _ = endpoint.get(key)?;
Some(Operator {
endpoint,
connection_key: key,
})
}
pub(crate) fn from_tuple(endpoint: &'a mut dyn Endpoint, tuple: FourTuple) -> Result<Self, &'a mut dyn Endpoint> {
let key = match endpoint.find_tuple(tuple) {
Some(entry) => Some(entry.slot_key()),
None => None,
};
match key {
Some(key) => Ok(Operator {
endpoint,
connection_key: key,
}),
None => Err(endpoint),
}
}
pub(crate) fn arrives(&mut self, incoming: &InPacket) -> Signals {
let (entry_key, connection) = self.entry().into_key_value();
connection.arrives(incoming, entry_key)
}
pub(crate) fn next_send_segment(&mut self, available: AvailableBytes, time: Instant)
-> OutSignals
{
let (entry_key, connection) = self.entry().into_key_value();
connection.next_send_segment(available, time, entry_key)
}
pub(crate) fn open(&mut self, time: Instant) -> Result<(), crate::layer::Error> {
let (entry_key, connection) = self.entry().into_key_value();
connection.open(time, entry_key)
}
pub(crate) fn delete(self) -> &'a mut dyn Endpoint {
self.endpoint.remove(self.connection_key);
self.endpoint
}
fn entry(&mut self) -> Entry {
self.endpoint.entry(self.connection_key).unwrap()
}
fn slot(&self) -> &Slot {
self.endpoint.get(self.connection_key).unwrap()
}
}
impl Default for State {
fn default() -> Self {
State::Closed
}
}
impl InnerRepr {
pub(crate) fn send_back(&self, incoming: &tcp::Repr) -> tcp::Repr {
self.send_impl(incoming.dst_port, incoming.src_port)
}
pub(crate) fn send_to(&self, tuple: FourTuple) -> tcp::Repr {
self.send_impl(tuple.local_port, tuple.remote_port)
}
fn send_impl(&self, src: u16, dst: u16) -> tcp::Repr {
tcp::Repr {
src_port: src,
dst_port: dst,
seq_number: self.seq_number,
flags: self.flags,
ack_number: self.ack_number,
window_len: self.window_len,
window_scale: self.window_scale,
max_seg_size: self.max_seg_size,
sack_permitted: self.sack_permitted,
sack_ranges: self.sack_ranges,
payload_len: self.payload_len,
}
}
}
#[cfg(test)]
mod tests {
use crate::layer::tcp::endpoint::{EntryKey, FourTuple, PortMap};
use crate::layer::tcp::IsnGenerator;
use crate::time::Instant;
use crate::wire::ip::Address;
use super::{AvailableBytes, Connection};
struct NoRemap;
impl PortMap for NoRemap {
fn remap(&mut self, _: FourTuple, _: FourTuple) {
panic!("Should not get remapped");
}
}
fn simple_connection() -> Connection {
Connection::zeroed()
}
#[test]
fn resent_syn() {
let mut connection = simple_connection();
let isn = IsnGenerator::from_key(0, 0);
let mut no_remap = NoRemap;
let mut four = FourTuple {
local: Address::v4(192, 0, 10, 1),
remote: Address::v4(192, 0, 10, 2),
local_port: 80,
remote_port: 80,
};
let time_start = Instant::from_secs(0);
let time_resend = Instant::from_secs(3);
let entry = EntryKey::fake(&mut no_remap, &isn, &mut four);
assert!(connection.open(time_start, entry).is_ok());
let entry = EntryKey::fake(&mut no_remap, &isn, &mut four);
let available = AvailableBytes { fin: false, total: 0 };
let _resent = connection.next_send_segment(available, time_resend, entry);
}
}