Просмотр исходного кода

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 год назад
Родитель
Сommit
ef3ebc5b2e
4 измененных файлов с 108 добавлено и 22 удалено
  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,
     system::Subscription,
     Error, Result,
     Error, Result,
 };
 };
-use darkfi_serial::{deserialize_async_partial, serialize_async};
+use darkfi_serial::serialize_async;
 use futures::FutureExt;
 use futures::FutureExt;
 use log::{debug, error, warn};
 use log::{debug, error, warn};
 use sled_overlay::sled;
 use sled_overlay::sled;
@@ -42,7 +42,7 @@ use smol::{
 
 
 use super::{
 use super::{
     server::{IrcServer, MAX_MSG_LEN, MAX_NICK_LEN},
     server::{IrcServer, MAX_MSG_LEN, MAX_NICK_LEN},
-    NickServ, Privmsg, SERVER_NAME,
+    Msg, NickServ, OldPrivmsg, SERVER_NAME,
 };
 };
 
 
 const PENALTY_LIMIT: usize = 5;
 const PENALTY_LIMIT: usize = 5;
@@ -228,8 +228,9 @@ impl Client {
                     }
                     }
 
 
                     // Try to deserialize the `Event`'s content into a `Privmsg`
                     // 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) => {
                         Err(e) => {
                             error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {}", e);
                             error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {}", e);
                             continue
                             continue
@@ -432,8 +433,15 @@ impl Client {
 
 
         // Truncate messages longer than MAX_MSG_LEN
         // 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 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.
         // Encrypt the Privmsg if an encryption method is available.
         self.server.try_encrypt(&mut privmsg).await;
         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 std::{collections::HashSet, sync::atomic::Ordering::SeqCst};
 
 
 use darkfi::Result;
 use darkfi::Result;
-use darkfi_serial::deserialize_async_partial;
 use log::{error, info};
 use log::{error, info};
 
 
 use super::{
 use super::{
     client::{Client, ReplyType},
     client::{Client, ReplyType},
     rpl::*,
     rpl::*,
     server::MAX_NICK_LEN,
     server::MAX_NICK_LEN,
-    IrcChannel, SERVER_NAME,
+    IrcChannel, Msg, SERVER_NAME,
 };
 };
 use crate::crypto::bcrypt::bcrypt_hash_password;
 use crate::crypto::bcrypt::bcrypt_hash_password;
 
 
@@ -978,8 +977,10 @@ impl Client {
             }
             }
 
 
             // Try to deserialize it. (Here we skip errors)
             // 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
             // Potentially decrypt the privmsg

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

@@ -19,7 +19,8 @@
 use std::{collections::HashSet, sync::Arc};
 use std::{collections::HashSet, sync::Arc};
 
 
 use crypto_box::ChaChaBox;
 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
 /// IRC client state
 pub(crate) mod client;
 pub(crate) mod client;
@@ -40,14 +41,90 @@ pub(crate) mod rpl;
 /// Hardcoded server name
 /// Hardcoded server name
 const SERVER_NAME: &str = "irc.dark.fi";
 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)]
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 pub struct Privmsg {
 pub struct Privmsg {
+    pub version: u8,
+    pub msg_type: u8,
     pub channel: String,
     pub channel: String,
     pub nick: String,
     pub nick: String,
     pub msg: 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
 /// IRC channel definition
 #[derive(Clone)]
 #[derive(Clone)]
 pub struct IrcChannel {
 pub struct IrcChannel {

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

@@ -38,7 +38,7 @@ use smol::{
 };
 };
 use url::Url;
 use url::Url;
 
 
-use super::{client::Client, IrcChannel, IrcContact, Privmsg};
+use super::{client::Client, IrcChannel, IrcContact, Priv, Privmsg};
 use crate::{
 use crate::{
     crypto::saltbox,
     crypto::saltbox,
     settings::{parse_autojoin_channels, parse_configured_channels, parse_configured_contacts},
     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.
     /// 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 {
             if let Some(saltbox) = &channel.saltbox {
                 // We will pad the name and nick to MAX_NICK_LEN so they all look the same.
                 // 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);
                 debug!("Successfully encrypted message for {}", name);
                 return
                 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 {
             if let Some(saltbox) = &contact.saltbox {
                 // We will pad the nicks to MAX_NICK_LEN so they all look the same.
                 // 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);
                 debug!("Successfully encrypted message for {}", name);
             }
             }
         };
         };