xmpp_codec.rs

  1use std;
  2use std::str::from_utf8;
  3use std::io::{Error, ErrorKind};
  4use std::collections::HashMap;
  5use tokio_core::io::{Codec, EasyBuf, Framed};
  6use xml;
  7
  8const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/";
  9const NS_STREAMS: &'static str = "http://etherx.jabber.org/streams";
 10const NS_CLIENT: &'static str = "jabber:client";
 11
 12struct XMPPRoot {
 13    builder: xml::ElementBuilder,
 14    pub attributes: HashMap<(String, Option<String>), String>,
 15}
 16
 17impl XMPPRoot {
 18    fn new(root: xml::StartTag) -> Self {
 19        let mut builder = xml::ElementBuilder::new();
 20        let mut attributes = HashMap::new();
 21        println!("root attributes: {:?}", root.attributes);
 22        for (name_ns, value) in root.attributes {
 23            match name_ns {
 24                (ref name, None) if name == "xmlns" =>
 25                    builder.set_default_ns(value),
 26                (ref prefix, Some(ref ns)) if ns == NS_XMLNS =>
 27                    builder.define_prefix(prefix.to_owned(), value),
 28                _ => {
 29                    attributes.insert(name_ns, value);
 30                },
 31            }
 32        }
 33
 34        XMPPRoot {
 35            builder: builder,
 36            attributes: attributes,
 37        }
 38    }
 39
 40    fn handle_event(&mut self, event: Result<xml::Event, xml::ParserError>)
 41                    -> Option<Result<xml::Element, xml::BuilderError>> {
 42        self.builder.handle_event(event)
 43    }
 44}
 45
 46#[derive(Debug)]
 47pub enum Packet {
 48    Error(Box<std::error::Error>),
 49    StreamStart,
 50    Stanza(xml::Element),
 51    StreamEnd,
 52}
 53
 54pub type XMPPStream<T> = Framed<T, XMPPCodec>;
 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 Codec for XMPPCodec {
 71    type In = Vec<Packet>;
 72    type Out = Packet;
 73
 74    fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, Error> {
 75        println!("XMPPCodec.decode {:?}", buf.len());
 76        match from_utf8(buf.as_slice()) {
 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 = None;
 84        let mut results = Vec::new();
 85        for event in &mut self.parser {
 86            match &mut self.root {
 87                &mut None => {
 88                    // Expecting <stream:stream>
 89                    match event {
 90                        Ok(xml::Event::ElementStart(start_tag)) => {
 91                            new_root = Some(XMPPRoot::new(start_tag));
 92                            results.push(Packet::StreamStart);
 93                        },
 94                        Err(e) =>
 95                            results.push(Packet::Error(Box::new(e))),
 96                        _ =>
 97                            (),
 98                    }
 99                }
100
101                &mut Some(ref mut root) => {
102                    match root.handle_event(event) {
103                        None => (),
104                        Some(Ok(stanza)) => {
105                            println!("stanza: {}", stanza);
106                            results.push(Packet::Stanza(stanza));
107                        },
108                        Some(Err(e)) =>
109                            results.push(Packet::Error(Box::new(e))),
110                    };
111                },
112            }
113
114            match new_root.take() {
115                None => (),
116                Some(root) => self.root = Some(root),
117            }
118        }
119
120        if results.len() == 0 {
121            Ok(None)
122        } else {
123            Ok(Some(results))
124        }
125    }
126
127    fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> Result<(), Error> {
128        match msg {
129            Packet::StreamStart => {
130                let mut write = |s: &str| {
131                    buf.extend_from_slice(s.as_bytes());
132                };
133
134                write("<?xml version='1.0'?>\n");
135                write("<stream:stream");
136                write(" version='1.0'");
137                write(" to='spaceboyz.net'");
138                write(&format!(" xmlns='{}'", NS_CLIENT));
139                write(&format!(" xmlns:stream='{}'", NS_STREAMS));
140                write(">\n");
141
142                Ok(())
143            },
144            // TODO: Implement all
145            _ => Ok(())
146        }
147    }
148
149    fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result<Self::In, Error> {
150        Ok(vec!())
151    }
152}