1use std;
2use std::str::from_utf8;
3use std::io::{Error, ErrorKind};
4use std::collections::HashMap;
5use tokio_core::io::{Codec, EasyBuf};
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 struct XMPPCodec {
55 parser: xml::Parser,
56 root: Option<XMPPRoot>,
57}
58
59impl XMPPCodec {
60 pub fn new() -> Self {
61 XMPPCodec {
62 parser: xml::Parser::new(),
63 root: None,
64 }
65 }
66}
67
68impl Codec for XMPPCodec {
69 type In = Vec<Packet>;
70 type Out = Packet;
71
72 fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, Error> {
73 match from_utf8(buf.as_slice()) {
74 Ok(s) =>
75 self.parser.feed_str(s),
76 Err(e) =>
77 return Err(Error::new(ErrorKind::InvalidInput, e)),
78 }
79
80 let mut new_root = None;
81 let mut results = Vec::new();
82 for event in &mut self.parser {
83 match &mut self.root {
84 &mut None => {
85 // Expecting <stream:stream>
86 match event {
87 Ok(xml::Event::ElementStart(start_tag)) => {
88 new_root = Some(XMPPRoot::new(start_tag));
89 results.push(Packet::StreamStart);
90 },
91 Err(e) =>
92 results.push(Packet::Error(Box::new(e))),
93 _ =>
94 (),
95 }
96 }
97
98 &mut Some(ref mut root) => {
99 match root.handle_event(event) {
100 None => (),
101 Some(Ok(stanza)) => {
102 println!("stanza: {}", stanza);
103 results.push(Packet::Stanza(stanza));
104 },
105 Some(Err(e)) =>
106 results.push(Packet::Error(Box::new(e))),
107 };
108 },
109 }
110
111 match new_root.take() {
112 None => (),
113 Some(root) => self.root = Some(root),
114 }
115 }
116
117 if results.len() == 0 {
118 Ok(None)
119 } else {
120 Ok(Some(results))
121 }
122 }
123
124 fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> Result<(), Error> {
125 match msg {
126 Packet::StreamStart => {
127 let mut write = |s: &str| {
128 buf.extend_from_slice(s.as_bytes());
129 };
130
131 write("<?xml version='1.0'?>\n");
132 write("<stream:stream");
133 write(" version='1.0'");
134 write(" to='spaceboyz.net'");
135 write(&format!(" xmlns='{}'", NS_CLIENT));
136 write(&format!(" xmlns:stream='{}'", NS_STREAMS));
137 write(">\n");
138
139 Ok(())
140 },
141 // TODO: Implement all
142 _ => Ok(())
143 }
144 }
145
146 fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result<Self::In, Error> {
147 Ok(vec!())
148 }
149}