devices/virtio/vhost_user_backend/connection/sys/linux/
stream.rs1use std::fs;
6use std::os::unix::fs::FileTypeExt;
7use std::os::unix::net::UnixStream;
8use std::path::Path;
9use std::path::PathBuf;
10use std::pin::Pin;
11
12use anyhow::anyhow;
13use base::safe_descriptor_from_cmdline_fd;
14use base::AsRawDescriptor;
15use base::RawDescriptor;
16use cros_async::Executor;
17use futures::Future;
18use futures::FutureExt;
19use vmm_vhost::BackendServer;
20use vmm_vhost::Connection;
21
22use crate::virtio::vhost_user_backend::connection::VhostUserConnectionTrait;
23use crate::virtio::vhost_user_backend::handler::sys::linux::run_handler;
24
25pub struct VhostUserStream(UnixStream);
27
28fn path_is_socket(path: &Path) -> bool {
29 match fs::metadata(path) {
30 Ok(metadata) => metadata.file_type().is_socket(),
31 Err(_) => false, }
33}
34
35impl VhostUserStream {
36 pub fn new_socket_from_fd(socket_fd: RawDescriptor) -> anyhow::Result<Self> {
44 let path = PathBuf::from(format!("/proc/self/fd/{socket_fd}"));
45 if !path_is_socket(&path) {
46 return Err(anyhow!("fd {} is not a socket", socket_fd));
47 }
48
49 let safe_fd = safe_descriptor_from_cmdline_fd(&socket_fd)?;
50
51 let stream = UnixStream::from(safe_fd);
52
53 Ok(VhostUserStream(stream))
54 }
55}
56
57impl VhostUserConnectionTrait for VhostUserStream {
58 fn run_req_handler<'e>(
59 self,
60 handler: Box<dyn vmm_vhost::Backend>,
61 ex: &'e Executor,
62 ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>> {
63 async { stream_run_with_handler(self.0, handler, ex).await }.boxed_local()
64 }
65}
66
67impl AsRawDescriptor for VhostUserStream {
68 fn as_raw_descriptor(&self) -> RawDescriptor {
69 self.0.as_raw_descriptor()
70 }
71}
72
73async fn stream_run_with_handler(
74 stream: UnixStream,
75 handler: Box<dyn vmm_vhost::Backend>,
76 ex: &Executor,
77) -> anyhow::Result<()> {
78 let req_handler = BackendServer::new(Connection::try_from(stream)?, handler);
79 run_handler(req_handler, ex).await
80}