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::AsRawDescriptor; 9 use base::SafeDescriptor; 10 use cros_async::AsyncWrapper; 11 use cros_async::Executor; 12 use vmm_vhost::BackendServer; 13 use vmm_vhost::Error as VhostError; 14 15 /// Performs the run loop for an already-constructor request handler. run_handler<S>(mut backend_server: BackendServer<S>, ex: &Executor) -> Result<()> where S: vmm_vhost::Backend,16pub async fn run_handler<S>(mut backend_server: BackendServer<S>, ex: &Executor) -> Result<()> 17 where 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 } 53