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 5 mod listener; 6 mod stream; 7 8 use std::future::Future; 9 use std::pin::Pin; 10 11 use anyhow::bail; 12 use anyhow::Result; 13 use base::warn; 14 use base::AsRawDescriptor; 15 use base::RawDescriptor; 16 use cros_async::Executor; 17 pub use listener::VhostUserListener; 18 pub use stream::VhostUserStream; 19 20 use crate::virtio::vhost::user::device::BackendConnection; 21 use crate::virtio::vhost::user::VhostUserConnectionTrait; 22 use crate::virtio::vhost::user::VhostUserDevice; 23 use crate::virtio::vhost::user::VhostUserDeviceBuilder; 24 25 impl BackendConnection { from_opts( socket: Option<&str>, socket_path: Option<&str>, fd: Option<RawDescriptor>, ) -> Result<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 run_device( self, ex: Executor, device: Box<dyn VhostUserDeviceBuilder>, ) -> anyhow::Result<()>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 run_backend<'e>( self, backend: impl VhostUserDevice + 'static, ex: &'e Executor, ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>>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 77 impl AsRawDescriptor for BackendConnection { as_raw_descriptor(&self) -> RawDescriptor78 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 } 85