2023-10-28 21:06:42 +01:00
|
|
|
use std::str;
|
2023-07-04 21:27:15 +01:00
|
|
|
use std::sync::Arc;
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
use quick_xml::{events::Event, se::Serializer, NsReader, Writer};
|
2023-07-04 21:27:15 +01:00
|
|
|
use rsasl::prelude::SASLConfig;
|
2023-10-21 01:28:54 +01:00
|
|
|
use serde::Serialize;
|
|
|
|
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufReader, ReadHalf, WriteHalf};
|
2023-10-28 21:06:42 +01:00
|
|
|
use tracing::{debug, info, trace};
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
use crate::connection::{Tls, Unencrypted};
|
|
|
|
use crate::error::JabberError;
|
|
|
|
use crate::stanza::stream::Stream;
|
|
|
|
use crate::stanza::DECLARATION;
|
|
|
|
use crate::Result;
|
|
|
|
use crate::JID;
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
pub struct Jabber<S>
|
|
|
|
where
|
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
|
|
|
{
|
|
|
|
reader: NsReader<BufReader<ReadHalf<S>>>,
|
2023-10-28 21:06:42 +01:00
|
|
|
writer: WriteHalf<S>,
|
2023-10-21 01:28:54 +01:00
|
|
|
jid: Option<JID>,
|
|
|
|
auth: Option<Arc<SASLConfig>>,
|
|
|
|
server: String,
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
impl<S> Jabber<S>
|
|
|
|
where
|
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
|
|
|
{
|
|
|
|
pub fn new(
|
|
|
|
reader: ReadHalf<S>,
|
|
|
|
writer: WriteHalf<S>,
|
|
|
|
jid: Option<JID>,
|
|
|
|
auth: Option<Arc<SASLConfig>>,
|
|
|
|
server: String,
|
|
|
|
) -> Self {
|
|
|
|
let reader = NsReader::from_reader(BufReader::new(reader));
|
|
|
|
Self {
|
|
|
|
reader,
|
|
|
|
writer,
|
2023-06-19 19:23:54 +01:00
|
|
|
jid,
|
2023-07-04 21:27:15 +01:00
|
|
|
auth,
|
2023-06-19 19:23:54 +01:00
|
|
|
server,
|
2023-10-21 01:28:54 +01:00
|
|
|
}
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
2023-10-21 01:28:54 +01:00
|
|
|
}
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
impl<S> Jabber<S>
|
|
|
|
where
|
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
|
|
|
{
|
2023-10-28 21:06:42 +01:00
|
|
|
// pub async fn negotiate(self) -> Result<Jabber<S>> {}
|
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
pub async fn start_stream(&mut self) -> Result<()> {
|
|
|
|
// client to server
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
// declaration
|
2023-10-28 21:06:42 +01:00
|
|
|
let mut xmlwriter = Writer::new(&mut self.writer);
|
|
|
|
xmlwriter.write_event_async(DECLARATION.clone()).await?;
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
// opening stream element
|
|
|
|
let server = &self.server.to_owned().try_into()?;
|
|
|
|
let stream_element = Stream::new_client(None, server, None, "en");
|
|
|
|
// TODO: nicer function to serialize to xml writer
|
|
|
|
let mut buffer = String::new();
|
2023-10-28 21:06:42 +01:00
|
|
|
let ser = Serializer::with_root(&mut buffer, Some("stream:stream")).expect("stream name");
|
2023-10-21 01:28:54 +01:00
|
|
|
stream_element.serialize(ser).unwrap();
|
2023-10-28 21:06:42 +01:00
|
|
|
trace!("sent: {}", buffer);
|
|
|
|
self.writer.write_all(buffer.as_bytes()).await.unwrap();
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
// server to client
|
2023-06-19 19:23:54 +01:00
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
// may or may not send a declaration
|
|
|
|
let mut buf = Vec::new();
|
|
|
|
let mut first_event = self.reader.read_resolved_event_into_async(&mut buf).await?;
|
2023-10-28 21:06:42 +01:00
|
|
|
trace!("received: {:?}", first_event);
|
2023-10-21 01:28:54 +01:00
|
|
|
match first_event {
|
|
|
|
(quick_xml::name::ResolveResult::Unbound, Event::Decl(e)) => {
|
|
|
|
if let Ok(version) = e.version() {
|
|
|
|
if version.as_ref() == b"1.0" {
|
2023-10-28 21:06:42 +01:00
|
|
|
first_event = self.reader.read_resolved_event_into_async(&mut buf).await?;
|
|
|
|
trace!("received: {:?}", first_event);
|
2023-10-21 01:28:54 +01:00
|
|
|
} else {
|
|
|
|
// todo: error
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
} else {
|
2023-10-28 21:06:42 +01:00
|
|
|
first_event = self.reader.read_resolved_event_into_async(&mut buf).await?;
|
|
|
|
trace!("received: {:?}", first_event);
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
|
|
|
}
|
2023-10-21 01:28:54 +01:00
|
|
|
_ => (),
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
|
|
|
|
2023-10-21 01:28:54 +01:00
|
|
|
// receive stream element and validate
|
|
|
|
match first_event {
|
|
|
|
(quick_xml::name::ResolveResult::Bound(ns), Event::Start(e)) => {
|
|
|
|
if ns.0 == crate::stanza::stream::XMLNS.as_bytes() {
|
2023-10-28 21:06:42 +01:00
|
|
|
e.attributes().try_for_each(|attr| -> Result<()> {
|
|
|
|
let attr = attr?;
|
|
|
|
match attr.key.into_inner() {
|
|
|
|
b"from" => {
|
|
|
|
self.server = str::from_utf8(&attr.value)?.to_owned();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
_ => Ok(()),
|
|
|
|
}
|
|
|
|
});
|
2023-10-21 01:28:54 +01:00
|
|
|
return Ok(());
|
|
|
|
} else {
|
|
|
|
return Err(JabberError::BadStream);
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
|
|
|
}
|
2023-10-21 01:28:54 +01:00
|
|
|
// TODO: errors for incorrect namespace
|
2023-10-28 21:06:42 +01:00
|
|
|
_ => Err(JabberError::BadStream),
|
2023-06-19 19:23:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-21 01:28:54 +01:00
|
|
|
|
|
|
|
// pub async fn get_features(&mut self) -> Result<Vec<StreamFeature>> {
|
|
|
|
// Element::read(&mut self.reader).await?.try_into()
|
|
|
|
// }
|
|
|
|
|
|
|
|
impl Jabber<Unencrypted> {
|
2023-10-28 21:06:42 +01:00
|
|
|
pub async fn starttls(&mut self) -> Result<Jabber<Tls>> {
|
2023-10-21 01:28:54 +01:00
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
// let mut starttls_element = BytesStart::new("starttls");
|
|
|
|
// starttls_element.push_attribute(("xmlns", "urn:ietf:params:xml:ns:xmpp-tls"));
|
|
|
|
// self.writer
|
|
|
|
// .write_event_async(Event::Empty(starttls_element))
|
|
|
|
// .await
|
|
|
|
// .unwrap();
|
|
|
|
// let mut buf = Vec::new();
|
|
|
|
// match self.reader.read_event_into_async(&mut buf).await.unwrap() {
|
|
|
|
// Event::Empty(e) => match e.name() {
|
|
|
|
// QName(b"proceed") => {
|
|
|
|
// let connector = TlsConnector::new().unwrap();
|
|
|
|
// let stream = self
|
|
|
|
// .reader
|
|
|
|
// .into_inner()
|
|
|
|
// .into_inner()
|
|
|
|
// .unsplit(self.writer.into_inner());
|
|
|
|
// if let Ok(tlsstream) = tokio_native_tls::TlsConnector::from(connector)
|
|
|
|
// .connect(&self.jabber.server, stream)
|
|
|
|
// .await
|
|
|
|
// {
|
|
|
|
// let (read, write) = tokio::io::split(tlsstream);
|
|
|
|
// let reader = Reader::from_reader(BufReader::new(read));
|
|
|
|
// let writer = Writer::new(write);
|
|
|
|
// let mut client =
|
|
|
|
// super::encrypted::JabberClient::new(reader, writer, self.jabber);
|
|
|
|
// client.start_stream().await?;
|
|
|
|
// return Ok(client);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// QName(_) => return Err(JabberError::TlsNegotiation),
|
|
|
|
// },
|
|
|
|
// _ => return Err(JabberError::TlsNegotiation),
|
|
|
|
// }
|
|
|
|
// Err(JabberError::TlsNegotiation)
|
|
|
|
// }
|
|
|
|
}
|
2023-10-28 21:06:42 +01:00
|
|
|
|
|
|
|
impl std::fmt::Debug for Jabber<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> {
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use crate::connection::Connection;
|
|
|
|
use test_log::test;
|
|
|
|
|
|
|
|
#[test(tokio::test)]
|
|
|
|
async fn start_stream() {
|
|
|
|
let connection = Connection::connect("blos.sm").await.unwrap();
|
|
|
|
match connection {
|
|
|
|
Connection::Encrypted(mut c) => c.start_stream().await.unwrap(),
|
|
|
|
Connection::Unencrypted(mut c) => c.start_stream().await.unwrap(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|