usecrate::codec::UserError; usecrate::error::Reason; usecrate::frame; usecrate::proto::*; use std::task::{Context, Poll};
#[derive(Debug)] pub(crate) struct Settings { /// Our local SETTINGS sync state with the remote.
local: Local, /// Received SETTINGS frame pending processing. The ACK must be written to /// the socket first then the settings applied **before** receiving any /// further frames.
remote: Option<frame::Settings>,
}
#[derive(Debug)] enum Local { /// We want to send these SETTINGS to the remote when the socket is ready.
ToSend(frame::Settings), /// We have sent these SETTINGS and are waiting for the remote to ACK /// before we apply them.
WaitingAck(frame::Settings), /// Our local settings are in sync with the remote.
Synced,
}
impl Settings { pub(crate) fn new(local: frame::Settings) -> Self {
Settings { // We assume the initial local SETTINGS were flushed during // the handshake process.
local: Local::WaitingAck(local),
remote: None,
}
}
iflet Some(max) = local.max_frame_size() {
codec.set_max_recv_frame_size(max as usize);
}
iflet Some(max) = local.max_header_list_size() {
codec.set_max_recv_header_list_size(max as usize);
}
iflet Some(val) = local.header_table_size() {
codec.set_recv_header_table_size(val as usize);
}
streams.apply_local_settings(local)?; self.local = Local::Synced;
Ok(())
}
Local::ToSend(..) | Local::Synced => { // We haven't sent any SETTINGS frames to be ACKed, so // this is very bizarre! Remote is either buggy or malicious.
proto_err!(conn: "received unexpected settings ack");
Err(Error::library_go_away(Reason::PROTOCOL_ERROR))
}
}
} else { // We always ACK before reading more frames, so `remote` should // always be none!
assert!(self.remote.is_none()); self.remote = Some(frame);
Ok(())
}
}