nfq-rs
nfq-rs copied to clipboard
Add try_verdict method which doesn't consume the passed msg in case you need…
This patch adds a try_verdict method that only takes a reference to a Message and doesn't consume it.
I needed this, because I am wrapping a Queue object in an AsyncFd and set it to non-blocking. In case the write to issue the verdict fails with EWOULDBLOCK, the passed in Message is gone, because it is moved into the verdict method and I can't retry later.
The naming of try_verdict is debatable, but naming things is one of the hardest problems in computer science, I guess. I am open for better name suggestions.
Here is some code that I implemented to make a Queue async so that it's clearer why I need that new method:
use std::{fmt, io};
use nfq::{Message, Queue};
use tokio::io::unix::AsyncFd;
pub struct AsyncQueue {
inner: AsyncFd<Queue>,
}
impl fmt::Debug for AsyncQueue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AsyncQueue").finish()
}
}
impl AsyncQueue {
pub fn new(mut queue: Queue) -> io::Result<Self> {
queue.set_nonblocking(true);
Ok(Self {
inner: AsyncFd::new(queue).expect("Unable to create AsyncFd for nfqueue"),
})
}
pub async fn recv(&mut self) -> io::Result<nfq::Message> {
loop {
let mut guard = self.inner.readable_mut().await?;
match guard.try_io(|inner| inner.get_mut().recv()) {
Ok(result) => return result,
Err(_would_block) => continue,
}
}
}
pub async fn verdict(&mut self, msg: Message) -> io::Result<()> {
loop {
let mut guard = self.inner.writable_mut().await?;
match guard.try_io(|inner| inner.get_mut().try_verdict(&msg)) {
Ok(result) => return result,
Err(_would_block) => continue,
}
}
}
}