fake_archive_accessor/fake_archive_accessor/
archivist_server.rsuse fidl::prelude::*;
use fidl_fuchsia_diagnostics::{
BatchIteratorControlHandle, BatchIteratorRequest, BatchIteratorRequestStream, FormattedContent,
};
use futures::prelude::*;
use thiserror::Error;
use tracing::warn;
use zx_status::Status as ZxStatus;
pub struct AccessorServer {
requests: BatchIteratorRequestStream,
}
impl AccessorServer {
pub fn new(requests: BatchIteratorRequestStream) -> Self {
Self { requests }
}
fn build_vmo(&self, data: &str) -> Result<Vec<FormattedContent>, ServerError> {
let size = data.len() as u64;
if size > 1024 * 1024 {
return Err(ServerError::DataTooBig);
}
let vmo = zx::Vmo::create(size).map_err(ServerError::VmoCreate)?;
vmo.write(data.as_bytes(), 0).map_err(ServerError::VmoWrite)?;
Ok(vec![FormattedContent::Json(fidl_fuchsia_mem::Buffer { vmo, size })])
}
pub async fn send(mut self, data: &str) -> Result<(), ServerError> {
if let Some(res) = self.requests.next().await {
match res? {
BatchIteratorRequest::GetNext { responder } => {
let response = self.build_vmo(data)?;
responder.send(Ok(response))?;
}
BatchIteratorRequest::WaitForReady { responder } => responder.send()?,
BatchIteratorRequest::_UnknownMethod { .. } => {
unreachable!("Unexpected method call");
}
};
if let Some(res) = self.requests.next().await {
match res? {
BatchIteratorRequest::GetNext { responder } => responder.send(Ok(vec![]))?,
BatchIteratorRequest::WaitForReady { responder } => responder.send()?,
BatchIteratorRequest::_UnknownMethod { .. } => {
unreachable!("Unexpected method call");
}
};
} else {
return Err(ServerError::TooFewBatchRequests);
}
} else {
return Err(ServerError::TooFewBatchRequests);
}
Ok(())
}
}
#[derive(Debug, Error)]
pub enum ServerError {
#[error("Inspect data for test must be <1 MB")]
DataTooBig,
#[error("The client closed the batch connection early")]
TooFewBatchRequests,
#[error("data_type must be set")]
MissingDataType,
#[error("client_selector_configuration must be set")]
MissingSelectors,
#[error("no selectors were provided")]
EmptySelectors,
#[error("requested selectors are unsupported: {}", .0)]
InvalidSelectors(&'static str),
#[error("couldn't parse/validate the provided selectors")]
ParseSelectors(#[from] selectors::Error),
#[error("format must be set")]
MissingFormat,
#[error("Only Inspect supported right now")]
UnsupportedType,
#[error("only JSON supported right now")]
UnsupportedFormat,
#[error("stream_mode must be set")]
MissingMode,
#[error("only snapshot supported right now")]
UnsupportedMode,
#[error("IPC failure")]
Ipc {
#[from]
source: fidl::Error,
},
#[error("Unable to create a VMO -- extremely unusual!")]
VmoCreate(#[source] ZxStatus),
#[error("Unable to write to VMO -- we may be OOMing")]
VmoWrite(#[source] ZxStatus),
}
impl ServerError {
pub fn close(self, control: BatchIteratorControlHandle) {
warn!("Closing BatchIterator: {}", &self);
let epitaph = match self {
ServerError::MissingDataType | ServerError::DataTooBig => ZxStatus::INVALID_ARGS,
ServerError::EmptySelectors
| ServerError::MissingSelectors
| ServerError::InvalidSelectors(_)
| ServerError::ParseSelectors(_) => ZxStatus::INVALID_ARGS,
ServerError::VmoCreate(status) | ServerError::VmoWrite(status) => status,
ServerError::MissingFormat | ServerError::MissingMode => ZxStatus::INVALID_ARGS,
ServerError::UnsupportedFormat
| ServerError::UnsupportedMode
| ServerError::UnsupportedType => ZxStatus::WRONG_TYPE,
ServerError::Ipc { .. } | ServerError::TooFewBatchRequests => ZxStatus::IO,
};
control.shutdown_with_epitaph(epitaph);
}
}