From 212d9e7e7e80d48eb1f2fa39f5503b5782fd542a Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 2 Jun 2017 00:42:57 +0200 Subject: [PATCH 001/135] this ain't work --- .gitignore | 2 + Cargo.toml | 9 +++ src/lib.rs | 112 ++++++++++++++++++++++++++++++++++ src/xmpp_codec.rs | 149 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/xmpp_codec.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a9d37c560c6ab8d4afbf47eda643e8c42e857716 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4e643380825af52a1c9bf9460b5608f7446b2d03 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "tokio-xmpp" +version = "0.1.0" +authors = ["Astro "] + +[dependencies] +futures = "0.1.6" +tokio-core = "0.1.1" +RustyXML = "0.1.1" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e9162b02c91e1c8af9754f70e0514c185c925b3e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,112 @@ +extern crate futures; +extern crate tokio_core; +extern crate xml; + +use std::net::SocketAddr; +use std::net::ToSocketAddrs; +use std::sync::Arc; +use std::io::ErrorKind; +use futures::{Future, BoxFuture, Sink, Poll}; +use futures::stream::{Stream, iter}; +use futures::future::result; +use tokio_core::reactor::Handle; +use tokio_core::io::Io; +use tokio_core::net::TcpStream; + +mod xmpp_codec; +use xmpp_codec::*; + + +// type FullClient = sasl::Client> + +type Event = (); +type Error = std::io::Error; + +struct TCPStream { + source: Box>, + sink: Arc>>>, +} + +impl TCPStream { + pub fn connect(addr: &SocketAddr, handle: &Handle) -> BoxFuture, std::io::Error> { + TcpStream::connect(addr, handle) + .and_then(|stream| { + let (sink, source) = stream.framed(XMPPCodec::new()) + // .framed(UTF8Codec::new()) + .split(); + + sink.send(Packet::StreamStart) + .and_then(|sink| result(Ok((Arc::new(Box::new(sink)), source)))) + }) + .and_then(|(sink, source)| { + let sink1 = sink.clone(); + let source = source + .map(|items| iter(items.into_iter().map(Ok))) + .flatten() + .filter_map(move |pkt| Self::process_packet(pkt, &sink1)) + // .for_each(|ev| { + // match ev { + // Packet::Stanza + // _ => (), + // } + // Ok(println!("xmpp: {:?}", ev)) + // }) + // .boxed(); + ; + result(Ok(Arc::new(TCPStream { + source: Box::new(source), + sink: sink, + }))) + }).boxed() + //.map_err(|e| std::io::Error::new(ErrorKind::Other, e)); + } + + fn process_packet(pkt: Packet, sink: &Arc) -> Option + where S: Sink { + + println!("pkt: {:?}", pkt); + None + } +} + +struct ClientStream { + inner: TCPStream, +} + +impl ClientStream { + pub fn connect(jid: &str, password: &str, handle: &Handle) -> Box> { + let addr = "[2a01:4f8:a0:33d0::5]:5222" + .to_socket_addrs().unwrap() + .next().unwrap(); + let stream = + TCPStream::connect(&addr, handle) + .and_then(|stream| { + Ok(ClientStream { + inner: stream + }) + }); + Box::new(stream) + } +} + +#[cfg(test)] +mod tests { + use tokio_core::reactor::Core; + + #[test] + fn it_works() { + let mut core = Core::new().unwrap(); + let client = super::ClientStream::connect( + "astro@spaceboyz.net", + "...", + &core.handle() + ).and_then(|stream| { + stream.inner.source.boxed().for_each(|item| { + Ok(println!("stream item: {:?}", item)) + }) + }).boxed(); + core.run(client).unwrap(); + } + + // TODO: test truncated utf8 +} diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs new file mode 100644 index 0000000000000000000000000000000000000000..847339315fce725d93bebb51b0c194fe86810e1a --- /dev/null +++ b/src/xmpp_codec.rs @@ -0,0 +1,149 @@ +use std; +use std::str::from_utf8; +use std::io::{Error, ErrorKind}; +use std::collections::HashMap; +use tokio_core::io::{Codec, EasyBuf}; +use xml; + +const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; +const NS_STREAMS: &'static str = "http://etherx.jabber.org/streams"; +const NS_CLIENT: &'static str = "jabber:client"; + +struct XMPPRoot { + builder: xml::ElementBuilder, + pub attributes: HashMap<(String, Option), String>, +} + +impl XMPPRoot { + fn new(root: xml::StartTag) -> Self { + let mut builder = xml::ElementBuilder::new(); + let mut attributes = HashMap::new(); + println!("root attributes: {:?}", root.attributes); + for (name_ns, value) in root.attributes { + match name_ns { + (ref name, None) if name == "xmlns" => + builder.set_default_ns(value), + (ref prefix, Some(ref ns)) if ns == NS_XMLNS => + builder.define_prefix(prefix.to_owned(), value), + _ => { + attributes.insert(name_ns, value); + }, + } + } + + XMPPRoot { + builder: builder, + attributes: attributes, + } + } + + fn handle_event(&mut self, event: Result) + -> Option> { + self.builder.handle_event(event) + } +} + +#[derive(Debug)] +pub enum Packet { + Error(Box), + StreamStart, + Stanza(xml::Element), + StreamEnd, +} + +pub struct XMPPCodec { + parser: xml::Parser, + root: Option, +} + +impl XMPPCodec { + pub fn new() -> Self { + XMPPCodec { + parser: xml::Parser::new(), + root: None, + } + } +} + +impl Codec for XMPPCodec { + type In = Vec; + type Out = Packet; + + fn decode(&mut self, buf: &mut EasyBuf) -> Result, Error> { + match from_utf8(buf.as_slice()) { + Ok(s) => + self.parser.feed_str(s), + Err(e) => + return Err(Error::new(ErrorKind::InvalidInput, e)), + } + + let mut new_root = None; + let mut results = Vec::new(); + for event in &mut self.parser { + match &mut self.root { + &mut None => { + // Expecting + match event { + Ok(xml::Event::ElementStart(start_tag)) => { + new_root = Some(XMPPRoot::new(start_tag)); + results.push(Packet::StreamStart); + }, + Err(e) => + results.push(Packet::Error(Box::new(e))), + _ => + (), + } + } + + &mut Some(ref mut root) => { + match root.handle_event(event) { + None => (), + Some(Ok(stanza)) => { + println!("stanza: {}", stanza); + results.push(Packet::Stanza(stanza)); + }, + Some(Err(e)) => + results.push(Packet::Error(Box::new(e))), + }; + }, + } + + match new_root.take() { + None => (), + Some(root) => self.root = Some(root), + } + } + + if results.len() == 0 { + Ok(None) + } else { + Ok(Some(results)) + } + } + + fn encode(&mut self, msg: Self::Out, buf: &mut Vec) -> Result<(), Error> { + match msg { + Packet::StreamStart => { + let mut write = |s: &str| { + buf.extend_from_slice(s.as_bytes()); + }; + + write("\n"); + write("\n"); + + Ok(()) + }, + // TODO: Implement all + _ => Ok(()) + } + } + + fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result { + Ok(vec!()) + } +} From 005013f37ca8af711431e76852842b2bb32c83a3 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 3 Jun 2017 01:58:31 +0200 Subject: [PATCH 002/135] this kinda works --- Cargo.toml | 6 +- src/lib.rs | 147 ++++++++++++++++++++++++++-------------------- src/xmpp_codec.rs | 5 +- 3 files changed, 89 insertions(+), 69 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4e643380825af52a1c9bf9460b5608f7446b2d03..2a22e0bdfce87bb334039930997ae76d54fe982b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["Astro "] [dependencies] -futures = "0.1.6" -tokio-core = "0.1.1" -RustyXML = "0.1.1" +futures = "*" +tokio-core = "*" +RustyXML = "*" diff --git a/src/lib.rs b/src/lib.rs index e9162b02c91e1c8af9754f70e0514c185c925b3e..f8e6453e0d2b74008d72865223f4712c16cc9c2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate futures; extern crate tokio_core; extern crate xml; @@ -6,12 +7,12 @@ use std::net::SocketAddr; use std::net::ToSocketAddrs; use std::sync::Arc; use std::io::ErrorKind; -use futures::{Future, BoxFuture, Sink, Poll}; +use futures::{Future, BoxFuture, Sink, Poll, Async}; use futures::stream::{Stream, iter}; use futures::future::result; use tokio_core::reactor::Handle; use tokio_core::io::Io; -use tokio_core::net::TcpStream; +use tokio_core::net::{TcpStream, TcpStreamNew}; mod xmpp_codec; use xmpp_codec::*; @@ -19,92 +20,108 @@ use xmpp_codec::*; // type FullClient = sasl::Client> -type Event = (); -type Error = std::io::Error; +#[derive(Debug)] +pub struct TcpClient { + state: TcpClientState, +} -struct TCPStream { - source: Box>, - sink: Arc>>>, +enum TcpClientState { + Connecting(TcpStreamNew), + SendStart(futures::sink::Send>), + RecvStart(Option>), + Established, + Invalid, } -impl TCPStream { - pub fn connect(addr: &SocketAddr, handle: &Handle) -> BoxFuture, std::io::Error> { - TcpStream::connect(addr, handle) - .and_then(|stream| { - let (sink, source) = stream.framed(XMPPCodec::new()) - // .framed(UTF8Codec::new()) - .split(); - - sink.send(Packet::StreamStart) - .and_then(|sink| result(Ok((Arc::new(Box::new(sink)), source)))) - }) - .and_then(|(sink, source)| { - let sink1 = sink.clone(); - let source = source - .map(|items| iter(items.into_iter().map(Ok))) - .flatten() - .filter_map(move |pkt| Self::process_packet(pkt, &sink1)) - // .for_each(|ev| { - // match ev { - // Packet::Stanza - // _ => (), - // } - // Ok(println!("xmpp: {:?}", ev)) - // }) - // .boxed(); - ; - result(Ok(Arc::new(TCPStream { - source: Box::new(source), - sink: sink, - }))) - }).boxed() - //.map_err(|e| std::io::Error::new(ErrorKind::Other, e)); +impl std::fmt::Debug for TcpClientState { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + let s = match *self { + TcpClientState::Connecting(_) => "Connecting", + TcpClientState::SendStart(_) => "SendStart", + TcpClientState::RecvStart(_) => "RecvStart", + TcpClientState::Established => "Established", + TcpClientState::Invalid => "Invalid", + }; + write!(fmt, "{}", s) } +} - fn process_packet(pkt: Packet, sink: &Arc) -> Option - where S: Sink { - - println!("pkt: {:?}", pkt); - None +impl TcpClient { + pub fn connect(addr: &SocketAddr, handle: &Handle) -> Self { + let tcp_stream_new = TcpStream::connect(addr, handle); + TcpClient { + state: TcpClientState::Connecting(tcp_stream_new), + } } } -struct ClientStream { - inner: TCPStream, -} +impl Future for TcpClient { + type Item = XMPPStream; + type Error = std::io::Error; -impl ClientStream { - pub fn connect(jid: &str, password: &str, handle: &Handle) -> Box> { - let addr = "[2a01:4f8:a0:33d0::5]:5222" - .to_socket_addrs().unwrap() - .next().unwrap(); - let stream = - TCPStream::connect(&addr, handle) - .and_then(|stream| { - Ok(ClientStream { - inner: stream - }) - }); - Box::new(stream) + fn poll(&mut self) -> Poll { + let (new_state, result) = match self.state { + TcpClientState::Connecting(ref mut tcp_stream_new) => { + let tcp_stream = try_ready!(tcp_stream_new.poll()); + let xmpp_stream = tcp_stream.framed(XMPPCodec::new()); + let send = xmpp_stream.send(Packet::StreamStart); + let new_state = TcpClientState::SendStart(send); + (new_state, Ok(Async::NotReady)) + }, + TcpClientState::SendStart(ref mut send) => { + let xmpp_stream = try_ready!(send.poll()); + let new_state = TcpClientState::RecvStart(Some(xmpp_stream)); + (new_state, Ok(Async::NotReady)) + }, + TcpClientState::RecvStart(ref mut opt_xmpp_stream) => { + let mut xmpp_stream = opt_xmpp_stream.take().unwrap(); + match xmpp_stream.poll() { + Ok(Async::Ready(Some(events))) => println!("Recv start: {:?}", events), + Ok(Async::Ready(_)) => return Err(std::io::Error::from(ErrorKind::InvalidData)), + Ok(Async::NotReady) => { + *opt_xmpp_stream = Some(xmpp_stream); + return Ok(Async::NotReady); + }, + Err(e) => return Err(e) + }; + let new_state = TcpClientState::Established; + (new_state, Ok(Async::Ready(xmpp_stream))) + }, + TcpClientState::Established | TcpClientState::Invalid => + unreachable!(), + }; + + println!("Next state: {:?}", new_state); + self.state = new_state; + match result { + // by polling again, we register new future + Ok(Async::NotReady) => self.poll(), + result => result + } } } #[cfg(test)] mod tests { use tokio_core::reactor::Core; + use futures::{Future, Stream}; #[test] fn it_works() { + use std::net::ToSocketAddrs; + let addr = "[2a01:4f8:a0:33d0::5]:5222" + .to_socket_addrs().unwrap() + .next().unwrap(); + let mut core = Core::new().unwrap(); - let client = super::ClientStream::connect( - "astro@spaceboyz.net", - "...", + let client = super::TcpClient::connect( + &addr, &core.handle() ).and_then(|stream| { - stream.inner.source.boxed().for_each(|item| { + stream.for_each(|item| { Ok(println!("stream item: {:?}", item)) }) - }).boxed(); + }); core.run(client).unwrap(); } diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 847339315fce725d93bebb51b0c194fe86810e1a..e76dce59eb5e8521b6e277b26bdcdc4917398234 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -2,7 +2,7 @@ use std; use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; -use tokio_core::io::{Codec, EasyBuf}; +use tokio_core::io::{Codec, EasyBuf, Framed}; use xml; const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; @@ -51,6 +51,8 @@ pub enum Packet { StreamEnd, } +pub type XMPPStream = Framed; + pub struct XMPPCodec { parser: xml::Parser, root: Option, @@ -70,6 +72,7 @@ impl Codec for XMPPCodec { type Out = Packet; fn decode(&mut self, buf: &mut EasyBuf) -> Result, Error> { + println!("XMPPCodec.decode {:?}", buf.len()); match from_utf8(buf.as_slice()) { Ok(s) => self.parser.feed_str(s), From aece3798c11e564add80b2cdcd8f235fa907cc25 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 3 Jun 2017 02:17:12 +0200 Subject: [PATCH 003/135] XMPPCodec Input shall be just one Packet --- src/lib.rs | 2 +- src/xmpp_codec.rs | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f8e6453e0d2b74008d72865223f4712c16cc9c2c..f57e7b8fc6e887869092189bc0cce0a5c25bfd80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ impl Future for TcpClient { TcpClientState::RecvStart(ref mut opt_xmpp_stream) => { let mut xmpp_stream = opt_xmpp_stream.take().unwrap(); match xmpp_stream.poll() { - Ok(Async::Ready(Some(events))) => println!("Recv start: {:?}", events), + Ok(Async::Ready(Some(Packet::StreamStart))) => println!("Recv start!"), Ok(Async::Ready(_)) => return Err(std::io::Error::from(ErrorKind::InvalidData)), Ok(Async::NotReady) => { *opt_xmpp_stream = Some(xmpp_stream); diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index e76dce59eb5e8521b6e277b26bdcdc4917398234..ec718146dcab60b96d8681b25f05c27bc295654c 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -68,12 +68,14 @@ impl XMPPCodec { } impl Codec for XMPPCodec { - type In = Vec; + type In = Packet; type Out = Packet; fn decode(&mut self, buf: &mut EasyBuf) -> Result, Error> { println!("XMPPCodec.decode {:?}", buf.len()); - match from_utf8(buf.as_slice()) { + let buf_len = buf.len(); + let chunk = buf.drain_to(buf_len); + match from_utf8(chunk.as_slice()) { Ok(s) => self.parser.feed_str(s), Err(e) => @@ -81,7 +83,7 @@ impl Codec for XMPPCodec { } let mut new_root = None; - let mut results = Vec::new(); + let mut result = None; for event in &mut self.parser { match &mut self.root { &mut None => { @@ -89,10 +91,13 @@ impl Codec for XMPPCodec { match event { Ok(xml::Event::ElementStart(start_tag)) => { new_root = Some(XMPPRoot::new(start_tag)); - results.push(Packet::StreamStart); + result = Some(Packet::StreamStart); + break + }, + Err(e) => { + result = Some(Packet::Error(Box::new(e))); + break }, - Err(e) => - results.push(Packet::Error(Box::new(e))), _ => (), } @@ -103,10 +108,13 @@ impl Codec for XMPPCodec { None => (), Some(Ok(stanza)) => { println!("stanza: {}", stanza); - results.push(Packet::Stanza(stanza)); + result = Some(Packet::Stanza(stanza)); + break }, - Some(Err(e)) => - results.push(Packet::Error(Box::new(e))), + Some(Err(e)) => { + result = Some(Packet::Error(Box::new(e))); + break + } }; }, } @@ -117,11 +125,7 @@ impl Codec for XMPPCodec { } } - if results.len() == 0 { - Ok(None) - } else { - Ok(Some(results)) - } + Ok(result) } fn encode(&mut self, msg: Self::Out, buf: &mut Vec) -> Result<(), Error> { @@ -147,6 +151,6 @@ impl Codec for XMPPCodec { } fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result { - Ok(vec!()) + Err(Error::from(ErrorKind::UnexpectedEof)) } } From 0a34c6c71f9b3e508f9117b3a5d1b925b2e1d0e8 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 3 Jun 2017 02:26:44 +0200 Subject: [PATCH 004/135] fix stanza events --- src/lib.rs | 9 +++++++-- src/xmpp_codec.rs | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f57e7b8fc6e887869092189bc0cce0a5c25bfd80..043c81e7c3b2c36b5608c9fdb8488207c6821c49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,6 +105,7 @@ impl Future for TcpClient { mod tests { use tokio_core::reactor::Core; use futures::{Future, Stream}; + use xmpp_codec::Packet; #[test] fn it_works() { @@ -118,8 +119,12 @@ mod tests { &addr, &core.handle() ).and_then(|stream| { - stream.for_each(|item| { - Ok(println!("stream item: {:?}", item)) + stream.for_each(|event| { + match event { + Packet::Stanza(el) => println!("<< {}", el), + _ => println!("!! {:?}", event), + } + Ok(()) }) }); core.run(client).unwrap(); diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index ec718146dcab60b96d8681b25f05c27bc295654c..dc7aeb7e031b06077481ac95a003003a956e406b 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -85,12 +85,12 @@ impl Codec for XMPPCodec { let mut new_root = None; let mut result = None; for event in &mut self.parser { - match &mut self.root { - &mut None => { + match self.root { + None => { // Expecting match event { Ok(xml::Event::ElementStart(start_tag)) => { - new_root = Some(XMPPRoot::new(start_tag)); + self.root = Some(XMPPRoot::new(start_tag)); result = Some(Packet::StreamStart); break }, @@ -103,7 +103,7 @@ impl Codec for XMPPCodec { } } - &mut Some(ref mut root) => { + Some(ref mut root) => { match root.handle_event(event) { None => (), Some(Ok(stanza)) => { From 288930bcd44351d9f9617f8a213a5ebd3e2e8a81 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 4 Jun 2017 01:37:46 +0200 Subject: [PATCH 005/135] reorg --- examples/echo_bot.rs | 29 ++++++++++ src/lib.rs | 128 ++----------------------------------------- src/tcp.rs | 97 ++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 123 deletions(-) create mode 100644 examples/echo_bot.rs create mode 100644 src/tcp.rs diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs new file mode 100644 index 0000000000000000000000000000000000000000..f1e4aff2c1bbc61c0e480fc4af4e322ad3272ef7 --- /dev/null +++ b/examples/echo_bot.rs @@ -0,0 +1,29 @@ +extern crate futures; +extern crate tokio_core; +extern crate tokio_xmpp; + +use tokio_core::reactor::Core; +use futures::{Future, Stream}; +use tokio_xmpp::{Packet, TcpClient}; + +fn main() { + use std::net::ToSocketAddrs; + let addr = "[2a01:4f8:a0:33d0::5]:5222" + .to_socket_addrs().unwrap() + .next().unwrap(); + + let mut core = Core::new().unwrap(); + let client = TcpClient::connect( + &addr, + &core.handle() + ).and_then(|stream| { + stream.for_each(|event| { + match event { + Packet::Stanza(el) => println!("<< {}", el), + _ => println!("!! {:?}", event), + } + Ok(()) + }) + }); + core.run(client).unwrap(); +} diff --git a/src/lib.rs b/src/lib.rs index 043c81e7c3b2c36b5608c9fdb8488207c6821c49..02a3295ac4cc2d4acb24755bbe48b892a83b8d05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,133 +2,15 @@ extern crate futures; extern crate tokio_core; extern crate xml; +extern crate rustls; +extern crate tokio_rustls; -use std::net::SocketAddr; -use std::net::ToSocketAddrs; -use std::sync::Arc; -use std::io::ErrorKind; -use futures::{Future, BoxFuture, Sink, Poll, Async}; -use futures::stream::{Stream, iter}; -use futures::future::result; -use tokio_core::reactor::Handle; -use tokio_core::io::Io; -use tokio_core::net::{TcpStream, TcpStreamNew}; mod xmpp_codec; -use xmpp_codec::*; +pub use xmpp_codec::*; +mod tcp; +pub use tcp::*; // type FullClient = sasl::Client> -#[derive(Debug)] -pub struct TcpClient { - state: TcpClientState, -} - -enum TcpClientState { - Connecting(TcpStreamNew), - SendStart(futures::sink::Send>), - RecvStart(Option>), - Established, - Invalid, -} - -impl std::fmt::Debug for TcpClientState { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - let s = match *self { - TcpClientState::Connecting(_) => "Connecting", - TcpClientState::SendStart(_) => "SendStart", - TcpClientState::RecvStart(_) => "RecvStart", - TcpClientState::Established => "Established", - TcpClientState::Invalid => "Invalid", - }; - write!(fmt, "{}", s) - } -} - -impl TcpClient { - pub fn connect(addr: &SocketAddr, handle: &Handle) -> Self { - let tcp_stream_new = TcpStream::connect(addr, handle); - TcpClient { - state: TcpClientState::Connecting(tcp_stream_new), - } - } -} - -impl Future for TcpClient { - type Item = XMPPStream; - type Error = std::io::Error; - - fn poll(&mut self) -> Poll { - let (new_state, result) = match self.state { - TcpClientState::Connecting(ref mut tcp_stream_new) => { - let tcp_stream = try_ready!(tcp_stream_new.poll()); - let xmpp_stream = tcp_stream.framed(XMPPCodec::new()); - let send = xmpp_stream.send(Packet::StreamStart); - let new_state = TcpClientState::SendStart(send); - (new_state, Ok(Async::NotReady)) - }, - TcpClientState::SendStart(ref mut send) => { - let xmpp_stream = try_ready!(send.poll()); - let new_state = TcpClientState::RecvStart(Some(xmpp_stream)); - (new_state, Ok(Async::NotReady)) - }, - TcpClientState::RecvStart(ref mut opt_xmpp_stream) => { - let mut xmpp_stream = opt_xmpp_stream.take().unwrap(); - match xmpp_stream.poll() { - Ok(Async::Ready(Some(Packet::StreamStart))) => println!("Recv start!"), - Ok(Async::Ready(_)) => return Err(std::io::Error::from(ErrorKind::InvalidData)), - Ok(Async::NotReady) => { - *opt_xmpp_stream = Some(xmpp_stream); - return Ok(Async::NotReady); - }, - Err(e) => return Err(e) - }; - let new_state = TcpClientState::Established; - (new_state, Ok(Async::Ready(xmpp_stream))) - }, - TcpClientState::Established | TcpClientState::Invalid => - unreachable!(), - }; - - println!("Next state: {:?}", new_state); - self.state = new_state; - match result { - // by polling again, we register new future - Ok(Async::NotReady) => self.poll(), - result => result - } - } -} - -#[cfg(test)] -mod tests { - use tokio_core::reactor::Core; - use futures::{Future, Stream}; - use xmpp_codec::Packet; - - #[test] - fn it_works() { - use std::net::ToSocketAddrs; - let addr = "[2a01:4f8:a0:33d0::5]:5222" - .to_socket_addrs().unwrap() - .next().unwrap(); - - let mut core = Core::new().unwrap(); - let client = super::TcpClient::connect( - &addr, - &core.handle() - ).and_then(|stream| { - stream.for_each(|event| { - match event { - Packet::Stanza(el) => println!("<< {}", el), - _ => println!("!! {:?}", event), - } - Ok(()) - }) - }); - core.run(client).unwrap(); - } - - // TODO: test truncated utf8 -} diff --git a/src/tcp.rs b/src/tcp.rs new file mode 100644 index 0000000000000000000000000000000000000000..fc0d6654e0cfcf1dd9cc23dfb46c0edf6dd238d2 --- /dev/null +++ b/src/tcp.rs @@ -0,0 +1,97 @@ +use std::fmt; +use std::net::SocketAddr; +use std::net::ToSocketAddrs; +use std::sync::Arc; +use std::io::{Error, ErrorKind}; +use futures::{Future, BoxFuture, Sink, Poll, Async}; +use futures::stream::{Stream, iter}; +use futures::sink; +use tokio_core::reactor::Handle; +use tokio_core::io::Io; +use tokio_core::net::{TcpStream, TcpStreamNew}; +use rustls::ClientConfig; +use tokio_rustls::ClientConfigExt; + +use super::{XMPPStream, XMPPCodec, Packet}; + + +#[derive(Debug)] +pub struct TcpClient { + state: TcpClientState, +} + +enum TcpClientState { + Connecting(TcpStreamNew), + SendStart(sink::Send>), + RecvStart(Option>), + Established, + Invalid, +} + +impl fmt::Debug for TcpClientState { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let s = match *self { + TcpClientState::Connecting(_) => "Connecting", + TcpClientState::SendStart(_) => "SendStart", + TcpClientState::RecvStart(_) => "RecvStart", + TcpClientState::Established => "Established", + TcpClientState::Invalid => "Invalid", + }; + write!(fmt, "{}", s) + } +} + +impl TcpClient { + pub fn connect(addr: &SocketAddr, handle: &Handle) -> Self { + let tcp_stream_new = TcpStream::connect(addr, handle); + TcpClient { + state: TcpClientState::Connecting(tcp_stream_new), + } + } +} + +impl Future for TcpClient { + type Item = XMPPStream; + type Error = Error; + + fn poll(&mut self) -> Poll { + let (new_state, result) = match self.state { + TcpClientState::Connecting(ref mut tcp_stream_new) => { + let tcp_stream = try_ready!(tcp_stream_new.poll()); + let xmpp_stream = tcp_stream.framed(XMPPCodec::new()); + let send = xmpp_stream.send(Packet::StreamStart); + let new_state = TcpClientState::SendStart(send); + (new_state, Ok(Async::NotReady)) + }, + TcpClientState::SendStart(ref mut send) => { + let xmpp_stream = try_ready!(send.poll()); + let new_state = TcpClientState::RecvStart(Some(xmpp_stream)); + (new_state, Ok(Async::NotReady)) + }, + TcpClientState::RecvStart(ref mut opt_xmpp_stream) => { + let mut xmpp_stream = opt_xmpp_stream.take().unwrap(); + match xmpp_stream.poll() { + Ok(Async::Ready(Some(Packet::StreamStart))) => println!("Recv start!"), + Ok(Async::Ready(_)) => return Err(Error::from(ErrorKind::InvalidData)), + Ok(Async::NotReady) => { + *opt_xmpp_stream = Some(xmpp_stream); + return Ok(Async::NotReady); + }, + Err(e) => return Err(e) + }; + let new_state = TcpClientState::Established; + (new_state, Ok(Async::Ready(xmpp_stream))) + }, + TcpClientState::Established | TcpClientState::Invalid => + unreachable!(), + }; + + println!("Next state: {:?}", new_state); + self.state = new_state; + match result { + // by polling again, we register new future + Ok(Async::NotReady) => self.poll(), + result => result + } + } +} From 482bf779551b48d82a3c54f5f8a40ba93401eab2 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 4 Jun 2017 02:05:08 +0200 Subject: [PATCH 006/135] tidy up --- Cargo.toml | 2 ++ src/lib.rs | 4 ++-- src/tcp.rs | 19 +++++++---------- src/xmpp_codec.rs | 53 ++++++++++++++++++++++------------------------- 4 files changed, 36 insertions(+), 42 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a22e0bdfce87bb334039930997ae76d54fe982b..23d59db4b893beba008b8dbd1552479ac60c4432 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,6 @@ authors = ["Astro "] [dependencies] futures = "*" tokio-core = "*" +tokio-io = "*" +bytes = "*" RustyXML = "*" diff --git a/src/lib.rs b/src/lib.rs index 02a3295ac4cc2d4acb24755bbe48b892a83b8d05..20ded2ef7b9f65e20020acba0b31e279bec4ea2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,9 @@ #[macro_use] extern crate futures; extern crate tokio_core; +extern crate tokio_io; +extern crate bytes; extern crate xml; -extern crate rustls; -extern crate tokio_rustls; mod xmpp_codec; diff --git a/src/tcp.rs b/src/tcp.rs index fc0d6654e0cfcf1dd9cc23dfb46c0edf6dd238d2..01b9db0f102438758326221d04b4d04e049bcd17 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -1,16 +1,12 @@ use std::fmt; use std::net::SocketAddr; -use std::net::ToSocketAddrs; -use std::sync::Arc; use std::io::{Error, ErrorKind}; -use futures::{Future, BoxFuture, Sink, Poll, Async}; -use futures::stream::{Stream, iter}; +use futures::{Future, Sink, Poll, Async}; +use futures::stream::Stream; use futures::sink; use tokio_core::reactor::Handle; -use tokio_core::io::Io; +use tokio_io::AsyncRead; use tokio_core::net::{TcpStream, TcpStreamNew}; -use rustls::ClientConfig; -use tokio_rustls::ClientConfigExt; use super::{XMPPStream, XMPPCodec, Packet}; @@ -25,7 +21,6 @@ enum TcpClientState { SendStart(sink::Send>), RecvStart(Option>), Established, - Invalid, } impl fmt::Debug for TcpClientState { @@ -35,9 +30,9 @@ impl fmt::Debug for TcpClientState { TcpClientState::SendStart(_) => "SendStart", TcpClientState::RecvStart(_) => "RecvStart", TcpClientState::Established => "Established", - TcpClientState::Invalid => "Invalid", }; - write!(fmt, "{}", s) + try!(write!(fmt, "{}", s)); + Ok(()) } } @@ -58,7 +53,7 @@ impl Future for TcpClient { let (new_state, result) = match self.state { TcpClientState::Connecting(ref mut tcp_stream_new) => { let tcp_stream = try_ready!(tcp_stream_new.poll()); - let xmpp_stream = tcp_stream.framed(XMPPCodec::new()); + let xmpp_stream = AsyncRead::framed(tcp_stream, XMPPCodec::new()); let send = xmpp_stream.send(Packet::StreamStart); let new_state = TcpClientState::SendStart(send); (new_state, Ok(Async::NotReady)) @@ -82,7 +77,7 @@ impl Future for TcpClient { let new_state = TcpClientState::Established; (new_state, Ok(Async::Ready(xmpp_stream))) }, - TcpClientState::Established | TcpClientState::Invalid => + TcpClientState::Established => unreachable!(), }; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index dc7aeb7e031b06077481ac95a003003a956e406b..28c0dfbd21d98ae1460e6e3f9207954d6a8f68ea 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -1,9 +1,11 @@ use std; +use std::fmt::Write; use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; -use tokio_core::io::{Codec, EasyBuf, Framed}; +use tokio_io::codec::{Framed, Encoder, Decoder}; use xml; +use bytes::*; const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; const NS_STREAMS: &'static str = "http://etherx.jabber.org/streams"; @@ -67,22 +69,20 @@ impl XMPPCodec { } } -impl Codec for XMPPCodec { - type In = Packet; - type Out = Packet; +impl Decoder for XMPPCodec { + type Item = Packet; + type Error = Error; - fn decode(&mut self, buf: &mut EasyBuf) -> Result, Error> { + fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { println!("XMPPCodec.decode {:?}", buf.len()); - let buf_len = buf.len(); - let chunk = buf.drain_to(buf_len); - match from_utf8(chunk.as_slice()) { + match from_utf8(buf.take().as_ref()) { Ok(s) => self.parser.feed_str(s), Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)), } - let mut new_root = None; + let mut new_root: Option = None; let mut result = None; for event in &mut self.parser { match self.root { @@ -128,29 +128,26 @@ impl Codec for XMPPCodec { Ok(result) } - fn encode(&mut self, msg: Self::Out, buf: &mut Vec) -> Result<(), Error> { - match msg { + fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Error> { + self.decode(buf) + } +} + +impl Encoder for XMPPCodec { + type Item = Packet; + type Error = Error; + + fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + match item { Packet::StreamStart => { - let mut write = |s: &str| { - buf.extend_from_slice(s.as_bytes()); - }; - - write("\n"); - write("\n"); - - Ok(()) + write!(dst, + "\n +\n", + NS_CLIENT, NS_STREAMS) + .map_err(|_| Error::from(ErrorKind::WriteZero)) }, // TODO: Implement all _ => Ok(()) } } - - fn decode_eof(&mut self, _buf: &mut EasyBuf) -> Result { - Err(Error::from(ErrorKind::UnexpectedEof)) - } } From a618acd6d6fcc9f97490902fc401c2f157270fa0 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 5 Jun 2017 00:42:35 +0200 Subject: [PATCH 007/135] starttls works --- Cargo.toml | 2 + examples/echo_bot.rs | 21 ++++++- src/lib.rs | 4 ++ src/starttls.rs | 142 +++++++++++++++++++++++++++++++++++++++++++ src/tcp.rs | 3 +- src/xmpp_codec.rs | 10 +++ 6 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 src/starttls.rs diff --git a/Cargo.toml b/Cargo.toml index 23d59db4b893beba008b8dbd1552479ac60c4432..39de218681051fa316f44d867e007f7f5fad8306 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,5 @@ tokio-core = "*" tokio-io = "*" bytes = "*" RustyXML = "*" +rustls = "*" +tokio-rustls = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index f1e4aff2c1bbc61c0e480fc4af4e322ad3272ef7..6933e1a2f227a357b282e62ffbbaf20b61948768 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,10 +1,15 @@ extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; +extern crate rustls; +use std::sync::Arc; +use std::io::BufReader; +use std::fs::File; use tokio_core::reactor::Core; use futures::{Future, Stream}; -use tokio_xmpp::{Packet, TcpClient}; +use tokio_xmpp::{Packet, TcpClient, StartTlsClient}; +use rustls::ClientConfig; fn main() { use std::net::ToSocketAddrs; @@ -12,10 +17,16 @@ fn main() { .to_socket_addrs().unwrap() .next().unwrap(); + let mut config = ClientConfig::new(); + let mut certfile = BufReader::new(File::open("/usr/share/ca-certificates/CAcert/root.crt").unwrap()); + config.root_store.add_pem_file(&mut certfile).unwrap(); + let arc_config = Arc::new(config); + let mut core = Core::new().unwrap(); let client = TcpClient::connect( &addr, &core.handle() + ).and_then(|stream| StartTlsClient::from_stream(stream, arc_config) ).and_then(|stream| { stream.for_each(|event| { match event { @@ -25,5 +36,11 @@ fn main() { Ok(()) }) }); - core.run(client).unwrap(); + match core.run(client) { + Ok(_) => (), + Err(e) => { + println!("Fatal: {}", e); + () + } + } } diff --git a/src/lib.rs b/src/lib.rs index 20ded2ef7b9f65e20020acba0b31e279bec4ea2b..bcf666512f471a7c91730a5363928b5dca974dc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,16 @@ extern crate tokio_core; extern crate tokio_io; extern crate bytes; extern crate xml; +extern crate rustls; +extern crate tokio_rustls; mod xmpp_codec; pub use xmpp_codec::*; mod tcp; pub use tcp::*; +mod starttls; +pub use starttls::*; // type FullClient = sasl::Client> diff --git a/src/starttls.rs b/src/starttls.rs new file mode 100644 index 0000000000000000000000000000000000000000..b14982aba596815b73bf26191d30a9446fcf0e98 --- /dev/null +++ b/src/starttls.rs @@ -0,0 +1,142 @@ +use std::mem::replace; +use std::io::{Error, ErrorKind}; +use std::sync::Arc; +use futures::{Future, Sink, Poll, Async}; +use futures::stream::Stream; +use futures::sink; +use tokio_core::net::TcpStream; +use rustls::*; +use tokio_rustls::*; +use xml; + +use super::{XMPPStream, XMPPCodec, Packet}; + + +const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; +const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; + +pub struct StartTlsClient { + state: StartTlsClientState, + arc_config: Arc, +} + +enum StartTlsClientState { + Invalid, + AwaitFeatures(XMPPStream), + SendStartTls(sink::Send>), + AwaitProceed(XMPPStream), + StartingTls(ConnectAsync), +} + +impl StartTlsClient { + /// Waits for + pub fn from_stream(xmpp_stream: XMPPStream, arc_config: Arc) -> Self { + StartTlsClient { + state: StartTlsClientState::AwaitFeatures(xmpp_stream), + arc_config: arc_config, + } + } +} + +// TODO: eval , check ns +impl Future for StartTlsClient { + type Item = XMPPStream>; + type Error = Error; + + fn poll(&mut self) -> Poll { + let old_state = replace(&mut self.state, StartTlsClientState::Invalid); + let mut retry = false; + + let (new_state, result) = match old_state { + StartTlsClientState::AwaitFeatures(mut xmpp_stream) => + match xmpp_stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name == "features" + && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) + => + { + println!("Got features: {}", stanza); + match stanza.get_child("starttls", Some(NS_XMPP_TLS)) { + None => + (StartTlsClientState::Invalid, Err(Error::from(ErrorKind::InvalidData))), + Some(_) => { + let nonza = xml::Element::new( + "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), + vec![] + ); + println!("send {}", nonza); + let packet = Packet::Stanza(nonza); + let send = xmpp_stream.send(packet); + let new_state = StartTlsClientState::SendStartTls(send); + retry = true; + (new_state, Ok(Async::NotReady)) + }, + } + }, + Ok(Async::Ready(value)) => { + println!("StartTlsClient ignore {:?}", value); + (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)) + }, + Ok(_) => + (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)), + Err(e) => + (StartTlsClientState::AwaitFeatures(xmpp_stream), Err(e)), + }, + StartTlsClientState::SendStartTls(mut send) => + match send.poll() { + Ok(Async::Ready(xmpp_stream)) => { + println!("starttls sent"); + let new_state = StartTlsClientState::AwaitProceed(xmpp_stream); + retry = true; + (new_state, Ok(Async::NotReady)) + }, + Ok(Async::NotReady) => + (StartTlsClientState::SendStartTls(send), Ok(Async::NotReady)), + Err(e) => + (StartTlsClientState::SendStartTls(send), Err(e)), + }, + StartTlsClientState::AwaitProceed(mut xmpp_stream) => + match xmpp_stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name == "proceed" => + { + println!("* proceed *"); + let stream = xmpp_stream.into_inner(); + let connect = self.arc_config.connect_async("spaceboyz.net", stream); + let new_state = StartTlsClientState::StartingTls(connect); + retry = true; + (new_state, Ok(Async::NotReady)) + }, + Ok(Async::Ready(value)) => { + println!("StartTlsClient ignore {:?}", value); + (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)) + }, + Ok(_) => + (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)), + Err(e) => + (StartTlsClientState::AwaitProceed(xmpp_stream), Err(e)), + }, + StartTlsClientState::StartingTls(mut connect) => + match connect.poll() { + Ok(Async::Ready(tls_stream)) => { + println!("Got a TLS stream!"); + let xmpp_stream = XMPPCodec::frame_stream(tls_stream); + (StartTlsClientState::Invalid, Ok(Async::Ready(xmpp_stream))) + }, + Ok(Async::NotReady) => + (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), + Err(e) => + (StartTlsClientState::StartingTls(connect), Err(e)), + }, + StartTlsClientState::Invalid => + unreachable!(), + }; + + self.state = new_state; + if retry { + self.poll() + } else { + result + } + } +} diff --git a/src/tcp.rs b/src/tcp.rs index 01b9db0f102438758326221d04b4d04e049bcd17..29608ea6f2abcf47a358a42e1235eee573888a79 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -5,7 +5,6 @@ use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; use futures::sink; use tokio_core::reactor::Handle; -use tokio_io::AsyncRead; use tokio_core::net::{TcpStream, TcpStreamNew}; use super::{XMPPStream, XMPPCodec, Packet}; @@ -53,7 +52,7 @@ impl Future for TcpClient { let (new_state, result) = match self.state { TcpClientState::Connecting(ref mut tcp_stream_new) => { let tcp_stream = try_ready!(tcp_stream_new.poll()); - let xmpp_stream = AsyncRead::framed(tcp_stream, XMPPCodec::new()); + let xmpp_stream = XMPPCodec::frame_stream(tcp_stream); let send = xmpp_stream.send(Packet::StreamStart); let new_state = TcpClientState::SendStart(send); (new_state, Ok(Async::NotReady)) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 28c0dfbd21d98ae1460e6e3f9207954d6a8f68ea..38c593e46cd736aeb2976819dba501eaa96c376a 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -3,6 +3,7 @@ use std::fmt::Write; use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; +use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::{Framed, Encoder, Decoder}; use xml; use bytes::*; @@ -67,6 +68,12 @@ impl XMPPCodec { root: None, } } + + pub fn frame_stream(stream: S) -> Framed + where S: AsyncRead + AsyncWrite + { + AsyncRead::framed(stream, XMPPCodec::new()) + } } impl Decoder for XMPPCodec { @@ -146,6 +153,9 @@ impl Encoder for XMPPCodec { NS_CLIENT, NS_STREAMS) .map_err(|_| Error::from(ErrorKind::WriteZero)) }, + Packet::Stanza(stanza) => + write!(dst, "{}", stanza) + .map_err(|_| Error::from(ErrorKind::InvalidInput)), // TODO: Implement all _ => Ok(()) } From 98e7a2fbf4781f1b92c854a919ea075afe83899f Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 5 Jun 2017 00:45:16 +0200 Subject: [PATCH 008/135] starttls: parameterize TcpStream --- src/starttls.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/starttls.rs b/src/starttls.rs index b14982aba596815b73bf26191d30a9446fcf0e98..59946da38922cd3d60b941551f73fe85e6d5c5f1 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; use futures::sink; -use tokio_core::net::TcpStream; +use tokio_io::{AsyncRead, AsyncWrite}; use rustls::*; use tokio_rustls::*; use xml; @@ -15,22 +15,22 @@ use super::{XMPPStream, XMPPCodec, Packet}; const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; -pub struct StartTlsClient { - state: StartTlsClientState, +pub struct StartTlsClient { + state: StartTlsClientState, arc_config: Arc, } -enum StartTlsClientState { +enum StartTlsClientState { Invalid, - AwaitFeatures(XMPPStream), - SendStartTls(sink::Send>), - AwaitProceed(XMPPStream), - StartingTls(ConnectAsync), + AwaitFeatures(XMPPStream), + SendStartTls(sink::Send>), + AwaitProceed(XMPPStream), + StartingTls(ConnectAsync), } -impl StartTlsClient { +impl StartTlsClient { /// Waits for - pub fn from_stream(xmpp_stream: XMPPStream, arc_config: Arc) -> Self { + pub fn from_stream(xmpp_stream: XMPPStream, arc_config: Arc) -> Self { StartTlsClient { state: StartTlsClientState::AwaitFeatures(xmpp_stream), arc_config: arc_config, @@ -39,8 +39,8 @@ impl StartTlsClient { } // TODO: eval , check ns -impl Future for StartTlsClient { - type Item = XMPPStream>; +impl Future for StartTlsClient { + type Item = XMPPStream>; type Error = Error; fn poll(&mut self) -> Poll { From c32a38874c00e1befdbbb2cd92e6f3501410255f Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 5 Jun 2017 02:50:22 +0200 Subject: [PATCH 009/135] refactor into stream_start + xmpp_stream --- examples/echo_bot.rs | 10 ++++- src/lib.rs | 5 ++- src/starttls.rs | 79 ++++++++++++++------------------- src/stream_start.rs | 102 +++++++++++++++++++++++++++++++++++++++++++ src/tcp.rs | 52 ++++------------------ src/xmpp_codec.rs | 46 +++++++++---------- src/xmpp_stream.rs | 62 ++++++++++++++++++++++++++ 7 files changed, 239 insertions(+), 117 deletions(-) create mode 100644 src/stream_start.rs create mode 100644 src/xmpp_stream.rs diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 6933e1a2f227a357b282e62ffbbaf20b61948768..0cdd6b07e5c9dc8a4f460d22510daac81577cefc 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -8,7 +8,8 @@ use std::io::BufReader; use std::fs::File; use tokio_core::reactor::Core; use futures::{Future, Stream}; -use tokio_xmpp::{Packet, TcpClient, StartTlsClient}; +use tokio_xmpp::TcpClient; +use tokio_xmpp::xmpp_codec::Packet; use rustls::ClientConfig; fn main() { @@ -26,8 +27,13 @@ fn main() { let client = TcpClient::connect( &addr, &core.handle() - ).and_then(|stream| StartTlsClient::from_stream(stream, arc_config) ).and_then(|stream| { + if stream.can_starttls() { + stream.starttls(arc_config) + } else { + panic!("No STARTTLS") + } + }).and_then(|stream| { stream.for_each(|event| { match event { Packet::Stanza(el) => println!("<< {}", el), diff --git a/src/lib.rs b/src/lib.rs index bcf666512f471a7c91730a5363928b5dca974dc5..9764daeae2d7f1418f58ee181e2ca36730136f20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,9 @@ extern crate rustls; extern crate tokio_rustls; -mod xmpp_codec; -pub use xmpp_codec::*; +pub mod xmpp_codec; +pub mod xmpp_stream; +mod stream_start; mod tcp; pub use tcp::*; mod starttls; diff --git a/src/starttls.rs b/src/starttls.rs index 59946da38922cd3d60b941551f73fe85e6d5c5f1..b0fdc92f16c6807d8159e4e8baac7e92d8310719 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -1,5 +1,5 @@ use std::mem::replace; -use std::io::{Error, ErrorKind}; +use std::io::Error; use std::sync::Arc; use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; @@ -9,36 +9,44 @@ use rustls::*; use tokio_rustls::*; use xml; -use super::{XMPPStream, XMPPCodec, Packet}; +use xmpp_codec::*; +use xmpp_stream::*; +use stream_start::StreamStart; -const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; -const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; +pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; -pub struct StartTlsClient { +pub struct StartTlsClient { state: StartTlsClientState, arc_config: Arc, } -enum StartTlsClientState { +enum StartTlsClientState { Invalid, - AwaitFeatures(XMPPStream), SendStartTls(sink::Send>), AwaitProceed(XMPPStream), StartingTls(ConnectAsync), + Start(StreamStart>), } -impl StartTlsClient { +impl StartTlsClient { /// Waits for pub fn from_stream(xmpp_stream: XMPPStream, arc_config: Arc) -> Self { + let nonza = xml::Element::new( + "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), + vec![] + ); + println!("send {}", nonza); + let packet = Packet::Stanza(nonza); + let send = xmpp_stream.send(packet); + StartTlsClient { - state: StartTlsClientState::AwaitFeatures(xmpp_stream), + state: StartTlsClientState::SendStartTls(send), arc_config: arc_config, } } } -// TODO: eval , check ns impl Future for StartTlsClient { type Item = XMPPStream>; type Error = Error; @@ -48,40 +56,6 @@ impl Future for StartTlsClient { let mut retry = false; let (new_state, result) = match old_state { - StartTlsClientState::AwaitFeatures(mut xmpp_stream) => - match xmpp_stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name == "features" - && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) - => - { - println!("Got features: {}", stanza); - match stanza.get_child("starttls", Some(NS_XMPP_TLS)) { - None => - (StartTlsClientState::Invalid, Err(Error::from(ErrorKind::InvalidData))), - Some(_) => { - let nonza = xml::Element::new( - "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), - vec![] - ); - println!("send {}", nonza); - let packet = Packet::Stanza(nonza); - let send = xmpp_stream.send(packet); - let new_state = StartTlsClientState::SendStartTls(send); - retry = true; - (new_state, Ok(Async::NotReady)) - }, - } - }, - Ok(Async::Ready(value)) => { - println!("StartTlsClient ignore {:?}", value); - (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)) - }, - Ok(_) => - (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)), - Err(e) => - (StartTlsClientState::AwaitFeatures(xmpp_stream), Err(e)), - }, StartTlsClientState::SendStartTls(mut send) => match send.poll() { Ok(Async::Ready(xmpp_stream)) => { @@ -109,7 +83,7 @@ impl Future for StartTlsClient { }, Ok(Async::Ready(value)) => { println!("StartTlsClient ignore {:?}", value); - (StartTlsClientState::AwaitFeatures(xmpp_stream), Ok(Async::NotReady)) + (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)) }, Ok(_) => (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)), @@ -120,14 +94,25 @@ impl Future for StartTlsClient { match connect.poll() { Ok(Async::Ready(tls_stream)) => { println!("Got a TLS stream!"); - let xmpp_stream = XMPPCodec::frame_stream(tls_stream); - (StartTlsClientState::Invalid, Ok(Async::Ready(xmpp_stream))) + let start = XMPPStream::from_stream(tls_stream, "spaceboyz.net".to_owned()); + let new_state = StartTlsClientState::Start(start); + retry = true; + (new_state, Ok(Async::NotReady)) }, Ok(Async::NotReady) => (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), Err(e) => (StartTlsClientState::StartingTls(connect), Err(e)), }, + StartTlsClientState::Start(mut start) => + match start.poll() { + Ok(Async::Ready(xmpp_stream)) => + (StartTlsClientState::Invalid, Ok(Async::Ready(xmpp_stream))), + Ok(Async::NotReady) => + (StartTlsClientState::Start(start), Ok(Async::NotReady)), + Err(e) => + (StartTlsClientState::Invalid, Err(e)), + }, StartTlsClientState::Invalid => unreachable!(), }; diff --git a/src/stream_start.rs b/src/stream_start.rs new file mode 100644 index 0000000000000000000000000000000000000000..480178eb58588e4959c6b60389c0328c47eec290 --- /dev/null +++ b/src/stream_start.rs @@ -0,0 +1,102 @@ +use std::mem::replace; +use std::io::{Error, ErrorKind}; +use std::collections::HashMap; +use futures::*; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::codec::Framed; + +use xmpp_codec::*; +use xmpp_stream::*; + +const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; + +pub struct StreamStart { + state: StreamStartState, +} + +enum StreamStartState { + SendStart(sink::Send>), + RecvStart(Framed), + RecvFeatures(Framed, HashMap), + Invalid, +} + +impl StreamStart { + pub fn from_stream(stream: Framed, to: String) -> Self { + let attrs = [("to".to_owned(), to), + ("version".to_owned(), "1.0".to_owned()), + ("xmlns".to_owned(), "jabber:client".to_owned()), + ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), + ].iter().cloned().collect(); + let send = stream.send(Packet::StreamStart(attrs)); + + StreamStart { + state: StreamStartState::SendStart(send), + } + } +} + +impl Future for StreamStart { + type Item = XMPPStream; + type Error = Error; + + fn poll(&mut self) -> Poll { + let old_state = replace(&mut self.state, StreamStartState::Invalid); + let mut retry = false; + + let (new_state, result) = match old_state { + StreamStartState::SendStart(mut send) => + match send.poll() { + Ok(Async::Ready(stream)) => { + retry = true; + (StreamStartState::RecvStart(stream), Ok(Async::NotReady)) + }, + Ok(Async::NotReady) => + (StreamStartState::SendStart(send), Ok(Async::NotReady)), + Err(e) => + (StreamStartState::Invalid, Err(e)), + }, + StreamStartState::RecvStart(mut stream) => + match stream.poll() { + Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { + retry = true; + // TODO: skip RecvFeatures for version < 1.0 + (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) + }, + Ok(Async::Ready(_)) => + return Err(Error::from(ErrorKind::InvalidData)), + Ok(Async::NotReady) => + (StreamStartState::RecvStart(stream), Ok(Async::NotReady)), + Err(e) => + return Err(e), + }, + StreamStartState::RecvFeatures(mut stream, stream_attrs) => + match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => + if stanza.name == "features" + && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) { + (StreamStartState::Invalid, Ok(Async::Ready(XMPPStream { stream, stream_attrs, stream_features: stanza }))) + } else { + (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) + }, + Ok(Async::Ready(item)) => { + println!("StreamStart skip {:?}", item); + (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) + }, + Ok(Async::NotReady) => + (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)), + Err(e) => + return Err(e), + }, + StreamStartState::Invalid => + unreachable!(), + }; + + self.state = new_state; + if retry { + self.poll() + } else { + result + } + } +} diff --git a/src/tcp.rs b/src/tcp.rs index 29608ea6f2abcf47a358a42e1235eee573888a79..57fb0b1fe28d34368d56c268b0814e26a0af3796 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -1,40 +1,22 @@ -use std::fmt; use std::net::SocketAddr; -use std::io::{Error, ErrorKind}; -use futures::{Future, Sink, Poll, Async}; -use futures::stream::Stream; -use futures::sink; +use std::io::Error; +use futures::{Future, Poll, Async}; use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; -use super::{XMPPStream, XMPPCodec, Packet}; +use xmpp_stream::*; +use stream_start::StreamStart; - -#[derive(Debug)] pub struct TcpClient { state: TcpClientState, } enum TcpClientState { Connecting(TcpStreamNew), - SendStart(sink::Send>), - RecvStart(Option>), + Start(StreamStart), Established, } -impl fmt::Debug for TcpClientState { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let s = match *self { - TcpClientState::Connecting(_) => "Connecting", - TcpClientState::SendStart(_) => "SendStart", - TcpClientState::RecvStart(_) => "RecvStart", - TcpClientState::Established => "Established", - }; - try!(write!(fmt, "{}", s)); - Ok(()) - } -} - impl TcpClient { pub fn connect(addr: &SocketAddr, handle: &Handle) -> Self { let tcp_stream_new = TcpStream::connect(addr, handle); @@ -52,27 +34,12 @@ impl Future for TcpClient { let (new_state, result) = match self.state { TcpClientState::Connecting(ref mut tcp_stream_new) => { let tcp_stream = try_ready!(tcp_stream_new.poll()); - let xmpp_stream = XMPPCodec::frame_stream(tcp_stream); - let send = xmpp_stream.send(Packet::StreamStart); - let new_state = TcpClientState::SendStart(send); - (new_state, Ok(Async::NotReady)) - }, - TcpClientState::SendStart(ref mut send) => { - let xmpp_stream = try_ready!(send.poll()); - let new_state = TcpClientState::RecvStart(Some(xmpp_stream)); + let start = XMPPStream::from_stream(tcp_stream, "spaceboyz.net".to_owned()); + let new_state = TcpClientState::Start(start); (new_state, Ok(Async::NotReady)) }, - TcpClientState::RecvStart(ref mut opt_xmpp_stream) => { - let mut xmpp_stream = opt_xmpp_stream.take().unwrap(); - match xmpp_stream.poll() { - Ok(Async::Ready(Some(Packet::StreamStart))) => println!("Recv start!"), - Ok(Async::Ready(_)) => return Err(Error::from(ErrorKind::InvalidData)), - Ok(Async::NotReady) => { - *opt_xmpp_stream = Some(xmpp_stream); - return Ok(Async::NotReady); - }, - Err(e) => return Err(e) - }; + TcpClientState::Start(ref mut start) => { + let xmpp_stream = try_ready!(start.poll()); let new_state = TcpClientState::Established; (new_state, Ok(Async::Ready(xmpp_stream))) }, @@ -80,7 +47,6 @@ impl Future for TcpClient { unreachable!(), }; - println!("Next state: {:?}", new_state); self.state = new_state; match result { // by polling again, we register new future diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 38c593e46cd736aeb2976819dba501eaa96c376a..8595dfca21e47aaff03557e1d9770e5f4f0b726a 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -3,18 +3,17 @@ use std::fmt::Write; use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_io::codec::{Framed, Encoder, Decoder}; +use tokio_io::codec::{Encoder, Decoder}; use xml; use bytes::*; const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; -const NS_STREAMS: &'static str = "http://etherx.jabber.org/streams"; -const NS_CLIENT: &'static str = "jabber:client"; + +pub type Attributes = HashMap<(String, Option), String>; struct XMPPRoot { builder: xml::ElementBuilder, - pub attributes: HashMap<(String, Option), String>, + pub attributes: Attributes, } impl XMPPRoot { @@ -49,13 +48,11 @@ impl XMPPRoot { #[derive(Debug)] pub enum Packet { Error(Box), - StreamStart, + StreamStart(HashMap), Stanza(xml::Element), StreamEnd, } -pub type XMPPStream = Framed; - pub struct XMPPCodec { parser: xml::Parser, root: Option, @@ -68,12 +65,6 @@ impl XMPPCodec { root: None, } } - - pub fn frame_stream(stream: S) -> Framed - where S: AsyncRead + AsyncWrite - { - AsyncRead::framed(stream, XMPPCodec::new()) - } } impl Decoder for XMPPCodec { @@ -97,8 +88,12 @@ impl Decoder for XMPPCodec { // Expecting match event { Ok(xml::Event::ElementStart(start_tag)) => { + let mut attrs: HashMap = HashMap::new(); + for (&(ref name, _), value) in &start_tag.attributes { + attrs.insert(name.to_owned(), value.to_owned()); + } + result = Some(Packet::StreamStart(attrs)); self.root = Some(XMPPRoot::new(start_tag)); - result = Some(Packet::StreamStart); break }, Err(e) => { @@ -146,18 +141,23 @@ impl Encoder for XMPPCodec { fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { match item { - Packet::StreamStart => { - write!(dst, - "\n -\n", - NS_CLIENT, NS_STREAMS) - .map_err(|_| Error::from(ErrorKind::WriteZero)) + Packet::StreamStart(start_attrs) => { + let mut buf = String::new(); + write!(buf, "\n").unwrap(); + + println!("Encode start to {}", buf); + write!(dst, "{}", buf) }, Packet::Stanza(stanza) => - write!(dst, "{}", stanza) - .map_err(|_| Error::from(ErrorKind::InvalidInput)), + write!(dst, "{}", stanza), // TODO: Implement all _ => Ok(()) } + .map_err(|_| Error::from(ErrorKind::InvalidInput)) } } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs new file mode 100644 index 0000000000000000000000000000000000000000..c4080bb7a36bd428b6d7e04af287088be482a7dc --- /dev/null +++ b/src/xmpp_stream.rs @@ -0,0 +1,62 @@ +use std::sync::Arc; +use std::collections::HashMap; +use futures::*; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_io::codec::Framed; +use rustls::ClientConfig; +use xml; + +use xmpp_codec::*; +use stream_start::*; +use starttls::{NS_XMPP_TLS, StartTlsClient}; + +pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; + +pub struct XMPPStream { + pub stream: Framed, + pub stream_attrs: HashMap, + pub stream_features: xml::Element, +} + +impl XMPPStream { + pub fn from_stream(stream: S, to: String) -> StreamStart { + let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new()); + StreamStart::from_stream(xmpp_stream, to) + } + + pub fn into_inner(self) -> S { + self.stream.into_inner() + } + + pub fn can_starttls(&self) -> bool { + self.stream_features + .get_child("starttls", Some(NS_XMPP_TLS)) + .is_some() + } + + pub fn starttls(self, arc_config: Arc) -> StartTlsClient { + StartTlsClient::from_stream(self, arc_config) + } +} + +impl Sink for XMPPStream { + type SinkItem = as Sink>::SinkItem; + type SinkError = as Sink>::SinkError; + + fn start_send(&mut self, item: Self::SinkItem) -> StartSend { + self.stream.start_send(item) + } + + fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { + self.stream.poll_complete() + } +} + +impl Stream for XMPPStream { + type Item = as Stream>::Item; + type Error = as Stream>::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + self.stream.poll() + } +} From f8de49569f0433f25963ac2bfc5e235d6447853a Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 6 Jun 2017 01:29:20 +0200 Subject: [PATCH 010/135] add client_auth using sasl --- Cargo.toml | 2 + examples/echo_bot.rs | 5 +- src/client_auth.rs | 160 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 ++ src/xmpp_stream.rs | 12 ++++ 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/client_auth.rs diff --git a/Cargo.toml b/Cargo.toml index 39de218681051fa316f44d867e007f7f5fad8306..5da50ccad8d58aff1c6af27d9a15c0a591d791e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,5 @@ bytes = "*" RustyXML = "*" rustls = "*" tokio-rustls = "*" +sasl = "*" +rustc-serialize = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 0cdd6b07e5c9dc8a4f460d22510daac81577cefc..416e98d599646043772105717b7a045a6da8e8c8 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -33,6 +33,9 @@ fn main() { } else { panic!("No STARTTLS") } + }).map_err(|e| format!("{}", e) + ).and_then(|stream| { + stream.auth("astrobot", "").expect("auth") }).and_then(|stream| { stream.for_each(|event| { match event { @@ -40,7 +43,7 @@ fn main() { _ => println!("!! {:?}", event), } Ok(()) - }) + }).map_err(|e| format!("{}", e)) }); match core.run(client) { Ok(_) => (), diff --git a/src/client_auth.rs b/src/client_auth.rs new file mode 100644 index 0000000000000000000000000000000000000000..ecb0b78f1b84d0dd1835a8be0064f0cb449ae002 --- /dev/null +++ b/src/client_auth.rs @@ -0,0 +1,160 @@ +use std::mem::replace; +use futures::*; +use futures::sink; +use tokio_io::{AsyncRead, AsyncWrite}; +use xml; +use sasl::common::Credentials; +use sasl::common::scram::*; +use sasl::client::Mechanism; +use sasl::client::mechanisms::*; +use serialize::base64::{self, ToBase64, FromBase64}; + +use xmpp_codec::*; +use xmpp_stream::*; + +const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; + +pub struct ClientAuth { + state: ClientAuthState, + mechanism: Box, +} + +enum ClientAuthState { + WaitSend(sink::Send>), + WaitRecv(XMPPStream), + Invalid, +} + +impl ClientAuth { + pub fn new(stream: XMPPStream, creds: Credentials) -> Result { + let mechs: Vec> = vec![ + Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + Box::new(Plain::from_credentials(creds).unwrap()), + Box::new(Anonymous::new()), + ]; + + println!("stream_features: {}", stream.stream_features); + let mech_names: Vec = + match stream.stream_features.get_child("mechanisms", Some(NS_XMPP_SASL)) { + None => + return Err("No auth mechanisms".to_owned()), + Some(mechs) => + mechs.get_children("mechanism", Some(NS_XMPP_SASL)) + .map(|mech_el| mech_el.content_str()) + .collect(), + }; + println!("Offered mechanisms: {:?}", mech_names); + + for mut mech in mechs { + let name = mech.name().to_owned(); + if mech_names.iter().any(|name1| *name1 == name) { + println!("Selected mechanism: {:?}", name); + let initial = try!(mech.initial()); + let mut this = ClientAuth { + state: ClientAuthState::Invalid, + mechanism: mech, + }; + this.send( + stream, + "auth", &[("mechanism".to_owned(), name)], + &initial + ); + return Ok(this); + } + } + + Err("No supported SASL mechanism available".to_owned()) + } + + fn send(&mut self, stream: XMPPStream, nonza_name: &str, attrs: &[(String, String)], content: &[u8]) { + let mut nonza = xml::Element::new( + nonza_name.to_owned(), + Some(NS_XMPP_SASL.to_owned()), + attrs.iter() + .map(|&(ref name, ref value)| (name.clone(), None, value.clone())) + .collect() + ); + nonza.text(content.to_base64(base64::URL_SAFE)); + + println!("send {}", nonza); + let send = stream.send(Packet::Stanza(nonza)); + + self.state = ClientAuthState::WaitSend(send); + } +} + +impl Future for ClientAuth { + type Item = XMPPStream; + type Error = String; + + fn poll(&mut self) -> Poll { + let state = replace(&mut self.state, ClientAuthState::Invalid); + + match state { + ClientAuthState::WaitSend(mut send) => + match send.poll() { + Ok(Async::Ready(stream)) => { + println!("send done"); + self.state = ClientAuthState::WaitRecv(stream); + self.poll() + }, + Ok(Async::NotReady) => { + self.state = ClientAuthState::WaitSend(send); + Ok(Async::NotReady) + }, + Err(e) => + Err(format!("{}", e)), + }, + ClientAuthState::WaitRecv(mut stream) => + match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name == "challenge" + && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + { + let content = try!( + stanza.content_str() + .from_base64() + .map_err(|e| format!("{}", e)) + ); + let response = try!(self.mechanism.response(&content)); + self.send(stream, "response", &[], &response); + self.poll() + }, + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name == "success" + && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + Ok(Async::Ready(stream)), + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name == "failure" + && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + { + let mut e = None; + for child in &stanza.children { + match child { + &xml::Xml::ElementNode(ref child) => { + e = Some(child.name.clone()); + break + }, + _ => (), + } + } + let e = e.unwrap_or_else(|| "Authentication failure".to_owned()); + Err(e) + }, + Ok(Async::Ready(event)) => { + println!("ClientAuth ignore {:?}", event); + Ok(Async::NotReady) + }, + Ok(_) => { + self.state = ClientAuthState::WaitRecv(stream); + Ok(Async::NotReady) + }, + Err(e) => + Err(format!("{}", e)), + }, + ClientAuthState::Invalid => + unreachable!(), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 9764daeae2d7f1418f58ee181e2ca36730136f20..ceb6842433ab5645986f1f34b65208e3d22aceea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ extern crate bytes; extern crate xml; extern crate rustls; extern crate tokio_rustls; +extern crate sasl; +extern crate rustc_serialize as serialize; pub mod xmpp_codec; @@ -15,6 +17,8 @@ mod tcp; pub use tcp::*; mod starttls; pub use starttls::*; +mod client_auth; +pub use client_auth::*; // type FullClient = sasl::Client> diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index c4080bb7a36bd428b6d7e04af287088be482a7dc..e480ffdb1df8b7def06028a23ab3913e03e56626 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,3 +1,4 @@ +use std::default::Default; use std::sync::Arc; use std::collections::HashMap; use futures::*; @@ -5,10 +6,12 @@ use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use rustls::ClientConfig; use xml; +use sasl::common::Credentials; use xmpp_codec::*; use stream_start::*; use starttls::{NS_XMPP_TLS, StartTlsClient}; +use client_auth::ClientAuth; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -37,8 +40,16 @@ impl XMPPStream { pub fn starttls(self, arc_config: Arc) -> StartTlsClient { StartTlsClient::from_stream(self, arc_config) } + + pub fn auth(self, username: &str, password: &str) -> Result, String> { + let creds = Credentials::default() + .with_username(username) + .with_password(password); + ClientAuth::new(self, creds) + } } +/// Proxy to self.stream impl Sink for XMPPStream { type SinkItem = as Sink>::SinkItem; type SinkError = as Sink>::SinkError; @@ -52,6 +63,7 @@ impl Sink for XMPPStream { } } +/// Proxy to self.stream impl Stream for XMPPStream { type Item = as Stream>::Item; type Error = as Stream>::Error; From 52c60229e33a82b85ba345e564c3855c08c2ccb5 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 6 Jun 2017 01:38:48 +0200 Subject: [PATCH 011/135] client_auth: add stream restart --- src/client_auth.rs | 19 ++++++++++++++++++- src/xmpp_stream.rs | 7 +++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/client_auth.rs b/src/client_auth.rs index ecb0b78f1b84d0dd1835a8be0064f0cb449ae002..5ae57b76c9f9d2b2926292febad2c461b0a8c1a9 100644 --- a/src/client_auth.rs +++ b/src/client_auth.rs @@ -11,6 +11,7 @@ use serialize::base64::{self, ToBase64, FromBase64}; use xmpp_codec::*; use xmpp_stream::*; +use stream_start::*; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; @@ -22,6 +23,7 @@ pub struct ClientAuth { enum ClientAuthState { WaitSend(sink::Send>), WaitRecv(XMPPStream), + Start(StreamStart), Invalid, } @@ -124,7 +126,11 @@ impl Future for ClientAuth { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) if stanza.name == "success" && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => - Ok(Async::Ready(stream)), + { + let start = stream.restart(); + self.state = ClientAuthState::Start(start); + self.poll() + }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) if stanza.name == "failure" && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => @@ -153,6 +159,17 @@ impl Future for ClientAuth { Err(e) => Err(format!("{}", e)), }, + ClientAuthState::Start(mut start) => + match start.poll() { + Ok(Async::Ready(stream)) => + Ok(Async::Ready(stream)), + Ok(Async::NotReady) => { + self.state = ClientAuthState::Start(start); + Ok(Async::NotReady) + }, + Err(e) => + Err(format!("{}", e)), + }, ClientAuthState::Invalid => unreachable!(), } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index e480ffdb1df8b7def06028a23ab3913e03e56626..56c778c4777f2744add2f36cf972e3fa3b3ead72 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -31,6 +31,13 @@ impl XMPPStream { self.stream.into_inner() } + pub fn restart(self) -> StreamStart { + let to = self.stream_attrs.get("from") + .map(|s| s.to_owned()) + .unwrap_or_else(|| "".to_owned()); + Self::from_stream(self.into_inner(), to.clone()) + } + pub fn can_starttls(&self) -> bool { self.stream_features .get_child("starttls", Some(NS_XMPP_TLS)) From 0bae1ce3366dc0f1e1dc1a8956df8775bcee5fb1 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 6 Jun 2017 02:03:38 +0200 Subject: [PATCH 012/135] switch from rustls to native-tls --- Cargo.toml | 4 ++-- examples/echo_bot.rs | 16 +++------------- src/lib.rs | 4 ++-- src/starttls.rs | 36 ++++++++++++++++++++---------------- src/xmpp_stream.rs | 6 ++---- 5 files changed, 29 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5da50ccad8d58aff1c6af27d9a15c0a591d791e7..82c0ea9b74c7de518789bbd72e4c590ed4e02169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ tokio-core = "*" tokio-io = "*" bytes = "*" RustyXML = "*" -rustls = "*" -tokio-rustls = "*" +native-tls = "*" +tokio-tls = "*" sasl = "*" rustc-serialize = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 416e98d599646043772105717b7a045a6da8e8c8..9dfe1556b86690402aeeca1d0201a659b36c575d 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,16 +1,11 @@ extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; -extern crate rustls; -use std::sync::Arc; -use std::io::BufReader; -use std::fs::File; use tokio_core::reactor::Core; use futures::{Future, Stream}; use tokio_xmpp::TcpClient; use tokio_xmpp::xmpp_codec::Packet; -use rustls::ClientConfig; fn main() { use std::net::ToSocketAddrs; @@ -18,23 +13,18 @@ fn main() { .to_socket_addrs().unwrap() .next().unwrap(); - let mut config = ClientConfig::new(); - let mut certfile = BufReader::new(File::open("/usr/share/ca-certificates/CAcert/root.crt").unwrap()); - config.root_store.add_pem_file(&mut certfile).unwrap(); - let arc_config = Arc::new(config); - let mut core = Core::new().unwrap(); let client = TcpClient::connect( &addr, &core.handle() + ).map_err(|e| format!("{}", e) ).and_then(|stream| { if stream.can_starttls() { - stream.starttls(arc_config) + stream.starttls() } else { panic!("No STARTTLS") } - }).map_err(|e| format!("{}", e) - ).and_then(|stream| { + }).and_then(|stream| { stream.auth("astrobot", "").expect("auth") }).and_then(|stream| { stream.for_each(|event| { diff --git a/src/lib.rs b/src/lib.rs index ceb6842433ab5645986f1f34b65208e3d22aceea..6a402c366b22db62ceab465256310623dda657ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,8 @@ extern crate tokio_core; extern crate tokio_io; extern crate bytes; extern crate xml; -extern crate rustls; -extern crate tokio_rustls; +extern crate native_tls; +extern crate tokio_tls; extern crate sasl; extern crate rustc_serialize as serialize; diff --git a/src/starttls.rs b/src/starttls.rs index b0fdc92f16c6807d8159e4e8baac7e92d8310719..c893f0597bdd45c4d667366021f7f29fd9e926a9 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -1,12 +1,10 @@ use std::mem::replace; -use std::io::Error; -use std::sync::Arc; use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; -use rustls::*; -use tokio_rustls::*; +use tokio_tls::*; +use native_tls::TlsConnector; use xml; use xmpp_codec::*; @@ -18,7 +16,7 @@ pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; pub struct StartTlsClient { state: StartTlsClientState, - arc_config: Arc, + domain: String, } enum StartTlsClientState { @@ -26,12 +24,16 @@ enum StartTlsClientState { SendStartTls(sink::Send>), AwaitProceed(XMPPStream), StartingTls(ConnectAsync), - Start(StreamStart>), + Start(StreamStart>), } impl StartTlsClient { /// Waits for - pub fn from_stream(xmpp_stream: XMPPStream, arc_config: Arc) -> Self { + pub fn from_stream(xmpp_stream: XMPPStream) -> Self { + let domain = xmpp_stream.stream_attrs.get("from") + .map(|s| s.to_owned()) + .unwrap_or_else(|| String::new()); + let nonza = xml::Element::new( "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), vec![] @@ -42,14 +44,14 @@ impl StartTlsClient { StartTlsClient { state: StartTlsClientState::SendStartTls(send), - arc_config: arc_config, + domain, } } } impl Future for StartTlsClient { - type Item = XMPPStream>; - type Error = Error; + type Item = XMPPStream>; + type Error = String; fn poll(&mut self) -> Poll { let old_state = replace(&mut self.state, StartTlsClientState::Invalid); @@ -67,7 +69,7 @@ impl Future for StartTlsClient { Ok(Async::NotReady) => (StartTlsClientState::SendStartTls(send), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::SendStartTls(send), Err(e)), + (StartTlsClientState::SendStartTls(send), Err(format!("{}", e))), }, StartTlsClientState::AwaitProceed(mut xmpp_stream) => match xmpp_stream.poll() { @@ -76,7 +78,9 @@ impl Future for StartTlsClient { { println!("* proceed *"); let stream = xmpp_stream.into_inner(); - let connect = self.arc_config.connect_async("spaceboyz.net", stream); + let connect = TlsConnector::builder().unwrap() + .build().unwrap() + .connect_async(&self.domain, stream); let new_state = StartTlsClientState::StartingTls(connect); retry = true; (new_state, Ok(Async::NotReady)) @@ -88,13 +92,13 @@ impl Future for StartTlsClient { Ok(_) => (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::AwaitProceed(xmpp_stream), Err(e)), + (StartTlsClientState::AwaitProceed(xmpp_stream), Err(format!("{}", e))), }, StartTlsClientState::StartingTls(mut connect) => match connect.poll() { Ok(Async::Ready(tls_stream)) => { println!("Got a TLS stream!"); - let start = XMPPStream::from_stream(tls_stream, "spaceboyz.net".to_owned()); + let start = XMPPStream::from_stream(tls_stream, self.domain.clone()); let new_state = StartTlsClientState::Start(start); retry = true; (new_state, Ok(Async::NotReady)) @@ -102,7 +106,7 @@ impl Future for StartTlsClient { Ok(Async::NotReady) => (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::StartingTls(connect), Err(e)), + (StartTlsClientState::StartingTls(connect), Err(format!("{}", e))), }, StartTlsClientState::Start(mut start) => match start.poll() { @@ -111,7 +115,7 @@ impl Future for StartTlsClient { Ok(Async::NotReady) => (StartTlsClientState::Start(start), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::Invalid, Err(e)), + (StartTlsClientState::Invalid, Err(format!("{}", e))), }, StartTlsClientState::Invalid => unreachable!(), diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 56c778c4777f2744add2f36cf972e3fa3b3ead72..a8793db1f59f045dfb201643519c1c28bf5c347d 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,10 +1,8 @@ use std::default::Default; -use std::sync::Arc; use std::collections::HashMap; use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; -use rustls::ClientConfig; use xml; use sasl::common::Credentials; @@ -44,8 +42,8 @@ impl XMPPStream { .is_some() } - pub fn starttls(self, arc_config: Arc) -> StartTlsClient { - StartTlsClient::from_stream(self, arc_config) + pub fn starttls(self) -> StartTlsClient { + StartTlsClient::from_stream(self) } pub fn auth(self, username: &str, password: &str) -> Result, String> { From 1d9790a1d8a761f2305f49783ebe9e364bb3c32e Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 13 Jun 2017 23:52:41 +0200 Subject: [PATCH 013/135] stream_start: fix style --- src/stream_start.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stream_start.rs b/src/stream_start.rs index 480178eb58588e4959c6b60389c0328c47eec290..3e5bc8b2f9eb971932f6f2806a1e13763d5e2bd9 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -75,7 +75,7 @@ impl Future for StreamStart { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => if stanza.name == "features" && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) { - (StreamStartState::Invalid, Ok(Async::Ready(XMPPStream { stream, stream_attrs, stream_features: stanza }))) + (StreamStartState::Invalid, Ok(Async::Ready(XMPPStream::new(stream, stream_attrs, stanza)))) } else { (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) }, From df423e50478e022f3342e2f7e6c661e5fac661c6 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 14 Jun 2017 01:55:56 +0200 Subject: [PATCH 014/135] use jid --- Cargo.toml | 1 + examples/echo_bot.rs | 10 +++++++++- src/lib.rs | 1 + src/starttls.rs | 15 +++++++-------- src/stream_start.rs | 10 +++++++--- src/tcp.rs | 7 +++++-- src/xmpp_stream.rs | 20 +++++++++++++------- 7 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 82c0ea9b74c7de518789bbd72e4c590ed4e02169..12e818a70061ce8dffe43d691054bcd8a9589708 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ native-tls = "*" tokio-tls = "*" sasl = "*" rustc-serialize = "*" +jid = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 9dfe1556b86690402aeeca1d0201a659b36c575d..4f5f044730e978bb5251bae94156eab20abc1db6 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,13 +1,19 @@ extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; +extern crate jid; +use std::str::FromStr; use tokio_core::reactor::Core; use futures::{Future, Stream}; use tokio_xmpp::TcpClient; use tokio_xmpp::xmpp_codec::Packet; +use jid::Jid; fn main() { + let jid = Jid::from_str("astrobot@example.net").expect("JID"); + let password = "".to_owned(); + use std::net::ToSocketAddrs; let addr = "[2a01:4f8:a0:33d0::5]:5222" .to_socket_addrs().unwrap() @@ -15,6 +21,7 @@ fn main() { let mut core = Core::new().unwrap(); let client = TcpClient::connect( + jid.clone(), &addr, &core.handle() ).map_err(|e| format!("{}", e) @@ -25,7 +32,8 @@ fn main() { panic!("No STARTTLS") } }).and_then(|stream| { - stream.auth("astrobot", "").expect("auth") + let username = jid.node.as_ref().unwrap().to_owned(); + stream.auth(username, password).expect("auth") }).and_then(|stream| { stream.for_each(|event| { match event { diff --git a/src/lib.rs b/src/lib.rs index 6a402c366b22db62ceab465256310623dda657ea..e04778ac5134c090a8f38a3fc42b79cee879cd44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ extern crate native_tls; extern crate tokio_tls; extern crate sasl; extern crate rustc_serialize as serialize; +extern crate jid; pub mod xmpp_codec; diff --git a/src/starttls.rs b/src/starttls.rs index c893f0597bdd45c4d667366021f7f29fd9e926a9..2e7da7bc92bdbb8db945aaa105f4d7eedd1fb09d 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -6,6 +6,7 @@ use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::*; use native_tls::TlsConnector; use xml; +use jid::Jid; use xmpp_codec::*; use xmpp_stream::*; @@ -16,7 +17,7 @@ pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; pub struct StartTlsClient { state: StartTlsClientState, - domain: String, + jid: Jid, } enum StartTlsClientState { @@ -30,9 +31,7 @@ enum StartTlsClientState { impl StartTlsClient { /// Waits for pub fn from_stream(xmpp_stream: XMPPStream) -> Self { - let domain = xmpp_stream.stream_attrs.get("from") - .map(|s| s.to_owned()) - .unwrap_or_else(|| String::new()); + let jid = xmpp_stream.jid.clone(); let nonza = xml::Element::new( "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), @@ -44,7 +43,7 @@ impl StartTlsClient { StartTlsClient { state: StartTlsClientState::SendStartTls(send), - domain, + jid, } } } @@ -77,10 +76,10 @@ impl Future for StartTlsClient { if stanza.name == "proceed" => { println!("* proceed *"); - let stream = xmpp_stream.into_inner(); + let stream = xmpp_stream.stream.into_inner(); let connect = TlsConnector::builder().unwrap() .build().unwrap() - .connect_async(&self.domain, stream); + .connect_async(&self.jid.domain, stream); let new_state = StartTlsClientState::StartingTls(connect); retry = true; (new_state, Ok(Async::NotReady)) @@ -98,7 +97,7 @@ impl Future for StartTlsClient { match connect.poll() { Ok(Async::Ready(tls_stream)) => { println!("Got a TLS stream!"); - let start = XMPPStream::from_stream(tls_stream, self.domain.clone()); + let start = XMPPStream::from_stream(tls_stream, self.jid.clone()); let new_state = StartTlsClientState::Start(start); retry = true; (new_state, Ok(Async::NotReady)) diff --git a/src/stream_start.rs b/src/stream_start.rs index 3e5bc8b2f9eb971932f6f2806a1e13763d5e2bd9..11b074e6c7cb119c186b6211ab4961cecf936a5e 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; +use jid::Jid; use xmpp_codec::*; use xmpp_stream::*; @@ -12,6 +13,7 @@ const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; pub struct StreamStart { state: StreamStartState, + jid: Jid, } enum StreamStartState { @@ -22,8 +24,8 @@ enum StreamStartState { } impl StreamStart { - pub fn from_stream(stream: Framed, to: String) -> Self { - let attrs = [("to".to_owned(), to), + pub fn from_stream(stream: Framed, jid: Jid) -> Self { + let attrs = [("to".to_owned(), jid.domain.clone()), ("version".to_owned(), "1.0".to_owned()), ("xmlns".to_owned(), "jabber:client".to_owned()), ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), @@ -32,6 +34,7 @@ impl StreamStart { StreamStart { state: StreamStartState::SendStart(send), + jid, } } } @@ -75,7 +78,8 @@ impl Future for StreamStart { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => if stanza.name == "features" && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) { - (StreamStartState::Invalid, Ok(Async::Ready(XMPPStream::new(stream, stream_attrs, stanza)))) + let stream = XMPPStream::new(self.jid.clone(), stream, stream_attrs, stanza); + (StreamStartState::Invalid, Ok(Async::Ready(stream))) } else { (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) }, diff --git a/src/tcp.rs b/src/tcp.rs index 57fb0b1fe28d34368d56c268b0814e26a0af3796..4510a39e2917e6ffc2c53aabc885f88025b058e8 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -3,12 +3,14 @@ use std::io::Error; use futures::{Future, Poll, Async}; use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; +use jid::Jid; use xmpp_stream::*; use stream_start::StreamStart; pub struct TcpClient { state: TcpClientState, + jid: Jid, } enum TcpClientState { @@ -18,10 +20,11 @@ enum TcpClientState { } impl TcpClient { - pub fn connect(addr: &SocketAddr, handle: &Handle) -> Self { + pub fn connect(jid: Jid, addr: &SocketAddr, handle: &Handle) -> Self { let tcp_stream_new = TcpStream::connect(addr, handle); TcpClient { state: TcpClientState::Connecting(tcp_stream_new), + jid, } } } @@ -34,7 +37,7 @@ impl Future for TcpClient { let (new_state, result) = match self.state { TcpClientState::Connecting(ref mut tcp_stream_new) => { let tcp_stream = try_ready!(tcp_stream_new.poll()); - let start = XMPPStream::from_stream(tcp_stream, "spaceboyz.net".to_owned()); + let start = XMPPStream::from_stream(tcp_stream, self.jid.clone()); let new_state = TcpClientState::Start(start); (new_state, Ok(Async::NotReady)) }, diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index a8793db1f59f045dfb201643519c1c28bf5c347d..2b8f0981d202e65c9c2dcb828f4def30797ab95d 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -5,6 +5,7 @@ use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use xml; use sasl::common::Credentials; +use jid::Jid; use xmpp_codec::*; use stream_start::*; @@ -14,15 +15,23 @@ use client_auth::ClientAuth; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; pub struct XMPPStream { + pub jid: Jid, pub stream: Framed, pub stream_attrs: HashMap, pub stream_features: xml::Element, } impl XMPPStream { - pub fn from_stream(stream: S, to: String) -> StreamStart { + pub fn new(jid: Jid, + stream: Framed, + stream_attrs: HashMap, + stream_features: xml::Element) -> Self { + XMPPStream { jid, stream, stream_attrs, stream_features } + } + + pub fn from_stream(stream: S, jid: Jid) -> StreamStart { let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new()); - StreamStart::from_stream(xmpp_stream, to) + StreamStart::from_stream(xmpp_stream, jid) } pub fn into_inner(self) -> S { @@ -30,10 +39,7 @@ impl XMPPStream { } pub fn restart(self) -> StreamStart { - let to = self.stream_attrs.get("from") - .map(|s| s.to_owned()) - .unwrap_or_else(|| "".to_owned()); - Self::from_stream(self.into_inner(), to.clone()) + Self::from_stream(self.stream.into_inner(), self.jid) } pub fn can_starttls(&self) -> bool { @@ -46,7 +52,7 @@ impl XMPPStream { StartTlsClient::from_stream(self) } - pub fn auth(self, username: &str, password: &str) -> Result, String> { + pub fn auth(self, username: String, password: String) -> Result, String> { let creds = Credentials::default() .with_username(username) .with_password(password); From 973a5ca659848118f6aae9148a77b1a58e303492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Sat, 17 Jun 2017 01:23:38 +0100 Subject: [PATCH 015/135] Force channel binding to None --- src/tcp.rs | 10 +++++----- src/xmpp_stream.rs | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/tcp.rs b/src/tcp.rs index 4510a39e2917e6ffc2c53aabc885f88025b058e8..2f207ec513a00998dea4e03745fb28a6c7172a5e 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -51,10 +51,10 @@ impl Future for TcpClient { }; self.state = new_state; - match result { - // by polling again, we register new future - Ok(Async::NotReady) => self.poll(), - result => result - } + match result { + // by polling again, we register new future + Ok(Async::NotReady) => self.poll(), + result => result + } } } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 2b8f0981d202e65c9c2dcb828f4def30797ab95d..c84777f024cee98eb2e049b68b44a2216d0a0d68 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -4,7 +4,7 @@ use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use xml; -use sasl::common::Credentials; +use sasl::common::{Credentials, ChannelBinding}; use jid::Jid; use xmpp_codec::*; @@ -55,7 +55,8 @@ impl XMPPStream { pub fn auth(self, username: String, password: String) -> Result, String> { let creds = Credentials::default() .with_username(username) - .with_password(password); + .with_password(password) + .with_channel_binding(ChannelBinding::None); ClientAuth::new(self, creds) } } From 014633d119e523bae098da7ca688d27da1b8b905 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 19 Jun 2017 02:16:47 +0200 Subject: [PATCH 016/135] add client_bind --- examples/echo_bot.rs | 3 + src/client_bind.rs | 138 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/xmpp_stream.rs | 5 ++ 4 files changed, 148 insertions(+) create mode 100644 src/client_bind.rs diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 4f5f044730e978bb5251bae94156eab20abc1db6..df33cf0a5985262447bc428f4095fef397e4a2d4 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -35,6 +35,9 @@ fn main() { let username = jid.node.as_ref().unwrap().to_owned(); stream.auth(username, password).expect("auth") }).and_then(|stream| { + stream.bind() + }).and_then(|stream| { + println!("Bound to {}", stream.jid); stream.for_each(|event| { match event { Packet::Stanza(el) => println!("<< {}", el), diff --git a/src/client_bind.rs b/src/client_bind.rs new file mode 100644 index 0000000000000000000000000000000000000000..24238f63bc50b2d5f1a6452fbadb0f0d76e1e0f3 --- /dev/null +++ b/src/client_bind.rs @@ -0,0 +1,138 @@ +use std::mem::replace; +use std::error::Error; +use std::str::FromStr; +use futures::*; +use futures::sink; +use tokio_io::{AsyncRead, AsyncWrite}; +use xml; +use jid::Jid; + +use xmpp_codec::*; +use xmpp_stream::*; + +const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind"; +const BIND_REQ_ID: &str = "resource-bind"; + +pub enum ClientBind { + Unsupported(XMPPStream), + WaitSend(sink::Send>), + WaitRecv(XMPPStream), + Invalid, +} + +impl ClientBind { + /// Consumes and returns the stream to express that you cannot use + /// the stream for anything else until the resource binding + /// req/resp are done. + pub fn new(stream: XMPPStream) -> Self { + match stream.stream_features.get_child("bind", Some(NS_XMPP_BIND)) { + None => + // No resource binding available, + // return the (probably // usable) stream immediately + ClientBind::Unsupported(stream), + Some(_) => { + println!("Bind is supported!"); + + let iq = make_bind_request(stream.jid.resource.as_ref()); + println!("Send {}", iq); + let send = stream.send(Packet::Stanza(iq)); + ClientBind::WaitSend(send) + }, + } + } +} + +fn make_bind_request(resource: Option<&String>) -> xml::Element { + let mut iq = xml::Element::new( + "iq".to_owned(), + None, + vec![("type".to_owned(), None, "set".to_owned()), + ("id".to_owned(), None, BIND_REQ_ID.to_owned())] + ); + { + let bind_el = iq.tag( + xml::Element::new( + "bind".to_owned(), + Some(NS_XMPP_BIND.to_owned()), + vec![] + )); + resource.map(|resource| { + let resource_el = bind_el.tag( + xml::Element::new( + "resource".to_owned(), + Some(NS_XMPP_BIND.to_owned()), + vec![] + )); + resource_el.text(resource.clone()); + }); + } + iq +} + +impl Future for ClientBind { + type Item = XMPPStream; + type Error = String; + + fn poll(&mut self) -> Poll { + let state = replace(self, ClientBind::Invalid); + + match state { + ClientBind::Unsupported(stream) => + Ok(Async::Ready(stream)), + ClientBind::WaitSend(mut send) => { + match send.poll() { + Ok(Async::Ready(stream)) => { + replace(self, ClientBind::WaitRecv(stream)); + self.poll() + }, + Ok(Async::NotReady) => { + replace(self, ClientBind::WaitSend(send)); + Ok(Async::NotReady) + }, + Err(e) => + Err(e.description().to_owned()), + } + }, + ClientBind::WaitRecv(mut stream) => { + match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref iq)))) + if iq.name == "iq" + && iq.get_attribute("id", None) == Some(BIND_REQ_ID) => { + match iq.get_attribute("type", None) { + Some("result") => { + get_bind_response_jid(&iq) + .map(|jid| stream.jid = jid); + Ok(Async::Ready(stream)) + }, + _ => + Err("resource bind response".to_owned()), + } + }, + Ok(Async::Ready(_)) => { + replace(self, ClientBind::WaitRecv(stream)); + self.poll() + }, + Ok(_) => { + replace(self, ClientBind::WaitRecv(stream)); + Ok(Async::NotReady) + }, + Err(e) => + Err(e.description().to_owned()), + } + }, + ClientBind::Invalid => + unreachable!(), + } + } +} + +fn get_bind_response_jid(iq: &xml::Element) -> Option { + iq.get_child("bind", Some(NS_XMPP_BIND)) + .and_then(|bind_el| + bind_el.get_child("jid", Some(NS_XMPP_BIND)) + ) + .and_then(|jid_el| + Jid::from_str(&jid_el.content_str()) + .ok() + ) +} diff --git a/src/lib.rs b/src/lib.rs index e04778ac5134c090a8f38a3fc42b79cee879cd44..12b710e171ca4de85274f96fb2f5d618bca82986 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,8 @@ mod starttls; pub use starttls::*; mod client_auth; pub use client_auth::*; +mod client_bind; +pub use client_bind::*; // type FullClient = sasl::Client> diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index c84777f024cee98eb2e049b68b44a2216d0a0d68..6eb2b24d7c7bd98d8d45727797771c3c425654e2 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -11,6 +11,7 @@ use xmpp_codec::*; use stream_start::*; use starttls::{NS_XMPP_TLS, StartTlsClient}; use client_auth::ClientAuth; +use client_bind::ClientBind; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -59,6 +60,10 @@ impl XMPPStream { .with_channel_binding(ChannelBinding::None); ClientAuth::new(self, creds) } + + pub fn bind(self) -> ClientBind { + ClientBind::new(self) + } } /// Proxy to self.stream From 2e0dff5153e4d3f2edfb31572bbcdd123092b37f Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 19 Jun 2017 02:17:06 +0200 Subject: [PATCH 017/135] xmpp_codec: add Packet::Text --- src/xmpp_codec.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 8595dfca21e47aaff03557e1d9770e5f4f0b726a..b780a4800508371a233138467c34c5e8420e8c71 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -50,6 +50,7 @@ pub enum Packet { Error(Box), StreamStart(HashMap), Stanza(xml::Element), + Text(String), StreamEnd, } @@ -155,6 +156,8 @@ impl Encoder for XMPPCodec { }, Packet::Stanza(stanza) => write!(dst, "{}", stanza), + Packet::Text(text) => + write!(dst, "{}", xml::escape(&text)), // TODO: Implement all _ => Ok(()) } From 8b7a49d03a7e4f0f940af0de515e35146c5a36c9 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 19 Jun 2017 02:33:01 +0200 Subject: [PATCH 018/135] client_bind: tighten match this branch is specific to Async::NotReady --- src/client_bind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client_bind.rs b/src/client_bind.rs index 24238f63bc50b2d5f1a6452fbadb0f0d76e1e0f3..ac85a9c9b10e31ba7257b284189110703da25486 100644 --- a/src/client_bind.rs +++ b/src/client_bind.rs @@ -112,7 +112,7 @@ impl Future for ClientBind { replace(self, ClientBind::WaitRecv(stream)); self.poll() }, - Ok(_) => { + Ok(Async::NotReady) => { replace(self, ClientBind::WaitRecv(stream)); Ok(Async::NotReady) }, From 000f848dd0f91dcd728b0992876e7ab461254302 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 19 Jun 2017 02:34:16 +0200 Subject: [PATCH 019/135] consolidate debug output --- src/client_auth.rs | 7 ++----- src/client_bind.rs | 3 --- src/starttls.rs | 5 +---- src/xmpp_codec.rs | 27 +++++++++++++++++---------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/client_auth.rs b/src/client_auth.rs index 5ae57b76c9f9d2b2926292febad2c461b0a8c1a9..c6aa79d67975e09a4aedc2f76b9a3fe5a5ac3f06 100644 --- a/src/client_auth.rs +++ b/src/client_auth.rs @@ -36,7 +36,6 @@ impl ClientAuth { Box::new(Anonymous::new()), ]; - println!("stream_features: {}", stream.stream_features); let mech_names: Vec = match stream.stream_features.get_child("mechanisms", Some(NS_XMPP_SASL)) { None => @@ -46,12 +45,12 @@ impl ClientAuth { .map(|mech_el| mech_el.content_str()) .collect(), }; - println!("Offered mechanisms: {:?}", mech_names); + println!("SASL mechanisms offered: {:?}", mech_names); for mut mech in mechs { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { - println!("Selected mechanism: {:?}", name); + println!("SASL mechanism selected: {:?}", name); let initial = try!(mech.initial()); let mut this = ClientAuth { state: ClientAuthState::Invalid, @@ -79,7 +78,6 @@ impl ClientAuth { ); nonza.text(content.to_base64(base64::URL_SAFE)); - println!("send {}", nonza); let send = stream.send(Packet::Stanza(nonza)); self.state = ClientAuthState::WaitSend(send); @@ -97,7 +95,6 @@ impl Future for ClientAuth { ClientAuthState::WaitSend(mut send) => match send.poll() { Ok(Async::Ready(stream)) => { - println!("send done"); self.state = ClientAuthState::WaitRecv(stream); self.poll() }, diff --git a/src/client_bind.rs b/src/client_bind.rs index ac85a9c9b10e31ba7257b284189110703da25486..45f68e6f6f5a8ccf16b8c99dd01dd581c2f3990e 100644 --- a/src/client_bind.rs +++ b/src/client_bind.rs @@ -31,10 +31,7 @@ impl ClientBind { // return the (probably // usable) stream immediately ClientBind::Unsupported(stream), Some(_) => { - println!("Bind is supported!"); - let iq = make_bind_request(stream.jid.resource.as_ref()); - println!("Send {}", iq); let send = stream.send(Packet::Stanza(iq)); ClientBind::WaitSend(send) }, diff --git a/src/starttls.rs b/src/starttls.rs index 2e7da7bc92bdbb8db945aaa105f4d7eedd1fb09d..97a65c511509f0765ce69b209f96f0bb5547dc2c 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -37,7 +37,6 @@ impl StartTlsClient { "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), vec![] ); - println!("send {}", nonza); let packet = Packet::Stanza(nonza); let send = xmpp_stream.send(packet); @@ -60,7 +59,6 @@ impl Future for StartTlsClient { StartTlsClientState::SendStartTls(mut send) => match send.poll() { Ok(Async::Ready(xmpp_stream)) => { - println!("starttls sent"); let new_state = StartTlsClientState::AwaitProceed(xmpp_stream); retry = true; (new_state, Ok(Async::NotReady)) @@ -75,7 +73,6 @@ impl Future for StartTlsClient { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) if stanza.name == "proceed" => { - println!("* proceed *"); let stream = xmpp_stream.stream.into_inner(); let connect = TlsConnector::builder().unwrap() .build().unwrap() @@ -96,7 +93,7 @@ impl Future for StartTlsClient { StartTlsClientState::StartingTls(mut connect) => match connect.poll() { Ok(Async::Ready(tls_stream)) => { - println!("Got a TLS stream!"); + println!("TLS stream established"); let start = XMPPStream::from_stream(tls_stream, self.jid.clone()); let new_state = StartTlsClientState::Start(start); retry = true; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index b780a4800508371a233138467c34c5e8420e8c71..2551cc44fa13e8310ca066fe32e8397e668d465a 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -20,7 +20,6 @@ impl XMPPRoot { fn new(root: xml::StartTag) -> Self { let mut builder = xml::ElementBuilder::new(); let mut attributes = HashMap::new(); - println!("root attributes: {:?}", root.attributes); for (name_ns, value) in root.attributes { match name_ns { (ref name, None) if name == "xmlns" => @@ -73,10 +72,13 @@ impl Decoder for XMPPCodec { type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - println!("XMPPCodec.decode {:?}", buf.len()); match from_utf8(buf.take().as_ref()) { - Ok(s) => - self.parser.feed_str(s), + Ok(s) => { + if s.len() > 0 { + println!("<< {}", s); + self.parser.feed_str(s); + } + }, Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)), } @@ -110,7 +112,7 @@ impl Decoder for XMPPCodec { match root.handle_event(event) { None => (), Some(Ok(stanza)) => { - println!("stanza: {}", stanza); + // Emit the stanza result = Some(Packet::Stanza(stanza)); break }, @@ -151,13 +153,18 @@ impl Encoder for XMPPCodec { } write!(buf, ">\n").unwrap(); - println!("Encode start to {}", buf); + print!(">> {}", buf); write!(dst, "{}", buf) }, - Packet::Stanza(stanza) => - write!(dst, "{}", stanza), - Packet::Text(text) => - write!(dst, "{}", xml::escape(&text)), + Packet::Stanza(stanza) => { + println!(">> {}", stanza); + write!(dst, "{}", stanza) + }, + Packet::Text(text) => { + let escaped = xml::escape(&text); + println!(">> {}", escaped); + write!(dst, "{}", escaped) + }, // TODO: Implement all _ => Ok(()) } From 547902fe8f0172e9446944cdb4a9e1668d369449 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 19 Jun 2017 02:35:21 +0200 Subject: [PATCH 020/135] echo_bot: send presence --- examples/echo_bot.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index df33cf0a5985262447bc428f4095fef397e4a2d4..e9761c9338365fb8829e0277fe71b611b567cd77 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -2,13 +2,14 @@ extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; extern crate jid; +extern crate xml; use std::str::FromStr; use tokio_core::reactor::Core; -use futures::{Future, Stream}; +use futures::{Future, Stream, Sink}; +use jid::Jid; use tokio_xmpp::TcpClient; use tokio_xmpp::xmpp_codec::Packet; -use jid::Jid; fn main() { let jid = Jid::from_str("astrobot@example.net").expect("JID"); @@ -38,6 +39,11 @@ fn main() { stream.bind() }).and_then(|stream| { println!("Bound to {}", stream.jid); + + let presence = xml::Element::new("presence".to_owned(), None, vec![]); + stream.send(Packet::Stanza(presence)) + .map_err(|e| format!("{}", e)) + }).and_then(|stream| { stream.for_each(|event| { match event { Packet::Stanza(el) => println!("<< {}", el), From 1e2672ba5022c3ebe60b56471014f2ffe41a27fc Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 20 Jun 2017 21:26:51 +0200 Subject: [PATCH 021/135] impl stream for client --- examples/echo_bot.rs | 124 ++++++++++++------ src/{client_auth.rs => client/auth.rs} | 0 src/{client_bind.rs => client/bind.rs} | 0 src/client/mod.rs | 167 +++++++++++++++++++++++++ src/lib.rs | 6 +- src/starttls.rs | 1 + src/xmpp_stream.rs | 26 ---- 7 files changed, 254 insertions(+), 70 deletions(-) rename src/{client_auth.rs => client/auth.rs} (100%) rename src/{client_bind.rs => client/bind.rs} (100%) create mode 100644 src/client/mod.rs diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index e9761c9338365fb8829e0277fe71b611b567cd77..9f39dfe4e513f45f33ee88432fd6ef939fb369bb 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -6,53 +6,85 @@ extern crate xml; use std::str::FromStr; use tokio_core::reactor::Core; -use futures::{Future, Stream, Sink}; -use jid::Jid; -use tokio_xmpp::TcpClient; +use futures::{Future, Stream, Sink, future}; +use tokio_xmpp::{Client, ClientEvent}; use tokio_xmpp::xmpp_codec::Packet; fn main() { - let jid = Jid::from_str("astrobot@example.net").expect("JID"); - let password = "".to_owned(); + let mut core = Core::new().unwrap(); + let client = Client::new("astrobot@example.org", "", &core.handle()).unwrap(); + // let client = TcpClient::connect( + // jid.clone(), + // &addr, + // &core.handle() + // ).map_err(|e| format!("{}", e) + // ).and_then(|stream| { + // if stream.can_starttls() { + // stream.starttls() + // } else { + // panic!("No STARTTLS") + // } + // }).and_then(|stream| { + // let username = jid.node.as_ref().unwrap().to_owned(); + // stream.auth(username, password).expect("auth") + // }).and_then(|stream| { + // stream.bind() + // }).and_then(|stream| { + // println!("Bound to {}", stream.jid); - use std::net::ToSocketAddrs; - let addr = "[2a01:4f8:a0:33d0::5]:5222" - .to_socket_addrs().unwrap() - .next().unwrap(); + // let presence = xml::Element::new("presence".to_owned(), None, vec![]); + // stream.send(Packet::Stanza(presence)) + // .map_err(|e| format!("{}", e)) + // }).and_then(|stream| { + // let main_loop = |stream| { + // stream.into_future() + // .and_then(|(event, stream)| { + // stream.send(Packet::Stanza(unreachable!())) + // }).and_then(main_loop) + // }; + // main_loop(stream) + // }).and_then(|(event, stream)| { + // let (mut sink, stream) = stream.split(); + // stream.for_each(move |event| { + // match event { + // Packet::Stanza(ref message) + // if message.name == "message" => { + // let ty = message.get_attribute("type", None); + // let body = message.get_child("body", Some("jabber:client")) + // .map(|body_el| body_el.content_str()); + // match ty { + // None | Some("normal") | Some("chat") + // if body.is_some() => { + // let from = message.get_attribute("from", None).unwrap(); + // println!("Got message from {}: {:?}", from, body); + // let reply = make_reply(from, body.unwrap()); + // sink.send(Packet::Stanza(reply)) + // .and_then(|_| Ok(())) + // }, + // _ => future::ok(()), + // } + // }, + // _ => future::ok(()), + // } + // }).map_err(|e| format!("{}", e)) + // }); - let mut core = Core::new().unwrap(); - let client = TcpClient::connect( - jid.clone(), - &addr, - &core.handle() - ).map_err(|e| format!("{}", e) - ).and_then(|stream| { - if stream.can_starttls() { - stream.starttls() - } else { - panic!("No STARTTLS") + let done = client.for_each(|event| { + match event { + ClientEvent::Online => { + println!("Online!"); + }, + ClientEvent::Stanza(stanza) => { + }, + _ => { + println!("Event: {:?}", event); + }, } - }).and_then(|stream| { - let username = jid.node.as_ref().unwrap().to_owned(); - stream.auth(username, password).expect("auth") - }).and_then(|stream| { - stream.bind() - }).and_then(|stream| { - println!("Bound to {}", stream.jid); - - let presence = xml::Element::new("presence".to_owned(), None, vec![]); - stream.send(Packet::Stanza(presence)) - .map_err(|e| format!("{}", e)) - }).and_then(|stream| { - stream.for_each(|event| { - match event { - Packet::Stanza(el) => println!("<< {}", el), - _ => println!("!! {:?}", event), - } - Ok(()) - }).map_err(|e| format!("{}", e)) + + Ok(()) }); - match core.run(client) { + + match core.run(done) { Ok(_) => (), Err(e) => { println!("Fatal: {}", e); @@ -60,3 +92,15 @@ fn main() { } } } + +fn make_reply(to: &str, body: String) -> xml::Element { + let mut message = xml::Element::new( + "message".to_owned(), + None, + vec![("type".to_owned(), None, "chat".to_owned()), + ("to".to_owned(), None, to.to_owned())] + ); + message.tag(xml::Element::new("body".to_owned(), None, vec![])) + .text(body); + message +} diff --git a/src/client_auth.rs b/src/client/auth.rs similarity index 100% rename from src/client_auth.rs rename to src/client/auth.rs diff --git a/src/client_bind.rs b/src/client/bind.rs similarity index 100% rename from src/client_bind.rs rename to src/client/bind.rs diff --git a/src/client/mod.rs b/src/client/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..624bf7249df1f664e6024df9797fb557cc9559d4 --- /dev/null +++ b/src/client/mod.rs @@ -0,0 +1,167 @@ +use std::mem::replace; +use std::str::FromStr; +use std::error::Error; +use tokio_core::reactor::{Core, Handle}; +use tokio_core::net::TcpStream; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_tls::TlsStream; +use futures::*; +use jid::{Jid, JidParseError}; +use xml; +use sasl::common::{Credentials, ChannelBinding}; + +use super::xmpp_codec::Packet; +use super::xmpp_stream; +use super::tcp::TcpClient; +use super::starttls::{NS_XMPP_TLS, StartTlsClient}; + +mod auth; +use self::auth::*; +mod bind; +use self::bind::*; + +pub struct Client { + pub jid: Jid, + password: String, + state: ClientState, +} + +type XMPPStream = xmpp_stream::XMPPStream>; + +enum ClientState { + Invalid, + Disconnected, + Connecting(Box>), + Connected(XMPPStream), + // Sending, + // Drain, +} + +impl Client { + pub fn new(jid: &str, password: &str, handle: &Handle) -> Result { + let jid = try!(Jid::from_str(jid)); + let password = password.to_owned(); + let connect = Self::make_connect(jid.clone(), password.clone(), handle); + Ok(Client { + jid, password, + state: ClientState::Connecting(connect), + }) + } + + fn make_connect(jid: Jid, password: String, handle: &Handle) -> Box> { + use std::net::ToSocketAddrs; + let addr = "89.238.79.220:5222" + .to_socket_addrs().unwrap() + .next().unwrap(); + let username = jid.node.as_ref().unwrap().to_owned(); + let password = password; + Box::new( + TcpClient::connect( + jid, + &addr, + handle + ).map_err(|e| format!("{}", e) + ).and_then(|stream| { + if Self::can_starttls(&stream) { + Self::starttls(stream) + } else { + panic!("No STARTTLS") + } + }).and_then(move |stream| { + Self::auth(stream, username, password).expect("auth") + }).and_then(|stream| { + Self::bind(stream) + }).and_then(|stream| { + println!("Bound to {}", stream.jid); + + let presence = xml::Element::new("presence".to_owned(), None, vec![]); + stream.send(Packet::Stanza(presence)) + .map_err(|e| format!("{}", e)) + }) + ) + } + + fn can_starttls(stream: &xmpp_stream::XMPPStream) -> bool { + stream.stream_features + .get_child("starttls", Some(NS_XMPP_TLS)) + .is_some() + } + + fn starttls(stream: xmpp_stream::XMPPStream) -> StartTlsClient { + StartTlsClient::from_stream(stream) + } + + fn auth(stream: xmpp_stream::XMPPStream, username: String, password: String) -> Result, String> { + let creds = Credentials::default() + .with_username(username) + .with_password(password) + .with_channel_binding(ChannelBinding::None); + ClientAuth::new(stream, creds) + } + + fn bind(stream: xmpp_stream::XMPPStream) -> ClientBind { + ClientBind::new(stream) + } +} + +#[derive(Debug)] +pub enum ClientEvent { + Online, + Disconnected, + Stanza(xml::Element), +} + +impl Stream for Client { + type Item = ClientEvent; + type Error = String; + + fn poll(&mut self) -> Poll, Self::Error> { + println!("stream.poll"); + let state = replace(&mut self.state, ClientState::Invalid); + + match state { + ClientState::Invalid => + Err("invalid client state".to_owned()), + ClientState::Disconnected => + Ok(Async::NotReady), + ClientState::Connecting(mut connect) => { + match connect.poll() { + Ok(Async::Ready(stream)) => { + println!("connected"); + self.state = ClientState::Connected(stream); + self.poll() + }, + Ok(Async::NotReady) => { + self.state = ClientState::Connecting(connect); + Ok(Async::NotReady) + }, + Err(e) => + Err(e), + } + }, + ClientState::Connected(mut stream) => { + match stream.poll() { + Ok(Async::NotReady) => { + self.state = ClientState::Connected(stream); + Ok(Async::NotReady) + }, + Ok(Async::Ready(None)) => { + // EOF + self.state = ClientState::Disconnected; + Ok(Async::Ready(Some(ClientEvent::Disconnected))) + }, + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + self.state = ClientState::Connected(stream); + Ok(Async::Ready(Some(ClientEvent::Stanza(stanza)))) + }, + Ok(Async::Ready(_)) => { + self.state = ClientState::Connected(stream); + Ok(Async::NotReady) + }, + Err(e) => + Err(e.description().to_owned()), + } + }, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 12b710e171ca4de85274f96fb2f5d618bca82986..49cab6e9de522064cb9862a20678080b95aae8f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,10 +18,8 @@ mod tcp; pub use tcp::*; mod starttls; pub use starttls::*; -mod client_auth; -pub use client_auth::*; -mod client_bind; -pub use client_bind::*; +mod client; +pub use client::{Client, ClientEvent}; // type FullClient = sasl::Client> diff --git a/src/starttls.rs b/src/starttls.rs index 97a65c511509f0765ce69b209f96f0bb5547dc2c..79ee731c236e444cd50a541dfb3225ad9ab8dee3 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -15,6 +15,7 @@ use stream_start::StreamStart; pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; + pub struct StartTlsClient { state: StartTlsClientState, jid: Jid, diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 6eb2b24d7c7bd98d8d45727797771c3c425654e2..01d4aceb5b3617b9bdb98c3cd56943b1fc8b7326 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -4,14 +4,10 @@ use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use xml; -use sasl::common::{Credentials, ChannelBinding}; use jid::Jid; use xmpp_codec::*; use stream_start::*; -use starttls::{NS_XMPP_TLS, StartTlsClient}; -use client_auth::ClientAuth; -use client_bind::ClientBind; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -42,28 +38,6 @@ impl XMPPStream { pub fn restart(self) -> StreamStart { Self::from_stream(self.stream.into_inner(), self.jid) } - - pub fn can_starttls(&self) -> bool { - self.stream_features - .get_child("starttls", Some(NS_XMPP_TLS)) - .is_some() - } - - pub fn starttls(self) -> StartTlsClient { - StartTlsClient::from_stream(self) - } - - pub fn auth(self, username: String, password: String) -> Result, String> { - let creds = Credentials::default() - .with_username(username) - .with_password(password) - .with_channel_binding(ChannelBinding::None); - ClientAuth::new(self, creds) - } - - pub fn bind(self) -> ClientBind { - ClientBind::new(self) - } } /// Proxy to self.stream From 3c952e47d13dc9851f2518609791da85e5a05bb9 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 2 Jul 2017 01:25:22 +0200 Subject: [PATCH 022/135] impl Sink for Client + complete echo_bot --- examples/echo_bot.rs | 114 +++++++++++++++++++------------------------ src/client/mod.rs | 52 +++++++++++++++----- src/xmpp_stream.rs | 1 - 3 files changed, 89 insertions(+), 78 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 9f39dfe4e513f45f33ee88432fd6ef939fb369bb..03053dbdcb40b8028c2f4158bfaddf438335b805 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -4,84 +4,61 @@ extern crate tokio_xmpp; extern crate jid; extern crate xml; -use std::str::FromStr; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::{Client, ClientEvent}; -use tokio_xmpp::xmpp_codec::Packet; fn main() { let mut core = Core::new().unwrap(); let client = Client::new("astrobot@example.org", "", &core.handle()).unwrap(); - // let client = TcpClient::connect( - // jid.clone(), - // &addr, - // &core.handle() - // ).map_err(|e| format!("{}", e) - // ).and_then(|stream| { - // if stream.can_starttls() { - // stream.starttls() - // } else { - // panic!("No STARTTLS") - // } - // }).and_then(|stream| { - // let username = jid.node.as_ref().unwrap().to_owned(); - // stream.auth(username, password).expect("auth") - // }).and_then(|stream| { - // stream.bind() - // }).and_then(|stream| { - // println!("Bound to {}", stream.jid); - // let presence = xml::Element::new("presence".to_owned(), None, vec![]); - // stream.send(Packet::Stanza(presence)) - // .map_err(|e| format!("{}", e)) - // }).and_then(|stream| { - // let main_loop = |stream| { - // stream.into_future() - // .and_then(|(event, stream)| { - // stream.send(Packet::Stanza(unreachable!())) - // }).and_then(main_loop) - // }; - // main_loop(stream) - // }).and_then(|(event, stream)| { - // let (mut sink, stream) = stream.split(); - // stream.for_each(move |event| { - // match event { - // Packet::Stanza(ref message) - // if message.name == "message" => { - // let ty = message.get_attribute("type", None); - // let body = message.get_child("body", Some("jabber:client")) - // .map(|body_el| body_el.content_str()); - // match ty { - // None | Some("normal") | Some("chat") - // if body.is_some() => { - // let from = message.get_attribute("from", None).unwrap(); - // println!("Got message from {}: {:?}", from, body); - // let reply = make_reply(from, body.unwrap()); - // sink.send(Packet::Stanza(reply)) - // .and_then(|_| Ok(())) - // }, - // _ => future::ok(()), - // } - // }, - // _ => future::ok(()), - // } - // }).map_err(|e| format!("{}", e)) - // }); - - let done = client.for_each(|event| { - match event { + let (sink, stream) = client.split(); + let mut sink = Some(sink); + let done = stream.for_each(move |event| { + let result: Box> = match event { ClientEvent::Online => { println!("Online!"); + + let presence = make_presence(); + sink = Some( + sink.take(). + expect("sink") + .send(presence) + .wait() + .expect("sink.send") + ); + Box::new( + future::ok(()) + ) }, - ClientEvent::Stanza(stanza) => { + ClientEvent::Stanza(ref stanza) + if stanza.name == "message" + && stanza.get_attribute("type", None) != Some("error") => + { + let from = stanza.get_attribute("from", None); + let body = stanza.get_child("body", Some("jabber:client")) + .map(|el| el.content_str()); + + match (from.as_ref(), body) { + (Some(from), Some(body)) => { + let reply = make_reply(from, body); + sink = Some( + sink.take(). + expect("sink") + .send(reply) + .wait() + .expect("sink.send") + ); + }, + _ => (), + }; + Box::new(future::ok(())) }, _ => { - println!("Event: {:?}", event); + Box::new(future::ok(())) }, - } - - Ok(()) + }; + result }); match core.run(done) { @@ -93,6 +70,15 @@ fn main() { } } +fn make_presence() -> xml::Element { + let mut presence = xml::Element::new("presence".to_owned(), None, vec![]); + presence.tag(xml::Element::new("status".to_owned(), None, vec![])) + .text("chat".to_owned()); + presence.tag(xml::Element::new("show".to_owned(), None, vec![])) + .text("Echoing messages".to_owned()); + presence +} + fn make_reply(to: &str, body: String) -> xml::Element { let mut message = xml::Element::new( "message".to_owned(), diff --git a/src/client/mod.rs b/src/client/mod.rs index 624bf7249df1f664e6024df9797fb557cc9559d4..6554a6bce2f9a57126eb725869466526ab28b5e0 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,7 +1,7 @@ use std::mem::replace; use std::str::FromStr; use std::error::Error; -use tokio_core::reactor::{Core, Handle}; +use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; @@ -22,7 +22,6 @@ use self::bind::*; pub struct Client { pub jid: Jid, - password: String, state: ClientState, } @@ -33,8 +32,6 @@ enum ClientState { Disconnected, Connecting(Box>), Connected(XMPPStream), - // Sending, - // Drain, } impl Client { @@ -43,7 +40,7 @@ impl Client { let password = password.to_owned(); let connect = Self::make_connect(jid.clone(), password.clone(), handle); Ok(Client { - jid, password, + jid, state: ClientState::Connecting(connect), }) } @@ -73,10 +70,7 @@ impl Client { Self::bind(stream) }).and_then(|stream| { println!("Bound to {}", stream.jid); - - let presence = xml::Element::new("presence".to_owned(), None, vec![]); - stream.send(Packet::Stanza(presence)) - .map_err(|e| format!("{}", e)) + Ok(stream) }) ) } @@ -116,20 +110,18 @@ impl Stream for Client { type Error = String; fn poll(&mut self) -> Poll, Self::Error> { - println!("stream.poll"); let state = replace(&mut self.state, ClientState::Invalid); match state { ClientState::Invalid => Err("invalid client state".to_owned()), ClientState::Disconnected => - Ok(Async::NotReady), + Ok(Async::Ready(None)), ClientState::Connecting(mut connect) => { match connect.poll() { Ok(Async::Ready(stream)) => { - println!("connected"); self.state = ClientState::Connected(stream); - self.poll() + Ok(Async::Ready(Some(ClientEvent::Online))) }, Ok(Async::NotReady) => { self.state = ClientState::Connecting(connect); @@ -165,3 +157,37 @@ impl Stream for Client { } } } + +impl Sink for Client { + type SinkItem = xml::Element; + type SinkError = String; + + fn start_send(&mut self, item: Self::SinkItem) -> StartSend { + match self.state { + ClientState::Connected(ref mut stream) => + match stream.start_send(Packet::Stanza(item)) { + Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => + Ok(AsyncSink::NotReady(stanza)), + Ok(AsyncSink::NotReady(_)) => + panic!("Client.start_send with stanza but got something else back"), + Ok(AsyncSink::Ready) => { + Ok(AsyncSink::Ready) + }, + Err(e) => + Err(e.description().to_owned()), + }, + _ => + Ok(AsyncSink::NotReady(item)), + } + } + + fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { + match &mut self.state { + &mut ClientState::Connected(ref mut stream) => + stream.poll_complete() + .map_err(|e| e.description().to_owned()), + _ => + Ok(Async::Ready(())), + } + } +} diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 01d4aceb5b3617b9bdb98c3cd56943b1fc8b7326..a09b5a984c0b625dcd5342f2411536d53a47cb16 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,4 +1,3 @@ -use std::default::Default; use std::collections::HashMap; use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; From 32031a239ef23a156ef4a5c10ea2274272d29462 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 2 Jul 2017 01:26:36 +0200 Subject: [PATCH 023/135] TODO --- src/client/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client/mod.rs b/src/client/mod.rs index 6554a6bce2f9a57126eb725869466526ab28b5e0..e23b90fcf015ad21edbc4c32329006a7ea07b095 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -46,6 +46,7 @@ impl Client { } fn make_connect(jid: Jid, password: String, handle: &Handle) -> Box> { + // TODO: implement proper DNS SRV lookup use std::net::ToSocketAddrs; let addr = "89.238.79.220:5222" .to_socket_addrs().unwrap() From d5768c4c787b51b5c3599cd285fc6be38b2ae8cb Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 01:40:14 +0200 Subject: [PATCH 024/135] echo_bot: unify send() --- examples/echo_bot.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 03053dbdcb40b8028c2f4158bfaddf438335b805..4af8e8e2ea89dc6a8bd0703795fd83c9c1d48ac4 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -14,19 +14,22 @@ fn main() { let (sink, stream) = client.split(); let mut sink = Some(sink); - let done = stream.for_each(move |event| { + let mut send = move |stanza| { + sink = Some( + sink.take(). + expect("sink") + .send(stanza) + .wait() + .expect("sink.send") + ); + }; + let done = stream.for_each(|event| { let result: Box> = match event { ClientEvent::Online => { println!("Online!"); let presence = make_presence(); - sink = Some( - sink.take(). - expect("sink") - .send(presence) - .wait() - .expect("sink.send") - ); + send(presence); Box::new( future::ok(()) ) @@ -42,13 +45,7 @@ fn main() { match (from.as_ref(), body) { (Some(from), Some(body)) => { let reply = make_reply(from, body); - sink = Some( - sink.take(). - expect("sink") - .send(reply) - .wait() - .expect("sink.send") - ); + send(reply); }, _ => (), }; From e2a4f609fb796dcd5ac6ed5f6903d11c407d30aa Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 01:43:27 +0200 Subject: [PATCH 025/135] rm stale code --- src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 49cab6e9de522064cb9862a20678080b95aae8f3..6f9cf09c786f1a876ced54613678eb378791cad0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,3 @@ mod starttls; pub use starttls::*; mod client; pub use client::{Client, ClientEvent}; - - -// type FullClient = sasl::Client> - From 7f667041d95e63a0769074d98e5d6931f5eeffaf Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 01:47:05 +0200 Subject: [PATCH 026/135] more of a ClientEvent api --- examples/echo_bot.rs | 41 +++++++++++++++++++---------------------- src/client/event.rs | 31 +++++++++++++++++++++++++++++++ src/client/mod.rs | 9 ++------- 3 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 src/client/event.rs diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 4af8e8e2ea89dc6a8bd0703795fd83c9c1d48ac4..f5923f016833b3a3d1ad4c1f1db1b77c23028ad3 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -6,7 +6,7 @@ extern crate xml; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; -use tokio_xmpp::{Client, ClientEvent}; +use tokio_xmpp::Client; fn main() { let mut core = Core::new().unwrap(); @@ -24,8 +24,8 @@ fn main() { ); }; let done = stream.for_each(|event| { - let result: Box> = match event { - ClientEvent::Online => { + let result: Box> = + if event.is_online() { println!("Online!"); let presence = make_presence(); @@ -33,28 +33,25 @@ fn main() { Box::new( future::ok(()) ) - }, - ClientEvent::Stanza(ref stanza) - if stanza.name == "message" - && stanza.get_attribute("type", None) != Some("error") => - { - let from = stanza.get_attribute("from", None); - let body = stanza.get_child("body", Some("jabber:client")) - .map(|el| el.content_str()); + } else if let Some(stanza) = event.as_stanza() { + if stanza.name == "message" && + stanza.get_attribute("type", None) != Some("error") { + let from = stanza.get_attribute("from", None); + let body = stanza.get_child("body", Some("jabber:client")) + .map(|el| el.content_str()); - match (from.as_ref(), body) { - (Some(from), Some(body)) => { - let reply = make_reply(from, body); - send(reply); - }, - _ => (), - }; + match (from.as_ref(), body) { + (Some(from), Some(body)) => { + let reply = make_reply(from, body); + send(reply); + }, + _ => (), + }; + } Box::new(future::ok(())) - }, - _ => { + } else { Box::new(future::ok(())) - }, - }; + }; result }); diff --git a/src/client/event.rs b/src/client/event.rs new file mode 100644 index 0000000000000000000000000000000000000000..e54cff4121e0f60bdd0d24ea379d3ddce3c75f48 --- /dev/null +++ b/src/client/event.rs @@ -0,0 +1,31 @@ +use xml; + +#[derive(Debug)] +pub enum Event { + Online, + Disconnected, + Stanza(xml::Element), +} + +impl Event { + pub fn is_online(&self) -> bool { + match self { + &Event::Online => true, + _ => false, + } + } + + pub fn is_stanza(&self, name: &str) -> bool { + match self { + &Event::Stanza(ref stanza) => stanza.name == name, + _ => false, + } + } + + pub fn as_stanza(&self) -> Option<&xml::Element> { + match self { + &Event::Stanza(ref stanza) => Some(stanza), + _ => None, + } + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs index e23b90fcf015ad21edbc4c32329006a7ea07b095..3f962d9148ba6c16827cf7d53cb4f94705107317 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -19,6 +19,8 @@ mod auth; use self::auth::*; mod bind; use self::bind::*; +mod event; +pub use self::event::Event as ClientEvent; pub struct Client { pub jid: Jid, @@ -99,13 +101,6 @@ impl Client { } } -#[derive(Debug)] -pub enum ClientEvent { - Online, - Disconnected, - Stanza(xml::Element), -} - impl Stream for Client { type Item = ClientEvent; type Error = String; From e2c6a6ed37250d5c7b0bf140574938d1237d39b5 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 02:56:02 +0200 Subject: [PATCH 027/135] implement SRV lookup --- Cargo.toml | 3 +- src/client/mod.rs | 48 +++++++++++------------ src/happy_eyeballs.rs | 91 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- src/tcp.rs | 8 ++++ 5 files changed, 125 insertions(+), 28 deletions(-) create mode 100644 src/happy_eyeballs.rs diff --git a/Cargo.toml b/Cargo.toml index 12e818a70061ce8dffe43d691054bcd8a9589708..6410ca2a79a76462a1e7ff382338f09cdbd07d79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Astro "] [dependencies] futures = "*" -tokio-core = "*" +tokio-core = "0.1.7" tokio-io = "*" bytes = "*" RustyXML = "*" @@ -14,3 +14,4 @@ tokio-tls = "*" sasl = "*" rustc-serialize = "*" jid = "*" +domain = "0.2.1" diff --git a/src/client/mod.rs b/src/client/mod.rs index 3f962d9148ba6c16827cf7d53cb4f94705107317..d0be336a62b527f7ae27fb7240df2d7ff152fa47 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -14,6 +14,7 @@ use super::xmpp_codec::Packet; use super::xmpp_stream; use super::tcp::TcpClient; use super::starttls::{NS_XMPP_TLS, StartTlsClient}; +use super::happy_eyeballs::Connecter; mod auth; use self::auth::*; @@ -37,7 +38,7 @@ enum ClientState { } impl Client { - pub fn new(jid: &str, password: &str, handle: &Handle) -> Result { + pub fn new(jid: &str, password: &str, handle: Handle) -> Result { let jid = try!(Jid::from_str(jid)); let password = password.to_owned(); let connect = Self::make_connect(jid.clone(), password.clone(), handle); @@ -47,34 +48,29 @@ impl Client { }) } - fn make_connect(jid: Jid, password: String, handle: &Handle) -> Box> { - // TODO: implement proper DNS SRV lookup - use std::net::ToSocketAddrs; - let addr = "89.238.79.220:5222" - .to_socket_addrs().unwrap() - .next().unwrap(); + fn make_connect(jid: Jid, password: String, handle: Handle) -> Box> { let username = jid.node.as_ref().unwrap().to_owned(); let password = password; Box::new( - TcpClient::connect( - jid, - &addr, - handle - ).map_err(|e| format!("{}", e) - ).and_then(|stream| { - if Self::can_starttls(&stream) { - Self::starttls(stream) - } else { - panic!("No STARTTLS") - } - }).and_then(move |stream| { - Self::auth(stream, username, password).expect("auth") - }).and_then(|stream| { - Self::bind(stream) - }).and_then(|stream| { - println!("Bound to {}", stream.jid); - Ok(stream) - }) + Connecter::from_lookup(handle, &jid.domain, "_xmpp-client._tcp", 5222) + .expect("Connector::from_lookup") + .and_then(|tcp_stream| + TcpClient::from_stream(jid, tcp_stream) + .map_err(|e| format!("{}", e)) + ).and_then(|stream| { + if Self::can_starttls(&stream) { + Self::starttls(stream) + } else { + panic!("No STARTTLS") + } + }).and_then(move |stream| { + Self::auth(stream, username, password).expect("auth") + }).and_then(|stream| { + Self::bind(stream) + }).and_then(|stream| { + println!("Bound to {}", stream.jid); + Ok(stream) + }) ) } diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs new file mode 100644 index 0000000000000000000000000000000000000000..aa80df20a0e2033d4591e33f9b6eda2e5fcc6b98 --- /dev/null +++ b/src/happy_eyeballs.rs @@ -0,0 +1,91 @@ +use std::str::FromStr; +use futures::*; +use tokio_core::reactor::Handle; +use tokio_core::net::{TcpStream, TcpStreamNew}; +use domain::resolv::Resolver; +use domain::resolv::lookup::srv::*; +use domain::bits::DNameBuf; + +pub struct Connecter { + handle: Handle, + resolver: Resolver, + lookup: Option, + srvs: Option, + connects: Vec, +} + +impl Connecter { + pub fn from_lookup(handle: Handle, domain: &str, srv: &str, fallback_port: u16) -> Result { + let domain = try!( + DNameBuf::from_str(domain) + .map_err(|e| format!("{}", e)) + ); + let srv = try!( + DNameBuf::from_str(srv) + .map_err(|e| format!("{}", e)) + ); + + let resolver = Resolver::new(&handle); + let lookup = lookup_srv(resolver.clone(), srv, domain, fallback_port); + + Ok(Connecter { + handle, + resolver, + lookup: Some(lookup), + srvs: None, + connects: vec![], + }) + } +} + +impl Future for Connecter { + type Item = TcpStream; + type Error = String; + + fn poll(&mut self) -> Poll { + match self.lookup.as_mut().map(|mut lookup| lookup.poll()) { + None => (), + Some(Ok(Async::NotReady)) => (), + Some(Ok(Async::Ready(found_srvs))) => { + self.lookup = None; + match found_srvs { + Some(srvs) => + self.srvs = Some(srvs.to_stream(self.resolver.clone())), + None => + return Err("No SRV records".to_owned()), + } + }, + Some(Err(e)) => + return Err(format!("{}", e)), + } + + match self.srvs.as_mut().map(|mut srv| srv.poll()) { + None => (), + Some(Ok(Async::NotReady)) => (), + Some(Ok(Async::Ready(None))) => + self.srvs = None, + Some(Ok(Async::Ready(Some(srv_item)))) => { + for addr in srv_item.to_socket_addrs() { + println!("Connect to {}", addr); + let connect = TcpStream::connect(&addr, &self.handle); + self.connects.push(connect); + } + }, + Some(Err(e)) => + return Err(format!("{}", e)), + } + + for mut connect in &mut self.connects { + match connect.poll() { + Ok(Async::NotReady) => (), + Ok(Async::Ready(tcp_stream)) => + // Success! + return Ok(Async::Ready(tcp_stream)), + Err(e) => + return Err(format!("{}", e)), + } + } + + Ok(Async::NotReady) + } +} diff --git a/src/lib.rs b/src/lib.rs index 6f9cf09c786f1a876ced54613678eb378791cad0..bbc5d2ed4842e4382d1f5c23ab4870d7650300f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ extern crate tokio_tls; extern crate sasl; extern crate rustc_serialize as serialize; extern crate jid; - +extern crate domain; pub mod xmpp_codec; pub mod xmpp_stream; @@ -18,5 +18,6 @@ mod tcp; pub use tcp::*; mod starttls; pub use starttls::*; +mod happy_eyeballs; mod client; pub use client::{Client, ClientEvent}; diff --git a/src/tcp.rs b/src/tcp.rs index 2f207ec513a00998dea4e03745fb28a6c7172a5e..06aa7b83efd151520458218c2dfb52ee1961d95e 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -27,6 +27,14 @@ impl TcpClient { jid, } } + + pub fn from_stream(jid: Jid, tcp_stream: TcpStream) -> Self { + let start = XMPPStream::from_stream(tcp_stream, jid.clone()); + TcpClient { + state: TcpClientState::Start(start), + jid, + } + } } impl Future for TcpClient { From 7e18db0717736d7db1e422ed51724b44995f088e Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 22:04:54 +0200 Subject: [PATCH 028/135] echo_bot: document, simplify --- examples/echo_bot.rs | 61 ++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index f5923f016833b3a3d1ad4c1f1db1b77c23028ad3..7f27cfa8a5dc40cabc07b97fea2bf33decb4651e 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -9,10 +9,16 @@ use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; fn main() { + // Tokio_core context let mut core = Core::new().unwrap(); + // Client instance let client = Client::new("astrobot@example.org", "", &core.handle()).unwrap(); + // Make the two interfaces for sending and receiving independent + // of each other so we can move one into a closure. let (sink, stream) = client.split(); + // Wrap sink in Option so that we can take() it for the send(self) + // to consume and return it back when ready. let mut sink = Some(sink); let mut send = move |stanza| { sink = Some( @@ -23,38 +29,35 @@ fn main() { .expect("sink.send") ); }; + // Main loop, processes events let done = stream.for_each(|event| { - let result: Box> = - if event.is_online() { - println!("Online!"); + if event.is_online() { + println!("Online!"); - let presence = make_presence(); - send(presence); - Box::new( - future::ok(()) - ) - } else if let Some(stanza) = event.as_stanza() { - if stanza.name == "message" && - stanza.get_attribute("type", None) != Some("error") { - let from = stanza.get_attribute("from", None); - let body = stanza.get_child("body", Some("jabber:client")) - .map(|el| el.content_str()); + let presence = make_presence(); + send(presence); + } else if let Some(stanza) = event.as_stanza() { + if stanza.name == "message" && + stanza.get_attribute("type", None) != Some("error") { + // This is a message we'll echo + let from = stanza.get_attribute("from", None); + let body = stanza.get_child("body", Some("jabber:client")) + .map(|el| el.content_str()); - match (from.as_ref(), body) { - (Some(from), Some(body)) => { - let reply = make_reply(from, body); - send(reply); - }, - _ => (), - }; - } - Box::new(future::ok(())) - } else { - Box::new(future::ok(())) - }; - result + match (from.as_ref(), body) { + (Some(from), Some(body)) => { + let reply = make_reply(from, body); + send(reply); + }, + _ => (), + }; + } + } + + Box::new(future::ok(())) }); - + + // Start polling `done` match core.run(done) { Ok(_) => (), Err(e) => { @@ -64,6 +67,7 @@ fn main() { } } +// Construct a fn make_presence() -> xml::Element { let mut presence = xml::Element::new("presence".to_owned(), None, vec![]); presence.tag(xml::Element::new("status".to_owned(), None, vec![])) @@ -73,6 +77,7 @@ fn make_presence() -> xml::Element { presence } +// Construct a chat fn make_reply(to: &str, body: String) -> xml::Element { let mut message = xml::Element::new( "message".to_owned(), From 2335bab8443322f5483441b4e124dd0a4a6615d0 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 13 Jul 2017 22:17:29 +0200 Subject: [PATCH 029/135] happy_eyeballs: improvements --- src/happy_eyeballs.rs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index aa80df20a0e2033d4591e33f9b6eda2e5fcc6b98..039007bfb43ab1170ab7b5cdc777f6fb062326a1 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,4 +1,6 @@ use std::str::FromStr; +use std::collections::HashMap; +use std::net::SocketAddr; use futures::*; use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; @@ -11,7 +13,7 @@ pub struct Connecter { resolver: Resolver, lookup: Option, srvs: Option, - connects: Vec, + connects: HashMap, } impl Connecter { @@ -33,7 +35,7 @@ impl Connecter { resolver, lookup: Some(lookup), srvs: None, - connects: vec![], + connects: HashMap::new(), }) } } @@ -65,27 +67,37 @@ impl Future for Connecter { Some(Ok(Async::Ready(None))) => self.srvs = None, Some(Ok(Async::Ready(Some(srv_item)))) => { + let handle = &self.handle; for addr in srv_item.to_socket_addrs() { - println!("Connect to {}", addr); - let connect = TcpStream::connect(&addr, &self.handle); - self.connects.push(connect); + self.connects.entry(addr) + .or_insert_with(|| { + println!("Connect to {}", addr); + TcpStream::connect(&addr, handle) + }); } }, Some(Err(e)) => return Err(format!("{}", e)), } - for mut connect in &mut self.connects { + for mut connect in self.connects.values_mut() { match connect.poll() { Ok(Async::NotReady) => (), Ok(Async::Ready(tcp_stream)) => // Success! return Ok(Async::Ready(tcp_stream)), Err(e) => - return Err(format!("{}", e)), + println!("{}", e), } } - + + if self.lookup.is_none() && + self.srvs.is_none() && + self.connects.is_empty() + { + return Err("All connection attempts failed".to_owned()); + } + Ok(Async::NotReady) } } From 6e5f86632f78f40589f90d8af4a00b794bfc6d19 Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 14 Jul 2017 01:58:25 +0200 Subject: [PATCH 030/135] xmpp_codec: add remedies for truncated utf8 --- src/xmpp_codec.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 2551cc44fa13e8310ca066fe32e8397e668d465a..1069372f2280aa0112a222c7bd3b220e03fe4c56 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -56,6 +56,7 @@ pub enum Packet { pub struct XMPPCodec { parser: xml::Parser, root: Option, + buf: Vec, } impl XMPPCodec { @@ -63,6 +64,7 @@ impl XMPPCodec { XMPPCodec { parser: xml::Parser::new(), root: None, + buf: vec![], } } } @@ -72,15 +74,40 @@ impl Decoder for XMPPCodec { type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - match from_utf8(buf.take().as_ref()) { + let buf1: Box> = + if self.buf.len() > 0 && buf.len() > 0 { + let mut prefix = std::mem::replace(&mut self.buf, vec![]); + prefix.extend_from_slice(buf.take().as_ref()); + Box::new(prefix) + } else { + Box::new(buf.take()) + }; + let buf1 = buf1.as_ref().as_ref(); + match from_utf8(buf1) { Ok(s) => { if s.len() > 0 { println!("<< {}", s); self.parser.feed_str(s); } }, - Err(e) => - return Err(Error::new(ErrorKind::InvalidInput, e)), + // Remedies for truncated utf8 + Err(e) if e.valid_up_to() >= buf1.len() - 3 => { + // Prepare all the valid data + let mut b = BytesMut::with_capacity(e.valid_up_to()); + b.put(&buf1[0..e.valid_up_to()]); + + // Retry + let result = self.decode(&mut b); + + // Keep the tail back in + self.buf.extend_from_slice(&buf1[e.valid_up_to()..]); + + return result; + }, + Err(e) => { + println!("error {} at {}/{} in {:?}", e, e.valid_up_to(), buf1.len(), buf1); + return Err(Error::new(ErrorKind::InvalidInput, e)); + }, } let mut new_root: Option = None; @@ -171,3 +198,83 @@ impl Encoder for XMPPCodec { .map_err(|_| Error::from(ErrorKind::InvalidInput)) } } + +#[cfg(test)] +mod tests { + use super::*; + use bytes::BytesMut; + + #[test] + fn test_stream_start() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + } + + #[test] + fn test_truncated_stanza() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + + b.clear(); + b.put(r"ß true, + _ => false, + }); + + b.clear(); + b.put(r">"); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::Stanza(ref el))) + if el.name == "test" + && el.content_str() == "ß" + => true, + _ => false, + }); + } + + #[test] + fn test_truncated_utf8() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + + b.clear(); + b.put(&b"\xc3"[..]); + let r = c.decode(&mut b); + assert!(match r { + Ok(None) => true, + _ => false, + }); + + b.clear(); + b.put(&b"\x9f"[..]); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::Stanza(ref el))) + if el.name == "test" + && el.content_str() == "ß" + => true, + _ => false, + }); + } +} From fa08591162709ad3ea50853319cf9d714be35e87 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 15 Jul 2017 22:35:50 +0200 Subject: [PATCH 031/135] echo_bot: take jid, password from cmdline args --- examples/echo_bot.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 7f27cfa8a5dc40cabc07b97fea2bf33decb4651e..ee9925084bfb02e2d5959f2dccc5c61dba6511b0 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -4,15 +4,25 @@ extern crate tokio_xmpp; extern crate jid; extern crate xml; +use std::env::args; +use std::process::exit; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; fn main() { - // Tokio_core context + let args: Vec = args().collect(); + if args.len() != 3 { + println!("Usage: {} ", args[0]); + exit(1); + } + let jid = &args[1]; + let password = &args[2]; + + // tokio_core context let mut core = Core::new().unwrap(); // Client instance - let client = Client::new("astrobot@example.org", "", &core.handle()).unwrap(); + let client = Client::new(jid, password, core.handle()).unwrap(); // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. From d4bd64370ce93218de436d1f380a23888e2766aa Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 17 Jul 2017 20:53:00 +0200 Subject: [PATCH 032/135] switch from rustxml to minidom, doesn't work --- Cargo.toml | 6 +- examples/echo_bot.rs | 49 ++++----- src/client/auth.rs | 56 +++++----- src/client/bind.rs | 57 +++++------ src/client/event.rs | 8 +- src/client/mod.rs | 6 +- src/lib.rs | 4 +- src/starttls.rs | 11 +- src/stream_start.rs | 4 +- src/xmpp_codec.rs | 239 ++++++++++++++++++++++++++----------------- src/xmpp_stream.rs | 6 +- 11 files changed, 241 insertions(+), 205 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6410ca2a79a76462a1e7ff382338f09cdbd07d79..e80f7bbc51da09d90ef29fde73df50fe8579e5c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,10 @@ authors = ["Astro "] futures = "*" tokio-core = "0.1.7" tokio-io = "*" -bytes = "*" -RustyXML = "*" +bytes = "0.4.4" +xml5ever = "*" +tendril = "*" +minidom = { path = "../../programs/minidom-rs" } native-tls = "*" tokio-tls = "*" sasl = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index ee9925084bfb02e2d5959f2dccc5c61dba6511b0..8ba944ef5b2d50e6fb11b1cd979bab17b479607a 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -2,13 +2,14 @@ extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; extern crate jid; -extern crate xml; +extern crate minidom; use std::env::args; use std::process::exit; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; +use minidom::Element; fn main() { let args: Vec = args().collect(); @@ -47,14 +48,14 @@ fn main() { let presence = make_presence(); send(presence); } else if let Some(stanza) = event.as_stanza() { - if stanza.name == "message" && - stanza.get_attribute("type", None) != Some("error") { + if stanza.name() == "message" && + stanza.attr("type") != Some("error") { // This is a message we'll echo - let from = stanza.get_attribute("from", None); - let body = stanza.get_child("body", Some("jabber:client")) - .map(|el| el.content_str()); + let from = stanza.attr("from"); + let body = stanza.get_child("body", "jabber:client") + .map(|el| el.text()); - match (from.as_ref(), body) { + match (from, body) { (Some(from), Some(body)) => { let reply = make_reply(from, body); send(reply); @@ -78,24 +79,24 @@ fn main() { } // Construct a -fn make_presence() -> xml::Element { - let mut presence = xml::Element::new("presence".to_owned(), None, vec![]); - presence.tag(xml::Element::new("status".to_owned(), None, vec![])) - .text("chat".to_owned()); - presence.tag(xml::Element::new("show".to_owned(), None, vec![])) - .text("Echoing messages".to_owned()); - presence +fn make_presence() -> Element { + Element::builder("presence") + .append(Element::builder("status") + .append("chat") + .build()) + .append(Element::builder("show") + .append("Echoing messages") + .build()) + .build() } // Construct a chat -fn make_reply(to: &str, body: String) -> xml::Element { - let mut message = xml::Element::new( - "message".to_owned(), - None, - vec![("type".to_owned(), None, "chat".to_owned()), - ("to".to_owned(), None, to.to_owned())] - ); - message.tag(xml::Element::new("body".to_owned(), None, vec![])) - .text(body); - message +fn make_reply(to: &str, body: String) -> Element { + Element::builder("message") + .attr("type", "chat") + .attr("to", to) + .append(Element::builder("body") + .append(body) + .build()) + .build() } diff --git a/src/client/auth.rs b/src/client/auth.rs index c6aa79d67975e09a4aedc2f76b9a3fe5a5ac3f06..8716fea76edf9d0c6aa67086f1685fc00ee4dbd8 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -2,7 +2,7 @@ use std::mem::replace; use futures::*; use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; -use xml; +use minidom::Element; use sasl::common::Credentials; use sasl::common::scram::*; use sasl::client::Mechanism; @@ -37,12 +37,13 @@ impl ClientAuth { ]; let mech_names: Vec = - match stream.stream_features.get_child("mechanisms", Some(NS_XMPP_SASL)) { + match stream.stream_features.get_child("mechanisms", NS_XMPP_SASL) { None => return Err("No auth mechanisms".to_owned()), Some(mechs) => - mechs.get_children("mechanism", Some(NS_XMPP_SASL)) - .map(|mech_el| mech_el.content_str()) + mechs.children() + .filter(|child| child.is("mechanism", NS_XMPP_SASL)) + .map(|mech_el| mech_el.text()) .collect(), }; println!("SASL mechanisms offered: {:?}", mech_names); @@ -58,7 +59,7 @@ impl ClientAuth { }; this.send( stream, - "auth", &[("mechanism".to_owned(), name)], + "auth", &[("mechanism", &name)], &initial ); return Ok(this); @@ -68,15 +69,13 @@ impl ClientAuth { Err("No supported SASL mechanism available".to_owned()) } - fn send(&mut self, stream: XMPPStream, nonza_name: &str, attrs: &[(String, String)], content: &[u8]) { - let mut nonza = xml::Element::new( - nonza_name.to_owned(), - Some(NS_XMPP_SASL.to_owned()), - attrs.iter() - .map(|&(ref name, ref value)| (name.clone(), None, value.clone())) - .collect() - ); - nonza.text(content.to_base64(base64::URL_SAFE)); + fn send(&mut self, stream: XMPPStream, nonza_name: &str, attrs: &[(&str, &str)], content: &[u8]) { + let nonza = Element::builder(nonza_name) + .ns(NS_XMPP_SASL); + let nonza = attrs.iter() + .fold(nonza, |nonza, &(name, value)| nonza.attr(name, value)) + .append(content.to_base64(base64::URL_SAFE)) + .build(); let send = stream.send(Packet::Stanza(nonza)); @@ -108,11 +107,11 @@ impl Future for ClientAuth { ClientAuthState::WaitRecv(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name == "challenge" - && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + if stanza.name() == "challenge" + && stanza.ns() == Some(NS_XMPP_SASL) => { let content = try!( - stanza.content_str() + stanza.text() .from_base64() .map_err(|e| format!("{}", e)) ); @@ -121,29 +120,24 @@ impl Future for ClientAuth { self.poll() }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name == "success" - && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + if stanza.name() == "success" + && stanza.ns() == Some(NS_XMPP_SASL) => { let start = stream.restart(); self.state = ClientAuthState::Start(start); self.poll() }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name == "failure" - && stanza.ns == Some(NS_XMPP_SASL.to_owned()) => + if stanza.name() == "failure" + && stanza.ns() == Some(NS_XMPP_SASL) => { let mut e = None; - for child in &stanza.children { - match child { - &xml::Xml::ElementNode(ref child) => { - e = Some(child.name.clone()); - break - }, - _ => (), - } + for child in stanza.children() { + e = Some(child.name().clone()); + break } - let e = e.unwrap_or_else(|| "Authentication failure".to_owned()); - Err(e) + let e = e.unwrap_or_else(|| "Authentication failure"); + Err(e.to_owned()) }, Ok(Async::Ready(event)) => { println!("ClientAuth ignore {:?}", event); diff --git a/src/client/bind.rs b/src/client/bind.rs index 45f68e6f6f5a8ccf16b8c99dd01dd581c2f3990e..6a59503c4b50c53ba9d4be5b5ff9542b1b03fd96 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -4,8 +4,8 @@ use std::str::FromStr; use futures::*; use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; -use xml; use jid::Jid; +use minidom::Element; use xmpp_codec::*; use xmpp_stream::*; @@ -25,7 +25,7 @@ impl ClientBind { /// the stream for anything else until the resource binding /// req/resp are done. pub fn new(stream: XMPPStream) -> Self { - match stream.stream_features.get_child("bind", Some(NS_XMPP_BIND)) { + match stream.stream_features.get_child("bind", NS_XMPP_BIND) { None => // No resource binding available, // return the (probably // usable) stream immediately @@ -39,31 +39,22 @@ impl ClientBind { } } -fn make_bind_request(resource: Option<&String>) -> xml::Element { - let mut iq = xml::Element::new( - "iq".to_owned(), - None, - vec![("type".to_owned(), None, "set".to_owned()), - ("id".to_owned(), None, BIND_REQ_ID.to_owned())] - ); - { - let bind_el = iq.tag( - xml::Element::new( - "bind".to_owned(), - Some(NS_XMPP_BIND.to_owned()), - vec![] - )); - resource.map(|resource| { - let resource_el = bind_el.tag( - xml::Element::new( - "resource".to_owned(), - Some(NS_XMPP_BIND.to_owned()), - vec![] - )); - resource_el.text(resource.clone()); - }); +fn make_bind_request(resource: Option<&String>) -> Element { + let iq = Element::builder("iq") + .attr("type", "set") + .attr("id", BIND_REQ_ID); + let mut bind_el = Element::builder("bind") + .ns(NS_XMPP_BIND); + match resource { + Some(resource) => { + let resource_el = Element::builder("resource") + .append(resource); + bind_el = bind_el.append(resource_el.build()); + }, + None => (), } - iq + iq.append(bind_el.build()) + .build() } impl Future for ClientBind { @@ -93,9 +84,9 @@ impl Future for ClientBind { ClientBind::WaitRecv(mut stream) => { match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(ref iq)))) - if iq.name == "iq" - && iq.get_attribute("id", None) == Some(BIND_REQ_ID) => { - match iq.get_attribute("type", None) { + if iq.name() == "iq" + && iq.attr("id") == Some(BIND_REQ_ID) => { + match iq.attr("type") { Some("result") => { get_bind_response_jid(&iq) .map(|jid| stream.jid = jid); @@ -123,13 +114,13 @@ impl Future for ClientBind { } } -fn get_bind_response_jid(iq: &xml::Element) -> Option { - iq.get_child("bind", Some(NS_XMPP_BIND)) +fn get_bind_response_jid(iq: &Element) -> Option { + iq.get_child("bind", NS_XMPP_BIND) .and_then(|bind_el| - bind_el.get_child("jid", Some(NS_XMPP_BIND)) + bind_el.get_child("jid", NS_XMPP_BIND) ) .and_then(|jid_el| - Jid::from_str(&jid_el.content_str()) + Jid::from_str(&jid_el.text()) .ok() ) } diff --git a/src/client/event.rs b/src/client/event.rs index e54cff4121e0f60bdd0d24ea379d3ddce3c75f48..7aba984a480ef6e44421c4f0da488f45577453f3 100644 --- a/src/client/event.rs +++ b/src/client/event.rs @@ -1,10 +1,10 @@ -use xml; +use minidom::Element; #[derive(Debug)] pub enum Event { Online, Disconnected, - Stanza(xml::Element), + Stanza(Element), } impl Event { @@ -17,12 +17,12 @@ impl Event { pub fn is_stanza(&self, name: &str) -> bool { match self { - &Event::Stanza(ref stanza) => stanza.name == name, + &Event::Stanza(ref stanza) => stanza.name() == name, _ => false, } } - pub fn as_stanza(&self) -> Option<&xml::Element> { + pub fn as_stanza(&self) -> Option<&Element> { match self { &Event::Stanza(ref stanza) => Some(stanza), _ => None, diff --git a/src/client/mod.rs b/src/client/mod.rs index d0be336a62b527f7ae27fb7240df2d7ff152fa47..de0bdb6664bdb0e326e778f307ae97372628a9c7 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -6,8 +6,8 @@ use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; use futures::*; +use minidom::Element; use jid::{Jid, JidParseError}; -use xml; use sasl::common::{Credentials, ChannelBinding}; use super::xmpp_codec::Packet; @@ -76,7 +76,7 @@ impl Client { fn can_starttls(stream: &xmpp_stream::XMPPStream) -> bool { stream.stream_features - .get_child("starttls", Some(NS_XMPP_TLS)) + .get_child("starttls", NS_XMPP_TLS) .is_some() } @@ -151,7 +151,7 @@ impl Stream for Client { } impl Sink for Client { - type SinkItem = xml::Element; + type SinkItem = Element; type SinkError = String; fn start_send(&mut self, item: Self::SinkItem) -> StartSend { diff --git a/src/lib.rs b/src/lib.rs index bbc5d2ed4842e4382d1f5c23ab4870d7650300f9..c150760d0785c679929f8d8c430b6eba20eff210 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,9 @@ extern crate futures; extern crate tokio_core; extern crate tokio_io; extern crate bytes; -extern crate xml; +extern crate xml5ever; +extern crate tendril; +extern crate minidom; extern crate native_tls; extern crate tokio_tls; extern crate sasl; diff --git a/src/starttls.rs b/src/starttls.rs index 79ee731c236e444cd50a541dfb3225ad9ab8dee3..fe6c64105805fe9d08d68b2a37588f2c591c22d5 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -5,7 +5,7 @@ use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::*; use native_tls::TlsConnector; -use xml; +use minidom::Element; use jid::Jid; use xmpp_codec::*; @@ -34,10 +34,9 @@ impl StartTlsClient { pub fn from_stream(xmpp_stream: XMPPStream) -> Self { let jid = xmpp_stream.jid.clone(); - let nonza = xml::Element::new( - "starttls".to_owned(), Some(NS_XMPP_TLS.to_owned()), - vec![] - ); + let nonza = Element::builder("starttls") + .ns(NS_XMPP_TLS) + .build(); let packet = Packet::Stanza(nonza); let send = xmpp_stream.send(packet); @@ -72,7 +71,7 @@ impl Future for StartTlsClient { StartTlsClientState::AwaitProceed(mut xmpp_stream) => match xmpp_stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name == "proceed" => + if stanza.name() == "proceed" => { let stream = xmpp_stream.stream.into_inner(); let connect = TlsConnector::builder().unwrap() diff --git a/src/stream_start.rs b/src/stream_start.rs index 11b074e6c7cb119c186b6211ab4961cecf936a5e..bbccadd139a2611915c82f4957fba7e31b53358b 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -76,8 +76,8 @@ impl Future for StreamStart { StreamStartState::RecvFeatures(mut stream, stream_attrs) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => - if stanza.name == "features" - && stanza.ns == Some(NS_XMPP_STREAM.to_owned()) { + if stanza.name() == "features" + && stanza.ns() == Some(NS_XMPP_STREAM) { let stream = XMPPStream::new(self.jid.clone(), stream, stream_attrs, stanza); (StreamStartState::Invalid, Ok(Async::Ready(stream))) } else { diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 1069372f2280aa0112a222c7bd3b220e03fe4c56..e6a1bd2c543f94ebd3949d453a377998b7e91f53 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -1,69 +1,139 @@ use std; +use std::default::Default; +use std::iter::FromIterator; +use std::cell::RefCell; +use std::rc::Rc; use std::fmt::Write; use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; +use std::collections::vec_deque::VecDeque; use tokio_io::codec::{Encoder, Decoder}; -use xml; +use minidom::Element; +use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use bytes::*; -const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; +// const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; -pub type Attributes = HashMap<(String, Option), String>; +#[derive(Debug)] +pub enum Packet { + Error(Box), + StreamStart(HashMap), + Stanza(Element), + Text(String), + StreamEnd, +} -struct XMPPRoot { - builder: xml::ElementBuilder, - pub attributes: Attributes, +struct ParserSink { + // Ready stanzas + queue: Rc>>, + // Parsing stack + stack: Vec, } -impl XMPPRoot { - fn new(root: xml::StartTag) -> Self { - let mut builder = xml::ElementBuilder::new(); - let mut attributes = HashMap::new(); - for (name_ns, value) in root.attributes { - match name_ns { - (ref name, None) if name == "xmlns" => - builder.set_default_ns(value), - (ref prefix, Some(ref ns)) if ns == NS_XMLNS => - builder.define_prefix(prefix.to_owned(), value), - _ => { - attributes.insert(name_ns, value); - }, - } +impl ParserSink { + pub fn new(queue: Rc>>) -> Self { + ParserSink { + queue, + stack: vec![], } + } - XMPPRoot { - builder: builder, - attributes: attributes, - } + fn push_queue(&self, pkt: Packet) { + println!("push: {:?}", pkt); + self.queue.borrow_mut().push_back(pkt); } - fn handle_event(&mut self, event: Result) - -> Option> { - self.builder.handle_event(event) + fn handle_start_tag(&mut self, tag: Tag) { + let el = tag_to_element(&tag); + self.stack.push(el); + } + + fn handle_end_tag(&mut self) { + let el = self.stack.pop().unwrap(); + match self.stack.len() { + // + 0 => + self.push_queue(Packet::StreamEnd), + // + 1 => + self.push_queue(Packet::Stanza(el)), + len => { + let parent = &mut self.stack[len - 1]; + parent.append_child(el); + }, + } } } -#[derive(Debug)] -pub enum Packet { - Error(Box), - StreamStart(HashMap), - Stanza(xml::Element), - Text(String), - StreamEnd, +fn tag_to_element(tag: &Tag) -> Element { + let el_builder = Element::builder(tag.name.local.as_ref()) + .ns(tag.name.ns.as_ref()); + let el_builder = tag.attrs.iter().fold( + el_builder, + |el_builder, attr| el_builder.attr( + attr.name.local.as_ref(), + attr.value.as_ref() + ) + ); + el_builder.build() +} + +impl TokenSink for ParserSink { + fn process_token(&mut self, token: Token) { + println!("Token: {:?}", token); + match token { + Token::TagToken(tag) => match tag.kind { + TagKind::StartTag => + self.handle_start_tag(tag), + TagKind::EndTag => + self.handle_end_tag(), + TagKind::EmptyTag => { + self.handle_start_tag(tag); + self.handle_end_tag(); + }, + TagKind::ShortTag => + self.push_queue(Packet::Error(Box::new(Error::new(ErrorKind::InvalidInput, "ShortTag")))), + }, + Token::CharacterTokens(tendril) => + match self.stack.len() { + 0 | 1 => + self.push_queue(Packet::Text(tendril.into())), + len => { + let el = &mut self.stack[len - 1]; + el.append_text_node(tendril); + }, + }, + Token::EOFToken => + self.push_queue(Packet::StreamEnd), + Token::ParseError(s) => { + println!("ParseError: {:?}", s); + self.push_queue(Packet::Error(Box::new(Error::new(ErrorKind::InvalidInput, (*s).to_owned())))) + }, + _ => (), + } + } + + // fn end(&mut self) { + // } } pub struct XMPPCodec { - parser: xml::Parser, - root: Option, + parser: XmlTokenizer, + // For handling truncated utf8 buf: Vec, + queue: Rc>>, } impl XMPPCodec { pub fn new() -> Self { + let queue = Rc::new(RefCell::new((VecDeque::new()))); + let sink = ParserSink::new(queue.clone()); + // TODO: configure parser? + let parser = XmlTokenizer::new(sink, Default::default()); XMPPCodec { - parser: xml::Parser::new(), - root: None, + parser, + queue, buf: vec![], } } @@ -74,6 +144,7 @@ impl Decoder for XMPPCodec { type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { + println!("decode {} bytes", buf.len()); let buf1: Box> = if self.buf.len() > 0 && buf.len() > 0 { let mut prefix = std::mem::replace(&mut self.buf, vec![]); @@ -87,7 +158,8 @@ impl Decoder for XMPPCodec { Ok(s) => { if s.len() > 0 { println!("<< {}", s); - self.parser.feed_str(s); + let tendril = FromIterator::from_iter(s.chars()); + self.parser.feed(tendril); } }, // Remedies for truncated utf8 @@ -110,57 +182,11 @@ impl Decoder for XMPPCodec { }, } - let mut new_root: Option = None; - let mut result = None; - for event in &mut self.parser { - match self.root { - None => { - // Expecting - match event { - Ok(xml::Event::ElementStart(start_tag)) => { - let mut attrs: HashMap = HashMap::new(); - for (&(ref name, _), value) in &start_tag.attributes { - attrs.insert(name.to_owned(), value.to_owned()); - } - result = Some(Packet::StreamStart(attrs)); - self.root = Some(XMPPRoot::new(start_tag)); - break - }, - Err(e) => { - result = Some(Packet::Error(Box::new(e))); - break - }, - _ => - (), - } - } - - Some(ref mut root) => { - match root.handle_event(event) { - None => (), - Some(Ok(stanza)) => { - // Emit the stanza - result = Some(Packet::Stanza(stanza)); - break - }, - Some(Err(e)) => { - result = Some(Packet::Error(Box::new(e))); - break - } - }; - }, - } - - match new_root.take() { - None => (), - Some(root) => self.root = Some(root), - } - } - + let result = self.queue.borrow_mut().pop_front(); Ok(result) } - fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Error> { + fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { self.decode(buf) } } @@ -170,35 +196,56 @@ impl Encoder for XMPPCodec { type Error = Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + println!("encode {:?}", item); match item { Packet::StreamStart(start_attrs) => { let mut buf = String::new(); write!(buf, "\n").unwrap(); print!(">> {}", buf); write!(dst, "{}", buf) + .map_err(|_| Error::from(ErrorKind::InvalidInput)) }, Packet::Stanza(stanza) => { - println!(">> {}", stanza); - write!(dst, "{}", stanza) + println!(">> {:?}", stanza); + let mut root_ns = None; // TODO + stanza.write_to_inner(&mut dst.clone().writer(), &mut root_ns) + .map_err(|_| Error::from(ErrorKind::InvalidInput)) }, Packet::Text(text) => { - let escaped = xml::escape(&text); + let escaped = escape(&text); println!(">> {}", escaped); write!(dst, "{}", escaped) + .map_err(|_| Error::from(ErrorKind::InvalidInput)) }, // TODO: Implement all _ => Ok(()) } - .map_err(|_| Error::from(ErrorKind::InvalidInput)) } } +/// Copied from RustyXML for now +pub fn escape(input: &str) -> String { + let mut result = String::with_capacity(input.len()); + + for c in input.chars() { + match c { + '&' => result.push_str("&"), + '<' => result.push_str("<"), + '>' => result.push_str(">"), + '\'' => result.push_str("'"), + '"' => result.push_str("""), + o => result.push(o) + } + } + result +} + #[cfg(test)] mod tests { use super::*; @@ -240,8 +287,8 @@ mod tests { let r = c.decode(&mut b); assert!(match r { Ok(Some(Packet::Stanza(ref el))) - if el.name == "test" - && el.content_str() == "ß" + if el.name() == "test" + && el.text() == "ß" => true, _ => false, }); @@ -271,8 +318,8 @@ mod tests { let r = c.decode(&mut b); assert!(match r { Ok(Some(Packet::Stanza(ref el))) - if el.name == "test" - && el.content_str() == "ß" + if el.name() == "test" + && el.text() == "ß" => true, _ => false, }); diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index a09b5a984c0b625dcd5342f2411536d53a47cb16..932cbcef3e5d3d1100ea50818a78a154915504c7 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; -use xml; +use minidom::Element; use jid::Jid; use xmpp_codec::*; @@ -14,14 +14,14 @@ pub struct XMPPStream { pub jid: Jid, pub stream: Framed, pub stream_attrs: HashMap, - pub stream_features: xml::Element, + pub stream_features: Element, } impl XMPPStream { pub fn new(jid: Jid, stream: Framed, stream_attrs: HashMap, - stream_features: xml::Element) -> Self { + stream_features: Element) -> Self { XMPPStream { jid, stream, stream_attrs, stream_features } } From 36d7ab474e4a8baf3c41e509e11f21665747d745 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 18 Jul 2017 20:04:34 +0200 Subject: [PATCH 033/135] client::auth: fix base64 encoding --- src/client/auth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 8716fea76edf9d0c6aa67086f1685fc00ee4dbd8..a366b2ffa8ca4aae6624a674020f515c364edada 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -74,7 +74,7 @@ impl ClientAuth { .ns(NS_XMPP_SASL); let nonza = attrs.iter() .fold(nonza, |nonza, &(name, value)| nonza.attr(name, value)) - .append(content.to_base64(base64::URL_SAFE)) + .append(content.to_base64(base64::STANDARD)) .build(); let send = stream.send(Packet::Stanza(nonza)); From b944ca4ac7a2f9b4b606af03529c607e7e885963 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 18 Jul 2017 20:12:17 +0200 Subject: [PATCH 034/135] make it work with minidom --- src/xmpp_codec.rs | 159 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 31 deletions(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index e6a1bd2c543f94ebd3949d453a377998b7e91f53..808f238929db867967b03a6e08428f778dd28850 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -9,8 +9,9 @@ use std::io::{Error, ErrorKind}; use std::collections::HashMap; use std::collections::vec_deque::VecDeque; use tokio_io::codec::{Encoder, Decoder}; -use minidom::Element; +use minidom::{Element, Node}; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; +use xml5ever::interface::Attribute; use bytes::*; // const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; @@ -25,10 +26,11 @@ pub enum Packet { } struct ParserSink { - // Ready stanzas + // Ready stanzas, shared with XMPPCodec queue: Rc>>, // Parsing stack stack: Vec, + ns_stack: Vec, String>>, } impl ParserSink { @@ -36,21 +38,79 @@ impl ParserSink { ParserSink { queue, stack: vec![], + ns_stack: vec![], } } fn push_queue(&self, pkt: Packet) { - println!("push: {:?}", pkt); self.queue.borrow_mut().push_back(pkt); } + fn lookup_ns(&self, prefix: &Option) -> Option<&str> { + for nss in self.ns_stack.iter().rev() { + match nss.get(prefix) { + Some(ns) => return Some(ns), + None => (), + } + } + + None + } + fn handle_start_tag(&mut self, tag: Tag) { - let el = tag_to_element(&tag); + let mut nss = HashMap::new(); + let is_prefix_xmlns = |attr: &Attribute| attr.name.prefix.as_ref() + .map(|prefix| prefix.eq_str_ignore_ascii_case("xmlns")) + .unwrap_or(false); + for attr in &tag.attrs { + match attr.name.local.as_ref() { + "xmlns" => { + nss.insert(None, attr.value.as_ref().to_owned()); + }, + prefix if is_prefix_xmlns(attr) => { + nss.insert(Some(prefix.to_owned()), attr.value.as_ref().to_owned()); + }, + _ => (), + } + } + self.ns_stack.push(nss); + + let el = { + let mut el_builder = Element::builder(tag.name.local.as_ref()); + match self.lookup_ns(&tag.name.prefix.map(|prefix| prefix.as_ref().to_owned())) { + Some(el_ns) => el_builder = el_builder.ns(el_ns), + None => (), + } + for attr in &tag.attrs { + match attr.name.local.as_ref() { + "xmlns" => (), + _ if is_prefix_xmlns(attr) => (), + _ => { + el_builder = el_builder.attr( + attr.name.local.as_ref(), + attr.value.as_ref() + ); + }, + } + } + el_builder.build() + }; + + if self.stack.is_empty() { + let attrs = HashMap::from_iter( + el.attrs() + .map(|(name, value)| (name.to_owned(), value.to_owned())) + ); + self.push_queue(Packet::StreamStart(attrs)); + } + self.stack.push(el); } fn handle_end_tag(&mut self) { let el = self.stack.pop().unwrap(); + self.ns_stack.pop(); + match self.stack.len() { // 0 => @@ -66,22 +126,8 @@ impl ParserSink { } } -fn tag_to_element(tag: &Tag) -> Element { - let el_builder = Element::builder(tag.name.local.as_ref()) - .ns(tag.name.ns.as_ref()); - let el_builder = tag.attrs.iter().fold( - el_builder, - |el_builder, attr| el_builder.attr( - attr.name.local.as_ref(), - attr.value.as_ref() - ) - ); - el_builder.build() -} - impl TokenSink for ParserSink { fn process_token(&mut self, token: Token) { - println!("Token: {:?}", token); match token { Token::TagToken(tag) => match tag.kind { TagKind::StartTag => @@ -119,9 +165,14 @@ impl TokenSink for ParserSink { } pub struct XMPPCodec { + /// Outgoing + ns: Option, + /// Incoming parser: XmlTokenizer, - // For handling truncated utf8 + /// For handling incoming truncated utf8 + // TODO: optimize using tendrils? buf: Vec, + /// Shared with ParserSink queue: Rc>>, } @@ -132,6 +183,7 @@ impl XMPPCodec { // TODO: configure parser? let parser = XmlTokenizer::new(sink, Default::default()); XMPPCodec { + ns: None, parser, queue, buf: vec![], @@ -144,7 +196,6 @@ impl Decoder for XMPPCodec { type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - println!("decode {} bytes", buf.len()); let buf1: Box> = if self.buf.len() > 0 && buf.len() > 0 { let mut prefix = std::mem::replace(&mut self.buf, vec![]); @@ -196,32 +247,39 @@ impl Encoder for XMPPCodec { type Error = Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { - println!("encode {:?}", item); match item { Packet::StreamStart(start_attrs) => { let mut buf = String::new(); write!(buf, "\n").unwrap(); print!(">> {}", buf); write!(dst, "{}", buf) - .map_err(|_| Error::from(ErrorKind::InvalidInput)) + .map_err(|e| Error::new(ErrorKind::InvalidInput, e)) }, Packet::Stanza(stanza) => { - println!(">> {:?}", stanza); - let mut root_ns = None; // TODO - stanza.write_to_inner(&mut dst.clone().writer(), &mut root_ns) - .map_err(|_| Error::from(ErrorKind::InvalidInput)) + let root_ns = self.ns.as_ref().map(|s| s.as_ref()); + write_element(&stanza, dst, root_ns) + .and_then(|_| { + println!(">> {:?}", dst); + Ok(()) + }) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) }, Packet::Text(text) => { - let escaped = escape(&text); - println!(">> {}", escaped); - write!(dst, "{}", escaped) - .map_err(|_| Error::from(ErrorKind::InvalidInput)) + write_text(&text, dst) + .and_then(|_| { + println!(">> {:?}", dst); + Ok(()) + }) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) }, // TODO: Implement all _ => Ok(()) @@ -229,6 +287,45 @@ impl Encoder for XMPPCodec { } } +pub fn write_text(text: &str, writer: &mut W) -> Result<(), std::fmt::Error> { + write!(writer, "{}", text) +} + +// TODO: escape everything? +pub fn write_element(el: &Element, writer: &mut W, parent_ns: Option<&str>) -> Result<(), std::fmt::Error> { + write!(writer, "<")?; + write!(writer, "{}", el.name())?; + + if let Some(ref ns) = el.ns() { + if parent_ns.map(|s| s.as_ref()) != el.ns() { + write!(writer, " xmlns=\"{}\"", ns)?; + } + } + + for (key, value) in el.attrs() { + write!(writer, " {}=\"{}\"", key, value)?; + } + + if ! el.nodes().any(|_| true) { + write!(writer, " />")?; + return Ok(()) + } + + write!(writer, ">")?; + + for node in el.nodes() { + match node { + &Node::Element(ref child) => + write_element(child, writer, el.ns())?, + &Node::Text(ref text) => + write_text(text, writer)?, + } + } + + write!(writer, "", el.name())?; + Ok(()) +} + /// Copied from RustyXML for now pub fn escape(input: &str) -> String { let mut result = String::with_capacity(input.len()); From c6351e8efaaa76a51c81018b85b157c4dae31728 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 18 Jul 2017 21:22:12 +0200 Subject: [PATCH 035/135] Cargo: fix minidom dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e80f7bbc51da09d90ef29fde73df50fe8579e5c2..827b324f4b32409ffb70f7d0b2b4c3d274fe1f59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = { path = "../../programs/minidom-rs" } +minidom = "0.5" native-tls = "*" tokio-tls = "*" sasl = "*" From 68af9d2110db49bd13f31ede5a1b8003c7b2aad4 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 18 Jul 2017 22:12:00 +0200 Subject: [PATCH 036/135] xmpp_codec: fix large stanzas --- src/xmpp_codec.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 808f238929db867967b03a6e08428f778dd28850..e6d260451c2b9f23f778a626b9fcaf811515a247 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -247,6 +247,12 @@ impl Encoder for XMPPCodec { type Error = Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + let remaining = dst.capacity() - dst.len(); + let max_stanza_size: usize = 2usize.pow(16); + if remaining < max_stanza_size { + dst.reserve(max_stanza_size - remaining); + } + match item { Packet::StreamStart(start_attrs) => { let mut buf = String::new(); @@ -421,4 +427,28 @@ mod tests { _ => false, }); } + + /// By default, encode() only get's a BytesMut that has 8kb space reserved. + #[test] + fn test_large_stanza() { + use std::io::Cursor; + use futures::{Future, Sink}; + use tokio_io::codec::FramedWrite; + let framed = FramedWrite::new(Cursor::new(vec![]), XMPPCodec::new()); + let mut text = "".to_owned(); + for _ in 0..2usize.pow(15) { + text = text + "A"; + } + let stanza = Element::builder("message") + .append( + Element::builder("body") + .append(&text) + .build() + ) + .build(); + let framed = framed.send(Packet::Stanza(stanza)) + .wait() + .expect("send"); + assert_eq!(framed.get_ref().get_ref(), &("".to_owned() + &text + "").as_bytes()); + } } From 0ec0f3413e993e255f5b51ac174810db182b7e0c Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 18 Jul 2017 20:41:57 +0100 Subject: [PATCH 037/135] echo_bot: use xmpp-parsers to generate stanzas This also fixes a bug where show and status were inverted while creating the presence element. --- Cargo.toml | 1 + examples/echo_bot.rs | 26 +++++++++++--------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 827b324f4b32409ffb70f7d0b2b4c3d274fe1f59..16b9d4ebf026ab29d3da4a52bc0998068d97be7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ sasl = "*" rustc-serialize = "*" jid = "*" domain = "0.2.1" +xmpp-parsers = "0.6.0" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 8ba944ef5b2d50e6fb11b1cd979bab17b479607a..528ac341252ce584afbfea6008075f7482533cd7 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -3,6 +3,7 @@ extern crate tokio_core; extern crate tokio_xmpp; extern crate jid; extern crate minidom; +extern crate xmpp_parsers; use std::env::args; use std::process::exit; @@ -10,6 +11,8 @@ use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; use minidom::Element; +use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; +use xmpp_parsers::message::Message; fn main() { let args: Vec = args().collect(); @@ -80,23 +83,16 @@ fn main() { // Construct a fn make_presence() -> Element { - Element::builder("presence") - .append(Element::builder("status") - .append("chat") - .build()) - .append(Element::builder("show") - .append("Echoing messages") - .build()) - .build() + let mut presence = Presence::new(PresenceType::None); + presence.show = PresenceShow::Chat; + presence.statuses.insert(String::from("en"), String::from("Echoing messages.")); + Element::from(presence) } // Construct a chat fn make_reply(to: &str, body: String) -> Element { - Element::builder("message") - .attr("type", "chat") - .attr("to", to) - .append(Element::builder("body") - .append(body) - .build()) - .build() + let jid = to.parse().unwrap(); + let mut message = Message::new(Some(jid)); + message.bodies.insert(String::new(), body); + Element::from(message) } From 794a99472082ec05cae863d3eb0fabd81541ec6d Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 18 Jul 2017 21:54:10 +0100 Subject: [PATCH 038/135] =?UTF-8?q?don=E2=80=99t=20use=20wildcard=20use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/auth.rs | 13 ++++++------- src/client/bind.rs | 7 +++---- src/client/mod.rs | 6 +++--- src/happy_eyeballs.rs | 4 ++-- src/lib.rs | 4 ++-- src/starttls.rs | 6 +++--- src/stream_start.rs | 6 +++--- src/tcp.rs | 2 +- src/xmpp_codec.rs | 2 +- src/xmpp_stream.rs | 6 +++--- 10 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index a366b2ffa8ca4aae6624a674020f515c364edada..dce2f86c831c38103f007c88c7dcb00730f0cec7 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,17 +1,16 @@ use std::mem::replace; -use futures::*; -use futures::sink; +use futures::{Future, Poll, Async, sink, Sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use minidom::Element; use sasl::common::Credentials; -use sasl::common::scram::*; +use sasl::common::scram::{Sha1, Sha256}; use sasl::client::Mechanism; -use sasl::client::mechanisms::*; +use sasl::client::mechanisms::{Scram, Plain, Anonymous}; use serialize::base64::{self, ToBase64, FromBase64}; -use xmpp_codec::*; -use xmpp_stream::*; -use stream_start::*; +use xmpp_codec::Packet; +use xmpp_stream::XMPPStream; +use stream_start::StreamStart; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; diff --git a/src/client/bind.rs b/src/client/bind.rs index 6a59503c4b50c53ba9d4be5b5ff9542b1b03fd96..7800bbcca160a3acec647fa8cd9a64f20dee4dde 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,14 +1,13 @@ use std::mem::replace; use std::error::Error; use std::str::FromStr; -use futures::*; -use futures::sink; +use futures::{Future, Poll, Async, sink, Sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use jid::Jid; use minidom::Element; -use xmpp_codec::*; -use xmpp_stream::*; +use xmpp_codec::Packet; +use xmpp_stream::XMPPStream; const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind"; const BIND_REQ_ID: &str = "resource-bind"; diff --git a/src/client/mod.rs b/src/client/mod.rs index de0bdb6664bdb0e326e778f307ae97372628a9c7..a45cede8d9bd3b6509006fdf538a0faf0bf6b83c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -5,7 +5,7 @@ use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; -use futures::*; +use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; use minidom::Element; use jid::{Jid, JidParseError}; use sasl::common::{Credentials, ChannelBinding}; @@ -17,9 +17,9 @@ use super::starttls::{NS_XMPP_TLS, StartTlsClient}; use super::happy_eyeballs::Connecter; mod auth; -use self::auth::*; +use self::auth::ClientAuth; mod bind; -use self::bind::*; +use self::bind::ClientBind; mod event; pub use self::event::Event as ClientEvent; diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 039007bfb43ab1170ab7b5cdc777f6fb062326a1..f529a87a7ba0f92b69702d2d623a36b1c85750f3 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,11 +1,11 @@ use std::str::FromStr; use std::collections::HashMap; use std::net::SocketAddr; -use futures::*; +use futures::{Future, Poll, Async, Stream}; use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; use domain::resolv::Resolver; -use domain::resolv::lookup::srv::*; +use domain::resolv::lookup::srv::{lookup_srv, LookupSrv, LookupSrvStream}; use domain::bits::DNameBuf; pub struct Connecter { diff --git a/src/lib.rs b/src/lib.rs index c150760d0785c679929f8d8c430b6eba20eff210..0cea1db29ecd5478e29da6b3303476e9766198e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,9 +17,9 @@ pub mod xmpp_codec; pub mod xmpp_stream; mod stream_start; mod tcp; -pub use tcp::*; +pub use tcp::TcpClient; mod starttls; -pub use starttls::*; +pub use starttls::StartTlsClient; mod happy_eyeballs; mod client; pub use client::{Client, ClientEvent}; diff --git a/src/starttls.rs b/src/starttls.rs index fe6c64105805fe9d08d68b2a37588f2c591c22d5..91a7ea260e138bed8b8d2f289168d3c1727ae47f 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -3,13 +3,13 @@ use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_tls::*; +use tokio_tls::{TlsStream, TlsConnectorExt, ConnectAsync}; use native_tls::TlsConnector; use minidom::Element; use jid::Jid; -use xmpp_codec::*; -use xmpp_stream::*; +use xmpp_codec::Packet; +use xmpp_stream::XMPPStream; use stream_start::StreamStart; diff --git a/src/stream_start.rs b/src/stream_start.rs index bbccadd139a2611915c82f4957fba7e31b53358b..0b4fd9e79f682a3831bcea73c5541bec92ab28bf 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,13 +1,13 @@ use std::mem::replace; use std::io::{Error, ErrorKind}; use std::collections::HashMap; -use futures::*; +use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use jid::Jid; -use xmpp_codec::*; -use xmpp_stream::*; +use xmpp_codec::{XMPPCodec, Packet}; +use xmpp_stream::XMPPStream; const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; diff --git a/src/tcp.rs b/src/tcp.rs index 06aa7b83efd151520458218c2dfb52ee1961d95e..156fa4f5cb600981dd75e73389df038580f81898 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -5,7 +5,7 @@ use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; use jid::Jid; -use xmpp_stream::*; +use xmpp_stream::XMPPStream; use stream_start::StreamStart; pub struct TcpClient { diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index e6d260451c2b9f23f778a626b9fcaf811515a247..7504dfff28baed3de4cab1a9dc61672886d8fcef 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -12,7 +12,7 @@ use tokio_io::codec::{Encoder, Decoder}; use minidom::{Element, Node}; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; -use bytes::*; +use bytes::{BytesMut, BufMut}; // const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 932cbcef3e5d3d1100ea50818a78a154915504c7..9ff6916fad61c64483de126b40a7bbc20755f679 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; -use futures::*; +use futures::{Poll, Stream, Sink, StartSend}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use minidom::Element; use jid::Jid; -use xmpp_codec::*; -use stream_start::*; +use xmpp_codec::XMPPCodec; +use stream_start::StreamStart; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; From 35be5a43239a12c754aa866d0e33954d011fa4b5 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 19 Jul 2017 01:00:17 +0200 Subject: [PATCH 039/135] Cargo, echo_bot: fix xmpp-parsers usage --- Cargo.toml | 2 +- examples/echo_bot.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 16b9d4ebf026ab29d3da4a52bc0998068d97be7b..cf7735a0e1f554f6b12dfdab56f76889eb6503a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = "0.5" +minidom = "0.4.3" native-tls = "*" tokio-tls = "*" sasl = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 528ac341252ce584afbfea6008075f7482533cd7..b3be75cd1a7e26189ae669f03ac51c43b5cd62f9 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -86,7 +86,7 @@ fn make_presence() -> Element { let mut presence = Presence::new(PresenceType::None); presence.show = PresenceShow::Chat; presence.statuses.insert(String::from("en"), String::from("Echoing messages.")); - Element::from(presence) + presence.into() } // Construct a chat @@ -94,5 +94,5 @@ fn make_reply(to: &str, body: String) -> Element { let jid = to.parse().unwrap(); let mut message = Message::new(Some(jid)); message.bodies.insert(String::new(), body); - Element::from(message) + message.into() } From 7b7f2866fc4fbc9724d6fc07fdfe75f5489b2456 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 19 Jul 2017 01:02:45 +0200 Subject: [PATCH 040/135] move stream_start out of places --- src/client/mod.rs | 31 ++++++++++++--------- src/lib.rs | 3 -- src/starttls.rs | 22 ++------------- src/stream_start.rs | 30 +++++++++++--------- src/tcp.rs | 68 --------------------------------------------- src/xmpp_codec.rs | 4 +-- src/xmpp_stream.rs | 13 ++++----- 7 files changed, 46 insertions(+), 125 deletions(-) delete mode 100644 src/tcp.rs diff --git a/src/client/mod.rs b/src/client/mod.rs index a45cede8d9bd3b6509006fdf538a0faf0bf6b83c..aca0fdd20294cc45324a2492361eac8a12062a5b 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -12,7 +12,6 @@ use sasl::common::{Credentials, ChannelBinding}; use super::xmpp_codec::Packet; use super::xmpp_stream; -use super::tcp::TcpClient; use super::starttls::{NS_XMPP_TLS, StartTlsClient}; use super::happy_eyeballs::Connecter; @@ -29,6 +28,7 @@ pub struct Client { } type XMPPStream = xmpp_stream::XMPPStream>; +const NS_JABBER_CLIENT: &str = "jabber:client"; enum ClientState { Invalid, @@ -50,26 +50,31 @@ impl Client { fn make_connect(jid: Jid, password: String, handle: Handle) -> Box> { let username = jid.node.as_ref().unwrap().to_owned(); + let jid1 = jid.clone(); + let jid2 = jid.clone(); let password = password; Box::new( Connecter::from_lookup(handle, &jid.domain, "_xmpp-client._tcp", 5222) .expect("Connector::from_lookup") - .and_then(|tcp_stream| - TcpClient::from_stream(jid, tcp_stream) + .and_then(move |tcp_stream| + xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) .map_err(|e| format!("{}", e)) - ).and_then(|stream| { - if Self::can_starttls(&stream) { - Self::starttls(stream) + ).and_then(|xmpp_stream| { + if Self::can_starttls(&xmpp_stream) { + Self::starttls(xmpp_stream) } else { panic!("No STARTTLS") } - }).and_then(move |stream| { - Self::auth(stream, username, password).expect("auth") - }).and_then(|stream| { - Self::bind(stream) - }).and_then(|stream| { - println!("Bound to {}", stream.jid); - Ok(stream) + }).and_then(|tls_stream| + XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) + .map_err(|e| format!("{}", e)) + ).and_then(move |xmpp_stream| { + Self::auth(xmpp_stream, username, password).expect("auth") + }).and_then(|xmpp_stream| { + Self::bind(xmpp_stream) + }).and_then(|xmpp_stream| { + println!("Bound to {}", xmpp_stream.jid); + Ok(xmpp_stream) }) ) } diff --git a/src/lib.rs b/src/lib.rs index 0cea1db29ecd5478e29da6b3303476e9766198e8..348c03b2b2f118a20fa856b1948331836b1a356e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#[macro_use] extern crate futures; extern crate tokio_core; extern crate tokio_io; @@ -16,8 +15,6 @@ extern crate domain; pub mod xmpp_codec; pub mod xmpp_stream; mod stream_start; -mod tcp; -pub use tcp::TcpClient; mod starttls; pub use starttls::StartTlsClient; mod happy_eyeballs; diff --git a/src/starttls.rs b/src/starttls.rs index 91a7ea260e138bed8b8d2f289168d3c1727ae47f..7338b55cd10f34fdf4112c6c3d68361335a1e9af 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -10,7 +10,6 @@ use jid::Jid; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; -use stream_start::StreamStart; pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; @@ -26,7 +25,6 @@ enum StartTlsClientState { SendStartTls(sink::Send>), AwaitProceed(XMPPStream), StartingTls(ConnectAsync), - Start(StreamStart>), } impl StartTlsClient { @@ -48,7 +46,7 @@ impl StartTlsClient { } impl Future for StartTlsClient { - type Item = XMPPStream>; + type Item = TlsStream; type Error = String; fn poll(&mut self) -> Poll { @@ -92,24 +90,10 @@ impl Future for StartTlsClient { }, StartTlsClientState::StartingTls(mut connect) => match connect.poll() { - Ok(Async::Ready(tls_stream)) => { - println!("TLS stream established"); - let start = XMPPStream::from_stream(tls_stream, self.jid.clone()); - let new_state = StartTlsClientState::Start(start); - retry = true; - (new_state, Ok(Async::NotReady)) - }, + Ok(Async::Ready(tls_stream)) => + (StartTlsClientState::Invalid, Ok(Async::Ready(tls_stream))), Ok(Async::NotReady) => (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), - Err(e) => - (StartTlsClientState::StartingTls(connect), Err(format!("{}", e))), - }, - StartTlsClientState::Start(mut start) => - match start.poll() { - Ok(Async::Ready(xmpp_stream)) => - (StartTlsClientState::Invalid, Ok(Async::Ready(xmpp_stream))), - Ok(Async::NotReady) => - (StartTlsClientState::Start(start), Ok(Async::NotReady)), Err(e) => (StartTlsClientState::Invalid, Err(format!("{}", e))), }, diff --git a/src/stream_start.rs b/src/stream_start.rs index 0b4fd9e79f682a3831bcea73c5541bec92ab28bf..b194b5bb4f0e7b5353524a75e9c9602d9b159ceb 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,6 +1,5 @@ use std::mem::replace; use std::io::{Error, ErrorKind}; -use std::collections::HashMap; use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; @@ -14,20 +13,21 @@ const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; pub struct StreamStart { state: StreamStartState, jid: Jid, + ns: String, } enum StreamStartState { SendStart(sink::Send>), RecvStart(Framed), - RecvFeatures(Framed, HashMap), + RecvFeatures(Framed, String), Invalid, } impl StreamStart { - pub fn from_stream(stream: Framed, jid: Jid) -> Self { + pub fn from_stream(stream: Framed, jid: Jid, ns: String) -> Self { let attrs = [("to".to_owned(), jid.domain.clone()), ("version".to_owned(), "1.0".to_owned()), - ("xmlns".to_owned(), "jabber:client".to_owned()), + ("xmlns".to_owned(), ns.clone()), ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), ].iter().cloned().collect(); let send = stream.send(Packet::StreamStart(attrs)); @@ -35,6 +35,7 @@ impl StreamStart { StreamStart { state: StreamStartState::SendStart(send), jid, + ns, } } } @@ -63,8 +64,13 @@ impl Future for StreamStart { match stream.poll() { Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { retry = true; + let stream_ns = match stream_attrs.get("xmlns") { + Some(ns) => ns.clone(), + None => + return Err(Error::from(ErrorKind::InvalidData)), + }; // TODO: skip RecvFeatures for version < 1.0 - (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) + (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) }, Ok(Async::Ready(_)) => return Err(Error::from(ErrorKind::InvalidData)), @@ -73,22 +79,20 @@ impl Future for StreamStart { Err(e) => return Err(e), }, - StreamStartState::RecvFeatures(mut stream, stream_attrs) => + StreamStartState::RecvFeatures(mut stream, stream_ns) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => if stanza.name() == "features" && stanza.ns() == Some(NS_XMPP_STREAM) { - let stream = XMPPStream::new(self.jid.clone(), stream, stream_attrs, stanza); + let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), stanza); (StreamStartState::Invalid, Ok(Async::Ready(stream))) } else { - (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) + (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) }, - Ok(Async::Ready(item)) => { - println!("StreamStart skip {:?}", item); - (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)) - }, + Ok(Async::Ready(item)) => + (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), Ok(Async::NotReady) => - (StreamStartState::RecvFeatures(stream, stream_attrs), Ok(Async::NotReady)), + (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), Err(e) => return Err(e), }, diff --git a/src/tcp.rs b/src/tcp.rs deleted file mode 100644 index 156fa4f5cb600981dd75e73389df038580f81898..0000000000000000000000000000000000000000 --- a/src/tcp.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::net::SocketAddr; -use std::io::Error; -use futures::{Future, Poll, Async}; -use tokio_core::reactor::Handle; -use tokio_core::net::{TcpStream, TcpStreamNew}; -use jid::Jid; - -use xmpp_stream::XMPPStream; -use stream_start::StreamStart; - -pub struct TcpClient { - state: TcpClientState, - jid: Jid, -} - -enum TcpClientState { - Connecting(TcpStreamNew), - Start(StreamStart), - Established, -} - -impl TcpClient { - pub fn connect(jid: Jid, addr: &SocketAddr, handle: &Handle) -> Self { - let tcp_stream_new = TcpStream::connect(addr, handle); - TcpClient { - state: TcpClientState::Connecting(tcp_stream_new), - jid, - } - } - - pub fn from_stream(jid: Jid, tcp_stream: TcpStream) -> Self { - let start = XMPPStream::from_stream(tcp_stream, jid.clone()); - TcpClient { - state: TcpClientState::Start(start), - jid, - } - } -} - -impl Future for TcpClient { - type Item = XMPPStream; - type Error = Error; - - fn poll(&mut self) -> Poll { - let (new_state, result) = match self.state { - TcpClientState::Connecting(ref mut tcp_stream_new) => { - let tcp_stream = try_ready!(tcp_stream_new.poll()); - let start = XMPPStream::from_stream(tcp_stream, self.jid.clone()); - let new_state = TcpClientState::Start(start); - (new_state, Ok(Async::NotReady)) - }, - TcpClientState::Start(ref mut start) => { - let xmpp_stream = try_ready!(start.poll()); - let new_state = TcpClientState::Established; - (new_state, Ok(Async::Ready(xmpp_stream))) - }, - TcpClientState::Established => - unreachable!(), - }; - - self.state = new_state; - match result { - // by polling again, we register new future - Ok(Async::NotReady) => self.poll(), - result => result - } - } -} diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 7504dfff28baed3de4cab1a9dc61672886d8fcef..6686ed2b6c9b23b8a0f64f462e602ac63b07bc44 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -98,8 +98,8 @@ impl ParserSink { if self.stack.is_empty() { let attrs = HashMap::from_iter( - el.attrs() - .map(|(name, value)| (name.to_owned(), value.to_owned())) + tag.attrs.iter() + .map(|attr| (attr.name.local.as_ref().to_owned(), attr.value.as_ref().to_owned())) ); self.push_queue(Packet::StreamStart(attrs)); } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 9ff6916fad61c64483de126b40a7bbc20755f679..2b9c7aeac5a48c8a8bf3b78a3f1404079197f365 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use futures::{Poll, Stream, Sink, StartSend}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; @@ -13,21 +12,21 @@ pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; pub struct XMPPStream { pub jid: Jid, pub stream: Framed, - pub stream_attrs: HashMap, pub stream_features: Element, + pub ns: String, } impl XMPPStream { pub fn new(jid: Jid, stream: Framed, - stream_attrs: HashMap, + ns: String, stream_features: Element) -> Self { - XMPPStream { jid, stream, stream_attrs, stream_features } + XMPPStream { jid, stream, stream_features, ns } } - pub fn from_stream(stream: S, jid: Jid) -> StreamStart { + pub fn start(stream: S, jid: Jid, ns: String) -> StreamStart { let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new()); - StreamStart::from_stream(xmpp_stream, jid) + StreamStart::from_stream(xmpp_stream, jid, ns) } pub fn into_inner(self) -> S { @@ -35,7 +34,7 @@ impl XMPPStream { } pub fn restart(self) -> StreamStart { - Self::from_stream(self.stream.into_inner(), self.jid) + Self::start(self.stream.into_inner(), self.jid, self.ns) } } From 8850c95155196a9941bd27b920bad24be0f43d01 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 19 Jul 2017 01:32:53 +0200 Subject: [PATCH 041/135] happy_eyeballs: don't retain errored connects --- src/happy_eyeballs.rs | 26 ++++++++++++++++++++------ src/stream_start.rs | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index f529a87a7ba0f92b69702d2d623a36b1c85750f3..3cd42f4e615d0ad47514b4e93142266ef759f844 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -80,15 +80,29 @@ impl Future for Connecter { return Err(format!("{}", e)), } - for mut connect in self.connects.values_mut() { + let mut connected_stream = None; + self.connects.retain(|_, connect| { + if connected_stream.is_some() { + return false; + } + match connect.poll() { - Ok(Async::NotReady) => (), - Ok(Async::Ready(tcp_stream)) => + Ok(Async::NotReady) => true, + Ok(Async::Ready(tcp_stream)) => { // Success! - return Ok(Async::Ready(tcp_stream)), - Err(e) => - println!("{}", e), + connected_stream = Some(tcp_stream); + false + }, + Err(e) => { + println!("{}", e); + false + }, } + }); + match connected_stream { + Some(tcp_stream) => + return Ok(Async::Ready(tcp_stream)), + None => (), } if self.lookup.is_none() && diff --git a/src/stream_start.rs b/src/stream_start.rs index b194b5bb4f0e7b5353524a75e9c9602d9b159ceb..4d79d4d9286cd99d74c25f36846df4bae2806734 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -89,7 +89,7 @@ impl Future for StreamStart { } else { (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) }, - Ok(Async::Ready(item)) => + Ok(Async::Ready(_)) => (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), Ok(Async::NotReady) => (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), From 6ae3292d0c1b9735ca61d2efa30c89cb462a27a4 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 19 Jul 2017 01:57:46 +0200 Subject: [PATCH 042/135] add .travis.yml --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..9fdb54bc1da3ce5ba281caa0d4b8174685f26644 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +sudo: false + +language: rust + +rust: + - stable + - beta + - nightly From fc0973539f1a750f2a5a570c6b2a5dfcdfb9867d Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 19 Jul 2017 01:57:54 +0200 Subject: [PATCH 043/135] add README with TODOs --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ea4beac8ccdda18dc2359b507aaaf62ed5bd290e --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# TODO + +- [ ] Error type +- [ ] doc +- [ ] tests From 00e2daaecde9d203b6e4beabff9bf1c8b881f759 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Jul 2017 01:07:07 +0200 Subject: [PATCH 044/135] echo_bot: use xmpp-parsers to parse message --- examples/echo_bot.rs | 26 +++++++++++++------------- src/client/event.rs | 7 +++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index b3be75cd1a7e26189ae669f03ac51c43b5cd62f9..2307cdf643416b46a20b3ee50d7eaf3f64bdba05 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,3 +1,5 @@ +#![feature(try_from)] + extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; @@ -7,12 +9,14 @@ extern crate xmpp_parsers; use std::env::args; use std::process::exit; +use std::convert::TryFrom; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; -use xmpp_parsers::message::Message; +use xmpp_parsers::message::{Message, MessageType}; +use jid::Jid; fn main() { let args: Vec = args().collect(); @@ -50,15 +54,11 @@ fn main() { let presence = make_presence(); send(presence); - } else if let Some(stanza) = event.as_stanza() { - if stanza.name() == "message" && - stanza.attr("type") != Some("error") { + } else if let Some(stanza) = event.into_stanza() { + if let Ok(message) = Message::try_from(stanza) { + if message.type_ != MessageType::Error { // This is a message we'll echo - let from = stanza.attr("from"); - let body = stanza.get_child("body", "jabber:client") - .map(|el| el.text()); - - match (from, body) { + match (message.from, message.bodies.get("")) { (Some(from), Some(body)) => { let reply = make_reply(from, body); send(reply); @@ -66,6 +66,7 @@ fn main() { _ => (), }; } + } } Box::new(future::ok(())) @@ -90,9 +91,8 @@ fn make_presence() -> Element { } // Construct a chat -fn make_reply(to: &str, body: String) -> Element { - let jid = to.parse().unwrap(); - let mut message = Message::new(Some(jid)); - message.bodies.insert(String::new(), body); +fn make_reply(to: Jid, body: &str) -> Element { + let mut message = Message::new(Some(to)); + message.bodies.insert(String::new(), body.to_owned()); message.into() } diff --git a/src/client/event.rs b/src/client/event.rs index 7aba984a480ef6e44421c4f0da488f45577453f3..cae6ceaafa8bef99dbacd39db3bae778d126184c 100644 --- a/src/client/event.rs +++ b/src/client/event.rs @@ -28,4 +28,11 @@ impl Event { _ => None, } } + + pub fn into_stanza(self) -> Option { + match self { + Event::Stanza(stanza) => Some(stanza), + _ => None, + } + } } From 7cd31bd425efc599f1c54534cc2ad109dd07d14d Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 21 Jul 2017 00:19:08 +0200 Subject: [PATCH 045/135] delint (clippy) --- examples/echo_bot.rs | 23 +++++++++++------------ src/client/auth.rs | 9 +++------ src/client/bind.rs | 13 +++++-------- src/client/event.rs | 12 ++++++------ src/client/mod.rs | 9 +++------ src/happy_eyeballs.rs | 12 ++++-------- src/stream_start.rs | 4 +--- src/xmpp_codec.rs | 37 ++++++++++++++++++++++--------------- 8 files changed, 55 insertions(+), 64 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 2307cdf643416b46a20b3ee50d7eaf3f64bdba05..40b20ac95fb86f3fed6afd51a65a761b37f7fb24 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -54,18 +54,17 @@ fn main() { let presence = make_presence(); send(presence); - } else if let Some(stanza) = event.into_stanza() { - if let Ok(message) = Message::try_from(stanza) { - if message.type_ != MessageType::Error { - // This is a message we'll echo - match (message.from, message.bodies.get("")) { - (Some(from), Some(body)) => { - let reply = make_reply(from, body); - send(reply); - }, - _ => (), - }; - } + } else if let Some(message) = event.into_stanza() + .and_then(|stanza| Message::try_from(stanza).ok()) + { + // This is a message we'll echo + match (message.from, message.bodies.get("")) { + (Some(from), Some(body)) => + if message.type_ != MessageType::Error { + let reply = make_reply(from, body); + send(reply); + }, + _ => (), } } diff --git a/src/client/auth.rs b/src/client/auth.rs index dce2f86c831c38103f007c88c7dcb00730f0cec7..05006fdd5053fe7b767a448c08275b61ba7c48f1 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -130,12 +130,9 @@ impl Future for ClientAuth { if stanza.name() == "failure" && stanza.ns() == Some(NS_XMPP_SASL) => { - let mut e = None; - for child in stanza.children() { - e = Some(child.name().clone()); - break - } - let e = e.unwrap_or_else(|| "Authentication failure"); + let e = stanza.children().next() + .map(|child| child.name()) + .unwrap_or("Authentication failure"); Err(e.to_owned()) }, Ok(Async::Ready(event)) => { diff --git a/src/client/bind.rs b/src/client/bind.rs index 7800bbcca160a3acec647fa8cd9a64f20dee4dde..1541afd3543c4284cae66c45405d83869243c650 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -44,13 +44,10 @@ fn make_bind_request(resource: Option<&String>) -> Element { .attr("id", BIND_REQ_ID); let mut bind_el = Element::builder("bind") .ns(NS_XMPP_BIND); - match resource { - Some(resource) => { - let resource_el = Element::builder("resource") - .append(resource); - bind_el = bind_el.append(resource_el.build()); - }, - None => (), + if let Some(resource) = resource { + let resource_el = Element::builder("resource") + .append(resource); + bind_el = bind_el.append(resource_el.build()); } iq.append(bind_el.build()) .build() @@ -87,7 +84,7 @@ impl Future for ClientBind { && iq.attr("id") == Some(BIND_REQ_ID) => { match iq.attr("type") { Some("result") => { - get_bind_response_jid(&iq) + get_bind_response_jid(iq) .map(|jid| stream.jid = jid); Ok(Async::Ready(stream)) }, diff --git a/src/client/event.rs b/src/client/event.rs index cae6ceaafa8bef99dbacd39db3bae778d126184c..8ff44bd70a84ded7200eace6cea4055015a7e29a 100644 --- a/src/client/event.rs +++ b/src/client/event.rs @@ -9,22 +9,22 @@ pub enum Event { impl Event { pub fn is_online(&self) -> bool { - match self { - &Event::Online => true, + match *self { + Event::Online => true, _ => false, } } pub fn is_stanza(&self, name: &str) -> bool { - match self { - &Event::Stanza(ref stanza) => stanza.name() == name, + match *self { + Event::Stanza(ref stanza) => stanza.name() == name, _ => false, } } pub fn as_stanza(&self) -> Option<&Element> { - match self { - &Event::Stanza(ref stanza) => Some(stanza), + match *self { + Event::Stanza(ref stanza) => Some(stanza), _ => None, } } diff --git a/src/client/mod.rs b/src/client/mod.rs index aca0fdd20294cc45324a2492361eac8a12062a5b..b5d7e8fcef6b52554faff5f6c1f702471f169ca7 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -130,10 +130,6 @@ impl Stream for Client { }, ClientState::Connected(mut stream) => { match stream.poll() { - Ok(Async::NotReady) => { - self.state = ClientState::Connected(stream); - Ok(Async::NotReady) - }, Ok(Async::Ready(None)) => { // EOF self.state = ClientState::Disconnected; @@ -143,6 +139,7 @@ impl Stream for Client { self.state = ClientState::Connected(stream); Ok(Async::Ready(Some(ClientEvent::Stanza(stanza)))) }, + Ok(Async::NotReady) | Ok(Async::Ready(_)) => { self.state = ClientState::Connected(stream); Ok(Async::NotReady) @@ -179,8 +176,8 @@ impl Sink for Client { } fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { - match &mut self.state { - &mut ClientState::Connected(ref mut stream) => + match self.state { + ClientState::Connected(ref mut stream) => stream.poll_complete() .map_err(|e| e.description().to_owned()), _ => diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 3cd42f4e615d0ad47514b4e93142266ef759f844..806472c5d602b4b32e082841a997f7b8634cc0ed 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -46,8 +46,7 @@ impl Future for Connecter { fn poll(&mut self) -> Poll { match self.lookup.as_mut().map(|mut lookup| lookup.poll()) { - None => (), - Some(Ok(Async::NotReady)) => (), + None | Some(Ok(Async::NotReady)) => (), Some(Ok(Async::Ready(found_srvs))) => { self.lookup = None; match found_srvs { @@ -62,8 +61,7 @@ impl Future for Connecter { } match self.srvs.as_mut().map(|mut srv| srv.poll()) { - None => (), - Some(Ok(Async::NotReady)) => (), + None | Some(Ok(Async::NotReady)) => (), Some(Ok(Async::Ready(None))) => self.srvs = None, Some(Ok(Async::Ready(Some(srv_item)))) => { @@ -99,10 +97,8 @@ impl Future for Connecter { }, } }); - match connected_stream { - Some(tcp_stream) => - return Ok(Async::Ready(tcp_stream)), - None => (), + if let Some(tcp_stream) = connected_stream { + return Ok(Async::Ready(tcp_stream)); } if self.lookup.is_none() && diff --git a/src/stream_start.rs b/src/stream_start.rs index 4d79d4d9286cd99d74c25f36846df4bae2806734..b97e87d99d80ecbc734a1c848ab033180d2180a8 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -89,9 +89,7 @@ impl Future for StreamStart { } else { (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) }, - Ok(Async::Ready(_)) => - (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), - Ok(Async::NotReady) => + Ok(Async::Ready(_)) | Ok(Async::NotReady) => (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), Err(e) => return Err(e), diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 6686ed2b6c9b23b8a0f64f462e602ac63b07bc44..bb725835d57949a97e1be48cf82a8ff9dfc21994 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -48,9 +48,8 @@ impl ParserSink { fn lookup_ns(&self, prefix: &Option) -> Option<&str> { for nss in self.ns_stack.iter().rev() { - match nss.get(prefix) { - Some(ns) => return Some(ns), - None => (), + if let Some(ns) = nss.get(prefix) { + return Some(ns); } } @@ -77,9 +76,11 @@ impl ParserSink { let el = { let mut el_builder = Element::builder(tag.name.local.as_ref()); - match self.lookup_ns(&tag.name.prefix.map(|prefix| prefix.as_ref().to_owned())) { - Some(el_ns) => el_builder = el_builder.ns(el_ns), - None => (), + if let Some(el_ns) = self.lookup_ns( + &tag.name.prefix.map(|prefix| + prefix.as_ref().to_owned()) + ) { + el_builder = el_builder.ns(el_ns); } for attr in &tag.attrs { match attr.name.local.as_ref() { @@ -178,7 +179,7 @@ pub struct XMPPCodec { impl XMPPCodec { pub fn new() -> Self { - let queue = Rc::new(RefCell::new((VecDeque::new()))); + let queue = Rc::new(RefCell::new(VecDeque::new())); let sink = ParserSink::new(queue.clone()); // TODO: configure parser? let parser = XmlTokenizer::new(sink, Default::default()); @@ -191,13 +192,19 @@ impl XMPPCodec { } } +impl Default for XMPPCodec { + fn default() -> Self { + Self::new() + } +} + impl Decoder for XMPPCodec { type Item = Packet; type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { let buf1: Box> = - if self.buf.len() > 0 && buf.len() > 0 { + if ! self.buf.is_empty() && ! buf.is_empty() { let mut prefix = std::mem::replace(&mut self.buf, vec![]); prefix.extend_from_slice(buf.take().as_ref()); Box::new(prefix) @@ -207,7 +214,7 @@ impl Decoder for XMPPCodec { let buf1 = buf1.as_ref().as_ref(); match from_utf8(buf1) { Ok(s) => { - if s.len() > 0 { + if ! s.is_empty() { println!("<< {}", s); let tendril = FromIterator::from_iter(s.chars()); self.parser.feed(tendril); @@ -257,7 +264,7 @@ impl Encoder for XMPPCodec { Packet::StreamStart(start_attrs) => { let mut buf = String::new(); write!(buf, "(el: &Element, writer: &mut W, parent_ns: Option<& write!(writer, "<")?; write!(writer, "{}", el.name())?; - if let Some(ref ns) = el.ns() { + if let Some(ns) = el.ns() { if parent_ns.map(|s| s.as_ref()) != el.ns() { write!(writer, " xmlns=\"{}\"", ns)?; } @@ -320,10 +327,10 @@ pub fn write_element(el: &Element, writer: &mut W, parent_ns: Option<& write!(writer, ">")?; for node in el.nodes() { - match node { - &Node::Element(ref child) => + match *node { + Node::Element(ref child) => write_element(child, writer, el.ns())?, - &Node::Text(ref text) => + Node::Text(ref text) => write_text(text, writer)?, } } @@ -332,7 +339,7 @@ pub fn write_element(el: &Element, writer: &mut W, parent_ns: Option<& Ok(()) } -/// Copied from RustyXML for now +/// Copied from `RustyXML` for now pub fn escape(input: &str) -> String { let mut result = String::with_capacity(input.len()); From dc5ddc73f6cd776224ca8b9414871b07bfd690dd Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 21 Jul 2017 00:39:29 +0200 Subject: [PATCH 046/135] client: use idna --- Cargo.toml | 1 + src/client/mod.rs | 19 ++++++++++++++----- src/lib.rs | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cf7735a0e1f554f6b12dfdab56f76889eb6503a7..aacdbc4c0f9bcbd02d51ac8a6e8fb5215fd930f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ rustc-serialize = "*" jid = "*" domain = "0.2.1" xmpp-parsers = "0.6.0" +idna = "*" diff --git a/src/client/mod.rs b/src/client/mod.rs index b5d7e8fcef6b52554faff5f6c1f702471f169ca7..77641110d11a3c980714400faa7e180135d97125 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -5,10 +5,11 @@ use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; -use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; +use futures::{future, Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; use minidom::Element; use jid::{Jid, JidParseError}; use sasl::common::{Credentials, ChannelBinding}; +use idna; use super::xmpp_codec::Packet; use super::xmpp_stream; @@ -53,19 +54,27 @@ impl Client { let jid1 = jid.clone(); let jid2 = jid.clone(); let password = password; + let domain = match idna::domain_to_ascii(&jid.domain) { + Ok(domain) => + domain, + Err(e) => + return Box::new(future::err(format!("{:?}", e))), + }; Box::new( - Connecter::from_lookup(handle, &jid.domain, "_xmpp-client._tcp", 5222) + Connecter::from_lookup(handle, &domain, "_xmpp-client._tcp", 5222) .expect("Connector::from_lookup") .and_then(move |tcp_stream| xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) .map_err(|e| format!("{}", e)) ).and_then(|xmpp_stream| { if Self::can_starttls(&xmpp_stream) { - Self::starttls(xmpp_stream) + Ok(Self::starttls(xmpp_stream)) } else { - panic!("No STARTTLS") + Err("No STARTTLS".to_owned()) } - }).and_then(|tls_stream| + }).and_then(|starttls| + starttls + ).and_then(|tls_stream| XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) .map_err(|e| format!("{}", e)) ).and_then(move |xmpp_stream| { diff --git a/src/lib.rs b/src/lib.rs index 348c03b2b2f118a20fa856b1948331836b1a356e..ce8ccb7d7ceca60bb53f4514a48b024eeda18cdf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ extern crate sasl; extern crate rustc_serialize as serialize; extern crate jid; extern crate domain; +extern crate idna; pub mod xmpp_codec; pub mod xmpp_stream; From 430cd4b44d50f93cd630eaa37e9206c19e71e4f1 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 23 Jul 2017 02:04:46 +0200 Subject: [PATCH 047/135] README: TODO --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ea4beac8ccdda18dc2359b507aaaf62ed5bd290e..c3b636a02cd135b1efd309efdc4564b84a0c6c12 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # TODO +- [ ] minidom ns +- [ ] customize tls verify? - [ ] Error type +- [ ] unexpected event errors - [ ] doc - [ ] tests From c0f3fc4afbb78092cf48d1c62d3dd67de5ddc145 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 22 Jul 2017 01:59:51 +0100 Subject: [PATCH 048/135] lib: add a component connection method --- Cargo.toml | 2 + examples/echo_component.rs | 103 +++++++++++++++++++++++++ src/component/auth.rs | 101 ++++++++++++++++++++++++ src/component/event.rs | 38 +++++++++ src/component/mod.rs | 154 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 + src/stream_start.rs | 18 ++++- 7 files changed, 416 insertions(+), 3 deletions(-) create mode 100644 examples/echo_component.rs create mode 100644 src/component/auth.rs create mode 100644 src/component/event.rs create mode 100644 src/component/mod.rs diff --git a/Cargo.toml b/Cargo.toml index aacdbc4c0f9bcbd02d51ac8a6e8fb5215fd930f6..560305c8038cdd26bf5bc8057a3d1b0b265013fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,5 @@ jid = "*" domain = "0.2.1" xmpp-parsers = "0.6.0" idna = "*" +try_from = "0.2.2" +sha-1 = "0.4.1" diff --git a/examples/echo_component.rs b/examples/echo_component.rs new file mode 100644 index 0000000000000000000000000000000000000000..7ea1b7dd7577fa8b21a5f85d833ca45471b57afd --- /dev/null +++ b/examples/echo_component.rs @@ -0,0 +1,103 @@ +extern crate futures; +extern crate tokio_core; +extern crate tokio_xmpp; +extern crate jid; +extern crate minidom; +extern crate xmpp_parsers; +extern crate try_from; + +use std::env::args; +use std::process::exit; +use std::str::FromStr; +use try_from::TryFrom; +use tokio_core::reactor::Core; +use futures::{Future, Stream, Sink, future}; +use tokio_xmpp::Component; +use minidom::Element; +use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; +use xmpp_parsers::message::{Message, MessageType}; +use jid::Jid; + +fn main() { + let args: Vec = args().collect(); + if args.len() < 3 || args.len() > 5 { + println!("Usage: {} [server] [port]", args[0]); + exit(1); + } + let jid = &args[1]; + let password = &args[2]; + let server = &args.get(3).unwrap().parse().unwrap_or("127.0.0.1".to_owned()); + let port: u16 = args.get(4).unwrap().parse().unwrap_or(5347u16); + + // tokio_core context + let mut core = Core::new().unwrap(); + // Component instance + println!("{} {} {} {} {:?}", jid, password, server, port, core.handle()); + let component = Component::new(jid, password, server, port, core.handle()).unwrap(); + + // Make the two interfaces for sending and receiving independent + // of each other so we can move one into a closure. + println!("Got it: {}", component.jid); + let (sink, stream) = component.split(); + // Wrap sink in Option so that we can take() it for the send(self) + // to consume and return it back when ready. + let mut sink = Some(sink); + let mut send = move |stanza| { + sink = Some( + sink.take(). + expect("sink") + .send(stanza) + .wait() + .expect("sink.send") + ); + }; + // Main loop, processes events + let done = stream.for_each(|event| { + if event.is_online() { + println!("Online!"); + + let presence = make_presence(Jid::from_str("test@component.linkmauve.fr/coucou").unwrap(), Jid::from_str("linkmauve@linkmauve.fr").unwrap()); + send(presence); + } else if let Some(message) = event.into_stanza() + .and_then(|stanza| Message::try_from(stanza).ok()) + { + // This is a message we'll echo + match (message.from, message.bodies.get("")) { + (Some(from), Some(body)) => + if message.type_ != MessageType::Error { + let reply = make_reply(from, body); + send(reply); + }, + _ => (), + } + } + + Box::new(future::ok(())) + }); + + // Start polling `done` + match core.run(done) { + Ok(_) => (), + Err(e) => { + println!("Fatal: {}", e); + () + } + } +} + +// Construct a +fn make_presence(from: Jid, to: Jid) -> Element { + let mut presence = Presence::new(PresenceType::None); + presence.from = Some(from); + presence.to = Some(to); + presence.show = PresenceShow::Chat; + presence.statuses.insert(String::from("en"), String::from("Echoing messages.")); + presence.into() +} + +// Construct a chat +fn make_reply(to: Jid, body: &str) -> Element { + let mut message = Message::new(Some(to)); + message.bodies.insert(String::new(), body.to_owned()); + message.into() +} diff --git a/src/component/auth.rs b/src/component/auth.rs new file mode 100644 index 0000000000000000000000000000000000000000..773e453d68c2b26155698242d95c521068169d8a --- /dev/null +++ b/src/component/auth.rs @@ -0,0 +1,101 @@ +use std::mem::replace; +use futures::{Future, Poll, Async, sink, Sink, Stream}; +use tokio_io::{AsyncRead, AsyncWrite}; +use minidom::Element; +use sha_1::{Sha1, Digest}; + +use xmpp_codec::Packet; +use xmpp_stream::XMPPStream; + +const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; + +pub struct ComponentAuth { + state: ComponentAuthState, +} + +enum ComponentAuthState { + WaitSend(sink::Send>), + WaitRecv(XMPPStream), + Invalid, +} + +impl ComponentAuth { + pub fn new(stream: XMPPStream, password: String) -> Result { + // FIXME: huge hack, shouldn’t be an element! + let sid = stream.stream_features.name().to_owned(); + let mut this = ComponentAuth { + state: ComponentAuthState::Invalid, + }; + this.send( + stream, + "handshake", + // TODO: sha1(sid + password) + &format!("{:x}", Sha1::digest((sid + &password).as_bytes())) + ); + return Ok(this); + } + + fn send(&mut self, stream: XMPPStream, nonza_name: &str, handshake: &str) { + let nonza = Element::builder(nonza_name) + .ns(NS_JABBER_COMPONENT_ACCEPT) + .append(handshake) + .build(); + + let send = stream.send(Packet::Stanza(nonza)); + + self.state = ComponentAuthState::WaitSend(send); + } +} + +impl Future for ComponentAuth { + type Item = XMPPStream; + type Error = String; + + fn poll(&mut self) -> Poll { + let state = replace(&mut self.state, ComponentAuthState::Invalid); + + match state { + ComponentAuthState::WaitSend(mut send) => + match send.poll() { + Ok(Async::Ready(stream)) => { + self.state = ComponentAuthState::WaitRecv(stream); + self.poll() + }, + Ok(Async::NotReady) => { + self.state = ComponentAuthState::WaitSend(send); + Ok(Async::NotReady) + }, + Err(e) => + Err(format!("{}", e)), + }, + ComponentAuthState::WaitRecv(mut stream) => + match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name() == "handshake" + && stanza.ns() == Some(NS_JABBER_COMPONENT_ACCEPT) => + { + self.state = ComponentAuthState::Invalid; + Ok(Async::Ready(stream)) + }, + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.is("error", "http://etherx.jabber.org/streams") => + { + let e = "Authentication failure"; + Err(e.to_owned()) + }, + Ok(Async::Ready(event)) => { + println!("ComponentAuth ignore {:?}", event); + Ok(Async::NotReady) + }, + Ok(_) => { + self.state = ComponentAuthState::WaitRecv(stream); + Ok(Async::NotReady) + }, + Err(e) => + Err(format!("{}", e)), + }, + ComponentAuthState::Invalid => + unreachable!(), + } + } +} diff --git a/src/component/event.rs b/src/component/event.rs new file mode 100644 index 0000000000000000000000000000000000000000..8ff44bd70a84ded7200eace6cea4055015a7e29a --- /dev/null +++ b/src/component/event.rs @@ -0,0 +1,38 @@ +use minidom::Element; + +#[derive(Debug)] +pub enum Event { + Online, + Disconnected, + Stanza(Element), +} + +impl Event { + pub fn is_online(&self) -> bool { + match *self { + Event::Online => true, + _ => false, + } + } + + pub fn is_stanza(&self, name: &str) -> bool { + match *self { + Event::Stanza(ref stanza) => stanza.name() == name, + _ => false, + } + } + + pub fn as_stanza(&self) -> Option<&Element> { + match *self { + Event::Stanza(ref stanza) => Some(stanza), + _ => None, + } + } + + pub fn into_stanza(self) -> Option { + match self { + Event::Stanza(stanza) => Some(stanza), + _ => None, + } + } +} diff --git a/src/component/mod.rs b/src/component/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..95790f000546e2e2a851583332411a90af179257 --- /dev/null +++ b/src/component/mod.rs @@ -0,0 +1,154 @@ +use std::mem::replace; +use std::str::FromStr; +use std::error::Error; +use tokio_core::reactor::Handle; +use tokio_core::net::TcpStream; +use tokio_io::{AsyncRead, AsyncWrite}; +use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; +use minidom::Element; +use jid::{Jid, JidParseError}; + +use super::xmpp_codec::Packet; +use super::xmpp_stream; +use super::happy_eyeballs::Connecter; + +mod auth; +use self::auth::ComponentAuth; +mod event; +pub use self::event::Event as ComponentEvent; + +pub struct Component { + pub jid: Jid, + state: ComponentState, +} + +type XMPPStream = xmpp_stream::XMPPStream; +const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; + +enum ComponentState { + Invalid, + Disconnected, + Connecting(Box>), + Connected(XMPPStream), +} + +impl Component { + pub fn new(jid: &str, password: &str, server: &str, port: u16, handle: Handle) -> Result { + let jid = try!(Jid::from_str(jid)); + let password = password.to_owned(); + let connect = Self::make_connect(jid.clone(), password, server, port, handle); + Ok(Component { + jid, + state: ComponentState::Connecting(connect), + }) + } + + fn make_connect(jid: Jid, password: String, server: &str, port: u16, handle: Handle) -> Box> { + let jid1 = jid.clone(); + let password = password; + Box::new( + Connecter::from_lookup(handle, server, "_xmpp-component._tcp", port) + .expect("Connector::from_lookup") + .and_then(move |tcp_stream| { + xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) + .map_err(|e| format!("{}", e)) + }).and_then(move |xmpp_stream| { + Self::auth(xmpp_stream, password).expect("auth") + }).and_then(|xmpp_stream| { + println!("Bound to {}", xmpp_stream.jid); + Ok(xmpp_stream) + }) + ) + } + + fn auth(stream: xmpp_stream::XMPPStream, password: String) -> Result, String> { + ComponentAuth::new(stream, password) + } +} + +impl Stream for Component { + type Item = ComponentEvent; + type Error = String; + + fn poll(&mut self) -> Poll, Self::Error> { + let state = replace(&mut self.state, ComponentState::Invalid); + + match state { + ComponentState::Invalid => + Err("invalid client state".to_owned()), + ComponentState::Disconnected => + Ok(Async::Ready(None)), + ComponentState::Connecting(mut connect) => { + match connect.poll() { + Ok(Async::Ready(stream)) => { + self.state = ComponentState::Connected(stream); + Ok(Async::Ready(Some(ComponentEvent::Online))) + }, + Ok(Async::NotReady) => { + self.state = ComponentState::Connecting(connect); + Ok(Async::NotReady) + }, + Err(e) => + Err(e), + } + }, + ComponentState::Connected(mut stream) => { + match stream.poll() { + Ok(Async::NotReady) => { + self.state = ComponentState::Connected(stream); + Ok(Async::NotReady) + }, + Ok(Async::Ready(None)) => { + // EOF + self.state = ComponentState::Disconnected; + Ok(Async::Ready(Some(ComponentEvent::Disconnected))) + }, + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + self.state = ComponentState::Connected(stream); + Ok(Async::Ready(Some(ComponentEvent::Stanza(stanza)))) + }, + Ok(Async::Ready(_)) => { + self.state = ComponentState::Connected(stream); + Ok(Async::NotReady) + }, + Err(e) => + Err(e.description().to_owned()), + } + }, + } + } +} + +impl Sink for Component { + type SinkItem = Element; + type SinkError = String; + + fn start_send(&mut self, item: Self::SinkItem) -> StartSend { + match self.state { + ComponentState::Connected(ref mut stream) => + match stream.start_send(Packet::Stanza(item)) { + Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => + Ok(AsyncSink::NotReady(stanza)), + Ok(AsyncSink::NotReady(_)) => + panic!("Component.start_send with stanza but got something else back"), + Ok(AsyncSink::Ready) => { + Ok(AsyncSink::Ready) + }, + Err(e) => + Err(e.description().to_owned()), + }, + _ => + Ok(AsyncSink::NotReady(item)), + } + } + + fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { + match &mut self.state { + &mut ComponentState::Connected(ref mut stream) => + stream.poll_complete() + .map_err(|e| e.description().to_owned()), + _ => + Ok(Async::Ready(())), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index ce8ccb7d7ceca60bb53f4514a48b024eeda18cdf..81f3b1c6ac4d9ff63c6cc4796f50fad95d0a5e2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ extern crate rustc_serialize as serialize; extern crate jid; extern crate domain; extern crate idna; +extern crate sha_1; pub mod xmpp_codec; pub mod xmpp_stream; @@ -21,3 +22,5 @@ pub use starttls::StartTlsClient; mod happy_eyeballs; mod client; pub use client::{Client, ClientEvent}; +mod component; +pub use component::{Component, ComponentEvent}; diff --git a/src/stream_start.rs b/src/stream_start.rs index b97e87d99d80ecbc734a1c848ab033180d2180a8..1d1813a383209784d6e367b0f17901527db3434a 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -4,6 +4,7 @@ use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use jid::Jid; +use minidom::Element; use xmpp_codec::{XMPPCodec, Packet}; use xmpp_stream::XMPPStream; @@ -63,14 +64,25 @@ impl Future for StreamStart { StreamStartState::RecvStart(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { - retry = true; let stream_ns = match stream_attrs.get("xmlns") { Some(ns) => ns.clone(), None => return Err(Error::from(ErrorKind::InvalidData)), }; - // TODO: skip RecvFeatures for version < 1.0 - (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) + if self.ns == "jabber:client" { + retry = true; + // TODO: skip RecvFeatures for version < 1.0 + (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) + } else { + let id = match stream_attrs.get("id") { + Some(id) => id.clone(), + None => + return Err(Error::from(ErrorKind::InvalidData)), + }; + // FIXME: huge hack, shouldn’t be an element! + let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), Element::builder(id).build()); + (StreamStartState::Invalid, Ok(Async::Ready(stream))) + } }, Ok(Async::Ready(_)) => return Err(Error::from(ErrorKind::InvalidData)), From 993fdcab8f85e14f999871da85c0c975402b6c37 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 23 Jul 2017 02:46:47 +0200 Subject: [PATCH 049/135] unify Client::Event and Component::Event into Event --- src/client/mod.rs | 11 +++++------ src/component/event.rs | 38 -------------------------------------- src/component/mod.rs | 11 +++++------ src/{client => }/event.rs | 0 src/lib.rs | 6 ++++-- 5 files changed, 14 insertions(+), 52 deletions(-) delete mode 100644 src/component/event.rs rename src/{client => }/event.rs (100%) diff --git a/src/client/mod.rs b/src/client/mod.rs index 77641110d11a3c980714400faa7e180135d97125..e814f9b6e269f2ac978db41dcd91d769211dc19c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -15,13 +15,12 @@ use super::xmpp_codec::Packet; use super::xmpp_stream; use super::starttls::{NS_XMPP_TLS, StartTlsClient}; use super::happy_eyeballs::Connecter; +use super::event::Event; mod auth; use self::auth::ClientAuth; mod bind; use self::bind::ClientBind; -mod event; -pub use self::event::Event as ClientEvent; pub struct Client { pub jid: Jid, @@ -112,7 +111,7 @@ impl Client { } impl Stream for Client { - type Item = ClientEvent; + type Item = Event; type Error = String; fn poll(&mut self) -> Poll, Self::Error> { @@ -127,7 +126,7 @@ impl Stream for Client { match connect.poll() { Ok(Async::Ready(stream)) => { self.state = ClientState::Connected(stream); - Ok(Async::Ready(Some(ClientEvent::Online))) + Ok(Async::Ready(Some(Event::Online))) }, Ok(Async::NotReady) => { self.state = ClientState::Connecting(connect); @@ -142,11 +141,11 @@ impl Stream for Client { Ok(Async::Ready(None)) => { // EOF self.state = ClientState::Disconnected; - Ok(Async::Ready(Some(ClientEvent::Disconnected))) + Ok(Async::Ready(Some(Event::Disconnected))) }, Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { self.state = ClientState::Connected(stream); - Ok(Async::Ready(Some(ClientEvent::Stanza(stanza)))) + Ok(Async::Ready(Some(Event::Stanza(stanza)))) }, Ok(Async::NotReady) | Ok(Async::Ready(_)) => { diff --git a/src/component/event.rs b/src/component/event.rs deleted file mode 100644 index 8ff44bd70a84ded7200eace6cea4055015a7e29a..0000000000000000000000000000000000000000 --- a/src/component/event.rs +++ /dev/null @@ -1,38 +0,0 @@ -use minidom::Element; - -#[derive(Debug)] -pub enum Event { - Online, - Disconnected, - Stanza(Element), -} - -impl Event { - pub fn is_online(&self) -> bool { - match *self { - Event::Online => true, - _ => false, - } - } - - pub fn is_stanza(&self, name: &str) -> bool { - match *self { - Event::Stanza(ref stanza) => stanza.name() == name, - _ => false, - } - } - - pub fn as_stanza(&self) -> Option<&Element> { - match *self { - Event::Stanza(ref stanza) => Some(stanza), - _ => None, - } - } - - pub fn into_stanza(self) -> Option { - match self { - Event::Stanza(stanza) => Some(stanza), - _ => None, - } - } -} diff --git a/src/component/mod.rs b/src/component/mod.rs index 95790f000546e2e2a851583332411a90af179257..2964700ffefa4268ca45cb6cea50b6faec809c18 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -11,11 +11,10 @@ use jid::{Jid, JidParseError}; use super::xmpp_codec::Packet; use super::xmpp_stream; use super::happy_eyeballs::Connecter; +use super::event::Event; mod auth; use self::auth::ComponentAuth; -mod event; -pub use self::event::Event as ComponentEvent; pub struct Component { pub jid: Jid, @@ -67,7 +66,7 @@ impl Component { } impl Stream for Component { - type Item = ComponentEvent; + type Item = Event; type Error = String; fn poll(&mut self) -> Poll, Self::Error> { @@ -82,7 +81,7 @@ impl Stream for Component { match connect.poll() { Ok(Async::Ready(stream)) => { self.state = ComponentState::Connected(stream); - Ok(Async::Ready(Some(ComponentEvent::Online))) + Ok(Async::Ready(Some(Event::Online))) }, Ok(Async::NotReady) => { self.state = ComponentState::Connecting(connect); @@ -101,11 +100,11 @@ impl Stream for Component { Ok(Async::Ready(None)) => { // EOF self.state = ComponentState::Disconnected; - Ok(Async::Ready(Some(ComponentEvent::Disconnected))) + Ok(Async::Ready(Some(Event::Disconnected))) }, Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { self.state = ComponentState::Connected(stream); - Ok(Async::Ready(Some(ComponentEvent::Stanza(stanza)))) + Ok(Async::Ready(Some(Event::Stanza(stanza)))) }, Ok(Async::Ready(_)) => { self.state = ComponentState::Connected(stream); diff --git a/src/client/event.rs b/src/event.rs similarity index 100% rename from src/client/event.rs rename to src/event.rs diff --git a/src/lib.rs b/src/lib.rs index 81f3b1c6ac4d9ff63c6cc4796f50fad95d0a5e2d..ddb4f9a3b1bd2704c32775ba5d73da3e3223f4d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,9 @@ mod stream_start; mod starttls; pub use starttls::StartTlsClient; mod happy_eyeballs; +mod event; +pub use event::Event; mod client; -pub use client::{Client, ClientEvent}; +pub use client::Client; mod component; -pub use component::{Component, ComponentEvent}; +pub use component::Component; From a204e667098c13ceee8e16630b7426a11c7f93ef Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 23 Jul 2017 02:47:07 +0200 Subject: [PATCH 050/135] echo_component: TODO --- examples/echo_component.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 7ea1b7dd7577fa8b21a5f85d833ca45471b57afd..076bb170c8245a1f9e25f04ede365793eecf350f 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -56,6 +56,7 @@ fn main() { if event.is_online() { println!("Online!"); + // TODO: replace these hardcoded JIDs let presence = make_presence(Jid::from_str("test@component.linkmauve.fr/coucou").unwrap(), Jid::from_str("linkmauve@linkmauve.fr").unwrap()); send(presence); } else if let Some(message) = event.into_stanza() From 6e506fbc57313fd14d0dbe78e46559b8e477807c Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 23 Jul 2017 19:03:29 +0100 Subject: [PATCH 051/135] Cargo.toml, echo_bot: update xmpp-parsers to 0.7.0 --- Cargo.toml | 2 +- examples/echo_bot.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 560305c8038cdd26bf5bc8057a3d1b0b265013fc..42de0ff804c0b34695d93dec85134267c985372a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ sasl = "*" rustc-serialize = "*" jid = "*" domain = "0.2.1" -xmpp-parsers = "0.6.0" +xmpp-parsers = "0.7.0" idna = "*" try_from = "0.2.2" sha-1 = "0.4.1" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 40b20ac95fb86f3fed6afd51a65a761b37f7fb24..3f6a4ab52d9e316fd117b9eaa240679b99998a63 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,15 +1,14 @@ -#![feature(try_from)] - extern crate futures; extern crate tokio_core; extern crate tokio_xmpp; extern crate jid; extern crate minidom; extern crate xmpp_parsers; +extern crate try_from; use std::env::args; use std::process::exit; -use std::convert::TryFrom; +use try_from::TryFrom; use tokio_core::reactor::Core; use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; From ff165d745d27bb06c144eac9e5073e22524e8359 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 23 Jul 2017 23:53:08 +0200 Subject: [PATCH 052/135] Cargo.toml: update minidom to 0.4.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 42de0ff804c0b34695d93dec85134267c985372a..b5d8eeeaa5e0944241f805fa3b280efc73d084af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = "0.4.3" +minidom = "0.4.4" native-tls = "*" tokio-tls = "*" sasl = "*" From 0743249280446bc910eb8fd9062d59f651f23865 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 14 Aug 2017 03:56:08 +0200 Subject: [PATCH 053/135] migrate to minidom 0.6.0 --- Cargo.toml | 2 +- src/client/auth.rs | 9 ++---- src/component/auth.rs | 3 +- src/stream_start.rs | 3 +- src/xmpp_codec.rs | 67 ++++++++++++++++++------------------------- 5 files changed, 34 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5d8eeeaa5e0944241f805fa3b280efc73d084af..c6cd33b70c4d0891e5cae5b16e4064f7db320d65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = "0.4.4" +minidom = "0.6.0" native-tls = "*" tokio-tls = "*" sasl = "*" diff --git a/src/client/auth.rs b/src/client/auth.rs index 05006fdd5053fe7b767a448c08275b61ba7c48f1..ef828b37a479e0b8a74bf1e21eced63eaeb7c1d3 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -106,8 +106,7 @@ impl Future for ClientAuth { ClientAuthState::WaitRecv(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name() == "challenge" - && stanza.ns() == Some(NS_XMPP_SASL) => + if stanza.is("challenge", NS_XMPP_SASL) => { let content = try!( stanza.text() @@ -119,16 +118,14 @@ impl Future for ClientAuth { self.poll() }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name() == "success" - && stanza.ns() == Some(NS_XMPP_SASL) => + if stanza.is("success", NS_XMPP_SASL) => { let start = stream.restart(); self.state = ClientAuthState::Start(start); self.poll() }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name() == "failure" - && stanza.ns() == Some(NS_XMPP_SASL) => + if stanza.is("failure", NS_XMPP_SASL) => { let e = stanza.children().next() .map(|child| child.name()) diff --git a/src/component/auth.rs b/src/component/auth.rs index 773e453d68c2b26155698242d95c521068169d8a..729fd3c12652d182cf94f7ca43bdbc43720a9636 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -71,8 +71,7 @@ impl Future for ComponentAuth { ComponentAuthState::WaitRecv(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name() == "handshake" - && stanza.ns() == Some(NS_JABBER_COMPONENT_ACCEPT) => + if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) => { self.state = ComponentAuthState::Invalid; Ok(Async::Ready(stream)) diff --git a/src/stream_start.rs b/src/stream_start.rs index 1d1813a383209784d6e367b0f17901527db3434a..5dda29aea435ac1add25bf0d02c65339667f899b 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -94,8 +94,7 @@ impl Future for StreamStart { StreamStartState::RecvFeatures(mut stream, stream_ns) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => - if stanza.name() == "features" - && stanza.ns() == Some(NS_XMPP_STREAM) { + if stanza.is("features", NS_XMPP_STREAM) { let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), stanza); (StreamStartState::Invalid, Ok(Async::Ready(stream))) } else { diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index bb725835d57949a97e1be48cf82a8ff9dfc21994..5e340a9fb5177f18c37667b4fd071bc1a64b865d 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -9,7 +9,7 @@ use std::io::{Error, ErrorKind}; use std::collections::HashMap; use std::collections::vec_deque::VecDeque; use tokio_io::codec::{Encoder, Decoder}; -use minidom::{Element, Node}; +use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; @@ -278,8 +278,7 @@ impl Encoder for XMPPCodec { .map_err(|e| Error::new(ErrorKind::InvalidInput, e)) }, Packet::Stanza(stanza) => { - let root_ns = self.ns.as_ref().map(|s| s.as_ref()); - write_element(&stanza, dst, root_ns) + stanza.write_to_inner(&mut WriteBytes::new(dst)) .and_then(|_| { println!(">> {:?}", dst); Ok(()) @@ -301,42 +300,7 @@ impl Encoder for XMPPCodec { } pub fn write_text(text: &str, writer: &mut W) -> Result<(), std::fmt::Error> { - write!(writer, "{}", text) -} - -// TODO: escape everything? -pub fn write_element(el: &Element, writer: &mut W, parent_ns: Option<&str>) -> Result<(), std::fmt::Error> { - write!(writer, "<")?; - write!(writer, "{}", el.name())?; - - if let Some(ns) = el.ns() { - if parent_ns.map(|s| s.as_ref()) != el.ns() { - write!(writer, " xmlns=\"{}\"", ns)?; - } - } - - for (key, value) in el.attrs() { - write!(writer, " {}=\"{}\"", key, value)?; - } - - if ! el.nodes().any(|_| true) { - write!(writer, " />")?; - return Ok(()) - } - - write!(writer, ">")?; - - for node in el.nodes() { - match *node { - Node::Element(ref child) => - write_element(child, writer, el.ns())?, - Node::Text(ref text) => - write_text(text, writer)?, - } - } - - write!(writer, "", el.name())?; - Ok(()) + write!(writer, "{}", escape(text)) } /// Copied from `RustyXML` for now @@ -356,6 +320,31 @@ pub fn escape(input: &str) -> String { result } +/// BytesMut impl only std::fmt::Write but not std::io::Write. The +/// latter trait is required for minidom's +/// `Element::write_to_inner()`. +struct WriteBytes<'a> { + dst: &'a mut BytesMut, +} + +impl<'a> WriteBytes<'a> { + fn new(dst: &'a mut BytesMut) -> Self { + WriteBytes { dst } + } +} + +impl<'a> std::io::Write for WriteBytes<'a> { + fn write(&mut self, buf: &[u8]) -> std::result::Result { + self.dst.put_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::result::Result<(), std::io::Error> { + Ok(()) + } +} + + #[cfg(test)] mod tests { use super::*; From b83905dc96c1174c362622eae12c2e18d438b3f9 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 15 Aug 2017 00:27:40 +0200 Subject: [PATCH 054/135] update to newer jid --- Cargo.toml | 2 +- examples/echo_bot.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c6cd33b70c4d0891e5cae5b16e4064f7db320d65..b6c9a710268fb7cb6a3065c7c60b4f4f71b18d60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ native-tls = "*" tokio-tls = "*" sasl = "*" rustc-serialize = "*" -jid = "*" +jid = { version = "0.2.3", features = ["minidom"] } domain = "0.2.1" xmpp-parsers = "0.7.0" idna = "*" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 3f6a4ab52d9e316fd117b9eaa240679b99998a63..2cb09a913c8c05f52b92bc95a7e47c5a7989e5eb 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -14,7 +14,7 @@ use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Client; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; -use xmpp_parsers::message::{Message, MessageType}; +use xmpp_parsers::message::{Message, MessageType, Body}; use jid::Jid; fn main() { @@ -60,7 +60,7 @@ fn main() { match (message.from, message.bodies.get("")) { (Some(from), Some(body)) => if message.type_ != MessageType::Error { - let reply = make_reply(from, body); + let reply = make_reply(from, &body.0); send(reply); }, _ => (), @@ -91,6 +91,6 @@ fn make_presence() -> Element { // Construct a chat fn make_reply(to: Jid, body: &str) -> Element { let mut message = Message::new(Some(to)); - message.bodies.insert(String::new(), body.to_owned()); + message.bodies.insert(String::new(), Body(body.to_owned())); message.into() } From a92e7a0ff744ca5de7076f37741be830b93bb3f0 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 24 Aug 2017 19:54:33 +0200 Subject: [PATCH 055/135] update deps --- Cargo.toml | 6 +++--- examples/echo_component.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b6c9a710268fb7cb6a3065c7c60b4f4f71b18d60..89e07ba02f67e12b701dcf4447ebc039e9e15e50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,14 +10,14 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = "0.6.0" +minidom = "0.6.1" native-tls = "*" tokio-tls = "*" sasl = "*" rustc-serialize = "*" -jid = { version = "0.2.3", features = ["minidom"] } +jid = { version = "0.3.0", features = ["minidom"] } domain = "0.2.1" -xmpp-parsers = "0.7.0" +xmpp-parsers = "0.7.2" idna = "*" try_from = "0.2.2" sha-1 = "0.4.1" diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 076bb170c8245a1f9e25f04ede365793eecf350f..ab385732b19b0c848a25c99f36fb0230e487ca9a 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -15,7 +15,7 @@ use futures::{Future, Stream, Sink, future}; use tokio_xmpp::Component; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; -use xmpp_parsers::message::{Message, MessageType}; +use xmpp_parsers::message::{Message, MessageType, Body}; use jid::Jid; fn main() { @@ -66,7 +66,7 @@ fn main() { match (message.from, message.bodies.get("")) { (Some(from), Some(body)) => if message.type_ != MessageType::Error { - let reply = make_reply(from, body); + let reply = make_reply(from, &body.0); send(reply); }, _ => (), @@ -99,6 +99,6 @@ fn make_presence(from: Jid, to: Jid) -> Element { // Construct a chat fn make_reply(to: Jid, body: &str) -> Element { let mut message = Message::new(Some(to)); - message.bodies.insert(String::new(), body.to_owned()); + message.bodies.insert(String::new(), Body(body.to_owned())); message.into() } From 58b5a84391399b31be551371e1986541df873e41 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 24 Aug 2017 20:10:58 +0200 Subject: [PATCH 056/135] client: stream.poll_complete() for ease of use --- examples/echo_bot.rs | 13 +++---------- examples/echo_component.rs | 13 +++---------- src/client/mod.rs | 9 +++++++++ src/component/mod.rs | 9 +++++++++ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 2cb09a913c8c05f52b92bc95a7e47c5a7989e5eb..462f7fe870f1af721d32837b26db62f8e093a922 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -10,7 +10,7 @@ use std::env::args; use std::process::exit; use try_from::TryFrom; use tokio_core::reactor::Core; -use futures::{Future, Stream, Sink, future}; +use futures::{Stream, Sink, future}; use tokio_xmpp::Client; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; @@ -33,18 +33,11 @@ fn main() { // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. - let (sink, stream) = client.split(); + let (mut sink, stream) = client.split(); // Wrap sink in Option so that we can take() it for the send(self) // to consume and return it back when ready. - let mut sink = Some(sink); let mut send = move |stanza| { - sink = Some( - sink.take(). - expect("sink") - .send(stanza) - .wait() - .expect("sink.send") - ); + sink.start_send(stanza).expect("start_send"); }; // Main loop, processes events let done = stream.for_each(|event| { diff --git a/examples/echo_component.rs b/examples/echo_component.rs index ab385732b19b0c848a25c99f36fb0230e487ca9a..745e0771a6e50514100f0a25db28a5878abf3062 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -11,7 +11,7 @@ use std::process::exit; use std::str::FromStr; use try_from::TryFrom; use tokio_core::reactor::Core; -use futures::{Future, Stream, Sink, future}; +use futures::{Stream, Sink, future}; use tokio_xmpp::Component; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; @@ -38,18 +38,11 @@ fn main() { // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. println!("Got it: {}", component.jid); - let (sink, stream) = component.split(); + let (mut sink, stream) = component.split(); // Wrap sink in Option so that we can take() it for the send(self) // to consume and return it back when ready. - let mut sink = Some(sink); let mut send = move |stanza| { - sink = Some( - sink.take(). - expect("sink") - .send(stanza) - .wait() - .expect("sink.send") - ); + sink.start_send(stanza).expect("start_send"); }; // Main loop, processes events let done = stream.for_each(|event| { diff --git a/src/client/mod.rs b/src/client/mod.rs index e814f9b6e269f2ac978db41dcd91d769211dc19c..dc948fa5e0b3e3ef35097f2e77842c99158dbcc5 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -137,6 +137,15 @@ impl Stream for Client { } }, ClientState::Connected(mut stream) => { + // Poll sink + match stream.poll_complete() { + Ok(Async::NotReady) => (), + Ok(Async::Ready(())) => (), + Err(e) => + return Err(e.description().to_owned()), + }; + + // Poll stream match stream.poll() { Ok(Async::Ready(None)) => { // EOF diff --git a/src/component/mod.rs b/src/component/mod.rs index 2964700ffefa4268ca45cb6cea50b6faec809c18..04613c50350817bc2db133e68f09ac2f90b79e84 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -92,6 +92,15 @@ impl Stream for Component { } }, ComponentState::Connected(mut stream) => { + // Poll sink + match stream.poll_complete() { + Ok(Async::NotReady) => (), + Ok(Async::Ready(())) => (), + Err(e) => + return Err(e.description().to_owned()), + }; + + // Poll stream match stream.poll() { Ok(Async::NotReady) => { self.state = ComponentState::Connected(stream); From 1a46449c16d5a06783514cd14c1958e6f9021343 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 28 Aug 2017 21:00:59 +0200 Subject: [PATCH 057/135] Cargo.toml: update xmpp-parsers from 0.7.2 to 0.8.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 89e07ba02f67e12b701dcf4447ebc039e9e15e50..e8386b53b9da8fbce9e9dc85dc012950365ebda8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ sasl = "*" rustc-serialize = "*" jid = { version = "0.3.0", features = ["minidom"] } domain = "0.2.1" -xmpp-parsers = "0.7.2" +xmpp-parsers = "0.8.0" idna = "*" try_from = "0.2.2" sha-1 = "0.4.1" From 6ac5bb99dbe1d3392d621e34432e2993bdba2e26 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 22 Feb 2018 19:56:56 +0100 Subject: [PATCH 058/135] happy_eyeballs: fix two mut warnings --- src/happy_eyeballs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 806472c5d602b4b32e082841a997f7b8634cc0ed..f2cd1a62d6e18deb7337d301a6617c20cde06ed6 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -45,7 +45,7 @@ impl Future for Connecter { type Error = String; fn poll(&mut self) -> Poll { - match self.lookup.as_mut().map(|mut lookup| lookup.poll()) { + match self.lookup.as_mut().map(|lookup| lookup.poll()) { None | Some(Ok(Async::NotReady)) => (), Some(Ok(Async::Ready(found_srvs))) => { self.lookup = None; @@ -60,7 +60,7 @@ impl Future for Connecter { return Err(format!("{}", e)), } - match self.srvs.as_mut().map(|mut srv| srv.poll()) { + match self.srvs.as_mut().map(|srv| srv.poll()) { None | Some(Ok(Async::NotReady)) => (), Some(Ok(Async::Ready(None))) => self.srvs = None, From 772c6b56ee4e487b8f162f0f80e735a27dce4df2 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 22 Feb 2018 20:05:41 +0100 Subject: [PATCH 059/135] update dependencies --- Cargo.toml | 9 +++++---- src/component/auth.rs | 2 +- src/lib.rs | 3 ++- src/xmpp_codec.rs | 3 ++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8386b53b9da8fbce9e9dc85dc012950365ebda8..b664112a7b3a326927c4c32c861c74c5102f53f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,14 +10,15 @@ tokio-io = "*" bytes = "0.4.4" xml5ever = "*" tendril = "*" -minidom = "0.6.1" +minidom = "0.8.0" native-tls = "*" tokio-tls = "*" sasl = "*" rustc-serialize = "*" -jid = { version = "0.3.0", features = ["minidom"] } +jid = { version = "0.5.0", features = ["minidom"] } domain = "0.2.1" -xmpp-parsers = "0.8.0" +xmpp-parsers = "0.10.0" idna = "*" try_from = "0.2.2" -sha-1 = "0.4.1" +sha-1 = "0.7.0" +quick-xml = "*" diff --git a/src/component/auth.rs b/src/component/auth.rs index 729fd3c12652d182cf94f7ca43bdbc43720a9636..bd1c9aa7000e444bbf73faa13ffd00a21ae5a283 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -2,7 +2,7 @@ use std::mem::replace; use futures::{Future, Poll, Async, sink, Sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use minidom::Element; -use sha_1::{Sha1, Digest}; +use sha1::{Sha1, Digest}; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; diff --git a/src/lib.rs b/src/lib.rs index ddb4f9a3b1bd2704c32775ba5d73da3e3223f4d2..9401cc46c5c2226f660b3bf4050a365e1427686e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ extern crate tokio_io; extern crate bytes; extern crate xml5ever; extern crate tendril; +extern crate quick_xml; extern crate minidom; extern crate native_tls; extern crate tokio_tls; @@ -12,7 +13,7 @@ extern crate rustc_serialize as serialize; extern crate jid; extern crate domain; extern crate idna; -extern crate sha_1; +extern crate sha1; pub mod xmpp_codec; pub mod xmpp_stream; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 5e340a9fb5177f18c37667b4fd071bc1a64b865d..97fe2a80d429a8642455becce6b02f9f052fc90f 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -13,6 +13,7 @@ use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; +use quick_xml::writer::Writer as EventWriter; // const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; @@ -278,7 +279,7 @@ impl Encoder for XMPPCodec { .map_err(|e| Error::new(ErrorKind::InvalidInput, e)) }, Packet::Stanza(stanza) => { - stanza.write_to_inner(&mut WriteBytes::new(dst)) + stanza.write_to_inner(&mut EventWriter::new(WriteBytes::new(dst))) .and_then(|_| { println!(">> {:?}", dst); Ok(()) From 53db39f0c843e856443e6adf048ae1117e041ae6 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 31 Jul 2018 22:37:04 +0200 Subject: [PATCH 060/135] bump some deps --- Cargo.toml | 18 ++++++++++-------- src/xmpp_codec.rs | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b664112a7b3a326927c4c32c861c74c5102f53f5..665167a23da4eca3377cacd4195b05ce58ec2d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,20 +4,22 @@ version = "0.1.0" authors = ["Astro "] [dependencies] -futures = "*" -tokio-core = "0.1.7" -tokio-io = "*" -bytes = "0.4.4" +futures = "^0.1" +tokio-core = "^0.1" +tokio-io = "^0.1" +bytes = "0.4.9" xml5ever = "*" tendril = "*" -minidom = "0.8.0" -native-tls = "*" +minidom = "0.9.1" +# TODO: update to 0.2.0 +native-tls = "0.1" tokio-tls = "*" sasl = "*" rustc-serialize = "*" -jid = { version = "0.5.0", features = ["minidom"] } +jid = { version = "0.5.2", features = ["minidom"] } +#jid = { version = "0.5.0", features = ["minidom"] } domain = "0.2.1" -xmpp-parsers = "0.10.0" +xmpp-parsers = "0.10" idna = "*" try_from = "0.2.2" sha-1 = "0.7.0" diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 97fe2a80d429a8642455becce6b02f9f052fc90f..349b5ac7bf5739f035d3b432b8f29aeddb8a86fb 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -13,7 +13,7 @@ use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; -use quick_xml::writer::Writer as EventWriter; +use quick_xml::Writer as EventWriter; // const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; From 1a3707649ee01204f05a14515ef72969eed659e4 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 31 Jul 2018 23:34:04 +0200 Subject: [PATCH 061/135] use tokio-codec --- Cargo.toml | 1 + src/lib.rs | 1 + src/stream_start.rs | 2 +- src/xmpp_codec.rs | 4 ++-- src/xmpp_stream.rs | 4 ++-- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 665167a23da4eca3377cacd4195b05ce58ec2d74..e9f2938cbf34bd8c672be491324f71769cd37dc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Astro "] futures = "^0.1" tokio-core = "^0.1" tokio-io = "^0.1" +tokio-codec = "^0.1" bytes = "0.4.9" xml5ever = "*" tendril = "*" diff --git a/src/lib.rs b/src/lib.rs index 9401cc46c5c2226f660b3bf4050a365e1427686e..7c42c378f503a32886081429108ca4b90909c6b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ extern crate futures; extern crate tokio_core; extern crate tokio_io; +extern crate tokio_codec; extern crate bytes; extern crate xml5ever; extern crate tendril; diff --git a/src/stream_start.rs b/src/stream_start.rs index 5dda29aea435ac1add25bf0d02c65339667f899b..f7c3b79d933fb9fd395044ea7eb6240fdb2fa2ef 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -2,7 +2,7 @@ use std::mem::replace; use std::io::{Error, ErrorKind}; use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_io::codec::Framed; +use tokio_codec::Framed; use jid::Jid; use minidom::Element; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 349b5ac7bf5739f035d3b432b8f29aeddb8a86fb..f38d8450c396e9c45db92ad00d7408536b3336f5 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -8,7 +8,7 @@ use std::str::from_utf8; use std::io::{Error, ErrorKind}; use std::collections::HashMap; use std::collections::vec_deque::VecDeque; -use tokio_io::codec::{Encoder, Decoder}; +use tokio_codec::{Encoder, Decoder}; use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; @@ -430,7 +430,7 @@ mod tests { fn test_large_stanza() { use std::io::Cursor; use futures::{Future, Sink}; - use tokio_io::codec::FramedWrite; + use tokio_codec::FramedWrite; let framed = FramedWrite::new(Cursor::new(vec![]), XMPPCodec::new()); let mut text = "".to_owned(); for _ in 0..2usize.pow(15) { diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 2b9c7aeac5a48c8a8bf3b78a3f1404079197f365..29f7d2e7dac68ab7b412b07f1af6b9a8eaba257b 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,6 +1,6 @@ use futures::{Poll, Stream, Sink, StartSend}; use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_io::codec::Framed; +use tokio_codec::Framed; use minidom::Element; use jid::Jid; @@ -25,7 +25,7 @@ impl XMPPStream { } pub fn start(stream: S, jid: Jid, ns: String) -> StreamStart { - let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new()); + let xmpp_stream = Framed::new(stream, XMPPCodec::new()); StreamStart::from_stream(xmpp_stream, jid, ns) } From 4e183838064b7bb196c5bd57cc8a331b84a750f1 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 31 Jul 2018 23:37:12 +0200 Subject: [PATCH 062/135] update dependencies --- Cargo.toml | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e9f2938cbf34bd8c672be491324f71769cd37dc0..54cb22d325b7fd861bb843c21e2b9e7834c4c662 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,24 +4,23 @@ version = "0.1.0" authors = ["Astro "] [dependencies] -futures = "^0.1" -tokio-core = "^0.1" -tokio-io = "^0.1" -tokio-codec = "^0.1" +futures = "0.1" +tokio-core = "0.1" +tokio-io = "0.1" +tokio-codec = "0.1" bytes = "0.4.9" -xml5ever = "*" -tendril = "*" -minidom = "0.9.1" +xml5ever = "0.12" +tendril = "0.4" +minidom = "0.9" # TODO: update to 0.2.0 native-tls = "0.1" -tokio-tls = "*" -sasl = "*" -rustc-serialize = "*" -jid = { version = "0.5.2", features = ["minidom"] } -#jid = { version = "0.5.0", features = ["minidom"] } -domain = "0.2.1" +tokio-tls = "0.1" +sasl = "0.4" +rustc-serialize = "0.3" +jid = { version = "0.5", features = ["minidom"] } +domain = "0.2" xmpp-parsers = "0.10" -idna = "*" -try_from = "0.2.2" -sha-1 = "0.7.0" -quick-xml = "*" +idna = "0.1" +try_from = "0.2" +sha-1 = "0.7" +quick-xml = "0.12" From 7baced0c3f28037ba19820803086e0c0a41081ec Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 1 Aug 2018 00:28:24 +0200 Subject: [PATCH 063/135] tokio-xmpp 0.1.1 --- Cargo.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 54cb22d325b7fd861bb843c21e2b9e7834c4c662..2faf4fb553cf3d668cc26cfd555fc956918a4618 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,12 @@ [package] name = "tokio-xmpp" -version = "0.1.0" +version = "0.1.1" authors = ["Astro "] +description = "Asynchronous XMPP for Rust with tokio" +license = "MPL-2.0" +homepage = "https://github.com/astro/tokio-xmpp" +repository = "https://github.com/astro/tokio-xmpp" +documentation = "https://docs.rs/tokio-xmpp" [dependencies] futures = "0.1" From 2e746f89e21b295d28d8878bbd96384abdb3a273 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 1 Aug 2018 01:07:10 +0200 Subject: [PATCH 064/135] replace sha-1 with xmpp-parsers for component handshake --- Cargo.toml | 1 - src/component/auth.rs | 14 ++++---------- src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2faf4fb553cf3d668cc26cfd555fc956918a4618..fab462b1919c59c28a8d8f43c9c65a7e7416ec68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,5 +27,4 @@ domain = "0.2" xmpp-parsers = "0.10" idna = "0.1" try_from = "0.2" -sha-1 = "0.7" quick-xml = "0.12" diff --git a/src/component/auth.rs b/src/component/auth.rs index bd1c9aa7000e444bbf73faa13ffd00a21ae5a283..2149da8fe734e66ae6ee7a5a7ac7c4c55997d4e7 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -2,7 +2,7 @@ use std::mem::replace; use futures::{Future, Poll, Async, sink, Sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use minidom::Element; -use sha1::{Sha1, Digest}; +use xmpp_parsers::component::Handshake; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; @@ -28,19 +28,13 @@ impl ComponentAuth { }; this.send( stream, - "handshake", - // TODO: sha1(sid + password) - &format!("{:x}", Sha1::digest((sid + &password).as_bytes())) + Handshake::from_password_and_stream_id(&password, &sid) ); return Ok(this); } - fn send(&mut self, stream: XMPPStream, nonza_name: &str, handshake: &str) { - let nonza = Element::builder(nonza_name) - .ns(NS_JABBER_COMPONENT_ACCEPT) - .append(handshake) - .build(); - + fn send(&mut self, stream: XMPPStream, handshake: Handshake) { + let nonza = Element::from(handshake); let send = stream.send(Packet::Stanza(nonza)); self.state = ComponentAuthState::WaitSend(send); diff --git a/src/lib.rs b/src/lib.rs index 7c42c378f503a32886081429108ca4b90909c6b7..222b3c4747c98918e6b1ec5e78dfc3a6cc42b6aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ extern crate rustc_serialize as serialize; extern crate jid; extern crate domain; extern crate idna; -extern crate sha1; +extern crate xmpp_parsers; pub mod xmpp_codec; pub mod xmpp_stream; From 06b97ea22849162c2e9e798f0d02ae578f7469f1 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 00:00:00 +0200 Subject: [PATCH 065/135] ClientBind: replace with xmpp_parsers::bind::Bind --- src/client/bind.rs | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/client/bind.rs b/src/client/bind.rs index 1541afd3543c4284cae66c45405d83869243c650..d258f7b7000da133e0b587f38f232ad9fca0c6d3 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -5,6 +5,7 @@ use futures::{Future, Poll, Async, sink, Sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use jid::Jid; use minidom::Element; +use xmpp_parsers::bind::Bind; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; @@ -30,7 +31,10 @@ impl ClientBind { // return the (probably // usable) stream immediately ClientBind::Unsupported(stream), Some(_) => { - let iq = make_bind_request(stream.jid.resource.as_ref()); + let resource = stream.jid.resource.clone(); + let iq = Element::from( + Bind::new(resource) + ); let send = stream.send(Packet::Stanza(iq)); ClientBind::WaitSend(send) }, @@ -38,21 +42,6 @@ impl ClientBind { } } -fn make_bind_request(resource: Option<&String>) -> Element { - let iq = Element::builder("iq") - .attr("type", "set") - .attr("id", BIND_REQ_ID); - let mut bind_el = Element::builder("bind") - .ns(NS_XMPP_BIND); - if let Some(resource) = resource { - let resource_el = Element::builder("resource") - .append(resource); - bind_el = bind_el.append(resource_el.build()); - } - iq.append(bind_el.build()) - .build() -} - impl Future for ClientBind { type Item = XMPPStream; type Error = String; From 71e2b1c84fef31b8c33ccaaeba2426df8b26aae4 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 00:19:06 +0200 Subject: [PATCH 066/135] add XMPPStream.send_stanza() convenience method --- src/client/auth.rs | 2 +- src/client/bind.rs | 6 ++---- src/component/auth.rs | 4 ++-- src/xmpp_stream.rs | 10 +++++++++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index ef828b37a479e0b8a74bf1e21eced63eaeb7c1d3..36f66059d109dc77bf535d5a60ea879fa54a3d12 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -76,7 +76,7 @@ impl ClientAuth { .append(content.to_base64(base64::STANDARD)) .build(); - let send = stream.send(Packet::Stanza(nonza)); + let send = stream.send_stanza(nonza); self.state = ClientAuthState::WaitSend(send); } diff --git a/src/client/bind.rs b/src/client/bind.rs index d258f7b7000da133e0b587f38f232ad9fca0c6d3..348fc3071595d4455578b358349ea93125cac5aa 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -32,10 +32,8 @@ impl ClientBind { ClientBind::Unsupported(stream), Some(_) => { let resource = stream.jid.resource.clone(); - let iq = Element::from( - Bind::new(resource) - ); - let send = stream.send(Packet::Stanza(iq)); + let iq = Bind::new(resource); + let send = stream.send_stanza(iq); ClientBind::WaitSend(send) }, } diff --git a/src/component/auth.rs b/src/component/auth.rs index 2149da8fe734e66ae6ee7a5a7ac7c4c55997d4e7..d53cc67b5dfa32df1dc3141bf60d026ca9388687 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -34,8 +34,8 @@ impl ComponentAuth { } fn send(&mut self, stream: XMPPStream, handshake: Handshake) { - let nonza = Element::from(handshake); - let send = stream.send(Packet::Stanza(nonza)); + let nonza = handshake; + let send = stream.send_stanza(nonza); self.state = ComponentAuthState::WaitSend(send); } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index 29f7d2e7dac68ab7b412b07f1af6b9a8eaba257b..e5ba9fcb26d6dd40b6b3cd7658d3ad0a3319224a 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,10 +1,11 @@ use futures::{Poll, Stream, Sink, StartSend}; +use futures::sink::Send; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_codec::Framed; use minidom::Element; use jid::Jid; -use xmpp_codec::XMPPCodec; +use xmpp_codec::{XMPPCodec, Packet}; use stream_start::StreamStart; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -38,6 +39,13 @@ impl XMPPStream { } } +impl XMPPStream { + /// Convenience method + pub fn send_stanza>(self, e: E) -> Send { + self.send(Packet::Stanza(e.into())) + } +} + /// Proxy to self.stream impl Sink for XMPPStream { type SinkItem = as Sink>::SinkItem; From 0155e3fdac3223a65adea16d8316c3d6846bc696 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 01:01:41 +0200 Subject: [PATCH 067/135] more replacement with xmpp-parsers --- src/client/auth.rs | 4 ++-- src/client/bind.rs | 53 ++++++++++++++++++++----------------------- src/component/auth.rs | 3 +-- src/lib.rs | 1 + 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 36f66059d109dc77bf535d5a60ea879fa54a3d12..d50a69341fed398eba9772980daafb7091b9e2ff 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,12 +1,12 @@ use std::mem::replace; -use futures::{Future, Poll, Async, sink, Sink, Stream}; +use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; -use minidom::Element; use sasl::common::Credentials; use sasl::common::scram::{Sha1, Sha256}; use sasl::client::Mechanism; use sasl::client::mechanisms::{Scram, Plain, Anonymous}; use serialize::base64::{self, ToBase64, FromBase64}; +use minidom::Element; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; diff --git a/src/client/bind.rs b/src/client/bind.rs index 348fc3071595d4455578b358349ea93125cac5aa..1ef268cc6a4f48f8ef6e01b02bba7d7ec297370b 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,11 +1,10 @@ use std::mem::replace; use std::error::Error; -use std::str::FromStr; -use futures::{Future, Poll, Async, sink, Sink, Stream}; +use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; -use jid::Jid; -use minidom::Element; +use xmpp_parsers::iq::{Iq, IqType}; use xmpp_parsers::bind::Bind; +use try_from::TryFrom; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; @@ -32,7 +31,8 @@ impl ClientBind { ClientBind::Unsupported(stream), Some(_) => { let resource = stream.jid.resource.clone(); - let iq = Bind::new(resource); + let iq = Iq::from_set(Bind::new(resource)) + .with_id(BIND_REQ_ID.to_string()); let send = stream.send_stanza(iq); ClientBind::WaitSend(send) }, @@ -66,18 +66,26 @@ impl Future for ClientBind { }, ClientBind::WaitRecv(mut stream) => { match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(ref iq)))) - if iq.name() == "iq" - && iq.attr("id") == Some(BIND_REQ_ID) => { - match iq.attr("type") { - Some("result") => { - get_bind_response_jid(iq) - .map(|jid| stream.jid = jid); - Ok(Async::Ready(stream)) - }, - _ => - Err("resource bind response".to_owned()), - } + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => + match Iq::try_from(stanza) { + Ok(iq) => if iq.id == Some(BIND_REQ_ID.to_string()) { + match iq.payload { + IqType::Result(payload) => { + payload + .and_then(|payload| Bind::try_from(payload).ok()) + .map(|bind| match bind { + Bind::Jid(jid) => stream.jid = jid, + _ => {} + }); + Ok(Async::Ready(stream)) + }, + _ => + Err("resource bind response".to_owned()), + } + } else { + Ok(Async::NotReady) + }, + _ => Ok(Async::NotReady), }, Ok(Async::Ready(_)) => { replace(self, ClientBind::WaitRecv(stream)); @@ -96,14 +104,3 @@ impl Future for ClientBind { } } } - -fn get_bind_response_jid(iq: &Element) -> Option { - iq.get_child("bind", NS_XMPP_BIND) - .and_then(|bind_el| - bind_el.get_child("jid", NS_XMPP_BIND) - ) - .and_then(|jid_el| - Jid::from_str(&jid_el.text()) - .ok() - ) -} diff --git a/src/component/auth.rs b/src/component/auth.rs index d53cc67b5dfa32df1dc3141bf60d026ca9388687..7801c92f2dd4538a9c551b62b21c5f0e2cba1e52 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -1,7 +1,6 @@ use std::mem::replace; -use futures::{Future, Poll, Async, sink, Sink, Stream}; +use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; -use minidom::Element; use xmpp_parsers::component::Handshake; use xmpp_codec::Packet; diff --git a/src/lib.rs b/src/lib.rs index 222b3c4747c98918e6b1ec5e78dfc3a6cc42b6aa..6ee15d1db93c0cdcedd548f83f26bf374529b4d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ extern crate jid; extern crate domain; extern crate idna; extern crate xmpp_parsers; +extern crate try_from; pub mod xmpp_codec; pub mod xmpp_stream; From db81338bc665cdea94212f5b874f9c4470d53f72 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 01:44:48 +0200 Subject: [PATCH 068/135] replace parts of client::auth with xmpp-parsers --- src/client/auth.rs | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index d50a69341fed398eba9772980daafb7091b9e2ff..575b1d4bc071ec6497f004c8ada0b4ddc7a045dc 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -5,8 +5,9 @@ use sasl::common::Credentials; use sasl::common::scram::{Sha1, Sha256}; use sasl::client::Mechanism; use sasl::client::mechanisms::{Scram, Plain, Anonymous}; -use serialize::base64::{self, ToBase64, FromBase64}; +use serialize::base64::FromBase64; use minidom::Element; +use xmpp_parsers::sasl::{Auth, Response, Mechanism as XMPPMechanism}; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; @@ -28,11 +29,19 @@ enum ClientAuthState { impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { - let mechs: Vec> = vec![ - Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - Box::new(Plain::from_credentials(creds).unwrap()), - Box::new(Anonymous::new()), + let mechs: Vec<(Box, XMPPMechanism)> = vec![ + // (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + // XMPPMechanism::ScramSha256 + // ), + (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + XMPPMechanism::ScramSha1 + ), + (Box::new(Plain::from_credentials(creds).unwrap()), + XMPPMechanism::Plain + ), + (Box::new(Anonymous::new()), + XMPPMechanism::Anonymous + ), ]; let mech_names: Vec = @@ -47,7 +56,7 @@ impl ClientAuth { }; println!("SASL mechanisms offered: {:?}", mech_names); - for mut mech in mechs { + for (mut mech, mechanism) in mechs { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { println!("SASL mechanism selected: {:?}", name); @@ -58,8 +67,10 @@ impl ClientAuth { }; this.send( stream, - "auth", &[("mechanism", &name)], - &initial + Auth { + mechanism, + data: initial, + } ); return Ok(this); } @@ -68,14 +79,7 @@ impl ClientAuth { Err("No supported SASL mechanism available".to_owned()) } - fn send(&mut self, stream: XMPPStream, nonza_name: &str, attrs: &[(&str, &str)], content: &[u8]) { - let nonza = Element::builder(nonza_name) - .ns(NS_XMPP_SASL); - let nonza = attrs.iter() - .fold(nonza, |nonza, &(name, value)| nonza.attr(name, value)) - .append(content.to_base64(base64::STANDARD)) - .build(); - + fn send>(&mut self, stream: XMPPStream, nonza: N) { let send = stream.send_stanza(nonza); self.state = ClientAuthState::WaitSend(send); @@ -114,7 +118,7 @@ impl Future for ClientAuth { .map_err(|e| format!("{}", e)) ); let response = try!(self.mechanism.response(&content)); - self.send(stream, "response", &[], &response); + self.send(stream, Response { data: response }); self.poll() }, Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) From 2a17ffc6241eace4995293b6cf083ab6feb236c6 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 18:12:41 +0200 Subject: [PATCH 069/135] replace parts of client::auth with xmpp-parsers --- Cargo.toml | 1 - src/client/auth.rs | 53 ++++++++++++++++++---------------------------- src/lib.rs | 1 - 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fab462b1919c59c28a8d8f43c9c65a7e7416ec68..53c0a281a57529b704531016223c877c6e0ee9b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ minidom = "0.9" native-tls = "0.1" tokio-tls = "0.1" sasl = "0.4" -rustc-serialize = "0.3" jid = { version = "0.5", features = ["minidom"] } domain = "0.2" xmpp-parsers = "0.10" diff --git a/src/client/auth.rs b/src/client/auth.rs index 575b1d4bc071ec6497f004c8ada0b4ddc7a045dc..1953dad415912c6fe022249951f5d6565f81a3a7 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -5,9 +5,9 @@ use sasl::common::Credentials; use sasl::common::scram::{Sha1, Sha256}; use sasl::client::Mechanism; use sasl::client::mechanisms::{Scram, Plain, Anonymous}; -use serialize::base64::FromBase64; use minidom::Element; -use xmpp_parsers::sasl::{Auth, Response, Mechanism as XMPPMechanism}; +use xmpp_parsers::sasl::{Auth, Challenge, Response, Success, Failure, Mechanism as XMPPMechanism}; +use try_from::TryFrom; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; @@ -30,9 +30,9 @@ enum ClientAuthState { impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { let mechs: Vec<(Box, XMPPMechanism)> = vec![ - // (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - // XMPPMechanism::ScramSha256 - // ), + (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + XMPPMechanism::ScramSha256 + ), (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), XMPPMechanism::ScramSha1 ), @@ -109,33 +109,22 @@ impl Future for ClientAuth { }, ClientAuthState::WaitRecv(mut stream) => match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.is("challenge", NS_XMPP_SASL) => - { - let content = try!( - stanza.text() - .from_base64() - .map_err(|e| format!("{}", e)) - ); - let response = try!(self.mechanism.response(&content)); - self.send(stream, Response { data: response }); - self.poll() - }, - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.is("success", NS_XMPP_SASL) => - { - let start = stream.restart(); - self.state = ClientAuthState::Start(start); - self.poll() - }, - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.is("failure", NS_XMPP_SASL) => - { - let e = stanza.children().next() - .map(|child| child.name()) - .unwrap_or("Authentication failure"); - Err(e.to_owned()) - }, + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + if let Ok(challenge) = Challenge::try_from(stanza.clone()) { + let response = try!(self.mechanism.response(&challenge.data)); + self.send(stream, Response { data: response }); + self.poll() + } else if let Ok(_) = Success::try_from(stanza.clone()) { + let start = stream.restart(); + self.state = ClientAuthState::Start(start); + self.poll() + } else if let Ok(failure) = Failure::try_from(stanza) { + let e = failure.data; + Err(e) + } else { + Ok(Async::NotReady) + } + } Ok(Async::Ready(event)) => { println!("ClientAuth ignore {:?}", event); Ok(Async::NotReady) diff --git a/src/lib.rs b/src/lib.rs index 6ee15d1db93c0cdcedd548f83f26bf374529b4d4..3ae6405f3d5ccf533c5a63ecf66ee7b558afd8ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,6 @@ extern crate minidom; extern crate native_tls; extern crate tokio_tls; extern crate sasl; -extern crate rustc_serialize as serialize; extern crate jid; extern crate domain; extern crate idna; From 0e4941dc7aadcf9746859b9ddee2650260651936 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 18:46:54 +0200 Subject: [PATCH 070/135] rm unused dep tendril --- Cargo.toml | 1 - src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 53c0a281a57529b704531016223c877c6e0ee9b3..a23afb3e5323af35293e65390e4eaab377b0ac6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ tokio-io = "0.1" tokio-codec = "0.1" bytes = "0.4.9" xml5ever = "0.12" -tendril = "0.4" minidom = "0.9" # TODO: update to 0.2.0 native-tls = "0.1" diff --git a/src/lib.rs b/src/lib.rs index 3ae6405f3d5ccf533c5a63ecf66ee7b558afd8ac..40da556890fdeab3bfb29f5889f2d08f6aead900 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,6 @@ extern crate tokio_io; extern crate tokio_codec; extern crate bytes; extern crate xml5ever; -extern crate tendril; extern crate quick_xml; extern crate minidom; extern crate native_tls; From b929a3c71eca8bf1e3208bf042a502b34c3a4a1a Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 19:58:19 +0200 Subject: [PATCH 071/135] doc --- src/client/mod.rs | 6 ++++++ src/component/mod.rs | 9 +++++++++ src/event.rs | 8 ++++++++ src/lib.rs | 4 ++++ src/starttls.rs | 3 ++- src/xmpp_codec.rs | 15 +++++++++++++-- src/xmpp_stream.rs | 15 +++++++++++++++ 7 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index dc948fa5e0b3e3ef35097f2e77842c99158dbcc5..95b9242fe9ae70ff3497baab416937093cdfe645 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -22,7 +22,9 @@ use self::auth::ClientAuth; mod bind; use self::bind::ClientBind; +/// XMPP client connection and state pub struct Client { + /// The client's current Jabber-Id pub jid: Jid, state: ClientState, } @@ -38,6 +40,10 @@ enum ClientState { } impl Client { + /// Start a new XMPP client + /// + /// Start polling the returned instance so that it will connect + /// and yield events. pub fn new(jid: &str, password: &str, handle: Handle) -> Result { let jid = try!(Jid::from_str(jid)); let password = password.to_owned(); diff --git a/src/component/mod.rs b/src/component/mod.rs index 04613c50350817bc2db133e68f09ac2f90b79e84..21ef8974d18a0d13e398712e23b400d6b621d2c9 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -1,3 +1,6 @@ +//! Components in XMPP are services/gateways that are logged into an +//! XMPP server under a JID consisting of just a domain name. They are +//! allowed to use any user and resource identifiers in their stanzas. use std::mem::replace; use std::str::FromStr; use std::error::Error; @@ -16,7 +19,9 @@ use super::event::Event; mod auth; use self::auth::ComponentAuth; +/// Component connection to an XMPP server pub struct Component { + /// The component's Jabber-Id pub jid: Jid, state: ComponentState, } @@ -32,6 +37,10 @@ enum ComponentState { } impl Component { + /// Start a new XMPP component + /// + /// Start polling the returned instance so that it will connect + /// and yield events. pub fn new(jid: &str, password: &str, server: &str, port: u16, handle: Handle) -> Result { let jid = try!(Jid::from_str(jid)); let password = password.to_owned(); diff --git a/src/event.rs b/src/event.rs index 8ff44bd70a84ded7200eace6cea4055015a7e29a..7a225ba352d9f3015aaa9d78b8b7b1d3b0beff31 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,13 +1,18 @@ use minidom::Element; +/// High-level event on the Stream implemented by Client and Component #[derive(Debug)] pub enum Event { + /// Stream is connected and initialized Online, + /// Stream end Disconnected, + /// Received stanza/nonza Stanza(Element), } impl Event { + /// `Online` event? pub fn is_online(&self) -> bool { match *self { Event::Online => true, @@ -15,6 +20,7 @@ impl Event { } } + /// `Stanza` event? pub fn is_stanza(&self, name: &str) -> bool { match *self { Event::Stanza(ref stanza) => stanza.name() == name, @@ -22,6 +28,7 @@ impl Event { } } + /// If this is a `Stanza` event, get its data pub fn as_stanza(&self) -> Option<&Element> { match *self { Event::Stanza(ref stanza) => Some(stanza), @@ -29,6 +36,7 @@ impl Event { } } + /// If this is a `Stanza` event, unwrap into its data pub fn into_stanza(self) -> Option { match self { Event::Stanza(stanza) => Some(stanza), diff --git a/src/lib.rs b/src/lib.rs index 40da556890fdeab3bfb29f5889f2d08f6aead900..ebba1f1bd9baf5f1f77197ff0aff7bd684a99c72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +#![deny(unsafe_code, unused, missing_docs)] + +//! XMPP implemeentation with asynchronous I/O using Tokio. + extern crate futures; extern crate tokio_core; extern crate tokio_io; diff --git a/src/starttls.rs b/src/starttls.rs index 7338b55cd10f34fdf4112c6c3d68361335a1e9af..6ac23acfb4d2025461005633c6a15b0969d08a24 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -11,10 +11,11 @@ use jid::Jid; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; - +/// XMPP TLS XML namespace pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; +/// XMPP stream that switches to TLS if available in received features pub struct StartTlsClient { state: StartTlsClientState, jid: Jid, diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index f38d8450c396e9c45db92ad00d7408536b3336f5..ededf214138481f9ab9c071aadd49b500dfe4ff2 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -1,3 +1,5 @@ +//! XML stream parser for XMPP + use std; use std::default::Default; use std::iter::FromIterator; @@ -15,17 +17,22 @@ use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; use quick_xml::Writer as EventWriter; -// const NS_XMLNS: &'static str = "http://www.w3.org/2000/xmlns/"; - +/// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug)] pub enum Packet { + /// General error (`InvalidInput`) Error(Box), + /// `` start tag StreamStart(HashMap), + /// A complete stanza or nonza Stanza(Element), + /// Plain text (think whitespace keep-alive) Text(String), + /// `` closing tag StreamEnd, } +/// Parser state struct ParserSink { // Ready stanzas, shared with XMPPCodec queue: Rc>>, @@ -47,6 +54,7 @@ impl ParserSink { self.queue.borrow_mut().push_back(pkt); } + /// Lookup XML namespace declaration for given prefix (or no prefix) fn lookup_ns(&self, prefix: &Option) -> Option<&str> { for nss in self.ns_stack.iter().rev() { if let Some(ns) = nss.get(prefix) { @@ -166,6 +174,7 @@ impl TokenSink for ParserSink { // } } +/// Stateful encoder/decoder for a bytestream from/to XMPP `Packet` pub struct XMPPCodec { /// Outgoing ns: Option, @@ -179,6 +188,7 @@ pub struct XMPPCodec { } impl XMPPCodec { + /// Constructor pub fn new() -> Self { let queue = Rc::new(RefCell::new(VecDeque::new())); let sink = ParserSink::new(queue.clone()); @@ -300,6 +310,7 @@ impl Encoder for XMPPCodec { } } +/// Write XML-escaped text string pub fn write_text(text: &str, writer: &mut W) -> Result<(), std::fmt::Error> { write!(writer, "{}", escape(text)) } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index e5ba9fcb26d6dd40b6b3cd7658d3ad0a3319224a..c5443a98e54242bf100cefbb1fa9dad471c8fb8e 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,3 +1,5 @@ +//! `XMPPStream` is the common container for all XMPP network connections + use futures::{Poll, Stream, Sink, StartSend}; use futures::sink::Send; use tokio_io::{AsyncRead, AsyncWrite}; @@ -8,16 +10,26 @@ use jid::Jid; use xmpp_codec::{XMPPCodec, Packet}; use stream_start::StreamStart; +/// namespace pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; +/// Wraps a `stream` pub struct XMPPStream { + /// The local Jabber-Id pub jid: Jid, + /// Codec instance pub stream: Framed, + /// `` for XMPP version 1.0 pub stream_features: Element, + /// Root namespace + /// + /// This is different for either c2s, s2s, or component + /// connections. pub ns: String, } impl XMPPStream { + /// Constructor pub fn new(jid: Jid, stream: Framed, ns: String, @@ -25,15 +37,18 @@ impl XMPPStream { XMPPStream { jid, stream, stream_features, ns } } + /// Send a `` start tag pub fn start(stream: S, jid: Jid, ns: String) -> StreamStart { let xmpp_stream = Framed::new(stream, XMPPCodec::new()); StreamStart::from_stream(xmpp_stream, jid, ns) } + /// Unwraps the inner stream pub fn into_inner(self) -> S { self.stream.into_inner() } + /// Re-run `start()` pub fn restart(self) -> StreamStart { Self::start(self.stream.into_inner(), self.jid, self.ns) } From b82237f42223dfeb1f1e8f3acdeefde2b7054059 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 2 Aug 2018 20:10:26 +0200 Subject: [PATCH 072/135] replace try! with ? syntax --- src/client/auth.rs | 4 ++-- src/client/mod.rs | 2 +- src/component/mod.rs | 2 +- src/happy_eyeballs.rs | 12 ++++-------- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 1953dad415912c6fe022249951f5d6565f81a3a7..7d933a44f0bc615afac7fc71827be699f99441b6 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -60,7 +60,7 @@ impl ClientAuth { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { println!("SASL mechanism selected: {:?}", name); - let initial = try!(mech.initial()); + let initial = mech.initial()?; let mut this = ClientAuth { state: ClientAuthState::Invalid, mechanism: mech, @@ -111,7 +111,7 @@ impl Future for ClientAuth { match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { if let Ok(challenge) = Challenge::try_from(stanza.clone()) { - let response = try!(self.mechanism.response(&challenge.data)); + let response = self.mechanism.response(&challenge.data)?; self.send(stream, Response { data: response }); self.poll() } else if let Ok(_) = Success::try_from(stanza.clone()) { diff --git a/src/client/mod.rs b/src/client/mod.rs index 95b9242fe9ae70ff3497baab416937093cdfe645..4f633ebad14d753c0394e79ca5f4581b6683e2c5 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -45,7 +45,7 @@ impl Client { /// Start polling the returned instance so that it will connect /// and yield events. pub fn new(jid: &str, password: &str, handle: Handle) -> Result { - let jid = try!(Jid::from_str(jid)); + let jid = Jid::from_str(jid)?; let password = password.to_owned(); let connect = Self::make_connect(jid.clone(), password.clone(), handle); Ok(Client { diff --git a/src/component/mod.rs b/src/component/mod.rs index 21ef8974d18a0d13e398712e23b400d6b621d2c9..9536f0a8f1485a1e67ec097ea516d718046860fd 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -42,7 +42,7 @@ impl Component { /// Start polling the returned instance so that it will connect /// and yield events. pub fn new(jid: &str, password: &str, server: &str, port: u16, handle: Handle) -> Result { - let jid = try!(Jid::from_str(jid)); + let jid = Jid::from_str(jid)?; let password = password.to_owned(); let connect = Self::make_connect(jid.clone(), password, server, port, handle); Ok(Component { diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index f2cd1a62d6e18deb7337d301a6617c20cde06ed6..2d83301c7ecc36b071b0a21b0ca5af4cafb4cf23 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -18,14 +18,10 @@ pub struct Connecter { impl Connecter { pub fn from_lookup(handle: Handle, domain: &str, srv: &str, fallback_port: u16) -> Result { - let domain = try!( - DNameBuf::from_str(domain) - .map_err(|e| format!("{}", e)) - ); - let srv = try!( - DNameBuf::from_str(srv) - .map_err(|e| format!("{}", e)) - ); + let domain = DNameBuf::from_str(domain) + .map_err(|e| format!("{}", e))?; + let srv = DNameBuf::from_str(srv) + .map_err(|e| format!("{}", e))?; let resolver = Resolver::new(&handle); let lookup = lookup_srv(resolver.clone(), srv, domain, fallback_port); From a3db744e46d3bfebc6d440d6888e6d478b355c38 Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 3 Aug 2018 01:11:55 +0200 Subject: [PATCH 073/135] client::auth: update xmpp-parsers usage --- Cargo.toml | 2 +- src/client/auth.rs | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a23afb3e5323af35293e65390e4eaab377b0ac6c..4d16028a57988414147d5b674d3a276cd0e2c4c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ tokio-tls = "0.1" sasl = "0.4" jid = { version = "0.5", features = ["minidom"] } domain = "0.2" -xmpp-parsers = "0.10" +xmpp-parsers = "0.11" idna = "0.1" try_from = "0.2" quick-xml = "0.12" diff --git a/src/client/auth.rs b/src/client/auth.rs index 7d933a44f0bc615afac7fc71827be699f99441b6..916b1ddce1a6d972933f3cf30e325791df5f6341 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,4 +1,5 @@ use std::mem::replace; +use std::str::FromStr; use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use sasl::common::Credentials; @@ -29,19 +30,11 @@ enum ClientAuthState { impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { - let mechs: Vec<(Box, XMPPMechanism)> = vec![ - (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - XMPPMechanism::ScramSha256 - ), - (Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - XMPPMechanism::ScramSha1 - ), - (Box::new(Plain::from_credentials(creds).unwrap()), - XMPPMechanism::Plain - ), - (Box::new(Anonymous::new()), - XMPPMechanism::Anonymous - ), + let mechs: Vec> = vec![ + Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + Box::new(Scram::::from_credentials(creds.clone()).unwrap()), + Box::new(Plain::from_credentials(creds).unwrap()), + Box::new(Anonymous::new()), ]; let mech_names: Vec = @@ -56,7 +49,7 @@ impl ClientAuth { }; println!("SASL mechanisms offered: {:?}", mech_names); - for (mut mech, mechanism) in mechs { + for mut mech in mechs { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { println!("SASL mechanism selected: {:?}", name); @@ -65,6 +58,8 @@ impl ClientAuth { state: ClientAuthState::Invalid, mechanism: mech, }; + let mechanism = XMPPMechanism::from_str(&name) + .map_err(|e| format!("{:?}", e))?; this.send( stream, Auth { @@ -119,7 +114,7 @@ impl Future for ClientAuth { self.state = ClientAuthState::Start(start); self.poll() } else if let Ok(failure) = Failure::try_from(stanza) { - let e = failure.data; + let e = format!("{:?}", failure.defined_condition); Err(e) } else { Ok(Async::NotReady) From bacd8673852c8c32185eb1595a9dd1ce49686b21 Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 3 Aug 2018 01:14:21 +0200 Subject: [PATCH 074/135] comment debug output --- README.md | 3 ++- src/client/auth.rs | 8 ++++---- src/client/mod.rs | 2 +- src/component/mod.rs | 2 +- src/happy_eyeballs.rs | 6 +++--- src/xmpp_codec.rs | 10 +++++----- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c3b636a02cd135b1efd309efdc4564b84a0c6c12..52e43abd48e3b0c2092fc39398ce4740a092d399 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # TODO - [ ] minidom ns +- [ ] replace debug output with log crate - [ ] customize tls verify? - [ ] Error type - [ ] unexpected event errors -- [ ] doc +- [x] doc - [ ] tests diff --git a/src/client/auth.rs b/src/client/auth.rs index 916b1ddce1a6d972933f3cf30e325791df5f6341..0dc66d1654455c29bf20e5ab0857d020fecdd324 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -47,12 +47,12 @@ impl ClientAuth { .map(|mech_el| mech_el.text()) .collect(), }; - println!("SASL mechanisms offered: {:?}", mech_names); + // println!("SASL mechanisms offered: {:?}", mech_names); for mut mech in mechs { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { - println!("SASL mechanism selected: {:?}", name); + // println!("SASL mechanism selected: {:?}", name); let initial = mech.initial()?; let mut this = ClientAuth { state: ClientAuthState::Invalid, @@ -120,8 +120,8 @@ impl Future for ClientAuth { Ok(Async::NotReady) } } - Ok(Async::Ready(event)) => { - println!("ClientAuth ignore {:?}", event); + Ok(Async::Ready(_event)) => { + // println!("ClientAuth ignore {:?}", _event); Ok(Async::NotReady) }, Ok(_) => { diff --git a/src/client/mod.rs b/src/client/mod.rs index 4f633ebad14d753c0394e79ca5f4581b6683e2c5..44dc8d0c34dd488fb066c38f8bfba965b2488008 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -87,7 +87,7 @@ impl Client { }).and_then(|xmpp_stream| { Self::bind(xmpp_stream) }).and_then(|xmpp_stream| { - println!("Bound to {}", xmpp_stream.jid); + // println!("Bound to {}", xmpp_stream.jid); Ok(xmpp_stream) }) ) diff --git a/src/component/mod.rs b/src/component/mod.rs index 9536f0a8f1485a1e67ec097ea516d718046860fd..bf9a005f24ce2bf3873edcab11304d83e030cecc 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -63,7 +63,7 @@ impl Component { }).and_then(move |xmpp_stream| { Self::auth(xmpp_stream, password).expect("auth") }).and_then(|xmpp_stream| { - println!("Bound to {}", xmpp_stream.jid); + // println!("Bound to {}", xmpp_stream.jid); Ok(xmpp_stream) }) ) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 2d83301c7ecc36b071b0a21b0ca5af4cafb4cf23..7b95f8232402aa51a486aa83d312215af521160b 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -65,7 +65,7 @@ impl Future for Connecter { for addr in srv_item.to_socket_addrs() { self.connects.entry(addr) .or_insert_with(|| { - println!("Connect to {}", addr); + // println!("Connect to {}", addr); TcpStream::connect(&addr, handle) }); } @@ -87,8 +87,8 @@ impl Future for Connecter { connected_stream = Some(tcp_stream); false }, - Err(e) => { - println!("{}", e); + Err(_e) => { + // println!("{}", _e); false }, } diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index ededf214138481f9ab9c071aadd49b500dfe4ff2..7215563ff9854b22f4814caa28e5cdbaaeda7bf8 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -163,7 +163,7 @@ impl TokenSink for ParserSink { Token::EOFToken => self.push_queue(Packet::StreamEnd), Token::ParseError(s) => { - println!("ParseError: {:?}", s); + // println!("ParseError: {:?}", s); self.push_queue(Packet::Error(Box::new(Error::new(ErrorKind::InvalidInput, (*s).to_owned())))) }, _ => (), @@ -226,7 +226,7 @@ impl Decoder for XMPPCodec { match from_utf8(buf1) { Ok(s) => { if ! s.is_empty() { - println!("<< {}", s); + // println!("<< {}", s); let tendril = FromIterator::from_iter(s.chars()); self.parser.feed(tendril); } @@ -246,7 +246,7 @@ impl Decoder for XMPPCodec { return result; }, Err(e) => { - println!("error {} at {}/{} in {:?}", e, e.valid_up_to(), buf1.len(), buf1); + // println!("error {} at {}/{} in {:?}", e, e.valid_up_to(), buf1.len(), buf1); return Err(Error::new(ErrorKind::InvalidInput, e)); }, } @@ -291,7 +291,7 @@ impl Encoder for XMPPCodec { Packet::Stanza(stanza) => { stanza.write_to_inner(&mut EventWriter::new(WriteBytes::new(dst))) .and_then(|_| { - println!(">> {:?}", dst); + // println!(">> {:?}", dst); Ok(()) }) .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) @@ -299,7 +299,7 @@ impl Encoder for XMPPCodec { Packet::Text(text) => { write_text(&text, dst) .and_then(|_| { - println!(">> {:?}", dst); + // println!(">> {:?}", dst); Ok(()) }) .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) From 0d93bb566f567fcd653c232a398209208f3d1f2f Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 3 Aug 2018 01:16:42 +0200 Subject: [PATCH 075/135] tokio-xmpp 0.1.2 --- Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d16028a57988414147d5b674d3a276cd0e2c4c9..02a706d46ee65b2090cf5b1418f4ad65f0c8f653 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,14 @@ [package] name = "tokio-xmpp" -version = "0.1.1" -authors = ["Astro "] +version = "0.1.2" +authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" homepage = "https://github.com/astro/tokio-xmpp" repository = "https://github.com/astro/tokio-xmpp" documentation = "https://docs.rs/tokio-xmpp" +categories = ["asynchronous", "network-programming"] +keywords = ["xmpp", "tokio"] [dependencies] futures = "0.1" From 2e0dd44352a05b1e27d44d2d2f09569f25e481cf Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 5 Aug 2018 21:52:32 +0200 Subject: [PATCH 076/135] a proper ParserError type for XMPPCodec --- src/stream_start.rs | 14 +++---- src/xmpp_codec.rs | 95 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/stream_start.rs b/src/stream_start.rs index f7c3b79d933fb9fd395044ea7eb6240fdb2fa2ef..aa1284e2f76634190d7440daccc86acb3512619a 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,12 +1,12 @@ use std::mem::replace; -use std::io::{Error, ErrorKind}; +use std::borrow::Cow; use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_codec::Framed; use jid::Jid; use minidom::Element; -use xmpp_codec::{XMPPCodec, Packet}; +use xmpp_codec::{XMPPCodec, Packet, ParserError}; use xmpp_stream::XMPPStream; const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -43,7 +43,7 @@ impl StreamStart { impl Future for StreamStart { type Item = XMPPStream; - type Error = Error; + type Error = ParserError; fn poll(&mut self) -> Poll { let old_state = replace(&mut self.state, StreamStartState::Invalid); @@ -59,7 +59,7 @@ impl Future for StreamStart { Ok(Async::NotReady) => (StreamStartState::SendStart(send), Ok(Async::NotReady)), Err(e) => - (StreamStartState::Invalid, Err(e)), + (StreamStartState::Invalid, Err(e.into())), }, StreamStartState::RecvStart(mut stream) => match stream.poll() { @@ -67,7 +67,7 @@ impl Future for StreamStart { let stream_ns = match stream_attrs.get("xmlns") { Some(ns) => ns.clone(), None => - return Err(Error::from(ErrorKind::InvalidData)), + return Err(ParserError::Parse(Cow::from("Missing stream namespace"))), }; if self.ns == "jabber:client" { retry = true; @@ -77,7 +77,7 @@ impl Future for StreamStart { let id = match stream_attrs.get("id") { Some(id) => id.clone(), None => - return Err(Error::from(ErrorKind::InvalidData)), + return Err(ParserError::Parse(Cow::from("No stream id"))), }; // FIXME: huge hack, shouldn’t be an element! let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), Element::builder(id).build()); @@ -85,7 +85,7 @@ impl Future for StreamStart { } }, Ok(Async::Ready(_)) => - return Err(Error::from(ErrorKind::InvalidData)), + return Err(ParserError::Parse(Cow::from("Invalid XML event received"))), Ok(Async::NotReady) => (StreamStartState::RecvStart(stream), Ok(Async::NotReady)), Err(e) => diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 7215563ff9854b22f4814caa28e5cdbaaeda7bf8..09ea1ea4c123895ab253d3b8591fd13bef7e1a90 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -6,10 +6,13 @@ use std::iter::FromIterator; use std::cell::RefCell; use std::rc::Rc; use std::fmt::Write; -use std::str::from_utf8; -use std::io::{Error, ErrorKind}; +use std::str::{from_utf8, Utf8Error}; +use std::io; use std::collections::HashMap; use std::collections::vec_deque::VecDeque; +use std::error::Error as StdError; +use std::fmt; +use std::borrow::Cow; use tokio_codec::{Encoder, Decoder}; use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; @@ -20,8 +23,6 @@ use quick_xml::Writer as EventWriter; /// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug)] pub enum Packet { - /// General error (`InvalidInput`) - Error(Box), /// `` start tag StreamStart(HashMap), /// A complete stanza or nonza @@ -32,17 +33,68 @@ pub enum Packet { StreamEnd, } +/// Causes for stream parsing errors +#[derive(Debug)] +pub enum ParserError { + /// Encoding error + Utf8(Utf8Error), + /// XML parse error + Parse(Cow<'static, str>), + /// Illegal `` + ShortTag, + /// Required by `impl Decoder` + IO(io::Error), +} + +impl From for ParserError { + fn from(e: io::Error) -> Self { + ParserError::IO(e) + } +} + +impl StdError for ParserError { + fn description(&self) -> &str { + match *self { + ParserError::Utf8(ref ue) => ue.description(), + ParserError::Parse(ref pe) => pe, + ParserError::ShortTag => "short tag", + ParserError::IO(ref ie) => ie.description(), + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + ParserError::Utf8(ref ue) => ue.cause(), + ParserError::IO(ref ie) => ie.cause(), + _ => None, + } + } +} + +impl fmt::Display for ParserError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ParserError::Utf8(ref ue) => write!(f, "{}", ue), + ParserError::Parse(ref pe) => write!(f, "{}", pe), + ParserError::ShortTag => write!(f, "Short tag"), + ParserError::IO(ref ie) => write!(f, "{}", ie), + } + } +} + +type QueueItem = Result; + /// Parser state struct ParserSink { // Ready stanzas, shared with XMPPCodec - queue: Rc>>, + queue: Rc>>, // Parsing stack stack: Vec, ns_stack: Vec, String>>, } impl ParserSink { - pub fn new(queue: Rc>>) -> Self { + pub fn new(queue: Rc>>) -> Self { ParserSink { queue, stack: vec![], @@ -51,7 +103,11 @@ impl ParserSink { } fn push_queue(&self, pkt: Packet) { - self.queue.borrow_mut().push_back(pkt); + self.queue.borrow_mut().push_back(Ok(pkt)); + } + + fn push_queue_error(&self, e: ParserError) { + self.queue.borrow_mut().push_back(Err(e)); } /// Lookup XML namespace declaration for given prefix (or no prefix) @@ -149,7 +205,7 @@ impl TokenSink for ParserSink { self.handle_end_tag(); }, TagKind::ShortTag => - self.push_queue(Packet::Error(Box::new(Error::new(ErrorKind::InvalidInput, "ShortTag")))), + self.push_queue_error(ParserError::ShortTag), }, Token::CharacterTokens(tendril) => match self.stack.len() { @@ -164,7 +220,7 @@ impl TokenSink for ParserSink { self.push_queue(Packet::StreamEnd), Token::ParseError(s) => { // println!("ParseError: {:?}", s); - self.push_queue(Packet::Error(Box::new(Error::new(ErrorKind::InvalidInput, (*s).to_owned())))) + self.push_queue_error(ParserError::Parse(s)); }, _ => (), } @@ -184,7 +240,7 @@ pub struct XMPPCodec { // TODO: optimize using tendrils? buf: Vec, /// Shared with ParserSink - queue: Rc>>, + queue: Rc>>, } impl XMPPCodec { @@ -211,7 +267,7 @@ impl Default for XMPPCodec { impl Decoder for XMPPCodec { type Item = Packet; - type Error = Error; + type Error = ParserError; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { let buf1: Box> = @@ -247,12 +303,15 @@ impl Decoder for XMPPCodec { }, Err(e) => { // println!("error {} at {}/{} in {:?}", e, e.valid_up_to(), buf1.len(), buf1); - return Err(Error::new(ErrorKind::InvalidInput, e)); + return Err(ParserError::Utf8(e)); }, } - let result = self.queue.borrow_mut().pop_front(); - Ok(result) + match self.queue.borrow_mut().pop_front() { + None => Ok(None), + Some(result) => + result.map(|pkt| Some(pkt)), + } } fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { @@ -262,7 +321,7 @@ impl Decoder for XMPPCodec { impl Encoder for XMPPCodec { type Item = Packet; - type Error = Error; + type Error = io::Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { let remaining = dst.capacity() - dst.len(); @@ -286,7 +345,7 @@ impl Encoder for XMPPCodec { print!(">> {}", buf); write!(dst, "{}", buf) - .map_err(|e| Error::new(ErrorKind::InvalidInput, e)) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e)) }, Packet::Stanza(stanza) => { stanza.write_to_inner(&mut EventWriter::new(WriteBytes::new(dst))) @@ -294,7 +353,7 @@ impl Encoder for XMPPCodec { // println!(">> {:?}", dst); Ok(()) }) - .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) }, Packet::Text(text) => { write_text(&text, dst) @@ -302,7 +361,7 @@ impl Encoder for XMPPCodec { // println!(">> {:?}", dst); Ok(()) }) - .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{}", e))) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) }, // TODO: Implement all _ => Ok(()) From d3039127ddb3628c510757bb4af9962be7ef7243 Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 1 Sep 2018 22:59:02 +0300 Subject: [PATCH 077/135] Move from tokio-core to tokio. --- Cargo.toml | 10 +- examples/echo_bot.rs | 10 +- examples/echo_component.rs | 12 +-- src/client/mod.rs | 11 +- src/component/mod.rs | 11 +- src/happy_eyeballs.rs | 200 ++++++++++++++++++++++--------------- src/lib.rs | 5 +- src/starttls.rs | 14 +-- 8 files changed, 158 insertions(+), 115 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02a706d46ee65b2090cf5b1418f4ad65f0c8f653..9c6c8d1b29bf3159cdaf206fdfe463251976d07f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,18 +12,18 @@ keywords = ["xmpp", "tokio"] [dependencies] futures = "0.1" -tokio-core = "0.1" +tokio = "0.1" tokio-io = "0.1" tokio-codec = "0.1" bytes = "0.4.9" xml5ever = "0.12" minidom = "0.9" -# TODO: update to 0.2.0 -native-tls = "0.1" -tokio-tls = "0.1" +native-tls = "0.2" +tokio-tls = "0.2" sasl = "0.4" jid = { version = "0.5", features = ["minidom"] } -domain = "0.2" +trust-dns-resolver = "0.9.1" +trust-dns-proto = "0.4.0" xmpp-parsers = "0.11" idna = "0.1" try_from = "0.2" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 462f7fe870f1af721d32837b26db62f8e093a922..138222609515f49ee5cc68c24b98c2c94f40f409 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,5 +1,5 @@ extern crate futures; -extern crate tokio_core; +extern crate tokio; extern crate tokio_xmpp; extern crate jid; extern crate minidom; @@ -9,8 +9,8 @@ extern crate try_from; use std::env::args; use std::process::exit; use try_from::TryFrom; -use tokio_core::reactor::Core; use futures::{Stream, Sink, future}; +use tokio::runtime::current_thread::Runtime; use tokio_xmpp::Client; use minidom::Element; use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; @@ -27,9 +27,9 @@ fn main() { let password = &args[2]; // tokio_core context - let mut core = Core::new().unwrap(); + let mut rt = Runtime::new().unwrap(); // Client instance - let client = Client::new(jid, password, core.handle()).unwrap(); + let client = Client::new(jid, password).unwrap(); // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. @@ -64,7 +64,7 @@ fn main() { }); // Start polling `done` - match core.run(done) { + match rt.block_on(done) { Ok(_) => (), Err(e) => { println!("Fatal: {}", e); diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 745e0771a6e50514100f0a25db28a5878abf3062..1239354aa0fceb19cebfb8e039bd298da548d7fe 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -1,5 +1,5 @@ extern crate futures; -extern crate tokio_core; +extern crate tokio; extern crate tokio_xmpp; extern crate jid; extern crate minidom; @@ -10,7 +10,7 @@ use std::env::args; use std::process::exit; use std::str::FromStr; use try_from::TryFrom; -use tokio_core::reactor::Core; +use tokio::runtime::current_thread::Runtime; use futures::{Stream, Sink, future}; use tokio_xmpp::Component; use minidom::Element; @@ -30,10 +30,10 @@ fn main() { let port: u16 = args.get(4).unwrap().parse().unwrap_or(5347u16); // tokio_core context - let mut core = Core::new().unwrap(); + let mut rt = Runtime::new().unwrap(); // Component instance - println!("{} {} {} {} {:?}", jid, password, server, port, core.handle()); - let component = Component::new(jid, password, server, port, core.handle()).unwrap(); + println!("{} {} {} {}", jid, password, server, port); + let component = Component::new(jid, password, server, port).unwrap(); // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. @@ -70,7 +70,7 @@ fn main() { }); // Start polling `done` - match core.run(done) { + match rt.block_on(done) { Ok(_) => (), Err(e) => { println!("Fatal: {}", e); diff --git a/src/client/mod.rs b/src/client/mod.rs index 44dc8d0c34dd488fb066c38f8bfba965b2488008..d4151163ec6f040a3a684ef4248ce8abe99712ea 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,8 +1,7 @@ use std::mem::replace; use std::str::FromStr; use std::error::Error; -use tokio_core::reactor::Handle; -use tokio_core::net::TcpStream; +use tokio::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; use futures::{future, Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; @@ -44,17 +43,17 @@ impl Client { /// /// Start polling the returned instance so that it will connect /// and yield events. - pub fn new(jid: &str, password: &str, handle: Handle) -> Result { + pub fn new(jid: &str, password: &str) -> Result { let jid = Jid::from_str(jid)?; let password = password.to_owned(); - let connect = Self::make_connect(jid.clone(), password.clone(), handle); + let connect = Self::make_connect(jid.clone(), password.clone()); Ok(Client { jid, state: ClientState::Connecting(connect), }) } - fn make_connect(jid: Jid, password: String, handle: Handle) -> Box> { + fn make_connect(jid: Jid, password: String) -> Box> { let username = jid.node.as_ref().unwrap().to_owned(); let jid1 = jid.clone(); let jid2 = jid.clone(); @@ -66,7 +65,7 @@ impl Client { return Box::new(future::err(format!("{:?}", e))), }; Box::new( - Connecter::from_lookup(handle, &domain, "_xmpp-client._tcp", 5222) + Connecter::from_lookup(&domain, "_xmpp-client._tcp", 5222) .expect("Connector::from_lookup") .and_then(move |tcp_stream| xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) diff --git a/src/component/mod.rs b/src/component/mod.rs index bf9a005f24ce2bf3873edcab11304d83e030cecc..1cf8a39bd096f7c271723199af25eaf447136257 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -4,8 +4,7 @@ use std::mem::replace; use std::str::FromStr; use std::error::Error; -use tokio_core::reactor::Handle; -use tokio_core::net::TcpStream; +use tokio::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; use minidom::Element; @@ -41,21 +40,21 @@ impl Component { /// /// Start polling the returned instance so that it will connect /// and yield events. - pub fn new(jid: &str, password: &str, server: &str, port: u16, handle: Handle) -> Result { + pub fn new(jid: &str, password: &str, server: &str, port: u16) -> Result { let jid = Jid::from_str(jid)?; let password = password.to_owned(); - let connect = Self::make_connect(jid.clone(), password, server, port, handle); + let connect = Self::make_connect(jid.clone(), password, server, port); Ok(Component { jid, state: ComponentState::Connecting(connect), }) } - fn make_connect(jid: Jid, password: String, server: &str, port: u16, handle: Handle) -> Box> { + fn make_connect(jid: Jid, password: String, server: &str, port: u16) -> Box> { let jid1 = jid.clone(); let password = password; Box::new( - Connecter::from_lookup(handle, server, "_xmpp-component._tcp", port) + Connecter::from_lookup(server, "_xmpp-component._tcp", port) .expect("Connector::from_lookup") .and_then(move |tcp_stream| { xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 7b95f8232402aa51a486aa83d312215af521160b..9edd2ca5b37b3dc56409a4c3eb079ef43e805d7b 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,37 +1,46 @@ -use std::str::FromStr; -use std::collections::HashMap; -use std::net::SocketAddr; -use futures::{Future, Poll, Async, Stream}; -use tokio_core::reactor::Handle; -use tokio_core::net::{TcpStream, TcpStreamNew}; -use domain::resolv::Resolver; -use domain::resolv::lookup::srv::{lookup_srv, LookupSrv, LookupSrvStream}; -use domain::bits::DNameBuf; +use std::mem; +use std::net::{SocketAddr, IpAddr}; +use std::collections::{BTreeMap, btree_map}; +use std::collections::VecDeque; +use futures::{Future, Poll, Async}; +use tokio::net::{ConnectFuture, TcpStream}; +use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; +use trust_dns_resolver::lookup::SrvLookupFuture; +use trust_dns_resolver::lookup_ip::LookupIpFuture; +use trust_dns_proto::rr::rdata::srv::SRV; pub struct Connecter { - handle: Handle, - resolver: Resolver, - lookup: Option, - srvs: Option, - connects: HashMap, + fallback_port: u16, + name: Name, + domain: Name, + resolver_future: Box + Send>, + resolver_opt: Option, + srv_lookup_opt: Option, + srvs_opt: Option>, + ip_lookup_opt: Option<(u16, LookupIpFuture)>, + ips_opt: Option<(u16, VecDeque)>, + connect_opt: Option, } impl Connecter { - pub fn from_lookup(handle: Handle, domain: &str, srv: &str, fallback_port: u16) -> Result { - let domain = DNameBuf::from_str(domain) - .map_err(|e| format!("{}", e))?; - let srv = DNameBuf::from_str(srv) - .map_err(|e| format!("{}", e))?; + pub fn from_lookup(domain: &str, srv: &str, fallback_port: u16) -> Result { + let resolver_future = ResolverFuture::from_system_conf() + .map_err(|e| format!("Configure resolver: {:?}", e))?; - let resolver = Resolver::new(&handle); - let lookup = lookup_srv(resolver.clone(), srv, domain, fallback_port); + let name = format!("{}.{}.", srv, domain).into_name() + .map_err(|e| format!("Parse service name: {:?}", e))?; Ok(Connecter { - handle, - resolver, - lookup: Some(lookup), - srvs: None, - connects: HashMap::new(), + fallback_port, + name, + domain: domain.into_name().map_err(|e| format!("Parse domain name: {:?}", e))?, + resolver_future, + resolver_opt: None, + srv_lookup_opt: None, + srvs_opt: None, + ip_lookup_opt: None, + ips_opt: None, + connect_opt: None, }) } } @@ -41,69 +50,104 @@ impl Future for Connecter { type Error = String; fn poll(&mut self) -> Poll { - match self.lookup.as_mut().map(|lookup| lookup.poll()) { - None | Some(Ok(Async::NotReady)) => (), - Some(Ok(Async::Ready(found_srvs))) => { - self.lookup = None; - match found_srvs { - Some(srvs) => - self.srvs = Some(srvs.to_stream(self.resolver.clone())), - None => - return Err("No SRV records".to_owned()), + if self.resolver_opt.is_none() { + //println!("Poll resolver future"); + match self.resolver_future.poll() { + Ok(Async::Ready(resolver)) => { + self.resolver_opt = Some(resolver); } - }, - Some(Err(e)) => - return Err(format!("{}", e)), + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => return Err(format!("Cann't get resolver: {:?}", e)), + } } - match self.srvs.as_mut().map(|srv| srv.poll()) { - None | Some(Ok(Async::NotReady)) => (), - Some(Ok(Async::Ready(None))) => - self.srvs = None, - Some(Ok(Async::Ready(Some(srv_item)))) => { - let handle = &self.handle; - for addr in srv_item.to_socket_addrs() { - self.connects.entry(addr) - .or_insert_with(|| { - // println!("Connect to {}", addr); - TcpStream::connect(&addr, handle) - }); + if let Some(ref resolver) = self.resolver_opt { + if self.srvs_opt.is_none() { + if self.srv_lookup_opt.is_none() { + //println!("Lookup srv: {:?}", self.name); + self.srv_lookup_opt = Some(resolver.lookup_srv(&self.name)); } - }, - Some(Err(e)) => - return Err(format!("{}", e)), - } - let mut connected_stream = None; - self.connects.retain(|_, connect| { - if connected_stream.is_some() { - return false; + if let Some(ref mut srv_lookup) = self.srv_lookup_opt { + match srv_lookup.poll() { + Ok(Async::Ready(t)) => { + let mut srvs = BTreeMap::new(); + for srv in t.iter() { + srvs.insert(srv.priority(), srv.clone()); + } + srvs.insert(65535, SRV::new(65535, 0, self.fallback_port, self.domain.clone())); + self.srvs_opt = Some(srvs.into_iter()); + } + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(_) => { + //println!("Ignore SVR error: {:?}", e); + let mut srvs = BTreeMap::new(); + srvs.insert(65535, SRV::new(65535, 0, self.fallback_port, self.domain.clone())); + self.srvs_opt = Some(srvs.into_iter()); + }, + } + } + } + + if self.connect_opt.is_none() { + if self.ips_opt.is_none() { + if self.ip_lookup_opt.is_none() { + if let Some(ref mut srvs) = self.srvs_opt { + if let Some((_, srv)) = srvs.next() { + //println!("Lookup ip: {:?}", srv); + self.ip_lookup_opt = Some((srv.port(), resolver.lookup_ip(srv.target()))); + } else { + return Err("Cann't connect".to_string()); + } + } + } + + if let Some((port, mut ip_lookup)) = mem::replace(&mut self.ip_lookup_opt, None) { + match ip_lookup.poll() { + Ok(Async::Ready(t)) => { + let mut ip_deque = VecDeque::new(); + ip_deque.extend(t.iter()); + //println!("IPs: {:?}", ip_deque); + self.ips_opt = Some((port, ip_deque)); + self.ip_lookup_opt = None; + }, + Ok(Async::NotReady) => { + self.ip_lookup_opt = Some((port, ip_lookup)); + return Ok(Async::NotReady) + }, + Err(_) => { + //println!("Ignore lookup error: {:?}", e); + self.ip_lookup_opt = None; + } + } + } + } + + if let Some((port, mut ip_deque)) = mem::replace(&mut self.ips_opt, None) { + if let Some(ip) = ip_deque.pop_front() { + //println!("Connect to {:?}:{}", ip, port); + self.connect_opt = Some(TcpStream::connect(&SocketAddr::new(ip, port))); + self.ips_opt = Some((port, ip_deque)); + } + } } - match connect.poll() { - Ok(Async::NotReady) => true, - Ok(Async::Ready(tcp_stream)) => { - // Success! - connected_stream = Some(tcp_stream); - false - }, - Err(_e) => { - // println!("{}", _e); - false - }, + if let Some(mut connect_future) = mem::replace(&mut self.connect_opt, None) { + match connect_future.poll() { + Ok(Async::Ready(t)) => return Ok(Async::Ready(t)), + Ok(Async::NotReady) => { + self.connect_opt = Some(connect_future); + return Ok(Async::NotReady) + } + Err(_) => { + //println!("Ignore connect error: {:?}", e); + }, + } } - }); - if let Some(tcp_stream) = connected_stream { - return Ok(Async::Ready(tcp_stream)); - } - if self.lookup.is_none() && - self.srvs.is_none() && - self.connects.is_empty() - { - return Err("All connection attempts failed".to_owned()); } Ok(Async::NotReady) } } + diff --git a/src/lib.rs b/src/lib.rs index ebba1f1bd9baf5f1f77197ff0aff7bd684a99c72..13f374dbd9acebeef45b9261a56eb15e2c0d08e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ //! XMPP implemeentation with asynchronous I/O using Tokio. extern crate futures; -extern crate tokio_core; +extern crate tokio; extern crate tokio_io; extern crate tokio_codec; extern crate bytes; @@ -14,7 +14,8 @@ extern crate native_tls; extern crate tokio_tls; extern crate sasl; extern crate jid; -extern crate domain; +extern crate trust_dns_resolver; +extern crate trust_dns_proto; extern crate idna; extern crate xmpp_parsers; extern crate try_from; diff --git a/src/starttls.rs b/src/starttls.rs index 6ac23acfb4d2025461005633c6a15b0969d08a24..1d56a9cdb3bcb5cced18636a1be4cdf27d45f62d 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -3,8 +3,8 @@ use futures::{Future, Sink, Poll, Async}; use futures::stream::Stream; use futures::sink; use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_tls::{TlsStream, TlsConnectorExt, ConnectAsync}; -use native_tls::TlsConnector; +use tokio_tls::{TlsStream, TlsConnector, Connect}; +use native_tls::TlsConnector as NativeTlsConnector; use minidom::Element; use jid::Jid; @@ -25,7 +25,7 @@ enum StartTlsClientState { Invalid, SendStartTls(sink::Send>), AwaitProceed(XMPPStream), - StartingTls(ConnectAsync), + StartingTls(Connect), } impl StartTlsClient { @@ -53,7 +53,7 @@ impl Future for StartTlsClient { fn poll(&mut self) -> Poll { let old_state = replace(&mut self.state, StartTlsClientState::Invalid); let mut retry = false; - + let (new_state, result) = match old_state { StartTlsClientState::SendStartTls(mut send) => match send.poll() { @@ -73,9 +73,9 @@ impl Future for StartTlsClient { if stanza.name() == "proceed" => { let stream = xmpp_stream.stream.into_inner(); - let connect = TlsConnector::builder().unwrap() - .build().unwrap() - .connect_async(&self.jid.domain, stream); + let connect = TlsConnector::from(NativeTlsConnector::builder() + .build().unwrap()) + .connect(&self.jid.domain, stream); let new_state = StartTlsClientState::StartingTls(connect); retry = true; (new_state, Ok(Async::NotReady)) From e9d30f16c3b6f8cceb355834b22daef6cd329ebb Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 6 Sep 2018 17:46:06 +0200 Subject: [PATCH 078/135] unstringify Error type --- Cargo.toml | 1 + src/client/auth.rs | 33 +++++++++------ src/client/bind.rs | 10 ++--- src/client/mod.rs | 85 +++++++++++++++++++------------------- src/component/auth.rs | 13 +++--- src/component/mod.rs | 43 +++++++++----------- src/error.rs | 94 +++++++++++++++++++++++++++++++++++++++++++ src/happy_eyeballs.rs | 21 +++++----- src/lib.rs | 6 ++- src/starttls.rs | 9 +++-- src/stream_start.rs | 74 ++++++++++++++++++++++++++++++---- src/xmpp_codec.rs | 57 ++------------------------ 12 files changed, 279 insertions(+), 167 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index 02a706d46ee65b2090cf5b1418f4ad65f0c8f653..f348e860a9ad7434385abc70a24dbcb4adc0fa34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,4 @@ xmpp-parsers = "0.11" idna = "0.1" try_from = "0.2" quick-xml = "0.12" +derive-error = "0.0.4" diff --git a/src/client/auth.rs b/src/client/auth.rs index 0dc66d1654455c29bf20e5ab0857d020fecdd324..97a6a12d30ba918adab6f3642cc540e0551e9092 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -13,9 +13,11 @@ use try_from::TryFrom; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; use stream_start::StreamStart; +use {Error, AuthError, ProtocolError}; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; + pub struct ClientAuth { state: ClientAuthState, mechanism: Box, @@ -29,7 +31,7 @@ enum ClientAuthState { } impl ClientAuth { - pub fn new(stream: XMPPStream, creds: Credentials) -> Result { + pub fn new(stream: XMPPStream, creds: Credentials) -> Result { let mechs: Vec> = vec![ Box::new(Scram::::from_credentials(creds.clone()).unwrap()), Box::new(Scram::::from_credentials(creds.clone()).unwrap()), @@ -40,7 +42,7 @@ impl ClientAuth { let mech_names: Vec = match stream.stream_features.get_child("mechanisms", NS_XMPP_SASL) { None => - return Err("No auth mechanisms".to_owned()), + return Err(AuthError::NoMechanism.into()), Some(mechs) => mechs.children() .filter(|child| child.is("mechanism", NS_XMPP_SASL)) @@ -53,13 +55,18 @@ impl ClientAuth { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { // println!("SASL mechanism selected: {:?}", name); - let initial = mech.initial()?; + let initial = match mech.initial() { + Ok(initial) => initial, + Err(e) => return Err(AuthError::Sasl(e).into()), + }; let mut this = ClientAuth { state: ClientAuthState::Invalid, mechanism: mech, }; - let mechanism = XMPPMechanism::from_str(&name) - .map_err(|e| format!("{:?}", e))?; + let mechanism = match XMPPMechanism::from_str(&name) { + Ok(mechanism) => mechanism, + Err(e) => return Err(ProtocolError::Parsers(e).into()), + }; this.send( stream, Auth { @@ -71,7 +78,7 @@ impl ClientAuth { } } - Err("No supported SASL mechanism available".to_owned()) + Err(AuthError::NoMechanism.into()) } fn send>(&mut self, stream: XMPPStream, nonza: N) { @@ -83,7 +90,7 @@ impl ClientAuth { impl Future for ClientAuth { type Item = XMPPStream; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll { let state = replace(&mut self.state, ClientAuthState::Invalid); @@ -100,13 +107,14 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(format!("{}", e)), + Err(e.into()), }, ClientAuthState::WaitRecv(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { if let Ok(challenge) = Challenge::try_from(stanza.clone()) { - let response = self.mechanism.response(&challenge.data)?; + let response = self.mechanism.response(&challenge.data) + .map_err(AuthError::Sasl)?; self.send(stream, Response { data: response }); self.poll() } else if let Ok(_) = Success::try_from(stanza.clone()) { @@ -114,8 +122,7 @@ impl Future for ClientAuth { self.state = ClientAuthState::Start(start); self.poll() } else if let Ok(failure) = Failure::try_from(stanza) { - let e = format!("{:?}", failure.defined_condition); - Err(e) + Err(AuthError::Fail(failure.defined_condition).into()) } else { Ok(Async::NotReady) } @@ -129,7 +136,7 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(format!("{}", e)), + Err(ProtocolError::Parser(e).into()) }, ClientAuthState::Start(mut start) => match start.poll() { @@ -140,7 +147,7 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(format!("{}", e)), + Err(e.into()) }, ClientAuthState::Invalid => unreachable!(), diff --git a/src/client/bind.rs b/src/client/bind.rs index 1ef268cc6a4f48f8ef6e01b02bba7d7ec297370b..974860befe8a616ad1f55e1bdb69aa5a312e531a 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,5 +1,4 @@ use std::mem::replace; -use std::error::Error; use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use xmpp_parsers::iq::{Iq, IqType}; @@ -8,6 +7,7 @@ use try_from::TryFrom; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; +use {Error, ProtocolError}; const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind"; const BIND_REQ_ID: &str = "resource-bind"; @@ -42,7 +42,7 @@ impl ClientBind { impl Future for ClientBind { type Item = XMPPStream; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll { let state = replace(self, ClientBind::Invalid); @@ -61,7 +61,7 @@ impl Future for ClientBind { Ok(Async::NotReady) }, Err(e) => - Err(e.description().to_owned()), + Err(e.into()) } }, ClientBind::WaitRecv(mut stream) => { @@ -80,7 +80,7 @@ impl Future for ClientBind { Ok(Async::Ready(stream)) }, _ => - Err("resource bind response".to_owned()), + Err(ProtocolError::InvalidBindResponse.into()), } } else { Ok(Async::NotReady) @@ -96,7 +96,7 @@ impl Future for ClientBind { Ok(Async::NotReady) }, Err(e) => - Err(e.description().to_owned()), + Err(e.into()), } }, ClientBind::Invalid => diff --git a/src/client/mod.rs b/src/client/mod.rs index 44dc8d0c34dd488fb066c38f8bfba965b2488008..b50e5392f60df95fd15bd98f26e44075e1cd77a6 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,11 +1,11 @@ use std::mem::replace; use std::str::FromStr; -use std::error::Error; +use std::error::Error as StdError; use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; -use futures::{future, Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; +use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink, done}; use minidom::Element; use jid::{Jid, JidParseError}; use sasl::common::{Credentials, ChannelBinding}; @@ -16,6 +16,7 @@ use super::xmpp_stream; use super::starttls::{NS_XMPP_TLS, StartTlsClient}; use super::happy_eyeballs::Connecter; use super::event::Event; +use super::{Error, ProtocolError}; mod auth; use self::auth::ClientAuth; @@ -35,7 +36,7 @@ const NS_JABBER_CLIENT: &str = "jabber:client"; enum ClientState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } @@ -50,47 +51,47 @@ impl Client { let connect = Self::make_connect(jid.clone(), password.clone(), handle); Ok(Client { jid, - state: ClientState::Connecting(connect), + state: ClientState::Connecting(Box::new(connect)), }) } - fn make_connect(jid: Jid, password: String, handle: Handle) -> Box> { + fn make_connect(jid: Jid, password: String, handle: Handle) -> impl Future { let username = jid.node.as_ref().unwrap().to_owned(); let jid1 = jid.clone(); let jid2 = jid.clone(); let password = password; - let domain = match idna::domain_to_ascii(&jid.domain) { - Ok(domain) => - domain, - Err(e) => - return Box::new(future::err(format!("{:?}", e))), - }; - Box::new( - Connecter::from_lookup(handle, &domain, "_xmpp-client._tcp", 5222) - .expect("Connector::from_lookup") - .and_then(move |tcp_stream| - xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) - .map_err(|e| format!("{}", e)) - ).and_then(|xmpp_stream| { - if Self::can_starttls(&xmpp_stream) { - Ok(Self::starttls(xmpp_stream)) - } else { - Err("No STARTTLS".to_owned()) - } - }).and_then(|starttls| - starttls - ).and_then(|tls_stream| - XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) - .map_err(|e| format!("{}", e)) - ).and_then(move |xmpp_stream| { - Self::auth(xmpp_stream, username, password).expect("auth") - }).and_then(|xmpp_stream| { - Self::bind(xmpp_stream) - }).and_then(|xmpp_stream| { - // println!("Bound to {}", xmpp_stream.jid); - Ok(xmpp_stream) - }) - ) + done(idna::domain_to_ascii(&jid.domain)) + .map_err(|_| Error::Idna) + .and_then(|domain| + done(Connecter::from_lookup(handle, &domain, "_xmpp-client._tcp", 5222)) + .map_err(Error::Domain) + ) + .and_then(|connecter| + connecter + .map_err(Error::Connection) + ).and_then(move |tcp_stream| + xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) + ).and_then(|xmpp_stream| { + if Self::can_starttls(&xmpp_stream) { + Ok(Self::starttls(xmpp_stream)) + } else { + Err(Error::Protocol(ProtocolError::NoTls)) + } + }).and_then(|starttls| + // TODO: flatten? + starttls + ).and_then(|tls_stream| + XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) + ).and_then(move |xmpp_stream| + done(Self::auth(xmpp_stream, username, password)) + // TODO: flatten? + ).and_then(|auth| auth) + .and_then(|xmpp_stream| { + Self::bind(xmpp_stream) + }).and_then(|xmpp_stream| { + // println!("Bound to {}", xmpp_stream.jid); + Ok(xmpp_stream) + }) } fn can_starttls(stream: &xmpp_stream::XMPPStream) -> bool { @@ -103,7 +104,7 @@ impl Client { StartTlsClient::from_stream(stream) } - fn auth(stream: xmpp_stream::XMPPStream, username: String, password: String) -> Result, String> { + fn auth(stream: xmpp_stream::XMPPStream, username: String, password: String) -> Result, Error> { let creds = Credentials::default() .with_username(username) .with_password(password) @@ -118,14 +119,14 @@ impl Client { impl Stream for Client { type Item = Event; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll, Self::Error> { let state = replace(&mut self.state, ClientState::Invalid); match state { ClientState::Invalid => - Err("invalid client state".to_owned()), + Err(Error::InvalidState), ClientState::Disconnected => Ok(Async::Ready(None)), ClientState::Connecting(mut connect) => { @@ -148,7 +149,7 @@ impl Stream for Client { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), Err(e) => - return Err(e.description().to_owned()), + return Err(Error::Io(e)), }; // Poll stream @@ -168,7 +169,7 @@ impl Stream for Client { Ok(Async::NotReady) }, Err(e) => - Err(e.description().to_owned()), + Err(e.into()), } }, } diff --git a/src/component/auth.rs b/src/component/auth.rs index 7801c92f2dd4538a9c551b62b21c5f0e2cba1e52..3b66511450527beff1c4901b68b6027d50414a1e 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -5,6 +5,7 @@ use xmpp_parsers::component::Handshake; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; +use {Error, AuthError}; const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; @@ -19,7 +20,8 @@ enum ComponentAuthState { } impl ComponentAuth { - pub fn new(stream: XMPPStream, password: String) -> Result { + // TODO: doesn't have to be a Result<> actually + pub fn new(stream: XMPPStream, password: String) -> Result { // FIXME: huge hack, shouldn’t be an element! let sid = stream.stream_features.name().to_owned(); let mut this = ComponentAuth { @@ -42,7 +44,7 @@ impl ComponentAuth { impl Future for ComponentAuth { type Item = XMPPStream; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll { let state = replace(&mut self.state, ComponentAuthState::Invalid); @@ -59,7 +61,7 @@ impl Future for ComponentAuth { Ok(Async::NotReady) }, Err(e) => - Err(format!("{}", e)), + Err(e.into()), }, ComponentAuthState::WaitRecv(mut stream) => match stream.poll() { @@ -72,8 +74,7 @@ impl Future for ComponentAuth { Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) if stanza.is("error", "http://etherx.jabber.org/streams") => { - let e = "Authentication failure"; - Err(e.to_owned()) + Err(AuthError::ComponentFail.into()) }, Ok(Async::Ready(event)) => { println!("ComponentAuth ignore {:?}", event); @@ -84,7 +85,7 @@ impl Future for ComponentAuth { Ok(Async::NotReady) }, Err(e) => - Err(format!("{}", e)), + Err(e.into()), }, ComponentAuthState::Invalid => unreachable!(), diff --git a/src/component/mod.rs b/src/component/mod.rs index bf9a005f24ce2bf3873edcab11304d83e030cecc..08ea6343871c21df540d43ddd49e314d1f53f991 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -3,11 +3,11 @@ //! allowed to use any user and resource identifiers in their stanzas. use std::mem::replace; use std::str::FromStr; -use std::error::Error; +use std::error::Error as StdError; use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; -use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink}; +use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink, done}; use minidom::Element; use jid::{Jid, JidParseError}; @@ -15,6 +15,7 @@ use super::xmpp_codec::Packet; use super::xmpp_stream; use super::happy_eyeballs::Connecter; use super::event::Event; +use super::Error; mod auth; use self::auth::ComponentAuth; @@ -32,7 +33,7 @@ const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; enum ComponentState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } @@ -47,43 +48,39 @@ impl Component { let connect = Self::make_connect(jid.clone(), password, server, port, handle); Ok(Component { jid, - state: ComponentState::Connecting(connect), + state: ComponentState::Connecting(Box::new(connect)), }) } - fn make_connect(jid: Jid, password: String, server: &str, port: u16, handle: Handle) -> Box> { + fn make_connect(jid: Jid, password: String, server: &str, port: u16, handle: Handle) -> impl Future { let jid1 = jid.clone(); let password = password; - Box::new( - Connecter::from_lookup(handle, server, "_xmpp-component._tcp", port) - .expect("Connector::from_lookup") - .and_then(move |tcp_stream| { - xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) - .map_err(|e| format!("{}", e)) - }).and_then(move |xmpp_stream| { - Self::auth(xmpp_stream, password).expect("auth") - }).and_then(|xmpp_stream| { - // println!("Bound to {}", xmpp_stream.jid); - Ok(xmpp_stream) - }) - ) + done(Connecter::from_lookup(handle, server, "_xmpp-component._tcp", port)) + .map_err(Error::Domain) + .and_then(|connecter| connecter + .map_err(Error::Connection) + ).and_then(move |tcp_stream| { + xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) + }).and_then(move |xmpp_stream| { + Self::auth(xmpp_stream, password).expect("auth") + }) } - fn auth(stream: xmpp_stream::XMPPStream, password: String) -> Result, String> { + fn auth(stream: xmpp_stream::XMPPStream, password: String) -> Result, Error> { ComponentAuth::new(stream, password) } } impl Stream for Component { type Item = Event; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll, Self::Error> { let state = replace(&mut self.state, ComponentState::Invalid); match state { ComponentState::Invalid => - Err("invalid client state".to_owned()), + Err(Error::InvalidState), ComponentState::Disconnected => Ok(Async::Ready(None)), ComponentState::Connecting(mut connect) => { @@ -106,7 +103,7 @@ impl Stream for Component { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), Err(e) => - return Err(e.description().to_owned()), + return Err(e.into()), }; // Poll stream @@ -129,7 +126,7 @@ impl Stream for Component { Ok(Async::NotReady) }, Err(e) => - Err(e.description().to_owned()), + Err(e.into()), } }, } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..7384f92ee71b2ad8382b57418d1d48c296dcf104 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,94 @@ +use std::io::Error as IoError; +use std::error::Error as StdError; +use std::str::Utf8Error; +use std::borrow::Cow; +use std::fmt; +use domain::resolv::error::Error as DNSError; +use domain::bits::name::FromStrError; +use native_tls::Error as TlsError; +use xmpp_parsers::error::Error as ParsersError; +use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; + +#[derive(Debug, Error)] +pub enum Error { + Io(IoError), + Connection(ConnecterError), + /// DNS label conversion error, no details available from module + /// `idna` + Idna, + Domain(FromStrError), + Protocol(ProtocolError), + Auth(AuthError), + Tls(TlsError), + /// Shoud never happen + InvalidState, +} + +/// Causes for stream parsing errors +#[derive(Debug, Error)] +pub enum ParserError { + /// Encoding error + Utf8(Utf8Error), + /// XML parse error + Parse(ParseError), + /// Illegal `` + ShortTag, + /// Required by `impl Decoder` + IO(IoError), +} + +impl From for Error { + fn from(e: ParserError) -> Self { + ProtocolError::Parser(e).into() + } +} + +/// XML parse error wrapper type +#[derive(Debug)] +pub struct ParseError(pub Cow<'static, str>); + +impl StdError for ParseError { + fn description(&self) -> &str { + self.0.as_ref() + } + fn cause(&self) -> Option<&StdError> { + None + } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +#[derive(Debug, Error)] +pub enum ProtocolError { + Parser(ParserError), + #[error(non_std)] + Parsers(ParsersError), + NoTls, + InvalidBindResponse, + NoStreamNamespace, + NoStreamId, + InvalidToken, +} + +#[derive(Debug, Error)] +pub enum AuthError { + /// No SASL mechanism available + NoMechanism, + #[error(no_from, non_std, msg_embedded)] + Sasl(String), + #[error(non_std)] + Fail(SaslDefinedCondition), + #[error(no_from)] + ComponentFail, +} + +#[derive(Debug, Error)] +pub enum ConnecterError { + NoSrv, + AllFailed, + DNS(DNSError), +} diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 7b95f8232402aa51a486aa83d312215af521160b..498079323f09ba10a159e9e77d59e934b7e2dc73 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -6,7 +6,8 @@ use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; use domain::resolv::Resolver; use domain::resolv::lookup::srv::{lookup_srv, LookupSrv, LookupSrvStream}; -use domain::bits::DNameBuf; +use domain::bits::name::{DNameBuf, FromStrError}; +use ConnecterError; pub struct Connecter { handle: Handle, @@ -17,11 +18,9 @@ pub struct Connecter { } impl Connecter { - pub fn from_lookup(handle: Handle, domain: &str, srv: &str, fallback_port: u16) -> Result { - let domain = DNameBuf::from_str(domain) - .map_err(|e| format!("{}", e))?; - let srv = DNameBuf::from_str(srv) - .map_err(|e| format!("{}", e))?; + pub fn from_lookup(handle: Handle, domain: &str, srv: &str, fallback_port: u16) -> Result { + let domain = DNameBuf::from_str(domain)?; + let srv = DNameBuf::from_str(srv)?; let resolver = Resolver::new(&handle); let lookup = lookup_srv(resolver.clone(), srv, domain, fallback_port); @@ -38,7 +37,7 @@ impl Connecter { impl Future for Connecter { type Item = TcpStream; - type Error = String; + type Error = ConnecterError; fn poll(&mut self) -> Poll { match self.lookup.as_mut().map(|lookup| lookup.poll()) { @@ -49,11 +48,11 @@ impl Future for Connecter { Some(srvs) => self.srvs = Some(srvs.to_stream(self.resolver.clone())), None => - return Err("No SRV records".to_owned()), + return Err(ConnecterError::NoSrv), } }, Some(Err(e)) => - return Err(format!("{}", e)), + return Err(e.into()), } match self.srvs.as_mut().map(|srv| srv.poll()) { @@ -71,7 +70,7 @@ impl Future for Connecter { } }, Some(Err(e)) => - return Err(format!("{}", e)), + return Err(e.into()), } let mut connected_stream = None; @@ -101,7 +100,7 @@ impl Future for Connecter { self.srvs.is_none() && self.connects.is_empty() { - return Err("All connection attempts failed".to_owned()); + return Err(ConnecterError::AllFailed); } Ok(Async::NotReady) diff --git a/src/lib.rs b/src/lib.rs index ebba1f1bd9baf5f1f77197ff0aff7bd684a99c72..19a0da68c2c35b0d89e648d70d85428a6b4e6e60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_code, unused, missing_docs)] +// #![deny(unsafe_code, unused, missing_docs)] //! XMPP implemeentation with asynchronous I/O using Tokio. @@ -18,6 +18,8 @@ extern crate domain; extern crate idna; extern crate xmpp_parsers; extern crate try_from; +#[macro_use] +extern crate derive_error; pub mod xmpp_codec; pub mod xmpp_stream; @@ -31,3 +33,5 @@ mod client; pub use client::Client; mod component; pub use component::Component; +mod error; +pub use error::{Error, ProtocolError, AuthError, ConnecterError, ParseError, ParserError}; diff --git a/src/starttls.rs b/src/starttls.rs index 6ac23acfb4d2025461005633c6a15b0969d08a24..444a9cb8b4b864f63f854ba0513afb1d1711adfd 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -10,6 +10,7 @@ use jid::Jid; use xmpp_codec::Packet; use xmpp_stream::XMPPStream; +use Error; /// XMPP TLS XML namespace pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; @@ -48,7 +49,7 @@ impl StartTlsClient { impl Future for StartTlsClient { type Item = TlsStream; - type Error = String; + type Error = Error; fn poll(&mut self) -> Poll { let old_state = replace(&mut self.state, StartTlsClientState::Invalid); @@ -65,7 +66,7 @@ impl Future for StartTlsClient { Ok(Async::NotReady) => (StartTlsClientState::SendStartTls(send), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::SendStartTls(send), Err(format!("{}", e))), + (StartTlsClientState::SendStartTls(send), Err(e.into())), }, StartTlsClientState::AwaitProceed(mut xmpp_stream) => match xmpp_stream.poll() { @@ -87,7 +88,7 @@ impl Future for StartTlsClient { Ok(_) => (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::AwaitProceed(xmpp_stream), Err(format!("{}", e))), + (StartTlsClientState::AwaitProceed(xmpp_stream), Err(Error::Protocol(e.into()))), }, StartTlsClientState::StartingTls(mut connect) => match connect.poll() { @@ -96,7 +97,7 @@ impl Future for StartTlsClient { Ok(Async::NotReady) => (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), Err(e) => - (StartTlsClientState::Invalid, Err(format!("{}", e))), + (StartTlsClientState::Invalid, Err(e.into())), }, StartTlsClientState::Invalid => unreachable!(), diff --git a/src/stream_start.rs b/src/stream_start.rs index aa1284e2f76634190d7440daccc86acb3512619a..8871840250b1f418dc58e8aaf9dd96d6dab35e3d 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,13 +1,15 @@ use std::mem::replace; -use std::borrow::Cow; +// use std::error::Error as StdError; +// use std::{fmt, io}; use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_codec::Framed; use jid::Jid; use minidom::Element; -use xmpp_codec::{XMPPCodec, Packet, ParserError}; +use xmpp_codec::{XMPPCodec, Packet}; use xmpp_stream::XMPPStream; +use {Error, ProtocolError}; const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -43,7 +45,7 @@ impl StreamStart { impl Future for StreamStart { type Item = XMPPStream; - type Error = ParserError; + type Error = Error; fn poll(&mut self) -> Poll { let old_state = replace(&mut self.state, StreamStartState::Invalid); @@ -67,7 +69,7 @@ impl Future for StreamStart { let stream_ns = match stream_attrs.get("xmlns") { Some(ns) => ns.clone(), None => - return Err(ParserError::Parse(Cow::from("Missing stream namespace"))), + return Err(ProtocolError::NoStreamNamespace.into()), }; if self.ns == "jabber:client" { retry = true; @@ -77,7 +79,7 @@ impl Future for StreamStart { let id = match stream_attrs.get("id") { Some(id) => id.clone(), None => - return Err(ParserError::Parse(Cow::from("No stream id"))), + return Err(ProtocolError::NoStreamId.into()), }; // FIXME: huge hack, shouldn’t be an element! let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), Element::builder(id).build()); @@ -85,11 +87,11 @@ impl Future for StreamStart { } }, Ok(Async::Ready(_)) => - return Err(ParserError::Parse(Cow::from("Invalid XML event received"))), + return Err(ProtocolError::InvalidToken.into()), Ok(Async::NotReady) => (StreamStartState::RecvStart(stream), Ok(Async::NotReady)), Err(e) => - return Err(e), + return Err(ProtocolError::from(e).into()), }, StreamStartState::RecvFeatures(mut stream, stream_ns) => match stream.poll() { @@ -103,7 +105,7 @@ impl Future for StreamStart { Ok(Async::Ready(_)) | Ok(Async::NotReady) => (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), Err(e) => - return Err(e), + return Err(ProtocolError::from(e).into()), }, StreamStartState::Invalid => unreachable!(), @@ -117,3 +119,59 @@ impl Future for StreamStart { } } } + +// #[derive(Debug)] +// pub enum StreamStartError { +// MissingStreamNs, +// MissingStreamId, +// Unexpected, +// Parser(ParserError), +// IO(io::Error), +// } + +// impl From for StreamStartError { +// fn from(e: io::Error) -> Self { +// StreamStartError::IO(e) +// } +// } + +// impl From for StreamStartError { +// fn from(e: ParserError) -> Self { +// match e { +// ParserError::IO(e) => StreamStartError::IO(e), +// _ => StreamStartError::Parser(e) +// } +// } +// } + +// impl StdError for StreamStartError { +// fn description(&self) -> &str { +// match *self { +// StreamStartError::MissingStreamNs => "Missing stream namespace", +// StreamStartError::MissingStreamId => "Missing stream id", +// StreamStartError::Unexpected => "Unexpected", +// StreamStartError::Parser(ref pe) => pe.description(), +// StreamStartError::IO(ref ie) => ie.description(), +// } +// } + +// fn cause(&self) -> Option<&StdError> { +// match *self { +// StreamStartError::Parser(ref pe) => pe.cause(), +// StreamStartError::IO(ref ie) => ie.cause(), +// _ => None, +// } +// } +// } + +// impl fmt::Display for StreamStartError { +// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +// match *self { +// StreamStartError::MissingStreamNs => write!(f, "Missing stream namespace"), +// StreamStartError::MissingStreamId => write!(f, "Missing stream id"), +// StreamStartError::Unexpected => write!(f, "Received unexpected data"), +// StreamStartError::Parser(ref pe) => write!(f, "{}", pe), +// StreamStartError::IO(ref ie) => write!(f, "{}", ie), +// } +// } +// } diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 09ea1ea4c123895ab253d3b8591fd13bef7e1a90..37e5a78c8dccb8d9d43ac6e2dc8bbc4d49205603 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -6,19 +6,17 @@ use std::iter::FromIterator; use std::cell::RefCell; use std::rc::Rc; use std::fmt::Write; -use std::str::{from_utf8, Utf8Error}; +use std::str::from_utf8; use std::io; use std::collections::HashMap; use std::collections::vec_deque::VecDeque; -use std::error::Error as StdError; -use std::fmt; -use std::borrow::Cow; use tokio_codec::{Encoder, Decoder}; use minidom::Element; use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; use quick_xml::Writer as EventWriter; +use {ParserError, ParseError}; /// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug)] @@ -33,55 +31,6 @@ pub enum Packet { StreamEnd, } -/// Causes for stream parsing errors -#[derive(Debug)] -pub enum ParserError { - /// Encoding error - Utf8(Utf8Error), - /// XML parse error - Parse(Cow<'static, str>), - /// Illegal `` - ShortTag, - /// Required by `impl Decoder` - IO(io::Error), -} - -impl From for ParserError { - fn from(e: io::Error) -> Self { - ParserError::IO(e) - } -} - -impl StdError for ParserError { - fn description(&self) -> &str { - match *self { - ParserError::Utf8(ref ue) => ue.description(), - ParserError::Parse(ref pe) => pe, - ParserError::ShortTag => "short tag", - ParserError::IO(ref ie) => ie.description(), - } - } - - fn cause(&self) -> Option<&StdError> { - match *self { - ParserError::Utf8(ref ue) => ue.cause(), - ParserError::IO(ref ie) => ie.cause(), - _ => None, - } - } -} - -impl fmt::Display for ParserError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ParserError::Utf8(ref ue) => write!(f, "{}", ue), - ParserError::Parse(ref pe) => write!(f, "{}", pe), - ParserError::ShortTag => write!(f, "Short tag"), - ParserError::IO(ref ie) => write!(f, "{}", ie), - } - } -} - type QueueItem = Result; /// Parser state @@ -220,7 +169,7 @@ impl TokenSink for ParserSink { self.push_queue(Packet::StreamEnd), Token::ParseError(s) => { // println!("ParseError: {:?}", s); - self.push_queue_error(ParserError::Parse(s)); + self.push_queue_error(ParserError::Parse(ParseError(s))); }, _ => (), } From f4007511ea32fba0dfca2074506459782f4a51e4 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 6 Sep 2018 23:57:42 +0200 Subject: [PATCH 079/135] improve style --- src/client/auth.rs | 37 +++++++++------------ src/client/bind.rs | 6 ++-- src/client/mod.rs | 6 ++-- src/component/auth.rs | 6 ++-- src/component/mod.rs | 6 ++-- src/happy_eyeballs.rs | 8 ++--- src/stream_start.rs | 76 ++++--------------------------------------- 7 files changed, 37 insertions(+), 108 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 97a6a12d30ba918adab6f3642cc540e0551e9092..55dfe2d2ac6a91c4137af9db756edcafd6ac904e 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -40,33 +40,26 @@ impl ClientAuth { ]; let mech_names: Vec = - match stream.stream_features.get_child("mechanisms", NS_XMPP_SASL) { - None => - return Err(AuthError::NoMechanism.into()), - Some(mechs) => - mechs.children() - .filter(|child| child.is("mechanism", NS_XMPP_SASL)) - .map(|mech_el| mech_el.text()) - .collect(), - }; + stream.stream_features.get_child("mechanisms", NS_XMPP_SASL) + .ok_or(AuthError::NoMechanism)? + .children() + .filter(|child| child.is("mechanism", NS_XMPP_SASL)) + .map(|mech_el| mech_el.text()) + .collect(); // println!("SASL mechanisms offered: {:?}", mech_names); for mut mech in mechs { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { // println!("SASL mechanism selected: {:?}", name); - let initial = match mech.initial() { - Ok(initial) => initial, - Err(e) => return Err(AuthError::Sasl(e).into()), - }; + let initial = mech.initial() + .map_err(AuthError::Sasl)?; let mut this = ClientAuth { state: ClientAuthState::Invalid, mechanism: mech, }; - let mechanism = match XMPPMechanism::from_str(&name) { - Ok(mechanism) => mechanism, - Err(e) => return Err(ProtocolError::Parsers(e).into()), - }; + let mechanism = XMPPMechanism::from_str(&name) + .map_err(ProtocolError::Parsers)?; this.send( stream, Auth { @@ -78,7 +71,7 @@ impl ClientAuth { } } - Err(AuthError::NoMechanism.into()) + Err(AuthError::NoMechanism)? } fn send>(&mut self, stream: XMPPStream, nonza: N) { @@ -107,7 +100,7 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)?, }, ClientAuthState::WaitRecv(mut stream) => match stream.poll() { @@ -122,7 +115,7 @@ impl Future for ClientAuth { self.state = ClientAuthState::Start(start); self.poll() } else if let Ok(failure) = Failure::try_from(stanza) { - Err(AuthError::Fail(failure.defined_condition).into()) + Err(AuthError::Fail(failure.defined_condition))? } else { Ok(Async::NotReady) } @@ -136,7 +129,7 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(ProtocolError::Parser(e).into()) + Err(ProtocolError::Parser(e))? }, ClientAuthState::Start(mut start) => match start.poll() { @@ -147,7 +140,7 @@ impl Future for ClientAuth { Ok(Async::NotReady) }, Err(e) => - Err(e.into()) + Err(e) }, ClientAuthState::Invalid => unreachable!(), diff --git a/src/client/bind.rs b/src/client/bind.rs index 974860befe8a616ad1f55e1bdb69aa5a312e531a..b0268e6eb777d6b66a6e8ee905a0a71975da682f 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -61,7 +61,7 @@ impl Future for ClientBind { Ok(Async::NotReady) }, Err(e) => - Err(e.into()) + Err(e)? } }, ClientBind::WaitRecv(mut stream) => { @@ -80,7 +80,7 @@ impl Future for ClientBind { Ok(Async::Ready(stream)) }, _ => - Err(ProtocolError::InvalidBindResponse.into()), + Err(ProtocolError::InvalidBindResponse)?, } } else { Ok(Async::NotReady) @@ -96,7 +96,7 @@ impl Future for ClientBind { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)?, } }, ClientBind::Invalid => diff --git a/src/client/mod.rs b/src/client/mod.rs index e3a36528e30179c951e9270b2082db29a3f4b113..6c3226c291795afcfc8ad337eba15ff296285833 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -147,7 +147,7 @@ impl Stream for Client { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), Err(e) => - return Err(e.into()), + return Err(e)?, }; // Poll stream @@ -167,7 +167,7 @@ impl Stream for Client { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)?, } }, } @@ -190,7 +190,7 @@ impl Sink for Client { Ok(AsyncSink::Ready) }, Err(e) => - Err(e.into()), + Err(e)?, }, _ => Ok(AsyncSink::NotReady(item)), diff --git a/src/component/auth.rs b/src/component/auth.rs index 3b66511450527beff1c4901b68b6027d50414a1e..b108ef3ffffe120ca7c038873677b070055cebc0 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -31,7 +31,7 @@ impl ComponentAuth { stream, Handshake::from_password_and_stream_id(&password, &sid) ); - return Ok(this); + Ok(this) } fn send(&mut self, stream: XMPPStream, handshake: Handshake) { @@ -61,7 +61,7 @@ impl Future for ComponentAuth { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)? }, ComponentAuthState::WaitRecv(mut stream) => match stream.poll() { @@ -85,7 +85,7 @@ impl Future for ComponentAuth { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)? }, ComponentAuthState::Invalid => unreachable!(), diff --git a/src/component/mod.rs b/src/component/mod.rs index 150ffd9a4d46344a31f8a1eac93b8bab5cde61a3..088d20d5675f98a5d62e4a41813c9147362fe8d8 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -100,7 +100,7 @@ impl Stream for Component { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), Err(e) => - return Err(e.into()), + return Err(e)?, }; // Poll stream @@ -123,7 +123,7 @@ impl Stream for Component { Ok(Async::NotReady) }, Err(e) => - Err(e.into()), + Err(e)?, } }, } @@ -146,7 +146,7 @@ impl Sink for Component { Ok(AsyncSink::Ready) }, Err(e) => - Err(e.into()), + Err(e)?, }, _ => Ok(AsyncSink::NotReady(item)), diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 0a5fd235873afd608556039106b55c4c3b04bf49..e3bebe9983fe5d789ca5da1b4ff4e83ff9f86cd0 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -50,13 +50,11 @@ impl Future for Connecter { fn poll(&mut self) -> Poll { if self.resolver_opt.is_none() { //println!("Poll resolver future"); - match self.resolver_future.poll() { - Ok(Async::Ready(resolver)) => + match self.resolver_future.poll()? { + Async::Ready(resolver) => self.resolver_opt = Some(resolver), - Ok(Async::NotReady) => + Async::NotReady => return Ok(Async::NotReady), - Err(e) => - return Err(e.into()), } } diff --git a/src/stream_start.rs b/src/stream_start.rs index 8871840250b1f418dc58e8aaf9dd96d6dab35e3d..ce9db27a8128eb42ac1296405c125379b5343cee 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,6 +1,4 @@ use std::mem::replace; -// use std::error::Error as StdError; -// use std::{fmt, io}; use futures::{Future, Async, Poll, Stream, sink, Sink}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_codec::Framed; @@ -66,22 +64,18 @@ impl Future for StreamStart { StreamStartState::RecvStart(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { - let stream_ns = match stream_attrs.get("xmlns") { - Some(ns) => ns.clone(), - None => - return Err(ProtocolError::NoStreamNamespace.into()), - }; + let stream_ns = stream_attrs.get("xmlns") + .ok_or(ProtocolError::NoStreamNamespace)? + .clone(); if self.ns == "jabber:client" { retry = true; // TODO: skip RecvFeatures for version < 1.0 (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) } else { - let id = match stream_attrs.get("id") { - Some(id) => id.clone(), - None => - return Err(ProtocolError::NoStreamId.into()), - }; - // FIXME: huge hack, shouldn’t be an element! + let id = stream_attrs.get("id") + .ok_or(ProtocolError::NoStreamId)? + .clone(); + // FIXME: huge hack, shouldn’t be an element! let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), Element::builder(id).build()); (StreamStartState::Invalid, Ok(Async::Ready(stream))) } @@ -119,59 +113,3 @@ impl Future for StreamStart { } } } - -// #[derive(Debug)] -// pub enum StreamStartError { -// MissingStreamNs, -// MissingStreamId, -// Unexpected, -// Parser(ParserError), -// IO(io::Error), -// } - -// impl From for StreamStartError { -// fn from(e: io::Error) -> Self { -// StreamStartError::IO(e) -// } -// } - -// impl From for StreamStartError { -// fn from(e: ParserError) -> Self { -// match e { -// ParserError::IO(e) => StreamStartError::IO(e), -// _ => StreamStartError::Parser(e) -// } -// } -// } - -// impl StdError for StreamStartError { -// fn description(&self) -> &str { -// match *self { -// StreamStartError::MissingStreamNs => "Missing stream namespace", -// StreamStartError::MissingStreamId => "Missing stream id", -// StreamStartError::Unexpected => "Unexpected", -// StreamStartError::Parser(ref pe) => pe.description(), -// StreamStartError::IO(ref ie) => ie.description(), -// } -// } - -// fn cause(&self) -> Option<&StdError> { -// match *self { -// StreamStartError::Parser(ref pe) => pe.cause(), -// StreamStartError::IO(ref ie) => ie.cause(), -// _ => None, -// } -// } -// } - -// impl fmt::Display for StreamStartError { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// match *self { -// StreamStartError::MissingStreamNs => write!(f, "Missing stream namespace"), -// StreamStartError::MissingStreamId => write!(f, "Missing stream id"), -// StreamStartError::Unexpected => write!(f, "Received unexpected data"), -// StreamStartError::Parser(ref pe) => write!(f, "{}", pe), -// StreamStartError::IO(ref ie) => write!(f, "{}", ie), -// } -// } -// } From 81191041c48c56c27ebcdae8c6b61aa48cd3419a Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 7 Sep 2018 00:12:00 +0200 Subject: [PATCH 080/135] improve style: flatten future --- src/client/mod.rs | 8 +- src/component/mod.rs | 4 +- src/happy_eyeballs.rs | 233 ++++++++++++++++++++++++------------------ 3 files changed, 138 insertions(+), 107 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 6c3226c291795afcfc8ad337eba15ff296285833..cf4553a052f29aaeb67922f6eb39dd41434ece3f 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -61,7 +61,7 @@ impl Client { done(idna::domain_to_ascii(&jid.domain)) .map_err(|_| Error::Idna) .and_then(|domain| - done(Connecter::from_lookup(&domain, "_xmpp-client._tcp", 5222)) + done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) .map_err(Error::Connection) ) .and_then(|connecter| @@ -75,10 +75,8 @@ impl Client { } else { Err(Error::Protocol(ProtocolError::NoTls)) } - }).and_then(|starttls| - // TODO: flatten? - starttls - ).and_then(|tls_stream| + }).flatten() + .and_then(|tls_stream| XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) ).and_then(move |xmpp_stream| done(Self::auth(xmpp_stream, username, password)) diff --git a/src/component/mod.rs b/src/component/mod.rs index 088d20d5675f98a5d62e4a41813c9147362fe8d8..e34ecd4da5a0b02184058080822b6de51a45ae33 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -53,8 +53,8 @@ impl Component { fn make_connect(jid: Jid, password: String, server: &str, port: u16) -> impl Future { let jid1 = jid.clone(); let password = password; - done(Connecter::from_lookup(server, "_xmpp-component._tcp", port)) - .and_then(|connecter| connecter) + done(Connecter::from_lookup(server, None, port)) + .flatten() .map_err(Error::Connection) .and_then(move |tcp_stream| { xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index e3bebe9983fe5d789ca5da1b4ff4e83ff9f86cd0..6b22cca04cf589c0eb319c0556376c2a71addbf2 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,44 +1,61 @@ use std::mem; -use std::net::{SocketAddr, IpAddr}; -use std::collections::{BTreeMap, btree_map}; +use std::net::SocketAddr; +use std::collections::BTreeMap; use std::collections::VecDeque; +use std::cell::RefCell; use futures::{Future, Poll, Async}; use tokio::net::{ConnectFuture, TcpStream}; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; -use trust_dns_proto::rr::rdata::srv::SRV; use ConnecterError; +enum State { + AwaitResolver(Box + Send>), + ResolveSrv(ResolverFuture, SrvLookupFuture), + ResolveTarget(ResolverFuture, LookupIpFuture, u16), + Connecting(Option, Vec>), + Invalid, +} + pub struct Connecter { fallback_port: u16, - name: Name, + srv_domain: Option, domain: Name, - resolver_future: Box + Send>, - resolver_opt: Option, - srv_lookup_opt: Option, - srvs_opt: Option>, - ip_lookup_opt: Option<(u16, LookupIpFuture)>, - ips_opt: Option<(u16, VecDeque)>, - connect_opt: Option, + state: State, + targets: VecDeque<(Name, u16)>, } impl Connecter { - pub fn from_lookup(domain: &str, srv: &str, fallback_port: u16) -> Result { + pub fn from_lookup(domain: &str, srv: Option<&str>, fallback_port: u16) -> Result { + if let Ok(ip) = domain.parse() { + // use specified IP address, not domain name, skip the whole dns part + let connect = + RefCell::new(TcpStream::connect(&SocketAddr::new(ip, fallback_port))); + return Ok(Connecter { + fallback_port, + srv_domain: None, + domain: "nohost".into_name()?, + state: State::Connecting(None, vec![connect]), + targets: VecDeque::new(), + }); + } + let resolver_future = ResolverFuture::from_system_conf()?; - let name = format!("{}.{}.", srv, domain).into_name()?; + let state = State::AwaitResolver(resolver_future); + let srv_domain = match srv { + Some(srv) => + Some(format!("{}.{}.", srv, domain).into_name()?), + None => + None, + }; Ok(Connecter { fallback_port, - name, + srv_domain, domain: domain.into_name()?, - resolver_future, - resolver_opt: None, - srv_lookup_opt: None, - srvs_opt: None, - ip_lookup_opt: None, - ips_opt: None, - connect_opt: None, + state, + targets: VecDeque::new(), }) } } @@ -48,102 +65,118 @@ impl Future for Connecter { type Error = ConnecterError; fn poll(&mut self) -> Poll { - if self.resolver_opt.is_none() { - //println!("Poll resolver future"); - match self.resolver_future.poll()? { - Async::Ready(resolver) => - self.resolver_opt = Some(resolver), - Async::NotReady => - return Ok(Async::NotReady), - } - } - - if let Some(ref resolver) = self.resolver_opt { - if self.srvs_opt.is_none() { - if self.srv_lookup_opt.is_none() { - //println!("Lookup srv: {:?}", self.name); - self.srv_lookup_opt = Some(resolver.lookup_srv(&self.name)); - } - - if let Some(ref mut srv_lookup) = self.srv_lookup_opt { - match srv_lookup.poll() { - Ok(Async::Ready(t)) => { - let mut srvs = BTreeMap::new(); - for srv in t.iter() { - srvs.insert(srv.priority(), srv.clone()); + let state = mem::replace(&mut self.state, State::Invalid); + match state { + State::AwaitResolver(mut resolver_future) => { + match resolver_future.poll()? { + Async::NotReady => { + self.state = State::AwaitResolver(resolver_future); + Ok(Async::NotReady) + } + Async::Ready(resolver) => { + match &self.srv_domain { + &Some(ref srv_domain) => { + let srv_lookup = resolver.lookup_srv(srv_domain); + self.state = State::ResolveSrv(resolver, srv_lookup); + } + None => { + self.targets = + [(self.domain.clone(), self.fallback_port)].into_iter() + .cloned() + .collect(); + self.state = State::Connecting(Some(resolver), vec![]); } - srvs.insert(65535, SRV::new(65535, 0, self.fallback_port, self.domain.clone())); - self.srvs_opt = Some(srvs.into_iter()); } - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(_) => { - //println!("Ignore SVR error: {:?}", e); - let mut srvs = BTreeMap::new(); - srvs.insert(65535, SRV::new(65535, 0, self.fallback_port, self.domain.clone())); - self.srvs_opt = Some(srvs.into_iter()); - }, + self.poll() } } } - - if self.connect_opt.is_none() { - if self.ips_opt.is_none() { - if self.ip_lookup_opt.is_none() { - if let Some(ref mut srvs) = self.srvs_opt { - if let Some((_, srv)) = srvs.next() { - //println!("Lookup ip: {:?}", srv); - self.ip_lookup_opt = Some((srv.port(), resolver.lookup_ip(srv.target()))); - } else { - return Err(ConnecterError::NoSrv); - } - } + State::ResolveSrv(resolver, mut srv_lookup) => { + match srv_lookup.poll() { + Ok(Async::NotReady) => { + self.state = State::ResolveSrv(resolver, srv_lookup); + Ok(Async::NotReady) } - - if let Some((port, mut ip_lookup)) = mem::replace(&mut self.ip_lookup_opt, None) { - match ip_lookup.poll() { - Ok(Async::Ready(t)) => { - let mut ip_deque = VecDeque::new(); - ip_deque.extend(t.iter()); - //println!("IPs: {:?}", ip_deque); - self.ips_opt = Some((port, ip_deque)); - self.ip_lookup_opt = None; - }, - Ok(Async::NotReady) => { - self.ip_lookup_opt = Some((port, ip_lookup)); - return Ok(Async::NotReady) - }, - Err(_) => { - //println!("Ignore lookup error: {:?}", e); - self.ip_lookup_opt = None; - } - } + Ok(Async::Ready(srv_result)) => { + let mut srv_map: BTreeMap<_, _> = + srv_result.iter() + .map(|srv| (srv.priority(), (srv.target().clone(), srv.port()))) + .collect(); + let targets = + srv_map.into_iter() + .map(|(_, tp)| tp) + .collect(); + self.targets = targets; + self.state = State::Connecting(Some(resolver), vec![]); + self.poll() + } + Err(_) => { + // ignore, fallback + self.targets = + [(self.domain.clone(), self.fallback_port)].into_iter() + .cloned() + .collect(); + self.state = State::Connecting(Some(resolver), vec![]); + self.poll() } } - - if let Some((port, mut ip_deque)) = mem::replace(&mut self.ips_opt, None) { - if let Some(ip) = ip_deque.pop_front() { - //println!("Connect to {:?}:{}", ip, port); - self.connect_opt = Some(TcpStream::connect(&SocketAddr::new(ip, port))); - self.ips_opt = Some((port, ip_deque)); + } + State::Connecting(resolver, mut connects) => { + if resolver.is_some() && + connects.len() == 0 && + self.targets.len() > 0 { + let resolver = resolver.unwrap(); + let (host, port) = self.targets.pop_front().unwrap(); + let ip_lookup = resolver.lookup_ip(host); + self.state = State::ResolveTarget(resolver, ip_lookup, port); + self.poll() + } else if connects.len() > 0 { + let mut success = None; + connects.retain(|connect| { + match connect.borrow_mut().poll() { + Ok(Async::NotReady) => true, + Ok(Async::Ready(connection)) => { + success = Some(connection); + false + } + Err(_) => false, + } + }); + match success { + Some(connection) => + Ok(Async::Ready(connection)), + None => { + self.state = State::Connecting(resolver, connects); + Ok(Async::NotReady) + }, } + } else { + Err(ConnecterError::AllFailed) } } - - if let Some(mut connect_future) = mem::replace(&mut self.connect_opt, None) { - match connect_future.poll() { - Ok(Async::Ready(t)) => return Ok(Async::Ready(t)), + State::ResolveTarget(resolver, mut ip_lookup, port) => { + match ip_lookup.poll() { Ok(Async::NotReady) => { - self.connect_opt = Some(connect_future); - return Ok(Async::NotReady) + self.state = State::ResolveTarget(resolver, ip_lookup, port); + Ok(Async::NotReady) + } + Ok(Async::Ready(ip_result)) => { + let connects = + ip_result.iter() + .map(|ip| RefCell::new(TcpStream::connect(&SocketAddr::new(ip, port)))) + .collect(); + self.state = State::Connecting(Some(resolver), connects); + self.poll() } Err(_) => { - //println!("Ignore connect error: {:?}", e); - }, + // ignore, next… + self.state = State::Connecting(Some(resolver), vec![]); + self.poll() + } } } + _ => panic!("") } - - Ok(Async::NotReady) } } From ce2ce363b02af8dbef6e23fbc9e833b1b98fdc6a Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 01:35:26 +0200 Subject: [PATCH 081/135] happy_eyeballs: propagate actual connection error --- src/client/mod.rs | 6 ++---- src/component/mod.rs | 1 - src/happy_eyeballs.rs | 43 +++++++++++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index cf4553a052f29aaeb67922f6eb39dd41434ece3f..d2af19c3bc56f1cc3eb6769bbe43da3b7d9e4e4e 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -64,10 +64,8 @@ impl Client { done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) .map_err(Error::Connection) ) - .and_then(|connecter| - connecter - .map_err(Error::Connection) - ).and_then(move |tcp_stream| + .flatten() + .and_then(move |tcp_stream| xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) ).and_then(|xmpp_stream| { if Self::can_starttls(&xmpp_stream) { diff --git a/src/component/mod.rs b/src/component/mod.rs index e34ecd4da5a0b02184058080822b6de51a45ae33..ce55e7ecdba1c7548c62c2b1e3c15fe4e4197c9e 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -55,7 +55,6 @@ impl Component { let password = password; done(Connecter::from_lookup(server, None, port)) .flatten() - .map_err(Error::Connection) .and_then(move |tcp_stream| { xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) }).and_then(move |xmpp_stream| { diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 6b22cca04cf589c0eb319c0556376c2a71addbf2..4a1185642e66a8bf0c5192d29af92244a66d2883 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -8,7 +8,7 @@ use tokio::net::{ConnectFuture, TcpStream}; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; -use ConnecterError; +use {Error, ConnecterError}; enum State { AwaitResolver(Box + Send>), @@ -24,6 +24,7 @@ pub struct Connecter { domain: Name, state: State, targets: VecDeque<(Name, u16)>, + error: Option, } impl Connecter { @@ -38,6 +39,7 @@ impl Connecter { domain: "nohost".into_name()?, state: State::Connecting(None, vec![connect]), targets: VecDeque::new(), + error: None, }); } @@ -56,19 +58,20 @@ impl Connecter { domain: domain.into_name()?, state, targets: VecDeque::new(), + error: None, }) } } impl Future for Connecter { type Item = TcpStream; - type Error = ConnecterError; + type Error = Error; fn poll(&mut self) -> Poll { let state = mem::replace(&mut self.state, State::Invalid); match state { State::AwaitResolver(mut resolver_future) => { - match resolver_future.poll()? { + match resolver_future.poll().map_err(ConnecterError::Resolve)? { Async::NotReady => { self.state = State::AwaitResolver(resolver_future); Ok(Async::NotReady) @@ -122,14 +125,12 @@ impl Future for Connecter { } } State::Connecting(resolver, mut connects) => { - if resolver.is_some() && - connects.len() == 0 && - self.targets.len() > 0 { - let resolver = resolver.unwrap(); - let (host, port) = self.targets.pop_front().unwrap(); - let ip_lookup = resolver.lookup_ip(host); - self.state = State::ResolveTarget(resolver, ip_lookup, port); - self.poll() + if resolver.is_some() && connects.len() == 0 && self.targets.len() > 0 { + let resolver = resolver.unwrap(); + let (host, port) = self.targets.pop_front().unwrap(); + let ip_lookup = resolver.lookup_ip(host); + self.state = State::ResolveTarget(resolver, ip_lookup, port); + self.poll() } else if connects.len() > 0 { let mut success = None; connects.retain(|connect| { @@ -139,7 +140,12 @@ impl Future for Connecter { success = Some(connection); false } - Err(_) => false, + Err(e) => { + if self.error.is_none() { + self.error = Some(e.into()); + } + false + }, } }); match success { @@ -151,7 +157,13 @@ impl Future for Connecter { }, } } else { - Err(ConnecterError::AllFailed) + // All targets tried + match self.error.take() { + None => + Err(ConnecterError::AllFailed.into()), + Some(e) => + Err(e), + } } } State::ResolveTarget(resolver, mut ip_lookup, port) => { @@ -168,7 +180,10 @@ impl Future for Connecter { self.state = State::Connecting(Some(resolver), connects); self.poll() } - Err(_) => { + Err(e) => { + if self.error.is_none() { + self.error = Some(ConnecterError::Resolve(e).into()); + } // ignore, next… self.state = State::Connecting(Some(resolver), vec![]); self.poll() From d3fab29d388754f21f76a881b1fffe0dc9b5d7d9 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 01:42:23 +0200 Subject: [PATCH 082/135] rm stale DomainError, add error docs --- src/error.rs | 46 ++++++++++++++++++++++------------------------ src/lib.rs | 2 +- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/error.rs b/src/error.rs index 541bbbfd4b1cb5733dabb33cfaf6ddb99a337244..43f5af1480b34de631a5a9dcd3679bb87d305611 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,15 +10,21 @@ use trust_dns_proto::error::ProtoError; use xmpp_parsers::error::Error as ParsersError; use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; +/// Top-level error type #[derive(Debug, Error)] pub enum Error { + /// I/O error Io(IoError), + /// Error resolving DNS and establishing a connection Connection(ConnecterError), /// DNS label conversion error, no details available from module /// `idna` Idna, + /// Protocol-level error Protocol(ProtocolError), + /// Authentication error Auth(AuthError), + /// TLS error Tls(TlsError), /// Shoud never happen InvalidState, @@ -62,57 +68,49 @@ impl fmt::Display for ParseError { } } +/// XMPP protocol-level error #[derive(Debug, Error)] pub enum ProtocolError { + /// XML parser error Parser(ParserError), + /// Error with expected stanza schema #[error(non_std)] Parsers(ParsersError), + /// No TLS available NoTls, + /// Invalid response to resource binding InvalidBindResponse, + /// No xmlns attribute in NoStreamNamespace, + /// No id attribute in NoStreamId, + /// Encountered an unexpected XML token InvalidToken, } +/// Authentication error #[derive(Debug, Error)] pub enum AuthError { - /// No SASL mechanism available + /// No matching SASL mechanism available NoMechanism, + /// Local SASL implementation error #[error(no_from, non_std, msg_embedded)] Sasl(String), + /// Failure from server #[error(non_std)] Fail(SaslDefinedCondition), + /// Component authentication failure #[error(no_from)] ComponentFail, } +/// Error establishing connection #[derive(Debug, Error)] pub enum ConnecterError { - NoSrv, + /// All attempts failed, no error available AllFailed, - /// DNS name error - Domain(DomainError), - /// DNS resolution error + /// DNS protocol error Dns(ProtoError), /// DNS resolution error Resolve(ResolveError), } - -/// DNS name error wrapper type -#[derive(Debug)] -pub struct DomainError(pub String); - -impl StdError for DomainError { - fn description(&self) -> &str { - &self.0 - } - fn cause(&self) -> Option<&StdError> { - None - } -} - -impl fmt::Display for DomainError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} diff --git a/src/lib.rs b/src/lib.rs index b23aefc6d400c450b824ea0bf49961346f3ce145..bed95b0722ccc7eecfe9b6bc4397d94343f136e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -// #![deny(unsafe_code, unused, missing_docs)] +#![deny(unsafe_code, unused, missing_docs)] //! XMPP implemeentation with asynchronous I/O using Tokio. From 662c61b801c5ec689e9b2e06146faf58813bb0c3 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 02:12:49 +0200 Subject: [PATCH 083/135] happy_eyeballs: enable parallel A/AAAA resolution --- src/client/mod.rs | 1 - src/happy_eyeballs.rs | 25 +++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index d2af19c3bc56f1cc3eb6769bbe43da3b7d9e4e4e..72634a2ee02c93077f967a7b00b30e908d8c11c4 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -62,7 +62,6 @@ impl Client { .map_err(|_| Error::Idna) .and_then(|domain| done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) - .map_err(Error::Connection) ) .flatten() .and_then(move |tcp_stream| diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 4a1185642e66a8bf0c5192d29af92244a66d2883..6d201fdee5d85ad861f92dc57d5758d873f528ab 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,4 +1,5 @@ use std::mem; +use std::io::Error as IoError; use std::net::SocketAddr; use std::collections::BTreeMap; use std::collections::VecDeque; @@ -8,6 +9,8 @@ use tokio::net::{ConnectFuture, TcpStream}; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; +use trust_dns_resolver::system_conf; +use trust_dns_resolver::config::LookupIpStrategy; use {Error, ConnecterError}; enum State { @@ -27,8 +30,14 @@ pub struct Connecter { error: Option, } +fn resolver_future() -> Result + Send>, IoError> { + let (conf, mut opts) = system_conf::read_system_conf()?; + opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; + Ok(ResolverFuture::new(conf, opts)) +} + impl Connecter { - pub fn from_lookup(domain: &str, srv: Option<&str>, fallback_port: u16) -> Result { + pub fn from_lookup(domain: &str, srv: Option<&str>, fallback_port: u16) -> Result { if let Ok(ip) = domain.parse() { // use specified IP address, not domain name, skip the whole dns part let connect = @@ -36,18 +45,21 @@ impl Connecter { return Ok(Connecter { fallback_port, srv_domain: None, - domain: "nohost".into_name()?, + domain: "nohost".into_name() + .map_err(ConnecterError::Dns)?, state: State::Connecting(None, vec![connect]), targets: VecDeque::new(), error: None, }); } - let resolver_future = ResolverFuture::from_system_conf()?; - let state = State::AwaitResolver(resolver_future); + let state = State::AwaitResolver(resolver_future()?); let srv_domain = match srv { Some(srv) => - Some(format!("{}.{}.", srv, domain).into_name()?), + Some(format!("{}.{}.", srv, domain) + .into_name() + .map_err(ConnecterError::Dns)? + ), None => None, }; @@ -55,7 +67,8 @@ impl Connecter { Ok(Connecter { fallback_port, srv_domain, - domain: domain.into_name()?, + domain: domain.into_name() + .map_err(ConnecterError::Dns)?, state, targets: VecDeque::new(), error: None, From 3954435d57aa13886b431b6c508423162ed75760 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 02:13:18 +0200 Subject: [PATCH 084/135] tokio-xmpp 0.2.0 --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 87c6bc83a191da9a08e7d1216c82c48de1ec7147..09a0343714303b99bcd4d454dd3f300666d8243d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tokio-xmpp" -version = "0.1.2" -authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep "] +version = "0.2.0" +authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" homepage = "https://github.com/astro/tokio-xmpp" @@ -15,7 +15,7 @@ futures = "0.1" tokio = "0.1" tokio-io = "0.1" tokio-codec = "0.1" -bytes = "0.4.9" +bytes = "0.4" xml5ever = "0.12" minidom = "0.9" native-tls = "0.2" From 3c829655810e1f2bb67dc55e1b3181b7ac4b2372 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 02:16:45 +0200 Subject: [PATCH 085/135] README: TODO update --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 52e43abd48e3b0c2092fc39398ce4740a092d399..eccc836f75a474b8eba96906767dfb7cdc5af3e4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,4 @@ - [ ] minidom ns - [ ] replace debug output with log crate - [ ] customize tls verify? -- [ ] Error type -- [ ] unexpected event errors -- [x] doc -- [ ] tests +- [ ] more tests From 4ab3890cd30b5bd5279a7e22b5546dc437afcb54 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Mon, 1 Oct 2018 12:34:33 +0200 Subject: [PATCH 086/135] Use tokio::net::tcp::ConnectFuture directly. This removes this warning: ``` warning: use of deprecated item 'tokio::net::ConnectFuture': use `tokio::net::tcp::ConnectFuture` instead ``` --- src/happy_eyeballs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 6d201fdee5d85ad861f92dc57d5758d873f528ab..6e7f02757fc0bd4711af1b9687ebc45e02217a07 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -5,7 +5,8 @@ use std::collections::BTreeMap; use std::collections::VecDeque; use std::cell::RefCell; use futures::{Future, Poll, Async}; -use tokio::net::{ConnectFuture, TcpStream}; +use tokio::net::TcpStream; +use tokio::net::tcp::ConnectFuture; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; From 24b2ff185107d59db0e8cfdb02c296e96122a43a Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 18 Dec 2018 18:29:31 +0100 Subject: [PATCH 087/135] Move to edition 2018. --- Cargo.toml | 1 + src/client/auth.rs | 8 ++++---- src/client/bind.rs | 6 +++--- src/component/auth.rs | 6 +++--- src/happy_eyeballs.rs | 2 +- src/lib.rs | 10 +++++----- src/starttls.rs | 6 +++--- src/stream_start.rs | 6 +++--- src/xmpp_codec.rs | 2 +- src/xmpp_stream.rs | 4 ++-- 10 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 09a0343714303b99bcd4d454dd3f300666d8243d..08ff17c5cb6fd35a4aca21d6e9eb933530257493 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ repository = "https://github.com/astro/tokio-xmpp" documentation = "https://docs.rs/tokio-xmpp" categories = ["asynchronous", "network-programming"] keywords = ["xmpp", "tokio"] +edition = "2018" [dependencies] futures = "0.1" diff --git a/src/client/auth.rs b/src/client/auth.rs index 55dfe2d2ac6a91c4137af9db756edcafd6ac904e..2efb7071ae1a7ef958dc64c7a51e490a824b73e7 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -10,10 +10,10 @@ use minidom::Element; use xmpp_parsers::sasl::{Auth, Challenge, Response, Success, Failure, Mechanism as XMPPMechanism}; use try_from::TryFrom; -use xmpp_codec::Packet; -use xmpp_stream::XMPPStream; -use stream_start::StreamStart; -use {Error, AuthError, ProtocolError}; +use crate::xmpp_codec::Packet; +use crate::xmpp_stream::XMPPStream; +use crate::stream_start::StreamStart; +use crate::{Error, AuthError, ProtocolError}; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; diff --git a/src/client/bind.rs b/src/client/bind.rs index b0268e6eb777d6b66a6e8ee905a0a71975da682f..bfcca2bee78201a5cee33d8afd39ecdf7058bcf5 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -5,9 +5,9 @@ use xmpp_parsers::iq::{Iq, IqType}; use xmpp_parsers::bind::Bind; use try_from::TryFrom; -use xmpp_codec::Packet; -use xmpp_stream::XMPPStream; -use {Error, ProtocolError}; +use crate::xmpp_codec::Packet; +use crate::xmpp_stream::XMPPStream; +use crate::{Error, ProtocolError}; const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind"; const BIND_REQ_ID: &str = "resource-bind"; diff --git a/src/component/auth.rs b/src/component/auth.rs index b108ef3ffffe120ca7c038873677b070055cebc0..ce55b3a9b2b9f365427721282872466beb5558ac 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -3,9 +3,9 @@ use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use xmpp_parsers::component::Handshake; -use xmpp_codec::Packet; -use xmpp_stream::XMPPStream; -use {Error, AuthError}; +use crate::xmpp_codec::Packet; +use crate::xmpp_stream::XMPPStream; +use crate::{Error, AuthError}; const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 6e7f02757fc0bd4711af1b9687ebc45e02217a07..7bdab7eeca16c999e75d9fb1cd1d90f9b9058759 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -12,7 +12,7 @@ use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; use trust_dns_resolver::system_conf; use trust_dns_resolver::config::LookupIpStrategy; -use {Error, ConnecterError}; +use crate::{Error, ConnecterError}; enum State { AwaitResolver(Box + Send>), diff --git a/src/lib.rs b/src/lib.rs index bed95b0722ccc7eecfe9b6bc4397d94343f136e1..f874315f8d1a4286d6d3e3e4171a4a802bb2c75b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,13 +26,13 @@ pub mod xmpp_codec; pub mod xmpp_stream; mod stream_start; mod starttls; -pub use starttls::StartTlsClient; +pub use crate::starttls::StartTlsClient; mod happy_eyeballs; mod event; -pub use event::Event; +pub use crate::event::Event; mod client; -pub use client::Client; +pub use crate::client::Client; mod component; -pub use component::Component; +pub use crate::component::Component; mod error; -pub use error::{Error, ProtocolError, AuthError, ConnecterError, ParseError, ParserError}; +pub use crate::error::{Error, ProtocolError, AuthError, ConnecterError, ParseError, ParserError}; diff --git a/src/starttls.rs b/src/starttls.rs index 5acfcb15b9ea99734284ba54a9186bac859c2100..a7f7fd392bc19c80f1be419441aa5d6e0e566697 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -8,9 +8,9 @@ use native_tls::TlsConnector as NativeTlsConnector; use minidom::Element; use jid::Jid; -use xmpp_codec::Packet; -use xmpp_stream::XMPPStream; -use Error; +use crate::xmpp_codec::Packet; +use crate::xmpp_stream::XMPPStream; +use crate::Error; /// XMPP TLS XML namespace pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; diff --git a/src/stream_start.rs b/src/stream_start.rs index ce9db27a8128eb42ac1296405c125379b5343cee..9aef117da7a622d2419cecd03256d4d9f31908bf 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -5,9 +5,9 @@ use tokio_codec::Framed; use jid::Jid; use minidom::Element; -use xmpp_codec::{XMPPCodec, Packet}; -use xmpp_stream::XMPPStream; -use {Error, ProtocolError}; +use crate::xmpp_codec::{XMPPCodec, Packet}; +use crate::xmpp_stream::XMPPStream; +use crate::{Error, ProtocolError}; const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 37e5a78c8dccb8d9d43ac6e2dc8bbc4d49205603..4088552c9c9fea4fb4b0690b22cccc54fb5f2b02 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -16,7 +16,7 @@ use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; use xml5ever::interface::Attribute; use bytes::{BytesMut, BufMut}; use quick_xml::Writer as EventWriter; -use {ParserError, ParseError}; +use crate::{ParserError, ParseError}; /// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug)] diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index c5443a98e54242bf100cefbb1fa9dad471c8fb8e..d8e878d5a2bf52451547808a090889cc2119c3bc 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -7,8 +7,8 @@ use tokio_codec::Framed; use minidom::Element; use jid::Jid; -use xmpp_codec::{XMPPCodec, Packet}; -use stream_start::StreamStart; +use crate::xmpp_codec::{XMPPCodec, Packet}; +use crate::stream_start::StreamStart; /// namespace pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; From 3aba4e707043c0b86ce1deebc27a9a8025564753 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 18 Dec 2018 19:04:02 +0100 Subject: [PATCH 088/135] Remove now-useless "extern crate"s. --- examples/echo_bot.rs | 8 -------- examples/echo_component.rs | 8 -------- src/happy_eyeballs.rs | 2 +- src/lib.rs | 17 ----------------- 4 files changed, 1 insertion(+), 34 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 138222609515f49ee5cc68c24b98c2c94f40f409..67cbfbb35f98097ac7f7750a4cce612fb27b0967 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,11 +1,3 @@ -extern crate futures; -extern crate tokio; -extern crate tokio_xmpp; -extern crate jid; -extern crate minidom; -extern crate xmpp_parsers; -extern crate try_from; - use std::env::args; use std::process::exit; use try_from::TryFrom; diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 1239354aa0fceb19cebfb8e039bd298da548d7fe..b9e24265dafb60473b32af6a00ae35f84ff8cf33 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -1,11 +1,3 @@ -extern crate futures; -extern crate tokio; -extern crate tokio_xmpp; -extern crate jid; -extern crate minidom; -extern crate xmpp_parsers; -extern crate try_from; - use std::env::args; use std::process::exit; use std::str::FromStr; diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 7bdab7eeca16c999e75d9fb1cd1d90f9b9058759..451f9c73499a9e6137c3f402b73de41fd14fd551 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -115,7 +115,7 @@ impl Future for Connecter { Ok(Async::NotReady) } Ok(Async::Ready(srv_result)) => { - let mut srv_map: BTreeMap<_, _> = + let srv_map: BTreeMap<_, _> = srv_result.iter() .map(|srv| (srv.priority(), (srv.target().clone(), srv.port()))) .collect(); diff --git a/src/lib.rs b/src/lib.rs index f874315f8d1a4286d6d3e3e4171a4a802bb2c75b..b1942119211f44ce2b68f0d30b05460875077cd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,23 +2,6 @@ //! XMPP implemeentation with asynchronous I/O using Tokio. -extern crate futures; -extern crate tokio; -extern crate tokio_io; -extern crate tokio_codec; -extern crate bytes; -extern crate xml5ever; -extern crate quick_xml; -extern crate minidom; -extern crate native_tls; -extern crate tokio_tls; -extern crate sasl; -extern crate jid; -extern crate trust_dns_resolver; -extern crate trust_dns_proto; -extern crate idna; -extern crate xmpp_parsers; -extern crate try_from; #[macro_use] extern crate derive_error; From 51bae9b0e5f97d0b36dc66f0306252b878fe17c8 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 18 Dec 2018 19:04:31 +0100 Subject: [PATCH 089/135] Run `cargo fmt` on the entire project. --- examples/echo_bot.rs | 24 ++--- examples/echo_component.rs | 35 +++++--- src/client/auth.rs | 130 +++++++++++++-------------- src/client/bind.rs | 107 +++++++++++------------ src/client/mod.rs | 142 +++++++++++++++--------------- src/component/auth.rs | 79 ++++++++--------- src/component/mod.rs | 110 +++++++++++------------ src/error.rs | 10 +-- src/happy_eyeballs.rs | 106 +++++++++++----------- src/lib.rs | 8 +- src/starttls.rs | 112 ++++++++++++------------ src/stream_start.rs | 133 +++++++++++++++------------- src/xmpp_codec.rs | 175 +++++++++++++++++-------------------- src/xmpp_stream.rs | 27 +++--- 14 files changed, 591 insertions(+), 607 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 67cbfbb35f98097ac7f7750a4cce612fb27b0967..80ffc97fcc142e4e035d3488abb05379a1c53008 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,13 +1,13 @@ +use futures::{future, Sink, Stream}; +use jid::Jid; +use minidom::Element; use std::env::args; use std::process::exit; -use try_from::TryFrom; -use futures::{Stream, Sink, future}; use tokio::runtime::current_thread::Runtime; use tokio_xmpp::Client; -use minidom::Element; -use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; -use xmpp_parsers::message::{Message, MessageType, Body}; -use jid::Jid; +use try_from::TryFrom; +use xmpp_parsers::message::{Body, Message, MessageType}; +use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; fn main() { let args: Vec = args().collect(); @@ -38,16 +38,18 @@ fn main() { let presence = make_presence(); send(presence); - } else if let Some(message) = event.into_stanza() + } else if let Some(message) = event + .into_stanza() .and_then(|stanza| Message::try_from(stanza).ok()) { // This is a message we'll echo match (message.from, message.bodies.get("")) { - (Some(from), Some(body)) => + (Some(from), Some(body)) => { if message.type_ != MessageType::Error { let reply = make_reply(from, &body.0); send(reply); - }, + } + } _ => (), } } @@ -69,7 +71,9 @@ fn main() { fn make_presence() -> Element { let mut presence = Presence::new(PresenceType::None); presence.show = PresenceShow::Chat; - presence.statuses.insert(String::from("en"), String::from("Echoing messages.")); + presence + .statuses + .insert(String::from("en"), String::from("Echoing messages.")); presence.into() } diff --git a/examples/echo_component.rs b/examples/echo_component.rs index b9e24265dafb60473b32af6a00ae35f84ff8cf33..348b06a4d2d812303943b996e514a966b945f610 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -1,14 +1,14 @@ +use futures::{future, Sink, Stream}; +use jid::Jid; +use minidom::Element; use std::env::args; use std::process::exit; use std::str::FromStr; -use try_from::TryFrom; use tokio::runtime::current_thread::Runtime; -use futures::{Stream, Sink, future}; use tokio_xmpp::Component; -use minidom::Element; -use xmpp_parsers::presence::{Presence, Type as PresenceType, Show as PresenceShow}; -use xmpp_parsers::message::{Message, MessageType, Body}; -use jid::Jid; +use try_from::TryFrom; +use xmpp_parsers::message::{Body, Message, MessageType}; +use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; fn main() { let args: Vec = args().collect(); @@ -18,7 +18,11 @@ fn main() { } let jid = &args[1]; let password = &args[2]; - let server = &args.get(3).unwrap().parse().unwrap_or("127.0.0.1".to_owned()); + let server = &args + .get(3) + .unwrap() + .parse() + .unwrap_or("127.0.0.1".to_owned()); let port: u16 = args.get(4).unwrap().parse().unwrap_or(5347u16); // tokio_core context @@ -42,18 +46,23 @@ fn main() { println!("Online!"); // TODO: replace these hardcoded JIDs - let presence = make_presence(Jid::from_str("test@component.linkmauve.fr/coucou").unwrap(), Jid::from_str("linkmauve@linkmauve.fr").unwrap()); + let presence = make_presence( + Jid::from_str("test@component.linkmauve.fr/coucou").unwrap(), + Jid::from_str("linkmauve@linkmauve.fr").unwrap(), + ); send(presence); - } else if let Some(message) = event.into_stanza() + } else if let Some(message) = event + .into_stanza() .and_then(|stanza| Message::try_from(stanza).ok()) { // This is a message we'll echo match (message.from, message.bodies.get("")) { - (Some(from), Some(body)) => + (Some(from), Some(body)) => { if message.type_ != MessageType::Error { let reply = make_reply(from, &body.0); send(reply); - }, + } + } _ => (), } } @@ -77,7 +86,9 @@ fn make_presence(from: Jid, to: Jid) -> Element { presence.from = Some(from); presence.to = Some(to); presence.show = PresenceShow::Chat; - presence.statuses.insert(String::from("en"), String::from("Echoing messages.")); + presence + .statuses + .insert(String::from("en"), String::from("Echoing messages.")); presence.into() } diff --git a/src/client/auth.rs b/src/client/auth.rs index 2efb7071ae1a7ef958dc64c7a51e490a824b73e7..eadceb02a63c873d607cd6b5efc25cecb3dbba6d 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,23 +1,22 @@ +use futures::{sink, Async, Future, Poll, Stream}; +use minidom::Element; +use sasl::client::mechanisms::{Anonymous, Plain, Scram}; +use sasl::client::Mechanism; +use sasl::common::scram::{Sha1, Sha256}; +use sasl::common::Credentials; use std::mem::replace; use std::str::FromStr; -use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; -use sasl::common::Credentials; -use sasl::common::scram::{Sha1, Sha256}; -use sasl::client::Mechanism; -use sasl::client::mechanisms::{Scram, Plain, Anonymous}; -use minidom::Element; -use xmpp_parsers::sasl::{Auth, Challenge, Response, Success, Failure, Mechanism as XMPPMechanism}; use try_from::TryFrom; +use xmpp_parsers::sasl::{Auth, Challenge, Failure, Mechanism as XMPPMechanism, Response, Success}; +use crate::stream_start::StreamStart; use crate::xmpp_codec::Packet; use crate::xmpp_stream::XMPPStream; -use crate::stream_start::StreamStart; -use crate::{Error, AuthError, ProtocolError}; +use crate::{AuthError, Error, ProtocolError}; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; - pub struct ClientAuth { state: ClientAuthState, mechanism: Box, @@ -39,8 +38,9 @@ impl ClientAuth { Box::new(Anonymous::new()), ]; - let mech_names: Vec = - stream.stream_features.get_child("mechanisms", NS_XMPP_SASL) + let mech_names: Vec = stream + .stream_features + .get_child("mechanisms", NS_XMPP_SASL) .ok_or(AuthError::NoMechanism)? .children() .filter(|child| child.is("mechanism", NS_XMPP_SASL)) @@ -52,20 +52,18 @@ impl ClientAuth { let name = mech.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { // println!("SASL mechanism selected: {:?}", name); - let initial = mech.initial() - .map_err(AuthError::Sasl)?; + let initial = mech.initial().map_err(AuthError::Sasl)?; let mut this = ClientAuth { state: ClientAuthState::Invalid, mechanism: mech, }; - let mechanism = XMPPMechanism::from_str(&name) - .map_err(ProtocolError::Parsers)?; + let mechanism = XMPPMechanism::from_str(&name).map_err(ProtocolError::Parsers)?; this.send( stream, Auth { mechanism, data: initial, - } + }, ); return Ok(this); } @@ -89,61 +87,55 @@ impl Future for ClientAuth { let state = replace(&mut self.state, ClientAuthState::Invalid); match state { - ClientAuthState::WaitSend(mut send) => - match send.poll() { - Ok(Async::Ready(stream)) => { - self.state = ClientAuthState::WaitRecv(stream); + ClientAuthState::WaitSend(mut send) => match send.poll() { + Ok(Async::Ready(stream)) => { + self.state = ClientAuthState::WaitRecv(stream); + self.poll() + } + Ok(Async::NotReady) => { + self.state = ClientAuthState::WaitSend(send); + Ok(Async::NotReady) + } + Err(e) => Err(e)?, + }, + ClientAuthState::WaitRecv(mut stream) => match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + if let Ok(challenge) = Challenge::try_from(stanza.clone()) { + let response = self + .mechanism + .response(&challenge.data) + .map_err(AuthError::Sasl)?; + self.send(stream, Response { data: response }); self.poll() - }, - Ok(Async::NotReady) => { - self.state = ClientAuthState::WaitSend(send); - Ok(Async::NotReady) - }, - Err(e) => - Err(e)?, - }, - ClientAuthState::WaitRecv(mut stream) => - match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { - if let Ok(challenge) = Challenge::try_from(stanza.clone()) { - let response = self.mechanism.response(&challenge.data) - .map_err(AuthError::Sasl)?; - self.send(stream, Response { data: response }); - self.poll() - } else if let Ok(_) = Success::try_from(stanza.clone()) { - let start = stream.restart(); - self.state = ClientAuthState::Start(start); - self.poll() - } else if let Ok(failure) = Failure::try_from(stanza) { - Err(AuthError::Fail(failure.defined_condition))? - } else { - Ok(Async::NotReady) - } - } - Ok(Async::Ready(_event)) => { - // println!("ClientAuth ignore {:?}", _event); - Ok(Async::NotReady) - }, - Ok(_) => { - self.state = ClientAuthState::WaitRecv(stream); - Ok(Async::NotReady) - }, - Err(e) => - Err(ProtocolError::Parser(e))? - }, - ClientAuthState::Start(mut start) => - match start.poll() { - Ok(Async::Ready(stream)) => - Ok(Async::Ready(stream)), - Ok(Async::NotReady) => { + } else if let Ok(_) = Success::try_from(stanza.clone()) { + let start = stream.restart(); self.state = ClientAuthState::Start(start); + self.poll() + } else if let Ok(failure) = Failure::try_from(stanza) { + Err(AuthError::Fail(failure.defined_condition))? + } else { Ok(Async::NotReady) - }, - Err(e) => - Err(e) - }, - ClientAuthState::Invalid => - unreachable!(), + } + } + Ok(Async::Ready(_event)) => { + // println!("ClientAuth ignore {:?}", _event); + Ok(Async::NotReady) + } + Ok(_) => { + self.state = ClientAuthState::WaitRecv(stream); + Ok(Async::NotReady) + } + Err(e) => Err(ProtocolError::Parser(e))?, + }, + ClientAuthState::Start(mut start) => match start.poll() { + Ok(Async::Ready(stream)) => Ok(Async::Ready(stream)), + Ok(Async::NotReady) => { + self.state = ClientAuthState::Start(start); + Ok(Async::NotReady) + } + Err(e) => Err(e), + }, + ClientAuthState::Invalid => unreachable!(), } } } diff --git a/src/client/bind.rs b/src/client/bind.rs index bfcca2bee78201a5cee33d8afd39ecdf7058bcf5..3758a563708083650694d4419f14bd186ba3d15d 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,9 +1,9 @@ +use futures::{sink, Async, Future, Poll, Stream}; use std::mem::replace; -use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; -use xmpp_parsers::iq::{Iq, IqType}; -use xmpp_parsers::bind::Bind; use try_from::TryFrom; +use xmpp_parsers::bind::Bind; +use xmpp_parsers::iq::{Iq, IqType}; use crate::xmpp_codec::Packet; use crate::xmpp_stream::XMPPStream; @@ -26,16 +26,17 @@ impl ClientBind { pub fn new(stream: XMPPStream) -> Self { match stream.stream_features.get_child("bind", NS_XMPP_BIND) { None => - // No resource binding available, - // return the (probably // usable) stream immediately - ClientBind::Unsupported(stream), + // No resource binding available, + // return the (probably // usable) stream immediately + { + ClientBind::Unsupported(stream) + } Some(_) => { let resource = stream.jid.resource.clone(); - let iq = Iq::from_set(Bind::new(resource)) - .with_id(BIND_REQ_ID.to_string()); + let iq = Iq::from_set(Bind::new(resource)).with_id(BIND_REQ_ID.to_string()); let send = stream.send_stanza(iq); ClientBind::WaitSend(send) - }, + } } } } @@ -48,59 +49,51 @@ impl Future for ClientBind { let state = replace(self, ClientBind::Invalid); match state { - ClientBind::Unsupported(stream) => - Ok(Async::Ready(stream)), - ClientBind::WaitSend(mut send) => { - match send.poll() { - Ok(Async::Ready(stream)) => { - replace(self, ClientBind::WaitRecv(stream)); - self.poll() - }, - Ok(Async::NotReady) => { - replace(self, ClientBind::WaitSend(send)); - Ok(Async::NotReady) - }, - Err(e) => - Err(e)? + ClientBind::Unsupported(stream) => Ok(Async::Ready(stream)), + ClientBind::WaitSend(mut send) => match send.poll() { + Ok(Async::Ready(stream)) => { + replace(self, ClientBind::WaitRecv(stream)); + self.poll() + } + Ok(Async::NotReady) => { + replace(self, ClientBind::WaitSend(send)); + Ok(Async::NotReady) } + Err(e) => Err(e)?, }, - ClientBind::WaitRecv(mut stream) => { - match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => - match Iq::try_from(stanza) { - Ok(iq) => if iq.id == Some(BIND_REQ_ID.to_string()) { - match iq.payload { - IqType::Result(payload) => { - payload - .and_then(|payload| Bind::try_from(payload).ok()) - .map(|bind| match bind { - Bind::Jid(jid) => stream.jid = jid, - _ => {} - }); - Ok(Async::Ready(stream)) - }, - _ => - Err(ProtocolError::InvalidBindResponse)?, + ClientBind::WaitRecv(mut stream) => match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => match Iq::try_from(stanza) { + Ok(iq) => { + if iq.id == Some(BIND_REQ_ID.to_string()) { + match iq.payload { + IqType::Result(payload) => { + payload + .and_then(|payload| Bind::try_from(payload).ok()) + .map(|bind| match bind { + Bind::Jid(jid) => stream.jid = jid, + _ => {} + }); + Ok(Async::Ready(stream)) } - } else { - Ok(Async::NotReady) - }, - _ => Ok(Async::NotReady), - }, - Ok(Async::Ready(_)) => { - replace(self, ClientBind::WaitRecv(stream)); - self.poll() - }, - Ok(Async::NotReady) => { - replace(self, ClientBind::WaitRecv(stream)); - Ok(Async::NotReady) - }, - Err(e) => - Err(e)?, + _ => Err(ProtocolError::InvalidBindResponse)?, + } + } else { + Ok(Async::NotReady) + } + } + _ => Ok(Async::NotReady), + }, + Ok(Async::Ready(_)) => { + replace(self, ClientBind::WaitRecv(stream)); + self.poll() + } + Ok(Async::NotReady) => { + replace(self, ClientBind::WaitRecv(stream)); + Ok(Async::NotReady) } + Err(e) => Err(e)?, }, - ClientBind::Invalid => - unreachable!(), + ClientBind::Invalid => unreachable!(), } } } diff --git a/src/client/mod.rs b/src/client/mod.rs index 72634a2ee02c93077f967a7b00b30e908d8c11c4..9e62373dc4f276d059b9203592ede8886139bfd4 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,19 +1,19 @@ +use futures::{done, Async, AsyncSink, Future, Poll, Sink, StartSend, Stream}; +use idna; +use jid::{Jid, JidParseError}; +use minidom::Element; +use sasl::common::{ChannelBinding, Credentials}; use std::mem::replace; use std::str::FromStr; use tokio::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_tls::TlsStream; -use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink, done}; -use minidom::Element; -use jid::{Jid, JidParseError}; -use sasl::common::{Credentials, ChannelBinding}; -use idna; +use super::event::Event; +use super::happy_eyeballs::Connecter; +use super::starttls::{StartTlsClient, NS_XMPP_TLS}; use super::xmpp_codec::Packet; use super::xmpp_stream; -use super::starttls::{NS_XMPP_TLS, StartTlsClient}; -use super::happy_eyeballs::Connecter; -use super::event::Event; use super::{Error, ProtocolError}; mod auth; @@ -34,7 +34,7 @@ const NS_JABBER_CLIENT: &str = "jabber:client"; enum ClientState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } @@ -53,51 +53,62 @@ impl Client { }) } - fn make_connect(jid: Jid, password: String) -> impl Future { + fn make_connect(jid: Jid, password: String) -> impl Future { let username = jid.node.as_ref().unwrap().to_owned(); let jid1 = jid.clone(); let jid2 = jid.clone(); let password = password; done(idna::domain_to_ascii(&jid.domain)) .map_err(|_| Error::Idna) - .and_then(|domain| - done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) - ) + .and_then(|domain| { + done(Connecter::from_lookup( + &domain, + Some("_xmpp-client._tcp"), + 5222, + )) + }) .flatten() - .and_then(move |tcp_stream| - xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) - ).and_then(|xmpp_stream| { + .and_then(move |tcp_stream| { + xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) + }) + .and_then(|xmpp_stream| { if Self::can_starttls(&xmpp_stream) { Ok(Self::starttls(xmpp_stream)) } else { Err(Error::Protocol(ProtocolError::NoTls)) } - }).flatten() - .and_then(|tls_stream| - XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned()) - ).and_then(move |xmpp_stream| - done(Self::auth(xmpp_stream, username, password)) - // TODO: flatten? - ).and_then(|auth| auth) + }) + .flatten() + .and_then(|tls_stream| XMPPStream::start(tls_stream, jid2, NS_JABBER_CLIENT.to_owned())) + .and_then( + move |xmpp_stream| done(Self::auth(xmpp_stream, username, password)), // TODO: flatten? + ) + .and_then(|auth| auth) + .and_then(|xmpp_stream| Self::bind(xmpp_stream)) .and_then(|xmpp_stream| { - Self::bind(xmpp_stream) - }).and_then(|xmpp_stream| { // println!("Bound to {}", xmpp_stream.jid); Ok(xmpp_stream) }) } fn can_starttls(stream: &xmpp_stream::XMPPStream) -> bool { - stream.stream_features + stream + .stream_features .get_child("starttls", NS_XMPP_TLS) .is_some() } - fn starttls(stream: xmpp_stream::XMPPStream) -> StartTlsClient { + fn starttls( + stream: xmpp_stream::XMPPStream, + ) -> StartTlsClient { StartTlsClient::from_stream(stream) } - fn auth(stream: xmpp_stream::XMPPStream, username: String, password: String) -> Result, Error> { + fn auth( + stream: xmpp_stream::XMPPStream, + username: String, + password: String, + ) -> Result, Error> { let creds = Credentials::default() .with_username(username) .with_password(password) @@ -118,31 +129,25 @@ impl Stream for Client { let state = replace(&mut self.state, ClientState::Invalid); match state { - ClientState::Invalid => - Err(Error::InvalidState), - ClientState::Disconnected => - Ok(Async::Ready(None)), - ClientState::Connecting(mut connect) => { - match connect.poll() { - Ok(Async::Ready(stream)) => { - self.state = ClientState::Connected(stream); - Ok(Async::Ready(Some(Event::Online))) - }, - Ok(Async::NotReady) => { - self.state = ClientState::Connecting(connect); - Ok(Async::NotReady) - }, - Err(e) => - Err(e), + ClientState::Invalid => Err(Error::InvalidState), + ClientState::Disconnected => Ok(Async::Ready(None)), + ClientState::Connecting(mut connect) => match connect.poll() { + Ok(Async::Ready(stream)) => { + self.state = ClientState::Connected(stream); + Ok(Async::Ready(Some(Event::Online))) + } + Ok(Async::NotReady) => { + self.state = ClientState::Connecting(connect); + Ok(Async::NotReady) } + Err(e) => Err(e), }, ClientState::Connected(mut stream) => { // Poll sink match stream.poll_complete() { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), - Err(e) => - return Err(e)?, + Err(e) => return Err(e)?, }; // Poll stream @@ -151,20 +156,18 @@ impl Stream for Client { // EOF self.state = ClientState::Disconnected; Ok(Async::Ready(Some(Event::Disconnected))) - }, + } Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { self.state = ClientState::Connected(stream); Ok(Async::Ready(Some(Event::Stanza(stanza)))) - }, - Ok(Async::NotReady) | - Ok(Async::Ready(_)) => { + } + Ok(Async::NotReady) | Ok(Async::Ready(_)) => { self.state = ClientState::Connected(stream); Ok(Async::NotReady) - }, - Err(e) => - Err(e)?, + } + Err(e) => Err(e)?, } - }, + } } } } @@ -175,30 +178,23 @@ impl Sink for Client { fn start_send(&mut self, item: Self::SinkItem) -> StartSend { match self.state { - ClientState::Connected(ref mut stream) => - match stream.start_send(Packet::Stanza(item)) { - Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => - Ok(AsyncSink::NotReady(stanza)), - Ok(AsyncSink::NotReady(_)) => - panic!("Client.start_send with stanza but got something else back"), - Ok(AsyncSink::Ready) => { - Ok(AsyncSink::Ready) - }, - Err(e) => - Err(e)?, - }, - _ => - Ok(AsyncSink::NotReady(item)), + ClientState::Connected(ref mut stream) => match stream.start_send(Packet::Stanza(item)) + { + Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => Ok(AsyncSink::NotReady(stanza)), + Ok(AsyncSink::NotReady(_)) => { + panic!("Client.start_send with stanza but got something else back") + } + Ok(AsyncSink::Ready) => Ok(AsyncSink::Ready), + Err(e) => Err(e)?, + }, + _ => Ok(AsyncSink::NotReady(item)), } } fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { match self.state { - ClientState::Connected(ref mut stream) => - stream.poll_complete() - .map_err(|e| e.into()), - _ => - Ok(Async::Ready(())), + ClientState::Connected(ref mut stream) => stream.poll_complete().map_err(|e| e.into()), + _ => Ok(Async::Ready(())), } } } diff --git a/src/component/auth.rs b/src/component/auth.rs index ce55b3a9b2b9f365427721282872466beb5558ac..92ae0903cd8ab4aa93a0658cd8a7486f521878f8 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -1,11 +1,11 @@ +use futures::{sink, Async, Future, Poll, Stream}; use std::mem::replace; -use futures::{Future, Poll, Async, sink, Stream}; use tokio_io::{AsyncRead, AsyncWrite}; use xmpp_parsers::component::Handshake; use crate::xmpp_codec::Packet; use crate::xmpp_stream::XMPPStream; -use crate::{Error, AuthError}; +use crate::{AuthError, Error}; const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; @@ -29,7 +29,7 @@ impl ComponentAuth { }; this.send( stream, - Handshake::from_password_and_stream_id(&password, &sid) + Handshake::from_password_and_stream_id(&password, &sid), ); Ok(this) } @@ -50,45 +50,40 @@ impl Future for ComponentAuth { let state = replace(&mut self.state, ComponentAuthState::Invalid); match state { - ComponentAuthState::WaitSend(mut send) => - match send.poll() { - Ok(Async::Ready(stream)) => { - self.state = ComponentAuthState::WaitRecv(stream); - self.poll() - }, - Ok(Async::NotReady) => { - self.state = ComponentAuthState::WaitSend(send); - Ok(Async::NotReady) - }, - Err(e) => - Err(e)? - }, - ComponentAuthState::WaitRecv(mut stream) => - match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) => - { - self.state = ComponentAuthState::Invalid; - Ok(Async::Ready(stream)) - }, - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.is("error", "http://etherx.jabber.org/streams") => - { - Err(AuthError::ComponentFail.into()) - }, - Ok(Async::Ready(event)) => { - println!("ComponentAuth ignore {:?}", event); - Ok(Async::NotReady) - }, - Ok(_) => { - self.state = ComponentAuthState::WaitRecv(stream); - Ok(Async::NotReady) - }, - Err(e) => - Err(e)? - }, - ComponentAuthState::Invalid => - unreachable!(), + ComponentAuthState::WaitSend(mut send) => match send.poll() { + Ok(Async::Ready(stream)) => { + self.state = ComponentAuthState::WaitRecv(stream); + self.poll() + } + Ok(Async::NotReady) => { + self.state = ComponentAuthState::WaitSend(send); + Ok(Async::NotReady) + } + Err(e) => Err(e)?, + }, + ComponentAuthState::WaitRecv(mut stream) => match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) => + { + self.state = ComponentAuthState::Invalid; + Ok(Async::Ready(stream)) + } + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.is("error", "http://etherx.jabber.org/streams") => + { + Err(AuthError::ComponentFail.into()) + } + Ok(Async::Ready(event)) => { + println!("ComponentAuth ignore {:?}", event); + Ok(Async::NotReady) + } + Ok(_) => { + self.state = ComponentAuthState::WaitRecv(stream); + Ok(Async::NotReady) + } + Err(e) => Err(e)?, + }, + ComponentAuthState::Invalid => unreachable!(), } } } diff --git a/src/component/mod.rs b/src/component/mod.rs index ce55e7ecdba1c7548c62c2b1e3c15fe4e4197c9e..aac66ab4e5e64e40eac3a5233b9cf7cc4831bf0e 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -1,18 +1,18 @@ //! Components in XMPP are services/gateways that are logged into an //! XMPP server under a JID consisting of just a domain name. They are //! allowed to use any user and resource identifiers in their stanzas. +use futures::{done, Async, AsyncSink, Future, Poll, Sink, StartSend, Stream}; +use jid::{Jid, JidParseError}; +use minidom::Element; use std::mem::replace; use std::str::FromStr; use tokio::net::TcpStream; use tokio_io::{AsyncRead, AsyncWrite}; -use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink, done}; -use minidom::Element; -use jid::{Jid, JidParseError}; +use super::event::Event; +use super::happy_eyeballs::Connecter; use super::xmpp_codec::Packet; use super::xmpp_stream; -use super::happy_eyeballs::Connecter; -use super::event::Event; use super::Error; mod auth; @@ -31,7 +31,7 @@ const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; enum ComponentState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } @@ -50,19 +50,30 @@ impl Component { }) } - fn make_connect(jid: Jid, password: String, server: &str, port: u16) -> impl Future { + fn make_connect( + jid: Jid, + password: String, + server: &str, + port: u16, + ) -> impl Future { let jid1 = jid.clone(); let password = password; done(Connecter::from_lookup(server, None, port)) .flatten() .and_then(move |tcp_stream| { - xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) - }).and_then(move |xmpp_stream| { - Self::auth(xmpp_stream, password).expect("auth") + xmpp_stream::XMPPStream::start( + tcp_stream, + jid1, + NS_JABBER_COMPONENT_ACCEPT.to_owned(), + ) }) + .and_then(move |xmpp_stream| Self::auth(xmpp_stream, password).expect("auth")) } - fn auth(stream: xmpp_stream::XMPPStream, password: String) -> Result, Error> { + fn auth( + stream: xmpp_stream::XMPPStream, + password: String, + ) -> Result, Error> { ComponentAuth::new(stream, password) } } @@ -75,31 +86,25 @@ impl Stream for Component { let state = replace(&mut self.state, ComponentState::Invalid); match state { - ComponentState::Invalid => - Err(Error::InvalidState), - ComponentState::Disconnected => - Ok(Async::Ready(None)), - ComponentState::Connecting(mut connect) => { - match connect.poll() { - Ok(Async::Ready(stream)) => { - self.state = ComponentState::Connected(stream); - Ok(Async::Ready(Some(Event::Online))) - }, - Ok(Async::NotReady) => { - self.state = ComponentState::Connecting(connect); - Ok(Async::NotReady) - }, - Err(e) => - Err(e), + ComponentState::Invalid => Err(Error::InvalidState), + ComponentState::Disconnected => Ok(Async::Ready(None)), + ComponentState::Connecting(mut connect) => match connect.poll() { + Ok(Async::Ready(stream)) => { + self.state = ComponentState::Connected(stream); + Ok(Async::Ready(Some(Event::Online))) + } + Ok(Async::NotReady) => { + self.state = ComponentState::Connecting(connect); + Ok(Async::NotReady) } + Err(e) => Err(e), }, ComponentState::Connected(mut stream) => { // Poll sink match stream.poll_complete() { Ok(Async::NotReady) => (), Ok(Async::Ready(())) => (), - Err(e) => - return Err(e)?, + Err(e) => return Err(e)?, }; // Poll stream @@ -107,24 +112,23 @@ impl Stream for Component { Ok(Async::NotReady) => { self.state = ComponentState::Connected(stream); Ok(Async::NotReady) - }, + } Ok(Async::Ready(None)) => { // EOF self.state = ComponentState::Disconnected; Ok(Async::Ready(Some(Event::Disconnected))) - }, + } Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { self.state = ComponentState::Connected(stream); Ok(Async::Ready(Some(Event::Stanza(stanza)))) - }, + } Ok(Async::Ready(_)) => { self.state = ComponentState::Connected(stream); Ok(Async::NotReady) - }, - Err(e) => - Err(e)?, + } + Err(e) => Err(e)?, } - }, + } } } } @@ -135,30 +139,26 @@ impl Sink for Component { fn start_send(&mut self, item: Self::SinkItem) -> StartSend { match self.state { - ComponentState::Connected(ref mut stream) => - match stream.start_send(Packet::Stanza(item)) { - Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => - Ok(AsyncSink::NotReady(stanza)), - Ok(AsyncSink::NotReady(_)) => - panic!("Component.start_send with stanza but got something else back"), - Ok(AsyncSink::Ready) => { - Ok(AsyncSink::Ready) - }, - Err(e) => - Err(e)?, - }, - _ => - Ok(AsyncSink::NotReady(item)), + ComponentState::Connected(ref mut stream) => match stream + .start_send(Packet::Stanza(item)) + { + Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => Ok(AsyncSink::NotReady(stanza)), + Ok(AsyncSink::NotReady(_)) => { + panic!("Component.start_send with stanza but got something else back") + } + Ok(AsyncSink::Ready) => Ok(AsyncSink::Ready), + Err(e) => Err(e)?, + }, + _ => Ok(AsyncSink::NotReady(item)), } } fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { match &mut self.state { - &mut ComponentState::Connected(ref mut stream) => - stream.poll_complete() - .map_err(|e| e.into()), - _ => - Ok(Async::Ready(())), + &mut ComponentState::Connected(ref mut stream) => { + stream.poll_complete().map_err(|e| e.into()) + } + _ => Ok(Async::Ready(())), } } } diff --git a/src/error.rs b/src/error.rs index 43f5af1480b34de631a5a9dcd3679bb87d305611..26d794495ebff0562e894f022a955b1ea44e32c0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,11 @@ -use std::io::Error as IoError; -use std::error::Error as StdError; -use std::str::Utf8Error; +use native_tls::Error as TlsError; use std::borrow::Cow; +use std::error::Error as StdError; use std::fmt; -use native_tls::Error as TlsError; -use trust_dns_resolver::error::ResolveError; +use std::io::Error as IoError; +use std::str::Utf8Error; use trust_dns_proto::error::ProtoError; +use trust_dns_resolver::error::ResolveError; use xmpp_parsers::error::Error as ParsersError; use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 451f9c73499a9e6137c3f402b73de41fd14fd551..19dbe4939d4e7e51d84fa8843646ddd10cef5eac 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -1,18 +1,18 @@ -use std::mem; -use std::io::Error as IoError; -use std::net::SocketAddr; +use crate::{ConnecterError, Error}; +use futures::{Async, Future, Poll}; +use std::cell::RefCell; use std::collections::BTreeMap; use std::collections::VecDeque; -use std::cell::RefCell; -use futures::{Future, Poll, Async}; -use tokio::net::TcpStream; +use std::io::Error as IoError; +use std::mem; +use std::net::SocketAddr; use tokio::net::tcp::ConnectFuture; -use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; +use tokio::net::TcpStream; +use trust_dns_resolver::config::LookupIpStrategy; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; use trust_dns_resolver::system_conf; -use trust_dns_resolver::config::LookupIpStrategy; -use crate::{Error, ConnecterError}; +use trust_dns_resolver::{error::ResolveError, IntoName, Name, ResolverFuture}; enum State { AwaitResolver(Box + Send>), @@ -31,23 +31,26 @@ pub struct Connecter { error: Option, } -fn resolver_future() -> Result + Send>, IoError> { +fn resolver_future( +) -> Result + Send>, IoError> { let (conf, mut opts) = system_conf::read_system_conf()?; opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; Ok(ResolverFuture::new(conf, opts)) } impl Connecter { - pub fn from_lookup(domain: &str, srv: Option<&str>, fallback_port: u16) -> Result { + pub fn from_lookup( + domain: &str, + srv: Option<&str>, + fallback_port: u16, + ) -> Result { if let Ok(ip) = domain.parse() { // use specified IP address, not domain name, skip the whole dns part - let connect = - RefCell::new(TcpStream::connect(&SocketAddr::new(ip, fallback_port))); + let connect = RefCell::new(TcpStream::connect(&SocketAddr::new(ip, fallback_port))); return Ok(Connecter { fallback_port, srv_domain: None, - domain: "nohost".into_name() - .map_err(ConnecterError::Dns)?, + domain: "nohost".into_name().map_err(ConnecterError::Dns)?, state: State::Connecting(None, vec![connect]), targets: VecDeque::new(), error: None, @@ -56,20 +59,18 @@ impl Connecter { let state = State::AwaitResolver(resolver_future()?); let srv_domain = match srv { - Some(srv) => - Some(format!("{}.{}.", srv, domain) - .into_name() - .map_err(ConnecterError::Dns)? - ), - None => - None, + Some(srv) => Some( + format!("{}.{}.", srv, domain) + .into_name() + .map_err(ConnecterError::Dns)?, + ), + None => None, }; Ok(Connecter { fallback_port, srv_domain, - domain: domain.into_name() - .map_err(ConnecterError::Dns)?, + domain: domain.into_name().map_err(ConnecterError::Dns)?, state, targets: VecDeque::new(), error: None, @@ -97,8 +98,8 @@ impl Future for Connecter { self.state = State::ResolveSrv(resolver, srv_lookup); } None => { - self.targets = - [(self.domain.clone(), self.fallback_port)].into_iter() + self.targets = [(self.domain.clone(), self.fallback_port)] + .into_iter() .cloned() .collect(); self.state = State::Connecting(Some(resolver), vec![]); @@ -115,22 +116,19 @@ impl Future for Connecter { Ok(Async::NotReady) } Ok(Async::Ready(srv_result)) => { - let srv_map: BTreeMap<_, _> = - srv_result.iter() + let srv_map: BTreeMap<_, _> = srv_result + .iter() .map(|srv| (srv.priority(), (srv.target().clone(), srv.port()))) .collect(); - let targets = - srv_map.into_iter() - .map(|(_, tp)| tp) - .collect(); + let targets = srv_map.into_iter().map(|(_, tp)| tp).collect(); self.targets = targets; self.state = State::Connecting(Some(resolver), vec![]); self.poll() } Err(_) => { // ignore, fallback - self.targets = - [(self.domain.clone(), self.fallback_port)].into_iter() + self.targets = [(self.domain.clone(), self.fallback_port)] + .into_iter() .cloned() .collect(); self.state = State::Connecting(Some(resolver), vec![]); @@ -147,36 +145,31 @@ impl Future for Connecter { self.poll() } else if connects.len() > 0 { let mut success = None; - connects.retain(|connect| { - match connect.borrow_mut().poll() { - Ok(Async::NotReady) => true, - Ok(Async::Ready(connection)) => { - success = Some(connection); - false + connects.retain(|connect| match connect.borrow_mut().poll() { + Ok(Async::NotReady) => true, + Ok(Async::Ready(connection)) => { + success = Some(connection); + false + } + Err(e) => { + if self.error.is_none() { + self.error = Some(e.into()); } - Err(e) => { - if self.error.is_none() { - self.error = Some(e.into()); - } - false - }, + false } }); match success { - Some(connection) => - Ok(Async::Ready(connection)), + Some(connection) => Ok(Async::Ready(connection)), None => { self.state = State::Connecting(resolver, connects); Ok(Async::NotReady) - }, + } } } else { // All targets tried match self.error.take() { - None => - Err(ConnecterError::AllFailed.into()), - Some(e) => - Err(e), + None => Err(ConnecterError::AllFailed.into()), + Some(e) => Err(e), } } } @@ -187,8 +180,8 @@ impl Future for Connecter { Ok(Async::NotReady) } Ok(Async::Ready(ip_result)) => { - let connects = - ip_result.iter() + let connects = ip_result + .iter() .map(|ip| RefCell::new(TcpStream::connect(&SocketAddr::new(ip, port)))) .collect(); self.state = State::Connecting(Some(resolver), connects); @@ -204,8 +197,7 @@ impl Future for Connecter { } } } - _ => panic!("") + _ => panic!(""), } } } - diff --git a/src/lib.rs b/src/lib.rs index b1942119211f44ce2b68f0d30b05460875077cd0..39876b1917baaed46289aa35a5fd7e5d7997d36a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,17 +5,17 @@ #[macro_use] extern crate derive_error; +mod starttls; +mod stream_start; pub mod xmpp_codec; pub mod xmpp_stream; -mod stream_start; -mod starttls; pub use crate::starttls::StartTlsClient; -mod happy_eyeballs; mod event; +mod happy_eyeballs; pub use crate::event::Event; mod client; pub use crate::client::Client; mod component; pub use crate::component::Component; mod error; -pub use crate::error::{Error, ProtocolError, AuthError, ConnecterError, ParseError, ParserError}; +pub use crate::error::{AuthError, ConnecterError, Error, ParseError, ParserError, ProtocolError}; diff --git a/src/starttls.rs b/src/starttls.rs index a7f7fd392bc19c80f1be419441aa5d6e0e566697..e48d1824a1220f98b70b015098cc9c93ec9a9b0a 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -1,12 +1,12 @@ -use std::mem::replace; -use futures::{Future, Sink, Poll, Async}; -use futures::stream::Stream; use futures::sink; -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_tls::{TlsStream, TlsConnector, Connect}; -use native_tls::TlsConnector as NativeTlsConnector; -use minidom::Element; +use futures::stream::Stream; +use futures::{Async, Future, Poll, Sink}; use jid::Jid; +use minidom::Element; +use native_tls::TlsConnector as NativeTlsConnector; +use std::mem::replace; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_tls::{Connect, TlsConnector, TlsStream}; use crate::xmpp_codec::Packet; use crate::xmpp_stream::XMPPStream; @@ -15,7 +15,6 @@ use crate::Error; /// XMPP TLS XML namespace pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; - /// XMPP stream that switches to TLS if available in received features pub struct StartTlsClient { state: StartTlsClientState, @@ -34,9 +33,7 @@ impl StartTlsClient { pub fn from_stream(xmpp_stream: XMPPStream) -> Self { let jid = xmpp_stream.jid.clone(); - let nonza = Element::builder("starttls") - .ns(NS_XMPP_TLS) - .build(); + let nonza = Element::builder("starttls").ns(NS_XMPP_TLS).build(); let packet = Packet::Stanza(nonza); let send = xmpp_stream.send(packet); @@ -56,51 +53,56 @@ impl Future for StartTlsClient { let mut retry = false; let (new_state, result) = match old_state { - StartTlsClientState::SendStartTls(mut send) => - match send.poll() { - Ok(Async::Ready(xmpp_stream)) => { - let new_state = StartTlsClientState::AwaitProceed(xmpp_stream); - retry = true; - (new_state, Ok(Async::NotReady)) - }, - Ok(Async::NotReady) => - (StartTlsClientState::SendStartTls(send), Ok(Async::NotReady)), - Err(e) => - (StartTlsClientState::SendStartTls(send), Err(e.into())), - }, - StartTlsClientState::AwaitProceed(mut xmpp_stream) => - match xmpp_stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) - if stanza.name() == "proceed" => - { - let stream = xmpp_stream.stream.into_inner(); - let connect = TlsConnector::from(NativeTlsConnector::builder() - .build().unwrap()) + StartTlsClientState::SendStartTls(mut send) => match send.poll() { + Ok(Async::Ready(xmpp_stream)) => { + let new_state = StartTlsClientState::AwaitProceed(xmpp_stream); + retry = true; + (new_state, Ok(Async::NotReady)) + } + Ok(Async::NotReady) => { + (StartTlsClientState::SendStartTls(send), Ok(Async::NotReady)) + } + Err(e) => (StartTlsClientState::SendStartTls(send), Err(e.into())), + }, + StartTlsClientState::AwaitProceed(mut xmpp_stream) => match xmpp_stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(ref stanza)))) + if stanza.name() == "proceed" => + { + let stream = xmpp_stream.stream.into_inner(); + let connect = + TlsConnector::from(NativeTlsConnector::builder().build().unwrap()) .connect(&self.jid.domain, stream); - let new_state = StartTlsClientState::StartingTls(connect); - retry = true; - (new_state, Ok(Async::NotReady)) - }, - Ok(Async::Ready(value)) => { - println!("StartTlsClient ignore {:?}", value); - (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)) - }, - Ok(_) => - (StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady)), - Err(e) => - (StartTlsClientState::AwaitProceed(xmpp_stream), Err(Error::Protocol(e.into()))), - }, - StartTlsClientState::StartingTls(mut connect) => - match connect.poll() { - Ok(Async::Ready(tls_stream)) => - (StartTlsClientState::Invalid, Ok(Async::Ready(tls_stream))), - Ok(Async::NotReady) => - (StartTlsClientState::StartingTls(connect), Ok(Async::NotReady)), - Err(e) => - (StartTlsClientState::Invalid, Err(e.into())), - }, - StartTlsClientState::Invalid => - unreachable!(), + let new_state = StartTlsClientState::StartingTls(connect); + retry = true; + (new_state, Ok(Async::NotReady)) + } + Ok(Async::Ready(value)) => { + println!("StartTlsClient ignore {:?}", value); + ( + StartTlsClientState::AwaitProceed(xmpp_stream), + Ok(Async::NotReady), + ) + } + Ok(_) => ( + StartTlsClientState::AwaitProceed(xmpp_stream), + Ok(Async::NotReady), + ), + Err(e) => ( + StartTlsClientState::AwaitProceed(xmpp_stream), + Err(Error::Protocol(e.into())), + ), + }, + StartTlsClientState::StartingTls(mut connect) => match connect.poll() { + Ok(Async::Ready(tls_stream)) => { + (StartTlsClientState::Invalid, Ok(Async::Ready(tls_stream))) + } + Ok(Async::NotReady) => ( + StartTlsClientState::StartingTls(connect), + Ok(Async::NotReady), + ), + Err(e) => (StartTlsClientState::Invalid, Err(e.into())), + }, + StartTlsClientState::Invalid => unreachable!(), }; self.state = new_state; diff --git a/src/stream_start.rs b/src/stream_start.rs index 9aef117da7a622d2419cecd03256d4d9f31908bf..0a5945b7bda5e6d8dae908f23d20c59b3b5bb4e6 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,11 +1,11 @@ -use std::mem::replace; -use futures::{Future, Async, Poll, Stream, sink, Sink}; -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_codec::Framed; +use futures::{sink, Async, Future, Poll, Sink, Stream}; use jid::Jid; use minidom::Element; +use std::mem::replace; +use tokio_codec::Framed; +use tokio_io::{AsyncRead, AsyncWrite}; -use crate::xmpp_codec::{XMPPCodec, Packet}; +use crate::xmpp_codec::{Packet, XMPPCodec}; use crate::xmpp_stream::XMPPStream; use crate::{Error, ProtocolError}; @@ -26,11 +26,15 @@ enum StreamStartState { impl StreamStart { pub fn from_stream(stream: Framed, jid: Jid, ns: String) -> Self { - let attrs = [("to".to_owned(), jid.domain.clone()), - ("version".to_owned(), "1.0".to_owned()), - ("xmlns".to_owned(), ns.clone()), - ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), - ].iter().cloned().collect(); + let attrs = [ + ("to".to_owned(), jid.domain.clone()), + ("version".to_owned(), "1.0".to_owned()), + ("xmlns".to_owned(), ns.clone()), + ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), + ] + .iter() + .cloned() + .collect(); let send = stream.send(Packet::StreamStart(attrs)); StreamStart { @@ -50,59 +54,66 @@ impl Future for StreamStart { let mut retry = false; let (new_state, result) = match old_state { - StreamStartState::SendStart(mut send) => - match send.poll() { - Ok(Async::Ready(stream)) => { + StreamStartState::SendStart(mut send) => match send.poll() { + Ok(Async::Ready(stream)) => { + retry = true; + (StreamStartState::RecvStart(stream), Ok(Async::NotReady)) + } + Ok(Async::NotReady) => (StreamStartState::SendStart(send), Ok(Async::NotReady)), + Err(e) => (StreamStartState::Invalid, Err(e.into())), + }, + StreamStartState::RecvStart(mut stream) => match stream.poll() { + Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { + let stream_ns = stream_attrs + .get("xmlns") + .ok_or(ProtocolError::NoStreamNamespace)? + .clone(); + if self.ns == "jabber:client" { retry = true; - (StreamStartState::RecvStart(stream), Ok(Async::NotReady)) - }, - Ok(Async::NotReady) => - (StreamStartState::SendStart(send), Ok(Async::NotReady)), - Err(e) => - (StreamStartState::Invalid, Err(e.into())), - }, - StreamStartState::RecvStart(mut stream) => - match stream.poll() { - Ok(Async::Ready(Some(Packet::StreamStart(stream_attrs)))) => { - let stream_ns = stream_attrs.get("xmlns") - .ok_or(ProtocolError::NoStreamNamespace)? + // TODO: skip RecvFeatures for version < 1.0 + ( + StreamStartState::RecvFeatures(stream, stream_ns), + Ok(Async::NotReady), + ) + } else { + let id = stream_attrs + .get("id") + .ok_or(ProtocolError::NoStreamId)? .clone(); - if self.ns == "jabber:client" { - retry = true; - // TODO: skip RecvFeatures for version < 1.0 - (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) - } else { - let id = stream_attrs.get("id") - .ok_or(ProtocolError::NoStreamId)? - .clone(); - // FIXME: huge hack, shouldn’t be an element! - let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), Element::builder(id).build()); - (StreamStartState::Invalid, Ok(Async::Ready(stream))) - } - }, - Ok(Async::Ready(_)) => - return Err(ProtocolError::InvalidToken.into()), - Ok(Async::NotReady) => - (StreamStartState::RecvStart(stream), Ok(Async::NotReady)), - Err(e) => - return Err(ProtocolError::from(e).into()), - }, - StreamStartState::RecvFeatures(mut stream, stream_ns) => - match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => - if stanza.is("features", NS_XMPP_STREAM) { - let stream = XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), stanza); - (StreamStartState::Invalid, Ok(Async::Ready(stream))) - } else { - (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)) - }, - Ok(Async::Ready(_)) | Ok(Async::NotReady) => - (StreamStartState::RecvFeatures(stream, stream_ns), Ok(Async::NotReady)), - Err(e) => - return Err(ProtocolError::from(e).into()), - }, - StreamStartState::Invalid => - unreachable!(), + // FIXME: huge hack, shouldn’t be an element! + let stream = XMPPStream::new( + self.jid.clone(), + stream, + self.ns.clone(), + Element::builder(id).build(), + ); + (StreamStartState::Invalid, Ok(Async::Ready(stream))) + } + } + Ok(Async::Ready(_)) => return Err(ProtocolError::InvalidToken.into()), + Ok(Async::NotReady) => (StreamStartState::RecvStart(stream), Ok(Async::NotReady)), + Err(e) => return Err(ProtocolError::from(e).into()), + }, + StreamStartState::RecvFeatures(mut stream, stream_ns) => match stream.poll() { + Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + if stanza.is("features", NS_XMPP_STREAM) { + let stream = + XMPPStream::new(self.jid.clone(), stream, self.ns.clone(), stanza); + (StreamStartState::Invalid, Ok(Async::Ready(stream))) + } else { + ( + StreamStartState::RecvFeatures(stream, stream_ns), + Ok(Async::NotReady), + ) + } + } + Ok(Async::Ready(_)) | Ok(Async::NotReady) => ( + StreamStartState::RecvFeatures(stream, stream_ns), + Ok(Async::NotReady), + ), + Err(e) => return Err(ProtocolError::from(e).into()), + }, + StreamStartState::Invalid => unreachable!(), }; self.state = new_state; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 4088552c9c9fea4fb4b0690b22cccc54fb5f2b02..e8c4e0538e1b47d308e947bc25d548e9a1ec83b6 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -1,22 +1,22 @@ //! XML stream parser for XMPP +use crate::{ParseError, ParserError}; +use bytes::{BufMut, BytesMut}; +use minidom::Element; +use quick_xml::Writer as EventWriter; use std; +use std::cell::RefCell; +use std::collections::vec_deque::VecDeque; +use std::collections::HashMap; use std::default::Default; +use std::fmt::Write; +use std::io; use std::iter::FromIterator; -use std::cell::RefCell; use std::rc::Rc; -use std::fmt::Write; use std::str::from_utf8; -use std::io; -use std::collections::HashMap; -use std::collections::vec_deque::VecDeque; -use tokio_codec::{Encoder, Decoder}; -use minidom::Element; -use xml5ever::tokenizer::{XmlTokenizer, TokenSink, Token, Tag, TagKind}; +use tokio_codec::{Decoder, Encoder}; use xml5ever::interface::Attribute; -use bytes::{BytesMut, BufMut}; -use quick_xml::Writer as EventWriter; -use crate::{ParserError, ParseError}; +use xml5ever::tokenizer::{Tag, TagKind, Token, TokenSink, XmlTokenizer}; /// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug)] @@ -72,17 +72,21 @@ impl ParserSink { fn handle_start_tag(&mut self, tag: Tag) { let mut nss = HashMap::new(); - let is_prefix_xmlns = |attr: &Attribute| attr.name.prefix.as_ref() - .map(|prefix| prefix.eq_str_ignore_ascii_case("xmlns")) - .unwrap_or(false); + let is_prefix_xmlns = |attr: &Attribute| { + attr.name + .prefix + .as_ref() + .map(|prefix| prefix.eq_str_ignore_ascii_case("xmlns")) + .unwrap_or(false) + }; for attr in &tag.attrs { match attr.name.local.as_ref() { "xmlns" => { nss.insert(None, attr.value.as_ref().to_owned()); - }, + } prefix if is_prefix_xmlns(attr) => { - nss.insert(Some(prefix.to_owned()), attr.value.as_ref().to_owned()); - }, + nss.insert(Some(prefix.to_owned()), attr.value.as_ref().to_owned()); + } _ => (), } } @@ -90,10 +94,9 @@ impl ParserSink { let el = { let mut el_builder = Element::builder(tag.name.local.as_ref()); - if let Some(el_ns) = self.lookup_ns( - &tag.name.prefix.map(|prefix| - prefix.as_ref().to_owned()) - ) { + if let Some(el_ns) = + self.lookup_ns(&tag.name.prefix.map(|prefix| prefix.as_ref().to_owned())) + { el_builder = el_builder.ns(el_ns); } for attr in &tag.attrs { @@ -101,21 +104,20 @@ impl ParserSink { "xmlns" => (), _ if is_prefix_xmlns(attr) => (), _ => { - el_builder = el_builder.attr( - attr.name.local.as_ref(), - attr.value.as_ref() - ); - }, + el_builder = el_builder.attr(attr.name.local.as_ref(), attr.value.as_ref()); + } } } el_builder.build() }; if self.stack.is_empty() { - let attrs = HashMap::from_iter( - tag.attrs.iter() - .map(|attr| (attr.name.local.as_ref().to_owned(), attr.value.as_ref().to_owned())) - ); + let attrs = HashMap::from_iter(tag.attrs.iter().map(|attr| { + ( + attr.name.local.as_ref().to_owned(), + attr.value.as_ref().to_owned(), + ) + })); self.push_queue(Packet::StreamStart(attrs)); } @@ -128,15 +130,13 @@ impl ParserSink { match self.stack.len() { // - 0 => - self.push_queue(Packet::StreamEnd), + 0 => self.push_queue(Packet::StreamEnd), // - 1 => - self.push_queue(Packet::Stanza(el)), + 1 => self.push_queue(Packet::Stanza(el)), len => { let parent = &mut self.stack[len - 1]; parent.append_child(el); - }, + } } } } @@ -145,32 +145,26 @@ impl TokenSink for ParserSink { fn process_token(&mut self, token: Token) { match token { Token::TagToken(tag) => match tag.kind { - TagKind::StartTag => - self.handle_start_tag(tag), - TagKind::EndTag => - self.handle_end_tag(), + TagKind::StartTag => self.handle_start_tag(tag), + TagKind::EndTag => self.handle_end_tag(), TagKind::EmptyTag => { self.handle_start_tag(tag); self.handle_end_tag(); - }, - TagKind::ShortTag => - self.push_queue_error(ParserError::ShortTag), + } + TagKind::ShortTag => self.push_queue_error(ParserError::ShortTag), }, - Token::CharacterTokens(tendril) => - match self.stack.len() { - 0 | 1 => - self.push_queue(Packet::Text(tendril.into())), - len => { - let el = &mut self.stack[len - 1]; - el.append_text_node(tendril); - }, - }, - Token::EOFToken => - self.push_queue(Packet::StreamEnd), + Token::CharacterTokens(tendril) => match self.stack.len() { + 0 | 1 => self.push_queue(Packet::Text(tendril.into())), + len => { + let el = &mut self.stack[len - 1]; + el.append_text_node(tendril); + } + }, + Token::EOFToken => self.push_queue(Packet::StreamEnd), Token::ParseError(s) => { // println!("ParseError: {:?}", s); self.push_queue_error(ParserError::Parse(ParseError(s))); - }, + } _ => (), } } @@ -219,23 +213,22 @@ impl Decoder for XMPPCodec { type Error = ParserError; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - let buf1: Box> = - if ! self.buf.is_empty() && ! buf.is_empty() { - let mut prefix = std::mem::replace(&mut self.buf, vec![]); - prefix.extend_from_slice(buf.take().as_ref()); - Box::new(prefix) - } else { - Box::new(buf.take()) - }; + let buf1: Box> = if !self.buf.is_empty() && !buf.is_empty() { + let mut prefix = std::mem::replace(&mut self.buf, vec![]); + prefix.extend_from_slice(buf.take().as_ref()); + Box::new(prefix) + } else { + Box::new(buf.take()) + }; let buf1 = buf1.as_ref().as_ref(); match from_utf8(buf1) { Ok(s) => { - if ! s.is_empty() { + if !s.is_empty() { // println!("<< {}", s); let tendril = FromIterator::from_iter(s.chars()); self.parser.feed(tendril); } - }, + } // Remedies for truncated utf8 Err(e) if e.valid_up_to() >= buf1.len() - 3 => { // Prepare all the valid data @@ -249,17 +242,16 @@ impl Decoder for XMPPCodec { self.buf.extend_from_slice(&buf1[e.valid_up_to()..]); return result; - }, + } Err(e) => { // println!("error {} at {}/{} in {:?}", e, e.valid_up_to(), buf1.len(), buf1); return Err(ParserError::Utf8(e)); - }, + } } match self.queue.borrow_mut().pop_front() { None => Ok(None), - Some(result) => - result.map(|pkt| Some(pkt)), + Some(result) => result.map(|pkt| Some(pkt)), } } @@ -284,8 +276,7 @@ impl Encoder for XMPPCodec { let mut buf = String::new(); write!(buf, "\n").unwrap(); print!(">> {}", buf); - write!(dst, "{}", buf) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e)) - }, + write!(dst, "{}", buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e)) + } Packet::Stanza(stanza) => { - stanza.write_to_inner(&mut EventWriter::new(WriteBytes::new(dst))) + stanza + .write_to_inner(&mut EventWriter::new(WriteBytes::new(dst))) .and_then(|_| { // println!(">> {:?}", dst); Ok(()) }) .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) - }, + } Packet::Text(text) => { write_text(&text, dst) .and_then(|_| { @@ -311,9 +302,9 @@ impl Encoder for XMPPCodec { Ok(()) }) .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) - }, + } // TODO: Implement all - _ => Ok(()) + _ => Ok(()), } } } @@ -334,7 +325,7 @@ pub fn escape(input: &str) -> String { '>' => result.push_str(">"), '\'' => result.push_str("'"), '"' => result.push_str("""), - o => result.push(o) + o => result.push(o), } } result @@ -364,7 +355,6 @@ impl<'a> std::io::Write for WriteBytes<'a> { } } - #[cfg(test)] mod tests { use super::*; @@ -405,10 +395,7 @@ mod tests { b.put(r">"); let r = c.decode(&mut b); assert!(match r { - Ok(Some(Packet::Stanza(ref el))) - if el.name() == "test" - && el.text() == "ß" - => true, + Ok(Some(Packet::Stanza(ref el))) if el.name() == "test" && el.text() == "ß" => true, _ => false, }); } @@ -436,10 +423,7 @@ mod tests { b.put(&b"\x9f"[..]); let r = c.decode(&mut b); assert!(match r { - Ok(Some(Packet::Stanza(ref el))) - if el.name() == "test" - && el.text() == "ß" - => true, + Ok(Some(Packet::Stanza(ref el))) if el.name() == "test" && el.text() == "ß" => true, _ => false, }); } @@ -447,8 +431,8 @@ mod tests { /// By default, encode() only get's a BytesMut that has 8kb space reserved. #[test] fn test_large_stanza() { - use std::io::Cursor; use futures::{Future, Sink}; + use std::io::Cursor; use tokio_codec::FramedWrite; let framed = FramedWrite::new(Cursor::new(vec![]), XMPPCodec::new()); let mut text = "".to_owned(); @@ -456,15 +440,12 @@ mod tests { text = text + "A"; } let stanza = Element::builder("message") - .append( - Element::builder("body") - .append(&text) - .build() - ) + .append(Element::builder("body").append(&text).build()) .build(); - let framed = framed.send(Packet::Stanza(stanza)) - .wait() - .expect("send"); - assert_eq!(framed.get_ref().get_ref(), &("".to_owned() + &text + "").as_bytes()); + let framed = framed.send(Packet::Stanza(stanza)).wait().expect("send"); + assert_eq!( + framed.get_ref().get_ref(), + &("".to_owned() + &text + "").as_bytes() + ); } } diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index d8e878d5a2bf52451547808a090889cc2119c3bc..c67cc1efdd6ea8b53e84c784b2e88b4829fb6772 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -1,14 +1,14 @@ //! `XMPPStream` is the common container for all XMPP network connections -use futures::{Poll, Stream, Sink, StartSend}; use futures::sink::Send; -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_codec::Framed; -use minidom::Element; +use futures::{Poll, Sink, StartSend, Stream}; use jid::Jid; +use minidom::Element; +use tokio_codec::Framed; +use tokio_io::{AsyncRead, AsyncWrite}; -use crate::xmpp_codec::{XMPPCodec, Packet}; use crate::stream_start::StreamStart; +use crate::xmpp_codec::{Packet, XMPPCodec}; /// namespace pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; @@ -30,11 +30,18 @@ pub struct XMPPStream { impl XMPPStream { /// Constructor - pub fn new(jid: Jid, - stream: Framed, - ns: String, - stream_features: Element) -> Self { - XMPPStream { jid, stream, stream_features, ns } + pub fn new( + jid: Jid, + stream: Framed, + ns: String, + stream_features: Element, + ) -> Self { + XMPPStream { + jid, + stream, + stream_features, + ns, + } } /// Send a `` start tag From c7132493cf199099e0d32fdd4f1bec3be4af3566 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 17:30:32 +0100 Subject: [PATCH 090/135] Cargo: update paths for move to gitlab.com --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08ff17c5cb6fd35a4aca21d6e9eb933530257493..b6c86df71ea6a722313cfe86ea8378b44915c0ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ version = "0.2.0" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" -homepage = "https://github.com/astro/tokio-xmpp" -repository = "https://github.com/astro/tokio-xmpp" +homepage = "https://gitlab.com/xmpp-rs/tokio-xmpp" +repository = "https://gitlab.com/xmpp-rs/tokio-xmpp" documentation = "https://docs.rs/tokio-xmpp" categories = ["asynchronous", "network-programming"] keywords = ["xmpp", "tokio"] From bbadf75c010bcd0395ccad4ad2eb419c46ed8428 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 17:35:05 +0100 Subject: [PATCH 091/135] move from travis-ci to gitlab-ci --- .gitlab-ci.yml | 14 ++++++++++++++ .travis.yml | 8 -------- 2 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 .gitlab-ci.yml delete mode 100644 .travis.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..ae087bde44b0e6eb8078985f13099bf76e212345 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +stages: + - build +rust-latest: + stage: build + image: rust:latest + script: + - cargo build --verbose + - cargo test --verbose +rust-nightly: + stage: build + image: rustlang/rust:nightly + script: + - cargo build --verbose + - cargo test --verbose diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9fdb54bc1da3ce5ba281caa0d4b8174685f26644..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -sudo: false - -language: rust - -rust: - - stable - - beta - - nightly From ce039d767ebbc2a502b960d36d1cf2fee0065e92 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 20:39:01 +0100 Subject: [PATCH 092/135] restructure auth code --- src/client/auth.rs | 154 +++++++++++++++++++-------------------------- src/client/mod.rs | 2 +- src/error.rs | 2 + src/xmpp_codec.rs | 2 +- 4 files changed, 70 insertions(+), 90 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index eadceb02a63c873d607cd6b5efc25cecb3dbba6d..51bcaa115600ef96457b26b31327de6549d83c7c 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,37 +1,29 @@ -use futures::{sink, Async, Future, Poll, Stream}; +use std::mem::replace; +use std::str::FromStr; +use futures::{sink, Async, Future, Poll, Stream, future::{ok, err, IntoFuture}}; use minidom::Element; use sasl::client::mechanisms::{Anonymous, Plain, Scram}; use sasl::client::Mechanism; use sasl::common::scram::{Sha1, Sha256}; use sasl::common::Credentials; -use std::mem::replace; -use std::str::FromStr; use tokio_io::{AsyncRead, AsyncWrite}; use try_from::TryFrom; use xmpp_parsers::sasl::{Auth, Challenge, Failure, Mechanism as XMPPMechanism, Response, Success}; -use crate::stream_start::StreamStart; use crate::xmpp_codec::Packet; use crate::xmpp_stream::XMPPStream; use crate::{AuthError, Error, ProtocolError}; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; -pub struct ClientAuth { - state: ClientAuthState, - mechanism: Box, -} - -enum ClientAuthState { - WaitSend(sink::Send>), - WaitRecv(XMPPStream), - Start(StreamStart), - Invalid, +pub struct ClientAuth { + future: Box, Error = Error>>, } -impl ClientAuth { +impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { let mechs: Vec> = vec![ + // TODO: Box::new(|| … Box::new(Scram::::from_credentials(creds.clone()).unwrap()), Box::new(Scram::::from_credentials(creds.clone()).unwrap()), Box::new(Plain::from_credentials(creds).unwrap()), @@ -46,36 +38,74 @@ impl ClientAuth { .filter(|child| child.is("mechanism", NS_XMPP_SASL)) .map(|mech_el| mech_el.text()) .collect(); + // TODO: iter instead of collect() // println!("SASL mechanisms offered: {:?}", mech_names); - for mut mech in mechs { - let name = mech.name().to_owned(); + for mut mechanism in mechs { + let name = mechanism.name().to_owned(); if mech_names.iter().any(|name1| *name1 == name) { // println!("SASL mechanism selected: {:?}", name); - let initial = mech.initial().map_err(AuthError::Sasl)?; - let mut this = ClientAuth { - state: ClientAuthState::Invalid, - mechanism: mech, - }; - let mechanism = XMPPMechanism::from_str(&name).map_err(ProtocolError::Parsers)?; - this.send( - stream, - Auth { - mechanism, - data: initial, - }, - ); - return Ok(this); + let initial = mechanism.initial().map_err(AuthError::Sasl)?; + let mechanism_name = XMPPMechanism::from_str(&name).map_err(ProtocolError::Parsers)?; + + let send_initial = Box::new(stream.send_stanza(Auth { + mechanism: mechanism_name, + data: initial, + })) + .map_err(Error::Io); + let future = Box::new(send_initial.and_then( + |stream| Self::handle_challenge(stream, mechanism) + ).and_then( + |stream| stream.restart() + )); + return Ok(ClientAuth { + future, + }); } } Err(AuthError::NoMechanism)? } - fn send>(&mut self, stream: XMPPStream, nonza: N) { - let send = stream.send_stanza(nonza); - - self.state = ClientAuthState::WaitSend(send); + fn handle_challenge(stream: XMPPStream, mut mechanism: Box) -> Box, Error = Error>> { + Box::new( + stream.into_future() + .map_err(|(e, _stream)| e.into()) + .and_then(|(stanza, stream)| { + match stanza { + Some(Packet::Stanza(stanza)) => { + if let Ok(challenge) = Challenge::try_from(stanza.clone()) { + let response = mechanism + .response(&challenge.data); + Box::new( + response + .map_err(|e| AuthError::Sasl(e).into()) + .into_future() + .and_then(|response| { + // Send response and loop + stream.send_stanza(Response { data: response }) + .map_err(Error::Io) + .and_then(|stream| Self::handle_challenge(stream, mechanism)) + }) + ) + } else if let Ok(_) = Success::try_from(stanza.clone()) { + Box::new(ok(stream)) + } else if let Ok(failure) = Failure::try_from(stanza.clone()) { + Box::new(err(Error::Auth(AuthError::Fail(failure.defined_condition)))) + } else { + // ignore and loop + println!("Ignore: {:?}", stanza); + Self::handle_challenge(stream, mechanism) + } + } + Some(_) => { + // ignore and loop + Self::handle_challenge(stream, mechanism) + } + None => Box::new(err(Error::Disconnected)) + } + }) + ) } } @@ -84,58 +114,6 @@ impl Future for ClientAuth { type Error = Error; fn poll(&mut self) -> Poll { - let state = replace(&mut self.state, ClientAuthState::Invalid); - - match state { - ClientAuthState::WaitSend(mut send) => match send.poll() { - Ok(Async::Ready(stream)) => { - self.state = ClientAuthState::WaitRecv(stream); - self.poll() - } - Ok(Async::NotReady) => { - self.state = ClientAuthState::WaitSend(send); - Ok(Async::NotReady) - } - Err(e) => Err(e)?, - }, - ClientAuthState::WaitRecv(mut stream) => match stream.poll() { - Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { - if let Ok(challenge) = Challenge::try_from(stanza.clone()) { - let response = self - .mechanism - .response(&challenge.data) - .map_err(AuthError::Sasl)?; - self.send(stream, Response { data: response }); - self.poll() - } else if let Ok(_) = Success::try_from(stanza.clone()) { - let start = stream.restart(); - self.state = ClientAuthState::Start(start); - self.poll() - } else if let Ok(failure) = Failure::try_from(stanza) { - Err(AuthError::Fail(failure.defined_condition))? - } else { - Ok(Async::NotReady) - } - } - Ok(Async::Ready(_event)) => { - // println!("ClientAuth ignore {:?}", _event); - Ok(Async::NotReady) - } - Ok(_) => { - self.state = ClientAuthState::WaitRecv(stream); - Ok(Async::NotReady) - } - Err(e) => Err(ProtocolError::Parser(e))?, - }, - ClientAuthState::Start(mut start) => match start.poll() { - Ok(Async::Ready(stream)) => Ok(Async::Ready(stream)), - Ok(Async::NotReady) => { - self.state = ClientAuthState::Start(start); - Ok(Async::NotReady) - } - Err(e) => Err(e), - }, - ClientAuthState::Invalid => unreachable!(), - } + self.future.poll() } } diff --git a/src/client/mod.rs b/src/client/mod.rs index 9e62373dc4f276d059b9203592ede8886139bfd4..37670131b72b44e078b99c79b01e1c7809dbf904 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -104,7 +104,7 @@ impl Client { StartTlsClient::from_stream(stream) } - fn auth( + fn auth( stream: xmpp_stream::XMPPStream, username: String, password: String, diff --git a/src/error.rs b/src/error.rs index 26d794495ebff0562e894f022a955b1ea44e32c0..e7fad549fbda79e50f73884b7c7b2cee3ca4b397 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,6 +26,8 @@ pub enum Error { Auth(AuthError), /// TLS error Tls(TlsError), + /// Connection closed + Disconnected, /// Shoud never happen InvalidState, } diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index e8c4e0538e1b47d308e947bc25d548e9a1ec83b6..9c59bac877829b228e9b9f6640475300815b1939 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -19,7 +19,7 @@ use xml5ever::interface::Attribute; use xml5ever::tokenizer::{Tag, TagKind, Token, TokenSink, XmlTokenizer}; /// Anything that can be sent or received on an XMPP/XML stream -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Packet { /// `` start tag StreamStart(HashMap), From 11cc7f183a41be0a04e57ae80f4f826c658fe6d1 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 21:09:13 +0100 Subject: [PATCH 093/135] auth: add work-around for xmpp-parsers pickyness --- src/client/auth.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 51bcaa115600ef96457b26b31327de6549d83c7c..9a56d04907dda55965de107a668d0cd763df1305 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -92,9 +92,11 @@ impl ClientAuth { Box::new(ok(stream)) } else if let Ok(failure) = Failure::try_from(stanza.clone()) { Box::new(err(Error::Auth(AuthError::Fail(failure.defined_condition)))) + } else if stanza.name() == "failure" { + // Workaround for https://gitlab.com/xmpp-rs/xmpp-parsers/merge_requests/1 + Box::new(err(Error::Auth(AuthError::Sasl("failure".to_string())))) } else { // ignore and loop - println!("Ignore: {:?}", stanza); Self::handle_challenge(stream, mechanism) } } From 78f74c633850b44fd4485325c81606dd9c1d360b Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 21:17:56 +0100 Subject: [PATCH 094/135] auth: clarify + optimize --- src/client/auth.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index 9a56d04907dda55965de107a668d0cd763df1305..fb4243948f92fdc05c25ad08401e23f05fea709a 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,5 +1,6 @@ use std::mem::replace; use std::str::FromStr; +use std::collections::HashSet; use futures::{sink, Async, Future, Poll, Stream, future::{ok, err, IntoFuture}}; use minidom::Element; use sasl::client::mechanisms::{Anonymous, Plain, Scram}; @@ -22,15 +23,14 @@ pub struct ClientAuth { impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { - let mechs: Vec> = vec![ - // TODO: Box::new(|| … - Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - Box::new(Scram::::from_credentials(creds.clone()).unwrap()), - Box::new(Plain::from_credentials(creds).unwrap()), - Box::new(Anonymous::new()), + let local_mechs: Vec Box>> = vec![ + Box::new(|| Box::new(Scram::::from_credentials(creds.clone()).unwrap())), + Box::new(|| Box::new(Scram::::from_credentials(creds.clone()).unwrap())), + Box::new(|| Box::new(Plain::from_credentials(creds.clone()).unwrap())), + Box::new(|| Box::new(Anonymous::new())), ]; - let mech_names: Vec = stream + let remote_mechs: HashSet = stream .stream_features .get_child("mechanisms", NS_XMPP_SASL) .ok_or(AuthError::NoMechanism)? @@ -38,15 +38,12 @@ impl ClientAuth { .filter(|child| child.is("mechanism", NS_XMPP_SASL)) .map(|mech_el| mech_el.text()) .collect(); - // TODO: iter instead of collect() - // println!("SASL mechanisms offered: {:?}", mech_names); - for mut mechanism in mechs { - let name = mechanism.name().to_owned(); - if mech_names.iter().any(|name1| *name1 == name) { - // println!("SASL mechanism selected: {:?}", name); + for local_mech in local_mechs { + let mut mechanism = local_mech(); + if remote_mechs.contains(mechanism.name()) { let initial = mechanism.initial().map_err(AuthError::Sasl)?; - let mechanism_name = XMPPMechanism::from_str(&name).map_err(ProtocolError::Parsers)?; + let mechanism_name = XMPPMechanism::from_str(mechanism.name()).map_err(ProtocolError::Parsers)?; let send_initial = Box::new(stream.send_stanza(Auth { mechanism: mechanism_name, From a6512c2b42e9e41204924bed34397d6018ba9480 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 21:20:46 +0100 Subject: [PATCH 095/135] auth: delint --- src/client/auth.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index fb4243948f92fdc05c25ad08401e23f05fea709a..588b1a73e14c757c356244f8884a6efe1680bc3c 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,8 +1,6 @@ -use std::mem::replace; use std::str::FromStr; use std::collections::HashSet; -use futures::{sink, Async, Future, Poll, Stream, future::{ok, err, IntoFuture}}; -use minidom::Element; +use futures::{Future, Poll, Stream, future::{ok, err, IntoFuture}}; use sasl::client::mechanisms::{Anonymous, Plain, Scram}; use sasl::client::Mechanism; use sasl::common::scram::{Sha1, Sha256}; From 7bb4bd1094ca11372b79fe19c9022b98530187da Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 20 Dec 2018 21:30:56 +0100 Subject: [PATCH 096/135] tokio-xmpp 0.2.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b6c86df71ea6a722313cfe86ea8378b44915c0ed..ee3b80a49deb900dc4a568777042806a21962afe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-xmpp" -version = "0.2.0" +version = "0.2.1" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" From 983078f120a574bb0019afec44ac9beca52dd7ae Mon Sep 17 00:00:00 2001 From: O01eg Date: Tue, 8 Jan 2019 13:41:39 +0300 Subject: [PATCH 097/135] Add prefix support to decoder to accept xml:lang in presence statuses. --- src/xmpp_codec.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 9c59bac877829b228e9b9f6640475300815b1939..199627ba4ffedbd4983dda7451ae6e06e95c4747 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -104,7 +104,11 @@ impl ParserSink { "xmlns" => (), _ if is_prefix_xmlns(attr) => (), _ => { - el_builder = el_builder.attr(attr.name.local.as_ref(), attr.value.as_ref()); + if let Some(ref prefix) = attr.name.prefix { + el_builder = el_builder.attr(format!("{}:{}", prefix, attr.name.local), attr.value.as_ref()); + } else { + el_builder = el_builder.attr(attr.name.local.as_ref(), attr.value.as_ref()); + } } } } @@ -428,6 +432,28 @@ mod tests { }); } + /// test case for https://gitlab.com/xmpp-rs/tokio-xmpp/issues/3 + #[test] + fn test_atrribute_prefix() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + + b.clear(); + b.put(r"Test status"); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::Stanza(ref el))) if el.name() == "status" && el.text() == "Test status" && el.attr("xml:lang").map_or(false, |a| a == "en") => true, + _ => false, + }); + + } + /// By default, encode() only get's a BytesMut that has 8kb space reserved. #[test] fn test_large_stanza() { From 1225bf7027f624ad7cc0624ebe44943bc410e781 Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 13 Jan 2019 21:05:19 +0100 Subject: [PATCH 098/135] prefix support DRY --- src/xmpp_codec.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 199627ba4ffedbd4983dda7451ae6e06e95c4747..69ab5fc23c82b43370d0408a0bb86ce2c0632f11 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -14,6 +14,7 @@ use std::io; use std::iter::FromIterator; use std::rc::Rc; use std::str::from_utf8; +use std::borrow::Cow; use tokio_codec::{Decoder, Encoder}; use xml5ever::interface::Attribute; use xml5ever::tokenizer::{Tag, TagKind, Token, TokenSink, XmlTokenizer}; @@ -104,11 +105,12 @@ impl ParserSink { "xmlns" => (), _ if is_prefix_xmlns(attr) => (), _ => { - if let Some(ref prefix) = attr.name.prefix { - el_builder = el_builder.attr(format!("{}:{}", prefix, attr.name.local), attr.value.as_ref()); + let attr_name = if let Some(ref prefix) = attr.name.prefix { + Cow::Owned(format!("{}:{}", prefix, attr.name.local)) } else { - el_builder = el_builder.attr(attr.name.local.as_ref(), attr.value.as_ref()); - } + Cow::Borrowed(attr.name.local.as_ref()) + }; + el_builder = el_builder.attr(attr_name, attr.value.as_ref()); } } } From 49c0f6e7a6cabc4c08571aaf895209fef73663cf Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 14 Jan 2019 00:02:02 +0100 Subject: [PATCH 099/135] client: add new_with_jid() to reuse parsed Jid Should fix Gitlab issue #2 --- src/client/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 37670131b72b44e078b99c79b01e1c7809dbf904..146d51a40fdd57a23775dcf8b4775f2334605eab 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -45,12 +45,19 @@ impl Client { /// and yield events. pub fn new(jid: &str, password: &str) -> Result { let jid = Jid::from_str(jid)?; + let client = Self::new_with_jid(jid, password); + Ok(client) + } + + /// Start a new client given that the JID is already parsed. + pub fn new_with_jid(jid: Jid, password: &str) -> Self { let password = password.to_owned(); let connect = Self::make_connect(jid.clone(), password.clone()); - Ok(Client { + let client = Client { jid, state: ClientState::Connecting(Box::new(connect)), - }) + }; + client } fn make_connect(jid: Jid, password: String) -> impl Future { From 5eb211c9fc7bd202bbbe3369b5003247865c923e Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 14 Jan 2019 02:49:50 +0100 Subject: [PATCH 100/135] tokio-xmpp 0.2.2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ee3b80a49deb900dc4a568777042806a21962afe..e43d5d28c380ea9d4163a3b6b2fa7875834d44a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-xmpp" -version = "0.2.1" +version = "0.2.2" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" From 62e9dcc02293e0d77fc94b4f4cc079979d58daca Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 16 Jan 2019 14:35:38 +0100 Subject: [PATCH 101/135] Bump xmpp-parsers to 0.12.2. This also removes minidom, jid and try_from as direct dependencies, since they are now reexported by xmpp-parsers. --- Cargo.toml | 7 ++----- examples/echo_bot.rs | 4 +--- examples/echo_component.rs | 4 +--- src/client/auth.rs | 2 +- src/client/bind.rs | 2 +- src/client/mod.rs | 3 +-- src/component/mod.rs | 3 +-- src/error.rs | 2 +- src/event.rs | 2 +- src/starttls.rs | 3 +-- src/stream_start.rs | 3 +-- src/xmpp_codec.rs | 2 +- src/xmpp_stream.rs | 3 +-- 13 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e43d5d28c380ea9d4163a3b6b2fa7875834d44a7..c397ed40be7620798b5c561757d37cd9dce2bf37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,15 +18,12 @@ tokio-io = "0.1" tokio-codec = "0.1" bytes = "0.4" xml5ever = "0.12" -minidom = "0.9" native-tls = "0.2" tokio-tls = "0.2" sasl = "0.4" -jid = { version = "0.5", features = ["minidom"] } trust-dns-resolver = "0.9.1" trust-dns-proto = "0.4.0" -xmpp-parsers = "0.11" +xmpp-parsers = "0.12.2" idna = "0.1" -try_from = "0.2" -quick-xml = "0.12" +quick-xml = "0.13" derive-error = "0.0.4" diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 80ffc97fcc142e4e035d3488abb05379a1c53008..24b101079d76d0800a4d46f73262d50eea99a594 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,11 +1,9 @@ use futures::{future, Sink, Stream}; -use jid::Jid; -use minidom::Element; use std::env::args; use std::process::exit; use tokio::runtime::current_thread::Runtime; use tokio_xmpp::Client; -use try_from::TryFrom; +use xmpp_parsers::{Jid, Element, TryFrom}; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 348b06a4d2d812303943b996e514a966b945f610..618032e324a422621c168df9e9a986f5f6fa282e 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -1,12 +1,10 @@ use futures::{future, Sink, Stream}; -use jid::Jid; -use minidom::Element; use std::env::args; use std::process::exit; use std::str::FromStr; use tokio::runtime::current_thread::Runtime; use tokio_xmpp::Component; -use try_from::TryFrom; +use xmpp_parsers::{Jid, Element, TryFrom}; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; diff --git a/src/client/auth.rs b/src/client/auth.rs index 588b1a73e14c757c356244f8884a6efe1680bc3c..d961f7a0988b1b26ef11b99038e8bebab312d499 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -6,7 +6,7 @@ use sasl::client::Mechanism; use sasl::common::scram::{Sha1, Sha256}; use sasl::common::Credentials; use tokio_io::{AsyncRead, AsyncWrite}; -use try_from::TryFrom; +use xmpp_parsers::TryFrom; use xmpp_parsers::sasl::{Auth, Challenge, Failure, Mechanism as XMPPMechanism, Response, Success}; use crate::xmpp_codec::Packet; diff --git a/src/client/bind.rs b/src/client/bind.rs index 3758a563708083650694d4419f14bd186ba3d15d..083650b9b94196fac4a797534f0083dc51222129 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,7 +1,7 @@ use futures::{sink, Async, Future, Poll, Stream}; use std::mem::replace; use tokio_io::{AsyncRead, AsyncWrite}; -use try_from::TryFrom; +use xmpp_parsers::TryFrom; use xmpp_parsers::bind::Bind; use xmpp_parsers::iq::{Iq, IqType}; diff --git a/src/client/mod.rs b/src/client/mod.rs index 146d51a40fdd57a23775dcf8b4775f2334605eab..acc60441223ba248a620b696cb8a9a8c98acb326 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,7 +1,6 @@ use futures::{done, Async, AsyncSink, Future, Poll, Sink, StartSend, Stream}; use idna; -use jid::{Jid, JidParseError}; -use minidom::Element; +use xmpp_parsers::{Jid, JidParseError, Element}; use sasl::common::{ChannelBinding, Credentials}; use std::mem::replace; use std::str::FromStr; diff --git a/src/component/mod.rs b/src/component/mod.rs index aac66ab4e5e64e40eac3a5233b9cf7cc4831bf0e..cfc1ee5e2452504a6a39daa06fa26b3e0a61db5f 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -2,8 +2,7 @@ //! XMPP server under a JID consisting of just a domain name. They are //! allowed to use any user and resource identifiers in their stanzas. use futures::{done, Async, AsyncSink, Future, Poll, Sink, StartSend, Stream}; -use jid::{Jid, JidParseError}; -use minidom::Element; +use xmpp_parsers::{Jid, JidParseError, Element}; use std::mem::replace; use std::str::FromStr; use tokio::net::TcpStream; diff --git a/src/error.rs b/src/error.rs index e7fad549fbda79e50f73884b7c7b2cee3ca4b397..9697f2681b860b1416cc16da6e60cd29e436a5f3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,7 +7,7 @@ use std::str::Utf8Error; use trust_dns_proto::error::ProtoError; use trust_dns_resolver::error::ResolveError; -use xmpp_parsers::error::Error as ParsersError; +use xmpp_parsers::Error as ParsersError; use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; /// Top-level error type diff --git a/src/event.rs b/src/event.rs index 7a225ba352d9f3015aaa9d78b8b7b1d3b0beff31..94dd36c2b7f298642a6e33671d1fbf2f138dd7f2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,4 +1,4 @@ -use minidom::Element; +use xmpp_parsers::Element; /// High-level event on the Stream implemented by Client and Component #[derive(Debug)] diff --git a/src/starttls.rs b/src/starttls.rs index e48d1824a1220f98b70b015098cc9c93ec9a9b0a..00966ac1d491ba3d87d0b1b3bf0011d086e6a2ec 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -1,8 +1,7 @@ use futures::sink; use futures::stream::Stream; use futures::{Async, Future, Poll, Sink}; -use jid::Jid; -use minidom::Element; +use xmpp_parsers::{Jid, Element}; use native_tls::TlsConnector as NativeTlsConnector; use std::mem::replace; use tokio_io::{AsyncRead, AsyncWrite}; diff --git a/src/stream_start.rs b/src/stream_start.rs index 0a5945b7bda5e6d8dae908f23d20c59b3b5bb4e6..bf2d39e8b8968dc49474288be94a8c900f51beed 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -1,6 +1,5 @@ use futures::{sink, Async, Future, Poll, Sink, Stream}; -use jid::Jid; -use minidom::Element; +use xmpp_parsers::{Jid, Element}; use std::mem::replace; use tokio_codec::Framed; use tokio_io::{AsyncRead, AsyncWrite}; diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 69ab5fc23c82b43370d0408a0bb86ce2c0632f11..54ddcb51a5908b8716c339e7b18c78d11bfe2747 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -2,7 +2,7 @@ use crate::{ParseError, ParserError}; use bytes::{BufMut, BytesMut}; -use minidom::Element; +use xmpp_parsers::Element; use quick_xml::Writer as EventWriter; use std; use std::cell::RefCell; diff --git a/src/xmpp_stream.rs b/src/xmpp_stream.rs index c67cc1efdd6ea8b53e84c784b2e88b4829fb6772..129dd1d4fe8825b06409cf52fac2f145f6678969 100644 --- a/src/xmpp_stream.rs +++ b/src/xmpp_stream.rs @@ -2,8 +2,7 @@ use futures::sink::Send; use futures::{Poll, Sink, StartSend, Stream}; -use jid::Jid; -use minidom::Element; +use xmpp_parsers::{Jid, Element}; use tokio_codec::Framed; use tokio_io::{AsyncRead, AsyncWrite}; From 59f433fd218f5b3d1fd4d7b790f0b3754abc4217 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 17 Jan 2019 01:24:26 +0100 Subject: [PATCH 102/135] happy_eyeballs: migrate to newer trust-dns dependencies --- Cargo.toml | 4 ++-- src/error.rs | 10 +++++++- src/happy_eyeballs.rs | 56 ++++++++++++++++++------------------------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c397ed40be7620798b5c561757d37cd9dce2bf37..954a6052809a3233418dcad48bdc8b48155b8159 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,8 +21,8 @@ xml5ever = "0.12" native-tls = "0.2" tokio-tls = "0.2" sasl = "0.4" -trust-dns-resolver = "0.9.1" -trust-dns-proto = "0.4.0" +trust-dns-resolver = "0.10" +trust-dns-proto = "0.6" xmpp-parsers = "0.12.2" idna = "0.1" quick-xml = "0.13" diff --git a/src/error.rs b/src/error.rs index 9697f2681b860b1416cc16da6e60cd29e436a5f3..8ffa1b7a83c3de5204e9546544cf1df6699fad14 100644 --- a/src/error.rs +++ b/src/error.rs @@ -107,7 +107,7 @@ pub enum AuthError { } /// Error establishing connection -#[derive(Debug, Error)] +#[derive(Debug)] pub enum ConnecterError { /// All attempts failed, no error available AllFailed, @@ -116,3 +116,11 @@ pub enum ConnecterError { /// DNS resolution error Resolve(ResolveError), } + +impl std::error::Error for ConnecterError {} + +impl std::fmt::Display for ConnecterError { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!(fmt, "{:?}", self) + } +} diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 19dbe4939d4e7e51d84fa8843646ddd10cef5eac..3fa6169ca8d29681964c788ac7b6954eb8f3cb8a 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -8,17 +8,16 @@ use std::mem; use std::net::SocketAddr; use tokio::net::tcp::ConnectFuture; use tokio::net::TcpStream; -use trust_dns_resolver::config::LookupIpStrategy; +use trust_dns_resolver::{AsyncResolver, Name, IntoName, Background, BackgroundLookup}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; -use trust_dns_resolver::system_conf; -use trust_dns_resolver::{error::ResolveError, IntoName, Name, ResolverFuture}; + enum State { - AwaitResolver(Box + Send>), - ResolveSrv(ResolverFuture, SrvLookupFuture), - ResolveTarget(ResolverFuture, LookupIpFuture, u16), - Connecting(Option, Vec>), + Start(AsyncResolver), + ResolveSrv(AsyncResolver, BackgroundLookup), + ResolveTarget(AsyncResolver, Background, u16), + Connecting(Option, Vec>), Invalid, } @@ -31,11 +30,10 @@ pub struct Connecter { error: Option, } -fn resolver_future( -) -> Result + Send>, IoError> { - let (conf, mut opts) = system_conf::read_system_conf()?; - opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; - Ok(ResolverFuture::new(conf, opts)) +fn resolver() -> Result { + let (resolver, resolver_background) = AsyncResolver::from_system_conf()?; + tokio::runtime::current_thread::spawn(resolver_background); + Ok(resolver) } impl Connecter { @@ -57,7 +55,7 @@ impl Connecter { }); } - let state = State::AwaitResolver(resolver_future()?); + let state = State::Start(resolver()?); let srv_domain = match srv { Some(srv) => Some( format!("{}.{}.", srv, domain) @@ -85,29 +83,21 @@ impl Future for Connecter { fn poll(&mut self) -> Poll { let state = mem::replace(&mut self.state, State::Invalid); match state { - State::AwaitResolver(mut resolver_future) => { - match resolver_future.poll().map_err(ConnecterError::Resolve)? { - Async::NotReady => { - self.state = State::AwaitResolver(resolver_future); - Ok(Async::NotReady) + State::Start(resolver) => { + match &self.srv_domain { + &Some(ref srv_domain) => { + let srv_lookup = resolver.lookup_srv(srv_domain); + self.state = State::ResolveSrv(resolver, srv_lookup); } - Async::Ready(resolver) => { - match &self.srv_domain { - &Some(ref srv_domain) => { - let srv_lookup = resolver.lookup_srv(srv_domain); - self.state = State::ResolveSrv(resolver, srv_lookup); - } - None => { - self.targets = [(self.domain.clone(), self.fallback_port)] - .into_iter() - .cloned() - .collect(); - self.state = State::Connecting(Some(resolver), vec![]); - } - } - self.poll() + None => { + self.targets = [(self.domain.clone(), self.fallback_port)] + .into_iter() + .cloned() + .collect(); + self.state = State::Connecting(Some(resolver), vec![]); } } + self.poll() } State::ResolveSrv(resolver, mut srv_lookup) => { match srv_lookup.poll() { From e59d048cd04e6ba87c4668d689e430e28bb820c5 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 17 Jan 2019 01:29:48 +0100 Subject: [PATCH 103/135] happy_eyeballs: eliminate State::Start --- src/happy_eyeballs.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 3fa6169ca8d29681964c788ac7b6954eb8f3cb8a..a47ddd986262d70ecd4b1955446ee132fa8c6999 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -14,7 +14,6 @@ use trust_dns_resolver::lookup_ip::LookupIpFuture; enum State { - Start(AsyncResolver), ResolveSrv(AsyncResolver, BackgroundLookup), ResolveTarget(AsyncResolver, Background, u16), Connecting(Option, Vec>), @@ -55,7 +54,6 @@ impl Connecter { }); } - let state = State::Start(resolver()?); let srv_domain = match srv { Some(srv) => Some( format!("{}.{}.", srv, domain) @@ -65,14 +63,32 @@ impl Connecter { None => None, }; - Ok(Connecter { + let mut self_ = Connecter { fallback_port, srv_domain, domain: domain.into_name().map_err(ConnecterError::Dns)?, - state, + state: State::Invalid, targets: VecDeque::new(), error: None, - }) + }; + + let resolver = resolver()?; + // Initialize state + match &self_.srv_domain { + &Some(ref srv_domain) => { + let srv_lookup = resolver.lookup_srv(srv_domain); + self_.state = State::ResolveSrv(resolver, srv_lookup); + } + None => { + self_.targets = [(self_.domain.clone(), self_.fallback_port)] + .into_iter() + .cloned() + .collect(); + self_.state = State::Connecting(Some(resolver), vec![]); + } + } + + Ok(self_) } } @@ -83,22 +99,6 @@ impl Future for Connecter { fn poll(&mut self) -> Poll { let state = mem::replace(&mut self.state, State::Invalid); match state { - State::Start(resolver) => { - match &self.srv_domain { - &Some(ref srv_domain) => { - let srv_lookup = resolver.lookup_srv(srv_domain); - self.state = State::ResolveSrv(resolver, srv_lookup); - } - None => { - self.targets = [(self.domain.clone(), self.fallback_port)] - .into_iter() - .cloned() - .collect(); - self.state = State::Connecting(Some(resolver), vec![]); - } - } - self.poll() - } State::ResolveSrv(resolver, mut srv_lookup) => { match srv_lookup.poll() { Ok(Async::NotReady) => { From def0092b20a2aeef46cf8e9973efca8345da98b9 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 17 Jan 2019 01:38:24 +0100 Subject: [PATCH 104/135] happy_eyeballs: set LookupIpStrategy::Ipv4AndIpv6 this is what happy_eyeballs are all about --- src/happy_eyeballs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index a47ddd986262d70ecd4b1955446ee132fa8c6999..fc4e0280501f1444f2f8b43439d68612352d5036 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -9,6 +9,7 @@ use std::net::SocketAddr; use tokio::net::tcp::ConnectFuture; use tokio::net::TcpStream; use trust_dns_resolver::{AsyncResolver, Name, IntoName, Background, BackgroundLookup}; +use trust_dns_resolver::config::LookupIpStrategy; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; @@ -30,7 +31,9 @@ pub struct Connecter { } fn resolver() -> Result { - let (resolver, resolver_background) = AsyncResolver::from_system_conf()?; + let (config, mut opts) = trust_dns_resolver::system_conf::read_system_conf()?; + opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; + let (resolver, resolver_background) = AsyncResolver::new(config, opts); tokio::runtime::current_thread::spawn(resolver_background); Ok(resolver) } From 9921a59400c13f52f363cb972d929a61689d19f2 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 17 Jan 2019 01:41:42 +0100 Subject: [PATCH 105/135] add Cargo.lock --- .gitignore | 1 - Cargo.lock | 1709 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1709 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index a9d37c560c6ab8d4afbf47eda643e8c42e857716..eb5a316cbd195d26e3f768c7dd8e1b47299e17f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ target -Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..88d2a7cb6b842c4606c5786b35f8772be98850ef --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1709 @@ +[[package]] +name = "MacTypes-sys" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "case" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chrono" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive-error" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding_rs" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hostname" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ipconfig" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "jid" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.46" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lru-cache" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "markup5ever" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "minidom" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "native-tls" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "phf" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-xml" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "resolv-conf" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sasl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schannel" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "security-framework" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha3" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "socket2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "string_cache" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string_cache_codegen" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string_cache_shared" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempfile" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tendril" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-xmpp" +version = "0.2.2" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sasl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trust-dns-proto" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vcpkg" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "widestring" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winreg" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winutil" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "xml5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "xmpp-parsers" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jid 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7dbbe033994ae2198a18517c7132d952a29fb1db44249a1234779da7c50f4698" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" +"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e88b166b48e29667f5443df64df3c61dc07dc2b1a0b0d231800e07f09a33ecc1" +"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" +"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" +"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" +"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ec098440b29ea3b1ece3e641bac424c19cf996779b623c9e0f2171495425c2c8" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" +"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum jid 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "24e8a3f2ab860aa08074136e3144a2425e678d8823206e5adcc6145dc136503a" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "275024eea6c6ff4ace22f2750843831183785288eec1cff91a4e6b8898cf94f9" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" +"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682" +"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98d8d2d671bd29c6122a98b45ce3106391e89ba378f731274de677f1eff06e5f" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" +"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" +"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum sasl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbda5436dcd059da44fbf84b87a7164c5e3cad354efd0630c1f2be3c51c8859" +"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" +"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" +"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" +"checksum serde_json 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb1277d4d0563e4593e0b8b5d23d744d277b55d2bc0bf1c38d0d8a6589d38aa" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" +"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" +"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" +"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" +"checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" +"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" +"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30dde452f5d142d5e316a3b32386da95280c98b7e266639f8f3bc6fdf507d279" +"checksum trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de630f95a192f793436ffae5137e88253cc4142a97d9a8e73c8d804fa85ddf0a" +"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" +"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd7ebf0203c620906230ce22caa5df0b603c32b6fef72a275a48f6a2ae64b9" +"checksum xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58b4400e1ae0d246044db5fa7f2e693fdfe9cc6e8eaa72ef2a68c5dc1d3c96de" From 438dbaafecbf595df1b152af51e090c0c84fe577 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 17 Jan 2019 01:41:59 +0100 Subject: [PATCH 106/135] tokio-xmpp 0.2.3 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 954a6052809a3233418dcad48bdc8b48155b8159..afda4d2765c1a2d43e456f863bc26f71405d4c55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-xmpp" -version = "0.2.2" +version = "0.2.3" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" From c75eafa553c4b20abe628e869a21241f7bd67309 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 19:28:57 +0100 Subject: [PATCH 107/135] rm all annoying debug output --- src/component/auth.rs | 4 ++-- src/starttls.rs | 4 ++-- src/xmpp_codec.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/auth.rs b/src/component/auth.rs index 92ae0903cd8ab4aa93a0658cd8a7486f521878f8..44104f4c19052fe1db703563fab894cf32c2d7ca 100644 --- a/src/component/auth.rs +++ b/src/component/auth.rs @@ -73,8 +73,8 @@ impl Future for ComponentAuth { { Err(AuthError::ComponentFail.into()) } - Ok(Async::Ready(event)) => { - println!("ComponentAuth ignore {:?}", event); + Ok(Async::Ready(_event)) => { + // println!("ComponentAuth ignore {:?}", _event); Ok(Async::NotReady) } Ok(_) => { diff --git a/src/starttls.rs b/src/starttls.rs index 00966ac1d491ba3d87d0b1b3bf0011d086e6a2ec..41bc6001da06f74b49403108c45616d787a1ae7f 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -75,8 +75,8 @@ impl Future for StartTlsClient { retry = true; (new_state, Ok(Async::NotReady)) } - Ok(Async::Ready(value)) => { - println!("StartTlsClient ignore {:?}", value); + Ok(Async::Ready(_value)) => { + // println!("StartTlsClient ignore {:?}", _value); ( StartTlsClientState::AwaitProceed(xmpp_stream), Ok(Async::NotReady), diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 54ddcb51a5908b8716c339e7b18c78d11bfe2747..d8e5310a41aa99adff965b0c60655bf763ca0b58 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -289,7 +289,7 @@ impl Encoder for XMPPCodec { } write!(buf, ">\n").unwrap(); - print!(">> {}", buf); + // print!(">> {}", buf); write!(dst, "{}", buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e)) } Packet::Stanza(stanza) => { From 3586e5134d4b87bc31ed9426045131f1a8b0af66 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 19:39:05 +0100 Subject: [PATCH 108/135] client: reindent --- src/client/mod.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index acc60441223ba248a620b696cb8a9a8c98acb326..b4793f9c15809df273014be4cd0786e6409f9a58 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -184,16 +184,21 @@ impl Sink for Client { fn start_send(&mut self, item: Self::SinkItem) -> StartSend { match self.state { - ClientState::Connected(ref mut stream) => match stream.start_send(Packet::Stanza(item)) - { - Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => Ok(AsyncSink::NotReady(stanza)), - Ok(AsyncSink::NotReady(_)) => { - panic!("Client.start_send with stanza but got something else back") + ClientState::Connected(ref mut stream) => { + match stream.start_send(Packet::Stanza(item)) { + Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => + Ok(AsyncSink::NotReady(stanza)), + Ok(AsyncSink::NotReady(_)) => { + panic!("Client.start_send with stanza but got something else back") + } + Ok(AsyncSink::Ready) => + Ok(AsyncSink::Ready), + Err(e) => + Err(e)?, } - Ok(AsyncSink::Ready) => Ok(AsyncSink::Ready), - Err(e) => Err(e)?, - }, - _ => Ok(AsyncSink::NotReady(item)), + } + _ => + Ok(AsyncSink::NotReady(item)), } } From 380bd2fc0286112abb434e9f6909f4bc53dc9b9a Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 20:46:51 +0100 Subject: [PATCH 109/135] client: implement close() to close inner stream --- src/client/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/client/mod.rs b/src/client/mod.rs index b4793f9c15809df273014be4cd0786e6409f9a58..a33dade949bd60c4341e6d770ec495f7533b157a 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -208,4 +208,19 @@ impl Sink for Client { _ => Ok(Async::Ready(())), } } + + /// This closes the inner TCP stream. + /// + /// To synchronize your shutdown with the server side, you should + /// first send `Packet::StreamEnd` and wait it to be sent back + /// before closing the connection. + fn close(&mut self) -> Poll<(), Self::SinkError> { + match self.state { + ClientState::Connected(ref mut stream) => + stream.close() + .map_err(|e| e.into()), + _ => + Ok(Async::Ready(())), + } + } } From 599e3be32e6bd59976e8d74a73f9aea975993624 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 21:07:15 +0100 Subject: [PATCH 110/135] xmpp_codec, client: handle StreamEnd --- src/client/mod.rs | 20 +++++++++++++++++--- src/error.rs | 2 ++ src/xmpp_codec.rs | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index a33dade949bd60c4341e6d770ec495f7533b157a..9033b83bcb624f779ee5f2b7fc5ba974ff90450d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -164,10 +164,24 @@ impl Stream for Client { Ok(Async::Ready(Some(Event::Disconnected))) } Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => { + // Receive stanza self.state = ClientState::Connected(stream); Ok(Async::Ready(Some(Event::Stanza(stanza)))) } - Ok(Async::NotReady) | Ok(Async::Ready(_)) => { + Ok(Async::Ready(Some(Packet::Text(_)))) => { + // Ignore text between stanzas + Ok(Async::NotReady) + } + Ok(Async::Ready(Some(Packet::StreamStart(_)))) => { + // + Err(ProtocolError::InvalidStreamStart.into()) + } + Ok(Async::Ready(Some(Packet::StreamEnd))) => { + // End of stream: + Ok(Async::Ready(None)) + } + Ok(Async::NotReady) => { + // Try again later self.state = ClientState::Connected(stream); Ok(Async::NotReady) } @@ -212,8 +226,8 @@ impl Sink for Client { /// This closes the inner TCP stream. /// /// To synchronize your shutdown with the server side, you should - /// first send `Packet::StreamEnd` and wait it to be sent back - /// before closing the connection. + /// first send `Packet::StreamEnd` and wait for the end of the + /// incoming stream before closing the connection. fn close(&mut self) -> Poll<(), Self::SinkError> { match self.state { ClientState::Connected(ref mut stream) => diff --git a/src/error.rs b/src/error.rs index 8ffa1b7a83c3de5204e9546544cf1df6699fad14..375c5178c6c4ff908c5a8bde3af12227b025ef6f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -88,6 +88,8 @@ pub enum ProtocolError { NoStreamId, /// Encountered an unexpected XML token InvalidToken, + /// Unexpected (shouldn't occur) + InvalidStreamStart, } /// Authentication error diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index d8e5310a41aa99adff965b0c60655bf763ca0b58..82eda4a614d63d20076bc6cf5a17ff0bf4cbff45 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -378,6 +378,25 @@ mod tests { }); } + #[test] + fn test_stream_end() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + b.clear(); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamEnd)) => true, + _ => false, + }); + } + #[test] fn test_truncated_stanza() { let mut c = XMPPCodec::new(); From 6379f91e02fc0813e8478a1115bb9050d2a23cb6 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 23:58:12 +0100 Subject: [PATCH 111/135] client: add more state to make close() send `` --- src/client/mod.rs | 48 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 9033b83bcb624f779ee5f2b7fc5ba974ff90450d..025b4395f173fbfe52507d6af4021631584197fe 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -35,6 +35,8 @@ enum ClientState { Disconnected, Connecting(Box>), Connected(XMPPStream), + ClosingSendEnd(futures::sink::Send), + ClosingClose(XMPPStream), } impl Client { @@ -188,6 +190,14 @@ impl Stream for Client { Err(e) => Err(e)?, } } + ClientState::ClosingSendEnd(_) => { + self.state = state; + Ok(Async::NotReady) + } + ClientState::ClosingClose(_) => { + self.state = state; + Ok(Async::NotReady) + } } } } @@ -219,20 +229,40 @@ impl Sink for Client { fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { match self.state { ClientState::Connected(ref mut stream) => stream.poll_complete().map_err(|e| e.into()), + ClientState::ClosingSendEnd(ref mut send) => { + match send.poll()? { + Async::NotReady => + Ok(Async::NotReady), + Async::Ready(stream) => { + self.state = ClientState::ClosingClose(stream); + self.poll_complete() + } + } + } + ClientState::ClosingClose(ref mut stream) => { + match stream.close()? { + Async::NotReady => + Ok(Async::NotReady), + Async::Ready(()) => { + self.state = ClientState::Disconnected; + Ok(Async::Ready(())) + } + } + } _ => Ok(Async::Ready(())), } } - /// This closes the inner TCP stream. - /// - /// To synchronize your shutdown with the server side, you should - /// first send `Packet::StreamEnd` and wait for the end of the - /// incoming stream before closing the connection. + /// Send ` and later close the inner TCP stream. fn close(&mut self) -> Poll<(), Self::SinkError> { - match self.state { - ClientState::Connected(ref mut stream) => - stream.close() - .map_err(|e| e.into()), + let state = replace(&mut self.state, ClientState::Disconnected); + + match state { + ClientState::Connected(stream) => { + let send = stream.send(Packet::StreamEnd); + self.state = ClientState::ClosingSendEnd(send); + self.poll_complete() + } _ => Ok(Async::Ready(())), } From 234450b9d1615cfad6b4a6778d3f6f0501ce25ef Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 26 Jan 2019 23:59:06 +0100 Subject: [PATCH 112/135] echo_bot: illustrate close() --- examples/echo_bot.rs | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 24b101079d76d0800a4d46f73262d50eea99a594..0b69b9342e824c8a96492429e051618d0fb88c2c 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,4 +1,4 @@ -use futures::{future, Sink, Stream}; +use futures::{future, Future, Sink, Stream}; use std::env::args; use std::process::exit; use tokio::runtime::current_thread::Runtime; @@ -23,36 +23,50 @@ fn main() { // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. - let (mut sink, stream) = client.split(); - // Wrap sink in Option so that we can take() it for the send(self) - // to consume and return it back when ready. - let mut send = move |stanza| { - sink.start_send(stanza).expect("start_send"); - }; + let (sink, stream) = client.split(); + let mut sink_state = Some(sink); // Main loop, processes events - let done = stream.for_each(|event| { + let done = stream.for_each(move |event| { + let mut sink_future = None; + if event.is_online() { println!("Online!"); let presence = make_presence(); - send(presence); + let sink = sink_state.take().unwrap(); + sink_future = Some(Box::new(sink.send(presence))); } else if let Some(message) = event .into_stanza() .and_then(|stanza| Message::try_from(stanza).ok()) { - // This is a message we'll echo match (message.from, message.bodies.get("")) { - (Some(from), Some(body)) => { + (Some(ref from), Some(ref body)) if body.0 == "die" => { + println!("Secret die command triggered by {}", from); + let sink = sink_state.as_mut().unwrap(); + sink.close().expect("close"); + } + (Some(ref from), Some(ref body)) => { if message.type_ != MessageType::Error { - let reply = make_reply(from, &body.0); - send(reply); + // This is a message we'll echo + let reply = make_reply(from.clone(), &body.0); + let sink = sink_state.take().unwrap(); + sink_future = Some(Box::new(sink.send(reply))); } } - _ => (), + _ => {} } - } + }; - Box::new(future::ok(())) + sink_future + .map(|future| { + let wait_send: Box> = + Box::new(future + .map(|sink| { + sink_state = Some(sink); + })); + wait_send + }) + .unwrap_or_else(|| Box::new(future::ok(()))) }); // Start polling `done` From be78f6578befe107deabdf040d4297f994a52054 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 01:34:44 +0100 Subject: [PATCH 113/135] Revert "client: add more state to make close() send ``" This reverts commit 6379f91e02fc0813e8478a1115bb9050d2a23cb6. --- src/client/mod.rs | 48 +++++++++-------------------------------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 025b4395f173fbfe52507d6af4021631584197fe..9033b83bcb624f779ee5f2b7fc5ba974ff90450d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -35,8 +35,6 @@ enum ClientState { Disconnected, Connecting(Box>), Connected(XMPPStream), - ClosingSendEnd(futures::sink::Send), - ClosingClose(XMPPStream), } impl Client { @@ -190,14 +188,6 @@ impl Stream for Client { Err(e) => Err(e)?, } } - ClientState::ClosingSendEnd(_) => { - self.state = state; - Ok(Async::NotReady) - } - ClientState::ClosingClose(_) => { - self.state = state; - Ok(Async::NotReady) - } } } } @@ -229,40 +219,20 @@ impl Sink for Client { fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { match self.state { ClientState::Connected(ref mut stream) => stream.poll_complete().map_err(|e| e.into()), - ClientState::ClosingSendEnd(ref mut send) => { - match send.poll()? { - Async::NotReady => - Ok(Async::NotReady), - Async::Ready(stream) => { - self.state = ClientState::ClosingClose(stream); - self.poll_complete() - } - } - } - ClientState::ClosingClose(ref mut stream) => { - match stream.close()? { - Async::NotReady => - Ok(Async::NotReady), - Async::Ready(()) => { - self.state = ClientState::Disconnected; - Ok(Async::Ready(())) - } - } - } _ => Ok(Async::Ready(())), } } - /// Send ` and later close the inner TCP stream. + /// This closes the inner TCP stream. + /// + /// To synchronize your shutdown with the server side, you should + /// first send `Packet::StreamEnd` and wait for the end of the + /// incoming stream before closing the connection. fn close(&mut self) -> Poll<(), Self::SinkError> { - let state = replace(&mut self.state, ClientState::Disconnected); - - match state { - ClientState::Connected(stream) => { - let send = stream.send(Packet::StreamEnd); - self.state = ClientState::ClosingSendEnd(send); - self.poll_complete() - } + match self.state { + ClientState::Connected(ref mut stream) => + stream.close() + .map_err(|e| e.into()), _ => Ok(Async::Ready(())), } From 39346506c89e82744f17f580eb145098a435b0c9 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 01:50:55 +0100 Subject: [PATCH 114/135] xmpp_codec: remove packet encoding unwrap()s --- src/xmpp_codec.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 82eda4a614d63d20076bc6cf5a17ff0bf4cbff45..17894b3cc027a35daa9b60881bf1bcb1500857dd 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -277,20 +277,28 @@ impl Encoder for XMPPCodec { dst.reserve(max_stanza_size - remaining); } + fn to_io_err>>(e: E) -> io::Error { + io::Error::new(io::ErrorKind::InvalidInput, e) + } + match item { Packet::StreamStart(start_attrs) => { let mut buf = String::new(); - write!(buf, "\n").unwrap(); + write!(buf, ">\n") + .map_err(to_io_err)?; // print!(">> {}", buf); - write!(dst, "{}", buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e)) + write!(dst, "{}", buf) + .map_err(to_io_err) } Packet::Stanza(stanza) => { stanza @@ -299,7 +307,7 @@ impl Encoder for XMPPCodec { // println!(">> {:?}", dst); Ok(()) }) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) + .map_err(|e| to_io_err(format!("{}", e))) } Packet::Text(text) => { write_text(&text, dst) @@ -307,7 +315,7 @@ impl Encoder for XMPPCodec { // println!(">> {:?}", dst); Ok(()) }) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{}", e))) + .map_err(to_io_err) } // TODO: Implement all _ => Ok(()), From 1e7031aa3109c1beb9d67abe996df8793774d70a Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 01:51:22 +0100 Subject: [PATCH 115/135] xmpp_codec: encode --- src/xmpp_codec.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 17894b3cc027a35daa9b60881bf1bcb1500857dd..482cd78694603e912caa905258582aea65cdc8b3 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -317,8 +317,10 @@ impl Encoder for XMPPCodec { }) .map_err(to_io_err) } - // TODO: Implement all - _ => Ok(()), + Packet::StreamEnd => { + write!(dst, "\n") + .map_err(to_io_err) + } } } } From 2654722fa3a6ddfc634e7025484c6665042456af Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 01:52:07 +0100 Subject: [PATCH 116/135] client: switch SinkItem to Packet this breaks backwards compatibility --- examples/echo_bot.rs | 10 +++++----- src/client/mod.rs | 19 ++++--------------- src/lib.rs | 1 + 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 0b69b9342e824c8a96492429e051618d0fb88c2c..9a47ccb5769a0d47e8cd7443f0ed8e891d489b7b 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -2,7 +2,7 @@ use futures::{future, Future, Sink, Stream}; use std::env::args; use std::process::exit; use tokio::runtime::current_thread::Runtime; -use tokio_xmpp::Client; +use tokio_xmpp::{Client, Packet}; use xmpp_parsers::{Jid, Element, TryFrom}; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; @@ -34,7 +34,7 @@ fn main() { let presence = make_presence(); let sink = sink_state.take().unwrap(); - sink_future = Some(Box::new(sink.send(presence))); + sink_future = Some(Box::new(sink.send(Packet::Stanza(presence)))); } else if let Some(message) = event .into_stanza() .and_then(|stanza| Message::try_from(stanza).ok()) @@ -42,15 +42,15 @@ fn main() { match (message.from, message.bodies.get("")) { (Some(ref from), Some(ref body)) if body.0 == "die" => { println!("Secret die command triggered by {}", from); - let sink = sink_state.as_mut().unwrap(); - sink.close().expect("close"); + let sink = sink_state.take().unwrap(); + sink_future = Some(Box::new(sink.send(Packet::StreamEnd))); } (Some(ref from), Some(ref body)) => { if message.type_ != MessageType::Error { // This is a message we'll echo let reply = make_reply(from.clone(), &body.0); let sink = sink_state.take().unwrap(); - sink_future = Some(Box::new(sink.send(reply))); + sink_future = Some(Box::new(sink.send(Packet::Stanza(reply)))); } } _ => {} diff --git a/src/client/mod.rs b/src/client/mod.rs index 9033b83bcb624f779ee5f2b7fc5ba974ff90450d..99965dc8ec695e4a1ee09a850dd343873a7e3182 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,6 +1,6 @@ use futures::{done, Async, AsyncSink, Future, Poll, Sink, StartSend, Stream}; use idna; -use xmpp_parsers::{Jid, JidParseError, Element}; +use xmpp_parsers::{Jid, JidParseError}; use sasl::common::{ChannelBinding, Credentials}; use std::mem::replace; use std::str::FromStr; @@ -193,24 +193,13 @@ impl Stream for Client { } impl Sink for Client { - type SinkItem = Element; + type SinkItem = Packet; type SinkError = Error; fn start_send(&mut self, item: Self::SinkItem) -> StartSend { match self.state { - ClientState::Connected(ref mut stream) => { - match stream.start_send(Packet::Stanza(item)) { - Ok(AsyncSink::NotReady(Packet::Stanza(stanza))) => - Ok(AsyncSink::NotReady(stanza)), - Ok(AsyncSink::NotReady(_)) => { - panic!("Client.start_send with stanza but got something else back") - } - Ok(AsyncSink::Ready) => - Ok(AsyncSink::Ready), - Err(e) => - Err(e)?, - } - } + ClientState::Connected(ref mut stream) => + Ok(stream.start_send(item)?), _ => Ok(AsyncSink::NotReady(item)), } diff --git a/src/lib.rs b/src/lib.rs index 39876b1917baaed46289aa35a5fd7e5d7997d36a..50fdcf7cecb62971b4498ab1f1b6fc6dee82007c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ extern crate derive_error; mod starttls; mod stream_start; pub mod xmpp_codec; +pub use crate::xmpp_codec::Packet; pub mod xmpp_stream; pub use crate::starttls::StartTlsClient; mod event; From 1d69b1a256f9d64deb4dce0422736056798b30be Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 23:04:42 +0100 Subject: [PATCH 117/135] improve echo_bot example --- examples/echo_bot.rs | 47 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 9a47ccb5769a0d47e8cd7443f0ed8e891d489b7b..cda70536a2eab561d00ec4d4bfc89437669f73d6 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -24,17 +24,32 @@ fn main() { // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. let (sink, stream) = client.split(); - let mut sink_state = Some(sink); + + // Create outgoing pipe + let (mut tx, rx) = futures::unsync::mpsc::unbounded(); + rt.spawn( + rx.forward( + sink.sink_map_err(|_| panic!("Pipe")) + ) + .map(|(rx, mut sink)| { + drop(rx); + let _ = sink.close(); + }) + .map_err(|e| { + panic!("Send error: {:?}", e); + }) + ); + // Main loop, processes events + let mut wait_for_stream_end = false; let done = stream.for_each(move |event| { - let mut sink_future = None; - - if event.is_online() { + if wait_for_stream_end { + /* Do nothing */ + } else if event.is_online() { println!("Online!"); let presence = make_presence(); - let sink = sink_state.take().unwrap(); - sink_future = Some(Box::new(sink.send(Packet::Stanza(presence)))); + tx.start_send(Packet::Stanza(presence)).unwrap(); } else if let Some(message) = event .into_stanza() .and_then(|stanza| Message::try_from(stanza).ok()) @@ -42,31 +57,21 @@ fn main() { match (message.from, message.bodies.get("")) { (Some(ref from), Some(ref body)) if body.0 == "die" => { println!("Secret die command triggered by {}", from); - let sink = sink_state.take().unwrap(); - sink_future = Some(Box::new(sink.send(Packet::StreamEnd))); + wait_for_stream_end = true; + tx.start_send(Packet::StreamEnd).unwrap(); } (Some(ref from), Some(ref body)) => { if message.type_ != MessageType::Error { // This is a message we'll echo let reply = make_reply(from.clone(), &body.0); - let sink = sink_state.take().unwrap(); - sink_future = Some(Box::new(sink.send(Packet::Stanza(reply)))); + tx.start_send(Packet::Stanza(reply)).unwrap(); } } _ => {} } - }; + } - sink_future - .map(|future| { - let wait_send: Box> = - Box::new(future - .map(|sink| { - sink_state = Some(sink); - })); - wait_send - }) - .unwrap_or_else(|| Box::new(future::ok(()))) + future::ok(()) }); // Start polling `done` From 12e2f4e7e75170a48ef9ae76e70533072abf7340 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 29 Jan 2019 23:08:27 +0100 Subject: [PATCH 118/135] tokio-xmpp 1.0.0 --- Cargo.lock | 479 +++++++++++++++++++++++++++++------------------------ Cargo.toml | 2 +- 2 files changed, 265 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88d2a7cb6b842c4606c5786b35f8772be98850ef..302b72327dbadbda9333b807ffbcd53ab03e9489 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "MacTypes-sys" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,7 +16,7 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -24,10 +24,10 @@ name = "backtrace" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -38,24 +38,15 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -68,39 +59,39 @@ name = "blake2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-buffer" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-padding" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byte-tools" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -108,7 +99,7 @@ name = "bytes" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -151,7 +142,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -159,18 +150,31 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-channel" -version = "0.3.6" +name = "crossbeam" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -178,18 +182,18 @@ name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -197,10 +201,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,7 +237,7 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -260,9 +265,9 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -284,6 +289,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -320,12 +330,21 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -336,7 +355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -344,7 +363,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -401,7 +420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.46" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -446,9 +465,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -461,12 +480,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -494,7 +512,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -508,7 +526,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -529,14 +547,14 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -546,7 +564,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -581,12 +599,12 @@ name = "num_cpus" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -598,7 +616,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -613,7 +631,7 @@ version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -640,13 +658,22 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -675,7 +702,7 @@ version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,7 +725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -714,10 +741,10 @@ name = "quick-xml" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -727,36 +754,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -767,21 +795,21 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -789,7 +817,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -797,18 +825,28 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_os" +name = "rand_jitter" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -818,7 +856,7 @@ name = "rand_pcg" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -827,7 +865,7 @@ name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -835,12 +873,12 @@ name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -878,18 +916,17 @@ name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "safemem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "sasl" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -908,23 +945,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "security-framework" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -942,27 +979,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -970,10 +1007,10 @@ name = "sha-1" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -981,10 +1018,10 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -992,11 +1029,11 @@ name = "sha3" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1011,7 +1048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1023,8 +1060,8 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1042,7 +1079,7 @@ dependencies = [ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1054,8 +1091,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1081,11 +1118,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.24" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1102,9 +1139,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1114,9 +1151,9 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1136,14 +1173,14 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1156,9 +1193,10 @@ dependencies = [ "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1187,7 +1225,7 @@ name = "tokio-executor" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1198,7 +1236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1216,7 +1254,7 @@ name = "tokio-reactor" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1228,6 +1266,14 @@ dependencies = [ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-sync" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-tcp" version = "0.1.3" @@ -1243,25 +1289,27 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1299,7 +1347,7 @@ dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1310,7 +1358,7 @@ dependencies = [ [[package]] name = "tokio-xmpp" -version = "0.2.2" +version = "1.0.0" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1318,43 +1366,43 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sasl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-proto" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-resolver" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1365,9 +1413,9 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1393,8 +1441,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-xid" @@ -1434,11 +1485,6 @@ name = "vcpkg" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "void" version = "1.0.2" @@ -1519,7 +1565,7 @@ name = "xmpp-parsers" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1532,19 +1578,18 @@ dependencies = [ ] [metadata] -"checksum MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7dbbe033994ae2198a18517c7132d952a29fb1db44249a1234779da7c50f4698" +"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" -"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" -"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" -"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e88b166b48e29667f5443df64df3c61dc07dc2b1a0b0d231800e07f09a33ecc1" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" @@ -1553,25 +1598,28 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" -"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ec098440b29ea3b1ece3e641bac424c19cf996779b623c9e0f2171495425c2c8" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" +"checksum encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fd251508d65030820f3a4317af2248180db337fdb25d89967956242580277813" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -1582,7 +1630,7 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" @@ -1590,7 +1638,7 @@ dependencies = [ "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "275024eea6c6ff4ace22f2750843831183785288eec1cff91a4e6b8898cf94f9" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" @@ -1603,13 +1651,14 @@ dependencies = [ "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" @@ -1617,45 +1666,45 @@ dependencies = [ "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98d8d2d671bd29c6122a98b45ce3106391e89ba378f731274de677f1eff06e5f" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fe7b8bc348249f3b1bbb9ab8baa6fa3419196ecfbf213408bca1b2494710de" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" -"checksum sasl 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbda5436dcd059da44fbf84b87a7164c5e3cad354efd0630c1f2be3c51c8859" +"checksum sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e457758c85b736bbad56dc099406cd2a9c19554cf81880dba7a51d092929e600" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" -"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2" +"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" +"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" -"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" -"checksum serde_json 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb1277d4d0563e4593e0b8b5d23d744d277b55d2bc0bf1c38d0d8a6589d38aa" +"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" +"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" +"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" @@ -1663,38 +1712,38 @@ dependencies = [ "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" "checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" "checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" "checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-sync 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d65a58e2215c13179e6eeb2cf00511e0aee455cad40a9bfaef15a2fd8aab1c7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "21c04a314a1f69f73c0227beba6250e06cdc1e9a62e7eff912bf54a59b6d1b94" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum trust-dns-proto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30dde452f5d142d5e316a3b32386da95280c98b7e266639f8f3bc6fdf507d279" -"checksum trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de630f95a192f793436ffae5137e88253cc4142a97d9a8e73c8d804fa85ddf0a" +"checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" +"checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/Cargo.toml b/Cargo.toml index afda4d2765c1a2d43e456f863bc26f71405d4c55..78e175fdd4816fd3e6c1ec80d2c844a457ced04c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-xmpp" -version = "0.2.3" +version = "1.0.0" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" From fc5569a7651d52f35aefaac10e4e17686144edb1 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 14 Feb 2019 20:02:37 +0100 Subject: [PATCH 119/135] add logo --- logo.svg | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 logo.svg diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..2e15a475a809525bbe1b0492a7e17ee840587287 --- /dev/null +++ b/logo.svg @@ -0,0 +1,172 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 11a45a1330b0763429e41edf707cf08e4eeee504 Mon Sep 17 00:00:00 2001 From: Voker57 Date: Mon, 11 Mar 2019 19:00:25 +0000 Subject: [PATCH 120/135] Fix a typo in documentation --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 50fdcf7cecb62971b4498ab1f1b6fc6dee82007c..bfed02a5029575f7f05770728c8130f82452d3bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![deny(unsafe_code, unused, missing_docs)] -//! XMPP implemeentation with asynchronous I/O using Tokio. +//! XMPP implementation with asynchronous I/O using Tokio. #[macro_use] extern crate derive_error; From 63afd5d939beebcc1ca7ad03df1588da2e9b8ec7 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 26 Feb 2019 21:35:38 +0100 Subject: [PATCH 121/135] Bump xmpp-parsers to 0.13. Fixes #4. --- Cargo.toml | 2 +- src/client/bind.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 78e175fdd4816fd3e6c1ec80d2c844a457ced04c..3bcdbd2ce289807fda144beeb7c1a99cb5151241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ tokio-tls = "0.2" sasl = "0.4" trust-dns-resolver = "0.10" trust-dns-proto = "0.6" -xmpp-parsers = "0.12.2" +xmpp-parsers = "0.13" idna = "0.1" quick-xml = "0.13" derive-error = "0.0.4" diff --git a/src/client/bind.rs b/src/client/bind.rs index 083650b9b94196fac4a797534f0083dc51222129..322458e524bdfbb793398fc103051eee3d0b5f9f 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -33,7 +33,7 @@ impl ClientBind { } Some(_) => { let resource = stream.jid.resource.clone(); - let iq = Iq::from_set(Bind::new(resource)).with_id(BIND_REQ_ID.to_string()); + let iq = Iq::from_set(BIND_REQ_ID, Bind::new(resource)); let send = stream.send_stanza(iq); ClientBind::WaitSend(send) } @@ -64,7 +64,7 @@ impl Future for ClientBind { ClientBind::WaitRecv(mut stream) => match stream.poll() { Ok(Async::Ready(Some(Packet::Stanza(stanza)))) => match Iq::try_from(stanza) { Ok(iq) => { - if iq.id == Some(BIND_REQ_ID.to_string()) { + if iq.id == BIND_REQ_ID { match iq.payload { IqType::Result(payload) => { payload From d04eb02d4c78e1e481f952df211f39818e3261e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Mon, 28 Jan 2019 21:39:54 +0000 Subject: [PATCH 122/135] Add "Contact Address for XMPP Services" (0157) example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maxime “pep” Buquet --- Cargo.lock | 8 ++- examples/contact_addr.rs | 130 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 examples/contact_addr.rs diff --git a/Cargo.lock b/Cargo.lock index 302b72327dbadbda9333b807ffbcd53ab03e9489..306ce86be222bbce12d47add98d776a0e0422ce8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "MacTypes-sys" version = "2.1.0" @@ -1374,7 +1376,7 @@ dependencies = [ "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1562,7 +1564,7 @@ dependencies = [ [[package]] name = "xmpp-parsers" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1755,4 +1757,4 @@ dependencies = [ "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd7ebf0203c620906230ce22caa5df0b603c32b6fef72a275a48f6a2ae64b9" -"checksum xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58b4400e1ae0d246044db5fa7f2e693fdfe9cc6e8eaa72ef2a68c5dc1d3c96de" +"checksum xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c467bb13e01718be793cb7a1c3d38d0e9ba45898db306aa43e70657a8aa3c2f2" diff --git a/examples/contact_addr.rs b/examples/contact_addr.rs new file mode 100644 index 0000000000000000000000000000000000000000..0d74f8ee16f329e8e1c091a1180d31be0d6ff2b3 --- /dev/null +++ b/examples/contact_addr.rs @@ -0,0 +1,130 @@ +use futures::{future, Sink, Stream}; +use std::env::args; +use std::process::exit; +use tokio::runtime::current_thread::Runtime; +use tokio_xmpp::{Client, xmpp_codec::Packet}; +use xmpp_parsers::{ + Element, + Jid, + TryFrom, + ns, + iq::{ + Iq, + IqType, + }, + disco::{ + DiscoInfoResult, + DiscoInfoQuery, + }, + server_info::ServerInfo, +}; + +fn main() { + let args: Vec = args().collect(); + if args.len() != 4 { + println!("Usage: {} ", args[0]); + exit(1); + } + let jid = &args[1]; + let password = &args[2]; + let target = &args[3]; + + // tokio_core context + let mut rt = Runtime::new().unwrap(); + // Client instance + let client = Client::new(jid, password).unwrap(); + + // Make the two interfaces for sending and receiving independent + // of each other so we can move one into a closure. + let (mut sink, stream) = client.split(); + // Wrap sink in Option so that we can take() it for the send(self) + // to consume and return it back when ready. + let mut send = move |packet| { + sink.start_send(packet).expect("start_send"); + }; + // Main loop, processes events + let mut wait_for_stream_end = false; + let done = stream.for_each(|event| { + if wait_for_stream_end { + /* Do Nothing. */ + } else if event.is_online() { + println!("Online!"); + + let target_jid: Jid = target.clone().parse().unwrap(); + let iq = make_disco_iq(target_jid); + println!("Sending disco#info request to {}", target.clone()); + println!(">> {}", String::from(&iq)); + send(Packet::Stanza(iq)); + } else if let Some(stanza) = event.into_stanza() { + if stanza.is("iq", "jabber:client") { + let iq = Iq::try_from(stanza).unwrap(); + if let IqType::Result(Some(payload)) = iq.payload { + if payload.is("query", ns::DISCO_INFO) { + if let Ok(disco_info) = DiscoInfoResult::try_from(payload) { + for ext in disco_info.extensions { + if let Ok(server_info) = ServerInfo::try_from(ext) { + print_server_info(server_info); + wait_for_stream_end = true; + send(Packet::StreamEnd); + } + } + } + } + } + } + } + + Box::new(future::ok(())) + }); + + // Start polling `done` + match rt.block_on(done) { + Ok(_) => (), + Err(e) => { + println!("Fatal: {}", e); + () + } + } +} + +fn make_disco_iq(target: Jid) -> Element { + Iq::from_get("disco", DiscoInfoQuery { node: None }) + .with_id(String::from("contact")) + .with_to(target) + .into() +} + +fn convert_field(field: Vec) -> String { + field.iter() + .fold((field.len(), String::new()), |(l, mut acc), s| { + acc.push('<'); + acc.push_str(&s); + acc.push('>'); + if l > 1 { + acc.push(','); + acc.push(' '); + } + (0, acc) + }).1 +} + +fn print_server_info(server_info: ServerInfo) { + if server_info.abuse.len() != 0 { + println!("abuse: {}", convert_field(server_info.abuse)); + } + if server_info.admin.len() != 0 { + println!("admin: {}", convert_field(server_info.admin)); + } + if server_info.feedback.len() != 0 { + println!("feedback: {}", convert_field(server_info.feedback)); + } + if server_info.sales.len() != 0 { + println!("sales: {}", convert_field(server_info.sales)); + } + if server_info.security.len() != 0 { + println!("security: {}", convert_field(server_info.security)); + } + if server_info.support.len() != 0 { + println!("support: {}", convert_field(server_info.support)); + } +} From 2e10ff8091e579c6efe3f8316df620609d87f1bb Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 26 Feb 2019 19:28:41 +0100 Subject: [PATCH 123/135] download_avatars: new example client --- examples/download_avatars.rs | 230 +++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 examples/download_avatars.rs diff --git a/examples/download_avatars.rs b/examples/download_avatars.rs new file mode 100644 index 0000000000000000000000000000000000000000..06ff8c343e330cfa7c2220ff150d2731683ba048 --- /dev/null +++ b/examples/download_avatars.rs @@ -0,0 +1,230 @@ +use futures::{future, Future, Sink, Stream}; +use std::env::args; +use std::fs::{create_dir_all, File}; +use std::io::{self, Write}; +use std::process::exit; +use std::str::FromStr; +use tokio::runtime::current_thread::Runtime; +use tokio_xmpp::{Client, Packet}; +use xmpp_parsers::{ + avatar::{Data as AvatarData, Metadata as AvatarMetadata}, + caps::{compute_disco, hash_caps, Caps}, + disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity}, + hashes::Algo, + iq::{Iq, IqType}, + message::Message, + ns, + presence::{Presence, Type as PresenceType}, + pubsub::{ + event::PubSubEvent, + pubsub::{Items, PubSub}, + NodeName, + }, + stanza_error::{StanzaError, ErrorType, DefinedCondition}, + Jid, TryFrom, +}; + +fn main() { + let args: Vec = args().collect(); + if args.len() != 3 { + println!("Usage: {} ", args[0]); + exit(1); + } + let jid = &args[1]; + let password = &args[2]; + + // tokio_core context + let mut rt = Runtime::new().unwrap(); + // Client instance + let client = Client::new(jid, password).unwrap(); + + // Make the two interfaces for sending and receiving independent + // of each other so we can move one into a closure. + let (sink, stream) = client.split(); + + // Create outgoing pipe + let (mut tx, rx) = futures::unsync::mpsc::unbounded(); + rt.spawn( + rx.forward( + sink.sink_map_err(|_| panic!("Pipe")) + ) + .map(|(rx, mut sink)| { + drop(rx); + let _ = sink.close(); + }) + .map_err(|e| { + panic!("Send error: {:?}", e); + }) + ); + + let disco_info = make_disco(); + + // Main loop, processes events + let mut wait_for_stream_end = false; + let done = stream.for_each(move |event| { + // Helper function to send an iq error. + let mut send_error = |to, id, type_, condition, text: &str| { + let error = StanzaError::new(type_, condition, "en", text); + let iq = Iq::from_error(id, error) + .with_to(to); + tx.start_send(Packet::Stanza(iq.into())).unwrap(); + }; + + if wait_for_stream_end { + /* Do nothing */ + } else if event.is_online() { + println!("Online!"); + + let caps = get_disco_caps(&disco_info, "https://gitlab.com/xmpp-rs/tokio-xmpp"); + let presence = make_presence(caps); + tx.start_send(Packet::Stanza(presence.into())).unwrap(); + } else if let Some(stanza) = event.into_stanza() { + if stanza.is("iq", "jabber:client") { + let iq = Iq::try_from(stanza).unwrap(); + if let IqType::Get(payload) = iq.payload { + if payload.is("query", ns::DISCO_INFO) { + let query = DiscoInfoQuery::try_from(payload); + match query { + Ok(query) => { + let mut disco = disco_info.clone(); + disco.node = query.node; + let iq = Iq::from_result(iq.id, Some(disco)) + .with_to(iq.from.unwrap()); + tx.start_send(Packet::Stanza(iq.into())).unwrap(); + }, + Err(err) => { + send_error(iq.from.unwrap(), iq.id, ErrorType::Modify, DefinedCondition::BadRequest, &format!("{}", err)); + }, + } + } else { + // We MUST answer unhandled get iqs with a service-unavailable error. + send_error(iq.from.unwrap(), iq.id, ErrorType::Cancel, DefinedCondition::ServiceUnavailable, "No handler defined for this kind of iq."); + } + } else if let IqType::Result(Some(payload)) = iq.payload { + if payload.is("pubsub", ns::PUBSUB) { + let pubsub = PubSub::try_from(payload).unwrap(); + let from = + iq.from.clone().unwrap_or(Jid::from_str(jid).unwrap()); + handle_iq_result(pubsub, &from); + } + } else if let IqType::Set(_) = iq.payload { + // We MUST answer unhandled set iqs with a service-unavailable error. + send_error(iq.from.unwrap(), iq.id, ErrorType::Cancel, DefinedCondition::ServiceUnavailable, "No handler defined for this kind of iq."); + } + } else if stanza.is("message", "jabber:client") { + let message = Message::try_from(stanza).unwrap(); + let from = message.from.clone().unwrap(); + if let Some(body) = message.get_best_body(vec!["en"]) { + if body.1 .0 == "die" { + println!("Secret die command triggered by {}", from); + wait_for_stream_end = true; + tx.start_send(Packet::StreamEnd).unwrap(); + } + } + for child in message.payloads { + if child.is("event", ns::PUBSUB_EVENT) { + let event = PubSubEvent::try_from(child).unwrap(); + if let PubSubEvent::PublishedItems { node, items } = event { + if node.0 == ns::AVATAR_METADATA { + for item in items { + let payload = item.payload.clone().unwrap(); + if payload.is("metadata", ns::AVATAR_METADATA) { + // TODO: do something with these metadata. + let _metadata = AvatarMetadata::try_from(payload).unwrap(); + println!( + "{} has published an avatar, downloading...", + from + ); + let iq = download_avatar(&from); + tx.start_send(Packet::Stanza(iq.into())).unwrap(); + } + } + } + } + } + } + } else if stanza.is("presence", "jabber:client") { + // Nothing to do here. + } else { + panic!("Unknown stanza: {}", String::from(&stanza)); + } + } + + future::ok(()) + }); + + // Start polling `done` + match rt.block_on(done) { + Ok(_) => (), + Err(e) => { + println!("Fatal: {}", e); + () + } + } +} + +fn make_disco() -> DiscoInfoResult { + let identities = vec![Identity::new("client", "bot", "en", "tokio-xmpp")]; + let features = vec![ + Feature::new(ns::DISCO_INFO), + Feature::new(format!("{}+notify", ns::AVATAR_METADATA)), + ]; + DiscoInfoResult { + node: None, + identities, + features, + extensions: vec![], + } +} + +fn get_disco_caps(disco: &DiscoInfoResult, node: &str) -> Caps { + let caps_data = compute_disco(disco); + let hash = hash_caps(&caps_data, Algo::Sha_1).unwrap(); + Caps::new(node, hash) +} + +// Construct a +fn make_presence(caps: Caps) -> Presence { + let mut presence = Presence::new(PresenceType::None) + .with_priority(-1); + presence.set_status("en", "Downloading avatars."); + presence.add_payload(caps); + presence +} + +fn download_avatar(from: &Jid) -> Iq { + Iq::from_get("coucou", PubSub::Items(Items { + max_items: None, + node: NodeName(String::from(ns::AVATAR_DATA)), + subid: None, + items: Vec::new(), + })) + .with_to(from.clone()) +} + +fn handle_iq_result(pubsub: PubSub, from: &Jid) { + if let PubSub::Items(items) = pubsub { + if items.node.0 == ns::AVATAR_DATA { + for item in items.items { + if let Some(id) = item.id.clone() { + if let Some(payload) = &item.payload { + let data = AvatarData::try_from(payload.clone()).unwrap(); + save_avatar(from, id.0, &data.data).unwrap(); + } + } + } + } + } +} + +fn save_avatar(from: &Jid, id: String, data: &[u8]) -> io::Result<()> { + let directory = format!("data/{}", from); + let filename = format!("data/{}/{}", from, id); + println!( + "Saving avatar from {} to {}.", + from, filename + ); + create_dir_all(directory)?; + let mut file = File::create(filename)?; + file.write_all(data) +} From 956193e0daa217a780360683fbf13f621adc6ef6 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 12 Jun 2019 16:29:55 +0200 Subject: [PATCH 124/135] Fix all bare_trait_objects warnings, and deny them. --- src/client/auth.rs | 6 +++--- src/client/mod.rs | 2 +- src/component/mod.rs | 2 +- src/error.rs | 2 +- src/lib.rs | 2 +- src/xmpp_codec.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/client/auth.rs b/src/client/auth.rs index d961f7a0988b1b26ef11b99038e8bebab312d499..81210dc7539c85ebfada329cc7b8accec7f404e4 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -16,12 +16,12 @@ use crate::{AuthError, Error, ProtocolError}; const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; pub struct ClientAuth { - future: Box, Error = Error>>, + future: Box, Error = Error>>, } impl ClientAuth { pub fn new(stream: XMPPStream, creds: Credentials) -> Result { - let local_mechs: Vec Box>> = vec![ + let local_mechs: Vec Box>> = vec![ Box::new(|| Box::new(Scram::::from_credentials(creds.clone()).unwrap())), Box::new(|| Box::new(Scram::::from_credentials(creds.clone()).unwrap())), Box::new(|| Box::new(Plain::from_credentials(creds.clone()).unwrap())), @@ -62,7 +62,7 @@ impl ClientAuth { Err(AuthError::NoMechanism)? } - fn handle_challenge(stream: XMPPStream, mut mechanism: Box) -> Box, Error = Error>> { + fn handle_challenge(stream: XMPPStream, mut mechanism: Box) -> Box, Error = Error>> { Box::new( stream.into_future() .map_err(|(e, _stream)| e.into()) diff --git a/src/client/mod.rs b/src/client/mod.rs index 99965dc8ec695e4a1ee09a850dd343873a7e3182..37085788976a041c07b8339b991ddea0c0f849c7 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -33,7 +33,7 @@ const NS_JABBER_CLIENT: &str = "jabber:client"; enum ClientState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } diff --git a/src/component/mod.rs b/src/component/mod.rs index cfc1ee5e2452504a6a39daa06fa26b3e0a61db5f..8738111780499591c021ffa9a9693d55d8b8c322 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -30,7 +30,7 @@ const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept"; enum ComponentState { Invalid, Disconnected, - Connecting(Box>), + Connecting(Box>), Connected(XMPPStream), } diff --git a/src/error.rs b/src/error.rs index 375c5178c6c4ff908c5a8bde3af12227b025ef6f..d8b2063d473b44039e3d271472d5f27cb855ec6f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -59,7 +59,7 @@ impl StdError for ParseError { fn description(&self) -> &str { self.0.as_ref() } - fn cause(&self) -> Option<&StdError> { + fn cause(&self) -> Option<&dyn StdError> { None } } diff --git a/src/lib.rs b/src/lib.rs index bfed02a5029575f7f05770728c8130f82452d3bf..07ae878437455e1694c95b9cf41c8582ba73014f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_code, unused, missing_docs)] +#![deny(unsafe_code, unused, missing_docs, bare_trait_objects)] //! XMPP implementation with asynchronous I/O using Tokio. diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 482cd78694603e912caa905258582aea65cdc8b3..3920ba416145de670773b7c2ff53a2aaec4e7305 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -219,7 +219,7 @@ impl Decoder for XMPPCodec { type Error = ParserError; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - let buf1: Box> = if !self.buf.is_empty() && !buf.is_empty() { + let buf1: Box> = if !self.buf.is_empty() && !buf.is_empty() { let mut prefix = std::mem::replace(&mut self.buf, vec![]); prefix.extend_from_slice(buf.take().as_ref()); Box::new(prefix) From c6ab5a22b89467b1390247a18fc93f487e29d197 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 12 Jun 2019 16:44:13 +0200 Subject: [PATCH 125/135] Update xml5ever. --- Cargo.toml | 2 +- src/xmpp_codec.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3bcdbd2ce289807fda144beeb7c1a99cb5151241..db18052106adb775cc50b474b8f01a3e59703f5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ tokio = "0.1" tokio-io = "0.1" tokio-codec = "0.1" bytes = "0.4" -xml5ever = "0.12" +xml5ever = "0.14" native-tls = "0.2" tokio-tls = "0.2" sasl = "0.4" diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 3920ba416145de670773b7c2ff53a2aaec4e7305..0002087361b4d9341e630b15afc772b90642f813 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -18,6 +18,7 @@ use std::borrow::Cow; use tokio_codec::{Decoder, Encoder}; use xml5ever::interface::Attribute; use xml5ever::tokenizer::{Tag, TagKind, Token, TokenSink, XmlTokenizer}; +use xml5ever::buffer_queue::BufferQueue; /// Anything that can be sent or received on an XMPP/XML stream #[derive(Debug, Clone, PartialEq, Eq)] @@ -231,8 +232,10 @@ impl Decoder for XMPPCodec { Ok(s) => { if !s.is_empty() { // println!("<< {}", s); + let mut buffer_queue = BufferQueue::new(); let tendril = FromIterator::from_iter(s.chars()); - self.parser.feed(tendril); + buffer_queue.push_back(tendril); + self.parser.feed(&mut buffer_queue); } } // Remedies for truncated utf8 From 1eaf06bf1cd97d1cab5d01fdbd1114a967002b52 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 12 Jun 2019 16:48:39 +0200 Subject: [PATCH 126/135] Update trust-dns. --- Cargo.toml | 4 ++-- src/happy_eyeballs.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db18052106adb775cc50b474b8f01a3e59703f5f..a62b4ba1d696ff9e8e4047315844274c9af2b1e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,8 +21,8 @@ xml5ever = "0.14" native-tls = "0.2" tokio-tls = "0.2" sasl = "0.4" -trust-dns-resolver = "0.10" -trust-dns-proto = "0.6" +trust-dns-resolver = "0.11" +trust-dns-proto = "0.7" xmpp-parsers = "0.13" idna = "0.1" quick-xml = "0.13" diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index fc4e0280501f1444f2f8b43439d68612352d5036..7696f65e2cfa42f8903259b341719f381cc3b9b3 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -79,7 +79,7 @@ impl Connecter { // Initialize state match &self_.srv_domain { &Some(ref srv_domain) => { - let srv_lookup = resolver.lookup_srv(srv_domain); + let srv_lookup = resolver.lookup_srv(srv_domain.clone()); self_.state = State::ResolveSrv(resolver, srv_lookup); } None => { From ed28ba1a7d63c1422443f3dca32c848869a14501 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 5 Sep 2019 22:25:28 +0200 Subject: [PATCH 127/135] Remove the derive-error dependency. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It depends on a way too old syn crate, let’s drop it. --- Cargo.toml | 1 - src/error.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 3 -- 3 files changed, 105 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a62b4ba1d696ff9e8e4047315844274c9af2b1e4..c22979f6e5531a579f3418d747487a535cbad39e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,3 @@ trust-dns-proto = "0.7" xmpp-parsers = "0.13" idna = "0.1" quick-xml = "0.13" -derive-error = "0.0.4" diff --git a/src/error.rs b/src/error.rs index d8b2063d473b44039e3d271472d5f27cb855ec6f..68a1412e9f4d2b87c91c392514e2ec5f7b1217c6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,7 +11,7 @@ use xmpp_parsers::Error as ParsersError; use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; /// Top-level error type -#[derive(Debug, Error)] +#[derive(Debug)] pub enum Error { /// I/O error Io(IoError), @@ -32,8 +32,53 @@ pub enum Error { InvalidState, } +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::Io(e) => write!(fmt, "IO error: {}", e), + Error::Connection(e) => write!(fmt, "connection error: {}", e), + Error::Idna => write!(fmt, "IDNA error"), + Error::Protocol(e) => write!(fmt, "protocol error: {}", e), + Error::Auth(e) => write!(fmt, "authentication error: {}", e), + Error::Tls(e) => write!(fmt, "TLS error: {}", e), + Error::Disconnected => write!(fmt, "disconnected"), + Error::InvalidState => write!(fmt, "invalid state"), + } + } +} + +impl From for Error { + fn from(e: IoError) -> Self { + Error::Io(e) + } +} + +impl From for Error { + fn from(e: ConnecterError) -> Self { + Error::Connection(e) + } +} + +impl From for Error { + fn from(e: ProtocolError) -> Self { + Error::Protocol(e) + } +} + +impl From for Error { + fn from(e: AuthError) -> Self { + Error::Auth(e) + } +} + +impl From for Error { + fn from(e: TlsError) -> Self { + Error::Tls(e) + } +} + /// Causes for stream parsing errors -#[derive(Debug, Error)] +#[derive(Debug)] pub enum ParserError { /// Encoding error Utf8(Utf8Error), @@ -42,7 +87,24 @@ pub enum ParserError { /// Illegal `` ShortTag, /// Required by `impl Decoder` - IO(IoError), + Io(IoError), +} + +impl fmt::Display for ParserError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + ParserError::Utf8(e) => write!(fmt, "UTF-8 error: {}", e), + ParserError::Parse(e) => write!(fmt, "parse error: {}", e), + ParserError::ShortTag => write!(fmt, "short tag"), + ParserError::Io(e) => write!(fmt, "IO error: {}", e), + } + } +} + +impl From for ParserError { + fn from(e: IoError) -> Self { + ParserError::Io(e) + } } impl From for Error { @@ -71,12 +133,11 @@ impl fmt::Display for ParseError { } /// XMPP protocol-level error -#[derive(Debug, Error)] +#[derive(Debug)] pub enum ProtocolError { /// XML parser error Parser(ParserError), /// Error with expected stanza schema - #[error(non_std)] Parsers(ParsersError), /// No TLS available NoTls, @@ -92,22 +153,57 @@ pub enum ProtocolError { InvalidStreamStart, } +impl fmt::Display for ProtocolError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e), + ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e), + ProtocolError::NoTls => write!(fmt, "no TLS available"), + ProtocolError::InvalidBindResponse => write!(fmt, "invalid response to resource binding"), + ProtocolError::NoStreamNamespace => write!(fmt, "no xmlns attribute in "), + ProtocolError::NoStreamId => write!(fmt, "no id attribute in "), + ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"), + ProtocolError::InvalidStreamStart => write!(fmt, "unexpected "), + } + } +} + +impl From for ProtocolError { + fn from(e: ParserError) -> Self { + ProtocolError::Parser(e) + } +} + +impl From for ProtocolError { + fn from(e: ParsersError) -> Self { + ProtocolError::Parsers(e) + } +} + /// Authentication error -#[derive(Debug, Error)] +#[derive(Debug)] pub enum AuthError { /// No matching SASL mechanism available NoMechanism, /// Local SASL implementation error - #[error(no_from, non_std, msg_embedded)] Sasl(String), /// Failure from server - #[error(non_std)] Fail(SaslDefinedCondition), /// Component authentication failure - #[error(no_from)] ComponentFail, } +impl fmt::Display for AuthError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"), + AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s), + AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c), + AuthError::ComponentFail => write!(fmt, "component authentication failure"), + } + } +} + /// Error establishing connection #[derive(Debug)] pub enum ConnecterError { diff --git a/src/lib.rs b/src/lib.rs index 07ae878437455e1694c95b9cf41c8582ba73014f..2bd823eef822a644becfa69b81c3d3b45782317f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,6 @@ //! XMPP implementation with asynchronous I/O using Tokio. -#[macro_use] -extern crate derive_error; - mod starttls; mod stream_start; pub mod xmpp_codec; From 2e97f4de2e44c64524bbe9990553627e7a47f805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Sun, 8 Sep 2019 15:05:57 +0200 Subject: [PATCH 128/135] Fixes #11: Trim whitespace before feeding parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maxime “pep” Buquet --- src/xmpp_codec.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 0002087361b4d9341e630b15afc772b90642f813..654cc21ae71ea823a73fb6fa2244f5779de6a92e 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -229,7 +229,8 @@ impl Decoder for XMPPCodec { }; let buf1 = buf1.as_ref().as_ref(); match from_utf8(buf1) { - Ok(s) => { + Ok(mut s) => { + s = s.trim(); if !s.is_empty() { // println!("<< {}", s); let mut buffer_queue = BufferQueue::new(); @@ -508,4 +509,24 @@ mod tests { &("".to_owned() + &text + "").as_bytes() ); } + + #[test] + fn test_lone_whitespace() { + let mut c = XMPPCodec::new(); + let mut b = BytesMut::with_capacity(1024); + b.put(r""); + let r = c.decode(&mut b); + assert!(match r { + Ok(Some(Packet::StreamStart(_))) => true, + _ => false, + }); + + b.clear(); + b.put(r" "); + let r = c.decode(&mut b); + assert!(match r { + Ok(None) => true, + _ => false, + }); + } } From 3b37646d0a60ff2bc99139fa68802ac89b211f72 Mon Sep 17 00:00:00 2001 From: SonnyX Date: Sun, 8 Sep 2019 21:28:44 +0200 Subject: [PATCH 129/135] Update dependencies --- Cargo.lock | 1164 +++++++++++++++++----------------- Cargo.toml | 20 +- examples/contact_addr.rs | 2 +- examples/download_avatars.rs | 13 +- examples/echo_bot.rs | 7 +- examples/echo_component.rs | 7 +- src/client/auth.rs | 2 +- src/client/bind.rs | 21 +- src/client/mod.rs | 4 +- src/starttls.rs | 2 +- src/stream_start.rs | 2 +- src/xmpp_codec.rs | 2 +- 12 files changed, 617 insertions(+), 629 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 306ce86be222bbce12d47add98d776a0e0422ce8..ac0af39db11a1f3ebf49e483cba9db20c546e3d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,8 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "MacTypes-sys" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -18,29 +10,27 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -48,39 +38,39 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-buffer" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-padding" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -93,40 +83,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "case" -version = "0.1.0" +name = "c2-chacha" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cc" -version = "1.0.28" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -135,79 +130,60 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation" -version = "0.5.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "crossbeam-channel" -version = "0.3.8" +name = "crossbeam-deque" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-deque" -version = "0.6.3" +name = "crossbeam-epoch" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-epoch" -version = "0.7.1" +name = "crossbeam-queue" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -215,42 +191,26 @@ name = "crypto-mac" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "derive-error" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "digest" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding_rs" -version = "0.8.15" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "error-chain" -version = "0.8.1" +name = "enum-as-inner" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -258,7 +218,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -267,10 +227,10 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -278,6 +238,11 @@ name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "foreign-types" version = "0.3.2" @@ -293,7 +258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fuchsia-cprng" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -301,7 +266,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -316,29 +281,39 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures" -version = "0.1.25" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "generic-array" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hmac" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -346,13 +321,13 @@ name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "idna" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -365,35 +340,32 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ipconfig" -version = "0.1.9" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jid" -version = "0.5.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "minidom 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -412,22 +384,17 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "linked-hash-map" -version = "0.4.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -441,18 +408,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lru-cache" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -462,14 +429,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "markup5ever" -version = "0.7.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -482,40 +450,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.1.3" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memoffset" -version = "0.2.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "minidom" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.16" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -528,8 +492,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -545,19 +509,19 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -565,18 +529,15 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "new_debug_unreachable" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "nodrop" @@ -585,41 +546,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -629,13 +594,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.40" +version = "0.9.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -660,11 +626,11 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -672,13 +638,13 @@ name = "pbkdf2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "percent-encoding" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -717,7 +683,12 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.14" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ppv-lite86" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -727,12 +698,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.26" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -740,38 +719,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quick-xml" -version = "0.13.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.6.11" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand" -version = "0.5.6" +name = "quote" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -779,17 +746,29 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -797,22 +776,39 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_core" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rand_hc" @@ -822,6 +818,14 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -832,34 +836,34 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -880,15 +884,15 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.51" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "remove_dir_all" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,7 +906,7 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -915,7 +919,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -924,20 +928,20 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "schannel" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -945,25 +949,28 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "security-framework" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -981,27 +988,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.85" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1009,10 +1016,10 @@ name = "sha-1" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1020,22 +1027,22 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sha3" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1050,21 +1057,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "socket2" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1077,11 +1081,11 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1093,8 +1097,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1110,54 +1114,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.11.11" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "synom" -version = "0.11.3" +name = "syn" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.5" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1175,31 +1171,31 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.15" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1208,72 +1204,74 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.0" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1281,40 +1279,39 @@ name = "tokio-tcp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.11" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1322,23 +1319,23 @@ name = "tokio-tls" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1346,91 +1343,85 @@ name = "tokio-uds" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-xmpp" version = "1.0.0" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", "sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xml5ever 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xmpp-parsers 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-proto" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trust-dns-resolver" -version = "0.10.3" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "try_from" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "typenum" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1446,35 +1437,27 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" +name = "unicode-xid" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "url" -version = "1.7.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1484,17 +1467,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vcpkg" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "void" -version = "1.0.2" +name = "wasi" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "widestring" -version = "0.2.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1504,7 +1487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1528,10 +1511,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winreg" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1539,7 +1522,7 @@ name = "winutil" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1553,208 +1536,207 @@ dependencies = [ [[package]] name = "xml5ever" -version = "0.12.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "xmpp-parsers" -version = "0.13.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jid 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "minidom 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" -"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" -"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e88b166b48e29667f5443df64df3c61dc07dc2b1a0b0d231800e07f09a33ecc1" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" -"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ec098440b29ea3b1ece3e641bac424c19cf996779b623c9e0f2171495425c2c8" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fd251508d65030820f3a4317af2248180db337fdb25d89967956242580277813" -"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" -"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" -"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum jid 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "24e8a3f2ab860aa08074136e3144a2425e678d8823206e5adcc6145dc136503a" +"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum jid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e3676672e1f13e4963e6af2c1d17114e7f9f96f96477c278fccdd192c618c67" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" -"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -"checksum markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" +"checksum markup5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65381d9d47506b8592b97c4efd936afcf673b09b059f2bef39c7211ee78b9d03" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "275024eea6c6ff4ace22f2750843831183785288eec1cff91a4e6b8898cf94f9" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum minidom 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df1f29c97815c4328d6b533d2b8976e80cbed02d97063970aa4a80c100ecf29a" +"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quick-xml 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98d8d2d671bd29c6122a98b45ce3106391e89ba378f731274de677f1eff06e5f" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum quick-xml 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd45021132c1cb5540995e93fcc2cf5a874ef84f9639168fb6819caa023d4be" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fe7b8bc348249f3b1bbb9ab8baa6fa3419196ecfbf213408bca1b2494710de" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e457758c85b736bbad56dc099406cd2a9c19554cf81880dba7a51d092929e600" -"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" +"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" -"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" -"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a" +"checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" +"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" -"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" -"checksum tokio-sync 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d65a58e2215c13179e6eeb2cf00511e0aee455cad40a9bfaef15a2fd8aab1c7" +"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" -"checksum tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "21c04a314a1f69f73c0227beba6250e06cdc1e9a62e7eff912bf54a59b6d1b94" +"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" +"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" -"checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" -"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05457ece29839d056d8cb66ec080209d34492b3d2e7e00641b486977be973db9" +"checksum trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb1b3a41ee784f8da051cd342c6f42a3a75ee45818164acad867eac8f2f85332" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" -"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" +"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd7ebf0203c620906230ce22caa5df0b603c32b6fef72a275a48f6a2ae64b9" -"checksum xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c467bb13e01718be793cb7a1c3d38d0e9ba45898db306aa43e70657a8aa3c2f2" +"checksum xml5ever 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b93ca59bfbbc3c0f807a61faea54e6a4c753f82857d3730e9afb5523b6149c7" +"checksum xmpp-parsers 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57991f57c0011b66caeed8ed4380489b42c39c41364e31e4bbe011649cb79002" diff --git a/Cargo.toml b/Cargo.toml index c22979f6e5531a579f3418d747487a535cbad39e..c6b5c26ed4cfbb038a92b2e01bb616ba39bb1f1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,17 +12,17 @@ keywords = ["xmpp", "tokio"] edition = "2018" [dependencies] +bytes = "0.4" futures = "0.1" +idna = "0.2" +native-tls = "0.2" +sasl = "0.4" tokio = "0.1" -tokio-io = "0.1" tokio-codec = "0.1" -bytes = "0.4" -xml5ever = "0.14" -native-tls = "0.2" +trust-dns-resolver = "0.12" +trust-dns-proto = "0.8" +tokio-io = "0.1" tokio-tls = "0.2" -sasl = "0.4" -trust-dns-resolver = "0.11" -trust-dns-proto = "0.7" -xmpp-parsers = "0.13" -idna = "0.1" -quick-xml = "0.13" +quick-xml = "0.16" +xml5ever = "0.15" +xmpp-parsers = "0.15" diff --git a/examples/contact_addr.rs b/examples/contact_addr.rs index 0d74f8ee16f329e8e1c091a1180d31be0d6ff2b3..f60601a8cdacad09d2b0a5577e89e8d6591b0b4b 100644 --- a/examples/contact_addr.rs +++ b/examples/contact_addr.rs @@ -1,4 +1,5 @@ use futures::{future, Sink, Stream}; +use std::convert::TryFrom; use std::env::args; use std::process::exit; use tokio::runtime::current_thread::Runtime; @@ -6,7 +7,6 @@ use tokio_xmpp::{Client, xmpp_codec::Packet}; use xmpp_parsers::{ Element, Jid, - TryFrom, ns, iq::{ Iq, diff --git a/examples/download_avatars.rs b/examples/download_avatars.rs index 06ff8c343e330cfa7c2220ff150d2731683ba048..837dbec4dbe3415b60c22d26d4669e167496697d 100644 --- a/examples/download_avatars.rs +++ b/examples/download_avatars.rs @@ -1,4 +1,5 @@ use futures::{future, Future, Sink, Stream}; +use std::convert::TryFrom; use std::env::args; use std::fs::{create_dir_all, File}; use std::io::{self, Write}; @@ -21,7 +22,7 @@ use xmpp_parsers::{ NodeName, }, stanza_error::{StanzaError, ErrorType, DefinedCondition}, - Jid, TryFrom, + Jid, }; fn main() { @@ -116,7 +117,7 @@ fn main() { let from = message.from.clone().unwrap(); if let Some(body) = message.get_best_body(vec!["en"]) { if body.1 .0 == "die" { - println!("Secret die command triggered by {}", from); + println!("Secret die command triggered by {}", from.clone()); wait_for_stream_end = true; tx.start_send(Packet::StreamEnd).unwrap(); } @@ -133,7 +134,7 @@ fn main() { let _metadata = AvatarMetadata::try_from(payload).unwrap(); println!( "{} has published an avatar, downloading...", - from + from.clone() ); let iq = download_avatar(&from); tx.start_send(Packet::Stanza(iq.into())).unwrap(); @@ -218,11 +219,11 @@ fn handle_iq_result(pubsub: PubSub, from: &Jid) { } fn save_avatar(from: &Jid, id: String, data: &[u8]) -> io::Result<()> { - let directory = format!("data/{}", from); - let filename = format!("data/{}/{}", from, id); + let directory = format!("data/{}", from.clone()); + let filename = format!("data/{}/{}", from.clone(), id); println!( "Saving avatar from {} to {}.", - from, filename + from.clone(), filename ); create_dir_all(directory)?; let mut file = File::create(filename)?; diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index cda70536a2eab561d00ec4d4bfc89437669f73d6..6de2ce72d9132b2347d28ddbe56d985d768b0deb 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -1,9 +1,10 @@ use futures::{future, Future, Sink, Stream}; +use std::convert::TryFrom; use std::env::args; use std::process::exit; use tokio::runtime::current_thread::Runtime; use tokio_xmpp::{Client, Packet}; -use xmpp_parsers::{Jid, Element, TryFrom}; +use xmpp_parsers::{Jid, Element}; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; @@ -56,7 +57,7 @@ fn main() { { match (message.from, message.bodies.get("")) { (Some(ref from), Some(ref body)) if body.0 == "die" => { - println!("Secret die command triggered by {}", from); + println!("Secret die command triggered by {}", from.clone()); wait_for_stream_end = true; tx.start_send(Packet::StreamEnd).unwrap(); } @@ -87,7 +88,7 @@ fn main() { // Construct a fn make_presence() -> Element { let mut presence = Presence::new(PresenceType::None); - presence.show = PresenceShow::Chat; + presence.show = Some(PresenceShow::Chat); presence .statuses .insert(String::from("en"), String::from("Echoing messages.")); diff --git a/examples/echo_component.rs b/examples/echo_component.rs index 618032e324a422621c168df9e9a986f5f6fa282e..6a8bc33c8fbd09ca93e0bac20516de5eda72975c 100644 --- a/examples/echo_component.rs +++ b/examples/echo_component.rs @@ -1,10 +1,11 @@ use futures::{future, Sink, Stream}; +use std::convert::TryFrom; use std::env::args; use std::process::exit; use std::str::FromStr; use tokio::runtime::current_thread::Runtime; use tokio_xmpp::Component; -use xmpp_parsers::{Jid, Element, TryFrom}; +use xmpp_parsers::{Jid, Element}; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; @@ -31,7 +32,7 @@ fn main() { // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. - println!("Got it: {}", component.jid); + println!("Got it: {}", component.jid.clone()); let (mut sink, stream) = component.split(); // Wrap sink in Option so that we can take() it for the send(self) // to consume and return it back when ready. @@ -83,7 +84,7 @@ fn make_presence(from: Jid, to: Jid) -> Element { let mut presence = Presence::new(PresenceType::None); presence.from = Some(from); presence.to = Some(to); - presence.show = PresenceShow::Chat; + presence.show = Some(PresenceShow::Chat); presence .statuses .insert(String::from("en"), String::from("Echoing messages.")); diff --git a/src/client/auth.rs b/src/client/auth.rs index 81210dc7539c85ebfada329cc7b8accec7f404e4..096a0bfbca3070dea65c31942c55fc5d8dce2e99 100644 --- a/src/client/auth.rs +++ b/src/client/auth.rs @@ -1,12 +1,12 @@ use std::str::FromStr; use std::collections::HashSet; +use std::convert::TryFrom; use futures::{Future, Poll, Stream, future::{ok, err, IntoFuture}}; use sasl::client::mechanisms::{Anonymous, Plain, Scram}; use sasl::client::Mechanism; use sasl::common::scram::{Sha1, Sha256}; use sasl::common::Credentials; use tokio_io::{AsyncRead, AsyncWrite}; -use xmpp_parsers::TryFrom; use xmpp_parsers::sasl::{Auth, Challenge, Failure, Mechanism as XMPPMechanism, Response, Success}; use crate::xmpp_codec::Packet; diff --git a/src/client/bind.rs b/src/client/bind.rs index 322458e524bdfbb793398fc103051eee3d0b5f9f..f7d1828740dff5bfde15e22c01a4cba3ecfbdd6d 100644 --- a/src/client/bind.rs +++ b/src/client/bind.rs @@ -1,8 +1,9 @@ use futures::{sink, Async, Future, Poll, Stream}; +use std::convert::TryFrom; use std::mem::replace; use tokio_io::{AsyncRead, AsyncWrite}; -use xmpp_parsers::TryFrom; -use xmpp_parsers::bind::Bind; +use xmpp_parsers::Jid; +use xmpp_parsers::bind::{BindQuery, BindResponse}; use xmpp_parsers::iq::{Iq, IqType}; use crate::xmpp_codec::Packet; @@ -32,8 +33,13 @@ impl ClientBind { ClientBind::Unsupported(stream) } Some(_) => { - let resource = stream.jid.resource.clone(); - let iq = Iq::from_set(BIND_REQ_ID, Bind::new(resource)); + let resource; + if let Jid::Full(jid) = stream.jid.clone() { + resource = Some(jid.resource); + } else { + resource = None; + } + let iq = Iq::from_set(BIND_REQ_ID, BindQuery::new(resource)); let send = stream.send_stanza(iq); ClientBind::WaitSend(send) } @@ -68,11 +74,8 @@ impl Future for ClientBind { match iq.payload { IqType::Result(payload) => { payload - .and_then(|payload| Bind::try_from(payload).ok()) - .map(|bind| match bind { - Bind::Jid(jid) => stream.jid = jid, - _ => {} - }); + .and_then(|payload| BindResponse::try_from(payload).ok()) + .map(|bind| stream.jid = bind.into()); Ok(Async::Ready(stream)) } _ => Err(ProtocolError::InvalidBindResponse)?, diff --git a/src/client/mod.rs b/src/client/mod.rs index 37085788976a041c07b8339b991ddea0c0f849c7..4f31dad037645c8066cf5a92e3b3e2cf45beb6d3 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -60,11 +60,11 @@ impl Client { } fn make_connect(jid: Jid, password: String) -> impl Future { - let username = jid.node.as_ref().unwrap().to_owned(); + let username = jid.clone().node().unwrap(); let jid1 = jid.clone(); let jid2 = jid.clone(); let password = password; - done(idna::domain_to_ascii(&jid.domain)) + done(idna::domain_to_ascii(&jid.domain())) .map_err(|_| Error::Idna) .and_then(|domain| { done(Connecter::from_lookup( diff --git a/src/starttls.rs b/src/starttls.rs index 41bc6001da06f74b49403108c45616d787a1ae7f..e23402792b96ac6f858c8ead10df9a154414d966 100644 --- a/src/starttls.rs +++ b/src/starttls.rs @@ -70,7 +70,7 @@ impl Future for StartTlsClient { let stream = xmpp_stream.stream.into_inner(); let connect = TlsConnector::from(NativeTlsConnector::builder().build().unwrap()) - .connect(&self.jid.domain, stream); + .connect(&self.jid.clone().domain(), stream); let new_state = StartTlsClientState::StartingTls(connect); retry = true; (new_state, Ok(Async::NotReady)) diff --git a/src/stream_start.rs b/src/stream_start.rs index bf2d39e8b8968dc49474288be94a8c900f51beed..f82c3901e0aaf8f4d58adf2fd75af38621800b95 100644 --- a/src/stream_start.rs +++ b/src/stream_start.rs @@ -26,7 +26,7 @@ enum StreamStartState { impl StreamStart { pub fn from_stream(stream: Framed, jid: Jid, ns: String) -> Self { let attrs = [ - ("to".to_owned(), jid.domain.clone()), + ("to".to_owned(), jid.clone().domain()), ("version".to_owned(), "1.0".to_owned()), ("xmlns".to_owned(), ns.clone()), ("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), diff --git a/src/xmpp_codec.rs b/src/xmpp_codec.rs index 654cc21ae71ea823a73fb6fa2244f5779de6a92e..588d947d5c09898da7e6bbba36f3e6ff618fc218 100644 --- a/src/xmpp_codec.rs +++ b/src/xmpp_codec.rs @@ -501,7 +501,7 @@ mod tests { text = text + "A"; } let stanza = Element::builder("message") - .append(Element::builder("body").append(&text).build()) + .append(Element::builder("body").append(text.as_ref()).build()) .build(); let framed = framed.send(Packet::Stanza(stanza)).wait().expect("send"); assert_eq!( From fd27582ac74544434d32949fd3aa261350b403e1 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 9 Sep 2019 14:57:08 +0200 Subject: [PATCH 130/135] examples: remove a few .clone() calls --- examples/download_avatars.rs | 23 ++++++++++++----------- examples/echo_bot.rs | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/download_avatars.rs b/examples/download_avatars.rs index 837dbec4dbe3415b60c22d26d4669e167496697d..ec27b6e5a9ad97285735a4409179aea22d50d2a6 100644 --- a/examples/download_avatars.rs +++ b/examples/download_avatars.rs @@ -117,7 +117,7 @@ fn main() { let from = message.from.clone().unwrap(); if let Some(body) = message.get_best_body(vec!["en"]) { if body.1 .0 == "die" { - println!("Secret die command triggered by {}", from.clone()); + println!("Secret die command triggered by {}", from); wait_for_stream_end = true; tx.start_send(Packet::StreamEnd).unwrap(); } @@ -127,7 +127,7 @@ fn main() { let event = PubSubEvent::try_from(child).unwrap(); if let PubSubEvent::PublishedItems { node, items } = event { if node.0 == ns::AVATAR_METADATA { - for item in items { + for item in items.into_iter() { let payload = item.payload.clone().unwrap(); if payload.is("metadata", ns::AVATAR_METADATA) { // TODO: do something with these metadata. @@ -136,7 +136,7 @@ fn main() { "{} has published an avatar, downloading...", from.clone() ); - let iq = download_avatar(&from); + let iq = download_avatar(from.clone()); tx.start_send(Packet::Stanza(iq.into())).unwrap(); } } @@ -193,25 +193,26 @@ fn make_presence(caps: Caps) -> Presence { presence } -fn download_avatar(from: &Jid) -> Iq { +fn download_avatar(from: Jid) -> Iq { Iq::from_get("coucou", PubSub::Items(Items { max_items: None, node: NodeName(String::from(ns::AVATAR_DATA)), subid: None, items: Vec::new(), })) - .with_to(from.clone()) + .with_to(from) } fn handle_iq_result(pubsub: PubSub, from: &Jid) { if let PubSub::Items(items) = pubsub { if items.node.0 == ns::AVATAR_DATA { for item in items.items { - if let Some(id) = item.id.clone() { - if let Some(payload) = &item.payload { - let data = AvatarData::try_from(payload.clone()).unwrap(); + match (item.id.clone(), item.payload.clone()) { + (Some(id), Some(payload)) => { + let data = AvatarData::try_from(payload).unwrap(); save_avatar(from, id.0, &data.data).unwrap(); } + _ => {} } } } @@ -219,11 +220,11 @@ fn handle_iq_result(pubsub: PubSub, from: &Jid) { } fn save_avatar(from: &Jid, id: String, data: &[u8]) -> io::Result<()> { - let directory = format!("data/{}", from.clone()); - let filename = format!("data/{}/{}", from.clone(), id); + let directory = format!("data/{}", from); + let filename = format!("data/{}/{}", from, id); println!( "Saving avatar from {} to {}.", - from.clone(), filename + from, filename ); create_dir_all(directory)?; let mut file = File::create(filename)?; diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 6de2ce72d9132b2347d28ddbe56d985d768b0deb..0d08dc966ee56a4be4a8f01e45efc17afedad06c 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -57,7 +57,7 @@ fn main() { { match (message.from, message.bodies.get("")) { (Some(ref from), Some(ref body)) if body.0 == "die" => { - println!("Secret die command triggered by {}", from.clone()); + println!("Secret die command triggered by {}", from); wait_for_stream_end = true; tx.start_send(Packet::StreamEnd).unwrap(); } From a572bf4dea0e61012aa013318f0e560819d066fa Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 9 Sep 2019 15:29:50 +0200 Subject: [PATCH 131/135] tokio-xmpp 1.0.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c6b5c26ed4cfbb038a92b2e01bb616ba39bb1f1f..b2cb5183bad08ac2bf40424976235d0c53407fbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-xmpp" -version = "1.0.0" +version = "1.0.1" authors = ["Astro ", "Emmanuel Gil Peyrot ", "pep ", "O01eg "] description = "Asynchronous XMPP for Rust with tokio" license = "MPL-2.0" From 16458dedf112d49401f5752aec069e760bc97727 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 15 Oct 2019 21:18:24 +0200 Subject: [PATCH 132/135] client: replace jid field with bound_jid() resolves gitlab MR #8 --- src/client/mod.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 4f31dad037645c8066cf5a92e3b3e2cf45beb6d3..fab4571cf034e16b6113c1abfeceb8de141d493c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -22,8 +22,6 @@ use self::bind::ClientBind; /// XMPP client connection and state pub struct Client { - /// The client's current Jabber-Id - pub jid: Jid, state: ClientState, } @@ -51,9 +49,8 @@ impl Client { /// Start a new client given that the JID is already parsed. pub fn new_with_jid(jid: Jid, password: &str) -> Self { let password = password.to_owned(); - let connect = Self::make_connect(jid.clone(), password.clone()); + let connect = Self::make_connect(jid, password.clone()); let client = Client { - jid, state: ClientState::Connecting(Box::new(connect)), }; client @@ -125,6 +122,15 @@ impl Client { fn bind(stream: xmpp_stream::XMPPStream) -> ClientBind { ClientBind::new(stream) } + + /// Get the client's bound JID (the one reported by the XMPP + /// server). + pub fn bound_jid(&self) -> Option<&Jid> { + match self.state { + ClientState::Connected(ref stream) => Some(&stream.jid), + _ => None, + } + } } impl Stream for Client { From 9a5c95694b36c2b48426a3a994b1a0b5681dc504 Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 15 Oct 2019 22:02:14 +0200 Subject: [PATCH 133/135] add jid to Event::Online breaks the API --- examples/echo_bot.rs | 5 ++++- src/client/mod.rs | 3 ++- src/component/mod.rs | 2 +- src/event.rs | 14 +++++++++++--- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/echo_bot.rs b/examples/echo_bot.rs index 0d08dc966ee56a4be4a8f01e45efc17afedad06c..a4144bf4f695475fc174bdc735867fd9a19a41c0 100644 --- a/examples/echo_bot.rs +++ b/examples/echo_bot.rs @@ -47,7 +47,10 @@ fn main() { if wait_for_stream_end { /* Do nothing */ } else if event.is_online() { - println!("Online!"); + let jid = event.get_jid() + .map(|jid| format!("{}", jid)) + .unwrap_or("unknown".to_owned()); + println!("Online at {}", jid); let presence = make_presence(); tx.start_send(Packet::Stanza(presence)).unwrap(); diff --git a/src/client/mod.rs b/src/client/mod.rs index fab4571cf034e16b6113c1abfeceb8de141d493c..bcd07c954cac2f53b4571544fcefed19b6ce1c73 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -145,8 +145,9 @@ impl Stream for Client { ClientState::Disconnected => Ok(Async::Ready(None)), ClientState::Connecting(mut connect) => match connect.poll() { Ok(Async::Ready(stream)) => { + let jid = stream.jid.clone(); self.state = ClientState::Connected(stream); - Ok(Async::Ready(Some(Event::Online))) + Ok(Async::Ready(Some(Event::Online(jid)))) } Ok(Async::NotReady) => { self.state = ClientState::Connecting(connect); diff --git a/src/component/mod.rs b/src/component/mod.rs index 8738111780499591c021ffa9a9693d55d8b8c322..d822e8839ae24993521f430191a62ac6fcd876d2 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -90,7 +90,7 @@ impl Stream for Component { ComponentState::Connecting(mut connect) => match connect.poll() { Ok(Async::Ready(stream)) => { self.state = ComponentState::Connected(stream); - Ok(Async::Ready(Some(Event::Online))) + Ok(Async::Ready(Some(Event::Online(self.jid.clone())))) } Ok(Async::NotReady) => { self.state = ComponentState::Connecting(connect); diff --git a/src/event.rs b/src/event.rs index 94dd36c2b7f298642a6e33671d1fbf2f138dd7f2..bd3dc402a2c2ad2f6b9eee29414e034db14406a2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,10 +1,10 @@ -use xmpp_parsers::Element; +use xmpp_parsers::{Element, Jid}; /// High-level event on the Stream implemented by Client and Component #[derive(Debug)] pub enum Event { /// Stream is connected and initialized - Online, + Online(Jid), /// Stream end Disconnected, /// Received stanza/nonza @@ -15,11 +15,19 @@ impl Event { /// `Online` event? pub fn is_online(&self) -> bool { match *self { - Event::Online => true, + Event::Online(_) => true, _ => false, } } + /// Get the server-assigned JID for the `Online` event + pub fn get_jid(&self) -> Option<&Jid> { + match *self { + Event::Online(ref jid) => Some(jid), + _ => None, + } + } + /// `Stanza` event? pub fn is_stanza(&self, name: &str) -> bool { match *self { From 450d43a0eeaeec1f6bf397740a90830f85295a5d Mon Sep 17 00:00:00 2001 From: Astro Date: Tue, 15 Oct 2019 22:37:50 +0200 Subject: [PATCH 134/135] update deps --- Cargo.lock | 341 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 2 files changed, 166 insertions(+), 177 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac0af39db11a1f3ebf49e483cba9db20c546e3d2..de1c70ae4c095007dbad31a9e699e2d1b6c07919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [[package]] name = "arrayvec" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -15,12 +15,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.37" +version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -30,7 +30,7 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -43,7 +43,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -92,7 +92,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -111,7 +111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -119,7 +119,7 @@ name = "chrono" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -130,7 +130,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -139,7 +139,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -161,8 +161,8 @@ name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -182,7 +182,7 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -215,22 +215,22 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -266,7 +266,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -302,8 +302,8 @@ name = "getrandom" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -321,7 +321,7 @@ name = "hostname" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -337,11 +337,10 @@ dependencies = [ [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -362,7 +361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jid" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "minidom 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -389,7 +388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -399,11 +398,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -411,7 +409,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -435,11 +433,11 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -476,9 +474,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -491,8 +489,8 @@ name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -513,12 +511,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -529,8 +527,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,7 +539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nodrop" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -566,7 +564,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -576,15 +574,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.24" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -594,40 +592,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.49" +version = "0.9.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -683,7 +676,7 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -706,7 +699,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -725,6 +718,14 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-xml" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.13" @@ -738,7 +739,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -747,7 +748,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -761,11 +762,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -839,7 +840,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -851,7 +852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -919,7 +920,7 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -937,18 +938,13 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "1.0.0" @@ -961,7 +957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -988,27 +984,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1065,40 +1061,35 @@ name = "socket2" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "string_cache" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string_cache_codegen" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1127,20 +1118,20 @@ name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.10.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1148,9 +1139,9 @@ name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1171,7 +1162,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1190,10 +1181,10 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1234,7 +1225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1249,7 +1240,7 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1258,16 +1249,16 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1281,24 +1272,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1335,7 +1326,7 @@ dependencies = [ "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1345,25 +1336,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-xmpp" -version = "1.0.0" +version = "1.0.1" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-xml 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1381,17 +1372,17 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1403,8 +1394,8 @@ name = "trust-dns-resolver" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1554,7 +1545,7 @@ dependencies = [ "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "minidom 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1562,12 +1553,12 @@ dependencies = [ ] [metadata] -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" +"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" @@ -1576,7 +1567,7 @@ dependencies = [ "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" @@ -1588,8 +1579,8 @@ dependencies = [ "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -1604,16 +1595,16 @@ dependencies = [ "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e3676672e1f13e4963e6af2c1d17114e7f9f96f96477c278fccdd192c618c67" +"checksum jid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "32b4cfc8edfd18c386be7b4e7307e59471aed5e21cd8b80e1aaf070b42de163d" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)" = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" @@ -1628,34 +1619,34 @@ dependencies = [ "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" +"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)" = "ba24190c8f0805d3bd2ce028f439fe5af1d55882bbe6261bed1dbc93b50dd6b1" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" +"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" +"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quick-xml 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd45021132c1cb5540995e93fcc2cf5a874ef84f9639168fb6819caa023d4be" +"checksum quick-xml 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcdba8c8d71275493d966ef052a88726ac8590c15a09968b32158205c672ef" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -1674,18 +1665,17 @@ dependencies = [ "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e457758c85b736bbad56dc099406cd2a9c19554cf81880dba7a51d092929e600" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a" -"checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" @@ -1693,14 +1683,13 @@ dependencies = [ "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" -"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" +"checksum string_cache 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "96ccb3a75a3caf2d7f2eb9ada86ec1fbbd4c74ad2bd8dc00a96a0c2f93509ef0" +"checksum string_cache_codegen 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" @@ -1710,10 +1699,10 @@ dependencies = [ "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" +"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" +"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" "checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" diff --git a/Cargo.toml b/Cargo.toml index b2cb5183bad08ac2bf40424976235d0c53407fbe..7bee03f8fb0cb463381d1b677488da7aedc75860 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,6 @@ trust-dns-resolver = "0.12" trust-dns-proto = "0.8" tokio-io = "0.1" tokio-tls = "0.2" -quick-xml = "0.16" +quick-xml = "0.17" xml5ever = "0.15" xmpp-parsers = "0.15" From 34aa71036627ca32621d01cae162416787e6b6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Fri, 18 Oct 2019 14:16:01 +0200 Subject: [PATCH 135/135] Prepare for merge: Move all tokio-xmpp files into tokio-xmpp/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maxime “pep” Buquet --- .gitignore => tokio-xmpp/.gitignore | 0 .gitlab-ci.yml => tokio-xmpp/.gitlab-ci.yml | 0 Cargo.lock => tokio-xmpp/Cargo.lock | 0 Cargo.toml => tokio-xmpp/Cargo.toml | 0 README.md => tokio-xmpp/README.md | 0 {examples => tokio-xmpp/examples}/contact_addr.rs | 0 {examples => tokio-xmpp/examples}/download_avatars.rs | 0 {examples => tokio-xmpp/examples}/echo_bot.rs | 0 {examples => tokio-xmpp/examples}/echo_component.rs | 0 logo.svg => tokio-xmpp/logo.svg | 0 {src => tokio-xmpp/src}/client/auth.rs | 0 {src => tokio-xmpp/src}/client/bind.rs | 0 {src => tokio-xmpp/src}/client/mod.rs | 0 {src => tokio-xmpp/src}/component/auth.rs | 0 {src => tokio-xmpp/src}/component/mod.rs | 0 {src => tokio-xmpp/src}/error.rs | 0 {src => tokio-xmpp/src}/event.rs | 0 {src => tokio-xmpp/src}/happy_eyeballs.rs | 0 {src => tokio-xmpp/src}/lib.rs | 0 {src => tokio-xmpp/src}/starttls.rs | 0 {src => tokio-xmpp/src}/stream_start.rs | 0 {src => tokio-xmpp/src}/xmpp_codec.rs | 0 {src => tokio-xmpp/src}/xmpp_stream.rs | 0 23 files changed, 0 insertions(+), 0 deletions(-) rename .gitignore => tokio-xmpp/.gitignore (100%) rename .gitlab-ci.yml => tokio-xmpp/.gitlab-ci.yml (100%) rename Cargo.lock => tokio-xmpp/Cargo.lock (100%) rename Cargo.toml => tokio-xmpp/Cargo.toml (100%) rename README.md => tokio-xmpp/README.md (100%) rename {examples => tokio-xmpp/examples}/contact_addr.rs (100%) rename {examples => tokio-xmpp/examples}/download_avatars.rs (100%) rename {examples => tokio-xmpp/examples}/echo_bot.rs (100%) rename {examples => tokio-xmpp/examples}/echo_component.rs (100%) rename logo.svg => tokio-xmpp/logo.svg (100%) rename {src => tokio-xmpp/src}/client/auth.rs (100%) rename {src => tokio-xmpp/src}/client/bind.rs (100%) rename {src => tokio-xmpp/src}/client/mod.rs (100%) rename {src => tokio-xmpp/src}/component/auth.rs (100%) rename {src => tokio-xmpp/src}/component/mod.rs (100%) rename {src => tokio-xmpp/src}/error.rs (100%) rename {src => tokio-xmpp/src}/event.rs (100%) rename {src => tokio-xmpp/src}/happy_eyeballs.rs (100%) rename {src => tokio-xmpp/src}/lib.rs (100%) rename {src => tokio-xmpp/src}/starttls.rs (100%) rename {src => tokio-xmpp/src}/stream_start.rs (100%) rename {src => tokio-xmpp/src}/xmpp_codec.rs (100%) rename {src => tokio-xmpp/src}/xmpp_stream.rs (100%) diff --git a/.gitignore b/tokio-xmpp/.gitignore similarity index 100% rename from .gitignore rename to tokio-xmpp/.gitignore diff --git a/.gitlab-ci.yml b/tokio-xmpp/.gitlab-ci.yml similarity index 100% rename from .gitlab-ci.yml rename to tokio-xmpp/.gitlab-ci.yml diff --git a/Cargo.lock b/tokio-xmpp/Cargo.lock similarity index 100% rename from Cargo.lock rename to tokio-xmpp/Cargo.lock diff --git a/Cargo.toml b/tokio-xmpp/Cargo.toml similarity index 100% rename from Cargo.toml rename to tokio-xmpp/Cargo.toml diff --git a/README.md b/tokio-xmpp/README.md similarity index 100% rename from README.md rename to tokio-xmpp/README.md diff --git a/examples/contact_addr.rs b/tokio-xmpp/examples/contact_addr.rs similarity index 100% rename from examples/contact_addr.rs rename to tokio-xmpp/examples/contact_addr.rs diff --git a/examples/download_avatars.rs b/tokio-xmpp/examples/download_avatars.rs similarity index 100% rename from examples/download_avatars.rs rename to tokio-xmpp/examples/download_avatars.rs diff --git a/examples/echo_bot.rs b/tokio-xmpp/examples/echo_bot.rs similarity index 100% rename from examples/echo_bot.rs rename to tokio-xmpp/examples/echo_bot.rs diff --git a/examples/echo_component.rs b/tokio-xmpp/examples/echo_component.rs similarity index 100% rename from examples/echo_component.rs rename to tokio-xmpp/examples/echo_component.rs diff --git a/logo.svg b/tokio-xmpp/logo.svg similarity index 100% rename from logo.svg rename to tokio-xmpp/logo.svg diff --git a/src/client/auth.rs b/tokio-xmpp/src/client/auth.rs similarity index 100% rename from src/client/auth.rs rename to tokio-xmpp/src/client/auth.rs diff --git a/src/client/bind.rs b/tokio-xmpp/src/client/bind.rs similarity index 100% rename from src/client/bind.rs rename to tokio-xmpp/src/client/bind.rs diff --git a/src/client/mod.rs b/tokio-xmpp/src/client/mod.rs similarity index 100% rename from src/client/mod.rs rename to tokio-xmpp/src/client/mod.rs diff --git a/src/component/auth.rs b/tokio-xmpp/src/component/auth.rs similarity index 100% rename from src/component/auth.rs rename to tokio-xmpp/src/component/auth.rs diff --git a/src/component/mod.rs b/tokio-xmpp/src/component/mod.rs similarity index 100% rename from src/component/mod.rs rename to tokio-xmpp/src/component/mod.rs diff --git a/src/error.rs b/tokio-xmpp/src/error.rs similarity index 100% rename from src/error.rs rename to tokio-xmpp/src/error.rs diff --git a/src/event.rs b/tokio-xmpp/src/event.rs similarity index 100% rename from src/event.rs rename to tokio-xmpp/src/event.rs diff --git a/src/happy_eyeballs.rs b/tokio-xmpp/src/happy_eyeballs.rs similarity index 100% rename from src/happy_eyeballs.rs rename to tokio-xmpp/src/happy_eyeballs.rs diff --git a/src/lib.rs b/tokio-xmpp/src/lib.rs similarity index 100% rename from src/lib.rs rename to tokio-xmpp/src/lib.rs diff --git a/src/starttls.rs b/tokio-xmpp/src/starttls.rs similarity index 100% rename from src/starttls.rs rename to tokio-xmpp/src/starttls.rs diff --git a/src/stream_start.rs b/tokio-xmpp/src/stream_start.rs similarity index 100% rename from src/stream_start.rs rename to tokio-xmpp/src/stream_start.rs diff --git a/src/xmpp_codec.rs b/tokio-xmpp/src/xmpp_codec.rs similarity index 100% rename from src/xmpp_codec.rs rename to tokio-xmpp/src/xmpp_codec.rs diff --git a/src/xmpp_stream.rs b/tokio-xmpp/src/xmpp_stream.rs similarity index 100% rename from src/xmpp_stream.rs rename to tokio-xmpp/src/xmpp_stream.rs