xref: /aosp_15_r20/external/crosvm/devices/src/virtio/vhost/user/device/connection.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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