use std::result::Result; use failure::Error; use crate::protocol::error::ProtocolError; use crate::protocol::primitive::{String, StringList, Variant, VariantList}; use crate::util::get_msg_type; mod types; pub use types::{VariantMap, HandshakeDeserialize, HandshakeSerialize, HandshakeQRead}; use crate::match_variant; #[derive(Debug)] pub struct ConnAck { flags: u8, extra: i16, version: i8 } impl crate::protocol::primitive::deserialize::Deserialize for ConnAck { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (flen, flags) = u8::parse(b)?; let (elen, extra) = i16::parse(&b[flen..])?; let (vlen, version) = i8::parse(&b[(flen+elen)..])?; return Ok((flen+elen+vlen, Self {flags, extra, version})); } } #[derive(Debug)] pub struct ClientInit { pub client_version: String, // Version of the client pub client_date: String, // Build date of the client pub client_features: u32, pub feature_list: StringList // List of supported extended features } impl HandshakeSerialize for ClientInit { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(5); values.insert("MsgType".to_string(), Variant::String("ClientInit".to_string())); values.insert("ClientVersion".to_string(), Variant::String(self.client_version.clone())); values.insert("ClientDate".to_string(), Variant::String(self.client_date.clone())); values.insert("Features".to_string(), Variant::u32(self.client_features)); values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone())); return HandshakeSerialize::serialize(&values); } } impl HandshakeDeserialize for ClientInit { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; let msgtype = get_msg_type(&values["MsgType"])?; if msgtype == "ClientInit" { return Ok((len, Self { client_version: match_variant!(values, Variant::String, "ClientVersion"), client_date: match_variant!(values, Variant::String, "ClientDate"), feature_list: match_variant!(values, Variant::StringList, "FeatureList"), client_features: match_variant!(values, Variant::u32, "Features") })); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct ClientInitReject { pub error_string: String } impl HandshakeSerialize for ClientInitReject { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(2); values.insert("MsgType".to_string(), Variant::String("ClientInitReject".to_string())); values.insert("ErrorString".to_string(), Variant::String(self.error_string.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 = get_msg_type(&values["MsgType"])?; if msgtype == "ClientInitReject" { return Ok((len, Self { error_string: match_variant!(values, Variant::String, "ErrorString") })); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct ClientInitAck { pub core_features: u32, // Flags of supported legacy features pub core_configured: bool, // If the core has already been configured pub storage_backends: VariantList, // List of VariantMaps of info on available backends pub authenticators: VariantList, // List of VariantMaps of info on available authenticators pub feature_list: StringList, // List of supported extended features } impl HandshakeSerialize for ClientInitAck { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(6); values.insert("MsgType".to_string(), Variant::String("ClientInitAck".to_string())); values.insert("CoreFeatures".to_string(), Variant::u32(self.core_features)); values.insert("Configured".to_string(), Variant::bool(self.core_configured)); values.insert("StorageBackends".to_string(), Variant::VariantList(self.storage_backends.clone())); values.insert("Authenticators".to_string(), Variant::VariantList(self.authenticators.clone())); values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone())); return HandshakeSerialize::serialize(&values); } } impl HandshakeDeserialize for ClientInitAck { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; let msgtype = get_msg_type(&values["MsgType"])?; if msgtype == "ClientInitAck" { return Ok((len, Self { core_features: 0x00008000, core_configured: match_variant!(values, Variant::bool, "Configured"), storage_backends: match_variant!(values, Variant::VariantList, "StorageBackends"), authenticators: match_variant!(values, Variant::VariantList, "Authenticators"), feature_list: match_variant!(values, Variant::StringList, "FeatureList") })); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct ClientLogin { pub user: String, pub password: String } impl HandshakeSerialize for ClientLogin { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::new(); values.insert("MsgType".to_string(), Variant::String("ClientLogin".to_string())); values.insert("User".to_string(), Variant::String(self.user.clone())); values.insert("Password".to_string(), Variant::String(self.password.clone())); return HandshakeSerialize::serialize(&values); } } impl HandshakeDeserialize for ClientLogin { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; let msgtype = get_msg_type(&values["MsgType"])?; if msgtype == "ClientLogin" { return Ok((len, Self { user: match_variant!(values, Variant::String, "User"), password: match_variant!(values, Variant::String, "Password") })); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct ClientLoginAck; impl HandshakeSerialize for ClientLoginAck { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(1); values.insert("MsgType".to_string(), Variant::String("ClientLoginAck".to_string())); return HandshakeSerialize::serialize(&values); } } impl HandshakeDeserialize for ClientLoginAck { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; let msgtype = get_msg_type(&values["MsgType"])?; if msgtype == "ClientLogin" { return Ok((len, Self {})); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct ClientLoginReject { error: String } impl HandshakeSerialize for ClientLoginReject { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(1); values.insert("MsgType".to_string(), Variant::String("ClientLoginReject".to_string())); values.insert("ErrorString".to_string(), Variant::String(self.error.clone())); return HandshakeSerialize::serialize(&values); } } impl HandshakeDeserialize for ClientLoginReject { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; let msgtype = get_msg_type(&values["MsgType"])?; if msgtype == "ClientLogin" { return Ok((len, Self { error: match_variant!(values, Variant::String, "ErrorString")})); } else { bail!(ProtocolError::WrongMsgType); } } } #[derive(Debug)] pub struct SessionInit { identities: VariantList, buffers: VariantList, network_ids: VariantList, } impl HandshakeSerialize for SessionInit { fn serialize(&self) -> Result, Error> { let mut values: VariantMap = VariantMap::with_capacity(1); values.insert("MsgType".to_string(), Variant::String("SessionInit".to_string())); values.insert("Identities".to_string(), Variant::VariantList(self.identities.clone())); values.insert("BufferInfos".to_string(), Variant::VariantList(self.buffers.clone())); values.insert("NetworkIds".to_string(), Variant::VariantList(self.network_ids.clone())); 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 = get_msg_type(&values["MsgType"])?; if msgtype == "ClientLogin" { return Ok((len, Self { identities: match_variant!(values, Variant::VariantList, "Identities"), buffers: match_variant!(values, Variant::VariantList, "BufferInfos"), network_ids: match_variant!(values, Variant::VariantList, "NetworkIds") })); } else { bail!(ProtocolError::WrongMsgType); } } }