use std::net::SocketAddr;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use crate::rand;
use super::congestion::{CongestionController, HighSpeed, NewReno};
use super::options::{
self, get_mss, get_sack_blocks, get_timestamp, get_wscale, has_sack_perm, mss_option,
sack_option, sack_perm_option, timestamp_option, wscale_option, TcpOption,
};
use super::recvbuf::RecvBuf;
use super::rto::{RtoState, MAX_RTO};
use super::segment::{flags, Segment};
use super::sendbuf::SendBuf;
use super::seqspace::{seq_after, seq_after_eq, seq_before_eq, seq_in_range};
pub const DEFAULT_MSS: u16 = 1460;
pub const DEFAULT_WINDOW_SIZE: u16 = 65535;
pub const DEFAULT_SEND_BUF: usize = 1 << 20;
pub const DEFAULT_RECV_BUF: usize = 1 << 20;
pub const MAX_RETRIES: u32 = 8;
pub const TIME_WAIT_DURATION: Duration = Duration::from_secs(2);
pub const DEFAULT_KEEPALIVE_IDLE: Duration = Duration::from_secs(300);
pub const DEFAULT_KEEPALIVE_INTERVAL: Duration = Duration::from_secs(15);
pub const DEFAULT_KEEPALIVE_COUNT: u32 = 3;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum State {
Closed,
Listen,
SynSent,
SynReceived,
Established,
FinWait1,
FinWait2,
CloseWait,
Closing,
LastAck,
TimeWait,
}
impl State {
pub fn is_synchronized(self) -> bool {
matches!(
self,
State::Established
| State::FinWait1
| State::FinWait2
| State::CloseWait
| State::Closing
| State::LastAck
| State::TimeWait
)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub enum CongestionKind {
NewReno,
#[default]
HighSpeed,
}
fn make_cc(kind: CongestionKind, mss: u32) -> Box<dyn CongestionController> {
match kind {
CongestionKind::NewReno => Box::new(NewReno::new(mss)),
CongestionKind::HighSpeed => Box::new(HighSpeed::new(mss)),
}
}
#[derive(Debug, Clone)]
pub struct ConnConfig {
pub local_addr: std::option::Option<SocketAddr>,
pub remote_addr: std::option::Option<SocketAddr>,
pub local_port: u16,
pub remote_port: u16,
pub mss: u16,
pub no_window_scaling: bool,
pub enable_timestamps: bool,
pub enable_sack: bool,
pub congestion: CongestionKind,
pub keepalive: bool,
pub keepalive_idle: Duration,
pub keepalive_interval: Duration,
pub keepalive_count: u32,
pub send_buf_size: usize,
pub recv_buf_size: usize,
}
impl Default for ConnConfig {
fn default() -> Self {
Self {
local_addr: None,
remote_addr: None,
local_port: 0,
remote_port: 0,
mss: DEFAULT_MSS,
no_window_scaling: false,
enable_timestamps: false,
enable_sack: false,
congestion: CongestionKind::default(),
keepalive: false,
keepalive_idle: DEFAULT_KEEPALIVE_IDLE,
keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL,
keepalive_count: DEFAULT_KEEPALIVE_COUNT,
send_buf_size: DEFAULT_SEND_BUF,
recv_buf_size: DEFAULT_RECV_BUF,
}
}
}
pub struct Conn {
cfg: ConnConfig,
state: State,
closed: bool,
send_buf: std::option::Option<SendBuf>,
recv_buf: std::option::Option<RecvBuf>,
snd_wnd: u32, mss: u16,
cc: Box<dyn CongestionController>,
rto: RtoState,
rto_deadline: std::option::Option<Instant>,
retries: u32,
snd_wnd_shift: u8,
rcv_wnd_shift: u8,
wscale_ok: bool,
ts_enabled: bool,
ts_ok: bool,
ts_recent: u32,
ts_offset_ms: u64,
sack_enabled: bool,
sack_ok: bool,
fin_pending: bool,
pending_fin_seq: u32,
persist_deadline: std::option::Option<Instant>,
persist_backoff: Duration,
time_wait_deadline: std::option::Option<Instant>,
keepalive_deadline: std::option::Option<Instant>,
keepalive_sent: u32,
last_recv: Instant,
established_signaled: bool,
fin_recvd_signaled: bool,
outgoing: Vec<Vec<u8>>,
}
impl std::fmt::Debug for Conn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Conn")
.field("state", &self.state)
.field("local_port", &self.cfg.local_port)
.field("remote_port", &self.cfg.remote_port)
.field("snd_una", &self.send_buf.as_ref().map(|s| s.una()))
.field("snd_nxt", &self.send_buf.as_ref().map(|s| s.nxt()))
.field("rcv_nxt", &self.recv_buf.as_ref().map(|r| r.nxt()))
.finish()
}
}
impl Conn {
pub fn new(cfg: ConnConfig) -> Self {
let mut rcv_shift = 0u8;
if !cfg.no_window_scaling {
for s in 0u8..=14 {
rcv_shift = s;
if cfg.recv_buf_size >> s <= 65535 {
break;
}
}
}
let mss = cfg.mss.max(1);
let cc = make_cc(cfg.congestion, mss as u32);
let ts_offset_ms = wallclock_ms();
Self {
cfg: cfg.clone(),
state: State::Closed,
closed: false,
send_buf: None,
recv_buf: None,
snd_wnd: DEFAULT_WINDOW_SIZE as u32,
mss,
cc,
rto: RtoState::new(),
rto_deadline: None,
retries: 0,
snd_wnd_shift: 0,
rcv_wnd_shift: rcv_shift,
wscale_ok: false,
ts_enabled: cfg.enable_timestamps,
ts_ok: false,
ts_recent: 0,
ts_offset_ms,
sack_enabled: cfg.enable_sack,
sack_ok: false,
fin_pending: false,
pending_fin_seq: 0,
persist_deadline: None,
persist_backoff: Duration::ZERO,
time_wait_deadline: None,
keepalive_deadline: None,
keepalive_sent: 0,
last_recv: Instant::now(),
established_signaled: false,
fin_recvd_signaled: false,
outgoing: Vec::new(),
}
}
#[inline]
pub fn state(&self) -> State {
self.state
}
#[inline]
pub fn is_closed(&self) -> bool {
self.closed
}
#[inline]
pub fn is_established(&self) -> bool {
self.established_signaled
}
#[inline]
pub fn fin_received(&self) -> bool {
self.fin_recvd_signaled
}
#[inline]
pub fn local_addr(&self) -> std::option::Option<SocketAddr> {
self.cfg.local_addr
}
#[inline]
pub fn remote_addr(&self) -> std::option::Option<SocketAddr> {
self.cfg.remote_addr
}
pub fn take_outgoing(&mut self) -> Vec<Vec<u8>> {
std::mem::take(&mut self.outgoing)
}
pub fn connect(&mut self) -> Vec<Vec<u8>> {
if self.state != State::Closed {
return Vec::new();
}
let iss = rand::u32();
self.send_buf = Some(SendBuf::new(self.cfg.send_buf_size, iss));
self.recv_buf = Some(RecvBuf::new(0, self.cfg.recv_buf_size));
self.state = State::SynSent;
let opts = self.build_syn_options();
let win = self.rcv_window();
let syn = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: iss,
ack: 0,
flags: flags::SYN,
window: win,
options: opts,
..Default::default()
};
self.queue_seg(syn);
self.send_buf.as_mut().unwrap().advance_sent(1); self.rto.start_timing(iss);
self.start_rto();
self.take_outgoing()
}
pub fn accept_syn(&mut self, syn: &Segment) -> Vec<Vec<u8>> {
if self.state != State::Closed && self.state != State::Listen {
return Vec::new();
}
let m = get_mss(&syn.options);
if m > 0 && m < self.mss {
self.mss = m;
}
self.negotiate_options(&syn.options);
let iss = rand::u32();
self.send_buf = Some(SendBuf::new(self.cfg.send_buf_size, iss));
self.recv_buf = Some(RecvBuf::new(
syn.seq.wrapping_add(1),
self.cfg.recv_buf_size,
));
self.state = State::SynReceived;
let opts = self.build_syn_options();
let win = self.rcv_window();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let synack = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: iss,
ack: rcv_nxt,
flags: flags::SYN | flags::ACK,
window: win,
options: opts,
..Default::default()
};
self.queue_seg(synack);
self.send_buf.as_mut().unwrap().advance_sent(1);
if !syn.payload.is_empty() {
self.recv_buf
.as_mut()
.unwrap()
.insert(syn.seq.wrapping_add(1), &syn.payload);
}
self.start_rto();
self.take_outgoing()
}
pub fn accept_cookie(
&mut self,
remote_seq: u32,
our_iss: u32,
mss: u16,
initial_data: &[u8],
) -> Vec<Vec<u8>> {
if self.state != State::Closed && self.state != State::Listen {
return Vec::new();
}
if mss < self.mss {
self.mss = mss;
}
self.send_buf = Some(SendBuf::new(
self.cfg.send_buf_size,
our_iss.wrapping_add(1),
));
self.recv_buf = Some(RecvBuf::new(remote_seq, self.cfg.recv_buf_size));
self.state = State::Established;
self.signal_established();
if self.cfg.keepalive {
self.start_keepalive();
}
if !initial_data.is_empty() {
self.recv_buf
.as_mut()
.unwrap()
.insert(remote_seq, initial_data);
}
self.queue_ack();
self.take_outgoing()
}
fn build_syn_options(&self) -> Vec<TcpOption> {
let mut opts = Vec::with_capacity(4);
opts.push(mss_option(self.mss));
opts.push(wscale_option(self.rcv_wnd_shift));
if self.sack_enabled {
opts.push(sack_perm_option());
}
if self.ts_enabled {
opts.push(timestamp_option(self.ts_now(), 0));
}
opts
}
fn negotiate_options(&mut self, remote_opts: &[TcpOption]) {
if let Some(ws) = get_wscale(remote_opts) {
self.snd_wnd_shift = ws.min(14);
self.wscale_ok = true;
}
if self.sack_enabled && has_sack_perm(remote_opts) {
self.sack_ok = true;
}
if self.ts_enabled {
if let Some((ts_val, _)) = get_timestamp(remote_opts) {
self.ts_recent = ts_val;
self.ts_ok = true;
}
}
}
fn add_options(&self, seg: &mut Segment) {
if self.ts_ok {
seg.options
.push(timestamp_option(self.ts_now(), self.ts_recent));
}
if self.sack_ok {
if let Some(rb) = self.recv_buf.as_ref() {
if rb.has_ooo() {
let blocks = rb.sack_blocks();
if !blocks.is_empty() {
seg.options.push(sack_option(&blocks));
}
}
}
}
}
fn ts_now(&self) -> u32 {
wallclock_ms().wrapping_sub(self.ts_offset_ms) as u32
}
fn update_timestamp(&mut self, opts: &[TcpOption]) -> bool {
if !self.ts_ok {
return true;
}
let Some((ts_val, _)) = get_timestamp(opts) else {
return true;
};
if self.ts_recent != 0 && (ts_val.wrapping_sub(self.ts_recent) as i32) < 0 {
return false;
}
self.ts_recent = ts_val;
true
}
fn rcv_window(&self) -> u16 {
let avail = self
.recv_buf
.as_ref()
.map(|r| r.window() as usize)
.unwrap_or(self.cfg.recv_buf_size);
let half = self.cfg.recv_buf_size / 2;
let sws_thresh = (self.mss as usize).min(half.max(1));
let mut w = if avail < sws_thresh { 0 } else { avail };
if self.wscale_ok {
w >>= self.rcv_wnd_shift;
}
if w > 65535 {
w = 65535;
}
w as u16
}
fn queue_seg(&mut self, seg: Segment) {
self.outgoing.push(seg.marshal());
}
fn queue_ack(&mut self) {
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
let rcv_nxt = self.recv_buf.as_ref().map(|r| r.nxt()).unwrap_or(0);
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::ACK,
window: self.rcv_window(),
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
}
fn queue_fin(&mut self) {
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
let rcv_nxt = self.recv_buf.as_ref().map(|r| r.nxt()).unwrap_or(0);
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::FIN | flags::ACK,
window: self.rcv_window(),
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
if let Some(s) = self.send_buf.as_mut() {
s.advance_sent(1); }
}
pub fn handle_segment(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
self.last_recv = Instant::now();
self.keepalive_sent = 0;
match self.state {
State::Closed => self.handle_closed(seg),
State::Listen => Vec::new(), State::SynSent => self.handle_syn_sent(seg),
State::SynReceived
| State::Established
| State::FinWait1
| State::FinWait2
| State::CloseWait
| State::Closing
| State::LastAck
| State::TimeWait => self.handle_synchronized(seg),
}
}
fn handle_closed(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
if seg.has_flag(flags::RST) {
return Vec::new();
}
let rst = if seg.has_flag(flags::ACK) {
Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: seg.ack,
flags: flags::RST,
..Default::default()
}
} else {
Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: 0,
ack: seg.seq.wrapping_add(seg.seg_len()),
flags: flags::RST | flags::ACK,
..Default::default()
}
};
self.queue_seg(rst);
self.take_outgoing()
}
fn segment_acceptable(&self, seg: &Segment) -> bool {
let Some(rb) = self.recv_buf.as_ref() else {
return true;
};
let rcv_nxt = rb.nxt();
let mut rcv_wnd = self.cfg.recv_buf_size as u32;
if rcv_wnd == 0 {
rcv_wnd = DEFAULT_RECV_BUF as u32;
}
let seg_len = seg.seg_len();
if seg_len == 0 {
if rcv_wnd == 0 {
return seg.seq == rcv_nxt;
}
return seq_in_range(seg.seq, rcv_nxt, rcv_nxt.wrapping_add(rcv_wnd));
}
if rcv_wnd == 0 {
return false;
}
let seg_end = seg.seq.wrapping_add(seg_len.wrapping_sub(1));
seq_in_range(seg.seq, rcv_nxt, rcv_nxt.wrapping_add(rcv_wnd))
|| seq_in_range(seg_end, rcv_nxt, rcv_nxt.wrapping_add(rcv_wnd))
}
fn validate_rst(&self, seg: &Segment) -> (bool, bool) {
match self.state {
State::SynSent => {
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
if seg.has_flag(flags::ACK) && seg.ack == snd_nxt {
(true, false)
} else {
(false, false)
}
}
_ => {
let Some(rb) = self.recv_buf.as_ref() else {
return (true, false);
};
let rcv_nxt = rb.nxt();
if seg.seq == rcv_nxt {
return (true, false);
}
let rcv_wnd = rb.window();
if seq_in_range(seg.seq, rcv_nxt, rcv_nxt.wrapping_add(rcv_wnd)) {
(false, true)
} else {
(false, false)
}
}
}
}
fn handle_synchronized(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
if !self.segment_acceptable(seg) {
let syn_rcvd_simopen = self.state == State::SynReceived
&& seg.has_flag(flags::SYN)
&& seg.has_flag(flags::ACK)
&& self
.send_buf
.as_ref()
.map(|s| s.nxt() == seg.ack)
.unwrap_or(false);
if !syn_rcvd_simopen {
if !seg.has_flag(flags::RST) {
self.queue_ack();
}
return self.take_outgoing();
}
}
if seg.has_flag(flags::RST) {
let (accept, challenge) = self.validate_rst(seg);
if challenge {
self.queue_ack();
return self.take_outgoing();
}
if !accept {
return self.take_outgoing();
}
self.tear_down(State::Closed);
return self.take_outgoing();
}
if seg.has_flag(flags::SYN) && self.state != State::SynReceived {
self.queue_ack();
return self.take_outgoing();
}
if !seg.has_flag(flags::ACK) {
return self.take_outgoing();
}
match self.state {
State::SynReceived => self.handle_syn_received(seg),
State::Established => self.handle_data_state(seg),
State::FinWait1 => self.handle_data_state(seg),
State::FinWait2 => self.handle_data_state(seg),
State::CloseWait => self.handle_close_wait(seg),
State::Closing => self.handle_closing(seg),
State::LastAck => self.handle_last_ack(seg),
State::TimeWait => {
self.restart_time_wait();
self.queue_ack();
self.take_outgoing()
}
_ => self.take_outgoing(),
}
}
fn handle_syn_sent(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
if seg.has_flag(flags::ACK) {
let una = self.send_buf.as_ref().unwrap().una();
let nxt = self.send_buf.as_ref().unwrap().nxt();
if seq_before_eq(seg.ack, una) || seq_after(seg.ack, nxt) {
if !seg.has_flag(flags::RST) {
let rst = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: seg.ack,
flags: flags::RST,
..Default::default()
};
self.queue_seg(rst);
}
return self.take_outgoing();
}
}
if seg.has_flag(flags::RST) {
if seg.has_flag(flags::ACK) {
self.tear_down(State::Closed);
}
return self.take_outgoing();
}
if !seg.has_flag(flags::SYN) {
return self.take_outgoing();
}
let m = get_mss(&seg.options);
if m > 0 && m < self.mss {
self.mss = m;
}
self.negotiate_options(&seg.options);
if seg.has_flag(flags::ACK) {
self.send_buf.as_mut().unwrap().acknowledge(seg.ack);
self.retries = 0;
self.stop_rto();
self.recv_buf = Some(RecvBuf::new(
seg.seq.wrapping_add(1),
self.cfg.recv_buf_size,
));
self.snd_wnd = (seg.window as u32) << self.snd_wnd_shift;
self.cc = make_cc(self.cfg.congestion, self.mss as u32);
self.rto.ack_received(seg.ack);
self.state = State::Established;
if !seg.payload.is_empty() {
self.recv_buf
.as_mut()
.unwrap()
.insert(seg.seq.wrapping_add(1), &seg.payload);
}
self.queue_ack();
self.flush_send_queue();
if self.cfg.keepalive {
self.start_keepalive();
}
self.signal_established();
return self.take_outgoing();
}
self.recv_buf = Some(RecvBuf::new(
seg.seq.wrapping_add(1),
self.cfg.recv_buf_size,
));
self.snd_wnd = (seg.window as u32) << self.snd_wnd_shift;
self.state = State::SynReceived;
self.retries = 0;
self.stop_rto();
if !seg.payload.is_empty() {
self.recv_buf
.as_mut()
.unwrap()
.insert(seg.seq.wrapping_add(1), &seg.payload);
}
let opts = self.build_syn_options();
let win = self.rcv_window();
let una = self.send_buf.as_ref().unwrap().una();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let synack = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: una,
ack: rcv_nxt,
flags: flags::SYN | flags::ACK,
window: win,
options: opts,
..Default::default()
};
self.queue_seg(synack);
self.start_rto();
self.take_outgoing()
}
fn handle_syn_received(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
let snd_nxt = self.send_buf.as_ref().unwrap().nxt();
if seg.ack != snd_nxt {
let rst = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: seg.ack,
flags: flags::RST,
..Default::default()
};
self.queue_seg(rst);
return self.take_outgoing();
}
self.send_buf.as_mut().unwrap().acknowledge(seg.ack);
self.retries = 0;
self.stop_rto();
self.snd_wnd = (seg.window as u32) << self.snd_wnd_shift;
self.state = State::Established;
if self.cfg.keepalive {
self.start_keepalive();
}
self.signal_established();
self.handle_data_state(seg)
}
fn handle_data_state(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
let mut need_ack = false;
if !self.update_timestamp(&seg.options) {
self.queue_ack();
return self.take_outgoing();
}
if seg.has_flag(flags::ACK) {
self.process_ack(seg.ack, &seg.options);
self.snd_wnd = (seg.window as u32) << self.snd_wnd_shift;
}
if !seg.payload.is_empty() {
self.process_data(seg);
need_ack = true;
}
if seg.has_flag(flags::FIN) {
let fin_seq = seg.seq.wrapping_add(seg.data_len());
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
if fin_seq == rcv_nxt {
self.recv_buf.as_mut().unwrap().bump_nxt(1);
need_ack = true;
self.process_fin_transition();
} else {
self.fin_pending = true;
self.pending_fin_seq = fin_seq;
need_ack = true;
}
} else if self.state == State::FinWait1
&& seg.has_flag(flags::ACK)
&& self
.send_buf
.as_ref()
.map(|s| seg.ack == s.nxt())
.unwrap_or(false)
{
self.state = State::FinWait2;
}
if need_ack {
self.queue_ack();
}
self.take_outgoing()
}
fn process_fin_transition(&mut self) {
match self.state {
State::Established => {
self.state = State::CloseWait;
self.signal_fin_recvd();
}
State::FinWait1 => {
let unacked = self.send_buf.as_ref().map(|s| s.unacked()).unwrap_or(0);
if unacked == 0 {
self.state = State::TimeWait;
self.stop_rto();
self.start_time_wait();
} else {
self.state = State::Closing;
}
self.signal_fin_recvd();
}
State::FinWait2 => {
self.state = State::TimeWait;
self.stop_rto();
self.start_time_wait();
self.signal_fin_recvd();
}
_ => {}
}
}
fn handle_close_wait(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
if seg.has_flag(flags::ACK) {
self.process_ack(seg.ack, &seg.options);
self.snd_wnd = (seg.window as u32) << self.snd_wnd_shift;
}
self.take_outgoing()
}
fn handle_closing(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
if seg.has_flag(flags::ACK) && seg.ack == snd_nxt {
self.state = State::TimeWait;
self.stop_rto();
self.start_time_wait();
}
self.queue_ack();
self.take_outgoing()
}
fn handle_last_ack(&mut self, seg: &Segment) -> Vec<Vec<u8>> {
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
if seg.has_flag(flags::ACK) && seg.ack == snd_nxt {
self.tear_down(State::Closed);
}
self.take_outgoing()
}
fn process_data(&mut self, seg: &Segment) {
let n = self
.recv_buf
.as_mut()
.unwrap()
.insert(seg.seq, &seg.payload);
let mut fin_ready = false;
if self.fin_pending && self.pending_fin_seq == self.recv_buf.as_ref().unwrap().nxt() {
self.recv_buf.as_mut().unwrap().bump_nxt(1);
self.fin_pending = false;
fin_ready = true;
}
if n > 0 {
}
if fin_ready {
self.process_fin_transition();
}
}
fn process_ack(&mut self, ack: u32, opts: &[TcpOption]) {
let una = self.send_buf.as_ref().unwrap().una();
if !seq_after(ack, una) {
if self.cc.on_dup_ack() {
let flight = self.send_buf.as_ref().unwrap().unacked() as u32;
let snd_nxt = self.send_buf.as_ref().unwrap().nxt();
self.cc.on_fast_retransmit(flight, snd_nxt);
self.retransmit();
}
if self.sack_ok {
let blocks = get_sack_blocks(opts);
if !blocks.is_empty() {
self.send_buf.as_mut().unwrap().mark_sacked(&blocks);
}
}
return;
}
let snd_nxt = self.send_buf.as_ref().unwrap().nxt();
if seq_after(ack, snd_nxt) {
self.queue_ack();
return;
}
let acked = self.send_buf.as_mut().unwrap().acknowledge(ack);
self.retries = 0;
self.cc.on_ack(acked);
if self.sack_ok {
let blocks = get_sack_blocks(opts);
if !blocks.is_empty() {
self.send_buf.as_mut().unwrap().mark_sacked(&blocks);
}
}
if self.snd_wnd > 0 && self.persist_deadline.is_some() {
self.stop_persist();
}
self.rto.ack_received(ack);
if self.cc.in_recovery() && seq_after_eq(ack, self.cc.recovery_seq()) {
self.cc.exit_recovery();
}
if self.send_buf.as_ref().unwrap().unacked() > 0 {
self.start_rto();
} else {
self.stop_rto();
}
self.flush_send_queue();
}
fn retransmit(&mut self) {
let data: Vec<u8> = {
let s = self.send_buf.as_ref().unwrap();
s.retransmit_data(self.mss as usize).to_vec()
};
if data.is_empty() {
return;
}
let una = self.send_buf.as_ref().unwrap().una();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: una,
ack: rcv_nxt,
flags: flags::ACK | flags::PSH,
window: self.rcv_window(),
payload: data,
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
self.rto.invalidate_timing();
self.start_rto();
}
fn flush_send_queue(&mut self) {
loop {
let pending = self.send_buf.as_ref().unwrap().pending();
if pending == 0 {
break;
}
let mut eff_wnd = self.snd_wnd;
let cc_wnd = self.cc.send_window();
if cc_wnd < eff_wnd {
eff_wnd = cc_wnd;
}
let unacked = self.send_buf.as_ref().unwrap().unacked() as u32;
if eff_wnd <= unacked {
break;
}
let avail = (eff_wnd - unacked) as usize;
let n = avail.min(self.mss as usize).min(pending);
if n < self.mss as usize && self.send_buf.as_ref().unwrap().unacked() > 0 {
break;
}
let data: Vec<u8> = {
let s = self.send_buf.as_ref().unwrap();
let d = s.peek_unsent(n);
if d.is_empty() {
break;
}
d.to_vec()
};
let snd_nxt = self.send_buf.as_ref().unwrap().nxt();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::ACK | flags::PSH,
window: self.rcv_window(),
payload: data.clone(),
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
self.send_buf.as_mut().unwrap().advance_sent(data.len());
self.rto.start_timing(snd_nxt);
if self.send_buf.as_ref().unwrap().unacked() > 0 && self.rto_deadline.is_none() {
self.start_rto();
}
}
if self
.send_buf
.as_ref()
.map(|s| s.pending() > 0)
.unwrap_or(false)
&& self.snd_wnd == 0
&& self.persist_deadline.is_none()
{
self.start_persist();
}
}
fn start_rto(&mut self) {
self.rto_deadline = Some(Instant::now() + self.rto.rto());
}
fn stop_rto(&mut self) {
self.rto_deadline = None;
}
fn start_persist(&mut self) {
if self.persist_backoff == Duration::ZERO {
self.persist_backoff = self.rto.rto();
}
self.persist_deadline = Some(Instant::now() + self.persist_backoff);
}
fn stop_persist(&mut self) {
self.persist_deadline = None;
self.persist_backoff = Duration::ZERO;
}
fn start_time_wait(&mut self) {
self.stop_keepalive();
self.stop_persist();
self.time_wait_deadline = Some(Instant::now() + TIME_WAIT_DURATION);
}
fn restart_time_wait(&mut self) {
if self.time_wait_deadline.is_some() {
self.time_wait_deadline = Some(Instant::now() + TIME_WAIT_DURATION);
}
}
fn start_keepalive(&mut self) {
self.stop_keepalive();
self.stop_persist();
self.keepalive_deadline = Some(Instant::now() + self.cfg.keepalive_idle);
}
fn stop_keepalive(&mut self) {
self.keepalive_deadline = None;
}
pub fn tick(&mut self) -> Vec<Vec<u8>> {
let now = Instant::now();
if let Some(d) = self.rto_deadline {
if now >= d && !self.closed && self.state != State::Closed {
self.on_rto_timeout();
}
}
if let Some(d) = self.persist_deadline {
if now >= d && !self.closed && self.state != State::Closed {
self.on_persist_timeout();
}
}
if let Some(d) = self.time_wait_deadline {
if now >= d {
self.time_wait_deadline = None;
self.state = State::Closed;
self.closed = true;
}
}
if let Some(d) = self.keepalive_deadline {
if now >= d && !self.closed && self.state != State::Closed {
self.on_keepalive();
}
}
self.take_outgoing()
}
fn on_rto_timeout(&mut self) {
self.retries += 1;
if self.retries > MAX_RETRIES {
self.tear_down(State::Closed);
return;
}
self.rto.backoff();
self.rto.invalidate_timing();
self.cc.on_timeout();
match self.state {
State::SynSent => {
let opts = self.build_syn_options();
let win = self.rcv_window();
let una = self.send_buf.as_ref().unwrap().una();
let syn = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: una,
flags: flags::SYN,
window: win,
options: opts,
..Default::default()
};
self.queue_seg(syn);
}
State::SynReceived => {
let opts = self.build_syn_options();
let win = self.rcv_window();
let una = self.send_buf.as_ref().unwrap().una();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let synack = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: una,
ack: rcv_nxt,
flags: flags::SYN | flags::ACK,
window: win,
options: opts,
..Default::default()
};
self.queue_seg(synack);
}
State::Established | State::CloseWait => {
self.retransmit();
}
State::FinWait1 | State::LastAck => {
let snd_nxt = self.send_buf.as_ref().unwrap().una();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::FIN | flags::ACK,
window: self.rcv_window(),
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
}
_ => {}
}
self.start_rto();
}
fn on_persist_timeout(&mut self) {
if self.snd_wnd > 0 {
self.stop_persist();
self.flush_send_queue();
return;
}
if self
.send_buf
.as_ref()
.map(|s| s.pending() > 0)
.unwrap_or(false)
{
let data: Vec<u8> = self.send_buf.as_ref().unwrap().peek_unsent(1).to_vec();
if !data.is_empty() {
let snd_nxt = self.send_buf.as_ref().unwrap().nxt();
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::ACK,
window: self.rcv_window(),
payload: data.clone(),
..Default::default()
};
self.queue_seg(seg);
self.send_buf.as_mut().unwrap().advance_sent(data.len());
}
}
self.persist_backoff = self.persist_backoff.saturating_mul(2);
if self.persist_backoff > MAX_RTO {
self.persist_backoff = MAX_RTO;
}
self.persist_deadline = Some(Instant::now() + self.persist_backoff);
}
fn on_keepalive(&mut self) {
if self.state != State::Established && self.state != State::CloseWait {
return;
}
if self.last_recv.elapsed() > self.cfg.keepalive_idle {
if self.keepalive_sent >= self.cfg.keepalive_count {
self.tear_down(State::Closed);
return;
}
let snd_nxt = self.send_buf.as_ref().unwrap().nxt().wrapping_sub(1);
let rcv_nxt = self.recv_buf.as_ref().unwrap().nxt();
let mut seg = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
ack: rcv_nxt,
flags: flags::ACK,
window: self.rcv_window(),
..Default::default()
};
self.add_options(&mut seg);
self.queue_seg(seg);
self.keepalive_sent += 1;
}
if self.keepalive_sent > 0 {
self.keepalive_deadline = Some(Instant::now() + self.cfg.keepalive_interval);
} else {
self.start_keepalive();
}
}
pub fn read(&mut self, buf: &mut [u8]) -> usize {
let Some(rb) = self.recv_buf.as_mut() else {
return 0;
};
rb.read(buf)
}
pub fn write(&mut self, buf: &[u8]) -> (usize, Vec<Vec<u8>>) {
if self.closed {
return (0, Vec::new());
}
if self.state != State::Established && self.state != State::CloseWait {
return (0, Vec::new());
}
let n = self.send_buf.as_mut().unwrap().write(buf);
if n > 0 {
self.flush_send_queue();
}
(n, self.take_outgoing())
}
pub fn close(&mut self) -> Vec<Vec<u8>> {
if self.closed {
return Vec::new();
}
match self.state {
State::Established => {
self.flush_send_queue();
self.state = State::FinWait1;
self.queue_fin();
self.start_rto();
}
State::CloseWait => {
self.state = State::LastAck;
self.queue_fin();
self.start_rto();
}
State::SynSent => {
self.tear_down(State::Closed);
}
State::SynReceived => {
self.state = State::FinWait1;
self.queue_fin();
self.start_rto();
}
State::FinWait1 | State::FinWait2 => {
}
_ => {
self.tear_down(State::Closed);
}
}
self.take_outgoing()
}
pub fn abort(&mut self) -> Vec<Vec<u8>> {
if self.state == State::Closed {
return Vec::new();
}
let was_established = self.state != State::Closed && self.state != State::SynSent;
let snd_nxt = self.send_buf.as_ref().map(|s| s.nxt()).unwrap_or(0);
self.tear_down(State::Closed);
if was_established {
let rst = Segment {
src_port: self.cfg.local_port,
dst_port: self.cfg.remote_port,
seq: snd_nxt,
flags: flags::RST,
..Default::default()
};
self.queue_seg(rst);
}
self.take_outgoing()
}
fn tear_down(&mut self, new_state: State) {
self.state = new_state;
self.closed = new_state == State::Closed;
self.stop_rto();
self.stop_keepalive();
self.stop_persist();
self.time_wait_deadline = None;
if self.closed {
self.signal_established();
self.signal_fin_recvd();
}
}
fn signal_established(&mut self) {
self.established_signaled = true;
}
fn signal_fin_recvd(&mut self) {
self.fin_recvd_signaled = true;
}
}
fn wallclock_ms() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0)
}
#[allow(dead_code)]
fn _options_export_is_used(_o: &TcpOption) {
let _ = options::kind::End;
}
#[cfg(test)]
mod tests {
use super::*;
fn cfg(local: u16, remote: u16) -> ConnConfig {
ConnConfig {
local_port: local,
remote_port: remote,
mss: 1460,
send_buf_size: 4096,
recv_buf_size: 4096,
..Default::default()
}
}
fn parse(bytes: &[u8]) -> Segment {
Segment::parse(bytes).expect("parse seg")
}
fn drive_handshake(client: &mut Conn, server: &mut Conn) {
let pkts = client.connect();
assert_eq!(pkts.len(), 1);
let syn = parse(&pkts[0]);
assert!(syn.has_flag(flags::SYN));
assert!(!syn.has_flag(flags::ACK));
let pkts = server.accept_syn(&syn);
assert_eq!(pkts.len(), 1);
let synack = parse(&pkts[0]);
assert!(synack.has_flag(flags::SYN) && synack.has_flag(flags::ACK));
let pkts = client.handle_segment(&synack);
assert_eq!(client.state(), State::Established);
let ack = parse(&pkts[0]);
assert!(ack.has_flag(flags::ACK));
assert!(!ack.has_flag(flags::SYN));
let _ = server.handle_segment(&ack);
assert_eq!(server.state(), State::Established);
}
#[test]
fn three_way_handshake() {
let mut client = Conn::new(cfg(40000, 80));
let mut server = Conn::new(cfg(80, 40000));
drive_handshake(&mut client, &mut server);
assert!(client.is_established());
assert!(server.is_established());
}
#[test]
fn data_transfer() {
let mut client = Conn::new(cfg(40001, 80));
let mut server = Conn::new(cfg(80, 40001));
drive_handshake(&mut client, &mut server);
let payload = b"hello, world!";
let (n, pkts) = client.write(payload);
assert_eq!(n, payload.len());
assert_eq!(pkts.len(), 1);
let seg = parse(&pkts[0]);
assert_eq!(seg.payload, payload);
let ack_pkts = server.handle_segment(&seg);
assert!(!ack_pkts.is_empty());
let mut buf = [0u8; 64];
let n = server.read(&mut buf);
assert_eq!(&buf[..n], payload);
let ack = parse(&ack_pkts[0]);
let _ = client.handle_segment(&ack);
}
#[test]
fn graceful_close() {
let mut client = Conn::new(cfg(40002, 80));
let mut server = Conn::new(cfg(80, 40002));
drive_handshake(&mut client, &mut server);
let pkts = client.close();
assert_eq!(client.state(), State::FinWait1);
assert_eq!(pkts.len(), 1);
let fin = parse(&pkts[0]);
assert!(fin.has_flag(flags::FIN));
let ack_pkts = server.handle_segment(&fin);
assert_eq!(server.state(), State::CloseWait);
assert!(server.fin_received());
let ack = parse(&ack_pkts[0]);
let _ = client.handle_segment(&ack);
assert_eq!(client.state(), State::FinWait2);
let pkts = server.close();
assert_eq!(server.state(), State::LastAck);
let fin2 = parse(&pkts[0]);
assert!(fin2.has_flag(flags::FIN));
let pkts = client.handle_segment(&fin2);
assert_eq!(client.state(), State::TimeWait);
let ack2 = parse(&pkts[0]);
let _ = server.handle_segment(&ack2);
assert_eq!(server.state(), State::Closed);
assert!(server.is_closed());
}
#[test]
fn abort_emits_rst() {
let mut client = Conn::new(cfg(40003, 80));
let mut server = Conn::new(cfg(80, 40003));
drive_handshake(&mut client, &mut server);
let pkts = client.abort();
assert_eq!(client.state(), State::Closed);
assert_eq!(pkts.len(), 1);
let rst = parse(&pkts[0]);
assert!(rst.has_flag(flags::RST));
}
#[test]
fn closed_replies_with_rst() {
let mut c = Conn::new(cfg(80, 40004));
let seg = Segment {
src_port: 40004,
dst_port: 80,
seq: 1000,
ack: 0,
flags: flags::SYN,
window: 65535,
..Default::default()
};
let pkts = c.handle_segment(&seg);
assert_eq!(pkts.len(), 1);
let rst = parse(&pkts[0]);
assert!(rst.has_flag(flags::RST));
}
}