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 pub mod sys; 6 use std::any::Any; 7 use std::pin::Pin; 8 9 use cros_async::Executor; 10 use futures::Future; 11 12 use crate::virtio::vhost::user::device::handler::DeviceRequestHandler; 13 use crate::virtio::vhost::user::device::handler::VhostUserDevice; 14 use crate::virtio::vhost::user::VhostUserDeviceBuilder; 15 use crate::virtio::vhost::user::VhostUserListener; 16 use crate::virtio::vhost::user::VhostUserStream; 17 18 pub enum BackendConnection { 19 Listener(VhostUserListener), 20 Stream(VhostUserStream), 21 } 22 23 /// Trait that the platform-specific type `VhostUserConnection` needs to implement. It contains all 24 /// the methods that are ok to call from non-platform specific code. 25 pub trait VhostUserConnectionTrait { 26 /// Take and return resources owned by the parent process in case of a incoming fork. 27 /// 28 /// This method needs to be called only if you are going to use the connection in a jailed child 29 /// process. In this case, the connection will belong to the child and the parent will drop it, 30 /// but the child may lack the rights to drop some resources created at construction time. One 31 /// such example is the socket file of a regular vhost-user device, that cannot be dropped by 32 /// the child unless it gets extra permissions. 33 /// 34 /// This method returns an opaque object that, upon being dropped, will free these resources. 35 /// That way, the child process does not need extra rights to clear them, and the parent can 36 /// drop the connection after forking and just need to keep that object alive until the child 37 /// exits to do housekeeping properly. 38 /// 39 /// The default implementation returns nothing as that's what most connection would need anyway. take_parent_process_resources(&mut self) -> Option<Box<dyn Any>>40 fn take_parent_process_resources(&mut self) -> Option<Box<dyn Any>> { 41 None 42 } 43 44 /// Returns a `Future` that processes requests for `handler`. The future exits when the 45 /// front-end side disconnects or an error occurs. run_req_handler<'e>( self, handler: Box<dyn vmm_vhost::Backend>, ex: &'e Executor, ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>>46 fn run_req_handler<'e>( 47 self, 48 handler: Box<dyn vmm_vhost::Backend>, 49 ex: &'e Executor, 50 ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>>; 51 52 /// Returns a `Future` that will process requests from `backend` when polled. The future exits 53 /// when the front-end side disconnects or an error occurs. 54 /// 55 /// This is a legacy way to run devices - prefer `run_device`. run_backend<'e>( self, backend: impl VhostUserDevice + 'static, ex: &'e Executor, ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>> where Self: Sized,56 fn run_backend<'e>( 57 self, 58 backend: impl VhostUserDevice + 'static, 59 ex: &'e Executor, 60 ) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + 'e>> 61 where 62 Self: Sized, 63 { 64 self.run_req_handler(Box::new(DeviceRequestHandler::new(backend)), ex) 65 } 66 67 /// Start processing requests for a `VhostUserDevice` on `connection`. Returns when the 68 /// front-end side disconnects or an error occurs. run_device(self, ex: Executor, device: Box<dyn VhostUserDeviceBuilder>) -> anyhow::Result<()> where Self: Sized,69 fn run_device(self, ex: Executor, device: Box<dyn VhostUserDeviceBuilder>) -> anyhow::Result<()> 70 where 71 Self: Sized, 72 { 73 ex.run_until(self.run_req_handler(device.build(&ex).unwrap(), &ex))? 74 } 75 } 76