use crate::layer;
use crate::wire::{Payload, PayloadMut};
use crate::wire::{ip, tcp};
use super::connection::{AvailableBytes, Endpoint, InPacket, Operator, OutSignals, ReceivedSegment, Segment, Signals};
use super::endpoint::{FourTuple, SlotKey};
pub enum In<'a, P: PayloadMut> {
Sending(Sending<'a>),
Open(Open<'a, P>),
Closing(Closing<'a>),
Closed(Closed<'a, P>),
Stray(Stray<'a, P>),
}
pub trait SendBuf {
fn available(&self) -> AvailableBytes;
fn fill(&mut self, buf: &mut [u8], begin: tcp::SeqNumber);
fn ack(&mut self, begin: tcp::SeqNumber);
}
pub trait RecvBuf {
fn receive(&mut self, buf: &[u8], segment: ReceivedSegment);
fn ack(&mut self) -> tcp::SeqNumber;
fn window(&self) -> usize;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct UserSignals {
pub reset: bool,
pub half_closed: bool,
pub data: bool,
pub relisten: bool,
}
enum Unhandled<'a, P: Payload> {
Open {
operator: Operator<'a>,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
},
Closed {
endpoint: &'a mut dyn Endpoint,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
},
}
pub struct Sending<'a> {
operator: Operator<'a>,
signals: UserSignals,
}
pub struct Closing<'a> {
#[allow(dead_code)] endpoint: &'a mut dyn Endpoint,
previous: SlotKey,
signals: UserSignals,
}
pub struct Closed<'a, P: PayloadMut> {
ip: layer::ip::Controller<'a>,
endpoint: &'a mut dyn Endpoint,
previous: SlotKey,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
}
pub struct Open<'a, P: PayloadMut> {
ip: layer::ip::Controller<'a>,
operator: Operator<'a>,
signals: UserSignals,
packet: OpenPacket<'a, P>,
}
pub struct Stray<'a, P: PayloadMut> {
ip: layer::ip::Controller<'a>,
endpoint: &'a mut dyn Endpoint,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
}
enum OpenPacket<'a, P: PayloadMut> {
In {
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
segment: ReceivedSegment,
},
Control {
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
},
Out {
raw: &'a mut P,
},
}
pub struct Raw<'a, P: PayloadMut> {
pub(super) ip: layer::ip::RawPacket<'a, P>,
pub(super) endpoint: &'a mut dyn Endpoint,
}
impl<'a, P: PayloadMut> Unhandled<'a, P> {
fn try_open(
endpoint: &'a mut dyn Endpoint,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
) -> Self {
let tcp_repr = tcp.repr();
let ip_repr = tcp.inner().repr();
let connection = FourTuple {
local: ip_repr.dst_addr(),
local_port: tcp_repr.dst_port,
remote: ip_repr.src_addr(),
remote_port: tcp_repr.src_port,
};
match Operator::from_tuple(endpoint, connection) {
Ok(operator) => Unhandled::Open {
operator,
tcp,
},
Err(endpoint) => Unhandled::Closed {
endpoint,
tcp,
}
}
}
}
impl<'a, P: PayloadMut> In<'a, P> {
pub fn from_arriving(
endpoint: &'a mut dyn Endpoint,
ip_control: layer::ip::Controller<'a>,
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
) -> Result<Self, crate::layer::Error> {
let (mut operator, tcp) = match Unhandled::try_open(endpoint, tcp) {
Unhandled::Open { operator, tcp } => (operator, tcp),
Unhandled::Closed { endpoint, tcp } => {
return Ok(In::Stray(Stray {
endpoint,
ip: ip_control,
tcp,
}));
}
};
let from = tcp.inner().repr().src_addr();
let time = ip_control.info().timestamp();
let in_packet = InPacket {
segment: tcp.repr(),
from,
time,
};
let mut signals = operator.arrives(&in_packet);
let user = UserSignals::new(&signals);
if signals.delete && signals.answer.is_none() {
let previous = operator.connection_key;
let endpoint = operator.delete();
return Ok(In::Closed(Closed {
ip: ip_control,
endpoint,
previous,
tcp,
}));
}
let answer = match signals.answer.take() {
Some(answer) => answer,
None => {
return Ok(In::Open(Open {
ip: ip_control,
operator,
signals: user,
packet: match signals.receive {
Some(segment) => OpenPacket::In { tcp, segment },
None => OpenPacket::Control { tcp },
},
}));
},
};
control_answer(tcp, answer, ip_control)?;
if signals.delete {
let previous = operator.connection_key;
let endpoint = operator.delete();
return Ok(In::Closing(Closing {
endpoint,
previous,
signals: user,
}));
}
debug_assert_eq!(signals.reset, false);
Ok(In::Sending(Sending {
operator,
signals: user,
}))
}
pub fn key(&self) -> Option<SlotKey> {
match self {
In::Sending(sending) => Some(sending.key()),
In::Open(open) => Some(open.key()),
In::Closing(closing) => Some(closing.key()),
In::Closed(closed) => Some(closed.key()),
In::Stray(_) => None,
}
}
pub fn user_signals(&self) -> UserSignals {
match self {
In::Sending(sending) => sending.signals,
In::Open(open) => open.signals,
In::Closing(closing) => closing.signals,
In::Closed(_) => UserSignals::default(),
In::Stray(_) => UserSignals::default(),
}
}
}
impl<'a, P: PayloadMut> Open<'a, P> {
pub fn key(&self) -> SlotKey {
self.operator.connection_key
}
pub fn read(&mut self, with: &mut impl RecvBuf) {
let connection = self.operator.connection_mut();
connection.recv.update_window(with.window());
if let OpenPacket::In { tcp, segment } = &self.packet {
with.receive(tcp.payload_slice(), *segment);
let progress = segment.acked_until(with.ack());
connection.set_recv_ack(progress);
}
}
pub fn write(self, with: &mut impl SendBuf) -> Result<Result<Sending<'a>, Closing<'a>>, crate::layer::Error> {
let Open { ip, mut operator, signals: mut user, packet, } = self;
let payload: &'a mut P = match packet {
OpenPacket::In { tcp, .. } | OpenPacket::Control { tcp }
=> tcp.into_inner().into_inner().into_inner(),
OpenPacket::Out { raw } => raw,
};
let tcp_seq = operator.connection().get_send_ack();
with.ack(tcp_seq);
let available = with.available();
let time = ip.info().timestamp();
let signals = operator.next_send_segment(available, time);
user.update(&signals);
if let Some(Segment { repr, range }) = signals.segment {
let raw_ip = layer::ip::RawPacket {
control: ip,
payload,
};
let mut out_ip = prepare(raw_ip, &mut operator, repr)?;
let ip_repr = out_ip.repr();
let mut tcp = tcp::Packet::new_unchecked(out_ip.payload_mut_slice(), repr);
with.fill(tcp.payload_mut_slice(), tcp_seq + range.start);
tcp.fill_checksum(ip_repr.src_addr(), ip_repr.dst_addr());
out_ip.send()?;
}
Ok(if signals.delete {
let previous = operator.key();
let endpoint = operator.delete();
Err(Closing {
endpoint,
previous,
signals: user,
})
} else {
Ok(Sending {
operator,
signals: user,
})
})
}
}
impl<'a, P: PayloadMut> Raw<'a, P> {
pub fn open(self, addr: ip::Address, port: u16) -> Result<Open<'a, P>, crate::layer::Error> {
let local = self.source(addr)?;
let local_port = self.endpoint.source_port(local)
.ok_or(crate::layer::Error::Exhausted)?;
let new = FourTuple {
local,
local_port,
remote: addr,
remote_port: port,
};
let mut operator = match self.endpoint.open(new) {
None => return Err(crate::layer::Error::Exhausted),
Some(key) => Operator::new(self.endpoint, key).unwrap(),
};
let time = self.ip.control.info().timestamp();
assert!(operator.open(time).is_ok());
let layer::ip::RawPacket {
control: ip,
payload: raw,
} = self.ip;
Ok(Open {
ip,
operator,
signals: UserSignals::default(),
packet: OpenPacket::Out { raw },
})
}
pub fn attach(self, key: SlotKey) -> Result<Open<'a, P>, Self> {
if self.endpoint.get(key).is_none() {
return Err(self);
};
let operator = Operator::new(self.endpoint, key).unwrap();
let layer::ip::RawPacket {
control: ip,
payload: raw,
} = self.ip;
Ok(Open {
ip,
operator,
signals: UserSignals::default(),
packet: OpenPacket::Out { raw },
})
}
fn source(&self, dst: ip::Address) -> Result<ip::Address, crate::layer::Error> {
let source = match dst {
ip::Address::Ipv4(_) => ip::Subnet::Ipv4(ip::v4::Subnet::ANY),
ip::Address::Ipv6(_) => ip::Subnet::Ipv6(ip::v6::Subnet::ANY),
_ => return Err(crate::layer::Error::Illegal),
};
self.ip.control().local_ip(source)
.ok_or(crate::layer::Error::Unreachable)
}
}
impl<'a> Sending<'a> {
pub fn key(&self) -> SlotKey {
self.operator.connection_key
}
}
impl<'a> Closing<'a> {
pub fn key(&self) -> SlotKey {
self.previous
}
}
impl<'a, P: PayloadMut> Closed<'a, P> {
pub fn key(&self) -> SlotKey {
self.previous
}
pub fn into_raw(self) -> Raw<'a, P> {
let raw_ip = layer::ip::RawPacket {
control: self.ip,
payload: self.tcp.into_inner().into_inner().into_inner(),
};
Raw {
ip: raw_ip,
endpoint: self.endpoint,
}
}
}
impl<'a, P: PayloadMut> Stray<'a, P> {
pub fn into_raw(self) -> Raw<'a, P> {
let raw_ip = layer::ip::RawPacket {
control: self.ip,
payload: self.tcp.into_inner().into_inner().into_inner(),
};
Raw {
ip: raw_ip,
endpoint: self.endpoint,
}
}
}
impl UserSignals {
fn new(signals: &Signals) -> Self {
UserSignals {
reset: signals.reset,
data: signals.receive.is_some(),
half_closed: false,
relisten: false,
}
}
fn update(&mut self, _signals: &OutSignals) {
}
}
fn control_answer<'a, P: PayloadMut>(
tcp: tcp::Packet<layer::ip::IpPacket<'a, P>>,
answer: tcp::Repr,
ip: layer::ip::Controller<'a>,
) -> Result<(), crate::layer::Error> {
assert_eq!(answer.payload_len, 0, "Control answer can not handle data");
let raw_buffer = tcp.into_inner();
let ip_repr = raw_buffer.repr();
let ip_payload_len = answer.header_len();
let packet = layer::ip::InPacket {
control: ip,
packet: raw_buffer,
};
let layer::ip::InPacket { control, mut packet, } = packet.reinit(layer::ip::Init {
source: layer::ip::Source::Exact(ip_repr.dst_addr()),
dst_addr: ip_repr.src_addr(),
protocol: ip::Protocol::Tcp,
payload: ip_payload_len,
})?.into_incoming();
let raw_packet = tcp::Packet::new_unchecked(&mut packet, answer.clone());
answer.emit(raw_packet);
let mut raw_packet = tcp::Packet::new_unchecked(&mut packet, answer.clone());
raw_packet.fill_checksum(ip_repr.src_addr(), ip_repr.dst_addr());
layer::ip::OutPacket::new_unchecked(control, packet)
.send()
}
fn prepare<'a, P: PayloadMut>(
packet: layer::ip::RawPacket<'a, P>,
operator: &mut Operator,
repr: tcp::Repr,
) -> Result<layer::ip::OutPacket<'a, P>, crate::layer::Error> {
let tuple = operator.four_tuple();
let init_ip = packet.prepare(layer::ip::Init {
dst_addr: tuple.remote,
source: layer::ip::Source::Exact(tuple.local),
protocol: ip::Protocol::Tcp,
payload: repr.header_len() + usize::from(repr.payload_len),
})?;
let layer::ip::InPacket { control, mut packet } = init_ip.into_incoming();
let tcp = tcp::Packet::new_unchecked(&mut packet, repr);
repr.emit(tcp);
Ok(layer::ip::OutPacket::new_unchecked(control, packet))
}