1use std;
2use std::fmt::Write;
3use std::str::from_utf8;
4use std::io::{Error, ErrorKind};
5use std::collections::HashMap;
6use tokio_io::codec::{Framed, Encoder, Decoder};
7use xml;
8use bytes::*;
9
10const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/";
11const NS_STREAMS: &'static str = "http://etherx.jabber.org/streams";
12const NS_CLIENT: &'static str = "jabber:client";
13
14struct XMPPRoot {
15 builder: xml::ElementBuilder,
16 pub attributes: HashMap<(String, Option<String>), String>,
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,
52 Stanza(xml::Element),
53 StreamEnd,
54}
55
56pub type XMPPStream<T> = Framed<T, XMPPCodec>;
57
58pub struct XMPPCodec {
59 parser: xml::Parser,
60 root: Option<XMPPRoot>,
61}
62
63impl XMPPCodec {
64 pub fn new() -> Self {
65 XMPPCodec {
66 parser: xml::Parser::new(),
67 root: None,
68 }
69 }
70}
71
72impl Decoder for XMPPCodec {
73 type Item = Packet;
74 type Error = Error;
75
76 fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
77 println!("XMPPCodec.decode {:?}", buf.len());
78 match from_utf8(buf.take().as_ref()) {
79 Ok(s) =>
80 self.parser.feed_str(s),
81 Err(e) =>
82 return Err(Error::new(ErrorKind::InvalidInput, e)),
83 }
84
85 let mut new_root: Option<XMPPRoot> = None;
86 let mut result = None;
87 for event in &mut self.parser {
88 match self.root {
89 None => {
90 // Expecting <stream:stream>
91 match event {
92 Ok(xml::Event::ElementStart(start_tag)) => {
93 self.root = Some(XMPPRoot::new(start_tag));
94 result = Some(Packet::StreamStart);
95 break
96 },
97 Err(e) => {
98 result = Some(Packet::Error(Box::new(e)));
99 break
100 },
101 _ =>
102 (),
103 }
104 }
105
106 Some(ref mut root) => {
107 match root.handle_event(event) {
108 None => (),
109 Some(Ok(stanza)) => {
110 println!("stanza: {}", stanza);
111 result = Some(Packet::Stanza(stanza));
112 break
113 },
114 Some(Err(e)) => {
115 result = Some(Packet::Error(Box::new(e)));
116 break
117 }
118 };
119 },
120 }
121
122 match new_root.take() {
123 None => (),
124 Some(root) => self.root = Some(root),
125 }
126 }
127
128 Ok(result)
129 }
130
131 fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
132 self.decode(buf)
133 }
134}
135
136impl Encoder for XMPPCodec {
137 type Item = Packet;
138 type Error = Error;
139
140 fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
141 match item {
142 Packet::StreamStart => {
143 write!(dst,
144 "<?xml version='1.0'?>\n
145<stream:stream version='1.0' to='spaceboyz.net' xmlns='{}' xmlns:stream='{}'>\n",
146 NS_CLIENT, NS_STREAMS)
147 .map_err(|_| Error::from(ErrorKind::WriteZero))
148 },
149 // TODO: Implement all
150 _ => Ok(())
151 }
152 }
153}