Files
boxmaker/crates/memoryd/src/honcho/state.rs
T

46 lines
1.8 KiB
Rust

//! Asking `brokerd` for a session's state on its `state.sock` (M5c spec, section 7): one question
//! per connection, one final answer, as on every socket between the roles.
use std::os::unix::net::UnixStream;
use std::path::Path;
use std::time::Duration;
use bxcore::{
Envelope, Message, PROTOCOL_VERSION, SessionId, SessionState, SessionStateReply, read_frame,
write_frame,
};
/// How long `brokerd` may leave the connection without a byte, sending or answering.
pub const WAIT: Duration = Duration::from_secs(5);
/// The runbook entry for a `brokerd` that does not answer.
pub const RUNBOOK: &str = "see docs/runbook.md#broker-state-unavailable";
/// `brokerd`'s answer for `session`, asked on `socket`. `wait` is the read and the write timeout;
/// the connect has none, and fails at once when nothing listens. Any error, an error frame
/// included, is `Err` with one line that names the socket or `brokerd`.
pub fn ask(
socket: &Path,
session: &SessionId,
wait: Duration,
) -> Result<SessionStateReply, String> {
let line = |e: &dyn std::fmt::Display| format!("{}: {e}", socket.display());
let mut stream = UnixStream::connect(socket).map_err(|e| line(&e))?;
stream.set_read_timeout(Some(wait)).map_err(|e| line(&e))?;
stream.set_write_timeout(Some(wait)).map_err(|e| line(&e))?;
let question = Envelope {
v: PROTOCOL_VERSION,
id: 1,
r#final: true,
msg: Message::SessionState(SessionState {
session: session.clone(),
}),
};
write_frame(&mut stream, &question).map_err(|e| line(&e))?;
match read_frame(&mut stream).map_err(|e| line(&e))?.msg {
Message::SessionStateReply(reply) => Ok(reply),
Message::Error(e) => Err(format!("brokerd: {}", e.detail)),
_ => Err("brokerd answered with the wrong message".to_string()),
}
}