xmpp-rs/tokio-xmpp/src/client/bind.rs

56 lines
2 KiB
Rust
Raw Normal View History

2020-03-05 00:25:24 +00:00
use futures::stream::StreamExt;
2019-09-08 19:28:44 +00:00
use std::convert::TryFrom;
2020-03-05 00:25:24 +00:00
use std::marker::Unpin;
use tokio::io::{AsyncRead, AsyncWrite};
2019-09-08 19:28:44 +00:00
use xmpp_parsers::bind::{BindQuery, BindResponse};
2018-12-18 18:04:31 +00:00
use xmpp_parsers::iq::{Iq, IqType};
use xmpp_parsers::Jid;
2017-06-19 00:16:47 +00:00
2018-12-18 17:29:31 +00:00
use crate::xmpp_codec::Packet;
use crate::xmpp_stream::XMPPStream;
use crate::{Error, ProtocolError};
2017-06-19 00:16:47 +00:00
const NS_XMPP_BIND: &str = "urn:ietf:params:xml:ns:xmpp-bind";
const BIND_REQ_ID: &str = "resource-bind";
2020-03-05 00:25:24 +00:00
pub async fn bind<S: AsyncRead + AsyncWrite + Unpin>(
mut stream: XMPPStream<S>,
) -> Result<XMPPStream<S>, Error> {
match stream.stream_features.get_child("bind", NS_XMPP_BIND) {
None => {
2018-12-18 18:04:31 +00:00
// No resource binding available,
// return the (probably // usable) stream immediately
2020-03-05 00:25:24 +00:00
return Ok(stream);
2017-06-19 00:16:47 +00:00
}
2020-03-05 00:25:24 +00:00
Some(_) => {
let resource = if let Jid::Full(jid) = stream.jid.clone() {
Some(jid.resource)
} else {
None
};
let iq = Iq::from_set(BIND_REQ_ID, BindQuery::new(resource));
stream.send_stanza(iq).await?;
2017-06-19 00:16:47 +00:00
2020-03-05 00:25:24 +00:00
loop {
match stream.next().await {
Some(Ok(Packet::Stanza(stanza))) => match Iq::try_from(stanza) {
Ok(iq) if iq.id == BIND_REQ_ID => match iq.payload {
IqType::Result(payload) => {
payload
.and_then(|payload| BindResponse::try_from(payload).ok())
.map(|bind| stream.jid = bind.into());
return Ok(stream);
2018-12-18 18:04:31 +00:00
}
2020-03-05 00:25:24 +00:00
_ => return Err(ProtocolError::InvalidBindResponse.into()),
},
_ => {}
},
Some(Ok(_)) => {}
Some(Err(e)) => return Err(e),
None => return Err(Error::Disconnected),
2017-06-19 00:16:47 +00:00
}
2020-03-05 00:25:24 +00:00
}
2017-06-19 00:16:47 +00:00
}
}
}