use crate::{Buf, BufMut, BufResult, Codec, Cursor};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Tcp {
pub source_port: Port,
pub destination_port: Port,
pub sequence_number: u32,
pub acknowledgment_number: u32,
pub data_offset: u8,
pub ns: bool,
pub cwr: bool,
pub ece: bool,
pub urg: bool,
pub ack: bool,
pub psh: bool,
pub rst: bool,
pub syn: bool,
pub fin: bool,
pub window: u16,
pub checksum: u16,
pub urgent_pointer: u16,
}
impl Codec for Tcp {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.source_port.encode(writer, ())?;
self.destination_port.encode(writer, ())?;
self.sequence_number.encode(writer, ())?;
self.acknowledgment_number.encode(writer, ())?;
let byte12 = ((self.data_offset & 0x0F) << 4) | (if self.ns { 0b0000_0001 } else { 0 });
let byte13 = (if self.cwr { 0b1000_0000 } else { 0 })
| (if self.ece { 0b0100_0000 } else { 0 })
| (if self.urg { 0b0010_0000 } else { 0 })
| (if self.ack { 0b0001_0000 } else { 0 })
| (if self.psh { 0b0000_1000 } else { 0 })
| (if self.rst { 0b0000_0100 } else { 0 })
| (if self.syn { 0b0000_0010 } else { 0 })
| (if self.fin { 0b0000_0001 } else { 0 });
writer.write_u8(byte12)?;
writer.write_u8(byte13)?;
self.window.encode(writer, ())?;
self.checksum.encode(writer, ())?;
self.urgent_pointer.encode(writer, ())?;
Ok(())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let source_port = Port::decode(reader, ())?;
let destination_port = Port::decode(reader, ())?;
let sequence_number = u32::decode(reader, ())?;
let acknowledgment_number = u32::decode(reader, ())?;
let byte12 = reader.read_u8()?;
let byte13 = reader.read_u8()?;
let data_offset = (byte12 >> 4) & 0x0F;
let ns = (byte12 & 0b0000_0001) != 0;
let cwr = (byte13 & 0b1000_0000) != 0;
let ece = (byte13 & 0b0100_0000) != 0;
let urg = (byte13 & 0b0010_0000) != 0;
let ack = (byte13 & 0b0001_0000) != 0;
let psh = (byte13 & 0b0000_1000) != 0;
let rst = (byte13 & 0b0000_0100) != 0;
let syn = (byte13 & 0b0000_0010) != 0;
let fin = (byte13 & 0b0000_0001) != 0;
let window = u16::decode(reader, ())?;
let checksum = u16::decode(reader, ())?;
let urgent_pointer = u16::decode(reader, ())?;
Ok(Self {
source_port,
destination_port,
sequence_number,
acknowledgment_number,
data_offset,
ns,
cwr,
ece,
urg,
ack,
psh,
rst,
syn,
fin,
window,
checksum,
urgent_pointer,
})
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Port(pub u16);
impl Port {
pub const UNDEFINED: Port = Port(0);
pub const FTP: Port = Port(21);
pub const SSH: Port = Port(22);
pub const TELNET: Port = Port(23);
pub const SMTP: Port = Port(25);
pub const DNS: Port = Port(53);
pub const HTTP: Port = Port(80);
pub const POP3: Port = Port(110);
pub const NTP: Port = Port(123);
pub const IMAP: Port = Port(143);
pub const HTTPS: Port = Port(443);
pub const SMB: Port = Port(445);
pub const SYSLOG: Port = Port(514);
pub const RTSP: Port = Port(554);
pub const MYSQL: Port = Port(3306);
pub const POSTGRES: Port = Port(5432);
}
impl From<u16> for Port {
fn from(port: u16) -> Self {
Self(port)
}
}
impl From<Port> for u16 {
fn from(port: Port) -> Self {
port.0
}
}
impl Codec for Port {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self(u16::decode(reader, ())?))
}
}
impl std::fmt::Display for Port {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}