aboutsummaryrefslogtreecommitdiffstats
path: root/src/jabber.rs
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2024-12-02 21:50:15 +0000
committerLibravatar cel 🌸 <cel@bunny.garden>2024-12-02 21:50:15 +0000
commitbe198ca15bbaf633c1535db5bae7091520546aed (patch)
treee7c33435851c4421bfb950818b285a00e63d93a0 /src/jabber.rs
parent859a19820d69eca5fca87fc01acad72a6355f97e (diff)
downloadluz-be198ca15bbaf633c1535db5bae7091520546aed.tar.gz
luz-be198ca15bbaf633c1535db5bae7091520546aed.tar.bz2
luz-be198ca15bbaf633c1535db5bae7091520546aed.zip
implement bind
Diffstat (limited to 'src/jabber.rs')
-rw-r--r--src/jabber.rs111
1 files changed, 110 insertions, 1 deletions
diff --git a/src/jabber.rs b/src/jabber.rs
index 599879d..96cd73a 100644
--- a/src/jabber.rs
+++ b/src/jabber.rs
@@ -13,6 +13,9 @@ use trust_dns_resolver::proto::rr::domain::IntoLabel;
use crate::connection::{Tls, Unencrypted};
use crate::error::Error;
+use crate::stanza::bind::{Bind, BindType, FullJidType, ResourceType};
+use crate::stanza::client::error::Error as ClientError;
+use crate::stanza::client::iq::{Iq, IqType, Query};
use crate::stanza::sasl::{Auth, Challenge, Mechanisms, Response, ServerResponse};
use crate::stanza::starttls::{Proceed, StartTls};
use crate::stanza::stream::{Feature, Features, Stream};
@@ -147,7 +150,96 @@ where
}
pub async fn bind(&mut self) -> Result<()> {
- todo!()
+ let iq_id = nanoid::nanoid!();
+ if let Some(resource) = self.jid.clone().unwrap().resourcepart {
+ let iq = Iq {
+ from: None,
+ id: iq_id.clone(),
+ to: None,
+ r#type: IqType::Set,
+ lang: None,
+ query: Some(Query::Bind(Bind {
+ r#type: Some(BindType::Resource(ResourceType(resource))),
+ })),
+ errors: Vec::new(),
+ };
+ self.writer.write_full(&iq).await?;
+ let result: Iq = self.reader.read().await?;
+ match result {
+ Iq {
+ from: _,
+ id,
+ to: _,
+ r#type: IqType::Result,
+ lang: _,
+ query:
+ Some(Query::Bind(Bind {
+ r#type: Some(BindType::Jid(FullJidType(jid))),
+ })),
+ errors: _,
+ } if id == iq_id => {
+ self.jid = Some(jid);
+ return Ok(());
+ }
+ Iq {
+ from: _,
+ id,
+ to: _,
+ r#type: IqType::Error,
+ lang: _,
+ query: None,
+ errors,
+ } if id == iq_id => {
+ return Err(Error::ClientError(
+ errors.first().ok_or(Error::MissingError)?.clone(),
+ ))
+ }
+ _ => return Err(Error::UnexpectedElement(result.into_element())),
+ }
+ } else {
+ let iq = Iq {
+ from: None,
+ id: iq_id.clone(),
+ to: None,
+ r#type: IqType::Set,
+ lang: None,
+ query: Some(Query::Bind(Bind { r#type: None })),
+ errors: Vec::new(),
+ };
+ self.writer.write_full(&iq).await?;
+ let result: Iq = self.reader.read().await?;
+ match result {
+ Iq {
+ from: _,
+ id,
+ to: _,
+ r#type: IqType::Result,
+ lang: _,
+ query:
+ Some(Query::Bind(Bind {
+ r#type: Some(BindType::Jid(FullJidType(jid))),
+ })),
+ errors: _,
+ } if id == iq_id => {
+ self.jid = Some(jid);
+ return Ok(());
+ }
+ Iq {
+ from: _,
+ id,
+ to: _,
+ r#type: IqType::Error,
+ lang: _,
+ query: None,
+ errors,
+ } if id == iq_id => {
+ return Err(Error::ClientError(
+ errors.first().ok_or(Error::MissingError)?.clone(),
+ ))
+ }
+ _ => return Err(Error::UnexpectedElement(result.into_element())),
+ }
+ }
}
#[instrument]
@@ -324,9 +416,12 @@ impl std::fmt::Debug for Jabber<Unencrypted> {
#[cfg(test)]
mod tests {
+ use std::time::Duration;
+
use super::*;
use crate::connection::Connection;
use test_log::test;
+ use tokio::time::sleep;
#[test(tokio::test)]
async fn start_stream() {
@@ -373,4 +468,18 @@ mod tests {
Feature::Unknown => todo!(),
}
}
+
+ #[tokio::test]
+ async fn negotiate() {
+ let jabber = Connection::connect_user("test@blos.sm", "slayed".to_string())
+ .await
+ .unwrap()
+ .ensure_tls()
+ .await
+ .unwrap()
+ .negotiate()
+ .await
+ .unwrap();
+ sleep(Duration::from_secs(5)).await
+ }
}