Path: blob/main/devices/src/virtio/vhost_user_backend/handler/sys/windows.rs
5394 views
// Copyright 2022 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use anyhow::anyhow;5use anyhow::Context;6use anyhow::Result;7use base::info;8use base::named_pipes::BlockingMode;9use base::named_pipes::FramingMode;10use base::named_pipes::PipeConnection;11use base::CloseNotifier;12use base::Event;13use base::RawDescriptor;14use base::ReadNotifier;15use base::Tube;16use cros_async::AsyncResult;17use cros_async::EventAsync;18use cros_async::Executor;19use futures::pin_mut;20use futures::select;21use futures::FutureExt;22use tube_transporter::TubeTransferDataList;23use tube_transporter::TubeTransporterReader;24use vmm_vhost::message::FrontendReq;25use vmm_vhost::message::VhostUserMsgHeader;26use vmm_vhost::BackendServer;27use vmm_vhost::Connection;2829pub fn read_from_tube_transporter(30raw_transport_tube: RawDescriptor,31) -> anyhow::Result<TubeTransferDataList> {32let tube_transporter = TubeTransporterReader::create_tube_transporter_reader(33// SAFETY:34// Safe because we know that raw_transport_tube is valid (passed by inheritance), and that35// the blocking & framing modes are accurate because we create them ourselves in the36// broker.37unsafe {38PipeConnection::from_raw_descriptor(39raw_transport_tube,40FramingMode::Message,41BlockingMode::Wait,42)43},44);4546tube_transporter.read_tubes().map_err(anyhow::Error::msg)47}4849/// Runs the generic handler over a given vhost-user device backend.50pub async fn run_handler(51handler: Box<dyn vmm_vhost::Backend>,52vhost_user_tube: Tube,53exit_event: Event,54ex: &Executor,55) -> Result<()> {56let read_notifier = vhost_user_tube57.get_read_notifier_event()58.try_clone()59.context("failed to clone event")?;60let close_notifier = vhost_user_tube61.get_close_notifier_event()62.try_clone()63.context("failed to clone event")?;6465let read_event = EventAsync::new_without_reset(read_notifier, ex)66.context("failed to create an async event")?;67let close_event = EventAsync::new_without_reset(close_notifier, ex)68.context("failed to create an async event")?;69let exit_event = EventAsync::new(exit_event, ex).context("failed to create an async event")?;7071let mut backend_server = BackendServer::new(Connection::from(vhost_user_tube), handler);7273let read_event_fut = read_event.next_val().fuse();74let close_event_fut = close_event.next_val().fuse();75let exit_event_fut = exit_event.next_val().fuse();76pin_mut!(read_event_fut);77pin_mut!(close_event_fut);78pin_mut!(exit_event_fut);7980let mut pending_header: Option<(VhostUserMsgHeader, Vec<std::fs::File>)> = None;81loop {82select! {83_read_res = read_event_fut => {84match pending_header.take() {85None => {86let (hdr, files) = backend_server87.recv_header()88.context("failed to handle a vhost-user request")?;89if backend_server.needs_wait_for_payload(&hdr) {90// Wait for the message body being notified.91pending_header = Some((hdr, files));92} else {93backend_server94.process_message(hdr, files)95.context("failed to handle a vhost-user request")?;96}97}98Some((hdr, files)) => {99backend_server100.process_message(hdr, files)101.context("failed to handle a vhost-user request")?;102}103}104read_event_fut.set(read_event.next_val().fuse());105}106// Tube closed event.107_close_res = close_event_fut => {108info!("exit run loop: got close event");109return Ok(())110}111// Broker exit event.112_exit_res = exit_event_fut => {113info!("exit run loop: got exit event");114return Ok(())115}116}117}118}119120121