Skip to content

Commit

Permalink
If server couldn't set buffer size, relay a warning back to the client
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyscot committed Sep 27, 2024
1 parent 88ba938 commit 1062934
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 13 deletions.
1 change: 1 addition & 0 deletions qcp/schema/control.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ struct ServerMessage {
port @0: UInt16; # UDP port the server has bound to
cert @1: Data; # Server's self-signed certificate (DER)
name @2: Text; # Name in the server cert (this saves us having to unpick it from the certificate)
warning @3: Text; # If present, a warning message to be relayed to a human
}
8 changes: 6 additions & 2 deletions qcp/src/client/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,15 @@ pub async fn client_main(args: ClientArgs, progress: MultiProgress) -> anyhow::R
trace!("waiting for server message");
let server_message = ServerMessage::read(&mut server_output).await?;
debug!(
"Got server message; cert length {}, port {}, hostname {}",
"Got server message; cert length {}, port {}, hostname {}, warning {:?}",
server_message.cert.len(),
server_message.port,
server_message.name
server_message.name,
server_message.warning
);
if let Some(w) = server_message.warning {
warn!("Remote endpoint warning: {w}");
}

let server_address_port = match server_address {
std::net::IpAddr::V4(ip) => SocketAddrV4::new(ip, server_message.port).into(),
Expand Down
27 changes: 25 additions & 2 deletions qcp/src/protocol/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,19 @@ pub struct ServerMessage {
pub cert: Vec<u8>,
/// Server's idea of its hostname (should match the certificate)
pub name: String,
/// Server warning message (if any)
pub warning: Option<String>,
}

impl ServerMessage {
// This is weirdly asymmetric to avoid needless allocs.
pub async fn write<W>(write: &mut W, port: u16, cert: &[u8], name: &str) -> Result<()>
pub async fn write<W>(
write: &mut W,
port: u16,
cert: &[u8],
name: &str,
warning: Option<&str>,
) -> Result<()>
where
W: tokio::io::AsyncWrite + Unpin,
{
Expand All @@ -90,6 +98,9 @@ impl ServerMessage {
builder.set_port(port);
builder.set_cert(cert);
builder.set_name(name);
if let Some(w) = warning {
builder.set_warning(w);
}
capnp_futures::serialize::write_message(write.compat_write(), &msg).await?;
Ok(())
}
Expand All @@ -104,7 +115,18 @@ impl ServerMessage {
let cert = msg_reader.get_cert()?.to_vec();
let name = msg_reader.get_name()?.to_str()?.to_string();
let port = msg_reader.get_port();
Ok(Self { port, cert, name })
let warning = msg_reader.get_warning()?.to_str()?.to_string();
let warning = if warning.len() == 0 {
None
} else {
Some(warning)
};
Ok(Self {
port,
cert,
name,
warning,
})
}
}

Expand Down Expand Up @@ -154,6 +176,7 @@ mod tests {
port,
cert,
name: "localhost".to_string(),
warning: Some("foo".to_string()),
})
}

Expand Down
17 changes: 8 additions & 9 deletions qcp/src/server/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ pub async fn server_main(args: &ServerArgs) -> anyhow::Result<()> {

// TODO: Allow port to be specified
let credentials = crate::cert::Credentials::generate()?;
let endpoint = create_endpoint(&credentials, client_message)?;
let (endpoint, warning) = create_endpoint(&credentials, client_message)?;
let local_addr = endpoint.local_addr()?;
debug!("Local address is {local_addr}");
ServerMessage::write(
&mut stdout,
local_addr.port(),
&credentials.certificate,
&credentials.hostname,
warning.as_deref(),
)
.await?;
stdout.flush().await?;
Expand Down Expand Up @@ -113,7 +114,7 @@ pub async fn server_main(args: &ServerArgs) -> anyhow::Result<()> {
fn create_endpoint(
credentials: &Credentials,
client_message: ClientMessage,
) -> anyhow::Result<quinn::Endpoint> {
) -> anyhow::Result<(quinn::Endpoint, Option<String>)> {
let client_cert: CertificateDer<'_> = client_message.cert.into();

let mut root_store = RootCertStore::empty();
Expand Down Expand Up @@ -142,17 +143,15 @@ fn create_endpoint(
}
};
let socket = std::net::UdpSocket::bind(addr)?;
let _ = util::socket::set_udp_buffer_sizes(&socket)?.inspect(|s| warn!("{s}"));
let warning = util::socket::set_udp_buffer_sizes(&socket)?.inspect(|s| warn!("{s}"));

// SOMEDAY: allow user to specify max_udp_payload_size in endpoint config, to support jumbo frames
let runtime =
quinn::default_runtime().ok_or_else(|| anyhow::anyhow!("no async runtime found"))?;
Ok(quinn::Endpoint::new(
EndpointConfig::default(),
Some(config),
socket,
runtime,
)?)
Ok((
quinn::Endpoint::new(EndpointConfig::default(), Some(config), socket, runtime)?,
warning,
))
}

async fn handle_connection(conn: quinn::Incoming, args: ServerArgs) -> anyhow::Result<()> {
Expand Down

0 comments on commit 1062934

Please sign in to comment.