Bläddra i källkod

darkirc: upgrade privmsg, added the logic of deserializing old and new versions
but old version will still be used to send, this should insure compatibility
after some time after enough nodes have upgraded we can switch to send new

dasman 1 år sedan
förälder
incheckning
ef3ebc5b2e
4 ändrade filer med 108 tillägg och 22 borttagningar
  1. 14 6
      bin/darkirc/src/irc/client.rs
  2. 5 4
      bin/darkirc/src/irc/command.rs
  3. 79 2
      bin/darkirc/src/irc/mod.rs
  4. 10 10
      bin/darkirc/src/irc/server.rs

+ 14 - 6
bin/darkirc/src/irc/client.rs

@@ -29,7 +29,7 @@ use darkfi::{
     system::Subscription,
     Error, Result,
 };
-use darkfi_serial::{deserialize_async_partial, serialize_async};
+use darkfi_serial::serialize_async;
 use futures::FutureExt;
 use log::{debug, error, warn};
 use sled_overlay::sled;
@@ -42,7 +42,7 @@ use smol::{
 
 use super::{
     server::{IrcServer, MAX_MSG_LEN, MAX_NICK_LEN},
-    NickServ, Privmsg, SERVER_NAME,
+    Msg, NickServ, OldPrivmsg, SERVER_NAME,
 };
 
 const PENALTY_LIMIT: usize = 5;
@@ -228,8 +228,9 @@ impl Client {
                     }
 
                     // Try to deserialize the `Event`'s content into a `Privmsg`
-                    let mut privmsg: Privmsg = match deserialize_async_partial(r.content()).await {
-                        Ok((v, _)) => v,
+                    let mut privmsg = match Msg::deserialize(r.content()).await {
+                        Ok(Msg::V1(old_msg)) => old_msg.into_new(),
+                        Ok(Msg::V2(new_msg)) => new_msg,
                         Err(e) => {
                             error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {}", e);
                             continue
@@ -432,8 +433,15 @@ impl Client {
 
         // Truncate messages longer than MAX_MSG_LEN
         let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
-        let mut privmsg =
-            Privmsg { channel, nick: self.nickname.read().await.to_string(), msg: msg.to_string() };
+
+        // TODO: This is kept as old version of privmsg, since now we
+        // can deserialize both old and new versions, after some time
+        // this will be replaced with Privmsg (new version)
+        let mut privmsg = OldPrivmsg {
+            channel,
+            nick: self.nickname.read().await.to_string(),
+            msg: msg.to_string(),
+        };
 
         // Encrypt the Privmsg if an encryption method is available.
         self.server.try_encrypt(&mut privmsg).await;

+ 5 - 4
bin/darkirc/src/irc/command.rs

@@ -52,14 +52,13 @@
 use std::{collections::HashSet, sync::atomic::Ordering::SeqCst};
 
 use darkfi::Result;
-use darkfi_serial::deserialize_async_partial;
 use log::{error, info};
 
 use super::{
     client::{Client, ReplyType},
     rpl::*,
     server::MAX_NICK_LEN,
-    IrcChannel, SERVER_NAME,
+    IrcChannel, Msg, SERVER_NAME,
 };
 use crate::crypto::bcrypt::bcrypt_hash_password;
 
@@ -978,8 +977,10 @@ impl Client {
             }
 
             // Try to deserialize it. (Here we skip errors)
-            let Ok((mut privmsg, _)) = deserialize_async_partial(event.content()).await else {
-                continue
+            let mut privmsg = match Msg::deserialize(event.content()).await {
+                Ok(Msg::V1(old_msg)) => old_msg.into_new(),
+                Ok(Msg::V2(new_msg)) => new_msg,
+                Err(_) => continue,
             };
 
             // Potentially decrypt the privmsg

+ 79 - 2
bin/darkirc/src/irc/mod.rs

@@ -19,7 +19,8 @@
 use std::{collections::HashSet, sync::Arc};
 
 use crypto_box::ChaChaBox;
-use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
+use darkfi::{Error, Result};
+use darkfi_serial::{async_trait, deserialize_async_partial, SerialDecodable, SerialEncodable};
 
 /// IRC client state
 pub(crate) mod client;
@@ -40,14 +41,90 @@ pub(crate) mod rpl;
 /// Hardcoded server name
 const SERVER_NAME: &str = "irc.dark.fi";
 
-/// IRC PRIVMSG
+pub trait Priv {
+    fn channel(&mut self) -> &mut String;
+    fn nick(&mut self) -> &mut String;
+    fn msg(&mut self) -> &mut String;
+}
+
+/// IRC PRIVMSG (old version)
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct OldPrivmsg {
+    pub channel: String,
+    pub nick: String,
+    pub msg: String,
+}
+
+impl OldPrivmsg {
+    pub fn into_new(&self) -> Privmsg {
+        Privmsg {
+            version: 0,
+            msg_type: 0,
+            channel: self.channel.clone(),
+            nick: self.nick.clone(),
+            msg: self.msg.clone(),
+        }
+    }
+}
+
+/// IRC PRIVMSG (new version)
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 pub struct Privmsg {
+    pub version: u8,
+    pub msg_type: u8,
     pub channel: String,
     pub nick: String,
     pub msg: String,
 }
 
+impl Priv for OldPrivmsg {
+    fn channel(&mut self) -> &mut String {
+        &mut self.channel
+    }
+
+    fn nick(&mut self) -> &mut String {
+        &mut self.nick
+    }
+
+    fn msg(&mut self) -> &mut String {
+        &mut self.msg
+    }
+}
+impl Priv for Privmsg {
+    fn channel(&mut self) -> &mut String {
+        &mut self.channel
+    }
+
+    fn nick(&mut self) -> &mut String {
+        &mut self.nick
+    }
+
+    fn msg(&mut self) -> &mut String {
+        &mut self.msg
+    }
+}
+
+pub enum Msg {
+    V1(OldPrivmsg),
+    V2(Privmsg),
+}
+
+impl Msg {
+    pub async fn deserialize(bytes: &[u8]) -> Result<Self> {
+        let old_privmsg = deserialize_async_partial(bytes).await;
+        if let Ok((old_msg, _)) = old_privmsg {
+            return Ok(Msg::V1(old_msg))
+        }
+
+        let new_privmsg = deserialize_async_partial(bytes).await;
+        if let Ok((new_msg, _)) = new_privmsg {
+            return Ok(Msg::V2(new_msg))
+        }
+
+        Err(Error::Custom("Unknown message format".into()))
+    }
+}
+
 /// IRC channel definition
 #[derive(Clone)]
 pub struct IrcChannel {

+ 10 - 10
bin/darkirc/src/irc/server.rs

@@ -38,7 +38,7 @@ use smol::{
 };
 use url::Url;
 
-use super::{client::Client, IrcChannel, IrcContact, Privmsg};
+use super::{client::Client, IrcChannel, IrcContact, Priv, Privmsg};
 use crate::{
     crypto::saltbox,
     settings::{parse_autojoin_channels, parse_configured_channels, parse_configured_contacts},
@@ -282,24 +282,24 @@ impl IrcServer {
     }
 
     /// Try encrypting a given `Privmsg` if there is such a channel/contact.
-    pub async fn try_encrypt(&self, privmsg: &mut Privmsg) {
-        if let Some((name, channel)) = self.channels.read().await.get_key_value(&privmsg.channel) {
+    pub async fn try_encrypt<T: Priv>(&self, privmsg: &mut T) {
+        if let Some((name, channel)) = self.channels.read().await.get_key_value(privmsg.channel()) {
             if let Some(saltbox) = &channel.saltbox {
                 // We will pad the name and nick to MAX_NICK_LEN so they all look the same.
-                privmsg.channel = saltbox::encrypt(saltbox, &Self::pad(&privmsg.channel));
-                privmsg.nick = saltbox::encrypt(saltbox, &Self::pad(&privmsg.nick));
-                privmsg.msg = saltbox::encrypt(saltbox, privmsg.msg.as_bytes());
+                *privmsg.channel() = saltbox::encrypt(saltbox, &Self::pad(privmsg.channel()));
+                *privmsg.nick() = saltbox::encrypt(saltbox, &Self::pad(privmsg.nick()));
+                *privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
                 debug!("Successfully encrypted message for {}", name);
                 return
             }
         };
 
-        if let Some((name, contact)) = self.contacts.read().await.get_key_value(&privmsg.channel) {
+        if let Some((name, contact)) = self.contacts.read().await.get_key_value(privmsg.channel()) {
             if let Some(saltbox) = &contact.saltbox {
                 // We will pad the nicks to MAX_NICK_LEN so they all look the same.
-                privmsg.channel = saltbox::encrypt(saltbox, &Self::pad(&privmsg.channel));
-                privmsg.nick = saltbox::encrypt(saltbox, &Self::pad(&privmsg.nick));
-                privmsg.msg = saltbox::encrypt(saltbox, privmsg.msg.as_bytes());
+                *privmsg.channel() = saltbox::encrypt(saltbox, &Self::pad(privmsg.channel()));
+                *privmsg.nick() = saltbox::encrypt(saltbox, &Self::pad(privmsg.nick()));
+                *privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
                 debug!("Successfully encrypted message for {}", name);
             }
         };