xmpp_codec.rs

  1use std;
  2use std::fmt::Write;
  3use std::str::from_utf8;
  4use std::io::{Error, ErrorKind};
  5use std::collections::HashMap;
  6use tokio_io::codec::{Encoder, Decoder};
  7use xml;
  8use bytes::*;
  9
 10const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/";
 11
 12pub type Attributes = HashMap<(String, Option<String>), String>;
 13
 14struct XMPPRoot {
 15    builder: xml::ElementBuilder,
 16    pub attributes: Attributes,
 17}
 18
 19impl XMPPRoot {
 20    fn new(root: xml::StartTag) -> Self {
 21        let mut builder = xml::ElementBuilder::new();
 22        let mut attributes = HashMap::new();
 23        println!("root attributes: {:?}", root.attributes);
 24        for (name_ns, value) in root.attributes {
 25            match name_ns {
 26                (ref name, None) if name == "xmlns" =>
 27                    builder.set_default_ns(value),
 28                (ref prefix, Some(ref ns)) if ns == NS_XMLNS =>
 29                    builder.define_prefix(prefix.to_owned(), value),
 30                _ => {
 31                    attributes.insert(name_ns, value);
 32                },
 33            }
 34        }
 35
 36        XMPPRoot {
 37            builder: builder,
 38            attributes: attributes,
 39        }
 40    }
 41
 42    fn handle_event(&mut self, event: Result<xml::Event, xml::ParserError>)
 43                    -> Option<Result<xml::Element, xml::BuilderError>> {
 44        self.builder.handle_event(event)
 45    }
 46}
 47
 48#[derive(Debug)]
 49pub enum Packet {
 50    Error(Box<std::error::Error>),
 51    StreamStart(HashMap<String, String>),
 52    Stanza(xml::Element),
 53    StreamEnd,
 54}
 55
 56pub struct XMPPCodec {
 57    parser: xml::Parser,
 58    root: Option<XMPPRoot>,
 59}
 60
 61impl XMPPCodec {
 62    pub fn new() -> Self {
 63        XMPPCodec {
 64            parser: xml::Parser::new(),
 65            root: None,
 66        }
 67    }
 68}
 69
 70impl Decoder for XMPPCodec {
 71    type Item = Packet;
 72    type Error = Error;
 73
 74    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
 75        println!("XMPPCodec.decode {:?}", buf.len());
 76        match from_utf8(buf.take().as_ref()) {
 77            Ok(s) =>
 78                self.parser.feed_str(s),
 79            Err(e) =>
 80                return Err(Error::new(ErrorKind::InvalidInput, e)),
 81        }
 82
 83        let mut new_root: Option<XMPPRoot> = None;
 84        let mut result = None;
 85        for event in &mut self.parser {
 86            match self.root {
 87                None => {
 88                    // Expecting <stream:stream>
 89                    match event {
 90                        Ok(xml::Event::ElementStart(start_tag)) => {
 91                            let mut attrs: HashMap<String, String> = HashMap::new();
 92                            for (&(ref name, _), value) in &start_tag.attributes {
 93                                attrs.insert(name.to_owned(), value.to_owned());
 94                            }
 95                            result = Some(Packet::StreamStart(attrs));
 96                            self.root = Some(XMPPRoot::new(start_tag));
 97                            break
 98                        },
 99                        Err(e) => {
100                            result = Some(Packet::Error(Box::new(e)));
101                            break
102                        },
103                        _ =>
104                            (),
105                    }
106                }
107
108                Some(ref mut root) => {
109                    match root.handle_event(event) {
110                        None => (),
111                        Some(Ok(stanza)) => {
112                            println!("stanza: {}", stanza);
113                            result = Some(Packet::Stanza(stanza));
114                            break
115                        },
116                        Some(Err(e)) => {
117                            result = Some(Packet::Error(Box::new(e)));
118                            break
119                        }
120                    };
121                },
122            }
123
124            match new_root.take() {
125                None => (),
126                Some(root) => self.root = Some(root),
127            }
128        }
129
130        Ok(result)
131    }
132
133    fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
134        self.decode(buf)
135    }
136}
137
138impl Encoder for XMPPCodec {
139    type Item = Packet;
140    type Error = Error;
141
142    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
143        match item {
144            Packet::StreamStart(start_attrs) => {
145                let mut buf = String::new();
146                write!(buf, "<stream:stream").unwrap();
147                for (ref name, ref value) in &start_attrs {
148                    write!(buf, " {}=\"{}\"", xml::escape(&name), xml::escape(&value))
149                        .unwrap();
150                }
151                write!(buf, ">\n").unwrap();
152
153                println!("Encode start to {}", buf);
154                write!(dst, "{}", buf)
155            },
156            Packet::Stanza(stanza) =>
157                write!(dst, "{}", stanza),
158            // TODO: Implement all
159            _ => Ok(())
160        }
161        .map_err(|_| Error::from(ErrorKind::InvalidInput))
162    }
163}