• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use anyhow::Context;
6 use anyhow::Result;
7 use base::info;
8 use base::CloseNotifier;
9 use base::ReadNotifier;
10 use base::SafeDescriptor;
11 use base::Tube;
12 use cros_async::EventAsync;
13 use cros_async::Executor;
14 use futures::channel::oneshot;
15 use futures::pin_mut;
16 use futures::select_biased;
17 use futures::FutureExt;
18 use vmm_vhost::message::VhostUserProtocolFeatures;
19 
20 use crate::virtio::vhost_user_frontend::handler::BackendReqHandler;
21 use crate::virtio::vhost_user_frontend::handler::BackendReqHandlerImpl;
22 use crate::virtio::vhost_user_frontend::Error;
23 use crate::virtio::vhost_user_frontend::Result as VhostResult;
24 
create_backend_req_handler( h: BackendReqHandlerImpl, backend_pid: Option<u32>, ) -> VhostResult<(BackendReqHandler, SafeDescriptor)>25 pub fn create_backend_req_handler(
26     h: BackendReqHandlerImpl,
27     backend_pid: Option<u32>,
28 ) -> VhostResult<(BackendReqHandler, SafeDescriptor)> {
29     let backend_pid = backend_pid.expect("tube needs target pid for backend requests");
30     vmm_vhost::FrontendServer::with_tube(h, backend_pid).map_err(Error::CreateBackendReqHandler)
31 }
32 
33 /// Process requests from the backend.
34 ///
35 /// If `stop_rx` is sent a value, the function will exit at a well defined point so that
36 /// `run_backend_request_handler` can be re-invoked to resume processing the connection.
run_backend_request_handler( ex: &Executor, handler: &mut BackendReqHandler, mut stop_rx: oneshot::Receiver<()>, ) -> Result<()>37 pub async fn run_backend_request_handler(
38     ex: &Executor,
39     handler: &mut BackendReqHandler,
40     mut stop_rx: oneshot::Receiver<()>,
41 ) -> Result<()> {
42     let read_notifier = handler.get_read_notifier();
43     let close_notifier = handler.get_close_notifier();
44 
45     let read_event = EventAsync::clone_raw_without_reset(read_notifier, ex)
46         .context("failed to create an async event")?;
47     let close_event = EventAsync::clone_raw_without_reset(close_notifier, ex)
48         .context("failed to create an async event")?;
49 
50     let read_event_fut = read_event.next_val().fuse();
51     let close_event_fut = close_event.next_val().fuse();
52     pin_mut!(read_event_fut);
53     pin_mut!(close_event_fut);
54 
55     loop {
56         select_biased! {
57             _ = stop_rx => return Ok(()),
58             _read_res = read_event_fut => {
59                 handler
60                     .handle_request()
61                     .context("failed to handle a vhost-user request")?;
62                 read_event_fut.set(read_event.next_val().fuse());
63             }
64             // Tube closed event.
65             _close_res = close_event_fut => {
66                 info!("exit run loop: got close event");
67                 return Ok(())
68             }
69         }
70     }
71 }
72