Skip to content

Commit 1c07cd9

Browse files
committed
Prioritize H2 via ALPN.
1 parent 468a26c commit 1c07cd9

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ hex = "0.4.3"
4141
nom = "8.0.0"
4242

4343
tokio-rustls = { version = "0.26", default-features = false }
44+
rustls-pemfile = "2.0"
4445
futures-util = { version = "0.3.31", default-features = false }
4546
httlib-hpack = "0.1.3"
4647
pin-project-lite = "0.2.9"

src/daemon.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl Daemon {
3232
/// Get the pid of the daemon
3333
fn get_pid(&self) -> crate::Result<Option<String>> {
3434
if let Ok(data) = std::fs::read(&self.pid_file) {
35-
let binding = String::from_utf8(data)?;
35+
let binding = String::from_utf8(data).unwrap();
3636
return Ok(Some(binding.trim().to_string()));
3737
}
3838
Ok(None)

src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ pub enum Error {
3333
#[error(transparent)]
3434
Join(#[from] tokio::task::JoinError),
3535

36-
#[error(transparent)]
37-
Utf8(#[from] std::string::FromUtf8Error),
36+
#[error("{0}")]
37+
Other(String),
3838
}

src/server/mod.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod certificate;
22
mod signal;
33
mod tracker;
44

5-
use std::{net::SocketAddr, str::FromStr, time::Duration};
5+
use std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration};
66

77
use axum::{
88
body::Body,
@@ -74,14 +74,20 @@ pub async fn run(args: Args) -> Result<()> {
7474
// Spawn a task to gracefully shutdown server.
7575
tokio::spawn(signal::graceful_shutdown(handle.clone()));
7676

77-
// Load TLS configuration
77+
// Load TLS configuration with HTTP/2 ALPN preference
7878
let tls_config = match (args.tls_cert.as_ref(), args.tls_key.as_ref()) {
79-
(Some(cert), Some(key)) => RustlsConfig::from_pem_chain_file(cert, key).await,
79+
(Some(cert_path), Some(key_path)) => {
80+
// Load certificate and key from files
81+
let cert_pem = std::fs::read(cert_path)?;
82+
let key_pem = std::fs::read(key_path)?;
83+
create_rustls_config_with_h2_alpn(cert_pem, key_pem).await?
84+
}
8085
_ => {
81-
let (cert, key) = certificate::get_self_signed_cert()?;
82-
RustlsConfig::from_pem(cert, key).await
86+
// Generate self-signed certificate
87+
let (cert_pem, key_pem) = certificate::get_self_signed_cert()?;
88+
create_rustls_config_with_h2_alpn(cert_pem, key_pem).await?
8389
}
84-
}?;
90+
};
8591

8692
// Use TLS configuration to create a secure server
8793
let mut server = axum_server::bind_rustls(args.bind, tls_config);
@@ -105,6 +111,45 @@ impl IntoResponse for Error {
105111
}
106112
}
107113

114+
/// Create RustlsConfig with HTTP/2 ALPN preference
115+
async fn create_rustls_config_with_h2_alpn(
116+
cert_pem: Vec<u8>,
117+
key_pem: Vec<u8>,
118+
) -> Result<RustlsConfig> {
119+
use tokio_rustls::rustls::{
120+
pki_types::{CertificateDer, PrivateKeyDer},
121+
ServerConfig,
122+
};
123+
124+
// Parse certificates/PK
125+
let certs: Vec<CertificateDer> = rustls_pemfile::certs(&mut cert_pem.as_slice())
126+
.collect::<std::result::Result<Vec<_>, _>>()
127+
.map_err(|e| Error::Other(format!("Failed to parse certificate: {}", e)))?;
128+
129+
let key: PrivateKeyDer = rustls_pemfile::private_key(&mut key_pem.as_slice())
130+
.map_err(|e| Error::Other(format!("Failed to parse private key: {}", e)))?
131+
.ok_or_else(|| Error::Other("No private key found".to_string()))?;
132+
133+
// Create server config with ALPN protocols (HTTP/2 first)
134+
let config = ServerConfig::builder()
135+
.with_no_client_auth()
136+
.with_single_cert(certs, key)
137+
.map_err(|e| Error::Other(format!("Failed to create TLS config: {}", e)))?;
138+
139+
// Set ALPN protocols with HTTP/2 preference
140+
let mut config = config;
141+
config.alpn_protocols = vec![
142+
b"h2".to_vec(),
143+
b"http/1.1".to_vec(),
144+
b"http/1.0".to_vec(),
145+
b"http/0.9".to_vec(),
146+
];
147+
148+
tracing::info!("TLS configured with ALPN protocols: h2 (HTTP/2), http/1.1, http/1.0, http/0.9");
149+
150+
Ok(RustlsConfig::from_config(Arc::new(config)))
151+
}
152+
108153
#[inline]
109154
pub async fn track(
110155
Extension(ConnectInfo(addr)): Extension<ConnectInfo<SocketAddr>>,

0 commit comments

Comments
 (0)