diff --git a/src/jingle_ibb.rs b/src/jingle_ibb.rs new file mode 100644 index 00000000..4ab73e68 --- /dev/null +++ b/src/jingle_ibb.rs @@ -0,0 +1,101 @@ +use std::str::FromStr; + +use minidom::Element; + +use error::Error; + +use ns; + +use ibb::Stanza; + +#[derive(Debug, Clone)] +pub struct Transport { + block_size: u16, + sid: String, + stanza: Stanza, +} + +fn optional_attr(root: &Element, attr: &str) -> Option { + root.attr(attr) + .and_then(|value| value.parse().ok()) +} + +fn required_attr(root: &Element, attr: &str, err: Error) -> Result { + optional_attr(root, attr).ok_or(err) +} + +pub fn parse_jingle_ibb(root: &Element) -> Result { + if root.is("transport", ns::JINGLE_IBB) { + for _ in root.children() { + return Err(Error::ParseError("Unknown child in JingleIBB element.")); + } + let block_size = required_attr(root, "block-size", Error::ParseError("Required attribute 'block-size' missing in JingleIBB element."))?; + let sid = required_attr(root, "sid", Error::ParseError("Required attribute 'sid' missing in JingleIBB element."))?; + let stanza = root.attr("stanza") + .unwrap_or("iq") + .parse()?; + Ok(Transport { + block_size: block_size, + sid: sid, + stanza: stanza + }) + } else { + Err(Error::ParseError("This is not an JingleIBB element.")) + } +} + +#[cfg(test)] +mod tests { + use minidom::Element; + use error::Error; + use ibb; + use jingle_ibb; + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + let transport = jingle_ibb::parse_jingle_ibb(&elem).unwrap(); + assert_eq!(transport.block_size, 3); + assert_eq!(transport.sid, "coucou"); + assert_eq!(transport.stanza, ibb::Stanza::Iq); + } + + #[test] + fn test_invalid() { + let elem: Element = "".parse().unwrap(); + let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Required attribute 'block-size' missing in JingleIBB element."); + + // TODO: maybe make a better error message here. + let elem: Element = "".parse().unwrap(); + let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Required attribute 'block-size' missing in JingleIBB element."); + + let elem: Element = "".parse().unwrap(); + let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Required attribute 'sid' missing in JingleIBB element."); + } + + #[test] + fn test_invalid_stanza() { + let elem: Element = "".parse().unwrap(); + let error = jingle_ibb::parse_jingle_ibb(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Invalid 'stanza' attribute."); + } +} diff --git a/src/lib.rs b/src/lib.rs index 614737dd..b311682b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,9 @@ pub mod attention; /// XEP-0234: Jingle File Transfer pub mod jingle_ft; +/// XEP-0261: Jingle In-Band Bytestreams Transport Method +pub mod jingle_ibb; + /// XEP-0300: Use of Cryptographic Hash Functions in XMPP pub mod hashes; diff --git a/src/ns.rs b/src/ns.rs index 5dfb3f5d..de18053a 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -36,6 +36,9 @@ pub const JINGLE_FT: &'static str = "urn:xmpp:jingle:apps:file-transfer:5"; /// XEP-0234: Jingle File Transfer pub const JINGLE_FT_ERROR: &'static str = "urn:xmpp:jingle:apps:file-transfer:errors:0"; +/// XEP-0261: Jingle In-Band Bytestreams Transport Method +pub const JINGLE_IBB: &'static str = "urn:xmpp:jingle:transports:ibb:1"; + /// XEP-0300: Use of Cryptographic Hash Functions in XMPP pub const HASHES: &'static str = "urn:xmpp:hashes:2";