#![deny(unsafe_code)]
#![deny(missing_debug_implementations)]
#![warn(missing_docs)]
pub mod error;
#[allow(unsafe_code)]
pub mod packet;
pub mod protocol_expectation;
pub mod source_admission;
pub mod transport;
#[cfg(all(feature = "linux", target_os = "linux"))]
pub mod worker;
#[cfg(not(all(feature = "linux", target_os = "linux")))]
#[path = "worker_stub.rs"]
pub mod worker;
pub use error::{NetError, Result};
pub use packet::{
parse_packet, parse_tcp_options, EthHeader, Ipv4Header, Ipv6Header, IpVersion, L4Protocol,
ParsedPacket, TcpHeader, TcpOptionsInfo, UdpHeader, VlanTag,
};
pub use protocol_expectation::ProtocolExpectation;
pub use source_admission::{
AdmissionAction, AdmissionRule, IpAddr, ProtoMatch, SourceAdmissionEngine,
};
pub use transport::{
Accept, AcceptedConn, AcceptError, BindTable, ConnectionKey, ConnectionState, ListenEndpoint,
StdTcpAcceptor, TcpAction, TcpConnection, TcpStateMachine, TcpStats, UdpAction, UdpMode,
UdpSession, UdpSessionTable, UdpStats, BIND_TABLE_CAPACITY,
QuicAction, QuicConnParams, QuicConnState, QuicConnection, QuicConnectionTable,
QuicFrameType, QuicHeader, QuicHeaderType, QuicStream, QuicStreamState,
PathChallengeFrame, PathResponseFrame, PathValidationState,
parse_quic_header, parse_path_challenge_frame, parse_path_response_frame,
QuicServer, QuicServerConfig, QuicServerError, QuicServerState,
QuicServerConnection, QuicServerFrame, QuicVersion,
build_ack_frame, build_connection_close_app, build_connection_close_transport, build_crypto_frame, build_handshake_done_frame,
build_padding_frame, build_ping_frame, build_stream_frame, build_default_transport_params,
decode_packet_number, parse_frame, parse_frames, parse_long_header_full,
parse_short_header, ParsedLongHeader, ParsedShortHeader,
TimerAction, TimerType, TimerWheel,
};
pub use worker::{Worker, WorkerState, WorkerStats};
#[cfg(all(feature = "linux", target_os = "linux"))]
pub use worker::UdpDatagram;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AddressFamily {
Ipv4,
Ipv6,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NetAddr {
ipv4: [u8; 4],
ipv6: [u8; 16],
port: u16,
family: AddressFamily,
}
impl NetAddr {
pub fn new_ipv4(ip: [u8; 4], port: u16) -> Self {
Self {
ipv4: ip,
ipv6: [0u8; 16],
port,
family: AddressFamily::Ipv4,
}
}
pub fn new_ipv6(ip: [u8; 16], port: u16) -> Self {
Self {
ipv4: [0u8; 4],
ipv6: ip,
port,
family: AddressFamily::Ipv6,
}
}
pub fn from_ip_addr(ip: IpAddr, port: u16) -> Self {
match ip {
IpAddr::V4(bytes) => Self::new_ipv4(bytes, port),
IpAddr::V6(bytes) => Self::new_ipv6(bytes, port),
IpAddr::Any => Self::new_ipv4([0, 0, 0, 0], port),
}
}
#[inline]
pub fn family(&self) -> AddressFamily {
self.family
}
#[inline]
pub fn port(&self) -> u16 {
self.port
}
#[inline]
pub fn ipv4_bytes(&self) -> [u8; 4] {
self.ipv4
}
#[inline]
pub fn ipv6_bytes(&self) -> [u8; 16] {
self.ipv6
}
#[inline]
pub fn to_ip_addr(&self) -> IpAddr {
match self.family {
AddressFamily::Ipv4 => IpAddr::V4(self.ipv4),
AddressFamily::Ipv6 => IpAddr::V6(self.ipv6),
}
}
pub fn to_string_addr(&self) -> String {
match self.family {
AddressFamily::Ipv4 => {
format!("{}.{}.{}.{}:{}", self.ipv4[0], self.ipv4[1], self.ipv4[2], self.ipv4[3], self.port)
}
AddressFamily::Ipv6 => {
let hex = zenith_foundation::hex_encode(&self.ipv6);
format!("[{}]:{}", hex, self.port)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_net_addr_ipv4() {
let addr = NetAddr::new_ipv4([127, 0, 0, 1], 8080);
assert_eq!(addr.ipv4_bytes(), [127, 0, 0, 1]);
assert_eq!(addr.port(), 8080);
assert_eq!(addr.family(), AddressFamily::Ipv4);
assert_eq!(addr.to_string_addr(), "127.0.0.1:8080");
}
#[test]
fn test_net_addr_ipv6() {
let addr = NetAddr::new_ipv6([0u8; 16], 443);
assert_eq!(addr.family(), AddressFamily::Ipv6);
assert_eq!(addr.port(), 443);
}
#[test]
fn test_net_addr_equality() {
let a = NetAddr::new_ipv4([10, 0, 0, 1], 80);
let b = NetAddr::new_ipv4([10, 0, 0, 1], 80);
assert_eq!(a, b);
}
#[test]
fn test_net_addr_from_ip_addr() {
let ip = IpAddr::V4([192, 168, 1, 1]);
let addr = NetAddr::from_ip_addr(ip, 8080);
assert_eq!(addr.ipv4_bytes(), [192, 168, 1, 1]);
assert_eq!(addr.port(), 8080);
let addr2 = NetAddr::from_ip_addr(IpAddr::V4_WILDCARD, 0);
assert_eq!(addr2.ipv4_bytes(), [0, 0, 0, 0]);
}
#[test]
fn test_net_addr_copy_semantics() {
let addr = NetAddr::new_ipv4([1, 2, 3, 4], 8080);
let copy = addr;
assert_eq!(addr, copy);
assert_eq!(addr.port(), 8080);
}
#[test]
fn test_net_addr_to_ip_addr() {
let addr = NetAddr::new_ipv4([10, 20, 30, 40], 80);
let ip = addr.to_ip_addr();
assert_eq!(ip, IpAddr::V4([10, 20, 30, 40]));
}
}