irc: handle non-UTF-8 input, CTCP VERSION, log outgoing messages
Three fixes: 1. Use read_until + from_utf8_lossy instead of AsyncBufRead::lines(), which returns Err on invalid UTF-8. IRC isn't guaranteed UTF-8 — Latin-1, Yiddish, etc. would crash the reader loop. 2. Handle CTCP requests (messages wrapped in \x01). Reply to VERSION queries so the server stops retrying, and skip CTCP for notification generation. 3. Log outgoing messages from the "send" command with append_log() so they appear in IRC logs alongside incoming traffic. Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
This commit is contained in:
parent
bea1bd5680
commit
5eb8a4eb6a
1 changed files with 24 additions and 3 deletions
|
|
@ -263,7 +263,7 @@ async fn connect_and_run(
|
||||||
async fn register_and_read<R: tokio::io::AsyncRead + Unpin>(
|
async fn register_and_read<R: tokio::io::AsyncRead + Unpin>(
|
||||||
state: &SharedIrc,
|
state: &SharedIrc,
|
||||||
config: &IrcConfig,
|
config: &IrcConfig,
|
||||||
reader: BufReader<R>,
|
mut reader: BufReader<R>,
|
||||||
notify_tx: &mpsc::UnboundedSender<Notification>,
|
notify_tx: &mpsc::UnboundedSender<Notification>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
// Register
|
// Register
|
||||||
|
|
@ -273,9 +273,15 @@ async fn register_and_read<R: tokio::io::AsyncRead + Unpin>(
|
||||||
s.send_raw(&format!("USER {} 0 * :{}", config.user, config.realname)).await?;
|
s.send_raw(&format!("USER {} 0 * :{}", config.user, config.realname)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut lines = reader.lines();
|
let mut buf = Vec::new();
|
||||||
|
|
||||||
while let Some(line) = lines.next_line().await? {
|
loop {
|
||||||
|
buf.clear();
|
||||||
|
let n = reader.read_until(b'\n', &mut buf).await?;
|
||||||
|
if n == 0 { break; }
|
||||||
|
// IRC is not guaranteed UTF-8 — lossy conversion handles Latin-1 etc.
|
||||||
|
let line = String::from_utf8_lossy(&buf).trim_end().to_string();
|
||||||
|
if line.is_empty() { continue; }
|
||||||
let msg = match IrcMessage::parse(&line) {
|
let msg = match IrcMessage::parse(&line) {
|
||||||
Some(m) => m,
|
Some(m) => m,
|
||||||
None => continue,
|
None => continue,
|
||||||
|
|
@ -306,6 +312,19 @@ async fn register_and_read<R: tokio::io::AsyncRead + Unpin>(
|
||||||
let text = msg.params.get(1).map(|s| s.as_str()).unwrap_or("");
|
let text = msg.params.get(1).map(|s| s.as_str()).unwrap_or("");
|
||||||
let nick = msg.nick().unwrap_or("unknown");
|
let nick = msg.nick().unwrap_or("unknown");
|
||||||
|
|
||||||
|
// Handle CTCP requests (wrapped in \x01)
|
||||||
|
if text.starts_with('\x01') && text.ends_with('\x01') {
|
||||||
|
let ctcp = &text[1..text.len()-1];
|
||||||
|
if ctcp.starts_with("VERSION") {
|
||||||
|
let reply = format!(
|
||||||
|
"NOTICE {nick} :\x01VERSION poc-daemon 0.4.0\x01"
|
||||||
|
);
|
||||||
|
state.borrow_mut().send_raw(&reply).await.ok();
|
||||||
|
}
|
||||||
|
// Don't generate notifications for CTCP
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Log the message
|
// Log the message
|
||||||
let log_line = if target.starts_with('#') {
|
let log_line = if target.starts_with('#') {
|
||||||
format!("[{}] <{}> {}", target, nick, text)
|
format!("[{}] <{}> {}", target, nick, text)
|
||||||
|
|
@ -453,11 +472,13 @@ pub async fn handle_command(
|
||||||
}
|
}
|
||||||
let target = &args[0];
|
let target = &args[0];
|
||||||
let msg = args[1..].join(" ");
|
let msg = args[1..].join(" ");
|
||||||
|
let nick = state.borrow().config.nick.clone();
|
||||||
state
|
state
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.send_privmsg(target, &msg)
|
.send_privmsg(target, &msg)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
append_log(target, &nick, &msg);
|
||||||
Ok(format!("sent to {target}"))
|
Ok(format!("sent to {target}"))
|
||||||
}
|
}
|
||||||
"status" => {
|
"status" => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue