aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2020-01-14 12:35:46 +0100
committerMax Audron <audron@cocaine.farm>2020-01-17 10:48:27 +0100
commit5d50a5f0c03baf460fee394decce5898812dbd2c (patch)
treefc53a8ea19786be4dc57f9736cd4bf4e76026227 /src
parentinitial implementation done (diff)
refactor parse impl
Diffstat (limited to 'src')
-rw-r--r--src/main.rs20
-rw-r--r--src/net.rs46
-rw-r--r--src/protocol/message/handshake.rs99
-rw-r--r--src/protocol/message/handshake/types.rs92
-rw-r--r--src/protocol/message/mod.rs3
-rw-r--r--src/protocol/mod.rs2
-rw-r--r--src/protocol/primitive/basic.rs270
-rw-r--r--src/protocol/primitive/mod.rs30
-rw-r--r--src/protocol/primitive/variant.rs334
-rw-r--r--src/tests/base_types.rs55
-rw-r--r--src/tests/handshake_types.rs29
-rw-r--r--src/tests/mod.rs8
-rw-r--r--src/tests/variant_types.rs88
-rw-r--r--src/types.rs54
-rw-r--r--src/types/basic.rs149
-rw-r--r--src/types/handshake.rs62
-rw-r--r--src/types/variant.rs298
-rw-r--r--src/util.rs27
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);
diff --git a/src/net.rs b/src/net.rs
index 3d56437..5dd9552 100644
--- a/src/net.rs
+++ b/src/net.rs
@@ -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)
+ }
+}