aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2024-12-03 23:57:04 +0000
committerLibravatar cel 🌸 <cel@bunny.garden>2024-12-03 23:57:04 +0000
commite0373c0520e7fae792bc907e9c500ab846d34e31 (patch)
treefcec4d201c85ac951500f6678824024be87a1b5e
parent7c2577d196c059ab6e2d5b0efe5e036bdad75be7 (diff)
downloadluz-e0373c0520e7fae792bc907e9c500ab846d34e31.tar.gz
luz-e0373c0520e7fae792bc907e9c500ab846d34e31.tar.bz2
luz-e0373c0520e7fae792bc907e9c500ab846d34e31.zip
WIP: connecting fsm
-rw-r--r--Cargo.toml1
-rw-r--r--src/client.rs180
-rw-r--r--src/connection.rs91
-rw-r--r--src/error.rs17
-rw-r--r--src/jabber.rs377
-rw-r--r--src/lib.rs18
6 files changed, 401 insertions, 283 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e9c12b5..687b980 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ tracing = "0.1.40"
trust-dns-resolver = "0.22.0"
try_map = "0.3.1"
peanuts = { version = "0.1.0", path = "../peanuts" }
+futures = "0.3.31"
[dev-dependencies]
test-log = { version = "0.2", features = ["trace"] }
diff --git a/src/client.rs b/src/client.rs
new file mode 100644
index 0000000..2908346
--- /dev/null
+++ b/src/client.rs
@@ -0,0 +1,180 @@
+use std::sync::Arc;
+
+use futures::{Sink, Stream};
+use rsasl::config::SASLConfig;
+
+use crate::{
+ connection::{Tls, Unencrypted},
+ stanza::{
+ client::Stanza,
+ sasl::Mechanisms,
+ stream::{Feature, Features},
+ },
+ Connection, Error, JabberStream, Result, JID,
+};
+
+// feed it client stanzas, receive client stanzas
+pub struct JabberClient {
+ connection: JabberState,
+ jid: JID,
+ password: Arc<SASLConfig>,
+ server: String,
+}
+
+pub enum JabberState {
+ Disconnected,
+ InsecureConnectionEstablised(Unencrypted),
+ InsecureStreamStarted(JabberStream<Unencrypted>),
+ InsecureGotFeatures((Features, JabberStream<Unencrypted>)),
+ StartTls(JabberStream<Unencrypted>),
+ ConnectionEstablished(Tls),
+ StreamStarted(JabberStream<Tls>),
+ GotFeatures((Features, JabberStream<Tls>)),
+ Sasl(Mechanisms, JabberStream<Tls>),
+ Bind(JabberStream<Tls>),
+ // when it's bound, can stream stanzas and sink stanzas
+ Bound(JabberStream<Tls>),
+}
+
+impl JabberState {
+ pub async fn advance_state(
+ self,
+ jid: &mut JID,
+ auth: Arc<SASLConfig>,
+ server: &mut String,
+ ) -> Result<JabberState> {
+ match self {
+ JabberState::Disconnected => match Connection::connect(server).await? {
+ Connection::Encrypted(tls_stream) => {
+ Ok(JabberState::ConnectionEstablished(tls_stream))
+ }
+ Connection::Unencrypted(tcp_stream) => {
+ Ok(JabberState::InsecureConnectionEstablised(tcp_stream))
+ }
+ },
+ JabberState::InsecureConnectionEstablised(tcp_stream) => Ok({
+ JabberState::InsecureStreamStarted(
+ JabberStream::start_stream(tcp_stream, server).await?,
+ )
+ }),
+ JabberState::InsecureStreamStarted(jabber_stream) => Ok(
+ JabberState::InsecureGotFeatures(jabber_stream.get_features().await?),
+ ),
+ JabberState::InsecureGotFeatures((features, jabber_stream)) => {
+ match features.negotiate()? {
+ Feature::StartTls(_start_tls) => Ok(JabberState::StartTls(jabber_stream)),
+ // TODO: better error
+ _ => return Err(Error::TlsRequired),
+ }
+ }
+ JabberState::StartTls(jabber_stream) => Ok(JabberState::ConnectionEstablished(
+ jabber_stream.starttls(server).await?,
+ )),
+ JabberState::ConnectionEstablished(tls_stream) => Ok(JabberState::StreamStarted(
+ JabberStream::start_stream(tls_stream, server).await?,
+ )),
+ JabberState::StreamStarted(jabber_stream) => Ok(JabberState::GotFeatures(
+ jabber_stream.get_features().await?,
+ )),
+ JabberState::GotFeatures((features, jabber_stream)) => match features.negotiate()? {
+ Feature::StartTls(_start_tls) => return Err(Error::AlreadyTls),
+ Feature::Sasl(mechanisms) => {
+ return Ok(JabberState::Sasl(mechanisms, jabber_stream))
+ }
+ Feature::Bind => return Ok(JabberState::Bind(jabber_stream)),
+ Feature::Unknown => return Err(Error::Unsupported),
+ },
+ JabberState::Sasl(mechanisms, jabber_stream) => {
+ return Ok(JabberState::ConnectionEstablished(
+ jabber_stream.sasl(mechanisms, auth).await?,
+ ))
+ }
+ JabberState::Bind(jabber_stream) => {
+ Ok(JabberState::Bound(jabber_stream.bind(jid).await?))
+ }
+ JabberState::Bound(jabber_stream) => Ok(JabberState::Bound(jabber_stream)),
+ }
+ }
+}
+
+impl Features {
+ pub fn negotiate(self) -> Result<Feature> {
+ if let Some(Feature::StartTls(s)) = self
+ .features
+ .iter()
+ .find(|feature| matches!(feature, Feature::StartTls(_s)))
+ {
+ // TODO: avoid clone
+ return Ok(Feature::StartTls(s.clone()));
+ } else if let Some(Feature::Sasl(mechanisms)) = self
+ .features
+ .iter()
+ .find(|feature| matches!(feature, Feature::Sasl(_)))
+ {
+ // TODO: avoid clone
+ return Ok(Feature::Sasl(mechanisms.clone()));
+ } else if let Some(Feature::Bind) = self
+ .features
+ .into_iter()
+ .find(|feature| matches!(feature, Feature::Bind))
+ {
+ Ok(Feature::Bind)
+ } else {
+ // TODO: better error
+ return Err(Error::Negotiation);
+ }
+ }
+}
+
+pub enum InsecureJabberConnection {
+ Disconnected,
+ ConnectionEstablished(Connection),
+ PreStarttls(JabberStream<Unencrypted>),
+ PreAuthenticated(JabberStream<Tls>),
+ Authenticated(Tls),
+ PreBound(JabberStream<Tls>),
+ Bound(JabberStream<Tls>),
+}
+
+impl Stream for JabberClient {
+ type Item = Stanza;
+
+ fn poll_next(
+ self: std::pin::Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Option<Self::Item>> {
+ todo!()
+ }
+}
+
+impl Sink<Stanza> for JabberClient {
+ type Error = Error;
+
+ fn poll_ready(
+ self: std::pin::Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<std::result::Result<(), Self::Error>> {
+ todo!()
+ }
+
+ fn start_send(
+ self: std::pin::Pin<&mut Self>,
+ item: Stanza,
+ ) -> std::result::Result<(), Self::Error> {
+ todo!()
+ }
+
+ fn poll_flush(
+ self: std::pin::Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<std::result::Result<(), Self::Error>> {
+ todo!()
+ }
+
+ fn poll_close(
+ self: std::pin::Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<std::result::Result<(), Self::Error>> {
+ todo!()
+ }
+}
diff --git a/src/connection.rs b/src/connection.rs
index 9e485d3..bc5a282 100644
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -10,7 +10,6 @@ use tokio_native_tls::native_tls::TlsConnector;
use tokio_native_tls::TlsStream;
use tracing::{debug, info, instrument, trace};
-use crate::Jabber;
use crate::Result;
use crate::{Error, JID};
@@ -19,69 +18,51 @@ pub type Unencrypted = TcpStream;
#[derive(Debug)]
pub enum Connection {
- Encrypted(Jabber<Tls>),
- Unencrypted(Jabber<Unencrypted>),
+ Encrypted(Tls),
+ Unencrypted(Unencrypted),
}
impl Connection {
- #[instrument]
+ // #[instrument]
/// stream not started
- pub async fn ensure_tls(self) -> Result<Jabber<Tls>> {
- match self {
- Connection::Encrypted(j) => Ok(j),
- Connection::Unencrypted(mut j) => {
- j.start_stream().await?;
- info!("upgrading connection to tls");
- j.get_features().await?;
- let j = j.starttls().await?;
- Ok(j)
- }
- }
- }
-
- pub async fn connect_user(jid: impl AsRef<str>, password: String) -> Result<Self> {
+ // pub async fn ensure_tls(self) -> Result<Jabber<Tls>> {
+ // match self {
+ // Connection::Encrypted(j) => Ok(j),
+ // Connection::Unencrypted(mut j) => {
+ // j.start_stream().await?;
+ // info!("upgrading connection to tls");
+ // j.get_features().await?;
+ // let j = j.starttls().await?;
+ // Ok(j)
+ // }
+ // }
+ // }
+
+ pub async fn connect_user(jid: impl AsRef<str>) -> Result<Self> {
let jid: JID = JID::from_str(jid.as_ref())?;
let server = jid.domainpart.clone();
- let auth = SASLConfig::with_credentials(None, jid.localpart.clone().unwrap(), password)?;
- println!("auth: {:?}", auth);
- Self::connect(&server, Some(jid), Some(auth)).await
+ Self::connect(&server).await
}
#[instrument]
- pub async fn connect(
- server: &str,
- jid: Option<JID>,
- auth: Option<Arc<SASLConfig>>,
- ) -> Result<Self> {
- info!("connecting to {}", server);
- let sockets = Self::get_sockets(&server).await;
+ pub async fn connect(server: impl AsRef<str> + std::fmt::Debug) -> Result<Self> {
+ info!("connecting to {}", server.as_ref());
+ let sockets = Self::get_sockets(server.as_ref()).await;
debug!("discovered sockets: {:?}", sockets);
for (socket_addr, tls) in sockets {
match tls {
true => {
- if let Ok(connection) = Self::connect_tls(socket_addr, &server).await {
+ if let Ok(connection) = Self::connect_tls(socket_addr, server.as_ref()).await {
info!("connected via encrypted stream to {}", socket_addr);
- let (readhalf, writehalf) = tokio::io::split(connection);
- return Ok(Self::Encrypted(Jabber::new(
- readhalf,
- writehalf,
- jid,
- auth,
- server.to_owned(),
- )));
+ // let (readhalf, writehalf) = tokio::io::split(connection);
+ return Ok(Self::Encrypted(connection));
}
}
false => {
if let Ok(connection) = Self::connect_unencrypted(socket_addr).await {
info!("connected via unencrypted stream to {}", socket_addr);
- let (readhalf, writehalf) = tokio::io::split(connection);
- return Ok(Self::Unencrypted(Jabber::new(
- readhalf,
- writehalf,
- jid,
- auth,
- server.to_owned(),
- )));
+ // let (readhalf, writehalf) = tokio::io::split(connection);
+ return Ok(Self::Unencrypted(connection));
}
}
}
@@ -188,16 +169,16 @@ mod tests {
#[test(tokio::test)]
async fn connect() {
- Connection::connect("blos.sm", None, None).await.unwrap();
+ Connection::connect("blos.sm").await.unwrap();
}
- #[test(tokio::test)]
- async fn test_tls() {
- Connection::connect("blos.sm", None, None)
- .await
- .unwrap()
- .ensure_tls()
- .await
- .unwrap();
- }
+ // #[test(tokio::test)]
+ // async fn test_tls() {
+ // Connection::connect("blos.sm", None, None)
+ // .await
+ // .unwrap()
+ // .ensure_tls()
+ // .await
+ // .unwrap();
+ // }
}
diff --git a/src/error.rs b/src/error.rs
index b5cf446..8cb6496 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -8,23 +8,12 @@ use crate::{jid::ParseError, stanza::sasl::Failure};
#[derive(Debug)]
pub enum Error {
Connection,
- BadStream,
- StartTlsUnavailable,
- TlsNegotiation,
Utf8Decode,
- NoFeatures,
- UnknownNamespace,
- UnknownAttribute,
- NoID,
- NoType,
- IDMismatch,
- BindError,
- ParseError,
Negotiation,
TlsRequired,
- UnexpectedEnd,
+ AlreadyTls,
+ Unsupported,
UnexpectedElement(peanuts::Element),
- UnexpectedText,
XML(peanuts::Error),
SASL(SASLError),
JID(ParseError),
@@ -37,8 +26,6 @@ pub enum Error {
pub enum SASLError {
SASL(rsasl::prelude::SASLError),
MechanismName(MechanismNameError),
- NoChallenge,
- NoSuccess,
}
impl From<rsasl::prelude::SASLError> for Error {
diff --git a/src/jabber.rs b/src/jabber.rs
index d5cfe13..cf90f73 100644
--- a/src/jabber.rs
+++ b/src/jabber.rs
@@ -1,4 +1,4 @@
-use std::str;
+use std::str::{self, FromStr};
use std::sync::Arc;
use async_recursion::async_recursion;
@@ -20,47 +20,18 @@ use crate::stanza::XML_VERSION;
use crate::JID;
use crate::{Connection, Result};
-pub struct Jabber<S> {
+// open stream (streams started)
+pub struct JabberStream<S> {
reader: Reader<ReadHalf<S>>,
writer: Writer<WriteHalf<S>>,
- jid: Option<JID>,
- auth: Option<Arc<SASLConfig>>,
- server: String,
}
-impl<S> Jabber<S>
+impl<S> JabberStream<S>
where
- S: AsyncRead + AsyncWrite + Unpin,
+ S: AsyncRead + AsyncWrite + Unpin + Send + std::fmt::Debug,
+ JabberStream<S>: std::fmt::Debug,
{
- pub fn new(
- reader: ReadHalf<S>,
- writer: WriteHalf<S>,
- jid: Option<JID>,
- auth: Option<Arc<SASLConfig>>,
- server: String,
- ) -> Self {
- let reader = Reader::new(reader);
- let writer = Writer::new(writer);
- Self {
- reader,
- writer,
- jid,
- auth,
- server,
- }
- }
-}
-
-impl<S> Jabber<S>
-where
- S: AsyncRead + AsyncWrite + Unpin + Send,
- Jabber<S>: std::fmt::Debug,
-{
- pub async fn sasl(
- &mut self,
- mechanisms: Mechanisms,
- sasl_config: Arc<SASLConfig>,
- ) -> Result<()> {
+ pub async fn sasl(mut self, mechanisms: Mechanisms, sasl_config: Arc<SASLConfig>) -> Result<S> {
let sasl = SASLClient::new(sasl_config);
let mut offered_mechs: Vec<&Mechname> = Vec::new();
for mechanism in &mechanisms.mechanisms {
@@ -143,12 +114,15 @@ where
}
}
}
- Ok(())
+ let writer = self.writer.into_inner();
+ let reader = self.reader.into_inner();
+ let stream = reader.unsplit(writer);
+ Ok(stream)
}
- pub async fn bind(&mut self) -> Result<()> {
+ pub async fn bind(mut self, jid: &mut JID) -> Result<Self> {
let iq_id = nanoid::nanoid!();
- if let Some(resource) = self.jid.clone().unwrap().resourcepart {
+ if let Some(resource) = &jid.resourcepart {
let iq = Iq {
from: None,
id: iq_id.clone(),
@@ -156,7 +130,7 @@ where
r#type: IqType::Set,
lang: None,
query: Some(Query::Bind(Bind {
- r#type: Some(BindType::Resource(ResourceType(resource))),
+ r#type: Some(BindType::Resource(ResourceType(resource.to_string()))),
})),
errors: Vec::new(),
};
@@ -171,12 +145,12 @@ where
lang: _,
query:
Some(Query::Bind(Bind {
- r#type: Some(BindType::Jid(FullJidType(jid))),
+ r#type: Some(BindType::Jid(FullJidType(new_jid))),
})),
errors: _,
} if id == iq_id => {
- self.jid = Some(jid);
- return Ok(());
+ *jid = new_jid;
+ return Ok(self);
}
Iq {
from: _,
@@ -214,12 +188,12 @@ where
lang: _,
query:
Some(Query::Bind(Bind {
- r#type: Some(BindType::Jid(FullJidType(jid))),
+ r#type: Some(BindType::Jid(FullJidType(new_jid))),
})),
errors: _,
} if id == iq_id => {
- self.jid = Some(jid);
- return Ok(());
+ *jid = new_jid;
+ return Ok(self);
}
Iq {
from: _,
@@ -240,39 +214,44 @@ where
}
#[instrument]
- pub async fn start_stream(&mut self) -> Result<()> {
+ pub async fn start_stream(connection: S, server: &mut String) -> Result<Self> {
// client to server
+ let (reader, writer) = tokio::io::split(connection);
+ let mut reader = Reader::new(reader);
+ let mut writer = Writer::new(writer);
// declaration
- self.writer.write_declaration(XML_VERSION).await?;
+ writer.write_declaration(XML_VERSION).await?;
// opening stream element
- let server = self.server.clone().try_into()?;
- let stream = Stream::new_client(None, server, None, "en".to_string());
- self.writer.write_start(&stream).await?;
+ let stream = Stream::new_client(
+ None,
+ JID::from_str(server.as_ref())?,
+ None,
+ "en".to_string(),
+ );
+ writer.write_start(&stream).await?;
// server to client
// may or may not send a declaration
- let _decl = self.reader.read_prolog().await?;
+ let _decl = reader.read_prolog().await?;
// receive stream element and validate
- let text = str::from_utf8(self.reader.buffer.data()).unwrap();
- debug!("data: {}", text);
- let stream: Stream = self.reader.read_start().await?;
+ let stream: Stream = reader.read_start().await?;
debug!("got stream: {:?}", stream);
if let Some(from) = stream.from {
- self.server = from.to_string()
+ *server = from.to_string();
}
- Ok(())
+ Ok(Self { reader, writer })
}
- pub async fn get_features(&mut self) -> Result<Features> {
+ pub async fn get_features(mut self) -> Result<(Features, Self)> {
debug!("getting features");
let features: Features = self.reader.read().await?;
debug!("got features: {:?}", features);
- Ok(features)
+ Ok((features, self))
}
pub fn into_inner(self) -> S {
@@ -280,89 +259,89 @@ where
}
}
-impl Jabber<Unencrypted> {
- pub async fn negotiate<S: AsyncRead + AsyncWrite + Unpin>(mut self) -> Result<Jabber<Tls>> {
- self.start_stream().await?;
- // TODO: timeout
- let features = self.get_features().await?.features;
- if let Some(Feature::StartTls(_)) = features
- .iter()
- .find(|feature| matches!(feature, Feature::StartTls(_s)))
- {
- let jabber = self.starttls().await?;
- let jabber = jabber.negotiate().await?;
- return Ok(jabber);
- } else {
- // TODO: better error
- return Err(Error::TlsRequired);
- }
- }
-
- #[async_recursion]
- pub async fn negotiate_tls_optional(mut self) -> Result<Connection> {
- self.start_stream().await?;
- // TODO: timeout
- let features = self.get_features().await?.features;
- if let Some(Feature::StartTls(_)) = features
- .iter()
- .find(|feature| matches!(feature, Feature::StartTls(_s)))
- {
- let jabber = self.starttls().await?;
- let jabber = jabber.negotiate().await?;
- return Ok(Connection::Encrypted(jabber));
- } else if let (Some(sasl_config), Some(Feature::Sasl(mechanisms))) = (
- self.auth.clone(),
- features
- .iter()
- .find(|feature| matches!(feature, Feature::Sasl(_))),
- ) {
- self.sasl(mechanisms.clone(), sasl_config).await?;
- let jabber = self.negotiate_tls_optional().await?;
- Ok(jabber)
- } else if let Some(Feature::Bind) = features
- .iter()
- .find(|feature| matches!(feature, Feature::Bind))
- {
- self.bind().await?;
- Ok(Connection::Unencrypted(self))
- } else {
- // TODO: better error
- return Err(Error::Negotiation);
- }
- }
+impl JabberStream<Unencrypted> {
+ // pub async fn negotiate<S: AsyncRead + AsyncWrite + Unpin>(
+ // mut self,
+ // features: Features,
+ // ) -> Result<Feature> {
+ // // TODO: timeout
+ // if let Some(Feature::StartTls(_)) = features
+ // .features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::StartTls(_s)))
+ // {
+ // return Ok(self);
+ // } else {
+ // // TODO: better error
+ // return Err(Error::TlsRequired);
+ // }
+ // }
+
+ // #[async_recursion]
+ // pub async fn negotiate_tls_optional(mut self) -> Result<Connection> {
+ // self.start_stream().await?;
+ // // TODO: timeout
+ // let features = self.get_features().await?.features;
+ // if let Some(Feature::StartTls(_)) = features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::StartTls(_s)))
+ // {
+ // let jabber = self.starttls().await?;
+ // let jabber = jabber.negotiate().await?;
+ // return Ok(Connection::Encrypted(jabber));
+ // } else if let (Some(sasl_config), Some(Feature::Sasl(mechanisms))) = (
+ // self.auth.clone(),
+ // features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::Sasl(_))),
+ // ) {
+ // self.sasl(mechanisms.clone(), sasl_config).await?;
+ // let jabber = self.negotiate_tls_optional().await?;
+ // Ok(jabber)
+ // } else if let Some(Feature::Bind) = features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::Bind))
+ // {
+ // self.bind().await?;
+ // Ok(Connection::Unencrypted(self))
+ // } else {
+ // // TODO: better error
+ // return Err(Error::Negotiation);
+ // }
+ // }
}
-impl Jabber<Tls> {
- #[async_recursion]
- pub async fn negotiate(mut self) -> Result<Jabber<Tls>> {
- self.start_stream().await?;
- let features = self.get_features().await?.features;
-
- if let (Some(sasl_config), Some(Feature::Sasl(mechanisms))) = (
- self.auth.clone(),
- features
- .iter()
- .find(|feature| matches!(feature, Feature::Sasl(_))),
- ) {
- // TODO: avoid clone
- self.sasl(mechanisms.clone(), sasl_config).await?;
- let jabber = self.negotiate().await?;
- Ok(jabber)
- } else if let Some(Feature::Bind) = features
- .iter()
- .find(|feature| matches!(feature, Feature::Bind))
- {
- self.bind().await?;
- Ok(self)
- } else {
- // TODO: better error
- return Err(Error::Negotiation);
- }
- }
+impl JabberStream<Tls> {
+ // #[async_recursion]
+ // pub async fn negotiate(mut self) -> Result<JabberStream<Tls>> {
+ // self.start_stream().await?;
+ // let features = self.get_features().await?.features;
+
+ // if let (Some(sasl_config), Some(Feature::Sasl(mechanisms))) = (
+ // self.auth.clone(),
+ // features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::Sasl(_))),
+ // ) {
+ // // TODO: avoid clone
+ // self.sasl(mechanisms.clone(), sasl_config).await?;
+ // let jabber = self.negotiate().await?;
+ // Ok(jabber)
+ // } else if let Some(Feature::Bind) = features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::Bind))
+ // {
+ // self.bind().await?;
+ // Ok(self)
+ // } else {
+ // // TODO: better error
+ // return Err(Error::Negotiation);
+ // }
+ // }
}
-impl Jabber<Unencrypted> {
- pub async fn starttls(mut self) -> Result<Jabber<Tls>> {
+impl JabberStream<Unencrypted> {
+ pub async fn starttls(mut self, domain: impl AsRef<str>) -> Result<Tls> {
self.writer
.write_full(&StartTls { required: false })
.await?;
@@ -370,43 +349,31 @@ impl Jabber<Unencrypted> {
debug!("got proceed: {:?}", proceed);
let connector = TlsConnector::new().unwrap();
let stream = self.reader.into_inner().unsplit(self.writer.into_inner());
- if let Ok(tlsstream) = tokio_native_tls::TlsConnector::from(connector)
- .connect(&self.server, stream)
+ if let Ok(tls_stream) = tokio_native_tls::TlsConnector::from(connector)
+ .connect(domain.as_ref(), stream)
.await
{
- let (read, write) = tokio::io::split(tlsstream);
- let client = Jabber::new(
- read,
- write,
- self.jid.to_owned(),
- self.auth.to_owned(),
- self.server.to_owned(),
- );
- return Ok(client);
+ // let (read, write) = tokio::io::split(tlsstream);
+ // let client = JabberStream::new(read, write);
+ return Ok(tls_stream);
} else {
return Err(Error::Connection);
}
}
}
-impl std::fmt::Debug for Jabber<Tls> {
+impl std::fmt::Debug for JabberStream<Tls> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Jabber")
.field("connection", &"tls")
- .field("jid", &self.jid)
- .field("auth", &self.auth)
- .field("server", &self.server)
.finish()
}
}
-impl std::fmt::Debug for Jabber<Unencrypted> {
+impl std::fmt::Debug for JabberStream<Unencrypted> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Jabber")
.field("connection", &"unencrypted")
- .field("jid", &self.jid)
- .field("auth", &self.auth)
- .field("server", &self.server)
.finish()
}
}
@@ -422,61 +389,61 @@ mod tests {
#[test(tokio::test)]
async fn start_stream() {
- let connection = Connection::connect("blos.sm", None, None).await.unwrap();
- match connection {
- Connection::Encrypted(mut c) => c.start_stream().await.unwrap(),
- Connection::Unencrypted(mut c) => c.start_stream().await.unwrap(),
- }
+ // let connection = Connection::connect("blos.sm", None, None).await.unwrap();
+ // match connection {
+ // Connection::Encrypted(mut c) => c.start_stream().await.unwrap(),
+ // Connection::Unencrypted(mut c) => c.start_stream().await.unwrap(),
+ // }
}
#[test(tokio::test)]
async fn sasl() {
- let mut jabber = Connection::connect_user("test@blos.sm", "slayed".to_string())
- .await
- .unwrap()
- .ensure_tls()
- .await
- .unwrap();
- let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
- println!("data: {}", text);
- jabber.start_stream().await.unwrap();
-
- let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
- println!("data: {}", text);
- jabber.reader.read_buf().await.unwrap();
- let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
- println!("data: {}", text);
-
- let features = jabber.get_features().await.unwrap();
- let (sasl_config, feature) = (
- jabber.auth.clone().unwrap(),
- features
- .features
- .iter()
- .find(|feature| matches!(feature, Feature::Sasl(_)))
- .unwrap(),
- );
- match feature {
- Feature::StartTls(_start_tls) => todo!(),
- Feature::Sasl(mechanisms) => {
- jabber.sasl(mechanisms.clone(), sasl_config).await.unwrap();
- }
- Feature::Bind => todo!(),
- Feature::Unknown => todo!(),
- }
+ // let mut jabber = Connection::connect_user("test@blos.sm", "slayed".to_string())
+ // .await
+ // .unwrap()
+ // .ensure_tls()
+ // .await
+ // .unwrap();
+ // let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
+ // println!("data: {}", text);
+ // jabber.start_stream().await.unwrap();
+
+ // let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
+ // println!("data: {}", text);
+ // jabber.reader.read_buf().await.unwrap();
+ // let text = str::from_utf8(jabber.reader.buffer.data()).unwrap();
+ // println!("data: {}", text);
+
+ // let features = jabber.get_features().await.unwrap();
+ // let (sasl_config, feature) = (
+ // jabber.auth.clone().unwrap(),
+ // features
+ // .features
+ // .iter()
+ // .find(|feature| matches!(feature, Feature::Sasl(_)))
+ // .unwrap(),
+ // );
+ // match feature {
+ // Feature::StartTls(_start_tls) => todo!(),
+ // Feature::Sasl(mechanisms) => {
+ // jabber.sasl(mechanisms.clone(), sasl_config).await.unwrap();
+ // }
+ // Feature::Bind => todo!(),
+ // 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
+ // 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
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 681d1d0..9c8d968 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,7 @@
// #![feature(let_chains)]
// TODO: logging (dropped errors)
+pub mod client;
pub mod connection;
pub mod error;
pub mod jabber;
@@ -11,18 +12,19 @@ pub mod stanza;
pub use connection::Connection;
use connection::Tls;
pub use error::Error;
-pub use jabber::Jabber;
+pub use jabber::JabberStream;
pub use jid::JID;
pub type Result<T> = std::result::Result<T, Error>;
-pub async fn login<J: AsRef<str>, P: AsRef<str>>(jid: J, password: P) -> Result<Jabber<Tls>> {
- Ok(Connection::connect_user(jid, password.as_ref().to_string())
- .await?
- .ensure_tls()
- .await?
- .negotiate()
- .await?)
+pub async fn login<J: AsRef<str>, P: AsRef<str>>(jid: J, password: P) -> Result<JabberStream<Tls>> {
+ todo!()
+ // Ok(Connection::connect_user(jid, password.as_ref().to_string())
+ // .await?
+ // .ensure_tls()
+ // .await?
+ // .negotiate()
+ // .await?)
}
#[cfg(test)]