devices/virtio/vhost_user_backend/handler/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
5use anyhow::Context;
6use anyhow::Result;
7use base::info;
8use base::AsRawDescriptor;
9use base::SafeDescriptor;
10use cros_async::AsyncWrapper;
11use cros_async::Executor;
12use vmm_vhost::BackendServer;
13use vmm_vhost::Error as VhostError;
14
15/// Performs the run loop for an already-constructor request handler.
16pub async fn run_handler<S>(mut backend_server: BackendServer<S>, ex: &Executor) -> Result<()>
17where
18    S: vmm_vhost::Backend,
19{
20    let h = SafeDescriptor::try_from(&backend_server as &dyn AsRawDescriptor)
21        .map(AsyncWrapper::new)
22        .context("failed to get safe descriptor for handler")?;
23    let handler_source = ex
24        .async_from(h)
25        .context("failed to create an async source")?;
26
27    loop {
28        handler_source
29            .wait_readable()
30            .await
31            .context("failed to wait for the handler to become readable")?;
32        let (hdr, files) = match backend_server.recv_header() {
33            Ok((hdr, files)) => (hdr, files),
34            Err(VhostError::ClientExit) => {
35                info!("vhost-user connection closed");
36                // Exit as the client closed the connection.
37                return Ok(());
38            }
39            Err(e) => {
40                return Err(e.into());
41            }
42        };
43
44        if backend_server.needs_wait_for_payload(&hdr) {
45            handler_source
46                .wait_readable()
47                .await
48                .context("failed to wait for the handler to become readable")?;
49        }
50        backend_server.process_message(hdr, files)?;
51    }
52}