diff options
| author | Max Audron <audron@cocaine.farm> | 2020-01-14 12:35:46 +0100 |
|---|---|---|
| committer | Max Audron <audron@cocaine.farm> | 2020-01-17 10:48:27 +0100 |
| commit | 5d50a5f0c03baf460fee394decce5898812dbd2c (patch) | |
| tree | fc53a8ea19786be4dc57f9736cd4bf4e76026227 /src | |
| parent | initial implementation done (diff) | |
refactor parse impl
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 20 | ||||
| -rw-r--r-- | src/net.rs | 46 | ||||
| -rw-r--r-- | src/protocol/message/handshake.rs | 99 | ||||
| -rw-r--r-- | src/protocol/message/handshake/types.rs | 92 | ||||
| -rw-r--r-- | src/protocol/message/mod.rs | 3 | ||||
| -rw-r--r-- | src/protocol/mod.rs | 2 | ||||
| -rw-r--r-- | src/protocol/primitive/basic.rs | 270 | ||||
| -rw-r--r-- | src/protocol/primitive/mod.rs | 30 | ||||
| -rw-r--r-- | src/protocol/primitive/variant.rs | 334 | ||||
| -rw-r--r-- | src/tests/base_types.rs | 55 | ||||
| -rw-r--r-- | src/tests/handshake_types.rs | 29 | ||||
| -rw-r--r-- | src/tests/mod.rs | 8 | ||||
| -rw-r--r-- | src/tests/variant_types.rs | 88 | ||||
| -rw-r--r-- | src/types.rs | 54 | ||||
| -rw-r--r-- | src/types/basic.rs | 149 | ||||
| -rw-r--r-- | src/types/handshake.rs | 62 | ||||
| -rw-r--r-- | src/types/variant.rs | 298 | ||||
| -rw-r--r-- | src/util.rs | 27 |
18 files changed, 1092 insertions, 574 deletions
diff --git a/src/main.rs b/src/main.rs index cd45c87..78a4e2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,17 @@ mod consts; mod net; -mod types; + +mod protocol; #[macro_use] mod util; +#[cfg(test)] +mod tests; + //use util::Hex; +use protocol::primitive::{String, StringList}; +use protocol::message::{ClientInit}; fn main() -> std::io::Result<()> { let mut server = net::connect( @@ -15,11 +21,13 @@ fn main() -> std::io::Result<()> { false, )?; - let client = types::handshake::ClientInit { - client_version: String::from("Rust 0.0.0"), - build_date: String::from("today"), - client_features: 0x00000000, - feature_list: types::StringList::new() + let mut features = StringList::new(); + features.push("SynchronizedMarkerLine".to_string()); + let client = ClientInit { + client_version:String::from("Rust 0.0.0"), + client_date: String::from("1579009211"), + feature_list: features, + client_features: 0, }; server.login("audron", "audron", client); @@ -8,8 +8,8 @@ use std::vec::Vec; extern crate log; // use log::{info, warn, debug}; -use super::types; -use super::types::Serialize; + +use crate::protocol::message; pub struct Client { tcp_stream: TcpStream, @@ -20,12 +20,30 @@ pub struct Client { } impl Client { - pub fn login(&mut self, user: &'static str, pass: &'static str, client: types::handshake::ClientInit) { - self.tcp_stream.write(&client.serialize()).unwrap(); + pub fn login(&mut self, user: &'static str, pass: &'static str, client: message::ClientInit) { + use crate::protocol::message::handshake::{HandshakeDeserialize, HandshakeSerialize, HandshakeQRead, VariantMap}; + use crate::protocol::message::handshake::{ClientInit, ClientInitAck}; + use std::convert::TryInto; + + let sclientinit = &client.serialize(); + let len: u32 = sclientinit.len().try_into().unwrap(); +// self.tcp_stream.write(&len.to_be_bytes()).unwrap(); + self.tcp_stream.write(sclientinit).unwrap(); + + let mut buf: Vec<u8> = [0; 2048].to_vec(); + VariantMap::read(&mut self.tcp_stream, &mut buf); + + // println!("{:?}", buf); + let res = ClientInitAck::parse(&buf); + println!("{:?}", res) } } pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) -> Result<Client, Error> { + use crate::protocol::primitive::serialize::Serialize; + use crate::protocol::primitive::deserialize::Deserialize; + use crate::protocol::primitive::qread::QRead; + //let mut s = BufWriter::new(TcpStream::connect(format!("{}:{}", address, port)).unwrap()); let mut s = TcpStream::connect(format!("{}:{}", address, port)).unwrap(); @@ -45,9 +63,27 @@ pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) - init.extend(proto.to_be_bytes().iter()); s.write(&init)?; + #[derive(Debug)] + struct ConnAck { + flags: u8, + extra: i16, + version: i8 + } + + impl Deserialize for ConnAck { + fn parse(b: &[u8]) -> (usize, Self) { + let (flen, flags) = u8::parse(b); + let (elen, extra) = i16::parse(&b[flen..]); + let (vlen, version) = i8::parse(&b[(flen+elen)..]); + + return (flen+elen+vlen, Self {flags, extra, version}); + } + } + let mut buf = [0; 4]; s.read_exact(&mut buf)?; - println!("Received: {:?}", buf); + let (_, val) = ConnAck::parse(&buf); + println!("Received: {:?}", val); let server: Client = Client { tcp_stream: s, diff --git a/src/protocol/message/handshake.rs b/src/protocol/message/handshake.rs new file mode 100644 index 0000000..918c424 --- /dev/null +++ b/src/protocol/message/handshake.rs @@ -0,0 +1,99 @@ +use crate::protocol::primitive::{String, StringList, Variant, VariantList}; +use crate::protocol::primitive::{serialize, deserialize, qread}; + +mod types; +pub use types::{VariantMap, HandshakeDeserialize, HandshakeSerialize, HandshakeQRead}; + +use crate::match_variant; +#[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) -> Vec<u8> { + 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]) -> (usize, Self) { + let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b); + + return (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") + }); + } +} + +#[derive(Debug)] +pub struct ClientInitReject { + pub error_string: String +} + +impl HandshakeSerialize for ClientInitReject { + fn serialize(&self) -> Vec<u8> { + let mut values: VariantMap = VariantMap::with_capacity(2); + values.insert("MsgProtocol::Primitive".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]) -> (usize, Self) { + let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b); + + return (len, Self { + error_string: match_variant!(values, Variant::String, "ErrorString") + }); + } +} + +#[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 backend_info: VariantList, // List of VariantMaps of info on available backends + pub authenticator_info: 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) -> Vec<u8> { + let mut values: VariantMap = VariantMap::with_capacity(2); + values.insert("MsgProtocol::Primitive".to_string(), Variant::String("ClientInitAck".to_string())); + values.insert("CoreFeatures".to_string(), Variant::u32(self.core_features)); + values.insert("CoreConfigured".to_string(), Variant::bool(self.core_configured)); + values.insert("BackendInfo".to_string(), Variant::VariantList(self.backend_info.clone())); + values.insert("AuthenticatorInfo".to_string(), Variant::VariantList(self.authenticator_info.clone())); + values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone())); + return HandshakeSerialize::serialize(&values); + } +} + +impl HandshakeDeserialize for ClientInitAck { + fn parse(b: &[u8]) -> (usize, Self) { + let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b); + + return (len, Self { + core_features: match_variant!(values, Variant::u32, "CoreFeatures"), + core_configured: match_variant!(values, Variant::bool, "CoreConfigured"), + backend_info: match_variant!(values, Variant::VariantList, "BackendInfo"), + authenticator_info: match_variant!(values, Variant::VariantList, "AuthenticatorInfo"), + feature_list: match_variant!(values, Variant::StringList, "FeatureList") + }); + } +} diff --git a/src/protocol/message/handshake/types.rs b/src/protocol/message/handshake/types.rs new file mode 100644 index 0000000..d6ea346 --- /dev/null +++ b/src/protocol/message/handshake/types.rs @@ -0,0 +1,92 @@ +use std::io::Read; +use std::vec::Vec; +use std::net::TcpStream; +use std::convert::TryInto; +use std::collections::HashMap; + +use crate::util; +use crate::protocol::primitive::{String, Variant}; +use crate::protocol::primitive::serialize::Serialize; +use crate::protocol::primitive::deserialize::Deserialize; +use crate::protocol::primitive::qread::QRead; + +pub trait HandshakeSerialize { + fn serialize(&self) -> Vec<u8>; +} + +pub trait HandshakeDeserialize { + fn parse(b: &[u8]) -> (usize, Self); +} + +pub trait HandshakeQRead { + fn read(stream: &mut std::net::TcpStream, buf: &mut [u8]) -> usize; +} + + +pub type VariantMap = HashMap<String, Variant>; + +impl HandshakeSerialize for VariantMap { + fn serialize<'a>(&'a self) -> Vec<u8> { + let mut res: Vec<u8> = Vec::new(); + + for (k, v) in self { + let key = Variant::String(k.clone()); + res.extend(key.serialize()); + res.extend(v.serialize()); + } + + util::insert_bytes(0, &mut res, &mut [0, 0, 0, 10]); + + let len: i32 = res.len().try_into().unwrap(); + util::insert_bytes(0, &mut res, &mut ((len + 4).to_be_bytes())); + println!("len: {:?}", len + 4); + + return res; + } +} + +impl HandshakeDeserialize for VariantMap { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, len) = i32::parse(&b[0..4]); + + let mut pos: usize = 8; + let mut map = VariantMap::new(); + let ulen: usize = len as usize; + loop { + if (pos) >= ulen { break; } + let (nlen, name) = Variant::parse(&b[(pos)..]); + pos += nlen; + + let (vlen, value) = Variant::parse(&b[(pos)..]); + pos += vlen; + + if let Variant::StringUTF8(x) = name { + map.insert(x, value); + } + } + + return (pos, map); + } +} + +impl HandshakeQRead for VariantMap { + fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..4]).unwrap(); + let (_, len) = i32::parse(&b[0..4]); + println!("len: {:?}", len); + + // Read the 00 00 00 0a VariantType bytes and discard + let mut tbuf = [0; 4]; + s.read(&mut tbuf).unwrap(); + + let mut pos = 4; + let len: usize = len as usize; + loop { + if pos >= (len - 4) { break; } + pos += Variant::read(&mut s, &mut b[pos..]); + pos += Variant::read(&mut s, &mut b[(pos+4..)]); + } + + return pos; + } +} diff --git a/src/protocol/message/mod.rs b/src/protocol/message/mod.rs new file mode 100644 index 0000000..3b6d1a8 --- /dev/null +++ b/src/protocol/message/mod.rs @@ -0,0 +1,3 @@ +pub mod handshake; + +pub use handshake::*; diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs new file mode 100644 index 0000000..044a28b --- /dev/null +++ b/src/protocol/mod.rs @@ -0,0 +1,2 @@ +pub mod message; +pub mod primitive; diff --git a/src/protocol/primitive/basic.rs b/src/protocol/primitive/basic.rs new file mode 100644 index 0000000..100da20 --- /dev/null +++ b/src/protocol/primitive/basic.rs @@ -0,0 +1,270 @@ +#[allow(dead_code)] +pub const VOID: u32 = 0x00000000; +pub const BOOL: u32 = 0x00000001; +pub const QCHAR: u32 = 0x00000007; + +pub const QVARIANT: u32 = 0x00000090; +pub const QVARIANTMAP: u32 = 0x00000008; +pub const QVARIANTLIST: u32 = 0x00000009; + +pub const QSTRING: u32 = 0x0000000a; +pub const QSTRINGLIST: u32 = 0x0000000b; +pub const QBYTEARRAY: u32 = 0x0000000c; + +pub const QTIME: u32 = 0x0000000f; +pub const QDATETIME: u32 = 0x00000010; +pub const USERTYPE: u32 = 0x0000007f; + + +// Basic types +pub const LONG: u32 = 0x00000081; // int64_t +pub const INT: u32 = 0x00000002; // int32_t +pub const SHORT: u32 = 0x00000082; // int16_t +pub const CHAR: u32 = 0x00000083; // int8_t + +pub const ULONG: u32 = 0x00000084; // uint64_t +pub const UINT: u32 = 0x00000003; // uint32_t +pub const USHORT: u32 = 0x00000085; // uint16_t +pub const UCHAR: u32 = 0x00000086; // uint8_t + +extern crate byteorder; +use std::io::Cursor; +use byteorder::{ByteOrder, BigEndian, ReadBytesExt}; + +use std::io::Read; +use std::vec::Vec; +use std::net::TcpStream; +use std::convert::TryInto; + +use crate::util; +use crate::protocol::primitive::{deserialize, serialize, qread}; + +impl deserialize::Deserialize for bool { + fn parse(b: &[u8]) -> (usize, Self) { + if b[0] == 0 { return (1, false) } else { return (1, true) }; + } +} + +impl qread::QRead for bool { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut [b[0]]).unwrap() + } +} + +impl deserialize::Deserialize for u64 { + fn parse(b: &[u8]) -> (usize, Self) { + return (8, BigEndian::read_u64(b)); + } +} + +impl qread::QRead for u64 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..8]).unwrap() + } +} + +impl deserialize::Deserialize for u32 { + fn parse(b: &[u8]) -> (usize, Self) { + // self = &rdr.read_u32::<BigEndian>().unwrap() + return (4, BigEndian::read_u32(b)); + } +} + +impl qread::QRead for u32 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..4]).unwrap() + } +} + +impl deserialize::Deserialize for u16 { + fn parse(b: &[u8]) -> (usize, Self) { + return (2, BigEndian::read_u16(b)); + } +} + +impl qread::QRead for u16 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..2]).unwrap() + } +} + +impl deserialize::Deserialize for u8 { + fn parse(b: &[u8]) -> (usize, Self) { + return (1, b[0]); + } +} + +impl qread::QRead for u8 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut [b[0]]).unwrap() + } +} + +impl deserialize::Deserialize for i64 { + fn parse(b: &[u8]) -> (usize, Self) { + return (8, BigEndian::read_i64(b)); + } +} + +impl qread::QRead for i64 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..8]).unwrap() + } +} + +impl deserialize::Deserialize for i32 { + fn parse(b: &[u8]) -> (usize, Self) { + let mut rdr = Cursor::new(&b[0..4]); + return (4, rdr.read_i32::<BigEndian>().unwrap()); + } +} + +impl qread::QRead for i32 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..4]).unwrap() + } +} + +impl deserialize::Deserialize for i16 { + fn parse(b: &[u8]) -> (usize, Self) { + return (2, BigEndian::read_i16(b)); + } +} + +impl qread::QRead for i16 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..2]).unwrap() + } +} + +impl deserialize::Deserialize for i8 { + fn parse(b: &[u8]) -> (usize, Self) { + return (1, b[0].try_into().unwrap()); + } +} + +impl qread::QRead for i8 { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut [b[0]]).unwrap() + } +} + + + +pub type String = std::string::String; +impl serialize::Serialize for String { + fn serialize(&self) -> Vec<u8> { + let mut res: Vec<u8> = Vec::new(); + + let utf16: Vec<u16> = self.encode_utf16().collect(); + for i in utf16 { + res.extend(i.to_be_bytes().iter()); + } + + util::prepend_byte_len(&mut res); + return res; + } +} + +impl serialize::SerializeUTF8 for String { + fn serialize_utf8(&self) -> Vec<u8> { + let mut res: Vec<u8> = Vec::new(); + res.extend(self.clone().into_bytes()); + util::prepend_byte_len(&mut res); + return res; + } +} + +impl deserialize::Deserialize for String { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, len) = i32::parse(&b[0..4]); + + let ulen = len as usize; + let mut pos: usize = 4; + let mut chars: Vec<u16> = Vec::new(); + loop { + if pos >= (ulen + 4) { break; } + let (slen, uchar) = u16::parse(&b[pos..(pos+2)]); + chars.push(uchar); + pos += slen; + } + + let res: String = String::from_utf16(&chars).unwrap(); + return (pos, res); + } +} + +impl deserialize::DeserializeUTF8 for String { + fn parse_utf8(b: &[u8]) -> (usize, Self) { + use crate::protocol::primitive::deserialize::Deserialize; + let (_, len) = i32::parse(&b[0..4]); + + let ulen = len as usize; + + let res: String = String::from_utf8(b[4..(ulen+4)].to_vec()).unwrap(); + return (ulen + 4, res); + } +} + +impl qread::QRead for String { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + use crate::protocol::primitive::deserialize::Deserialize; + + s.read(&mut b[0..4]).unwrap(); + let (_, len) = i32::parse(&b[0..4]); + + let ulen = len as usize; + s.read(&mut b[4..(4+ulen)]).unwrap(); + + return 4 + ulen; + } +} + +pub type StringList = Vec<String>; +impl serialize::Serialize for StringList { + fn serialize(&self) -> Vec<u8> { + let len: i32 = self.len().try_into().unwrap(); + let mut res: Vec<u8> = Vec::new(); + + res.extend(len.to_be_bytes().iter()); + for x in self { + res.extend(x.serialize()); + } + + return res; + } +} + +impl deserialize::Deserialize for StringList { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, len) = i32::parse(&b[0..4]); + let mut res: StringList = StringList::new(); + + let mut pos = 4; + if len > 0 { + for _ in 0..len { + let (lpos, val) = String::parse(&b[pos..]); + pos += lpos; + res.push(val); + } + } + + return (pos, res); + } +} + +impl qread::QRead for StringList { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + use crate::protocol::primitive::deserialize::Deserialize; + + s.read(&mut b[0..4]).unwrap(); + let (_, len) = i32::parse(&b[0..4]); + + let mut pos: usize = 0; + for _ in 0..len { + pos += String::read(s, &mut b[pos..]); + } + + return 4 + pos; + } +} diff --git a/src/protocol/primitive/mod.rs b/src/protocol/primitive/mod.rs new file mode 100644 index 0000000..03c62bc --- /dev/null +++ b/src/protocol/primitive/mod.rs @@ -0,0 +1,30 @@ +#[allow(dead_code)] +pub mod basic; +pub mod variant; + +pub use basic::*; +pub use variant::*; + +pub mod serialize { + pub trait Serialize { + fn serialize(&self) -> Vec<u8>; + } + pub trait SerializeUTF8 { + fn serialize_utf8(&self) -> Vec<u8>; + } +} + +pub mod deserialize { + pub trait Deserialize { + fn parse(b: &[u8]) -> (usize, Self); + } + pub trait DeserializeUTF8 { + fn parse_utf8(b: &[u8]) -> (usize, Self); + } +} + +pub mod qread { + pub trait QRead { + fn read(stream: &mut std::net::TcpStream, buf: &mut [u8]) -> usize; + } +} diff --git a/src/protocol/primitive/variant.rs b/src/protocol/primitive/variant.rs new file mode 100644 index 0000000..f868e9f --- /dev/null +++ b/src/protocol/primitive/variant.rs @@ -0,0 +1,334 @@ +use std::vec::Vec; +use std::convert::TryInto; +use std::collections::HashMap; + +use std::io::Read; +use std::net::TcpStream; + +use crate::util; +use crate::protocol::primitive::serialize::{Serialize, SerializeUTF8}; +use crate::protocol::primitive::deserialize::{Deserialize, DeserializeUTF8}; +use crate::protocol::primitive::qread::QRead; +use crate::protocol::primitive::{String,StringList}; +use crate::protocol::primitive; + +pub type VariantMap = HashMap<String, Variant>; + +impl Serialize for VariantMap { + fn serialize<'a>(&'a self) -> Vec<u8> { + let mut res: Vec<u8> = Vec::new(); + + for (k, v) in self { + res.extend(k.serialize()); + res.extend(v.serialize()); + } + + let len: i32 = self.len().try_into().unwrap(); + util::insert_bytes(0, &mut res, &mut len.to_be_bytes()); + + return res; + } +} + +impl Deserialize for VariantMap { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, len) = i32::parse(&b[0..4]); + println!("len: {:?}", len); + + let mut pos = 4; + let mut map = VariantMap::new(); + for _ in 0..len { + println!("pos: {:?}", pos); + let (nlen, name) = String::parse(&b[(pos)..]); + pos += nlen; + println!("pos: {:?}", pos); + + let (vlen, value) = Variant::parse(&b[(pos)..]); + pos += vlen; + println!("pos: {:?}", pos); + + map.insert(name, value); + } + + return (pos, map); + } +} + +impl QRead for VariantMap { + fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..4]).unwrap(); + + + let (_, len) = i32::parse(&b[0..4]); + + let mut pos = 4; + for _ in 0..len { + pos += String::read(&mut s, &mut b[pos..]); + pos += Variant::read(&mut s, &mut b[(pos+3..)]); + } + + return pos; + } +} + +///////////////////////////////////////////////////////////////////////// +pub type VariantList = Vec<Variant>; + +impl Serialize for VariantList { + fn serialize(&self) -> Vec<u8> { + let len: i32 = self.len().try_into().unwrap(); + let mut res: Vec<u8> = Vec::new(); + + res.extend(len.to_be_bytes().iter()); + for v in self { + res.extend(v.serialize().iter()); + } + + return res; + } +} + +impl Deserialize for VariantList { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, len) = i32::parse(&b[0..4]); + + let mut res: VariantList = VariantList::new(); + let mut pos: usize = 4; + for _ in 0..len { + let (vlen, val) = Variant::parse(&b[pos..]); + res.push(val); + pos += vlen; + } + + return (pos, res); + } +} + +impl QRead for VariantList { + fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize { + s.read(&mut b[0..4]).unwrap(); + + let (_, len) = i32::parse(&b[0..4]); + + let mut pos = 4; + for _ in 0..len { + pos += Variant::read(&mut s, &mut b[(pos+3..)]); + } + + return pos; + } +} + +///////////////////////////////////////////////////////////////////////// +#[allow(non_camel_case_types, dead_code)] +#[derive(Clone, Debug, std::cmp::PartialEq)] +pub enum Variant { + Unknown, + VariantMap(VariantMap), + VariantList(VariantList), + String(String), + StringUTF8(String), + StringList(StringList), + bool(bool), + u64(u64), + u32(u32), + u16(u16), + u8(u8), + i64(i64), + i32(i32), + i16(i16), + i8(i8), +} + +impl Serialize for Variant { + fn serialize(&self) -> Vec<u8> { + let unknown: u8 = 0x00; + let mut res: Vec<u8> = Vec::new(); + + match self { + Variant::Unknown => { + return res; + }, + Variant::VariantMap(v) => { + res.extend(primitive::QVARIANTMAP.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize().iter()); + }, + Variant::VariantList(v) => { + res.extend(primitive::QVARIANTLIST.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize().iter()); + }, + Variant::String(v) => { + res.extend(primitive::QSTRING.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize().iter()); + }, + Variant::StringUTF8(v) => { + res.extend(primitive::QBYTEARRAY.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize_utf8().iter()); + }, + Variant::StringList(v) => { + res.extend(primitive::QSTRINGLIST.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize().iter()); + }, + Variant::bool(v) => { + res.extend(primitive::BOOL.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + let i = *v as i8; + res.extend(i.to_be_bytes().iter()); + }, + Variant::u64(v) => { + res.extend(primitive::ULONG.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::u32(v) => { + res.extend(primitive::UINT.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::u16(v) => { + res.extend(primitive::USHORT.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::u8(v) => { + res.extend(primitive::UCHAR.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::i64(v) => { + res.extend(primitive::LONG.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::i32(v) => { + res.extend(primitive::INT.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::i16(v) => { + res.extend(primitive::SHORT.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + Variant::i8(v) => { + res.extend(primitive::CHAR.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.to_be_bytes().iter()); + }, + } + + return res + } +} + +impl Deserialize for Variant { + fn parse(b: &[u8]) -> (usize, Self) { + let (_, qtype) = i32::parse(&b[0..4]); + let qtype = qtype as u32; + + #[allow(unused_variables)] + let unknown: u8 = b[4]; + + let len = 5; + match qtype { + primitive::QVARIANTMAP => { + let (vlen, value) = VariantMap::parse(&b[len..]); + return (len+vlen, Variant::VariantMap(value)); + }, + primitive::QVARIANTLIST => { + let (vlen, value) = VariantList::parse(&b[len..]); + return (len+vlen, Variant::VariantList(value)); + }, + primitive::QSTRING => { + let (vlen, value) = String::parse(&b[len..]); + return (len+vlen, Variant::String(value.clone())); + }, + primitive::QBYTEARRAY => { + let (vlen, value) = String::parse_utf8(&b[len..]); + return (len+vlen, Variant::StringUTF8(value.clone())); + }, + primitive::QSTRINGLIST => { + let (vlen, value) = StringList::parse(&b[len..]); + return (len+vlen, Variant::StringList(value.clone())); + }, + primitive::BOOL => { + let (vlen, value) = bool::parse(&b[len..]); + return (len+vlen, Variant::bool(value)); + }, + primitive::ULONG => { + let (vlen, value) = u64::parse(&b[len..]); + return (len+vlen, Variant::u64(value)); + }, + primitive::UINT => { + let (vlen, value) = u32::parse(&b[len..]); + return (len+vlen, Variant::u32(value)); + }, + primitive::USHORT => { + let (vlen, value) = u16::parse(&b[len..]); + return (len+vlen, Variant::u16(value)); + }, + primitive::UCHAR => { + let (vlen, value) = u8::parse(&b[len..]); + return (len+vlen, Variant::u8(value)); + }, + primitive::LONG => { + let (vlen, value) = i64::parse(&b[len..]); + return (len+vlen, Variant::i64(value)); + }, + primitive::INT => { + let (vlen, value) = i32::parse(&b[len..]); + return (len+vlen, Variant::i32(value)); + }, + primitive::SHORT => { + let (vlen, value) = i16::parse(&b[len..]); + return (len+vlen, Variant::i16(value)); + }, + primitive::CHAR => { + let (vlen, value) = i8::parse(&b[len..]); + return (len+vlen, Variant::i8(value)); + }, + _ => { + return (0, Variant::Unknown); + } + } + } +} + +impl QRead for Variant { + fn read(s: &mut TcpStream, b: &mut [u8]) -> usize { + + s.read(&mut b[0..4]).unwrap(); + let (_, qtype) = i32::parse(&b[0..4]); + let qtype = qtype as u32; + + s.read(&mut [b[4]]).unwrap(); + #[allow(unused_variables)] + let unknown: u8 = b[4]; + + let mut len = 5; + match qtype { + primitive::QVARIANTMAP => len += VariantMap::read(s, &mut b[5..]), + primitive::QVARIANTLIST => len += VariantList::read(s, &mut b[5..]), + primitive::QSTRING => len += String::read(s, &mut b[5..]), + primitive::QBYTEARRAY => len += String::read(s, &mut b[5..]), + primitive::QSTRINGLIST => len += StringList::read(s, &mut b[5..]), + primitive::BOOL => len += bool::read(s, &mut b[5..]), + primitive::ULONG => len += u64::read(s, &mut b[5..]), + primitive::UINT => len += u32::read(s, &mut b[5..]), + primitive::USHORT => len += u16::read(s, &mut b[5..]), + primitive::UCHAR => len += u8::read(s, &mut b[5..]), + primitive::LONG => len += i64::read(s, &mut b[5..]), + primitive::INT => len += i32::read(s, &mut b[5..]), + primitive::SHORT => len += i16::read(s, &mut b[5..]), + primitive::CHAR => len += i8::read(s, &mut b[5..]), + _ => return len + } + + return len; + } +} diff --git a/src/tests/base_types.rs b/src/tests/base_types.rs new file mode 100644 index 0000000..a35f243 --- /dev/null +++ b/src/tests/base_types.rs @@ -0,0 +1,55 @@ +use crate::protocol::primitive::serialize::{Serialize, SerializeUTF8}; +use crate::protocol::primitive::deserialize::{Deserialize, DeserializeUTF8}; + +use crate::protocol::primitive::*; + +#[test] +pub fn serialize_string() { + let test_string: String = String::from("Configured"); + + assert_eq!(test_string.serialize(), [0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100]); +} + +#[test] +pub fn serialize_string_utf8() { + let test_string: String = String::from("Configured"); + + assert_eq!(test_string.serialize_utf8(), [0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100]); +} + +#[test] +pub fn deserialize_string() { + let test_bytes: &[u8] = &[0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1]; + let (len, res) = String::parse(test_bytes); + assert_eq!(res, "Configured"); + assert_eq!(len, 24); +} + +#[test] +pub fn deserialize_string_utf8() { + let test_bytes: &[u8] = &[0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 1]; + let (len, res) = String::parse_utf8(test_bytes); + assert_eq!(len, 14); + assert_eq!(res, "Configured"); +} + +#[test] +pub fn serialize_string_list() { + let mut test_list = StringList::new(); + test_list.push("Configured".to_string()); + assert_eq!( + test_list.serialize(), + [0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100] + ) +} + +#[test] +pub fn deserialize_string_list() { + let test_bytes: &[u8] = &[0, 0, 0, 24, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1]; + let mut test_list = StringList::new(); + test_list.push("Configured".to_string()); + println!("aaaaa"); + let (len, res) = StringList::parse(test_bytes); + assert_eq!(len, 28); + assert_eq!(test_list, res); +} diff --git a/src/tests/handshake_types.rs b/src/tests/handshake_types.rs new file mode 100644 index 0000000..99fc1ed --- /dev/null +++ b/src/tests/handshake_types.rs @@ -0,0 +1,29 @@ +use crate::protocol::message::handshake::{VariantMap, HandshakeSerialize, HandshakeDeserialize}; +use crate::protocol::primitive::{Variant}; + +#[test] +pub fn serialize_variantmap() { + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + let bytes = [0, 0, 0, 43, 0, 0, 0, 10, 0, 0, 0, 10, 0, + 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, + 0, 0, 0, 1, 0, 1].to_vec(); + assert_eq!( + test_variantmap.serialize(), + bytes + ); +} + +// #[test] +// pub fn deserialize_variantmap() { +// let test_bytes: &[u8] = &[0, 0, 0, 43, 0, 0, 0, 10, 0, 0, 0, 10, 0, +// 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, +// 0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; +// let mut test_variantmap = VariantMap::new(); +// test_variantmap.insert("Configured".to_string(), Variant::bool(true)); +// +// let (len, res) = VariantMap::parse(test_bytes); +// +// assert_eq!(len, 43); +// assert_eq!(res, test_variantmap); +// } diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..873046b --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +pub mod handshake_types; +pub mod variant_types; +pub mod base_types; + +use handshake_types::*; +use variant_types::*; +use base_types::*; diff --git a/src/tests/variant_types.rs b/src/tests/variant_types.rs new file mode 100644 index 0000000..8c4dedc --- /dev/null +++ b/src/tests/variant_types.rs @@ -0,0 +1,88 @@ +use crate::protocol::primitive::serialize::Serialize; +use crate::protocol::primitive::deserialize::Deserialize; + +use crate::protocol::primitive::{Variant, VariantList, VariantMap}; + +#[test] +pub fn serialize_variant_bool() { + let test_variant_true = Variant::bool(true); + let test_variant_false = Variant::bool(false); + assert_eq!( + test_variant_true.serialize(), + [0, 0, 0, 1, 0, 1] + ); + assert_eq!( + test_variant_false.serialize(), + [0, 0, 0, 1, 0, 0] + ); +} + +#[test] +pub fn deserialize_variant_bool() { + let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; + let (len, res) = Variant::parse(test_bytes); + assert_eq!(len, 6); + assert_eq!(res, Variant::bool(true)); +} + +#[test] +pub fn serialize_variantlist() { + let mut test_variantlist = VariantList::new(); + test_variantlist.push(Variant::bool(true)); + assert_eq!( + test_variantlist.serialize(), + [0, 0, 0, 1, 0, 0, 0, 1, 0, 1] + ); +} + +#[test] +pub fn deserialize_variantlist() { + let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; + let (len, res) = VariantList::parse(test_bytes); + let mut test_variantlist = VariantList::new(); + test_variantlist.push(Variant::bool(true)); + assert_eq!(len, 10); + assert_eq!(res, test_variantlist); +} + +#[test] +pub fn serialize_variantmap() { + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + let bytes = [0, 0, 0, 1, + 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, + 0, 0, 0, 1, 0, 1].to_vec(); + assert_eq!( + test_variantmap.serialize(), + bytes + ); +} + +#[test] +pub fn deserialize_variantmap() { + let test_bytes: &[u8] = &[0, 0, 0, 1, + 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, + 0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; + let (len, res) = VariantMap::parse(test_bytes); + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + assert_eq!(len, 34); + assert_eq!(res, test_variantmap); +} + +// +// 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. +// 0010 00 e2 36 3d 40 00 40 06 05 d7 7f 00 00 01 7f 00 ..6=@.@......... +// 0020 00 01 10 92 c0 dc e8 73 50 fe 2f 68 6d 9e 80 18 .......sP./hm... +// 0030 02 00 fe d6 00 00 01 01 08 0a 5f 0a 31 00 5f 0a .........._.1._. +// 0040 31 00 00 00 00 aa 00 00 00 0a 00 00 00 0c 00 00 1............... +// 0050 00 00 0a 43 6f 6e 66 69 67 75 72 65 64 00 00 00 ...Configured... +// 0060 01 00 01 00 00 00 0c 00 00 00 00 0c 43 6f 72 65 ............Core +// 0070 46 65 61 74 75 72 65 73 00 00 00 03 00 00 00 fe Features........ +// 0080 ff 00 00 00 0c 00 00 00 00 0c 4c 6f 67 69 6e 45 ..........LoginE +// 0090 6e 61 62 6c 65 64 00 00 00 01 00 01 00 00 00 0c nabled.......... +// 00a0 00 00 00 00 07 4d 73 67 54 79 70 65 00 00 00 0a .....MsgType.... +// 00b0 00 00 00 00 1a 00 43 00 6c 00 69 00 65 00 6e 00 ......C.l.i.e.n. +// 00c0 74 00 49 00 6e 00 69 00 74 00 41 00 63 00 6b 00 t.I.n.i.t.A.c.k. +// 00d0 00 00 0c 00 00 00 00 0f 53 74 6f 72 61 67 65 42 ........StorageB +// 00e0 61 63 6b 65 6e 64 73 00 00 00 09 00 00 00 00 00 ackends......... diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index 1c22ce6..0000000 --- a/src/types.rs +++ /dev/null @@ -1,54 +0,0 @@ -#[allow(dead_code)] -pub mod basic; -pub mod variant; -pub mod handshake; - -pub use basic::*; - -pub trait Serialize { - fn serialize(&self) -> Vec<u8>; -} - -pub trait Deserialize { - fn parse(&mut self, b: &[u8]) -> usize; -} - - -// 78 da 6c 54 6d 6b d3 50 14 7e 44 41 d1 09 -// 7e 50 10 19 a3 14 91 89 2f db fa b2 75 32 05 cd -// 2c 16 3b 19 6b d9 f7 98 dc a6 61 69 12 93 db ce -// f8 6f fc a3 ea 73 ce 4d ca 64 23 dc e4 bc 3c e7 -// 39 6f b7 05 ee fc 06 70 9f 67 03 22 78 49 6c 52 -// 7b ec 5b 53 9b f1 18 7b e8 e3 00 03 7d 1f a0 8b -// 1e e5 1a ff d0 e1 cf 4d 51 c6 59 5a 87 dc da c0 -// 0a bb 78 cb c0 1e de 20 47 01 83 16 b6 af d9 5e -// 51 1b 60 9f be 08 31 2c ed 47 f0 a9 cd d5 3b c3 -// 7b b4 29 5b 3e 39 4a bc c3 0e 1f 87 9c 63 89 ef -// 64 0b 90 61 41 eb 0f ea 3e 31 25 e3 92 1b 74 87 -// 5b 68 ec 0e 9b e8 31 73 87 0c 7b 08 99 7f 40 3d -// 60 be 0e e5 be 7a a4 49 83 43 3e 5d ea e2 e9 10 -// d9 a7 d4 65 17 33 fa 76 a9 1f f2 2b 83 69 e3 c3 -// 35 ce 23 e6 f1 69 7f d9 8c ea c1 d0 f8 76 59 98 -// 71 5c 5a 51 c5 f6 84 e7 35 26 a8 90 b2 00 69 3b -// a3 14 e3 17 89 43 9c 90 a0 c0 05 e5 02 63 5a 53 -// c8 52 9e 13 2f ad 25 f8 c8 26 65 14 86 1e 4b 7f -// 40 bb 7c 85 03 78 ba c6 7d c6 4f da 85 25 a5 25 -// a1 6f 1b 5f 88 0b 69 1b a9 2d d0 b8 15 f5 6f 3c -// 16 97 e4 90 cc 25 b1 9b 38 ad 47 e9 ac 21 3c e6 -// f4 19 17 69 3d 9b d4 7d 2e 48 22 23 22 84 e9 6a -// 1d 5b 38 d7 dc 31 c7 56 b1 26 91 57 fa 9e f0 19 -// 13 d1 22 c3 92 fc 56 97 74 a6 d1 46 3b 76 0b 93 -// 2a 5e b0 db 4b 7a 2a 0c b5 8a 85 a2 a6 8a 31 1a -// eb 53 ca b5 9e 9b e7 22 51 a5 ce ef 13 fd 33 5d -// 62 41 6c d3 bb 64 aa d6 bb 10 9c a7 31 86 36 37 -// 2b 99 59 44 de a4 fe da 7a 3e 13 cd 14 2a df 69 -// 7d 75 63 ce dc a8 bf c5 8e 0c 6b cb b4 ab 63 7a -// 4a bd 8e a9 ee 53 b2 0b a6 d9 91 e3 09 d9 a5 d1 -// aa 97 ca 27 3c 8f 38 91 4c a7 de 74 2d 3b 3e d3 -// fe e6 bc 2b 46 77 e4 eb 56 04 df 66 9f b2 d9 0b -// d6 9b d1 3a 24 32 a9 ef c1 94 5d e6 ca b0 c5 cc -// 01 f3 49 a4 a7 3e cb ea 73 7c a5 5c 29 cf b3 75 -// de ff 73 8c 18 e5 ba 77 13 33 7a 33 dc c4 e4 56 -// cd 28 d7 57 ff 5e 7d f5 85 ee 36 cf 9f bf 8d e7 -// ee 49 19 4d ab fc ca 9f 8d a7 e3 75 ab 1b e9 8f -// c1 fe 13 diff --git a/src/types/basic.rs b/src/types/basic.rs deleted file mode 100644 index dc5e8d5..0000000 --- a/src/types/basic.rs +++ /dev/null @@ -1,149 +0,0 @@ -#[allow(dead_code)] -pub const VOID: u32 = 0x00000000; -pub const BOOL: u32 = 0x00000001; -pub const QCHAR: u32 = 0x00000007; - -pub const QVARIANT: u32 = 0x00000090; -pub const QVARIANTMAP: u32 = 0x00000008; -pub const QVARIANTLIST: u32 = 0x00000009; - -pub const QSTRING: u32 = 0x0000000a; -pub const QSTRINGLIST: u32 = 0x0000000b; -pub const QBYTEARRAY: u32 = 0x0000000c; - -pub const QTIME: u32 = 0x0000000f; -pub const QDATETIME: u32 = 0x00000010; -pub const USERTYPE: u32 = 0x0000007f; - - -// Basic types -pub const LONG: u32 = 0x00000081; // int64_t -pub const INT: u32 = 0x00000002; // int32_t -pub const SHORT: u32 = 0x00000082; // int16_t -pub const CHAR: u32 = 0x00000083; // int8_t - -pub const ULONG: u32 = 0x00000084; // uint64_t -pub const UINT: u32 = 0x00000003; // uint32_t -pub const USHORT: u32 = 0x00000085; // uint16_t -pub const UCHAR: u32 = 0x00000086; // uint8_t - -extern crate byteorder; -use byteorder::{ByteOrder, BigEndian}; - -use std::vec::Vec; -use std::convert::TryInto; - -use crate::types; - -impl types::Deserialize for bool { - fn parse(&mut self, b: &[u8]) -> usize { - if b[0] == 0 { *self = false } else { *self = true }; - return 1; - } -} - -impl types::Deserialize for u64 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = BigEndian::read_u64(b); - return 8; - } -} -impl types::Deserialize for u32 { - fn parse(&mut self, b: &[u8]) -> usize { - // self = &rdr.read_u32::<BigEndian>().unwrap() - *self = BigEndian::read_u32(b); - return 4; - } -} -impl types::Deserialize for u16 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = BigEndian::read_u16(b); - return 2; - } -} -impl types::Deserialize for u8 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = b[0]; - return 1; - } -} - -impl types::Deserialize for i64 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = BigEndian::read_i64(b); - return 8; - } -} -impl types::Deserialize for i32 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = BigEndian::read_i32(b); - return 4; - } -} -impl types::Deserialize for i16 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = BigEndian::read_i16(b); - return 2; - } -} -impl types::Deserialize for i8 { - fn parse(&mut self, b: &[u8]) -> usize { - *self = b[0].try_into().unwrap(); - return 1; - } -} - - -pub type String = std::string::String; -impl types::Serialize for String { - fn serialize(&self) -> Vec<u8> { - let len: i32 = self.len().try_into().unwrap(); - let mut res: Vec<u8> = Vec::new(); - - res.extend(len.to_be_bytes().iter()); - res.extend(self.parse::<u16>().unwrap().to_be_bytes().iter()); - - return res; - } -} - -impl types::Deserialize for String { - fn parse(&mut self, b: &[u8]) -> usize { - let mut len: i32 = 0; - len.parse(&b[0..4]); - let ulen: usize = len as usize; - *self = BigEndian::read_u16(&b[(5)..(5+ulen)]).to_string(); - b.len() - } -} - -pub type StringList = Vec<String>; -impl types::Serialize for StringList { - fn serialize(&self) -> Vec<u8> { - let len: i32 = self.len().try_into().unwrap(); - let mut res: Vec<u8> = Vec::new(); - - res.extend(len.to_be_bytes().iter()); - for x in self { - res.extend(x.parse::<u16>().unwrap().to_be_bytes().iter()); - } - - return res; - } -} - -impl types::Deserialize for StringList { - fn parse(&mut self, b: &[u8]) -> usize { - let len: i32 = self.len().try_into().unwrap(); - let res: StringList = StringList::new(); - - let mut pos: usize = 0; - for _ in 0..len { - let mut val: String = String::new(); - pos = pos + val.parse(&b[pos..]); - } - - *self = res; - return pos; - } -} diff --git a/src/types/handshake.rs b/src/types/handshake.rs deleted file mode 100644 index cd79d29..0000000 --- a/src/types/handshake.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::types::{Serialize, Deserialize}; -use crate::types::variant::{Variant, VariantMap, VariantList}; -use crate::types::basic::{String, StringList}; - -pub struct ClientInit { - pub client_version: String, // Version of the client - pub build_date: String, // Build date of the client - pub client_features: u32, // Flags of supported legacy features - pub feature_list: StringList // List of supported extended features -} - -impl Serialize for ClientInit { - fn serialize(&self) -> Vec<u8> { - 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("BuildDate".to_string(), Variant::String(self.build_date.clone())); - values.insert("ClientFeatures".to_string(), Variant::u32(self.client_features)); - values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone())); - return values.serialize(); - } -} - -// impl Deserialize for ClientInit { -// fn deserialize(&mut self, b: &[u8]) { -// -// } -// } - -pub struct ClientInitReject { - pub error_string: String -} - -impl Serialize for ClientInitReject { - fn serialize(&self) -> Vec<u8> { - let mut values: VariantMap = VariantMap::with_capacity(2); - values.insert("MsgTypes".to_string(), Variant::String("ClientInitReject".to_string())); - values.insert("ErrorString".to_string(), Variant::String(self.error_string.clone())); - return values.serialize(); - } -} - -pub struct ClientInitAck { - pub core_features: u32, // Flags of supported legacy features - pub core_configured: bool, // If the core has already been configured - pub backend_info: VariantList, // List of VariantMaps of info on available backends - pub authenticator_info: VariantList, // List of VariantMaps of info on available authenticators - pub feature_list: StringList, // List of supported extended features -} - -impl Serialize for ClientInitAck { - fn serialize(&self) -> Vec<u8> { - let mut values: VariantMap = VariantMap::with_capacity(2); - values.insert("MsgTypes".to_string(), Variant::String("ClientInitAck".to_string())); - values.insert("CoreFeatures".to_string(), Variant::u32(self.core_features)); - values.insert("CoreConfigured".to_string(), Variant::bool(self.core_configured)); - values.insert("BackendInfo".to_string(), Variant::VariantList(self.backend_info.clone())); - values.insert("AuthenticatorInfo".to_string(), Variant::VariantList(self.authenticator_info.clone())); - values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone())); - return values.serialize(); - } -} diff --git a/src/types/variant.rs b/src/types/variant.rs deleted file mode 100644 index 59c287f..0000000 --- a/src/types/variant.rs +++ /dev/null @@ -1,298 +0,0 @@ -use std::vec::Vec; -use std::convert::TryInto; -use std::collections::HashMap; - -use crate::types::{Serialize, Deserialize}; -use crate::types::basic; -use crate::types::basic::*; -use crate::types::basic::{String,StringList}; - -pub type VariantMap = HashMap<String, Variant>; -impl Serialize for VariantMap { - fn serialize<'a>(&'a self) -> Vec<u8> { - let len: i32 = self.len().try_into().unwrap(); - let mut res: Vec<u8> = Vec::new(); - - res.extend(len.to_be_bytes().iter()); - for (k, v) in self { - res.extend(k.serialize().iter()); - res.extend(v.serialize().iter()); - } - - return res; - } -} - -impl Deserialize for VariantMap { - fn parse(&mut self, b: &[u8]) -> usize { - let mut len: i32 = 0; - len.parse(&b[0..3]); - - let mut pos = 4; - let map = VariantMap::new(); - for _ in 0..len { - let mut name: String = String::new(); - name.parse(&b[(pos)..(pos+2)]); - - let mut value: Variant = Variant::Unknown; - let res = value.parse(&b[(pos+3)..]); - - pos = pos + 2 + res; - } - - *self = map; - return pos; - } -} - -pub type VariantList = Vec<Variant>; -impl Serialize for VariantList { - fn serialize(&self) -> Vec<u8> { - let len: i32 = self.len().try_into().unwrap(); - let mut res: Vec<u8> = Vec::new(); - - res.extend(len.to_be_bytes().iter()); - for v in self { - res.extend(v.serialize().iter()); - } - - return res; - } -} - -impl Deserialize for VariantList { - fn parse(&mut self, b: &[u8]) -> usize { - let len: i32 = self.len().try_into().unwrap(); - let res: VariantList = VariantList::new(); - - let mut pos: usize = 0; - for _ in 0..len { - let mut val: Variant = Variant::Unknown; - pos = pos + val.parse(&b[pos..]); - } - - *self = res; - return pos; - } -} - -#[allow(non_camel_case_types, dead_code)] -#[derive(Clone)] -pub enum Variant { - Unknown, - VariantMap(VariantMap), - VariantList(VariantList), - String(String), - StringList(StringList), - bool(bool), - u64(u64), - u32(u32), - u16(u16), - u8(u8), - i64(i64), - i32(i32), - i16(i16), - i8(i8), -} - -impl Serialize for Variant { - fn serialize(&self) -> Vec<u8> { - let unknown: u32 = 0x00000000; - let mut res: Vec<u8> = Vec::new(); - - match self { - Variant::Unknown => { - return res; - }, - Variant::VariantMap(v) => { - res.extend(basic::QVARIANTMAP.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize().iter()); - }, - Variant::VariantList(v) => { - res.extend(basic::QVARIANTLIST.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize().iter()); - }, - Variant::String(v) => { - res.extend(basic::QSTRING.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize().iter()); - }, - Variant::StringList(v) => { - res.extend(basic::QSTRINGLIST.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize().iter()); - }, - Variant::bool(v) => { - res.extend(basic::BOOL.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - let i = *v as i8; - res.extend(i.to_be_bytes().iter()); - }, - Variant::u64(v) => { - res.extend(basic::ULONG.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::u32(v) => { - res.extend(basic::UINT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::u16(v) => { - res.extend(basic::USHORT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::u8(v) => { - res.extend(basic::UCHAR.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::i64(v) => { - res.extend(basic::LONG.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::i32(v) => { - res.extend(basic::INT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::i16(v) => { - res.extend(basic::SHORT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - Variant::i8(v) => { - res.extend(basic::CHAR.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - }, - } - - return res - } -} - -impl Deserialize for Variant { - fn parse(&mut self, b: &[u8]) -> usize { - let mut qtype: i32 = 0; - qtype.parse(&b[0..6]); - let qtype: u32 = qtype as u32; - - #[allow(unused_variables)] - let unknown: u8 = b[7]; - - match qtype { - QVARIANTMAP => { - let mut value: VariantMap = VariantMap::new(); - - let len = value.parse(&b[8..]); - *self = Variant::VariantMap(value.clone()); - - return len; - }, - QVARIANTLIST => { - let mut value: VariantList = VariantList::new(); - - let len = value.parse(&b[8..]); - *self = Variant::VariantList(value.clone()); - - return len; - }, - QSTRING => { - let mut value: String = String::new(); - - let len = value.parse(&b[8..]); - *self = Variant::String(value.clone()); - - return len; - }, - QSTRINGLIST => { - let mut value: StringList = StringList::new(); - - let len = value.parse(&b[8..]); - *self = Variant::StringList(value.clone()); - - return len; - }, - BOOL => { - let mut value: bool = false; - - let len = value.parse(&b[8..]); - *self = Variant::bool(value); - - return len; - }, - ULONG => { - let mut value: u64 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::u64(value); - - return len; - }, - UINT => { - let mut value: u32 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::u32(value); - - return len; - }, - USHORT => { - let mut value: u16 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::u16(value); - - return len; - }, - UCHAR => { - let mut value: u8 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::u8(value); - - return len; - }, - LONG => { - let mut value: i64 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::i64(value); - - return len; - }, - INT => { - let mut value: i32 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::i32(value); - - return len; - }, - SHORT => { - let mut value: i16 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::i16(value); - - return len; - }, - CHAR => { - let mut value: i8 = 0; - - let len = value.parse(&b[8..]); - *self = Variant::i8(value); - - return len; - }, - _ => { - return 0; - } - } - } -} diff --git a/src/util.rs b/src/util.rs index 809287f..48ab55e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -13,3 +13,30 @@ macro_rules! parse_match { }; }; } + +#[macro_export] +macro_rules! match_variant { + ( $values:expr, $x:path, $field:expr ) => { + match &$values[$field] { + $x(x) => { Ok(x.clone()) }, + _ => { Err("") } + }.unwrap(); + } +} + +pub fn prepend_byte_len(buf: &mut Vec<u8>) { + use std::convert::TryInto; + let len: i32 = buf.len().try_into().unwrap(); + let ulen: &[u8] = &len.to_be_bytes(); + buf.insert(0, ulen[3]); + buf.insert(0, ulen[2]); + buf.insert(0, ulen[1]); + buf.insert(0, ulen[0]); +} + +pub fn insert_bytes(pos: usize, buf: &mut Vec<u8>, input: &mut [u8]) { + input.reverse(); + for i in input { + buf.insert(pos, *i) + } +} |
