mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-18 16:16:28 +00:00
quinn: allow unsecure connections in WebTransport elements
WebTransport requires a secure connection, but certificates can have a validity of 2 weeks. For testing, a new property is added to allow unsecure connections. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1867>
This commit is contained in:
parent
be02c0e388
commit
a791cfff2b
5 changed files with 59 additions and 50 deletions
|
@ -57,6 +57,7 @@ struct Settings {
|
||||||
bind_port: u16,
|
bind_port: u16,
|
||||||
certificate_file: Option<PathBuf>,
|
certificate_file: Option<PathBuf>,
|
||||||
keep_alive_interval: u64,
|
keep_alive_interval: u64,
|
||||||
|
secure_conn: bool,
|
||||||
timeout: u32,
|
timeout: u32,
|
||||||
transport_config: QuinnQuicTransportConfig,
|
transport_config: QuinnQuicTransportConfig,
|
||||||
url: String,
|
url: String,
|
||||||
|
@ -77,6 +78,7 @@ impl Default for Settings {
|
||||||
bind_port: DEFAULT_BIND_PORT,
|
bind_port: DEFAULT_BIND_PORT,
|
||||||
certificate_file: None,
|
certificate_file: None,
|
||||||
keep_alive_interval: 0,
|
keep_alive_interval: 0,
|
||||||
|
secure_conn: DEFAULT_SECURE_CONNECTION,
|
||||||
timeout: DEFAULT_TIMEOUT,
|
timeout: DEFAULT_TIMEOUT,
|
||||||
transport_config,
|
transport_config,
|
||||||
url: DEFAULT_ADDR.to_string(),
|
url: DEFAULT_ADDR.to_string(),
|
||||||
|
@ -131,6 +133,29 @@ impl ElementImpl for QuinnWebTransportClientSrc {
|
||||||
|
|
||||||
PAD_TEMPLATES.as_ref()
|
PAD_TEMPLATES.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn change_state(
|
||||||
|
&self,
|
||||||
|
transition: gst::StateChange,
|
||||||
|
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
|
||||||
|
if transition == gst::StateChange::NullToReady {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fail the state change if a secure connection was requested but
|
||||||
|
* no certificate path was provided.
|
||||||
|
*/
|
||||||
|
if settings.secure_conn && settings.certificate_file.is_none() {
|
||||||
|
gst::error!(
|
||||||
|
CAT,
|
||||||
|
imp = self,
|
||||||
|
"Certificate or private key file not provided for secure connection"
|
||||||
|
);
|
||||||
|
return Err(gst::StateChangeError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.parent_change_state(transition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for QuinnWebTransportClientSrc {
|
impl ObjectImpl for QuinnWebTransportClientSrc {
|
||||||
|
@ -175,6 +200,11 @@ impl ObjectImpl for QuinnWebTransportClientSrc {
|
||||||
.blurb("Connection statistics")
|
.blurb("Connection statistics")
|
||||||
.read_only()
|
.read_only()
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecBoolean::builder("secure-connection")
|
||||||
|
.nick("Use secure connection.")
|
||||||
|
.blurb("Use certificates for QUIC connection. False: Insecure connection, True: Secure connection.")
|
||||||
|
.default_value(DEFAULT_SECURE_CONNECTION)
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -195,6 +225,9 @@ impl ObjectImpl for QuinnWebTransportClientSrc {
|
||||||
"timeout" => {
|
"timeout" => {
|
||||||
settings.timeout = value.get().expect("type checked upstream");
|
settings.timeout = value.get().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
"secure-connection" => {
|
||||||
|
settings.secure_conn = value.get().expect("type checked upstream");
|
||||||
|
}
|
||||||
"url" => {
|
"url" => {
|
||||||
settings.url = value.get::<String>().expect("type checked upstream");
|
settings.url = value.get::<String>().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
@ -217,6 +250,7 @@ impl ObjectImpl for QuinnWebTransportClientSrc {
|
||||||
"timeout" => settings.timeout.to_value(),
|
"timeout" => settings.timeout.to_value(),
|
||||||
"url" => settings.url.to_value(),
|
"url" => settings.url.to_value(),
|
||||||
"use-datagram" => settings.use_datagram.to_value(),
|
"use-datagram" => settings.use_datagram.to_value(),
|
||||||
|
"secure-connection" => settings.secure_conn.to_value(),
|
||||||
"stats" => {
|
"stats" => {
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
match *state {
|
match *state {
|
||||||
|
@ -471,7 +505,7 @@ impl QuinnWebTransportClientSrc {
|
||||||
server_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 4443), // This will be filled in correctly later
|
server_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 4443), // This will be filled in correctly later
|
||||||
server_name: DEFAULT_SERVER_NAME.to_string(),
|
server_name: DEFAULT_SERVER_NAME.to_string(),
|
||||||
client_addr: Some(client_addr),
|
client_addr: Some(client_addr),
|
||||||
secure_conn: true,
|
secure_conn: settings.secure_conn,
|
||||||
alpns: vec![HTTP3_ALPN.to_string()],
|
alpns: vec![HTTP3_ALPN.to_string()],
|
||||||
certificate_file: settings.certificate_file.clone(),
|
certificate_file: settings.certificate_file.clone(),
|
||||||
private_key_file: None,
|
private_key_file: None,
|
||||||
|
|
|
@ -21,7 +21,6 @@ use futures::future;
|
||||||
use gst::{glib, prelude::*, subclass::prelude::*};
|
use gst::{glib, prelude::*, subclass::prelude::*};
|
||||||
use gst_base::subclass::prelude::*;
|
use gst_base::subclass::prelude::*;
|
||||||
use quinn::{Connection, TransportConfig};
|
use quinn::{Connection, TransportConfig};
|
||||||
use web_transport_quinn::{Request, SendStream, Session};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{LazyLock, Mutex};
|
use std::sync::{LazyLock, Mutex};
|
||||||
use web_transport_quinn::{Request, SendStream, Session};
|
use web_transport_quinn::{Request, SendStream, Session};
|
||||||
|
@ -55,6 +54,7 @@ struct Settings {
|
||||||
use_datagram: bool,
|
use_datagram: bool,
|
||||||
certificate_file: Option<PathBuf>,
|
certificate_file: Option<PathBuf>,
|
||||||
private_key_file: Option<PathBuf>,
|
private_key_file: Option<PathBuf>,
|
||||||
|
secure_conn: bool,
|
||||||
transport_config: QuinnQuicTransportConfig,
|
transport_config: QuinnQuicTransportConfig,
|
||||||
drop_buffer_for_datagram: bool,
|
drop_buffer_for_datagram: bool,
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ impl Default for Settings {
|
||||||
use_datagram: false,
|
use_datagram: false,
|
||||||
certificate_file: None,
|
certificate_file: None,
|
||||||
private_key_file: None,
|
private_key_file: None,
|
||||||
|
secure_conn: DEFAULT_SECURE_CONNECTION,
|
||||||
transport_config,
|
transport_config,
|
||||||
drop_buffer_for_datagram: DEFAULT_DROP_BUFFER_FOR_DATAGRAM,
|
drop_buffer_for_datagram: DEFAULT_DROP_BUFFER_FOR_DATAGRAM,
|
||||||
}
|
}
|
||||||
|
@ -133,11 +134,14 @@ impl ElementImpl for QuinnWebTransportServerSink {
|
||||||
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
|
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
|
||||||
if transition == gst::StateChange::NullToReady {
|
if transition == gst::StateChange::NullToReady {
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WebTransport requires a secure connection, fail the state change if
|
* Fail the state change if a secure connection was requested but
|
||||||
* no certificate paths were provided.
|
* no certificate path was provided.
|
||||||
*/
|
*/
|
||||||
if settings.certificate_file.is_none() || settings.private_key_file.is_none() {
|
if settings.secure_conn
|
||||||
|
&& (settings.certificate_file.is_none() || settings.private_key_file.is_none())
|
||||||
|
{
|
||||||
gst::error!(
|
gst::error!(
|
||||||
CAT,
|
CAT,
|
||||||
imp = self,
|
imp = self,
|
||||||
|
@ -237,6 +241,11 @@ impl ObjectImpl for QuinnWebTransportServerSink {
|
||||||
.blurb("Drop buffers when using datagram if buffer size > max datagram size")
|
.blurb("Drop buffers when using datagram if buffer size > max datagram size")
|
||||||
.default_value(DEFAULT_DROP_BUFFER_FOR_DATAGRAM)
|
.default_value(DEFAULT_DROP_BUFFER_FOR_DATAGRAM)
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecBoolean::builder("secure-connection")
|
||||||
|
.nick("Use secure connection.")
|
||||||
|
.blurb("Use certificates for QUIC connection. False: Insecure connection, True: Secure connection.")
|
||||||
|
.default_value(DEFAULT_SECURE_CONNECTION)
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -299,6 +308,9 @@ impl ObjectImpl for QuinnWebTransportServerSink {
|
||||||
"drop-buffer-for-datagram" => {
|
"drop-buffer-for-datagram" => {
|
||||||
settings.drop_buffer_for_datagram = value.get().expect("type checked upstream");
|
settings.drop_buffer_for_datagram = value.get().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
"secure-connection" => {
|
||||||
|
settings.secure_conn = value.get().expect("type checked upstream");
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,6 +347,7 @@ impl ObjectImpl for QuinnWebTransportServerSink {
|
||||||
"datagram-send-buffer-size" => {
|
"datagram-send-buffer-size" => {
|
||||||
(settings.transport_config.datagram_send_buffer_size as u64).to_value()
|
(settings.transport_config.datagram_send_buffer_size as u64).to_value()
|
||||||
}
|
}
|
||||||
|
"secure-connection" => settings.secure_conn.to_value(),
|
||||||
"stats" => {
|
"stats" => {
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
match *state {
|
match *state {
|
||||||
|
@ -564,6 +577,7 @@ impl QuinnWebTransportServerSink {
|
||||||
let (use_datagram, endpoint_config) = {
|
let (use_datagram, endpoint_config) = {
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
|
let secure_conn = settings.secure_conn;
|
||||||
let server_addr =
|
let server_addr =
|
||||||
make_socket_addr(format!("{}:{}", settings.address, settings.port).as_str())?;
|
make_socket_addr(format!("{}:{}", settings.address, settings.port).as_str())?;
|
||||||
|
|
||||||
|
@ -573,7 +587,7 @@ impl QuinnWebTransportServerSink {
|
||||||
server_addr,
|
server_addr,
|
||||||
server_name: settings.server_name.clone(),
|
server_name: settings.server_name.clone(),
|
||||||
client_addr: None,
|
client_addr: None,
|
||||||
secure_conn: true,
|
secure_conn,
|
||||||
alpns: vec![HTTP3_ALPN.to_string()],
|
alpns: vec![HTTP3_ALPN.to_string()],
|
||||||
certificate_file: settings.certificate_file.clone(),
|
certificate_file: settings.certificate_file.clone(),
|
||||||
private_key_file: settings.private_key_file.clone(),
|
private_key_file: settings.private_key_file.clone(),
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIBZjCCAQ2gAwIBAgIUducmm59E2q/s87I6F8uymGvNuM4wCgYIKoZIzj0EAwIw
|
|
||||||
FDESMBAGA1UEAwwJTG9jYWxob3N0MB4XDTI0MTAxNjA4MDExMFoXDTI0MTExNTA4
|
|
||||||
MDExMFowFDESMBAGA1UEAwwJTG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
|
|
||||||
AQcDQgAEEmItpfgNKextROvDh4+phcUP3s0jb1OeQHuHnYa5hw5O+FVQf6FtgL6U
|
|
||||||
Zx5fdgl+NIW795ZR/Nt7y9D5H4fxP6M9MDswGgYDVR0RBBMwEYIJbG9jYWxob3N0
|
|
||||||
hwR/AAABMB0GA1UdDgQWBBSLX7qrn+1oorVuolaoiKVBU6irfTAKBggqhkjOPQQD
|
|
||||||
AgNHADBEAiASp7doLyxErcAfUJ3QLxQZ+Rav8+n/Xv7ukisxNr+UuAIgALEzXXsa
|
|
||||||
mN1VcFcbHPcQoTwCFlv/MxKAmaOgJel43tc=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,8 +0,0 @@
|
||||||
-----BEGIN EC PARAMETERS-----
|
|
||||||
BggqhkjOPQMBBw==
|
|
||||||
-----END EC PARAMETERS-----
|
|
||||||
-----BEGIN EC PRIVATE KEY-----
|
|
||||||
MHcCAQEEINlRLGfOFJfJFhcOYkW1PXw6OPM5qABO0FT158tiI25hoAoGCCqGSM49
|
|
||||||
AwEHoUQDQgAEEmItpfgNKextROvDh4+phcUP3s0jb1OeQHuHnYa5hw5O+FVQf6Ft
|
|
||||||
gL6UZx5fdgl+NIW795ZR/Nt7y9D5H4fxPw==
|
|
||||||
-----END EC PRIVATE KEY-----
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
use std::{path::PathBuf, thread};
|
use std::thread;
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
@ -27,40 +27,19 @@ fn make_buffer(content: &[u8]) -> gst::Buffer {
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_certificates_paths() -> (String, String) {
|
|
||||||
let mut certs_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
certs_dir.push("tests");
|
|
||||||
certs_dir.push("certs");
|
|
||||||
|
|
||||||
(
|
|
||||||
certs_dir
|
|
||||||
.join("localhost.crt")
|
|
||||||
.into_os_string()
|
|
||||||
.into_string()
|
|
||||||
.unwrap(),
|
|
||||||
certs_dir
|
|
||||||
.join("localhost.key")
|
|
||||||
.into_os_string()
|
|
||||||
.into_string()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_receive(src_pipeline_props: &str, sink_pipeline_props: &str) {
|
fn send_receive(src_pipeline_props: &str, sink_pipeline_props: &str) {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
let content = "Hello, world!\n".as_bytes();
|
let content = "Hello, world!\n".as_bytes();
|
||||||
|
|
||||||
let (cert_path, key_path) = get_certificates_paths();
|
|
||||||
|
|
||||||
let src_pipeline = format!(
|
let src_pipeline = format!(
|
||||||
"quinnwtclientsrc {} certificate-file={} caps=text/plain",
|
"quinnwtclientsrc {} secure-connection=false",
|
||||||
src_pipeline_props, cert_path
|
src_pipeline_props
|
||||||
);
|
);
|
||||||
let sink_pipeline = format!(
|
let sink_pipeline = format!(
|
||||||
"quinnwtserversink {} server-name=localhost \
|
"quinnwtserversink {} server-name=localhost \
|
||||||
address=127.0.0.1 certificate-file={} private-key-file={}",
|
address=127.0.0.1 secure-connection=false",
|
||||||
sink_pipeline_props, cert_path, key_path
|
sink_pipeline_props
|
||||||
);
|
);
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
|
Loading…
Reference in a new issue