diff --git a/Cargo.toml b/Cargo.toml index 4574a63..e3aa1e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ndisapi-rs" -version = "0.4.5" +version = "0.4.6" edition = "2021" authors = ["Vadim Smirnov "] description = "Rust crate for interacting with the Windows Packet Filter driver (NDISAPI)" diff --git a/README.md b/README.md index 6a646f6..9f40120 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Add the following to your `Cargo.toml` file: ```toml [dependencies] -ndisapi-rs = "0.4.5" +ndisapi-rs = "0.4.6" ``` ## Usage diff --git a/examples/packthru.rs b/examples/packthru.rs index 6e6f303..bba717d 100644 --- a/examples/packthru.rs +++ b/examples/packthru.rs @@ -108,7 +108,7 @@ fn main() -> Result<()> { packets_number = packets_number.saturating_sub(packets_read); // Process each packet. - for (i, packet) in to_read.drain_success_packets().enumerate() { + for (i, packet) in to_read.drain_success().enumerate() { let direction_flags = packet.get_device_flags(); // Print packet direction and remaining packets. @@ -142,12 +142,6 @@ fn main() -> Result<()> { Ok(_) => {} Err(err) => println!("Error sending packet to adapter. Error code = {err}"), } - - //to_read.consume(&mut to_adapter).unwrap(); - match to_read.consume(&mut to_adapter) { - Ok(_) => {} - Err(err) => println!("Error consuming outgoing packets. Error code = {err}"), - } } if !to_mstcp.get_packet_number() > 0 { @@ -155,11 +149,11 @@ fn main() -> Result<()> { Ok(_) => {} Err(err) => println!("Error sending packet to mstcp. Error code = {err}"), }; - //to_read.consume(&mut to_mstcp).unwrap(); - match to_read.consume(&mut to_mstcp) { - Ok(_) => {} - Err(err) => println!("Error consuming incoming packets. Error code = {err}"), - } + } + + match to_read.append(to_mstcp.drain().chain(to_adapter.drain())) { + Ok(_) => {} + Err(err) => println!("Error consuming processed packets. Error code = {err}"), } if packets_number == 0 { diff --git a/src/driver/base.rs b/src/driver/base.rs index 90b1894..be6ebdc 100644 --- a/src/driver/base.rs +++ b/src/driver/base.rs @@ -343,24 +343,24 @@ impl<'a, const N: usize> EthMRequest<'a, N> { } } - /// Takes the `IntermediateBuffer` from the `EthPacket` at the specified index, replacing it with `None`. - /// - /// This is useful when you want to use the packet's buffer elsewhere, while ensuring that the `EthMRequest` no longer has access to it. - fn take_packet(&mut self, index: usize) -> Option<&'a mut IntermediateBuffer> { - if index < N { - self.packets[index].buffer.take() - } else { - None - } - } - /// Returns an iterator that yields `Some(IntermediateBuffer)` for each non-empty buffer in `packets`, in order, /// up to `packet_success`. + /// + /// # Description + /// + /// This function, `drain_success`, operates on mutable reference to the current instance of the struct. + /// It returns an iterator that goes over each non-empty buffer in `packets`, in their + /// original order, but only up to the index specified by `packet_success`. This iterator will + /// yield `Some(IntermediateBuffer)` for each of these buffers. These buffers represent packets + /// that have been successfully read from the driver. /// - /// Once called, this method "drains" the non-empty buffers from `packets`, leaving them empty. - pub fn drain_success_packets( - &mut self, - ) -> impl Iterator + '_ { + /// Once called, this method drains the non-empty buffers from `packets`, up to `packet_success` making them empty (`None`). + /// + /// # Returns + /// + /// This function returns an implementation of Iterator trait. The iterator item type is a mutable reference + /// to an `IntermediateBuffer` (`&'a mut IntermediateBuffer`). This iterator can be used to iterate over the drained buffers. + pub fn drain_success(&mut self) -> impl Iterator + '_ { self.packets .iter_mut() .take(self.packet_success as usize) @@ -374,6 +374,31 @@ impl<'a, const N: usize> EthMRequest<'a, N> { }) } + /// Returns an iterator that yields `Some(IntermediateBuffer)` for each non-empty buffer in `packets`. + /// + /// # Description + /// + /// This function, `drain`, operates on mutable reference to the current instance of the struct. + /// It returns an iterator which yields mutable references to `IntermediateBuffer` for each non-empty buffer in `packets`, + /// and it yields them in the order they occur in `packets`. + /// + /// Once called, this method drains the non-empty buffers from `packets`, making them empty (`None`). + /// + /// # Returns + /// + /// This function returns an implementation of Iterator trait. The iterator item type is a mutable reference + /// to an `IntermediateBuffer` (`&'a mut IntermediateBuffer`). This iterator can be used to iterate over the drained buffers. + pub fn drain(&mut self) -> impl Iterator + '_ { + self.packets.iter_mut().filter_map(|packet| { + if packet.buffer.is_some() { + self.packet_number -= 1; + packet.buffer.take() + } else { + None + } + }) + } + /// Sets the `IntermediateBuffer` for the `EthPacket` at the specified index. /// /// This method allows you to associate a new buffer with the `EthPacket` at the given index. @@ -453,30 +478,29 @@ impl<'a, const N: usize> EthMRequest<'a, N> { .position(|packet| packet.buffer.is_none()) } - /// Consumes another `EthMRequest`, moving its packets into `self`. + /// Consumes packets from an Iterator, moving them into `self`. /// /// # Arguments - /// * `other` - The other `EthMRequest` to consume. + /// * `packets` - An iterator yielding mutable references to IntermediateBuffer. /// /// # Returns /// * Result indicating success or failure. - pub fn consume(&mut self, other: &mut EthMRequest<'a, N>) -> Result<()> { - let available_space = N - self.packet_number as usize; - if available_space < other.packet_number as usize { - return Err(ERROR_BUFFER_OVERFLOW.into()); - } + pub fn append(&mut self, packets: I) -> Result<()> + where + I: Iterator, + { + for buffer in packets { + if self.packet_number as usize >= N { + return Err(ERROR_BUFFER_OVERFLOW.into()); + } - for index in 0..other.packet_number as usize { - if let Some(buffer) = other.take_packet(index) { - if let Some(empty_slot) = self.first_empty_packet() { - self.set_packet(empty_slot, buffer)?; - self.packet_number += 1; - } else { - return Err(ERROR_BUFFER_OVERFLOW.into()); - } + if let Some(empty_slot) = self.first_empty_packet() { + self.set_packet(empty_slot, buffer)?; + self.packet_number += 1; + } else { + return Err(ERROR_BUFFER_OVERFLOW.into()); } } - other.packet_number = 0; Ok(()) }