use std::io::{ErrorKind, Result};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use futures::ready;
use nix::sys::socket::SockAddr;
use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::PollEvented;
use tokio::stream::Stream;
use crate::stream::VsockStream;
#[derive(Debug)]
pub struct VsockListener {
io: PollEvented<super::mio::VsockListener>,
}
impl VsockListener {
fn new(listener: super::mio::VsockListener) -> Result<Self> {
let io = PollEvented::new(listener)?;
Ok(Self { io })
}
pub fn bind(addr: &SockAddr) -> Result<Self> {
let l = super::mio::VsockListener::bind(addr)?;
Self::new(l)
}
pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Result<(VsockStream, SockAddr)>> {
let (io, addr) = ready!(self.poll_accept_std(cx))?;
let io = super::mio::VsockStream::from_std(io)?;
let io = VsockStream::new(io)?;
Ok((io, addr)).into()
}
pub fn poll_accept_std(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<(vsock::VsockStream, SockAddr)>> {
ready!(self.io.poll_read_ready(cx, mio::Ready::readable()))?;
match self.io.get_ref().accept_std() {
Ok((io, addr)) => Ok((io, addr)).into(),
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
self.io.clear_read_ready(cx, mio::Ready::readable())?;
Poll::Pending
}
Err(e) => Err(e).into(),
}
}
pub fn from_std(listener: vsock::VsockListener) -> Result<Self> {
let io = super::mio::VsockListener::from_std(listener)?;
let io = PollEvented::new(io)?;
Ok(VsockListener { io })
}
pub fn local_addr(&self) -> Result<SockAddr> {
self.io.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::from_std(vsock::VsockListener::from_raw_fd(fd)).unwrap()
}
}
impl AsRawFd for VsockListener {
fn as_raw_fd(&self) -> RawFd {
self.io.get_ref().as_raw_fd()
}
}
impl IntoRawFd for VsockListener {
fn into_raw_fd(self) -> RawFd {
let fd = self.io.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()
}
}