diff --git a/net/quinn/src/quinnwtclientsrc/imp.rs b/net/quinn/src/quinnwtclientsrc/imp.rs index 47a22387..2a41d30d 100644 --- a/net/quinn/src/quinnwtclientsrc/imp.rs +++ b/net/quinn/src/quinnwtclientsrc/imp.rs @@ -57,6 +57,7 @@ struct Settings { bind_port: u16, certificate_file: Option, keep_alive_interval: u64, + secure_conn: bool, timeout: u32, transport_config: QuinnQuicTransportConfig, url: String, @@ -77,6 +78,7 @@ impl Default for Settings { bind_port: DEFAULT_BIND_PORT, certificate_file: None, keep_alive_interval: 0, + secure_conn: DEFAULT_SECURE_CONNECTION, timeout: DEFAULT_TIMEOUT, transport_config, url: DEFAULT_ADDR.to_string(), @@ -131,6 +133,29 @@ impl ElementImpl for QuinnWebTransportClientSrc { PAD_TEMPLATES.as_ref() } + + fn change_state( + &self, + transition: gst::StateChange, + ) -> Result { + 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 { @@ -175,6 +200,11 @@ impl ObjectImpl for QuinnWebTransportClientSrc { .blurb("Connection statistics") .read_only() .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" => { settings.timeout = value.get().expect("type checked upstream"); } + "secure-connection" => { + settings.secure_conn = value.get().expect("type checked upstream"); + } "url" => { settings.url = value.get::().expect("type checked upstream"); } @@ -217,6 +250,7 @@ impl ObjectImpl for QuinnWebTransportClientSrc { "timeout" => settings.timeout.to_value(), "url" => settings.url.to_value(), "use-datagram" => settings.use_datagram.to_value(), + "secure-connection" => settings.secure_conn.to_value(), "stats" => { let state = self.state.lock().unwrap(); 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_name: DEFAULT_SERVER_NAME.to_string(), client_addr: Some(client_addr), - secure_conn: true, + secure_conn: settings.secure_conn, alpns: vec![HTTP3_ALPN.to_string()], certificate_file: settings.certificate_file.clone(), private_key_file: None, diff --git a/net/quinn/src/quinnwtserversink/imp.rs b/net/quinn/src/quinnwtserversink/imp.rs index 967e9af7..1ad54539 100644 --- a/net/quinn/src/quinnwtserversink/imp.rs +++ b/net/quinn/src/quinnwtserversink/imp.rs @@ -21,7 +21,6 @@ use futures::future; use gst::{glib, prelude::*, subclass::prelude::*}; use gst_base::subclass::prelude::*; use quinn::{Connection, TransportConfig}; -use web_transport_quinn::{Request, SendStream, Session}; use std::path::PathBuf; use std::sync::{LazyLock, Mutex}; use web_transport_quinn::{Request, SendStream, Session}; @@ -55,6 +54,7 @@ struct Settings { use_datagram: bool, certificate_file: Option, private_key_file: Option, + secure_conn: bool, transport_config: QuinnQuicTransportConfig, drop_buffer_for_datagram: bool, } @@ -74,6 +74,7 @@ impl Default for Settings { use_datagram: false, certificate_file: None, private_key_file: None, + secure_conn: DEFAULT_SECURE_CONNECTION, transport_config, drop_buffer_for_datagram: DEFAULT_DROP_BUFFER_FOR_DATAGRAM, } @@ -133,11 +134,14 @@ impl ElementImpl for QuinnWebTransportServerSink { ) -> Result { if transition == gst::StateChange::NullToReady { let settings = self.settings.lock().unwrap(); + /* - * WebTransport requires a secure connection, fail the state change if - * no certificate paths were provided. + * Fail the state change if a secure connection was requested but + * 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!( CAT, imp = self, @@ -237,6 +241,11 @@ impl ObjectImpl for QuinnWebTransportServerSink { .blurb("Drop buffers when using datagram if buffer size > max datagram size") .default_value(DEFAULT_DROP_BUFFER_FOR_DATAGRAM) .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" => { settings.drop_buffer_for_datagram = value.get().expect("type checked upstream"); } + "secure-connection" => { + settings.secure_conn = value.get().expect("type checked upstream"); + } _ => unimplemented!(), } } @@ -335,6 +347,7 @@ impl ObjectImpl for QuinnWebTransportServerSink { "datagram-send-buffer-size" => { (settings.transport_config.datagram_send_buffer_size as u64).to_value() } + "secure-connection" => settings.secure_conn.to_value(), "stats" => { let state = self.state.lock().unwrap(); match *state { @@ -564,6 +577,7 @@ impl QuinnWebTransportServerSink { let (use_datagram, endpoint_config) = { let settings = self.settings.lock().unwrap(); + let secure_conn = settings.secure_conn; let server_addr = make_socket_addr(format!("{}:{}", settings.address, settings.port).as_str())?; @@ -573,7 +587,7 @@ impl QuinnWebTransportServerSink { server_addr, server_name: settings.server_name.clone(), client_addr: None, - secure_conn: true, + secure_conn, alpns: vec![HTTP3_ALPN.to_string()], certificate_file: settings.certificate_file.clone(), private_key_file: settings.private_key_file.clone(), diff --git a/net/quinn/tests/certs/localhost.crt b/net/quinn/tests/certs/localhost.crt deleted file mode 100644 index 3f9d65f5..00000000 --- a/net/quinn/tests/certs/localhost.crt +++ /dev/null @@ -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----- diff --git a/net/quinn/tests/certs/localhost.key b/net/quinn/tests/certs/localhost.key deleted file mode 100644 index a640d5d7..00000000 --- a/net/quinn/tests/certs/localhost.key +++ /dev/null @@ -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----- diff --git a/net/quinn/tests/quinnwebtransport.rs b/net/quinn/tests/quinnwebtransport.rs index fc66b679..ad9c3cb8 100644 --- a/net/quinn/tests/quinnwebtransport.rs +++ b/net/quinn/tests/quinnwebtransport.rs @@ -9,7 +9,7 @@ use gst::prelude::*; use serial_test::serial; -use std::{path::PathBuf, thread}; +use std::thread; fn init() { use std::sync::Once; @@ -27,40 +27,19 @@ fn make_buffer(content: &[u8]) -> gst::Buffer { 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) { init(); let content = "Hello, world!\n".as_bytes(); - let (cert_path, key_path) = get_certificates_paths(); - let src_pipeline = format!( - "quinnwtclientsrc {} certificate-file={} caps=text/plain", - src_pipeline_props, cert_path + "quinnwtclientsrc {} secure-connection=false", + src_pipeline_props ); let sink_pipeline = format!( "quinnwtserversink {} server-name=localhost \ - address=127.0.0.1 certificate-file={} private-key-file={}", - sink_pipeline_props, cert_path, key_path + address=127.0.0.1 secure-connection=false", + sink_pipeline_props ); thread::spawn(move || {