128 lines
4.3 KiB
Rust
128 lines
4.3 KiB
Rust
use iroh::{Endpoint, endpoint::ConnectionError};
|
|
use n0_tracing_test::traced_test;
|
|
use tracing::Instrument;
|
|
use url::Url;
|
|
|
|
use crate::{ALPN_H3, Client, H3Request, QuicRequest, SessionError};
|
|
|
|
#[tokio::test]
|
|
#[traced_test]
|
|
async fn h3_smoke() -> n0_error::Result<()> {
|
|
let client = Endpoint::bind()
|
|
.instrument(tracing::error_span!("client-ep"))
|
|
.await
|
|
.unwrap();
|
|
let client_id = client.id();
|
|
let client = Client::new(client);
|
|
|
|
let server = Endpoint::builder()
|
|
.alpns(vec![ALPN_H3.as_bytes().to_vec()])
|
|
.bind()
|
|
.instrument(tracing::error_span!("server-ep"))
|
|
.await
|
|
.unwrap();
|
|
let server_id = server.id();
|
|
let server_addr = server.addr();
|
|
|
|
let url: Url = format!("https://{}/foo", server_id).parse().unwrap();
|
|
|
|
let client_task = tokio::task::spawn({
|
|
let url = url.clone();
|
|
async move {
|
|
let session = client.connect_h3(server_addr, url.clone()).await.inspect_err(|err| println!("{err:#?}")).unwrap();
|
|
assert_eq!(session.remote_id(), server_id);
|
|
assert_eq!(session.url(), Some(&url));
|
|
|
|
let mut stream = session.open_uni().await.unwrap();
|
|
stream.write_all(b"hi").await.unwrap();
|
|
stream.finish().unwrap();
|
|
let reason = session.closed().await;
|
|
assert!(
|
|
matches!(reason, SessionError::ConnectionError(ConnectionError::ApplicationClosed(frame)) if web_transport_proto::error_from_http3(frame.error_code.into_inner()) == Some(23))
|
|
);
|
|
|
|
drop(session);
|
|
client.close().await;
|
|
}.instrument(tracing::error_span!("client"))
|
|
});
|
|
|
|
let server_task = tokio::task::spawn(
|
|
async move {
|
|
let conn = server.accept().await.unwrap().await.unwrap();
|
|
assert_eq!(conn.alpn(), ALPN_H3.as_bytes());
|
|
let request = H3Request::accept(conn)
|
|
.await
|
|
.inspect_err(|err| tracing::error!("accept failed: {err:?}"))
|
|
.unwrap();
|
|
assert_eq!(request.url(), &url);
|
|
assert_eq!(request.conn().remote_id(), client_id);
|
|
let session = request.ok().await.unwrap();
|
|
assert_eq!(session.url(), Some(&url));
|
|
assert_eq!(session.conn().remote_id(), client_id);
|
|
let mut stream = session.accept_uni().await.unwrap();
|
|
let buf = stream.read_to_end(2).await.unwrap();
|
|
assert_eq!(buf, b"hi");
|
|
session.close(23, b"bye");
|
|
server.close().await;
|
|
}
|
|
.instrument(tracing::error_span!("server")),
|
|
);
|
|
|
|
client_task.await.unwrap();
|
|
server_task.await.unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[traced_test]
|
|
async fn quic_smoke() -> n0_error::Result<()> {
|
|
const ALPN: &str = "moql";
|
|
|
|
let client = Endpoint::bind().await.unwrap();
|
|
let client_id = client.id();
|
|
let client = Client::new(client);
|
|
|
|
let server = Endpoint::builder()
|
|
.alpns(vec![ALPN.as_bytes().to_vec()])
|
|
.bind()
|
|
.await
|
|
.unwrap();
|
|
let server_id = server.id();
|
|
let server_addr = server.addr();
|
|
|
|
let client_task = tokio::task::spawn({
|
|
async move {
|
|
let session = client
|
|
.connect_quic(server_addr, ALPN.as_bytes())
|
|
.await
|
|
.unwrap();
|
|
println!("session established");
|
|
assert_eq!(session.remote_id(), server_id);
|
|
assert_eq!(session.url(), None);
|
|
let reason = session.closed().await;
|
|
assert!(
|
|
matches!(reason, SessionError::ConnectionError(ConnectionError::ApplicationClosed(frame)) if frame.error_code.into_inner() == 23)
|
|
)
|
|
}.instrument(tracing::error_span!("client"))
|
|
});
|
|
|
|
let server_task = tokio::task::spawn({
|
|
async move {
|
|
let conn = server.accept().await.unwrap().await.unwrap();
|
|
assert_eq!(conn.alpn(), ALPN.as_bytes());
|
|
let request = QuicRequest::accept(conn);
|
|
assert_eq!(request.conn().remote_id(), client_id);
|
|
let session = request.ok();
|
|
assert_eq!(session.url(), None);
|
|
assert_eq!(session.conn().remote_id(), client_id);
|
|
session.close(23, b"bye");
|
|
}
|
|
.instrument(tracing::error_span!("server"))
|
|
});
|
|
|
|
client_task.await.unwrap();
|
|
server_task.await.unwrap();
|
|
|
|
Ok(())
|
|
}
|