From dfe9ba6a0bd63b8f01e55e4d08aa4db97c99cadb Mon Sep 17 00:00:00 2001 From: lurchi Date: Sun, 4 Sep 2016 17:37:35 +0200 Subject: [PATCH] parsing and rendering of packet IDs --- rust/src/lib.rs | 2 + rust/src/packet.rs | 48 ++++++++++-------- rust/src/packet_id.rs | 94 ++++++++++++++++++++++++++++++++++++ rust/src/parser.rs | 2 - rust/src/util.rs | 14 ++++++ rust/tests/test_packet_id.rs | 41 ++++++++++++++++ 6 files changed, 179 insertions(+), 22 deletions(-) create mode 100644 rust/src/packet_id.rs create mode 100644 rust/tests/test_packet_id.rs diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a70e024..3bc2edc 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -5,6 +5,8 @@ pub mod parser_types; pub mod packet_types; pub mod parser; pub mod packet; +pub mod packet_id; pub use parser::*; pub use packet::*; +pub use packet_id::*; diff --git a/rust/src/packet.rs b/rust/src/packet.rs index 41978d5..e9b9980 100644 --- a/rust/src/packet.rs +++ b/rust/src/packet.rs @@ -1,5 +1,7 @@ use types::*; use packet_types::*; +use packet_id::*; +use util; use std::mem; use std::ptr; use std::os::raw::c_char; @@ -41,25 +43,11 @@ extern "C" { content: *const c_char, contentlen: usize, flag: PsycPacketFlag); - - fn psyc_packet_id(list: *mut RawPsycList, - elems: *mut PsycElem, - context: *const c_char, - contextlen: usize, - source: *const c_char, - sourcelen: usize, - target: *const c_char, - targetlen: usize, - counter: *const c_char, - counterlen: usize, - fragment: *const c_char, - fragmentlen: usize); - + /// functions from render.h fn psyc_render(packet: *const RawPsycPacket, buffer: *mut c_char, buflen: usize) -> PsycRenderRC; fn psyc_render_modifier(modifier: *const RawPsycModifier, buffer: *mut c_char) -> usize; fn psyc_render_elem(elem: *const PsycElem, buffer: *mut c_char, buflen: usize) -> PsycRenderRC; - fn psyc_render_list(list: *const RawPsycList, buffer: *mut c_char, buflen: usize) -> PsycRenderRC; } pub struct PsycList { @@ -95,17 +83,14 @@ impl PsycList { pub fn new(list: &[&[u8]]) -> Self { let mut psyc_list: RawPsycList; let elements: Vec; - let mut buffer: Vec; + let buffer: Vec; unsafe { psyc_list = mem::uninitialized(); let psyc_list_ptr = &mut psyc_list as *mut RawPsycList; elements = list.iter().map(|e| make_psyc_elem(&e)).collect(); let elements_ptr = elements.as_ptr() as *const PsycElem; psyc_list_init(psyc_list_ptr, elements_ptr, list.len()); - buffer = Vec::with_capacity(psyc_list.length); - buffer.set_len(psyc_list.length); - let buffer_ptr = buffer.as_ptr() as *mut c_char; - let _ = psyc_render_list(psyc_list_ptr, buffer_ptr, psyc_list.length); + buffer = util::render_list(&psyc_list) } PsycList { rendered_list: buffer @@ -241,6 +226,29 @@ impl<'a> PsycPacket<'a> { } } + /// get the packet id + pub fn packet_id(&self) -> PacketId<'a> { + let get_value = |modifier: Option<&PsycModifier<'a>>| { + match modifier { + None => None, + Some(m) => Some(m.value) + } + }; + + let context = self.routing_modifiers.iter().find(|&r| r.name == "_context"); + let source = self.routing_modifiers.iter().find(|&r| r.name == "_source"); + let target = self.routing_modifiers.iter().find(|&r| r.name == "_target"); + let counter = self.routing_modifiers.iter().find(|&r| r.name == "_counter"); + + PacketId { + context: get_value(context), + source: get_value(source), + target: get_value(target), + counter: get_value(counter), + fragment: None + } + } + fn make_raw_modifier(modifier: &'a PsycModifier, flag: PsycModifierFlag) -> RawPsycModifier { diff --git a/rust/src/packet_id.rs b/rust/src/packet_id.rs new file mode 100644 index 0000000..17a6db3 --- /dev/null +++ b/rust/src/packet_id.rs @@ -0,0 +1,94 @@ +use packet_types::{RawPsycList, PsycElem}; +use parser::{PsycListParser, PsycListParserResult}; +use util; +use std::mem; +use std::ptr; +use std::os::raw::c_char; + +extern "C" { + fn psyc_packet_id(list: *mut RawPsycList, + elems: *mut PsycElem, + context: *const c_char, + contextlen: usize, + source: *const c_char, + sourcelen: usize, + target: *const c_char, + targetlen: usize, + counter: *const c_char, + counterlen: usize, + fragment: *const c_char, + fragmentlen: usize); +} + +#[derive(PartialEq, Debug)] +pub struct PacketId<'a> { + pub context: Option<&'a [u8]>, + pub source: Option<&'a [u8]>, + pub target: Option<&'a [u8]>, + pub counter: Option<&'a [u8]>, + pub fragment: Option<&'a [u8]> +} + +impl<'a> PacketId<'a> { + pub fn from_bytes(bytes: &'a [u8]) -> Option { + let mut parsed: Vec> = vec![None; 5]; + let mut parser = PsycListParser::new(); + let mut parsing_error = false; + for slice in &mut parsed { + match parser.parse(bytes) { + Ok(PsycListParserResult::ListElement {value: v}) => *slice = Some(v), + _ => parsing_error = true + } + } + if parsing_error { + None + } else { + let result = PacketId { + context: parsed[0], + source: parsed[1], + target: parsed[2], + counter: parsed[3], + fragment: parsed[4] + }; + Some(result) + } + } + + pub fn render(&self) -> Vec { + unsafe { + let get_ptr = |slice: Option<&'a [u8]>| { + match slice { + None => ptr::null::(), + Some(s) => s.as_ptr() as *const c_char + } + }; + + let get_len = |slice: Option<&'a [u8]>| { + match slice { + None => 0, + Some(s) => s.len() + } + }; + + let mut list: RawPsycList = mem::uninitialized(); + let mut elements: Vec = Vec::with_capacity(5); + let list_ptr = &mut list as *mut RawPsycList; + let elements_ptr = elements.as_mut_ptr(); + + psyc_packet_id(list_ptr, + elements_ptr, + get_ptr(self.context), + get_len(self.context), + get_ptr(self.source), + get_len(self.source), + get_ptr(self.target), + get_len(self.target), + get_ptr(self.counter), + get_len(self.counter), + get_ptr(self.fragment), + get_len(self.fragment)); + + util::render_list(&list) + } + } +} diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 841c3df..ffe3963 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -283,8 +283,6 @@ impl PsycListParser { let element_ptr = &mut element as *mut PsycString; loop { let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr); - println!("parse_result: {:?}", parse_result); - println!("cursor: {}", self.state.cursor); match parse_result { PsycParseListRC::PSYC_PARSE_LIST_END => return Ok(PsycListParserResult::Complete), diff --git a/rust/src/util.rs b/rust/src/util.rs index ebb2ec4..e40f84c 100644 --- a/rust/src/util.rs +++ b/rust/src/util.rs @@ -1,6 +1,20 @@ +use packet_types::{RawPsycList, PsycRenderRC}; use std::slice; use std::os::raw::c_char; +extern "C" { + fn psyc_render_list(list: *const RawPsycList, buffer: *mut c_char, buflen: usize) -> PsycRenderRC; +} + pub unsafe fn cstring_to_slice<'a>(cstring: *const c_char, length: usize) -> &'a[u8] { slice::from_raw_parts(cstring as *const u8, length) } + +pub unsafe fn render_list(list: &RawPsycList) -> Vec { + let mut buffer: Vec = Vec::with_capacity(list.length); + buffer.set_len(list.length); + let buffer_ptr = buffer.as_ptr() as *mut c_char; + let list_ptr = list as *const RawPsycList; + let _ = psyc_render_list(list_ptr, buffer_ptr, list.length); + buffer +} diff --git a/rust/tests/test_packet_id.rs b/rust/tests/test_packet_id.rs new file mode 100644 index 0000000..7b50eb8 --- /dev/null +++ b/rust/tests/test_packet_id.rs @@ -0,0 +1,41 @@ +extern crate psyc; + +use psyc::*; +use psyc::packet_types::*; + +#[test] +fn test_packet_id() { + let routing_modifiers = vec![PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET, + "_source", + b"psyc://ve.symlynx.com/~alice"), + PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET, + "_target", + b"psyc://ve.symlynx.com/~bob"), + PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET, + "_counter", + b"42")]; + + let entity_modifiers = vec![]; + + let data = vec![]; + + let packet = PsycPacket::new(&routing_modifiers, + &entity_modifiers, + "", + &data, + PsycStateOp::PSYC_STATE_NOOP); + + let expected_id = PacketId { + context: None, + source: Some(b"psyc://ve.symlynx.com/~alice"), + target: Some(b"psyc://ve.symlynx.com/~bob"), + counter: Some(b"42"), + fragment: None + }; + + assert_eq!(packet.packet_id(), expected_id); + + let expected_rendered = b"|| psyc://ve.symlynx.com/~alice| psyc://ve.symlynx.com/~bob| 42|"; + + assert_eq!(packet.packet_id().render(), expected_rendered.to_vec()); +}