Merge PR #1: IRC word-boundary splitting + flush (spqrz)

This commit is contained in:
Kent Overstreet 2026-04-11 18:13:26 -04:00
commit ed896d4e83

View file

@ -139,7 +139,12 @@ impl AsyncWriter for TlsWriter {
line: &str,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = io::Result<()>> + '_>> {
let data = format!("{line}\r\n");
Box::pin(async move { self.inner.write_all(data.as_bytes()).await })
Box::pin(async move {
self.inner.write_all(data.as_bytes()).await?;
// Unconfirmed reports that some servers require
// multiple lines to be in separate packets
self.inner.flush().await
})
}
}
@ -153,7 +158,12 @@ impl AsyncWriter for PlainWriter {
line: &str,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = io::Result<()>> + '_>> {
let data = format!("{line}\r\n");
Box::pin(async move { self.inner.write_all(data.as_bytes()).await })
Box::pin(async move {
self.inner.write_all(data.as_bytes()).await?;
// Unconfirmed reports that some servers require
// multiple lines to be in separate packets
self.inner.flush().await
})
}
}
@ -225,6 +235,8 @@ impl State {
}
async fn send_privmsg(&mut self, target: &str, msg: &str) -> io::Result<()> {
// Send PRIVMSG, which is used for both private and channel messages.
// Splits into multiple fragments if necessary.
// IRC max line = 512 bytes including CRLF. The server prepends
// our prefix when relaying: ":nick!~user@host PRIVMSG target :msg\r\n"
// User is often ~nick (nick_len + 1). Host is up to 63 bytes.
@ -246,7 +258,11 @@ impl State {
// Find last char boundary at or before max_msg
let mut i = max_msg;
while i > 0 && !remaining.is_char_boundary(i) { i -= 1; }
if i == 0 { max_msg } else { i }
// To avoid splitting mid-word, see if there was a space recently
let mut j = i;
while j > 0 && j > i-10 && remaining.as_bytes()[j] != b' ' { j -= 1; }
if remaining.as_bytes()[j] == b' ' { j }
else if i == 0 { max_msg } else { i }
};
let (chunk, rest) = remaining.split_at(split_at);
self.send_raw(&format!("PRIVMSG {target} :{chunk}")).await?;