Skip to content

Commit 4d7e047

Browse files
Add comprehensive Rust documentation for public APIs
Co-authored-by: SajjadPourali <20374762+SajjadPourali@users.noreply.github.com>
1 parent 60d94e4 commit 4d7e047

6 files changed

Lines changed: 452 additions & 1 deletion

File tree

src/error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
1+
/// Error types for the IP stack.
2+
///
3+
/// This enum represents all possible errors that can occur when working with the IP stack.
14
#[derive(thiserror::Error, Debug)]
25
pub enum IpStackError {
6+
/// The transport protocol is not supported.
37
#[error("The transport protocol is not supported")]
48
UnsupportedTransportProtocol,
59

10+
/// The packet is invalid or malformed.
611
#[error("The packet is invalid")]
712
InvalidPacket,
813

14+
/// A value is too large to fit in a u16.
915
#[error("ValueTooBigError<u16> {0}")]
1016
ValueTooBigErrorU16(#[from] etherparse::err::ValueTooBigError<u16>),
1117

18+
/// A value is too large to fit in a usize.
1219
#[error("ValueTooBigError<usize> {0}")]
1320
ValueTooBigErrorUsize(#[from] etherparse::err::ValueTooBigError<usize>),
1421

22+
/// The TCP packet is invalid.
1523
#[error("Invalid Tcp packet")]
1624
InvalidTcpPacket,
1725

26+
/// An I/O error occurred.
1827
#[error("IO error: {0}")]
1928
IoError(#[from] std::io::Error),
2029

30+
/// Error accepting a new stream.
2131
#[error("Accept Error")]
2232
AcceptError,
2333

34+
/// Error sending data through a channel.
2435
#[error("Send Error {0}")]
2536
SendError(#[from] Box<tokio::sync::mpsc::error::SendError<crate::stream::IpStackStream>>),
2637
}
@@ -48,4 +59,9 @@ impl From<IpStackError> for std::io::Error {
4859
}
4960
}
5061

62+
/// A specialized [`Result`] type for IP stack operations.
63+
///
64+
/// This type is used throughout the IP stack for any operation which may produce an error.
65+
///
66+
/// [`Result`]: std::result::Result
5167
pub type Result<T, E = IpStackError> = std::result::Result<T, E>;

src/lib.rs

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,34 @@ const TUN_PROTO_IP6: [u8; 2] = [0x00, 0x0A];
4242
#[cfg(any(target_os = "macos", target_os = "ios"))]
4343
const TUN_PROTO_IP4: [u8; 2] = [0x00, 0x02];
4444

45+
/// Configuration for the IP stack.
46+
///
47+
/// This structure holds configuration parameters that control the behavior of the IP stack,
48+
/// including network settings and protocol-specific timeouts.
49+
///
50+
/// # Examples
51+
///
52+
/// ```
53+
/// use ipstack::IpStackConfig;
54+
/// use std::time::Duration;
55+
///
56+
/// let mut config = IpStackConfig::default();
57+
/// config.mtu(1500)
58+
/// .udp_timeout(Duration::from_secs(60))
59+
/// .packet_information(false);
60+
/// ```
4561
#[non_exhaustive]
4662
pub struct IpStackConfig {
63+
/// Maximum Transmission Unit (MTU) size in bytes.
64+
/// Default is `u16::MAX` (65535).
4765
pub mtu: u16,
66+
/// Whether to include packet information headers (Unix platforms only).
67+
/// Default is `false`.
4868
pub packet_information: bool,
69+
/// TCP-specific configuration parameters.
4970
pub tcp_config: Arc<TcpConfig>,
71+
/// Timeout for UDP connections.
72+
/// Default is 30 seconds.
5073
pub udp_timeout: Duration,
5174
}
5275

@@ -62,31 +85,157 @@ impl Default for IpStackConfig {
6285
}
6386

6487
impl IpStackConfig {
65-
/// Set custom TCP configuration
88+
/// Set custom TCP configuration.
89+
///
90+
/// # Arguments
91+
///
92+
/// * `config` - The TCP configuration to use
93+
///
94+
/// # Examples
95+
///
96+
/// ```
97+
/// use ipstack::{IpStackConfig, TcpConfig};
98+
///
99+
/// let mut config = IpStackConfig::default();
100+
/// config.with_tcp_config(TcpConfig::default());
101+
/// ```
66102
pub fn with_tcp_config(&mut self, config: TcpConfig) -> &mut Self {
67103
self.tcp_config = Arc::new(config);
68104
self
69105
}
106+
107+
/// Set the UDP connection timeout.
108+
///
109+
/// # Arguments
110+
///
111+
/// * `timeout` - The timeout duration for UDP connections
112+
///
113+
/// # Examples
114+
///
115+
/// ```
116+
/// use ipstack::IpStackConfig;
117+
/// use std::time::Duration;
118+
///
119+
/// let mut config = IpStackConfig::default();
120+
/// config.udp_timeout(Duration::from_secs(60));
121+
/// ```
70122
pub fn udp_timeout(&mut self, timeout: Duration) -> &mut Self {
71123
self.udp_timeout = timeout;
72124
self
73125
}
126+
127+
/// Set the Maximum Transmission Unit (MTU) size.
128+
///
129+
/// # Arguments
130+
///
131+
/// * `mtu` - The MTU size in bytes
132+
///
133+
/// # Examples
134+
///
135+
/// ```
136+
/// use ipstack::IpStackConfig;
137+
///
138+
/// let mut config = IpStackConfig::default();
139+
/// config.mtu(1500);
140+
/// ```
74141
pub fn mtu(&mut self, mtu: u16) -> &mut Self {
75142
self.mtu = mtu;
76143
self
77144
}
145+
146+
/// Enable or disable packet information headers (Unix platforms only).
147+
///
148+
/// When enabled on Unix platforms, the TUN device will include 4-byte packet
149+
/// information headers.
150+
///
151+
/// # Arguments
152+
///
153+
/// * `packet_information` - Whether to include packet information headers
154+
///
155+
/// # Examples
156+
///
157+
/// ```
158+
/// use ipstack::IpStackConfig;
159+
///
160+
/// let mut config = IpStackConfig::default();
161+
/// config.packet_information(true);
162+
/// ```
78163
pub fn packet_information(&mut self, packet_information: bool) -> &mut Self {
79164
self.packet_information = packet_information;
80165
self
81166
}
82167
}
83168

169+
/// The main IP stack instance.
170+
///
171+
/// `IpStack` provides a userspace TCP/IP stack implementation for TUN devices.
172+
/// It processes network packets and creates stream abstractions for TCP, UDP, and
173+
/// unknown transport protocols.
174+
///
175+
/// # Examples
176+
///
177+
/// ```no_run
178+
/// use ipstack::{IpStack, IpStackConfig, IpStackStream};
179+
/// use std::net::Ipv4Addr;
180+
///
181+
/// #[tokio::main]
182+
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
183+
/// // Configure TUN device
184+
/// let mut config = tun::Configuration::default();
185+
/// config
186+
/// .address(Ipv4Addr::new(10, 0, 0, 1))
187+
/// .netmask(Ipv4Addr::new(255, 255, 255, 0))
188+
/// .up();
189+
///
190+
/// // Create IP stack
191+
/// let ipstack_config = IpStackConfig::default();
192+
/// let mut ip_stack = IpStack::new(ipstack_config, tun::create_as_async(&config)?);
193+
///
194+
/// // Accept incoming streams
195+
/// while let Ok(stream) = ip_stack.accept().await {
196+
/// match stream {
197+
/// IpStackStream::Tcp(tcp) => {
198+
/// // Handle TCP connection
199+
/// }
200+
/// IpStackStream::Udp(udp) => {
201+
/// // Handle UDP connection
202+
/// }
203+
/// _ => {}
204+
/// }
205+
/// }
206+
/// Ok(())
207+
/// }
208+
/// ```
84209
pub struct IpStack {
85210
accept_receiver: UnboundedReceiver<IpStackStream>,
86211
handle: JoinHandle<Result<()>>,
87212
}
88213

89214
impl IpStack {
215+
/// Create a new IP stack instance.
216+
///
217+
/// # Arguments
218+
///
219+
/// * `config` - Configuration for the IP stack
220+
/// * `device` - An async TUN device implementing `AsyncRead` + `AsyncWrite`
221+
///
222+
/// # Examples
223+
///
224+
/// ```no_run
225+
/// use ipstack::{IpStack, IpStackConfig};
226+
/// use std::net::Ipv4Addr;
227+
///
228+
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
229+
/// let mut tun_config = tun::Configuration::default();
230+
/// tun_config.address(Ipv4Addr::new(10, 0, 0, 1))
231+
/// .netmask(Ipv4Addr::new(255, 255, 255, 0))
232+
/// .up();
233+
///
234+
/// let ipstack_config = IpStackConfig::default();
235+
/// let ip_stack = IpStack::new(ipstack_config, tun::create_as_async(&tun_config)?);
236+
/// # Ok(())
237+
/// # }
238+
/// ```
90239
pub fn new<Device>(config: IpStackConfig, device: Device) -> IpStack
91240
where
92241
Device: AsyncRead + AsyncWrite + Unpin + Send + 'static,
@@ -98,6 +247,39 @@ impl IpStack {
98247
}
99248
}
100249

250+
/// Accept an incoming network stream.
251+
///
252+
/// This method waits for and returns the next incoming network connection or packet.
253+
/// The returned `IpStackStream` enum indicates the type of stream (TCP, UDP, or unknown).
254+
///
255+
/// # Returns
256+
///
257+
/// * `Ok(IpStackStream)` - The next incoming stream
258+
/// * `Err(IpStackError::AcceptError)` - If the IP stack has been shut down
259+
///
260+
/// # Examples
261+
///
262+
/// ```no_run
263+
/// use ipstack::{IpStack, IpStackConfig, IpStackStream};
264+
///
265+
/// # async fn example(mut ip_stack: IpStack) -> Result<(), Box<dyn std::error::Error>> {
266+
/// match ip_stack.accept().await? {
267+
/// IpStackStream::Tcp(tcp) => {
268+
/// println!("New TCP connection from {}", tcp.peer_addr());
269+
/// }
270+
/// IpStackStream::Udp(udp) => {
271+
/// println!("New UDP stream from {}", udp.peer_addr());
272+
/// }
273+
/// IpStackStream::UnknownTransport(unknown) => {
274+
/// println!("Unknown transport protocol: {:?}", unknown.ip_protocol());
275+
/// }
276+
/// IpStackStream::UnknownNetwork(data) => {
277+
/// println!("Unknown network packet: {} bytes", data.len());
278+
/// }
279+
/// }
280+
/// # Ok(())
281+
/// # }
282+
/// ```
101283
pub async fn accept(&mut self) -> Result<IpStackStream, IpStackError> {
102284
self.accept_receiver.recv().await.ok_or(IpStackError::AcceptError)
103285
}

src/stream/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,43 @@ mod tcp;
1111
mod udp;
1212
mod unknown;
1313

14+
/// A network stream accepted by the IP stack.
15+
///
16+
/// This enum represents different types of network streams that can be accepted from the TUN device.
17+
/// Each variant provides appropriate abstractions for handling specific protocol types.
18+
///
19+
/// # Variants
20+
///
21+
/// * `Tcp` - A TCP connection stream implementing `AsyncRead` + `AsyncWrite`
22+
/// * `Udp` - A UDP stream implementing `AsyncRead` + `AsyncWrite`
23+
/// * `UnknownTransport` - A stream for unknown transport layer protocols (e.g., ICMP, IGMP)
24+
/// * `UnknownNetwork` - Raw network layer packets that couldn't be parsed
1425
pub enum IpStackStream {
26+
/// A TCP connection stream.
1527
Tcp(IpStackTcpStream),
28+
/// A UDP stream.
1629
Udp(IpStackUdpStream),
30+
/// A stream for unknown transport protocols.
1731
UnknownTransport(IpStackUnknownTransport),
32+
/// Raw network packets that couldn't be parsed.
1833
UnknownNetwork(Vec<u8>),
1934
}
2035

2136
impl IpStackStream {
37+
/// Returns the local socket address for this stream.
38+
///
39+
/// For TCP and UDP streams, this returns the source address of the connection.
40+
/// For unknown transport and network streams, this returns an unspecified address.
41+
///
42+
/// # Examples
43+
///
44+
/// ```no_run
45+
/// # use ipstack::{IpStack, IpStackStream};
46+
/// # async fn example(stream: IpStackStream) {
47+
/// let local_addr = stream.local_addr();
48+
/// println!("Local address: {}", local_addr);
49+
/// # }
50+
/// ```
2251
pub fn local_addr(&self) -> SocketAddr {
2352
match self {
2453
IpStackStream::Tcp(tcp) => tcp.local_addr(),
@@ -30,6 +59,21 @@ impl IpStackStream {
3059
},
3160
}
3261
}
62+
63+
/// Returns the remote socket address for this stream.
64+
///
65+
/// For TCP and UDP streams, this returns the destination address of the connection.
66+
/// For unknown transport and network streams, this returns an unspecified address.
67+
///
68+
/// # Examples
69+
///
70+
/// ```no_run
71+
/// # use ipstack::{IpStack, IpStackStream};
72+
/// # async fn example(stream: IpStackStream) {
73+
/// let peer_addr = stream.peer_addr();
74+
/// println!("Peer address: {}", peer_addr);
75+
/// # }
76+
/// ```
3377
pub fn peer_addr(&self) -> SocketAddr {
3478
match self {
3579
IpStackStream::Tcp(tcp) => tcp.peer_addr(),
@@ -42,6 +86,14 @@ impl IpStackStream {
4286
}
4387
}
4488

89+
/// Returns a packet sender for this stream.
90+
///
91+
/// This is an internal method used to send packets back to the stream.
92+
/// Only available for TCP and UDP streams.
93+
///
94+
/// # Errors
95+
///
96+
/// Returns an error if called on `UnknownTransport` or `UnknownNetwork` variants.
4597
pub fn stream_sender(&self) -> Result<crate::PacketSender, std::io::Error> {
4698
match self {
4799
IpStackStream::Tcp(tcp) => Ok(tcp.stream_sender()),

0 commit comments

Comments
 (0)