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 = 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 let buf_len = buf.len();
77 let chunk = buf.drain_to(buf_len);
78 match from_utf8(chunk.as_slice()) {
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 = 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 encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> Result<(), Error> {
132 match msg {
133 Packet::StreamStart => {
134 let mut write = |s: &str| {
135 buf.extend_from_slice(s.as_bytes());
136 };
137
138 write("<?xml version='1.0'?>\n");
139 write("<stream:stream");
140 write(" version='1.0'");
141 write(" to='spaceboyz.net'");
142 write(&format!(" xmlns='{}'", NS_CLIENT));
143 write(&format!(" xmlns:stream='{}'", NS_STREAMS));
144 write(">\n");
145
146 Ok(())
147 },
148 // TODO: Implement all
149 _ => Ok(())
150 }
151 }
152
153 fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result<Self::In, Error> {
154 Err(Error::from(ErrorKind::UnexpectedEof))
155 }
156}