diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 3bc2edc..cdb2b18 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,12 +1,16 @@ #![allow(dead_code)] mod types; mod util; -pub mod parser_types; -pub mod packet_types; +mod uniform_types; +mod packet_types; +mod parser_types; pub mod parser; pub mod packet; pub mod packet_id; +pub mod uniform; pub use parser::*; pub use packet::*; pub use packet_id::*; +pub use uniform::*; +pub use packet_types::{PsycOperator, PsycStateOp}; diff --git a/rust/src/types.rs b/rust/src/types.rs index 09ef3e0..55431ca 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1,5 +1,6 @@ use std::os::raw::c_char; +#[derive(Clone)] #[repr(C)] pub struct PsycString { pub length: usize, diff --git a/rust/src/uniform.rs b/rust/src/uniform.rs new file mode 100644 index 0000000..4f5603a --- /dev/null +++ b/rust/src/uniform.rs @@ -0,0 +1,158 @@ +use uniform_types::*; +use std::os::raw::c_char; +use std::os::raw::c_int; +use std::marker::PhantomData; +use std::mem; +use util; + +extern "C" { + fn psyc_uniform_parse(uniform: *mut PsycUniform, + buffer: *const c_char, + length: usize) + -> c_int; +} + +pub struct Uniform<'a> { + uniform: PsycUniform, + phantom: PhantomData<&'a Vec> +} + +impl<'a> Uniform<'a> { + pub fn from_bytes(buffer: &'a [u8]) -> Result { + let buffer_ptr = buffer.as_ptr() as *const c_char; + let mut uniform: PsycUniform; + unsafe { + uniform = mem::zeroed(); + let uniform_ptr = &mut uniform as *mut PsycUniform; + let parse_result = psyc_uniform_parse(uniform_ptr, buffer_ptr, buffer.len()); + if parse_result < PsycScheme::PSYC_SCHEME_PSYC as _ { + return Err(mem::transmute(parse_result)) + } + } + let result = Uniform { + uniform: uniform, + phantom: PhantomData + }; + Ok(result) + } + + //pub fn from_raw_uniform(uniform: PsycUniform) -> Self { + // UniformRef { + // uniform: uniform, + // phantom: PhantomData + // } + //} + + pub fn is_valid(&self) -> bool { + self.uniform.valid + } + + pub fn scheme(&self) -> PsycScheme { + self.uniform.uniform_type + } + + pub fn name(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.user.data, self.uniform.user.length) + } + } + + pub fn password(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.pass.data, self.uniform.pass.length) + } + } + + pub fn host(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.host.data, self.uniform.host.length) + } + } + + pub fn port(&self) -> Option { + let slice: &'a str; + unsafe { + slice = util::cstring_to_str(self.uniform.port.data, + self.uniform.port.length) + } + match slice { + "" => None, + s => Some(s.parse::().unwrap()) + } + } + + pub fn transport(&self) -> Option { + let slice: &'a str; + unsafe { + slice = util::cstring_to_str(self.uniform.transport.data, + self.uniform.transport.length) + } + match slice { + "" => None, + tcp if tcp.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_TCP as u8 => + Some(PsycTransport::PSYC_TRANSPORT_TCP), + udp if udp.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_UDP as u8 => + Some(PsycTransport::PSYC_TRANSPORT_UDP), + tls if tls.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_TLS as u8 => + Some(PsycTransport::PSYC_TRANSPORT_TLS), + gnunet if gnunet.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_GNUNET as u8 => + Some(PsycTransport::PSYC_TRANSPORT_GNUNET), + _ => None + } + } + + pub fn resource(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.resource.data, + self.uniform.resource.length) + } + } + + pub fn query(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.query.data, self.uniform.query.length) + } + } + + pub fn channel(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.channel.data, self.uniform.channel.length) + } + } + + pub fn full(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.full.data, self.uniform.full.length) + } + } + + pub fn body(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.body.data, self.uniform.body.length) + } + } + + pub fn root(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.root.data, self.uniform.root.length) + } + } + + pub fn entity(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.entity.data, self.uniform.entity.length) + } + } + + pub fn path(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.path.data, self.uniform.path.length) + } + } + + pub fn nick(&self) -> &'a str { + unsafe { + util::cstring_to_str(self.uniform.nick.data, self.uniform.nick.length) + } + } +} diff --git a/rust/src/uniform_types.rs b/rust/src/uniform_types.rs new file mode 100644 index 0000000..b68e931 --- /dev/null +++ b/rust/src/uniform_types.rs @@ -0,0 +1,64 @@ +use types::*; + +#[derive(Clone, Copy)] +#[repr(C)] +pub enum PsycScheme { + PSYC_SCHEME_PSYC = 0, + PSYC_SCHEME_IRC = 1, + PSYC_SCHEME_XMPP = 2, + PSYC_SCHEME_SIP = 3 +} + +#[repr(C)] +pub enum PsycEntityType { + PSYC_ENTITY_ROOT = 0, + PSYC_ENTITY_PERSON = '~' as _, + PSYC_ENTITY_PLACE = '@' as _, + PSYC_ENTITY_SERVICE = '$' as _ +} + +#[repr(C)] +pub enum PsycTransport { + PSYC_TRANSPORT_TCP = 'c' as _, + PSYC_TRANSPORT_UDP = 'd' as _, + PSYC_TRANSPORT_TLS = 's' as _, + PSYC_TRANSPORT_GNUNET = 'g' as _, +} + +#[repr(C)] +pub enum UniformParseError { + PSYC_PARSE_UNIFORM_INVALID_SLASHES = -7, + PSYC_PARSE_UNIFORM_INVALID_CHANNEL = -6, + PSYC_PARSE_UNIFORM_INVALID_RESOURCE = -5, + PSYC_PARSE_UNIFORM_INVALID_TRANSPORT = -4, + PSYC_PARSE_UNIFORM_INVALID_PORT = -3, + PSYC_PARSE_UNIFORM_INVALID_HOST = -2, + PSYC_PARSE_UNIFORM_INVALID_SCHEME = -1, +} + +#[derive(Clone)] +#[repr(C)] +pub struct PsycUniform { + pub valid: bool, + pub uniform_type: PsycScheme, + pub scheme: PsycString, + pub user: PsycString, + pub pass: PsycString, + pub host: PsycString, + pub port: PsycString, + pub transport: PsycString, + pub resource: PsycString, + pub query: PsycString, + pub channel: PsycString, + + pub full: PsycString, + pub body: PsycString, + pub user_host: PsycString, + pub host_port: PsycString, + pub root: PsycString, + pub entity: PsycString, + pub slashes: PsycString, + pub slash: PsycString, + pub path: PsycString, + pub nick: PsycString +} diff --git a/rust/tests/test_packet.rs b/rust/tests/test_packet.rs index aa51797..c24dfc1 100644 --- a/rust/tests/test_packet.rs +++ b/rust/tests/test_packet.rs @@ -1,7 +1,6 @@ extern crate psyc; use psyc::*; -use psyc::packet_types::*; #[test] fn test_create_render() { diff --git a/rust/tests/test_packet_id.rs b/rust/tests/test_packet_id.rs index 58e822c..125ff44 100644 --- a/rust/tests/test_packet_id.rs +++ b/rust/tests/test_packet_id.rs @@ -1,7 +1,6 @@ extern crate psyc; use psyc::*; -use psyc::packet_types::*; #[test] fn test_packet_id() {