From 8f258977c8a74dd67f424375135b04f8fc585b7b Mon Sep 17 00:00:00 2001 From: parazyd Date: Thu, 27 Jul 2023 14:15:02 +0200 Subject: [PATCH] darkirc: Move state of joined channels out of ChannelInfo into IrcClient. --- bin/darkirc/src/crypto.rs | 7 ++--- bin/darkirc/src/irc/client.rs | 49 +++++++++++++++++++++-------------- bin/darkirc/src/settings.rs | 4 +-- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/bin/darkirc/src/crypto.rs b/bin/darkirc/src/crypto.rs index e7fbefeae..41f4b52a4 100644 --- a/bin/darkirc/src/crypto.rs +++ b/bin/darkirc/src/crypto.rs @@ -83,14 +83,11 @@ pub fn encrypt(salt_box: &ChaChaBox, plaintext: &[u8]) -> String { pub fn decrypt_target( contact: &mut String, privmsg: &mut PrivMsgEvent, - configured_chans: HashMap, - configured_contacts: HashMap, + configured_chans: &HashMap, + configured_contacts: &HashMap, ) { for chan_name in configured_chans.keys() { let chan_info = configured_chans.get(chan_name).unwrap(); - if !chan_info.joined { - continue - } if let Some(salt_box) = &chan_info.salt_box { let decrypted_target = try_decrypt(salt_box, &privmsg.target); diff --git a/bin/darkirc/src/irc/client.rs b/bin/darkirc/src/irc/client.rs index 10d698822..a7e7bcfbc 100644 --- a/bin/darkirc/src/irc/client.rs +++ b/bin/darkirc/src/irc/client.rs @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -use std::net::SocketAddr; +use std::{collections::HashSet, net::SocketAddr}; use async_std::sync::{Arc, Mutex}; use futures::{ @@ -50,6 +50,9 @@ pub struct IrcClient { // irc config irc_config: IrcConfig, + /// Joined channels, mapped here for better SIGHUP UX. + channels_joined: HashSet, + server_notifier: smol::channel::Sender<(NotifierMsg, u64)>, subscription: Subscription, @@ -71,6 +74,7 @@ impl IrcClient { read_stream, address, irc_config, + channels_joined: HashSet::new(), subscription, server_notifier, missed_events, @@ -137,22 +141,29 @@ impl IrcClient { decrypt_target( &mut contact, &mut msg, - self.irc_config.channels.clone(), - self.irc_config.contacts.clone(), + &self.irc_config.channels, + &self.irc_config.contacts, ); + // The message is a channel message if msg.target.starts_with('#') { // Try to potentially decrypt the incoming message. if !self.irc_config.channels.contains_key(&msg.target) { return Ok(()) } - let chan_info = self.irc_config.channels.get_mut(&msg.target).unwrap(); - if !chan_info.joined { + // Skip everything if we're not joined in the channel + if self.channels_joined.contains(&msg.target) { return Ok(()) } + let chan_info = self.irc_config.channels.get_mut(&msg.target).unwrap(); + + // We use this flag to mark if the message has been encrypted or not. + // Depending on it, we set a specific usermode to the nickname in the + // channel so in UI we can tell who is sending encrypted messages. let mut encrypted = false; + if let Some(salt_box) = &chan_info.salt_box { decrypt_privmsg(salt_box, &mut msg); encrypted = true; @@ -177,7 +188,11 @@ impl IrcClient { }; self.reply(&msg.to_string()).await?; - } else if self.irc_config.is_cap_end && self.irc_config.is_nick_init { + return Ok(()) + } + + // The message is not a channel message, handle accordingly. + if self.irc_config.is_cap_end && self.irc_config.is_nick_init { if !self.irc_config.contacts.contains_key(&contact) { return Ok(()) } @@ -191,6 +206,7 @@ impl IrcClient { } self.reply(&msg.to_string()).await?; + return Ok(()) } Ok(()) @@ -242,7 +258,7 @@ impl IrcClient { } async fn register(&mut self) -> Result<()> { - if !self.irc_config.is_pass_init && self.irc_config.password.is_empty() { + if !self.irc_config.is_pass_init && self.irc_config.pass.is_empty() { self.irc_config.is_pass_init = true } @@ -305,22 +321,17 @@ impl IrcClient { } self.irc_config.is_nick_init = true; - let old_nick = std::mem::replace(&mut self.irc_config.nickname, nickname.to_string()); + let old_nick = std::mem::replace(&mut self.irc_config.nick, nickname.to_string()); - let nick_reply = - format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.irc_config.nickname); + let nick_reply = format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.irc_config.nick); self.reply(&nick_reply).await } async fn on_receive_part(&mut self, channels: Vec) -> Result<()> { for chan in channels.iter() { - let part_reply = - format!(":{}!anon@dark.fi PART {}\r\n", self.irc_config.nickname, chan); + let part_reply = format!(":{}!anon@dark.fi PART {}\r\n", self.irc_config.nick, chan); self.reply(&part_reply).await?; - if self.irc_config.channels.contains_key(chan) { - let chan_info = self.irc_config.channels.get_mut(chan).unwrap(); - chan_info.joined = false; - } + self.channels_joined.remove(chan); } Ok(()) } @@ -499,12 +510,12 @@ impl IrcClient { return Ok(()) } - let channel_info = self.irc_config.channels.get(target).unwrap(); - - if !channel_info.joined { + if !self.channels_joined.contains(target) { return Ok(()) } + let channel_info = self.irc_config.channels.get(target).unwrap(); + if let Some(salt_box) = &channel_info.salt_box { encrypt_privmsg(salt_box, &mut privmsg); debug!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg); diff --git a/bin/darkirc/src/settings.rs b/bin/darkirc/src/settings.rs index 5024675ea..919b12d38 100644 --- a/bin/darkirc/src/settings.rs +++ b/bin/darkirc/src/settings.rs @@ -218,15 +218,13 @@ pub struct ChannelInfo { pub topic: Option, /// Optional NaCl box for the channel, used for {en,de}cryption. pub salt_box: Option>, - /// Flag indicates whether the user has joined the channel or not - pub joined: bool, /// All nicknames which are visible on the channel pub names: HashSet, } impl ChannelInfo { pub fn new() -> Result { - Ok(Self { topic: None, salt_box: None, joined: false, names: HashSet::new() }) + Ok(Self { topic: None, salt_box: None, names: HashSet::new() }) } pub fn names(&self) -> String {