pub struct BackendServer<S: Backend> {
    connection: Connection<FrontendReq>,
    backend: S,
    virtio_features: u64,
    acked_virtio_features: u64,
    protocol_features: VhostUserProtocolFeatures,
    acked_protocol_features: u64,
    reply_ack_enabled: bool,
}
Expand description

Handles requests from a vhost-user connection by dispatching them to [Backend] methods.

Fields§

§connection: Connection<FrontendReq>

Underlying connection for communication.

§backend: S§virtio_features: u64§acked_virtio_features: u64§protocol_features: VhostUserProtocolFeatures§acked_protocol_features: u64§reply_ack_enabled: bool

Sending ack for messages without payload.

Implementations§

source§

impl<S: Backend> BackendServer<S>

source

pub fn from_stream(socket: SystemStream, backend: S) -> Self

Create a backend server from a connected socket.

source§

impl<S: Backend> BackendServer<S>

source

pub fn new(connection: Connection<FrontendReq>, backend: S) -> Self

source

pub fn recv_header( &mut self ) -> Result<(VhostUserMsgHeader<FrontendReq>, Vec<File>)>

Receives and validates a vhost-user message header and optional files.

Since the length of vhost-user messages are different among message types, regular vhost-user messages are sent via an underlying communication channel in stream mode. (e.g. SOCK_STREAM in UNIX) So, the logic of receiving and handling a message consists of the following steps:

  1. Receives a message header and optional attached file.
  2. Validates the message header.
  3. Check if optional payloads is expected.
  4. Wait for the optional payloads.
  5. Receives optional payloads.
  6. Processes the message.

This method BackendServer::recv_header() is in charge of the step (1) and (2), BackendServer::needs_wait_for_payload() is (3), and BackendServer::process_message() is (5) and (6). We need to have the three method separately for multi-platform supports; BackendServer::recv_header() and BackendServer::process_message() need to be separated because the way of waiting for incoming messages differs between Unix and Windows so it’s the caller’s responsibility to wait before BackendServer::process_message().

Note that some vhost-user protocol variant such as VVU doesn’t assume stream mode. In this case, a message header and its body are sent together so the step (4) is skipped. We handle this case in BackendServer::needs_wait_for_payload().

The following pseudo code describes how a caller should process incoming vhost-user messages:

loop {
  // block until a message header comes.
  // The actual code differs, depending on platforms.
  connection.wait_readable().unwrap();

  // (1) and (2)
  let (hdr, files) = backend_server.recv_header();

  // (3)
  if backend_server.needs_wait_for_payload(&hdr) {
    // (4) block until a payload comes if needed.
    connection.wait_readable().unwrap();
  }

  // (5) and (6)
  backend_server.process_message(&hdr, &files).unwrap();
}
source

pub fn needs_wait_for_payload( &self, hdr: &VhostUserMsgHeader<FrontendReq> ) -> bool

Returns whether the caller needs to wait for the incoming message before calling BackendServer::process_message.

See BackendServer::recv_header’s doc comment for the usage.

source

pub fn process_message( &mut self, hdr: VhostUserMsgHeader<FrontendReq>, files: Vec<File> ) -> Result<()>

Main entrance to request from the communication channel.

Receive and handle one incoming request message from the frontend. See BackendServer::recv_header’s doc comment for the usage.

§Return:
  • Ok(()): one request was successfully handled.
  • Err(ClientExit): the frontend closed the connection properly. This isn’t an actual failure.
  • Err(Disconnect): the connection was closed unexpectedly.
  • Err(InvalidMessage): the vmm sent a illegal message.
  • other errors: failed to handle a request.
source

fn new_reply_header<T: Sized>( &self, req: &VhostUserMsgHeader<FrontendReq>, payload_size: usize ) -> Result<VhostUserMsgHeader<FrontendReq>>

source

fn send_ack_message( &mut self, req: &VhostUserMsgHeader<FrontendReq>, success: bool ) -> Result<()>

Sends reply back to Vhost frontend in response to a message.

source

fn send_reply_message<T: Sized + AsBytes>( &mut self, req: &VhostUserMsgHeader<FrontendReq>, msg: &T ) -> Result<()>

source

fn send_reply_with_payload<T: Sized + AsBytes>( &mut self, req: &VhostUserMsgHeader<FrontendReq>, msg: &T, payload: &[u8] ) -> Result<()>

source

fn set_mem_table( &mut self, hdr: &VhostUserMsgHeader<FrontendReq>, size: usize, buf: &[u8], files: Vec<File> ) -> Result<()>

source

fn get_config( &mut self, hdr: &VhostUserMsgHeader<FrontendReq>, buf: &[u8] ) -> Result<()>

source

fn set_config(&mut self, buf: &[u8]) -> Result<()>

source

fn set_backend_req_fd(&mut self, files: Vec<File>) -> Result<()>

source

fn handle_vring_fd_request( &mut self, buf: &[u8], files: Vec<File> ) -> Result<(u8, Option<File>)>

Parses an incoming |SET_VRING_KICK| or |SET_VRING_CALL| message into a Vring number and an fd.

source

fn check_request_size( &self, hdr: &VhostUserMsgHeader<FrontendReq>, size: usize, expected: usize ) -> Result<()>

source

fn check_attached_files( &self, hdr: &VhostUserMsgHeader<FrontendReq>, files: &[File] ) -> Result<()>

source

fn extract_request_body<T: Sized + FromBytes + VhostUserMsgValidator>( &self, hdr: &VhostUserMsgHeader<FrontendReq>, size: usize, buf: &[u8] ) -> Result<T>

source

fn update_reply_ack_flag(&mut self)

Trait Implementations§

source§

impl<S: Backend> AsRawDescriptor for BackendServer<S>

source§

fn as_raw_descriptor(&self) -> RawDescriptor

Returns the underlying raw descriptor. Read more
source§

impl<S: Backend> AsRef<S> for BackendServer<S>

source§

fn as_ref(&self) -> &S

Converts this type into a shared reference of the (usually inferred) input type.

Auto Trait Implementations§

§

impl<S> !RefUnwindSafe for BackendServer<S>

§

impl<S> Send for BackendServer<S>
where S: Send,

§

impl<S> !Sync for BackendServer<S>

§

impl<S> Unpin for BackendServer<S>
where S: Unpin,

§

impl<S> UnwindSafe for BackendServer<S>
where S: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> AsRawDescriptors for T
where T: AsRawDescriptor,

§

fn as_raw_descriptors(&self) -> Vec<i32>

Returns the underlying raw descriptors. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.