use rust_xmpp::{
http_service::serve_router,
http_transport::{ConnectionHandler, bosh_router, websocket_router},
wire::Framer,
};
use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::{TcpListener, TcpStream},
};
fn handler(count: Arc) -> ConnectionHandler {
Arc::new(move |mut stream| {
let count = count.clone();
Box::pin(async move {
let mut f = Framer::default();
while let Ok(xml) = f.next(&mut stream).await {
if xml.starts_with("PLAIN").await.unwrap();
} else if xml == "" {
break;
} else {
count.fetch_add(1, Ordering::SeqCst);
stream.write_all(xml.as_bytes()).await.unwrap();
}
}
})
})
}
async fn http(addr: std::net::SocketAddr, body: &str) -> String {
let mut stream = TcpStream::connect(addr).await.unwrap();
let req = format!(
"POST /http-bind HTTP/1.1\r\nHost: example.test\r\nContent-Type: text/xml\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
body.len()
);
stream.write_all(req.as_bytes()).await.unwrap();
let mut bytes = vec![];
stream.read_to_end(&mut bytes).await.unwrap();
String::from_utf8(bytes)
.unwrap()
.split_once("\r\n\r\n")
.unwrap()
.1
.into()
}
#[tokio::test]
async fn bosh_session_retries_restart_termination() {
let count = Arc::new(AtomicUsize::new(0));
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let app = bosh_router(handler(count.clone()));
let task = tokio::spawn(serve_router(listener, None, app));
let initial=http(addr,"").await;
let doc = roxmltree::Document::parse(&initial).unwrap();
let sid = doc.root_element().attribute("sid").unwrap().to_string();
assert!(initial.contains("mechanisms"));
let msg = format!(
"
hello"
);
let response = http(addr, &msg).await;
assert!(response.contains("hello"));
let replay = http(addr, &msg).await;
assert_eq!(replay, response);
assert_eq!(count.load(Ordering::SeqCst), 1);
let restart=http(addr,&format!("