diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 14 | ||||
| -rw-r--r-- | src/net.rs | 25 | ||||
| -rw-r--r-- | src/types.rs | 13 | ||||
| -rw-r--r-- | src/types/basic.rs | 154 | ||||
| -rw-r--r-- | src/types/handshake.rs | 62 | ||||
| -rw-r--r-- | src/types/variant.rs | 298 | ||||
| -rw-r--r-- | src/util.rs | 15 |
7 files changed, 543 insertions, 38 deletions
diff --git a/src/main.rs b/src/main.rs index 96324d7..cd45c87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,27 @@ mod consts; mod net; -mod util; mod types; +#[macro_use] +mod util; + //use util::Hex; fn main() -> std::io::Result<()> { - let server = net::connect( + let mut server = net::connect( "localhost", 4242, false, false, )?; - //server.login("audron", "audron"); + 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() + }; + server.login("audron", "audron", client); Ok(()) } // the stream is closed here @@ -6,25 +6,26 @@ use std::net::TcpStream; use std::vec::Vec; extern crate log; -use log::{info, warn, debug}; +// use log::{info, warn, debug}; use super::types; +use super::types::Serialize; -pub struct Server { - TcpStream: TcpStream, +pub struct Client { + tcp_stream: TcpStream, pub address: &'static str, pub port: u32, pub tls: bool, pub compression: bool, } -// impl Server { -// pub fn login(&self, user: &'static str, pass: &'static str) { -// println!("{:?}", basic::Void); -// } -// } +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 connect(address: &'static str, port: u32, tls: bool, compression: bool) -> Result<Server, Error> { +pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) -> Result<Client, Error> { //let mut s = BufWriter::new(TcpStream::connect(format!("{}:{}", address, port)).unwrap()); let mut s = TcpStream::connect(format!("{}:{}", address, port)).unwrap(); @@ -46,10 +47,10 @@ pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) - let mut buf = [0; 4]; s.read_exact(&mut buf)?; - println!("Received: {:?}", types::basic::VOID); + println!("Received: {:?}", buf); - let mut server: Server = Server { - TcpStream: s, + let server: Client = Client { + tcp_stream: s, address: address, port: port, tls: tls, diff --git a/src/types.rs b/src/types.rs index 9836248..1c22ce6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,4 +1,17 @@ +#[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 diff --git a/src/types/basic.rs b/src/types/basic.rs index f7a505a..dc5e8d5 100644 --- a/src/types/basic.rs +++ b/src/types/basic.rs @@ -1,41 +1,149 @@ +#[allow(dead_code)] pub const VOID: u32 = 0x00000000; pub const BOOL: u32 = 0x00000001; -pub const INT: u32 = 0x00000002; // int32_t -pub const UINT: u32 = 0x00000003; // uint32_t 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 -pub const QVARIANT: u32 = 0x00000090; -// Void 0x00000000 -// Bool 0x00000001 -// Int 0x00000002 int32_t -// UInt 0x00000003 uint32_t -// QChar 0x00000007 -// QVariantMap 0x00000008 -// QVariantList 0x00000009 -// QString 0x0000000a -// QStringList 0x0000000b -// QByteArray 0x0000000c -// QTime 0x0000000f -// QDateTime 0x00000010 -// UserType 0x0000007f -// Long 0x00000081 int64_t -// Short 0x00000082 int16_t -// Char 0x00000083 int8_t -// ULong 0x00000084 uint64_t -// UShort 0x00000085 uint16_t -// UChar 0x00000086 uint8_t -// QVariant 0x00000090 +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 new file mode 100644 index 0000000..cd79d29 --- /dev/null +++ b/src/types/handshake.rs @@ -0,0 +1,62 @@ +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 new file mode 100644 index 0000000..59c287f --- /dev/null +++ b/src/types/variant.rs @@ -0,0 +1,298 @@ +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 e69de29..809287f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -0,0 +1,15 @@ +#[macro_export] +macro_rules! parse_match { + ( $matchee:expr, $pos:expr, $map:expr, $bytes:expr, $name:expr, $(($pattern:pat, $type:ty, $variant:expr)),* ) => { + match $matchee { + $( + $pattern => { + let value: $type; + + $pos = $pos + value.parse(&$bytes[($pos)..]); + $map.insert($name, $variant(value)); + }, + )* + }; + }; +} |
