metrale_gpu_sys/
handshake.rs1use anyhow::{Context, Result, bail};
21use std::io::{Read, Write};
22
23use crate::wire::{CacheServerParams, STATUS_OK, VerbsClientParams};
24
25pub fn write_n_rails<W: Write>(w: &mut W, n: usize) -> Result<()> {
27 w.write_all(&[n as u8]).context("send n_rails")?;
28 Ok(())
29}
30
31pub fn read_rw_server_params<R: Read>(
35 r: &mut R,
36 want: usize,
37 peer: &str,
38) -> Result<Vec<CacheServerParams>> {
39 let mut b1 = [0u8; 1];
40 if let Err(e) = r.read_exact(&mut b1) {
41 if e.kind() == std::io::ErrorKind::UnexpectedEof {
45 bail!(
46 "{peer} closed the connection during the rail handshake without sending rail \
47 params. The peer REJECTED this client — read ITS log for the reason. Most \
48 common: the arena this client requested exceeds the peer's --max-blade-gb \
49 cap (peer logs \"paging blade cap\"); also possible: a blob_bytes/kind \
50 mismatch against an arena a prior client already fixed."
51 );
52 }
53 return Err(e).context("read peer n_rails");
54 }
55 if b1[0] as usize != want {
56 bail!("{peer} granted {} rails, wanted {want}", b1[0]);
57 }
58 let mut server = Vec::with_capacity(want);
59 for _ in 0..want {
60 server
61 .push(CacheServerParams::read_from(r).with_context(|| format!("read {peer} params"))?);
62 }
63 Ok(server)
64}
65
66pub fn write_client_params<W: Write>(w: &mut W, ids: &[(u32, u32, [u8; 16])]) -> Result<()> {
69 w.write_all(&[ids.len() as u8])
70 .context("send client n_rails")?;
71 for &(qpn, psn, gid) in ids {
72 VerbsClientParams { qpn, psn, gid }
73 .write_to(w)
74 .context("send verbs client params")?;
75 }
76 Ok(())
77}
78
79pub fn read_ack<R: Read>(r: &mut R, peer: &str) -> Result<()> {
81 let mut ack = [0u8; 1];
82 r.read_exact(&mut ack).context("read verbs ready ack")?;
83 if ack[0] != STATUS_OK {
84 bail!("{peer} refused connection (ack {})", ack[0]);
85 }
86 Ok(())
87}