mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-26 13:31:00 +00:00
net/quic: Allow specifying an ALPN transport parameter
See https://datatracker.ietf.org/doc/html/rfc9000#section-7.4. This controls the Transport Layer Security (TLS) extension for application-layer protocol negotiation within the TLS handshake. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1036>
This commit is contained in:
parent
953f6a3fd7
commit
75b25d011f
3 changed files with 54 additions and 6 deletions
|
@ -22,6 +22,7 @@ use std::sync::Mutex;
|
|||
static DEFAULT_SERVER_NAME: &str = "localhost";
|
||||
static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000";
|
||||
static DEFAULT_CLIENT_ADDR: &str = "127.0.0.1:5001";
|
||||
const DEFAULT_ALPN: &str = "h3";
|
||||
const DEFAULT_TIMEOUT: u32 = 15;
|
||||
const DEFAULT_SECURE_CONNECTION: bool = true;
|
||||
|
||||
|
@ -46,6 +47,7 @@ struct Settings {
|
|||
client_address: SocketAddr,
|
||||
server_address: SocketAddr,
|
||||
server_name: String,
|
||||
alpn: String,
|
||||
timeout: u32,
|
||||
secure_conn: bool,
|
||||
use_datagram: bool,
|
||||
|
@ -57,6 +59,7 @@ impl Default for Settings {
|
|||
client_address: DEFAULT_CLIENT_ADDR.parse::<SocketAddr>().unwrap(),
|
||||
server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(),
|
||||
server_name: DEFAULT_SERVER_NAME.to_string(),
|
||||
alpn: DEFAULT_ALPN.to_string(),
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
secure_conn: DEFAULT_SECURE_CONNECTION,
|
||||
use_datagram: false,
|
||||
|
@ -132,6 +135,10 @@ impl ObjectImpl for QuicSink {
|
|||
.nick("QUIC client address")
|
||||
.blurb("Address to be used by this QUIC client e.g. 127.0.0.1:5001")
|
||||
.build(),
|
||||
glib::ParamSpecString::builder("alpn")
|
||||
.nick("QUIC ALPN value")
|
||||
.blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) value")
|
||||
.build(),
|
||||
glib::ParamSpecUInt::builder("timeout")
|
||||
.nick("Timeout")
|
||||
.blurb("Value in seconds to timeout QUIC endpoint requests (0 = No timeout).")
|
||||
|
@ -191,6 +198,10 @@ impl ObjectImpl for QuicSink {
|
|||
),
|
||||
}
|
||||
}
|
||||
"alpn" => {
|
||||
let mut settings = self.settings.lock().unwrap();
|
||||
settings.alpn = value.get::<String>().expect("type checked upstream");
|
||||
}
|
||||
"timeout" => {
|
||||
let mut settings = self.settings.lock().unwrap();
|
||||
settings.timeout = value.get().expect("type checked upstream");
|
||||
|
@ -221,6 +232,10 @@ impl ObjectImpl for QuicSink {
|
|||
let settings = self.settings.lock().unwrap();
|
||||
settings.client_address.to_string().to_value()
|
||||
}
|
||||
"alpn" => {
|
||||
let settings = self.settings.lock().unwrap();
|
||||
settings.alpn.to_value()
|
||||
}
|
||||
"timeout" => {
|
||||
let settings = self.settings.lock().unwrap();
|
||||
settings.timeout.to_value()
|
||||
|
@ -424,6 +439,7 @@ impl QuicSink {
|
|||
let client_addr;
|
||||
let server_addr;
|
||||
let server_name;
|
||||
let alpn;
|
||||
let use_datagram;
|
||||
let secure_conn;
|
||||
|
||||
|
@ -432,11 +448,12 @@ impl QuicSink {
|
|||
client_addr = settings.client_address;
|
||||
server_addr = settings.server_address;
|
||||
server_name = settings.server_name.clone();
|
||||
alpn = settings.alpn.clone();
|
||||
use_datagram = settings.use_datagram;
|
||||
secure_conn = settings.secure_conn;
|
||||
}
|
||||
|
||||
let endpoint = client_endpoint(client_addr, secure_conn).map_err(|err| {
|
||||
let endpoint = client_endpoint(client_addr, secure_conn, &alpn).map_err(|err| {
|
||||
WaitError::FutureError(gst::error_msg!(
|
||||
gst::ResourceError::Failed,
|
||||
["Failed to configure endpoint: {}", err]
|
||||
|
|
|
@ -25,6 +25,7 @@ use std::sync::Mutex;
|
|||
|
||||
static DEFAULT_SERVER_NAME: &str = "localhost";
|
||||
static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000";
|
||||
const DEFAULT_ALPN: &str = "h3";
|
||||
const DEFAULT_TIMEOUT: u32 = 15;
|
||||
const DEFAULT_PRIVATE_KEY_TYPE: QuicPrivateKeyType = QuicPrivateKeyType::Pkcs8;
|
||||
const DEFAULT_SECURE_CONNECTION: bool = true;
|
||||
|
@ -53,6 +54,7 @@ enum State {
|
|||
struct Settings {
|
||||
server_address: SocketAddr,
|
||||
server_name: String,
|
||||
alpn: String,
|
||||
timeout: u32,
|
||||
secure_conn: bool,
|
||||
caps: gst::Caps,
|
||||
|
@ -66,6 +68,7 @@ impl Default for Settings {
|
|||
Settings {
|
||||
server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(),
|
||||
server_name: DEFAULT_SERVER_NAME.to_string(),
|
||||
alpn: DEFAULT_ALPN.to_string(),
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
secure_conn: DEFAULT_SECURE_CONNECTION,
|
||||
caps: gst::Caps::new_any(),
|
||||
|
@ -167,6 +170,10 @@ impl ObjectImpl for QuicSrc {
|
|||
.nick("QUIC server address")
|
||||
.blurb("Address of the QUIC server to connect to e.g. 127.0.0.1:5000")
|
||||
.build(),
|
||||
glib::ParamSpecString::builder("alpn")
|
||||
.nick("QUIC ALPN value")
|
||||
.blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) value")
|
||||
.build(),
|
||||
glib::ParamSpecUInt::builder("timeout")
|
||||
.nick("Timeout")
|
||||
.blurb("Value in seconds to timeout QUIC endpoint requests (0 = No timeout).")
|
||||
|
@ -223,6 +230,10 @@ impl ObjectImpl for QuicSrc {
|
|||
),
|
||||
}
|
||||
}
|
||||
"alpn" => {
|
||||
let mut settings = self.settings.lock().unwrap();
|
||||
settings.alpn = value.get::<String>().expect("type checked upstream");
|
||||
}
|
||||
"caps" => {
|
||||
let mut settings = self.settings.lock().unwrap();
|
||||
settings.caps = value
|
||||
|
@ -270,6 +281,10 @@ impl ObjectImpl for QuicSrc {
|
|||
let settings = self.settings.lock().unwrap();
|
||||
settings.server_address.to_string().to_value()
|
||||
}
|
||||
"alpn" => {
|
||||
let settings = self.settings.lock().unwrap();
|
||||
settings.alpn.to_value()
|
||||
}
|
||||
"caps" => {
|
||||
let settings = self.settings.lock().unwrap();
|
||||
settings.caps.to_value()
|
||||
|
@ -520,6 +535,7 @@ impl QuicSrc {
|
|||
async fn wait_for_connection(&self) -> Result<(Connection, Option<RecvStream>), WaitError> {
|
||||
let server_addr;
|
||||
let server_name;
|
||||
let alpn;
|
||||
let use_datagram;
|
||||
let secure_conn;
|
||||
let cert_path;
|
||||
|
@ -529,6 +545,7 @@ impl QuicSrc {
|
|||
let settings = self.settings.lock().unwrap();
|
||||
server_addr = settings.server_address;
|
||||
server_name = settings.server_name.clone();
|
||||
alpn = settings.alpn.clone();
|
||||
use_datagram = settings.use_datagram;
|
||||
secure_conn = settings.secure_conn;
|
||||
cert_path = settings.certificate_path.clone();
|
||||
|
@ -539,6 +556,7 @@ impl QuicSrc {
|
|||
server_addr,
|
||||
&server_name,
|
||||
secure_conn,
|
||||
&alpn,
|
||||
cert_path,
|
||||
private_key_type,
|
||||
)
|
||||
|
|
|
@ -131,14 +131,15 @@ impl rustls::client::ServerCertVerifier for SkipServerVerification {
|
|||
}
|
||||
}
|
||||
|
||||
fn configure_client(secure_conn: bool) -> Result<ClientConfig, Box<dyn Error>> {
|
||||
fn configure_client(secure_conn: bool, alpn: &str) -> Result<ClientConfig, Box<dyn Error>> {
|
||||
if secure_conn {
|
||||
Ok(ClientConfig::with_native_roots())
|
||||
} else {
|
||||
let crypto = rustls::ClientConfig::builder()
|
||||
let mut crypto = rustls::ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_custom_certificate_verifier(SkipServerVerification::new())
|
||||
.with_no_client_auth();
|
||||
crypto.alpn_protocols = vec![alpn.as_bytes().to_vec()];
|
||||
|
||||
Ok(ClientConfig::new(Arc::new(crypto)))
|
||||
}
|
||||
|
@ -201,6 +202,7 @@ fn read_certs_from_file(
|
|||
fn configure_server(
|
||||
server_name: &str,
|
||||
secure_conn: bool,
|
||||
alpn: &str,
|
||||
certificate_path: Option<PathBuf>,
|
||||
private_key_type: QuicPrivateKeyType,
|
||||
) -> Result<(ServerConfig, Vec<rustls::Certificate>), Box<dyn Error>> {
|
||||
|
@ -216,7 +218,16 @@ fn configure_server(
|
|||
(cert_chain, priv_key)
|
||||
};
|
||||
|
||||
let mut server_config = ServerConfig::with_single_cert(cert.clone(), key)?;
|
||||
let mut crypto = rustls::ServerConfig::builder()
|
||||
.with_safe_default_cipher_suites()
|
||||
.with_safe_default_kx_groups()
|
||||
.with_protocol_versions(&[&rustls::version::TLS13])
|
||||
.unwrap()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(cert.clone(), key)?;
|
||||
crypto.alpn_protocols = vec![alpn.as_bytes().to_vec()];
|
||||
let mut server_config = ServerConfig::with_crypto(Arc::new(crypto));
|
||||
|
||||
Arc::get_mut(&mut server_config.transport)
|
||||
.unwrap()
|
||||
.max_concurrent_bidi_streams(0_u8.into())
|
||||
|
@ -229,11 +240,12 @@ pub fn server_endpoint(
|
|||
server_addr: SocketAddr,
|
||||
server_name: &str,
|
||||
secure_conn: bool,
|
||||
alpn: &str,
|
||||
certificate_path: Option<PathBuf>,
|
||||
private_key_type: QuicPrivateKeyType,
|
||||
) -> Result<Endpoint, Box<dyn Error>> {
|
||||
let (server_config, _) =
|
||||
configure_server(server_name, secure_conn, certificate_path, private_key_type)?;
|
||||
configure_server(server_name, secure_conn, alpn, certificate_path, private_key_type)?;
|
||||
let endpoint = Endpoint::server(server_config, server_addr)?;
|
||||
|
||||
Ok(endpoint)
|
||||
|
@ -242,8 +254,9 @@ pub fn server_endpoint(
|
|||
pub fn client_endpoint(
|
||||
client_addr: SocketAddr,
|
||||
secure_conn: bool,
|
||||
alpn: &str,
|
||||
) -> Result<Endpoint, Box<dyn Error>> {
|
||||
let client_cfg = configure_client(secure_conn)?;
|
||||
let client_cfg = configure_client(secure_conn, alpn)?;
|
||||
let mut endpoint = Endpoint::client(client_addr)?;
|
||||
|
||||
endpoint.set_default_client_config(client_cfg);
|
||||
|
|
Loading…
Reference in a new issue