tokio-xmpp: use xmpp_parsers::ns everywhere

This commit is contained in:
Astro 2020-05-30 01:19:06 +02:00
parent 1a06a09774
commit e501addb96
9 changed files with 23 additions and 41 deletions

View file

@ -9,7 +9,7 @@ use tokio::net::TcpStream;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tokio::task::LocalSet; use tokio::task::LocalSet;
use tokio_tls::TlsStream; use tokio_tls::TlsStream;
use xmpp_parsers::{Element, Jid, JidParseError}; use xmpp_parsers::{ns, Element, Jid, JidParseError};
use super::auth::auth; use super::auth::auth;
use super::bind::bind; use super::bind::bind;
@ -35,7 +35,6 @@ pub struct Client {
} }
type XMPPStream = xmpp_stream::XMPPStream<TlsStream<TcpStream>>; type XMPPStream = xmpp_stream::XMPPStream<TlsStream<TcpStream>>;
const NS_JABBER_CLIENT: &str = "jabber:client";
enum ClientState { enum ClientState {
Invalid, Invalid,
@ -85,14 +84,14 @@ impl Client {
// Unencryped XMPPStream // Unencryped XMPPStream
let xmpp_stream = let xmpp_stream =
xmpp_stream::XMPPStream::start(tcp_stream, jid.clone(), NS_JABBER_CLIENT.to_owned()) xmpp_stream::XMPPStream::start(tcp_stream, jid.clone(), ns::JABBER_CLIENT.to_owned())
.await?; .await?;
let xmpp_stream = if xmpp_stream.stream_features.can_starttls() { let xmpp_stream = if xmpp_stream.stream_features.can_starttls() {
// TlsStream // TlsStream
let tls_stream = starttls(xmpp_stream).await?; let tls_stream = starttls(xmpp_stream).await?;
// Encrypted XMPPStream // Encrypted XMPPStream
xmpp_stream::XMPPStream::start(tls_stream, jid.clone(), NS_JABBER_CLIENT.to_owned()) xmpp_stream::XMPPStream::start(tls_stream, jid.clone(), ns::JABBER_CLIENT.to_owned())
.await? .await?
} else { } else {
return Err(Error::Protocol(ProtocolError::NoTls)); return Err(Error::Protocol(ProtocolError::NoTls));
@ -106,7 +105,7 @@ impl Client {
let stream = auth(xmpp_stream, creds).await?; let stream = auth(xmpp_stream, creds).await?;
// Authenticated XMPPStream // Authenticated XMPPStream
let xmpp_stream = let xmpp_stream =
xmpp_stream::XMPPStream::start(stream, jid, NS_JABBER_CLIENT.to_owned()).await?; xmpp_stream::XMPPStream::start(stream, jid, ns::JABBER_CLIENT.to_owned()).await?;
// XMPPStream bound to user session // XMPPStream bound to user session
let xmpp_stream = bind(xmpp_stream).await?; let xmpp_stream = bind(xmpp_stream).await?;

View file

@ -3,6 +3,3 @@ mod bind;
pub mod async_client; pub mod async_client;
pub mod simple_client; pub mod simple_client;
pub const NS_XMPP_SASL: &str = "urn:ietf:params:xml:ns:xmpp-sasl";
pub const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind";

View file

@ -6,7 +6,7 @@ use std::str::FromStr;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio::{net::TcpStream, stream::StreamExt}; use tokio::{net::TcpStream, stream::StreamExt};
use tokio_tls::TlsStream; use tokio_tls::TlsStream;
use xmpp_parsers::{Element, Jid}; use xmpp_parsers::{ns, Element, Jid};
use super::auth::auth; use super::auth::auth;
use super::bind::bind; use super::bind::bind;
@ -25,7 +25,6 @@ pub struct Client {
} }
type XMPPStream = xmpp_stream::XMPPStream<TlsStream<TcpStream>>; type XMPPStream = xmpp_stream::XMPPStream<TlsStream<TcpStream>>;
const NS_JABBER_CLIENT: &str = "jabber:client";
impl Client { impl Client {
/// Start a new XMPP client and wait for a usable session /// Start a new XMPP client and wait for a usable session
@ -51,14 +50,14 @@ impl Client {
// Unencryped XMPPStream // Unencryped XMPPStream
let xmpp_stream = let xmpp_stream =
xmpp_stream::XMPPStream::start(tcp_stream, jid.clone(), NS_JABBER_CLIENT.to_owned()) xmpp_stream::XMPPStream::start(tcp_stream, jid.clone(), ns::JABBER_CLIENT.to_owned())
.await?; .await?;
let xmpp_stream = if xmpp_stream.stream_features.can_starttls() { let xmpp_stream = if xmpp_stream.stream_features.can_starttls() {
// TlsStream // TlsStream
let tls_stream = starttls(xmpp_stream).await?; let tls_stream = starttls(xmpp_stream).await?;
// Encrypted XMPPStream // Encrypted XMPPStream
xmpp_stream::XMPPStream::start(tls_stream, jid.clone(), NS_JABBER_CLIENT.to_owned()) xmpp_stream::XMPPStream::start(tls_stream, jid.clone(), ns::JABBER_CLIENT.to_owned())
.await? .await?
} else { } else {
return Err(Error::Protocol(ProtocolError::NoTls)); return Err(Error::Protocol(ProtocolError::NoTls));
@ -72,7 +71,7 @@ impl Client {
let stream = auth(xmpp_stream, creds).await?; let stream = auth(xmpp_stream, creds).await?;
// Authenticated XMPPStream // Authenticated XMPPStream
let xmpp_stream = let xmpp_stream =
xmpp_stream::XMPPStream::start(stream, jid, NS_JABBER_CLIENT.to_owned()).await?; xmpp_stream::XMPPStream::start(stream, jid, ns::JABBER_CLIENT.to_owned()).await?;
// XMPPStream bound to user session // XMPPStream bound to user session
let xmpp_stream = bind(xmpp_stream).await?; let xmpp_stream = bind(xmpp_stream).await?;

View file

@ -1,14 +1,12 @@
use futures::stream::StreamExt; use futures::stream::StreamExt;
use std::marker::Unpin; use std::marker::Unpin;
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use xmpp_parsers::component::Handshake; use xmpp_parsers::{component::Handshake, ns};
use crate::xmpp_codec::Packet; use crate::xmpp_codec::Packet;
use crate::xmpp_stream::XMPPStream; use crate::xmpp_stream::XMPPStream;
use crate::{AuthError, Error}; use crate::{AuthError, Error};
const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept";
pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>( pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>(
stream: &mut XMPPStream<S>, stream: &mut XMPPStream<S>,
password: String, password: String,
@ -19,7 +17,7 @@ pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>(
loop { loop {
match stream.next().await { match stream.next().await {
Some(Ok(Packet::Stanza(ref stanza))) Some(Ok(Packet::Stanza(ref stanza)))
if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) => if stanza.is("handshake", ns::COMPONENT_ACCEPT) =>
{ {
return Ok(()); return Ok(());
} }

View file

@ -6,7 +6,7 @@ use std::pin::Pin;
use std::str::FromStr; use std::str::FromStr;
use std::task::Context; use std::task::Context;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use xmpp_parsers::{Element, Jid}; use xmpp_parsers::{ns, Element, Jid};
use super::happy_eyeballs::connect; use super::happy_eyeballs::connect;
use super::xmpp_codec::Packet; use super::xmpp_codec::Packet;
@ -26,7 +26,6 @@ pub struct Component {
} }
type XMPPStream = xmpp_stream::XMPPStream<TcpStream>; type XMPPStream = xmpp_stream::XMPPStream<TcpStream>;
const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept";
impl Component { impl Component {
/// Start a new XMPP component /// Start a new XMPP component
@ -46,7 +45,7 @@ impl Component {
let password = password; let password = password;
let tcp_stream = connect(server, None, port).await?; let tcp_stream = connect(server, None, port).await?;
let mut xmpp_stream = let mut xmpp_stream =
xmpp_stream::XMPPStream::start(tcp_stream, jid, NS_JABBER_COMPONENT_ACCEPT.to_owned()) xmpp_stream::XMPPStream::start(tcp_stream, jid, ns::COMPONENT_ACCEPT.to_owned())
.await?; .await?;
auth::auth(&mut xmpp_stream, password).await?; auth::auth(&mut xmpp_stream, password).await?;
Ok(xmpp_stream) Ok(xmpp_stream)

View file

@ -2,21 +2,18 @@ use futures::{sink::SinkExt, stream::StreamExt};
use native_tls::TlsConnector as NativeTlsConnector; use native_tls::TlsConnector as NativeTlsConnector;
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use tokio_tls::{TlsConnector, TlsStream}; use tokio_tls::{TlsConnector, TlsStream};
use xmpp_parsers::Element; use xmpp_parsers::{ns, Element};
use crate::xmpp_codec::Packet; use crate::xmpp_codec::Packet;
use crate::xmpp_stream::XMPPStream; use crate::xmpp_stream::XMPPStream;
use crate::{Error, ProtocolError}; use crate::{Error, ProtocolError};
/// XMPP TLS XML namespace
pub const NS_XMPP_TLS: &str = "urn:ietf:params:xml:ns:xmpp-tls";
/// Performs `<starttls/>` on an XMPPStream and returns a binary /// Performs `<starttls/>` on an XMPPStream and returns a binary
/// TlsStream. /// TlsStream.
pub async fn starttls<S: AsyncRead + AsyncWrite + Unpin>( pub async fn starttls<S: AsyncRead + AsyncWrite + Unpin>(
mut xmpp_stream: XMPPStream<S>, mut xmpp_stream: XMPPStream<S>,
) -> Result<TlsStream<S>, Error> { ) -> Result<TlsStream<S>, Error> {
let nonza = Element::builder("starttls", NS_XMPP_TLS).build(); let nonza = Element::builder("starttls", ns::TLS).build();
let packet = Packet::Stanza(nonza); let packet = Packet::Stanza(nonza);
xmpp_stream.send(packet).await?; xmpp_stream.send(packet).await?;

View file

@ -1,9 +1,7 @@
//! Contains wrapper for `<stream:features/>` //! Contains wrapper for `<stream:features/>`
use crate::client::{NS_XMPP_BIND, NS_XMPP_SASL};
use crate::error::AuthError; use crate::error::AuthError;
use crate::starttls::NS_XMPP_TLS; use xmpp_parsers::{ns, Element};
use xmpp_parsers::Element;
/// Wraps `<stream:features/>`, usually the very first nonza of an /// Wraps `<stream:features/>`, usually the very first nonza of an
/// XMPPStream. /// XMPPStream.
@ -20,22 +18,22 @@ impl StreamFeatures {
/// Can initiate TLS session with this server? /// Can initiate TLS session with this server?
pub fn can_starttls(&self) -> bool { pub fn can_starttls(&self) -> bool {
self.0.get_child("starttls", NS_XMPP_TLS).is_some() self.0.get_child("starttls", ns::TLS).is_some()
} }
/// Iterate over SASL mechanisms /// Iterate over SASL mechanisms
pub fn sasl_mechanisms<'a>(&'a self) -> Result<impl Iterator<Item = String> + 'a, AuthError> { pub fn sasl_mechanisms<'a>(&'a self) -> Result<impl Iterator<Item = String> + 'a, AuthError> {
Ok(self Ok(self
.0 .0
.get_child("mechanisms", NS_XMPP_SASL) .get_child("mechanisms", ns::SASL)
.ok_or(AuthError::NoMechanism)? .ok_or(AuthError::NoMechanism)?
.children() .children()
.filter(|child| child.is("mechanism", NS_XMPP_SASL)) .filter(|child| child.is("mechanism", ns::SASL))
.map(|mech_el| mech_el.text())) .map(|mech_el| mech_el.text()))
} }
/// Does server support user resource binding? /// Does server support user resource binding?
pub fn can_bind(&self) -> bool { pub fn can_bind(&self) -> bool {
self.0.get_child("bind", NS_XMPP_BIND).is_some() self.0.get_child("bind", ns::BIND).is_some()
} }
} }

View file

@ -2,14 +2,12 @@ use futures::{sink::SinkExt, stream::StreamExt};
use std::marker::Unpin; use std::marker::Unpin;
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::codec::Framed; use tokio_util::codec::Framed;
use xmpp_parsers::{Element, Jid}; use xmpp_parsers::{ns, Element, Jid};
use crate::xmpp_codec::{Packet, XMPPCodec}; use crate::xmpp_codec::{Packet, XMPPCodec};
use crate::xmpp_stream::XMPPStream; use crate::xmpp_stream::XMPPStream;
use crate::{Error, ProtocolError}; use crate::{Error, ProtocolError};
const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams";
/// Sends a `<stream:stream>`, then wait for one from the server, and /// Sends a `<stream:stream>`, then wait for one from the server, and
/// construct an XMPPStream. /// construct an XMPPStream.
pub async fn start<S: AsyncRead + AsyncWrite + Unpin>( pub async fn start<S: AsyncRead + AsyncWrite + Unpin>(
@ -21,7 +19,7 @@ pub async fn start<S: AsyncRead + AsyncWrite + Unpin>(
("to".to_owned(), jid.clone().domain()), ("to".to_owned(), jid.clone().domain()),
("version".to_owned(), "1.0".to_owned()), ("version".to_owned(), "1.0".to_owned()),
("xmlns".to_owned(), ns.clone()), ("xmlns".to_owned(), ns.clone()),
("xmlns:stream".to_owned(), NS_XMPP_STREAM.to_owned()), ("xmlns:stream".to_owned(), ns::STREAM.to_owned()),
] ]
.iter() .iter()
.cloned() .cloned()
@ -53,7 +51,7 @@ pub async fn start<S: AsyncRead + AsyncWrite + Unpin>(
let stream_features; let stream_features;
loop { loop {
match stream.next().await { match stream.next().await {
Some(Ok(Packet::Stanza(stanza))) if stanza.is("features", NS_XMPP_STREAM) => { Some(Ok(Packet::Stanza(stanza))) if stanza.is("features", ns::STREAM) => {
stream_features = stanza; stream_features = stanza;
break; break;
} }
@ -70,7 +68,7 @@ pub async fn start<S: AsyncRead + AsyncWrite + Unpin>(
stream, stream,
ns, ns,
stream_id.clone(), stream_id.clone(),
Element::builder(stream_id, NS_XMPP_STREAM).build(), Element::builder(stream_id, ns::STREAM).build(),
) )
}; };
Ok(stream) Ok(stream)

View file

@ -15,9 +15,6 @@ use crate::stream_start;
use crate::xmpp_codec::{Packet, XMPPCodec}; use crate::xmpp_codec::{Packet, XMPPCodec};
use crate::Error; use crate::Error;
/// <stream:stream> namespace
pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams";
/// Wraps a binary stream (tokio's `AsyncRead + AsyncWrite`) to decode /// Wraps a binary stream (tokio's `AsyncRead + AsyncWrite`) to decode
/// and encode XMPP packets. /// and encode XMPP packets.
/// ///