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}