use std::io::Result;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use futures::{future::poll_fn, ready, stream::Stream};
use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::unix::AsyncFd;
use crate::stream::VsockStream;
use crate::SockAddr;
#[derive(Debug)]
pub struct VsockListener {
inner: AsyncFd<vsock::VsockListener>,
}
impl VsockListener {
fn new(listener: vsock::VsockListener) -> Result<Self> {
listener.set_nonblocking(true)?;
Ok(Self {
inner: AsyncFd::new(listener)?,
})
}
pub fn bind(cid: u32, port: u32) -> Result<Self> {
let l = vsock::VsockListener::bind_with_cid_port(cid, port)?;
Self::new(l)
}
pub async fn accept(&mut self) -> Result<(VsockStream, SockAddr)> {
poll_fn(|cx| self.poll_accept(cx)).await
}
pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Result<(VsockStream, SockAddr)>> {
let (inner, addr) = ready!(self.poll_accept_std(cx))?;
let inner = VsockStream::new(inner)?;
Ok((inner, addr)).into()
}
pub fn poll_accept_std(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<(vsock::VsockStream, SockAddr)>> {
loop {
let mut guard = ready!(self.inner.poll_read_ready(cx))?;
match guard.try_io(|inner| inner.get_ref().accept()) {
Ok(Ok((inner, addr))) => return Ok((inner, addr)).into(),
Ok(Err(ref e)) if e.kind() == std::io::ErrorKind::Interrupted => continue,
Ok(Err(e)) => return Err(e).into(),
Err(_would_block) => continue,
}
}
}
pub fn local_addr(&self) -> Result<SockAddr> {
self.inner.get_ref().local_addr()
}
pub fn incoming(self) -> Incoming {
Incoming::new(self)
}
}
impl FromRawFd for VsockListener {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::new(vsock::VsockListener::from_raw_fd(fd)).unwrap()
}
}
impl AsRawFd for VsockListener {
fn as_raw_fd(&self) -> RawFd {
self.inner.get_ref().as_raw_fd()
}
}
impl IntoRawFd for VsockListener {
fn into_raw_fd(self) -> RawFd {
let fd = self.inner.get_ref().as_raw_fd();
mem::forget(self);
fd
}
}
#[derive(Debug)]
pub struct Incoming {
inner: VsockListener,
}
impl Incoming {
fn new(listener: VsockListener) -> Incoming {
Incoming { inner: listener }
}
}
impl Stream for Incoming {
type Item = Result<VsockStream>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let (socket, _) = ready!(self.inner.poll_accept(cx))?;
Poll::Ready(Some(Ok(socket)))
}
}
impl AsRawFd for Incoming {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}