Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1dbff1e
Initial commit
maddeleine Jun 26, 2025
5b5e22b
Edits
maddeleine Jul 18, 2025
0d2bcbc
Using Alloc::vec
maddeleine Jul 18, 2025
cf186e4
clippy fixes
maddeleine Jul 18, 2025
fdfade0
Comments
maddeleine Jul 18, 2025
e15ed70
Changes
maddeleine Jul 19, 2025
1beda51
Adds example
maddeleine Jul 21, 2025
26a8c87
Oops
maddeleine Jul 21, 2025
8639482
Fixing clippy
maddeleine Jul 21, 2025
5533291
Fixing for Windows
maddeleine Jul 21, 2025
322682f
Got rustls tests working
maddeleine Jul 22, 2025
45db21f
PR feedback
maddeleine Jul 22, 2025
aad52eb
More PR feedback
maddeleine Jul 23, 2025
10ab8fd
More PR feedback
maddeleine Jul 23, 2025
0427193
Minor fix
maddeleine Jul 23, 2025
d10dde7
Handled err cases
maddeleine Jul 23, 2025
abfb173
Adds timer to ConnFuture
maddeleine Jul 23, 2025
5f60e07
Clippy fixes
maddeleine Jul 23, 2025
520f55c
gating feature behind std
maddeleine Jul 23, 2025
6bc9939
Adds failing test
maddeleine Jul 23, 2025
cf08070
Fix failing windows test
maddeleine Jul 24, 2025
63c32fe
Getting exporter working
maddeleine Jul 28, 2025
c415882
Rustls fix
maddeleine Jul 29, 2025
0564b16
Cargo fmt
maddeleine Jul 29, 2025
0f3f93d
Clean up
maddeleine Jul 29, 2025
b83bde8
Fixed async client hello test
maddeleine Jul 29, 2025
d158cc0
PR feedback
maddeleine Jul 30, 2025
0400d40
Handle errors
maddeleine Jul 30, 2025
8ccdaba
progress
maddeleine Jul 31, 2025
9c597a0
More errors
maddeleine Jul 31, 2025
fb5f5a0
More fixes
maddeleine Jul 31, 2025
37f26e2
Adds default impl of Exporter
maddeleine Jul 31, 2025
ec7b43f
Clippy
maddeleine Jul 31, 2025
7e809f3
Removed commented out thing
maddeleine Jul 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/tls-offloading/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "tls-offloading"
version = "0.1.0"
edition = "2024"

[dependencies]
s2n-quic = { version = "1", path = "../../quic/s2n-quic", features = ["unstable-offload-tls"]}
tokio = { version = "1", features = ["full"] }
25 changes: 25 additions & 0 deletions examples/tls-offloading/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# TLS offload

s2n-quic is single-threaded by default. This can cause performance issues in the instance where many clients try to connect to a single s2n-quic server at the same time. Each incoming Client Hello will cause the s2n-quic server event loop to be blocked while the TLS provider completes the expensive cryptographic operations necessary to process the Client Hello. This has the potential to slow down all existing connections in favor of new ones. The TLS offloading feature attempts to alleviate this problem by moving each TLS connection to a separate async task, which can then be spawned by the runtime the user provides.

To do this, implement the `offload::Executor` trait with the runtime of your choice. In this example, we use the `tokio::spawn` function as our executor:
```
struct TokioExecutor;
impl Executor for TokioExecutor {
fn spawn(&self, task: impl core::future::Future<Output = ()> + Send + 'static) {
tokio::spawn(task);
}
}
```

# Warning
The default offloading feature as-is may result in packet loss in the handshake, depending on how packets arrive to the offload endpoint. This packet loss will slow down the handshake, as QUIC has to detect the loss and the peer has to resend the lost packets. We have an upcoming feature that will combat this packet loss and will probably be required to achieve the fastest handshakes possible with s2n-quic: https://github.com/aws/s2n-quic/pull/2668. However, it is still in the PR process.

# Set-up

Currently offloading is disabled by default as it is still in development. It can be enabled by adding this line to your Cargo.toml file:

```toml
[dependencies]
s2n-quic = { version = "1", features = ["unstable-offload-tls"]}
```
64 changes: 64 additions & 0 deletions examples/tls-offloading/src/bin/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use s2n_quic::{
Client,
client::Connect,
provider::tls::{
default,
offload::{Executor, OffloadBuilder},
},
};
use std::{error::Error, net::SocketAddr};

/// NOTE: this certificate is to be used for demonstration purposes only!
pub static CERT_PEM: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../quic/s2n-quic-core/certs/cert.pem"
));

struct TokioExecutor;
impl Executor for TokioExecutor {
fn spawn(&self, task: impl core::future::Future<Output = ()> + Send + 'static) {
tokio::spawn(task);
}
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let tls = default::Client::builder()
.with_certificate(CERT_PEM)?
.build()?;
let tls_endpoint = OffloadBuilder::new()
.with_endpoint(tls)
.with_executor(TokioExecutor)
.build();

let client = Client::builder()
.with_tls(tls_endpoint)?
.with_io("0.0.0.0:0")?
.start()?;

let addr: SocketAddr = "127.0.0.1:4433".parse()?;
let connect = Connect::new(addr).with_server_name("localhost");
let mut connection = client.connect(connect).await?;

// ensure the connection doesn't time out with inactivity
connection.keep_alive(true)?;

// open a new stream and split the receiving and sending sides
let stream = connection.open_bidirectional_stream().await?;
let (mut receive_stream, mut send_stream) = stream.split();

// spawn a task that copies responses from the server to stdout
tokio::spawn(async move {
let mut stdout = tokio::io::stdout();
let _ = tokio::io::copy(&mut receive_stream, &mut stdout).await;
});

// copy data from stdin and send it to the server
let mut stdin = tokio::io::stdin();
tokio::io::copy(&mut stdin, &mut send_stream).await?;

Ok(())
}
67 changes: 67 additions & 0 deletions examples/tls-offloading/src/bin/server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use s2n_quic::{
Server,
provider::tls::{
default,
offload::{Executor, OffloadBuilder},
},
};
use std::error::Error;

/// NOTE: this certificate is to be used for demonstration purposes only!
pub static CERT_PEM: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../quic/s2n-quic-core/certs/cert.pem"
));
/// NOTE: this certificate is to be used for demonstration purposes only!
pub static KEY_PEM: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../quic/s2n-quic-core/certs/key.pem"
));

struct TokioExecutor;
impl Executor for TokioExecutor {
fn spawn(&self, task: impl core::future::Future<Output = ()> + Send + 'static) {
tokio::spawn(task);
}
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let tls = default::Server::builder()
.with_certificate(CERT_PEM, KEY_PEM)?
.build()?;

let tls_endpoint = OffloadBuilder::new()
.with_endpoint(tls)
.with_executor(TokioExecutor)
.build();

let mut server = Server::builder()
.with_tls(tls_endpoint)?
.with_io("127.0.0.1:4433")?
.start()?;

while let Some(mut connection) = server.accept().await {
// spawn a new task for the connection
tokio::spawn(async move {
eprintln!("Connection accepted from {:?}", connection.remote_addr());

while let Ok(Some(mut stream)) = connection.accept_bidirectional_stream().await {
// spawn a new task for the stream
tokio::spawn(async move {
eprintln!("Stream opened from {:?}", stream.connection().remote_addr());

// echo any data back to the stream
while let Ok(Some(data)) = stream.receive().await {
stream.send(data).await.expect("stream should be open");
}
});
}
});
}

Ok(())
}
3 changes: 3 additions & 0 deletions quic/s2n-quic-core/src/crypto/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub mod null;
#[cfg(feature = "alloc")]
pub mod slow_tls;

#[cfg(feature = "std")]
pub mod offload;

/// Holds all application parameters which are exchanged within the TLS handshake.
#[derive(Debug)]
pub struct ApplicationParameters<'a> {
Expand Down
Loading
Loading