devices/virtio/vhost_user_backend/connection/sys/
linux.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5mod listener;
6mod stream;
7
8use std::future::Future;
9use std::pin::Pin;
10
11use anyhow::bail;
12use anyhow::Result;
13use base::warn;
14use base::AsRawDescriptor;
15use base::RawDescriptor;
16use cros_async::Executor;
17pub use listener::VhostUserListener;
18pub use stream::VhostUserStream;
19
20use crate::virtio::vhost_user_backend::BackendConnection;
21use crate::virtio::vhost_user_backend::VhostUserConnectionTrait;
22use crate::virtio::vhost_user_backend::VhostUserDevice;
23use crate::virtio::vhost_user_backend::VhostUserDeviceBuilder;
24
25impl BackendConnection {
26    pub fn from_opts(
27        socket: Option<&str>,
28        socket_path: Option<&str>,
29        fd: Option<RawDescriptor>,
30    ) -> Result<BackendConnection> {
31        let socket_path = if let Some(socket_path) = socket_path {
32            Some(socket_path)
33        } else if let Some(socket) = socket {
34            warn!("--socket is deprecated; please use --socket-path instead");
35            Some(socket)
36        } else {
37            None
38        };
39
40        match (socket_path, fd) {
41            (Some(socket), None) => {
42                let listener = VhostUserListener::new(socket)?;
43                Ok(BackendConnection::Listener(listener))
44            }
45            (None, Some(fd)) => {
46                let stream = VhostUserStream::new_socket_from_fd(fd)?;
47                Ok(BackendConnection::Stream(stream))
48            }
49            (Some(_), Some(_)) => bail!("Cannot specify both a socket path and a file descriptor"),
50            (None, None) => bail!("Must specify either a socket or a file descriptor"),
51        }
52    }
53
54    pub fn run_device(
55        self,
56        ex: Executor,
57        device: Box<dyn VhostUserDeviceBuilder>,
58    ) -> anyhow::Result<()> {
59        match self {
60            BackendConnection::Listener(listener) => listener.run_device(ex, device),
61            BackendConnection::Stream(stream) => stream.run_device(ex, device),
62        }
63    }
64
65    pub fn run_backend<'e>(
66        self,
67        backend: impl VhostUserDevice + 'static,
68        ex: &'e Executor,
69    ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>> {
70        match self {
71            BackendConnection::Listener(listener) => listener.run_backend(backend, ex),
72            BackendConnection::Stream(stream) => stream.run_backend(backend, ex),
73        }
74    }
75}
76
77impl AsRawDescriptor for BackendConnection {
78    fn as_raw_descriptor(&self) -> RawDescriptor {
79        match self {
80            BackendConnection::Listener(listener) => listener.as_raw_descriptor(),
81            BackendConnection::Stream(stream) => stream.as_raw_descriptor(),
82        }
83    }
84}