mod listener;
mod stream;
use std::future::Future;
use std::pin::Pin;
use anyhow::bail;
use anyhow::Result;
use base::warn;
use base::AsRawDescriptor;
use base::RawDescriptor;
use cros_async::Executor;
pub use listener::VhostUserListener;
pub use stream::VhostUserStream;
use crate::virtio::vhost::user::device::BackendConnection;
use crate::virtio::vhost::user::VhostUserConnectionTrait;
use crate::virtio::vhost::user::VhostUserDevice;
use crate::virtio::vhost::user::VhostUserDeviceBuilder;
impl BackendConnection {
pub fn from_opts(
socket: Option<&str>,
socket_path: Option<&str>,
fd: Option<RawDescriptor>,
) -> Result<BackendConnection> {
let socket_path = if let Some(socket_path) = socket_path {
Some(socket_path)
} else if let Some(socket) = socket {
warn!("--socket is deprecated; please use --socket-path instead");
Some(socket)
} else {
None
};
match (socket_path, fd) {
(Some(socket), None) => {
let listener = VhostUserListener::new(socket)?;
Ok(BackendConnection::Listener(listener))
}
(None, Some(fd)) => {
let stream = VhostUserStream::new_socket_from_fd(fd)?;
Ok(BackendConnection::Stream(stream))
}
(Some(_), Some(_)) => bail!("Cannot specify both a socket path and a file descriptor"),
(None, None) => bail!("Must specify either a socket or a file descriptor"),
}
}
pub fn run_device(
self,
ex: Executor,
device: Box<dyn VhostUserDeviceBuilder>,
) -> anyhow::Result<()> {
match self {
BackendConnection::Listener(listener) => listener.run_device(ex, device),
BackendConnection::Stream(stream) => stream.run_device(ex, device),
}
}
pub fn run_backend<'e>(
self,
backend: impl VhostUserDevice + 'static,
ex: &'e Executor,
) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>> {
match self {
BackendConnection::Listener(listener) => listener.run_backend(backend, ex),
BackendConnection::Stream(stream) => stream.run_backend(backend, ex),
}
}
}
impl AsRawDescriptor for BackendConnection {
fn as_raw_descriptor(&self) -> RawDescriptor {
match self {
BackendConnection::Listener(listener) => listener.as_raw_descriptor(),
BackendConnection::Stream(stream) => stream.as_raw_descriptor(),
}
}
}