This commit is contained in:
Mikhail 2024-05-02 19:19:35 +02:00
parent 1996c3d6c7
commit d9490c43fd
4 changed files with 121 additions and 7 deletions

View File

@ -4,7 +4,7 @@ use quick_xml::events::Event;
use lavina_core::room::{RoomId, RoomRegistry};
use proto_xmpp::bind::{BindResponse, Jid, Name, Server};
use proto_xmpp::client::{Iq, IqError, IqErrorType, IqType};
use proto_xmpp::client::{Iq, IqError, IqErrorType, IqType, Message, MessageType};
use proto_xmpp::disco::{Feature, Identity, InfoQuery, Item, ItemQuery};
use proto_xmpp::roster::RosterQuery;
use proto_xmpp::session::Session;
@ -12,7 +12,7 @@ use proto_xmpp::session::Session;
use crate::proto::IqClientBody;
use crate::XmppConnection;
use proto_xmpp::xml::ToXml;
use proto_xmpp::xml::{Ignore, ToXml};
impl<'a> XmppConnection<'a> {
pub async fn handle_iq(&self, output: &mut Vec<Event<'static>>, iq: Iq<IqClientBody>) {
@ -87,6 +87,9 @@ impl<'a> XmppConnection<'a> {
};
req.serialize(output);
}
IqClientBody::MessageArchiveRequest(request) => {
// let response = self.mam().await?;
}
_ => {
let req = Iq {
from: None,
@ -220,4 +223,22 @@ impl<'a> XmppConnection<'a> {
};
ItemQuery { item }
}
async fn mam(&self) -> Result<Message<Ignore>, ()> {
// return Ok(());
Ok(Message::<Ignore> {
from: None,
id: Some("aacea".to_string()),
to: Some(Jid {
name: Some(Name("nikita".into())),
server: Server("vlnv.dev".into()),
resource: None,
}),
r#type: MessageType::Chat,
lang: None,
subject: Some("daa".into()),
body: "bbb".into(),
custom: vec![Ignore],
})
}
}

View File

@ -7,6 +7,7 @@ use lavina_core::prelude::*;
use proto_xmpp::bind::BindRequest;
use proto_xmpp::client::{Iq, Message, Presence};
use proto_xmpp::disco::{InfoQuery, ItemQuery};
use proto_xmpp::mam::MessageArchiveRequest;
use proto_xmpp::roster::RosterQuery;
use proto_xmpp::session::Session;
use proto_xmpp::xml::*;
@ -18,6 +19,7 @@ pub enum IqClientBody {
Roster(RosterQuery),
DiscoInfo(InfoQuery),
DiscoItem(ItemQuery),
MessageArchiveRequest(MessageArchiveRequest),
Unknown(Ignore),
}
@ -38,6 +40,7 @@ impl FromXml for IqClientBody {
RosterQuery,
InfoQuery,
ItemQuery,
MessageArchiveRequest,
{
delegate_parsing!(Ignore, namespace, event).into()
}

View File

@ -1,4 +1,5 @@
use std::io::ErrorKind;
use std::str::from_utf8;
use std::sync::Arc;
use std::time::Duration;
@ -107,13 +108,14 @@ impl<'a> TestScopeTls<'a> {
}
struct IgnoreCertVerification;
impl ServerCertVerifier for IgnoreCertVerification {
fn verify_server_cert(
&self,
_end_entity: &tokio_rustls::rustls::Certificate,
_intermediates: &[tokio_rustls::rustls::Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_scts: &mut dyn Iterator<Item=&[u8]>,
_ocsp_response: &[u8],
_now: std::time::SystemTime,
) -> std::result::Result<tokio_rustls::rustls::client::ServerCertVerified, tokio_rustls::rustls::Error> {
@ -128,6 +130,7 @@ struct TestServer {
players: PlayerRegistry,
server: RunningServer,
}
impl TestServer {
async fn start() -> Result<TestServer> {
let _ = tracing_subscriber::fmt::try_init();
@ -141,7 +144,7 @@ impl TestServer {
let mut storage = Storage::open(StorageConfig {
db_path: ":memory:".into(),
})
.await?;
.await?;
let rooms = RoomRegistry::new(&mut metrics, storage.clone()).unwrap();
let players = PlayerRegistry::empty(rooms.clone(), storage.clone(), &mut metrics).unwrap();
let server = launch(config, players.clone(), rooms.clone(), metrics.clone(), storage.clone()).await.unwrap();
@ -300,3 +303,90 @@ async fn terminate_socket() -> Result<()> {
Ok(())
}
#[tokio::test]
async fn test_message_archive_request() -> Result<()> {
let mut server = TestServer::start().await?;
// test scenario
server.storage.create_user("tester").await?;
server.storage.set_password("tester", "password").await?;
let mut stream = TcpStream::connect(server.server.addr).await?;
let mut s = TestScope::new(&mut stream);
tracing::info!("TCP connection established");
s.send(r#"<?xml version="1.0"?>"#).await?;
s.send(r#"<stream:stream xmlns:stream="http://etherx.jabber.org/streams" to="127.0.0.1" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns="jabber:client" version="1.0">"#).await?;
assert_matches!(s.next_xml_event().await?, Event::Decl(_) => {});
assert_matches!(s.next_xml_event().await?, Event::Start(b) => assert_eq!(b.local_name().into_inner(), b"stream"));
assert_matches!(s.next_xml_event().await?, Event::Start(b) => assert_eq!(b.local_name().into_inner(), b"features"));
assert_matches!(s.next_xml_event().await?, Event::Start(b) => assert_eq!(b.local_name().into_inner(), b"starttls"));
assert_matches!(s.next_xml_event().await?, Event::Empty(b) => assert_eq!(b.local_name().into_inner(), b"required"));
assert_matches!(s.next_xml_event().await?, Event::End(b) => assert_eq!(b.local_name().into_inner(), b"starttls"));
assert_matches!(s.next_xml_event().await?, Event::End(b) => assert_eq!(b.local_name().into_inner(), b"features"));
s.send(r#"<starttls/>"#).await?;
assert_matches!(s.next_xml_event().await?, Event::Empty(b) => assert_eq!(b.local_name().into_inner(), b"proceed"));
let buffer = s.buffer;
tracing::info!("TLS feature negotiation complete");
let connector = TlsConnector::from(Arc::new(
ClientConfig::builder()
.with_safe_defaults()
.with_custom_certificate_verifier(Arc::new(IgnoreCertVerification))
.with_no_client_auth(),
));
tracing::info!("Initiating TLS connection...");
let mut stream = connector.connect(ServerName::IpAddress(server.server.addr.ip()), stream).await?;
tracing::info!("TLS connection established");
let mut s = TestScopeTls::new(&mut stream, buffer);
s.send(r#"<?xml version="1.0"?>"#).await?;
s.send(r#"<stream:stream xmlns:stream="http://etherx.jabber.org/streams" to="127.0.0.1" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns="jabber:client" version="1.0">"#).await?;
assert_matches!(s.next_xml_event().await?, Event::Decl(_) => {});
assert_matches!(s.next_xml_event().await?, Event::Start(b) => assert_eq!(b.local_name().into_inner(), b"stream"));
assert_matches!(s.next_xml_event().await?, Event::Start(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "features")
});
assert_matches!(s.next_xml_event().await?, Event::Start(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "mechanisms")
});
assert_matches!(s.next_xml_event().await?, Event::Start(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "mechanism")
});
assert_matches!(s.next_xml_event().await?, Event::Text(b) => {
// b.
// let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
// assert_eq!(local_name, "mechanism")
});
assert_matches!(s.next_xml_event().await?, Event::End(b) => {
// let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
// assert_eq!(local_name, "mechanism")
});
assert_matches!(s.next_xml_event().await?, Event::End(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "mechanisms")
});
assert_matches!(s.next_xml_event().await?, Event::End(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "features")
});
// s.send(r#"<iq type='get' id='juliet1'><query xmlns='urn:xmpp:mam:tmp' queryid='f27'/></iq>"#).await?;
assert_matches!(s.next_xml_event().await?, Event::Start(b) => {
let local_name: &str = from_utf8(b.local_name().into_inner()).unwrap();
assert_eq!(local_name, "message")
});
stream.shutdown().await?;
// wrap up
server.server.terminate().await?;
Ok(())
}

View File

@ -10,17 +10,17 @@ pub const DATA_XMLNS: &'static str = "jabber:x:data";
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct MessageArchiveRequest {
x: Option<X>,
pub x: Option<X>,
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct X {
fields: Vec<Field>,
pub fields: Vec<Field>,
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Field {
values: Vec<String>,
pub values: Vec<String>,
}
impl FromXmlTag for X {