diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml
index 39d643e..31e4c90 100644
--- a/.idea/leptos-use.iml
+++ b/.idea/leptos-use.iml
@@ -54,6 +54,8 @@
+
+
@@ -115,6 +117,8 @@
+
+
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index 8a47395..9818f37 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -46,7 +46,8 @@ members = [
]
exclude = [
- "ssr"
+ "ssr",
+ "use_webtransport_with_server",
]
[package]
diff --git a/examples/use_webtransport_with_server/client/Cargo.toml b/examples/use_webtransport_with_server/client/Cargo.toml
index f629f2d..5632fa1 100644
--- a/examples/use_webtransport_with_server/client/Cargo.toml
+++ b/examples/use_webtransport_with_server/client/Cargo.toml
@@ -1,14 +1,14 @@
[package]
-name = "use_webtransport"
+name = "use_webtransport_with_server_client"
version = "0.1.0"
edition = "2021"
[dependencies]
-leptos = { version = "0.5.0-beta2", features = ["nightly", "csr"] }
+leptos = { version = "0.5.0-rc1", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
-leptos-use = { path = "../..", features = ["docs"] }
+leptos-use = { path = "../../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
diff --git a/examples/use_webtransport_with_server/client/src/main.rs b/examples/use_webtransport_with_server/client/src/main.rs
index 52bd825..5c54c23 100644
--- a/examples/use_webtransport_with_server/client/src/main.rs
+++ b/examples/use_webtransport_with_server/client/src/main.rs
@@ -18,7 +18,7 @@ fn Demo() -> impl IntoView {
let id = store_value(0);
let transport = use_webtransport_with_options(
- "https://echo.webtransport.day",
+ "https://localhost:4433",
UseWebTransportOptions::default()
.on_open(move || {
set_datagrams_log.update(|log| log.push("Connection opened".to_string()))
diff --git a/examples/use_webtransport_with_server/server/Cargo.toml b/examples/use_webtransport_with_server/server/Cargo.toml
new file mode 100644
index 0000000..38f0ebd
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "webtransport_test_server"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1"
+base64 = "0.21.0"
+rcgen = "0.10.0"
+ring = "0.16.20"
+time = "0.3.21"
+tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
+tracing = "0.1"
+tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
+wtransport = "0.1"
\ No newline at end of file
diff --git a/examples/use_webtransport_with_server/server/cert.pem b/examples/use_webtransport_with_server/server/cert.pem
new file mode 100644
index 0000000..99dee79
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/cert.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBNTCB3KADAgECAghq294raE5e9TAKBggqhkjOPQQDAjAUMRIwEAYDVQQDDAls
+b2NhbGhvc3QwHhcNMjMwOTEzMDEyNzIxWhcNMjMwOTE3MDEyNzIxWjAUMRIwEAYD
+VQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARel++iw3/0
+CPZTew09XTEmyKWGyUW7clEok17gb6BIqVZHy5pZ+P1F/qHSSuJtzZ+WFueVS1ZO
+MCDfQql88sIyoxgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwCgYIKoZIzj0EAwID
+SAAwRQIhAMQi1xToDZY8y4zZMOk7JJ3qqFOei6JkNcZf/68Zdgk3AiBCbPgLxaIw
+n4bYLm0yqzQ5jzaJcOkrLMBQakaHJMyFoA==
+-----END CERTIFICATE-----
diff --git a/examples/use_webtransport_with_server/server/key.pem b/examples/use_webtransport_with_server/server/key.pem
new file mode 100644
index 0000000..2c4d2c6
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgsOnsJtFGWK8w011r
+400WvxgSScmnnAWFyuQ+o/dhvDGhRANCAARel++iw3/0CPZTew09XTEmyKWGyUW7
+clEok17gb6BIqVZHy5pZ+P1F/qHSSuJtzZ+WFueVS1ZOMCDfQql88sIy
+-----END PRIVATE KEY-----
diff --git a/examples/use_webtransport_with_server/server/rust-toolchain.toml b/examples/use_webtransport_with_server/server/rust-toolchain.toml
new file mode 100644
index 0000000..271800c
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
\ No newline at end of file
diff --git a/examples/use_webtransport_with_server/server/src/bin/gencert.rs b/examples/use_webtransport_with_server/server/src/bin/gencert.rs
new file mode 100644
index 0000000..6ca6397
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/src/bin/gencert.rs
@@ -0,0 +1,50 @@
+use base64::engine::general_purpose::STANDARD as Base64Engine;
+use base64::Engine;
+use rcgen::CertificateParams;
+use rcgen::DistinguishedName;
+use rcgen::DnType;
+use rcgen::KeyPair;
+use rcgen::PKCS_ECDSA_P256_SHA256;
+use ring::digest::digest;
+use ring::digest::SHA256;
+use std::fs;
+use std::io::Write;
+use time::Duration;
+use time::OffsetDateTime;
+
+fn main() {
+ const COMMON_NAME: &str = "localhost";
+
+ let mut dname = DistinguishedName::new();
+ dname.push(DnType::CommonName, COMMON_NAME);
+
+ let keypair = KeyPair::generate(&PKCS_ECDSA_P256_SHA256).unwrap();
+
+ let digest = digest(&SHA256, &keypair.public_key_der());
+
+ let mut cert_params = CertificateParams::new(vec![COMMON_NAME.to_string()]);
+ cert_params.distinguished_name = dname;
+ cert_params.alg = &PKCS_ECDSA_P256_SHA256;
+ cert_params.key_pair = Some(keypair);
+ cert_params.not_before = OffsetDateTime::now_utc()
+ .checked_sub(Duration::days(2))
+ .unwrap();
+ cert_params.not_after = OffsetDateTime::now_utc()
+ .checked_add(Duration::days(2))
+ .unwrap();
+
+ let certificate = rcgen::Certificate::from_params(cert_params).unwrap();
+
+ fs::File::create("cert.pem")
+ .unwrap()
+ .write_all(certificate.serialize_pem().unwrap().as_bytes())
+ .unwrap();
+
+ fs::File::create("key.pem")
+ .unwrap()
+ .write_all(certificate.serialize_private_key_pem().as_bytes())
+ .unwrap();
+
+ println!("Certificate generated");
+ println!("Fingerprint: {}", Base64Engine.encode(digest));
+}
diff --git a/examples/use_webtransport_with_server/server/src/main.rs b/examples/use_webtransport_with_server/server/src/main.rs
new file mode 100644
index 0000000..7b797a1
--- /dev/null
+++ b/examples/use_webtransport_with_server/server/src/main.rs
@@ -0,0 +1,113 @@
+use anyhow::Result;
+use std::time::Duration;
+use tracing::error;
+use tracing::info;
+use tracing::info_span;
+use tracing::Instrument;
+use tracing_subscriber::filter::LevelFilter;
+use tracing_subscriber::EnvFilter;
+use wtransport::endpoint::IncomingSession;
+use wtransport::tls::Certificate;
+use wtransport::Endpoint;
+use wtransport::ServerConfig;
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ init_logging();
+
+ let config = ServerConfig::builder()
+ .with_bind_default(4433)
+ .with_certificate(Certificate::load("cert.pem", "key.pem")?)
+ .keep_alive_interval(Some(Duration::from_secs(3)))
+ .build();
+
+ let server = Endpoint::server(config)?;
+
+ info!("Server listening at localhost:4433");
+
+ for id in 0.. {
+ let incoming_session = server.accept().await;
+ tokio::spawn(handle_connection(incoming_session).instrument(info_span!("Connection", id)));
+ }
+
+ Ok(())
+}
+
+async fn handle_connection(incoming_session: IncomingSession) {
+ let result = handle_connection_impl(incoming_session).await;
+ error!("{:?}", result);
+}
+
+async fn handle_connection_impl(incoming_session: IncomingSession) -> Result<()> {
+ let mut buffer = vec![0; 65536].into_boxed_slice();
+
+ info!("Waiting for session request...");
+
+ let session_request = incoming_session.await?;
+
+ info!(
+ "New session: Authority: '{}', Path: '{}'",
+ session_request.authority(),
+ session_request.path()
+ );
+
+ let connection = session_request.accept().await?;
+
+ info!("Waiting for data from client...");
+
+ loop {
+ tokio::select! {
+ stream = connection.accept_bi() => {
+ let mut stream = stream?;
+ info!("Accepted BI stream");
+
+ let bytes_read = match stream.1.read(&mut buffer).await? {
+ Some(bytes_read) => bytes_read,
+ None => continue,
+ };
+
+ let str_data = std::str::from_utf8(&buffer[..bytes_read])?;
+
+ info!("Received (bi) '{str_data}' from client");
+
+ stream.0.write_all(b"ACK").await?;
+ }
+ stream = connection.accept_uni() => {
+ let mut stream = stream?;
+ info!("Accepted UNI stream");
+
+ let bytes_read = match stream.read(&mut buffer).await? {
+ Some(bytes_read) => bytes_read,
+ None => continue,
+ };
+
+ let str_data = std::str::from_utf8(&buffer[..bytes_read])?;
+
+ info!("Received (uni) '{str_data}' from client");
+
+ let mut stream = connection.open_uni().await?.await?;
+ stream.write_all(b"ACK").await?;
+ }
+ dgram = connection.receive_datagram() => {
+ let dgram = dgram?;
+ let str_data = std::str::from_utf8(&dgram)?;
+
+ info!("Received (dgram) '{str_data}' from client");
+
+ connection.send_datagram(b"ACK")?;
+ }
+ }
+ }
+}
+
+fn init_logging() {
+ let env_filter = EnvFilter::builder()
+ .with_default_directive(LevelFilter::INFO.into())
+ .from_env_lossy();
+
+ tracing_subscriber::fmt()
+ .with_target(true)
+ .with_level(true)
+ .with_env_filter(env_filter)
+ .init();
+}