diff options
Diffstat (limited to '')
21 files changed, 943 insertions, 449 deletions
diff --git a/src/message/handshake/clientinit.rs b/src/message/handshake/clientinit.rs index 17ec9a1..d21d6aa 100644 --- a/src/message/handshake/clientinit.rs +++ b/src/message/handshake/clientinit.rs @@ -1,6 +1,5 @@ -use crate::error::ProtocolError; use crate::primitive::{StringList, Variant, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::HandshakeSerialize; use failure::Error; @@ -32,7 +31,7 @@ use failure::Error; /// | -- | EcdsaCertfpKeys | ECDSA keys for CertFP in identities | /// | -- | LongMessageId | 64-bit IDs for messages | /// | -- | SyncedCoreInfo | CoreInfo dynamically updated using signals | -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientInit { /// Version of the client pub client_version: String, @@ -68,24 +67,13 @@ impl HandshakeSerialize for ClientInit { } } -impl HandshakeDeserialize for ClientInit { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientInit" { - return Ok(( - len, - Self { - client_version: match_variant!(values["ClientVersion"], Variant::String), - client_date: match_variant!(values["ClientDate"], Variant::String), - feature_list: match_variant!(values["FeatureList"], Variant::StringList), - client_features: match_variant!(values["Features"], Variant::u32), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); +impl From<VariantMap> for ClientInit { + fn from(input: VariantMap) -> Self { + ClientInit { + client_version: match_variant!(input.get("ClientVersion").unwrap(), Variant::String), + client_date: match_variant!(input.get("ClientDate").unwrap(), Variant::String), + client_features: match_variant!(input.get("Features").unwrap(), Variant::u32), + feature_list: match_variant!(input.get("FeatureList").unwrap(), Variant::StringList), } } } diff --git a/src/message/handshake/clientinitack.rs b/src/message/handshake/clientinitack.rs index 637b989..f881113 100644 --- a/src/message/handshake/clientinitack.rs +++ b/src/message/handshake/clientinitack.rs @@ -1,11 +1,10 @@ -use crate::error::ProtocolError; -use crate::primitive::{StringList, Variant, VariantList, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::primitive::{Variant, VariantList, VariantMap}; +use crate::HandshakeSerialize; use failure::Error; /// ClientInitAck is received when the initialization was successfull -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientInitAck { /// Flags of supported legacy features pub core_features: u32, @@ -16,7 +15,7 @@ pub struct ClientInitAck { /// List of VariantMaps of info on available authenticators pub authenticators: VariantList, /// List of supported extended features - pub feature_list: StringList, + pub feature_list: Vec<String>, } impl HandshakeSerialize for ClientInitAck { @@ -47,28 +46,21 @@ impl HandshakeSerialize for ClientInitAck { } } -impl HandshakeDeserialize for ClientInitAck { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientInitAck" { - return Ok(( - len, - Self { - core_features: 0x00008000, - core_configured: match_variant!(values["Configured"], Variant::bool), - storage_backends: match_variant!( - values["StorageBackends"], - Variant::VariantList - ), - authenticators: match_variant!(values["Authenticators"], Variant::VariantList), - feature_list: match_variant!(values["FeatureList"], Variant::StringList), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); +impl From<VariantMap> for ClientInitAck { + fn from(input: VariantMap) -> Self { + ClientInitAck { + // TODO make this compatible with older clients + core_features: 0, + core_configured: match_variant!(input.get("Configured").unwrap(), Variant::bool), + storage_backends: match_variant!( + input.get("StorageBackends").unwrap(), + Variant::VariantList + ), + authenticators: match_variant!( + input.get("Authenticators").unwrap(), + Variant::VariantList + ), + feature_list: match_variant!(input.get("FeatureList").unwrap(), Variant::StringList), } } } diff --git a/src/message/handshake/clientinitreject.rs b/src/message/handshake/clientinitreject.rs index 06960b7..d93413d 100644 --- a/src/message/handshake/clientinitreject.rs +++ b/src/message/handshake/clientinitreject.rs @@ -1,14 +1,13 @@ -use crate::error::ProtocolError; use crate::primitive::{Variant, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::HandshakeSerialize; use failure::Error; /// ClientInitReject is received when the initialization fails -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientInitReject { /// String with an error message of what went wrong - pub error_string: String, + pub error: String, } impl HandshakeSerialize for ClientInitReject { @@ -20,27 +19,16 @@ impl HandshakeSerialize for ClientInitReject { ); values.insert( "ErrorString".to_string(), - Variant::String(self.error_string.clone()), + Variant::String(self.error.clone()), ); return HandshakeSerialize::serialize(&values); } } -impl HandshakeDeserialize for ClientInitReject { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientInitReject" { - return Ok(( - len, - Self { - error_string: match_variant!(values["ErrorString"], Variant::String), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); +impl From<VariantMap> for ClientInitReject { + fn from(input: VariantMap) -> Self { + ClientInitReject { + error: match_variant!(input.get("ErrorString").unwrap(), Variant::String), } } } diff --git a/src/message/handshake/clientlogin.rs b/src/message/handshake/clientlogin.rs index 769245b..dffd996 100644 --- a/src/message/handshake/clientlogin.rs +++ b/src/message/handshake/clientlogin.rs @@ -1,12 +1,11 @@ -use crate::error::ProtocolError; use crate::primitive::{Variant, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::HandshakeSerialize; use failure::Error; /// Login to the core with user data /// username and password are transmitted in plain text -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientLogin { pub user: String, pub password: String, @@ -28,22 +27,11 @@ impl HandshakeSerialize for ClientLogin { } } -impl HandshakeDeserialize for ClientLogin { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientLogin" { - return Ok(( - len, - Self { - user: match_variant!(values["User"], Variant::String), - password: match_variant!(values["Password"], Variant::String), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); +impl From<VariantMap> for ClientLogin { + fn from(input: VariantMap) -> Self { + ClientLogin { + user: match_variant!(input.get("User").unwrap(), Variant::String), + password: match_variant!(input.get("Password").unwrap(), Variant::String), } } } diff --git a/src/message/handshake/clientloginack.rs b/src/message/handshake/clientloginack.rs index 674d307..e385a81 100644 --- a/src/message/handshake/clientloginack.rs +++ b/src/message/handshake/clientloginack.rs @@ -6,7 +6,7 @@ use failure::Error; /// ClientLoginAck is received after the client has successfully logged in /// it has no fields -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientLoginAck; impl HandshakeSerialize for ClientLoginAck { diff --git a/src/message/handshake/clientloginreject.rs b/src/message/handshake/clientloginreject.rs index e8380d6..0c0fc85 100644 --- a/src/message/handshake/clientloginreject.rs +++ b/src/message/handshake/clientloginreject.rs @@ -1,14 +1,13 @@ -use crate::error::ProtocolError; use crate::primitive::{Variant, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::HandshakeSerialize; use failure::Error; /// ClientLoginReject is received after the client failed to login /// It contains an error message as String -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ClientLoginReject { - error: String, + pub error: String, } impl HandshakeSerialize for ClientLoginReject { @@ -26,21 +25,10 @@ impl HandshakeSerialize for ClientLoginReject { } } -impl HandshakeDeserialize for ClientLoginReject { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientLogin" { - return Ok(( - len, - Self { - error: match_variant!(values["ErrorString"], Variant::String), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); +impl From<VariantMap> for ClientLoginReject { + fn from(input: VariantMap) -> Self { + ClientLoginReject { + error: match_variant!(input.get("ErrorString").unwrap(), Variant::String), } } } diff --git a/src/message/handshake/init.rs b/src/message/handshake/init.rs index e4c0fa9..b4604b6 100644 --- a/src/message/handshake/init.rs +++ b/src/message/handshake/init.rs @@ -2,6 +2,7 @@ use crate::Deserialize; use crate::Serialize; /// The first few bytes sent to the core to initialize the connection and setup if we want to use tls and compression +#[derive(Clone, Debug)] pub struct Init { pub tls: bool, pub compression: bool, @@ -37,7 +38,15 @@ impl Init { handshake |= 0x02; } - return handshake.serialize().unwrap(); + // Select Protocol 2: Datastream + + let mut init: Vec<u8> = vec![]; + + // Add handshake and protocol to our buffer + init.extend(handshake.serialize().unwrap()); + init.extend(crate::message::Protocol::Datastream.serialize()); + + return init; } pub fn parse(buf: &[u8]) -> Self { diff --git a/src/message/handshake/mod.rs b/src/message/handshake/mod.rs index 9b3bcee..9885012 100644 --- a/src/message/handshake/mod.rs +++ b/src/message/handshake/mod.rs @@ -21,3 +21,49 @@ pub use init::*; pub use protocol::*; pub use sessioninit::*; pub use types::*; + +use crate::primitive::{Variant, VariantMap}; +use crate::{HandshakeDeserialize, HandshakeSerialize}; + +#[derive(Debug, Clone)] +pub enum HandshakeMessage { + ClientInit(ClientInit), + ClientInitAck(ClientInitAck), + ClientInitReject(ClientInitReject), + ClientLogin(ClientLogin), + ClientLoginAck, + ClientLoginReject(ClientLoginReject), + SessionInit(SessionInit), +} + +impl HandshakeSerialize for HandshakeMessage { + fn serialize(&self) -> Result<Vec<u8>, failure::Error> { + match self { + HandshakeMessage::ClientInit(inner) => inner.serialize(), + HandshakeMessage::ClientInitAck(inner) => inner.serialize(), + HandshakeMessage::ClientInitReject(inner) => inner.serialize(), + HandshakeMessage::ClientLogin(inner) => inner.serialize(), + HandshakeMessage::ClientLoginAck => ClientLoginAck.serialize(), + HandshakeMessage::ClientLoginReject(inner) => inner.serialize(), + HandshakeMessage::SessionInit(inner) => inner.serialize(), + } + } +} + +impl HandshakeDeserialize for HandshakeMessage { + fn parse(b: &[u8]) -> Result<(usize, Self), failure::Error> { + let (size, res) = VariantMap::parse(b)?; + + let msgtype = match_variant!(&res["MsgType"], Variant::String); + match msgtype.as_str() { + "ClientInit" => Ok((size, HandshakeMessage::ClientInit(res.into()))), + "ClientInitAck" => Ok((size, HandshakeMessage::ClientInitAck(res.into()))), + "ClientInitReject" => Ok((size, HandshakeMessage::ClientInitReject(res.into()))), + "ClientLogin" => Ok((size, HandshakeMessage::ClientLogin(res.into()))), + "ClientLoginAck" => Ok((size, HandshakeMessage::ClientLoginAck)), + "ClientLoginReject" => Ok((size, HandshakeMessage::ClientLoginReject(res.into()))), + "SessionInit" => Ok((size, HandshakeMessage::SessionInit(res.into()))), + _ => unimplemented!(), + } + } +} diff --git a/src/message/handshake/sessioninit.rs b/src/message/handshake/sessioninit.rs index eca4c10..d1b4b90 100644 --- a/src/message/handshake/sessioninit.rs +++ b/src/message/handshake/sessioninit.rs @@ -1,61 +1,81 @@ -use crate::error::ProtocolError; -use crate::primitive::{Variant, VariantList, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; +use crate::message::objects::Identity; +use crate::primitive::{BufferInfo, Variant, VariantMap}; +use crate::HandshakeSerialize; use failure::Error; /// SessionInit is received along with ClientLoginAck to initialize that user Session // TODO Replace with proper types -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SessionInit { /// List of all configured identities - identities: VariantList, + pub identities: Vec<Identity>, /// List of all existing buffers - buffers: VariantList, + pub buffers: Vec<BufferInfo>, /// Ids of all networks - network_ids: VariantList, + pub network_ids: Vec<i32>, +} + +impl From<VariantMap> for SessionInit { + fn from(input: VariantMap) -> Self { + let state = match_variant!(input.get("SessionState").unwrap(), Variant::VariantMap); + SessionInit { + identities: match_variant!(state.get("Identities").unwrap(), Variant::VariantList) + .iter() + .map(|ident| Identity::from(match_variant!(ident, Variant::VariantMap))) + .collect(), + buffers: match_variant!(state.get("BufferInfos").unwrap(), Variant::VariantList) + .iter() + .map(|buffer| match buffer { + Variant::BufferInfo(buffer) => buffer.clone(), + _ => unimplemented!(), + }) + .collect(), + network_ids: match_variant!(state.get("NetworkIds").unwrap(), Variant::VariantList) + .iter() + .map(|network| match network { + Variant::i32(network) => network.clone(), + _ => unimplemented!(), + }) + .collect(), + } + } } impl HandshakeSerialize for SessionInit { fn serialize(&self) -> Result<Vec<u8>, Error> { - let mut values: VariantMap = VariantMap::with_capacity(1); + let mut values: VariantMap = VariantMap::with_capacity(4); values.insert( "MsgType".to_string(), Variant::String("SessionInit".to_string()), ); values.insert( "Identities".to_string(), - Variant::VariantList(self.identities.clone()), + Variant::VariantList( + self.identities + .iter() + .map(|ident| Variant::VariantMap(ident.clone().into())) + .collect(), + ), ); values.insert( "BufferInfos".to_string(), - Variant::VariantList(self.buffers.clone()), + Variant::VariantList( + self.buffers + .iter() + .map(|buffer| Variant::BufferInfo(buffer.clone())) + .collect(), + ), ); values.insert( "NetworkIds".to_string(), - Variant::VariantList(self.network_ids.clone()), + Variant::VariantList( + self.network_ids + .iter() + .map(|id| Variant::i32(id.clone())) + .collect(), + ), ); return HandshakeSerialize::serialize(&values); } } - -impl HandshakeDeserialize for SessionInit { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); - - if msgtype == "ClientLogin" { - return Ok(( - len, - Self { - identities: match_variant!(values["Identities"], Variant::VariantList), - buffers: match_variant!(values["BufferInfos"], Variant::VariantList), - network_ids: match_variant!(values["NetworkIds"], Variant::VariantList), - }, - )); - } else { - bail!(ProtocolError::WrongMsgType); - } - } -} diff --git a/src/message/signalproxy.rs b/src/message/signalproxy.rs deleted file mode 100644 index 22a498a..0000000 --- a/src/message/signalproxy.rs +++ /dev/null @@ -1,309 +0,0 @@ -use crate::primitive::{DateTime, Variant, VariantList}; -use crate::{Deserialize, Serialize}; - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub enum Message { - /// Bidirectional - SyncMessage(SyncMessage), - /// Bidirectional - RpcCall(RpcCall), - InitRequest(InitRequest), - InitData(InitData), - /// Bidirectional - HeartBeat(HeartBeat), - /// Bidirectional - HeartBeatReply(HeartBeatReply), -} - -impl Serialize for Message { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - match &self { - Message::SyncMessage(value) => value.serialize(), - Message::RpcCall(value) => value.serialize(), - Message::InitRequest(value) => value.serialize(), - Message::InitData(value) => value.serialize(), - Message::HeartBeat(value) => value.serialize(), - Message::HeartBeatReply(value) => value.serialize(), - } - } -} - -impl Deserialize for Message { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (_, message_type) = i32::parse(&b[9..13])?; - - match MessageType::from(message_type) { - MessageType::SyncMessage => { - let (size, res) = SyncMessage::parse(&b)?; - - Ok((size, Message::SyncMessage(res))) - } - MessageType::RpcCall => { - let (size, res) = RpcCall::parse(&b)?; - - Ok((size, Message::RpcCall(res))) - } - MessageType::InitRequest => { - let (size, res) = InitRequest::parse(&b)?; - - Ok((size, Message::InitRequest(res))) - } - MessageType::InitData => { - let (size, res) = InitData::parse(&b)?; - - Ok((size, Message::InitData(res))) - } - MessageType::HeartBeat => { - let (size, res) = HeartBeat::parse(&b)?; - - Ok((size, Message::HeartBeat(res))) - } - MessageType::HeartBeatReply => { - let (size, res) = HeartBeatReply::parse(&b)?; - - Ok((size, Message::HeartBeatReply(res))) - } - } - } -} - -/// Type of an SignalProxy Message -/// The first element in the VariantList that is received -#[repr(i32)] -#[derive(Copy, Clone, Debug, std::cmp::PartialEq)] -pub enum MessageType { - /// Bidirectional - SyncMessage = 0x00000001, - /// Bidirectional - RpcCall = 0x00000002, - InitRequest = 0x00000003, - InitData = 0x00000004, - /// Bidirectional - HeartBeat = 0x00000005, - /// Bidirectional - HeartBeatReply = 0x00000006, -} - -impl From<i32> for MessageType { - fn from(val: i32) -> Self { - match val { - 0x00000001 => MessageType::SyncMessage, - 0x00000002 => MessageType::RpcCall, - 0x00000003 => MessageType::InitRequest, - 0x00000004 => MessageType::InitData, - 0x00000005 => MessageType::HeartBeat, - 0x00000006 => MessageType::HeartBeatReply, - _ => unimplemented!(), - } - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct SyncMessage { - class_name: String, - object_name: String, - slot_name: String, - params: VariantList, -} - -impl Serialize for SyncMessage { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::SyncMessage as i32)); - res.push(Variant::StringUTF8(self.class_name.clone())); - res.push(Variant::StringUTF8(self.object_name.clone())); - res.push(Variant::StringUTF8(self.slot_name.clone())); - - res.append(&mut self.params.clone()); - - res.serialize() - } -} - -impl Deserialize for SyncMessage { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - class_name: match_variant!(res.remove(0), Variant::StringUTF8), - object_name: match_variant!(res.remove(0), Variant::StringUTF8), - slot_name: match_variant!(res.remove(0), Variant::StringUTF8), - params: res, - }, - )) - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct RpcCall { - slot_name: String, - params: VariantList, -} - -impl Serialize for RpcCall { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::RpcCall as i32)); - res.push(Variant::StringUTF8(self.slot_name.clone())); - - res.append(&mut self.params.clone()); - - res.serialize() - } -} - -impl Deserialize for RpcCall { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - slot_name: match_variant!(res.remove(0), Variant::StringUTF8), - params: res, - }, - )) - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct InitRequest { - class_name: String, - object_name: String, -} - -impl Serialize for InitRequest { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::InitRequest as i32)); - res.push(Variant::StringUTF8(self.class_name.clone())); - res.push(Variant::StringUTF8(self.object_name.clone())); - - res.serialize() - } -} - -impl Deserialize for InitRequest { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - class_name: match_variant!(res.remove(0), Variant::StringUTF8), - object_name: match_variant!(res.remove(0), Variant::StringUTF8), - }, - )) - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct InitData { - class_name: String, - object_name: String, - init_data: VariantList, -} - -impl Serialize for InitData { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::InitData as i32)); - res.push(Variant::StringUTF8(self.class_name.clone())); - res.push(Variant::StringUTF8(self.object_name.clone())); - - res.append(&mut self.init_data.clone()); - - res.serialize() - } -} - -impl Deserialize for InitData { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - class_name: match_variant!(res.remove(0), Variant::StringUTF8), - object_name: match_variant!(res.remove(0), Variant::StringUTF8), - init_data: res, - }, - )) - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct HeartBeat { - timestamp: DateTime, -} - -impl Serialize for HeartBeat { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::HeartBeat as i32)); - res.push(Variant::DateTime(self.timestamp.clone())); - - res.serialize() - } -} - -impl Deserialize for HeartBeat { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - timestamp: match_variant!(res.remove(0), Variant::DateTime), - }, - )) - } -} - -#[derive(Clone, Debug, std::cmp::PartialEq)] -pub struct HeartBeatReply { - timestamp: DateTime, -} - -impl Serialize for HeartBeatReply { - fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { - let mut res = VariantList::new(); - - res.push(Variant::i32(MessageType::HeartBeatReply as i32)); - res.push(Variant::DateTime(self.timestamp.clone())); - - res.serialize() - } -} - -impl Deserialize for HeartBeatReply { - fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { - let (size, mut res) = VariantList::parse(&b)?; - - res.remove(0); - - Ok(( - size, - Self { - timestamp: match_variant!(res.remove(0), Variant::DateTime), - }, - )) - } -} diff --git a/src/message/signalproxy/heartbeat.rs b/src/message/signalproxy/heartbeat.rs new file mode 100644 index 0000000..46bfd51 --- /dev/null +++ b/src/message/signalproxy/heartbeat.rs @@ -0,0 +1,65 @@ +use crate::message::MessageType; +use crate::primitive::{DateTime, Variant, VariantList}; +use crate::{Deserialize, Serialize}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct HeartBeat { + timestamp: DateTime, +} + +impl Serialize for HeartBeat { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::HeartBeat as i32)); + res.push(Variant::DateTime(self.timestamp.clone())); + + res.serialize() + } +} + +impl Deserialize for HeartBeat { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + Ok(( + size, + Self { + timestamp: match_variant!(res.remove(0), Variant::DateTime), + }, + )) + } +} + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct HeartBeatReply { + timestamp: DateTime, +} + +impl Serialize for HeartBeatReply { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::HeartBeatReply as i32)); + res.push(Variant::DateTime(self.timestamp.clone())); + + res.serialize() + } +} + +impl Deserialize for HeartBeatReply { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + Ok(( + size, + Self { + timestamp: match_variant!(res.remove(0), Variant::DateTime), + }, + )) + } +} diff --git a/src/message/signalproxy/initdata.rs b/src/message/signalproxy/initdata.rs new file mode 100644 index 0000000..e4fb077 --- /dev/null +++ b/src/message/signalproxy/initdata.rs @@ -0,0 +1,41 @@ +use crate::message::MessageType; +use crate::primitive::{Variant, VariantList}; +use crate::{Deserialize, Serialize}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct InitData { + class_name: String, + object_name: String, + init_data: VariantList, +} + +impl Serialize for InitData { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::InitData as i32)); + res.push(Variant::StringUTF8(self.class_name.clone())); + res.push(Variant::StringUTF8(self.object_name.clone())); + + res.append(&mut self.init_data.clone()); + + res.serialize() + } +} + +impl Deserialize for InitData { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + Ok(( + size, + Self { + class_name: match_variant!(res.remove(0), Variant::StringUTF8), + object_name: match_variant!(res.remove(0), Variant::StringUTF8), + init_data: res, + }, + )) + } +} diff --git a/src/message/signalproxy/initrequest.rs b/src/message/signalproxy/initrequest.rs new file mode 100644 index 0000000..59eee2d --- /dev/null +++ b/src/message/signalproxy/initrequest.rs @@ -0,0 +1,37 @@ +use crate::message::MessageType; +use crate::primitive::{Variant, VariantList}; +use crate::{Deserialize, Serialize}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct InitRequest { + pub class_name: String, + pub object_name: String, +} + +impl Serialize for InitRequest { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::InitRequest as i32)); + res.push(Variant::ByteArray(self.class_name.clone())); + res.push(Variant::ByteArray(self.object_name.clone())); + + res.serialize() + } +} + +impl Deserialize for InitRequest { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + Ok(( + size, + Self { + class_name: match_variant!(res.remove(0), Variant::StringUTF8), + object_name: match_variant!(res.remove(0), Variant::StringUTF8), + }, + )) + } +} diff --git a/src/message/signalproxy/mod.rs b/src/message/signalproxy/mod.rs new file mode 100644 index 0000000..4e99fb0 --- /dev/null +++ b/src/message/signalproxy/mod.rs @@ -0,0 +1,124 @@ +use crate::{Deserialize, Serialize}; + +mod heartbeat; +mod initdata; +mod initrequest; +pub mod objects; +mod rpccall; +mod syncmessage; + +pub use heartbeat::*; +pub use initdata::*; +pub use initrequest::*; +pub use rpccall::*; +pub use syncmessage::*; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub enum Message { + /// Bidirectional + SyncMessage(SyncMessage), + /// Bidirectional + RpcCall(RpcCall), + InitRequest(InitRequest), + InitData(InitData), + /// Bidirectional + HeartBeat(HeartBeat), + /// Bidirectional + HeartBeatReply(HeartBeatReply), +} + +// impl Message { +// fn act(&self) { +// match &self { +// Message::SyncMessage(value) => value.serialize(), +// Message::RpcCall(value) => value.serialize(), +// Message::InitRequest(value) => value.serialize(), +// Message::InitData(value) => value.serialize(), +// Message::HeartBeat(value) => value.serialize(), +// Message::HeartBeatReply(value) => value.serialize(), +// } +// } +// } + +impl Serialize for Message { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + match &self { + Message::SyncMessage(value) => value.serialize(), + Message::RpcCall(value) => value.serialize(), + Message::InitRequest(value) => value.serialize(), + Message::InitData(value) => value.serialize(), + Message::HeartBeat(value) => value.serialize(), + Message::HeartBeatReply(value) => value.serialize(), + } + } +} + +impl Deserialize for Message { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (_, message_type) = i32::parse(&b[9..13])?; + + match MessageType::from(message_type) { + MessageType::SyncMessage => { + let (size, res) = SyncMessage::parse(&b)?; + + Ok((size, Message::SyncMessage(res))) + } + MessageType::RpcCall => { + let (size, res) = RpcCall::parse(&b)?; + + Ok((size, Message::RpcCall(res))) + } + MessageType::InitRequest => { + let (size, res) = InitRequest::parse(&b)?; + + Ok((size, Message::InitRequest(res))) + } + MessageType::InitData => { + let (size, res) = InitData::parse(&b)?; + + Ok((size, Message::InitData(res))) + } + MessageType::HeartBeat => { + let (size, res) = HeartBeat::parse(&b)?; + + Ok((size, Message::HeartBeat(res))) + } + MessageType::HeartBeatReply => { + let (size, res) = HeartBeatReply::parse(&b)?; + + Ok((size, Message::HeartBeatReply(res))) + } + } + } +} + +/// Type of an SignalProxy Message +/// The first element in the VariantList that is received +#[repr(i32)] +#[derive(Copy, Clone, Debug, std::cmp::PartialEq)] +pub enum MessageType { + /// Bidirectional + SyncMessage = 0x00000001, + /// Bidirectional + RpcCall = 0x00000002, + InitRequest = 0x00000003, + InitData = 0x00000004, + /// Bidirectional + HeartBeat = 0x00000005, + /// Bidirectional + HeartBeatReply = 0x00000006, +} + +impl From<i32> for MessageType { + fn from(val: i32) -> Self { + match val { + 0x00000001 => MessageType::SyncMessage, + 0x00000002 => MessageType::RpcCall, + 0x00000003 => MessageType::InitRequest, + 0x00000004 => MessageType::InitData, + 0x00000005 => MessageType::HeartBeat, + 0x00000006 => MessageType::HeartBeatReply, + _ => unimplemented!(), + } + } +} diff --git a/src/message/signalproxy/objects/aliasmanager.rs b/src/message/signalproxy/objects/aliasmanager.rs new file mode 100644 index 0000000..828caaa --- /dev/null +++ b/src/message/signalproxy/objects/aliasmanager.rs @@ -0,0 +1,46 @@ +use crate::primitive::{Variant, VariantMap}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct AliasManager { + pub aliases: Vec<Alias>, +} + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct Alias { + name: String, + expansion: String, +} + +impl AliasManager { + /// Client to Server + /// + /// Replaces all properties of the object with the content of the + /// "properties" parameter. This parameter is in network representation. + /// + fn request_update(self: &mut Self, properties: VariantMap) { + self.update(properties); + } + + /// Server to Client + fn add_alias(self: &mut Self, name: String, expansion: String) { + self.aliases.push(Alias { name, expansion }); + } + + /// Server to Client + /// + /// Replaces all properties of the object with the content of the + /// "properties" parameter. This parameter is in network representation. + /// + fn update(self: &mut Self, properties: VariantMap) { + let mut alias: Vec<Alias> = Vec::new(); + + // for (i, name) in match_variant!(properties[&"Aliases".to_string()], Variant::String) { + // alias.push(Alias { + // name, + // expansion: match_variant!(properties["Aliases"], Variant::String)["expansions"][i], + // }) + // } + + self.aliases = alias + } +} diff --git a/src/message/signalproxy/objects/backlogmanager.rs b/src/message/signalproxy/objects/backlogmanager.rs new file mode 100644 index 0000000..86a7f61 --- /dev/null +++ b/src/message/signalproxy/objects/backlogmanager.rs @@ -0,0 +1,161 @@ +// interface BacklogManager { +// +// +// // C->S calls +// +// /** +// * Loads backlog for `bufferId`, starting at message `first`, up to `last` +// * (plus `additional` more messages after `last`) but at most `limit` +// * messages total. +// */ +// requestBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int) +// /** +// * Same as `requestBacklog`, but only messages of a certain message `type` +// * with certain `flags` set. +// */ +// requestBacklogFiltered(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int, type: Int, flags: Int) +// /** +// * Same as `requestBacklog`, but applied to all buffers. +// */ +// requestBacklogAll(first: MsgId, last: MsgId, limit: Int, additional: Int) +// /** +// * Same as `requestBacklogFiltered`, but applied to all buffers. +// */ +// requestBacklogAllFiltered(first: MsgId, last: MsgId, limit: Int, additional: Int, type: Int, flags: Int) +// +// +// // S->C calls +// +// /** +// * The response to `requestBacklog`, with the messages encoded as QVariants +// * in the `messages` parameter. +// */ +// receiveBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int, messages: QVariantList) +// /** +// * The response to `requestBacklogFiltered`, with the messages encoded as +// * QVariants in the `messages` parameter. +// */ +// receiveBacklogFiltered(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int, type: Int, flags: Int, messages: QVariantList) +// /** +// * The response to `requestBacklogAll`, with the messages encoded as +// * QVariants in the `messages` parameter. +// */ +// receiveBacklogAll(first: MsgId, last: MsgId, limit: Int, additional: Int, messages: QVariantList) +// /** +// * The response to `requestBacklogAllFiltered`, with the messages encoded as +// * QVariants in the `messages` parameter. +// */ +// receiveBacklogAllFiltered(first: MsgId, last: MsgId, limit: Int, additional: Int, type: Int, flags: Int, messages: QVariantList) +// } + +use crate::primitive::VariantList; + +/// Receive and Request Backlog +/// All "request" functions are Client to Server and all "receive" functions are Server to Client +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct BacklogManager {} + +impl BacklogManager { + /// Loads backlog for `bufferId`, starting at message `first`, up to `last` + /// (plus `additional` more messages after `last`) but at most `limit` + /// messages total. + fn requestBacklog( + self: Self, + buffer_id: u32, + first: u32, + last: u32, + limit: u32, + additional: u32, + ) { + unimplemented!() + } + + /// Same as `requestBacklog`, but only messages of a certain message `type` + /// with certain `flags` set. + fn requestBacklogFiltered( + self: Self, + buffer_id: u32, + first: u32, + last: u32, + limit: u32, + additional: u32, + msgtype: u32, + flags: u32, + ) { + unimplemented!() + } + + /// Same as `requestBacklog`, but applied to all buffers. + fn requestBacklogAll(self: Self, first: u32, last: u32, limit: u32, additional: u32) { + unimplemented!() + } + + /// Same as `requestBacklogFiltered`, but applied to all buffers. + fn requestBacklogAllFiltered( + self: Self, + first: u32, + last: u32, + limit: u32, + additional: u32, + msgtype: u32, + flags: u32, + ) { + unimplemented!() + } + + /// The response to `requestBacklog`, with the messages encoded as Variants + /// in the `messages` parameter. + fn receiveBacklog( + self: Self, + buffer_id: u32, + first: u32, + last: u32, + limit: u32, + additional: u32, + messages: VariantList, + ) { + unimplemented!() + } + + /// The response to `requestBacklogFiltered`, with the messages encoded as + /// Variants in the `messages` parameter. + fn receiveBacklogFiltered( + self: Self, + buffer_id: u32, + first: u32, + last: u32, + limit: u32, + additional: u32, + msgtype: u32, + flags: u32, + messages: VariantList, + ) { + unimplemented!() + } + + /// Same as `receiveBacklog`, but applied to all buffers. + fn receiveBacklogAll( + self: Self, + first: u32, + last: u32, + limit: u32, + additional: u32, + messages: VariantList, + ) { + unimplemented!() + } + + /// Same as `receiveBacklogFiltered`, but applied to all buffers. + fn receiveBacklogAllFiltered( + self: Self, + first: u32, + last: u32, + limit: u32, + additional: u32, + msgtype: u32, + flags: u32, + messages: VariantList, + ) { + unimplemented!() + } +} diff --git a/src/message/signalproxy/objects/buffersyncer.rs b/src/message/signalproxy/objects/buffersyncer.rs new file mode 100644 index 0000000..7ee4ca5 --- /dev/null +++ b/src/message/signalproxy/objects/buffersyncer.rs @@ -0,0 +1,74 @@ +use crate::message::signalproxy::MessageType; +use std::collections::HashMap; + +// use default_macro::default; +// #[default(crate::message::signalproxy::objects::BufferSyncerClient)] +pub struct BufferSyncer { + pub activities: HashMap<u32, MessageType>, + pub highlight_counts: HashMap<u32, u32>, + pub last_seen_msg: HashMap<u32, u32>, + pub marker_line: HashMap<u32, u32>, +} + +pub trait BufferSyncerServer { + fn activities(self: &Self) -> &HashMap<u32, MessageType>; + fn activities_mut(self: &mut Self) -> &mut HashMap<u32, MessageType>; + + fn highlight_counts(self: &Self) -> &HashMap<u32, u32>; + fn highlight_counts_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn last_seen_msg(self: &Self) -> &HashMap<u32, u32>; + fn last_seen_msg_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn marker_line(self: &Self) -> &HashMap<u32, u32>; + fn marker_line_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn request_mark_buffer_as_read(buffer: u32); + fn request_merge_buffers_permanently(buffer1: u32, buffer2: u32); + fn request_purge_buffer_ids(); + fn request_remove_buffer(buffer: u32); + fn request_rename_buffer(buffer: u32, new_name: String); + + fn request_set_last_seen_msg(self: &mut Self, buffer: u32, msgid: u32) { + self.last_seen_msg_mut().insert(buffer, msgid); + } + + fn request_set_marker_line(self: &mut Self, buffer: u32, msgid: u32) { + self.marker_line_mut().insert(buffer, msgid); + } +} + +pub trait BufferSyncerClient { + fn activities(self: &Self) -> &HashMap<u32, MessageType>; + fn activities_mut(self: &mut Self) -> &mut HashMap<u32, MessageType>; + + fn highlight_counts(self: &Self) -> &HashMap<u32, u32>; + fn highlight_counts_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn last_seen_msg(self: &Self) -> &HashMap<u32, u32>; + fn last_seen_msg_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn marker_line(self: &Self) -> &HashMap<u32, u32>; + fn marker_line_mut(self: &mut Self) -> &mut HashMap<u32, u32>; + + fn mark_buffer_as_read(buffer: u32); + fn merge_buffers_permanently(buffer1: u32, buffer2: u32); + fn remove_buffer(buffer: u32); + fn rename_buffer(buffer: u32, new_name: String); + + fn set_buffer_activity(self: &mut Self, buffer: u32, activity: MessageType) { + self.activities_mut().insert(buffer, activity); + } + + fn set_highlight_count(self: &mut Self, buffer: u32, count: u32) { + self.highlight_counts_mut().insert(buffer, count); + } + + fn set_last_seen_msg(self: &mut Self, buffer: u32, msgid: u32) { + self.last_seen_msg_mut().insert(buffer, msgid); + } + + fn set_marker_line(self: &mut Self, buffer: u32, msgid: u32) { + self.marker_line_mut().insert(buffer, msgid); + } +} diff --git a/src/message/signalproxy/objects/identity.rs b/src/message/signalproxy/objects/identity.rs new file mode 100644 index 0000000..a710e5d --- /dev/null +++ b/src/message/signalproxy/objects/identity.rs @@ -0,0 +1,119 @@ +use crate::primitive::{Variant, VariantMap}; + +#[derive(Debug, Clone)] +pub struct Identity { + identity_id: i32, + identity_name: String, + real_name: String, + nicks: Vec<String>, + away_nick: String, + away_nick_enabled: bool, + away_reason: String, + away_reason_enabled: bool, + auto_away_enabled: bool, + auto_away_time: i32, + auto_away_reason: String, + auto_away_reason_enabled: bool, + detach_away_enabled: bool, + detach_away_reason: String, + detach_away_reason_enabled: bool, + ident: String, + kick_reason: String, + part_reason: String, + quit_reason: String, +} + +impl From<VariantMap> for Identity { + fn from(input: VariantMap) -> Self { + Identity { + identity_id: match_variant!(input.get("identityId").unwrap(), Variant::i32), + identity_name: match_variant!(input.get("identityName").unwrap(), Variant::String), + real_name: match_variant!(input.get("realName").unwrap(), Variant::String), + nicks: match_variant!(input.get("nicks").unwrap(), Variant::StringList), + away_nick: match_variant!(input.get("awayNick").unwrap(), Variant::String), + away_nick_enabled: match_variant!(input.get("awayNickEnabled").unwrap(), Variant::bool), + away_reason: match_variant!(input.get("awayReason").unwrap(), Variant::String), + away_reason_enabled: match_variant!( + input.get("awayReasonEnabled").unwrap(), + Variant::bool + ), + auto_away_enabled: match_variant!(input.get("autoAwayEnabled").unwrap(), Variant::bool), + auto_away_time: match_variant!(input.get("autoAwayTime").unwrap(), Variant::i32), + auto_away_reason: match_variant!(input.get("autoAwayReason").unwrap(), Variant::String), + auto_away_reason_enabled: match_variant!( + input.get("autoAwayReasonEnabled").unwrap(), + Variant::bool + ), + detach_away_enabled: match_variant!( + input.get("detachAwayEnabled").unwrap(), + Variant::bool + ), + detach_away_reason: match_variant!( + input.get("detachAwayReason").unwrap(), + Variant::String + ), + detach_away_reason_enabled: match_variant!( + input.get("detachAwayReasonEnabled").unwrap(), + Variant::bool + ), + ident: match_variant!(input.get("ident").unwrap(), Variant::String), + kick_reason: match_variant!(input.get("kickReason").unwrap(), Variant::String), + part_reason: match_variant!(input.get("partReason").unwrap(), Variant::String), + quit_reason: match_variant!(input.get("quitReason").unwrap(), Variant::String), + } + } +} + +impl Into<std::collections::HashMap<String, Variant>> for Identity { + fn into(self) -> VariantMap { + let mut res = VariantMap::with_capacity(19); + + res.insert("identityId".to_string(), Variant::i32(self.identity_id)); + res.insert( + "identityName".to_string(), + Variant::String(self.identity_name), + ); + res.insert("realName".to_string(), Variant::String(self.real_name)); + res.insert("nicks".to_string(), Variant::StringList(self.nicks)); + res.insert("awayNick".to_string(), Variant::String(self.away_nick)); + res.insert( + "awayNickEnabled".to_string(), + Variant::bool(self.away_nick_enabled), + ); + res.insert("awayReason".to_string(), Variant::String(self.away_reason)); + res.insert( + "awayReasonEnabled".to_string(), + Variant::bool(self.away_reason_enabled), + ); + res.insert( + "autoAwayEnabled".to_string(), + Variant::bool(self.auto_away_enabled), + ); + res.insert( + "autoAwayTime".to_string(), + Variant::i32(self.auto_away_time), + ); + res.insert( + "autoAwayReason".to_string(), + Variant::String(self.auto_away_reason), + ); + res.insert( + "detachAwayEnabled".to_string(), + Variant::bool(self.detach_away_enabled), + ); + res.insert( + "detachAwayReason".to_string(), + Variant::String(self.detach_away_reason), + ); + res.insert( + "detachAwayReasonEnabled".to_string(), + Variant::bool(self.detach_away_reason_enabled), + ); + res.insert("ident".to_string(), Variant::String(self.ident)); + res.insert("kickReason".to_string(), Variant::String(self.kick_reason)); + res.insert("partReason".to_string(), Variant::String(self.part_reason)); + res.insert("quitReason".to_string(), Variant::String(self.quit_reason)); + + res + } +} diff --git a/src/message/signalproxy/objects/mod.rs b/src/message/signalproxy/objects/mod.rs new file mode 100644 index 0000000..a84f6fa --- /dev/null +++ b/src/message/signalproxy/objects/mod.rs @@ -0,0 +1,12 @@ +// mod aliasmanager; +// mod backlogmanager; + +mod buffersyncer; +mod identity; + +pub use buffersyncer::*; +pub use identity::*; + +pub trait Act { + fn act(self: Self); +} diff --git a/src/message/signalproxy/rpccall.rs b/src/message/signalproxy/rpccall.rs new file mode 100644 index 0000000..2eac86d --- /dev/null +++ b/src/message/signalproxy/rpccall.rs @@ -0,0 +1,59 @@ +use crate::message::MessageType; +use crate::primitive::Message; +use crate::primitive::{Variant, VariantList}; +use crate::{Deserialize, Serialize}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub enum RpcCall { + DisplayMessage(DisplayMessage), +} + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct DisplayMessage { + pub message: Message, +} + +// #[derive(Clone, Debug, std::cmp::PartialEq)] +// pub struct RpcCall { +// pub slot_name: String, +// pub params: VariantList, +// } + +impl Serialize for RpcCall { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::RpcCall as i32)); + + match self { + RpcCall::DisplayMessage(msg) => { + res.push(Variant::StringUTF8("2displayMsg(Message)".to_string())); + res.push(Variant::Message(msg.message.clone())); + } + } + + res.serialize() + } +} + +impl Deserialize for RpcCall { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + let rpc = match_variant!(res.remove(0), Variant::StringUTF8); + + match rpc.as_str() { + "2displayMsg(Message)" => { + return Ok(( + size, + RpcCall::DisplayMessage(DisplayMessage { + message: match_variant!(res.remove(0), Variant::Message), + }), + )) + } + _ => unimplemented!(), + } + } +} diff --git a/src/message/signalproxy/syncmessage.rs b/src/message/signalproxy/syncmessage.rs new file mode 100644 index 0000000..737f3e0 --- /dev/null +++ b/src/message/signalproxy/syncmessage.rs @@ -0,0 +1,46 @@ +use crate::message::MessageType; +use crate::primitive::{Variant, VariantList}; +use crate::{Deserialize, Serialize}; + +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub struct SyncMessage { + class_name: String, + object_name: String, + slot_name: String, + params: VariantList, +} + +// impl Act for SyncMessage {} + +impl Serialize for SyncMessage { + fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> { + let mut res = VariantList::new(); + + res.push(Variant::i32(MessageType::SyncMessage as i32)); + res.push(Variant::StringUTF8(self.class_name.clone())); + res.push(Variant::StringUTF8(self.object_name.clone())); + res.push(Variant::StringUTF8(self.slot_name.clone())); + + res.append(&mut self.params.clone()); + + res.serialize() + } +} + +impl Deserialize for SyncMessage { + fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> { + let (size, mut res) = VariantList::parse(&b)?; + + res.remove(0); + + Ok(( + size, + Self { + class_name: match_variant!(res.remove(0), Variant::StringUTF8), + object_name: match_variant!(res.remove(0), Variant::StringUTF8), + slot_name: match_variant!(res.remove(0), Variant::StringUTF8), + params: res, + }, + )) + } +} |
