From 798b27ccb2621a42c33791a1a4fddf9bb343d17d Mon Sep 17 00:00:00 2001 From: JustTestingV Date: Sat, 20 Jan 2024 20:12:40 +0300 Subject: [PATCH 1/3] [xmpp] no panic! --- Cargo.lock | 1 + crates/projection-xmpp/src/lib.rs | 2 +- crates/proto-xmpp/Cargo.toml | 1 + crates/proto-xmpp/src/stream.rs | 7 ++++--- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0ed647..c46c42f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1376,6 +1376,7 @@ dependencies = [ "anyhow", "assert_matches", "derive_more", + "lavina-core", "lazy_static", "quick-xml", "regex", diff --git a/crates/projection-xmpp/src/lib.rs b/crates/projection-xmpp/src/lib.rs index 9192092..9e852ca 100644 --- a/crates/projection-xmpp/src/lib.rs +++ b/crates/projection-xmpp/src/lib.rs @@ -83,7 +83,7 @@ pub async fn launch( let key = match read_one(&mut SyncBufReader::new(File::open(config.key)?))? { Some(PemItem::ECKey(k) | PemItem::PKCS8Key(k) | PemItem::RSAKey(k)) => PrivateKey(k), - _ => panic!("no keys in file"), + _ => return Err(fail("no keys in file")), }; let loaded_config = Arc::new(LoadedConfig { diff --git a/crates/proto-xmpp/Cargo.toml b/crates/proto-xmpp/Cargo.toml index 01fec80..ec43715 100644 --- a/crates/proto-xmpp/Cargo.toml +++ b/crates/proto-xmpp/Cargo.toml @@ -4,6 +4,7 @@ edition = "2021" version.workspace = true [dependencies] +lavina-core.workspace = true quick-xml.workspace = true lazy_static.workspace = true regex.workspace = true diff --git a/crates/proto-xmpp/src/stream.rs b/crates/proto-xmpp/src/stream.rs index 4d11039..40f5f5b 100644 --- a/crates/proto-xmpp/src/stream.rs +++ b/crates/proto-xmpp/src/stream.rs @@ -3,6 +3,7 @@ use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; use quick_xml::name::{Namespace, QName, ResolveResult}; use quick_xml::{NsReader, Writer}; use tokio::io::{AsyncBufRead, AsyncWrite}; +use lavina_core::prelude::fail; use super::skip_text; @@ -28,10 +29,10 @@ impl ClientStreamStart { if let Event::Start(e) = incoming { let (ns, local) = reader.resolve_element(e.name()); if ns != ResolveResult::Bound(Namespace(XMLNS.as_bytes())) { - return Err(panic!()); + return Err(fail("Invalid namespace for stream element")); } if local.into_inner() != b"stream" { - return Err(panic!()); + return Err(fail("Invalid local name for stream element")); } let mut to = None; let mut lang = None; @@ -64,7 +65,7 @@ impl ClientStreamStart { version: version.unwrap(), }) } else { - Err(panic!()) + Err(fail("Incoming message does not belong XML Start Event")) } } } From b74325291675d54d9c94a9560d3de3d070c54727 Mon Sep 17 00:00:00 2001 From: JustTestingV Date: Sat, 20 Jan 2024 20:27:52 +0300 Subject: [PATCH 2/3] deleted lavina-core dependency in proto-xmpp --- Cargo.lock | 1 - crates/proto-xmpp/Cargo.toml | 1 - crates/proto-xmpp/src/stream.rs | 7 +++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c46c42f..c0ed647 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1376,7 +1376,6 @@ dependencies = [ "anyhow", "assert_matches", "derive_more", - "lavina-core", "lazy_static", "quick-xml", "regex", diff --git a/crates/proto-xmpp/Cargo.toml b/crates/proto-xmpp/Cargo.toml index ec43715..01fec80 100644 --- a/crates/proto-xmpp/Cargo.toml +++ b/crates/proto-xmpp/Cargo.toml @@ -4,7 +4,6 @@ edition = "2021" version.workspace = true [dependencies] -lavina-core.workspace = true quick-xml.workspace = true lazy_static.workspace = true regex.workspace = true diff --git a/crates/proto-xmpp/src/stream.rs b/crates/proto-xmpp/src/stream.rs index 40f5f5b..b336bc8 100644 --- a/crates/proto-xmpp/src/stream.rs +++ b/crates/proto-xmpp/src/stream.rs @@ -3,7 +3,6 @@ use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; use quick_xml::name::{Namespace, QName, ResolveResult}; use quick_xml::{NsReader, Writer}; use tokio::io::{AsyncBufRead, AsyncWrite}; -use lavina_core::prelude::fail; use super::skip_text; @@ -29,10 +28,10 @@ impl ClientStreamStart { if let Event::Start(e) = incoming { let (ns, local) = reader.resolve_element(e.name()); if ns != ResolveResult::Bound(Namespace(XMLNS.as_bytes())) { - return Err(fail("Invalid namespace for stream element")); + return Err(anyhow!("Invalid namespace for stream element")); } if local.into_inner() != b"stream" { - return Err(fail("Invalid local name for stream element")); + return Err(anyhow!("Invalid local name for stream element")); } let mut to = None; let mut lang = None; @@ -65,7 +64,7 @@ impl ClientStreamStart { version: version.unwrap(), }) } else { - Err(fail("Incoming message does not belong XML Start Event")) + Err(anyhow!("Incoming message does not belong XML Start Event")) } } } From 1905ac1977b2d177266f1b583e9886aa7e34f10d Mon Sep 17 00:00:00 2001 From: JustTestingV Date: Wed, 31 Jan 2024 16:54:40 +0300 Subject: [PATCH 3/3] attempt to write tests --- crates/projection-xmpp/src/lib.rs | 38 ++++++++++----- crates/projection-xmpp/tests/lib.rs | 72 +++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 12 deletions(-) diff --git a/crates/projection-xmpp/src/lib.rs b/crates/projection-xmpp/src/lib.rs index 9e852ca..6969e82 100644 --- a/crates/projection-xmpp/src/lib.rs +++ b/crates/projection-xmpp/src/lib.rs @@ -187,18 +187,32 @@ async fn handle_socket( let mut xml_reader = NsReader::from_reader(BufReader::new(a)); let mut xml_writer = Writer::new(b); - let authenticated = socket_auth(&mut xml_reader, &mut xml_writer, &mut reader_buf, &mut storage).await?; - log::debug!("User authenticated"); - let mut connection = players.connect_to_player(authenticated.player_id.clone()).await; - socket_final( - &mut xml_reader, - &mut xml_writer, - &mut reader_buf, - &authenticated, - &mut connection, - &rooms, - ) - .await?; + pin!(termination); + select! { + biased; + _ = &mut termination => return Ok(()), + authenticated = socket_auth(&mut xml_reader, &mut xml_writer, &mut reader_buf, &mut storage) => { + match authenticated { + Ok(authenticated) => { + log::debug!("User authenticated"); + let mut connection = players.connect_to_player(authenticated.player_id.clone()).await; + socket_final( + &mut xml_reader, + &mut xml_writer, + &mut reader_buf, + &authenticated, + &mut connection, + &rooms, + ) + .await?; + }, + Err(err) => { + log::error!("Authentication error: {:?}", err); + } + } + }, + } + let a = xml_reader.into_inner().into_inner(); let b = xml_writer.into_inner(); diff --git a/crates/projection-xmpp/tests/lib.rs b/crates/projection-xmpp/tests/lib.rs index 39675eb..ea20d1b 100644 --- a/crates/projection-xmpp/tests/lib.rs +++ b/crates/projection-xmpp/tests/lib.rs @@ -184,3 +184,75 @@ async fn scenario_basic() -> Result<()> { server.terminate().await?; Ok(()) } + + +#[tokio::test] +async fn terminate_socket() -> Result<()> { + tracing_subscriber::fmt::init(); + let config = ServerConfig { + listen_on: "127.0.0.1:0".parse().unwrap(), + cert: "tests/certs/xmpp.pem".parse().unwrap(), + key: "tests/certs/xmpp.key".parse().unwrap(), + }; + let mut metrics = MetricsRegistry::new(); + let mut storage = Storage::open(StorageConfig { + db_path: ":memory:".into(), + }) + .await?; + let rooms = RoomRegistry::new(&mut metrics, storage.clone()).unwrap(); + let players = PlayerRegistry::empty(rooms.clone(), &mut metrics).unwrap(); + let server = launch(config, players, rooms, metrics, storage.clone()).await.unwrap(); + + // test scenario + + storage.create_user("tester").await?; + storage.set_password("tester", "password").await?; + + let mut stream = TcpStream::connect(server.addr).await?; + let mut s = TestScope::new(&mut stream); + tracing::info!("TCP connection established"); + + s.send(r#""#).await?; + s.send(r#""#).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#""#).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.addr.ip()), stream).await?; + tracing::info!("TLS connection established"); + + server.terminate().await?; + + let mut s = TestScopeTls::new(&mut stream, buffer); + + println!("--------------------------------"); + let res = s.send(r#""#).await; + println!(); + assert!(res.is_ok()); + + // s.send(r#""#).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")); + + // stream.shutdown().await?; + + // wrap up + + // server.terminate().await?; + Ok(()) +}