Sanchayan Maity 2024-02-14 13:08:37 +05:30
parent 75b25d011f
commit ce930eab5f
3 changed files with 85 additions and 32 deletions

View file

@ -22,6 +22,14 @@ use std::sync::Mutex;
static DEFAULT_SERVER_NAME: &str = "localhost"; static DEFAULT_SERVER_NAME: &str = "localhost";
static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000"; static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000";
static DEFAULT_CLIENT_ADDR: &str = "127.0.0.1:5001"; static DEFAULT_CLIENT_ADDR: &str = "127.0.0.1:5001";
/*
* For QUIC transport parameters
* <https://datatracker.ietf.org/doc/html/rfc9000#section-7.4>
*
* A HTTP client might specify "http/1.1" and/or "h2" or "h3".
* Other well-known values are listed in the at IANA registry at
* <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>.
*/
const DEFAULT_ALPN: &str = "h3"; const DEFAULT_ALPN: &str = "h3";
const DEFAULT_TIMEOUT: u32 = 15; const DEFAULT_TIMEOUT: u32 = 15;
const DEFAULT_SECURE_CONNECTION: bool = true; const DEFAULT_SECURE_CONNECTION: bool = true;
@ -47,7 +55,7 @@ struct Settings {
client_address: SocketAddr, client_address: SocketAddr,
server_address: SocketAddr, server_address: SocketAddr,
server_name: String, server_name: String,
alpn: String, alpns: Vec<String>,
timeout: u32, timeout: u32,
secure_conn: bool, secure_conn: bool,
use_datagram: bool, use_datagram: bool,
@ -59,7 +67,7 @@ impl Default for Settings {
client_address: DEFAULT_CLIENT_ADDR.parse::<SocketAddr>().unwrap(), client_address: DEFAULT_CLIENT_ADDR.parse::<SocketAddr>().unwrap(),
server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(), server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(),
server_name: DEFAULT_SERVER_NAME.to_string(), server_name: DEFAULT_SERVER_NAME.to_string(),
alpn: DEFAULT_ALPN.to_string(), alpns: vec![DEFAULT_ALPN.to_string()],
timeout: DEFAULT_TIMEOUT, timeout: DEFAULT_TIMEOUT,
secure_conn: DEFAULT_SECURE_CONNECTION, secure_conn: DEFAULT_SECURE_CONNECTION,
use_datagram: false, use_datagram: false,
@ -135,9 +143,10 @@ impl ObjectImpl for QuicSink {
.nick("QUIC client address") .nick("QUIC client address")
.blurb("Address to be used by this QUIC client e.g. 127.0.0.1:5001") .blurb("Address to be used by this QUIC client e.g. 127.0.0.1:5001")
.build(), .build(),
glib::ParamSpecString::builder("alpn") gst::ParamSpecArray::builder("alpn-protocols")
.nick("QUIC ALPN value") .nick("QUIC ALPN values")
.blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) value") .blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) values")
.element_spec(&glib::ParamSpecString::builder("alpn-protocol").build())
.build(), .build(),
glib::ParamSpecUInt::builder("timeout") glib::ParamSpecUInt::builder("timeout")
.nick("Timeout") .nick("Timeout")
@ -198,9 +207,19 @@ impl ObjectImpl for QuicSink {
), ),
} }
} }
"alpn" => { "alpn-protocols" => {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
settings.alpn = value.get::<String>().expect("type checked upstream"); settings.alpns = value
.get::<gst::ArrayRef>()
.expect("type checked upstream")
.as_slice()
.iter()
.map(|alpn| {
alpn.get::<&str>()
.expect("type checked upstream")
.to_string()
})
.collect::<Vec<_>>();
} }
"timeout" => { "timeout" => {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
@ -232,9 +251,10 @@ impl ObjectImpl for QuicSink {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
settings.client_address.to_string().to_value() settings.client_address.to_string().to_value()
} }
"alpn" => { "alpn-protocols" => {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
settings.alpn.to_value() let alpns = settings.alpns.iter().map(|v| v.as_str());
gst::Array::new(alpns).to_value()
} }
"timeout" => { "timeout" => {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
@ -439,7 +459,7 @@ impl QuicSink {
let client_addr; let client_addr;
let server_addr; let server_addr;
let server_name; let server_name;
let alpn; let alpns;
let use_datagram; let use_datagram;
let secure_conn; let secure_conn;
@ -448,12 +468,12 @@ impl QuicSink {
client_addr = settings.client_address; client_addr = settings.client_address;
server_addr = settings.server_address; server_addr = settings.server_address;
server_name = settings.server_name.clone(); server_name = settings.server_name.clone();
alpn = settings.alpn.clone(); alpns = settings.alpns.clone();
use_datagram = settings.use_datagram; use_datagram = settings.use_datagram;
secure_conn = settings.secure_conn; secure_conn = settings.secure_conn;
} }
let endpoint = client_endpoint(client_addr, secure_conn, &alpn).map_err(|err| { let endpoint = client_endpoint(client_addr, secure_conn, alpns).map_err(|err| {
WaitError::FutureError(gst::error_msg!( WaitError::FutureError(gst::error_msg!(
gst::ResourceError::Failed, gst::ResourceError::Failed,
["Failed to configure endpoint: {}", err] ["Failed to configure endpoint: {}", err]

View file

@ -25,6 +25,14 @@ use std::sync::Mutex;
static DEFAULT_SERVER_NAME: &str = "localhost"; static DEFAULT_SERVER_NAME: &str = "localhost";
static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000"; static DEFAULT_SERVER_ADDR: &str = "127.0.0.1:5000";
/*
* For QUIC transport parameters
* <https://datatracker.ietf.org/doc/html/rfc9000#section-7.4>
*
* A HTTP client might specify "http/1.1" and/or "h2" or "h3".
* Other well-known values are listed in the at IANA registry at
* <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>.
*/
const DEFAULT_ALPN: &str = "h3"; const DEFAULT_ALPN: &str = "h3";
const DEFAULT_TIMEOUT: u32 = 15; const DEFAULT_TIMEOUT: u32 = 15;
const DEFAULT_PRIVATE_KEY_TYPE: QuicPrivateKeyType = QuicPrivateKeyType::Pkcs8; const DEFAULT_PRIVATE_KEY_TYPE: QuicPrivateKeyType = QuicPrivateKeyType::Pkcs8;
@ -54,7 +62,7 @@ enum State {
struct Settings { struct Settings {
server_address: SocketAddr, server_address: SocketAddr,
server_name: String, server_name: String,
alpn: String, alpns: Vec<String>,
timeout: u32, timeout: u32,
secure_conn: bool, secure_conn: bool,
caps: gst::Caps, caps: gst::Caps,
@ -68,7 +76,7 @@ impl Default for Settings {
Settings { Settings {
server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(), server_address: DEFAULT_SERVER_ADDR.parse::<SocketAddr>().unwrap(),
server_name: DEFAULT_SERVER_NAME.to_string(), server_name: DEFAULT_SERVER_NAME.to_string(),
alpn: DEFAULT_ALPN.to_string(), alpns: vec![DEFAULT_ALPN.to_string()],
timeout: DEFAULT_TIMEOUT, timeout: DEFAULT_TIMEOUT,
secure_conn: DEFAULT_SECURE_CONNECTION, secure_conn: DEFAULT_SECURE_CONNECTION,
caps: gst::Caps::new_any(), caps: gst::Caps::new_any(),
@ -170,9 +178,10 @@ impl ObjectImpl for QuicSrc {
.nick("QUIC server address") .nick("QUIC server address")
.blurb("Address of the QUIC server to connect to e.g. 127.0.0.1:5000") .blurb("Address of the QUIC server to connect to e.g. 127.0.0.1:5000")
.build(), .build(),
glib::ParamSpecString::builder("alpn") gst::ParamSpecArray::builder("alpn-protocols")
.nick("QUIC ALPN value") .nick("QUIC ALPN values")
.blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) value") .blurb("QUIC connection Application-Layer Protocol Negotiation (ALPN) values")
.element_spec(&glib::ParamSpecString::builder("alpn-protocol").build())
.build(), .build(),
glib::ParamSpecUInt::builder("timeout") glib::ParamSpecUInt::builder("timeout")
.nick("Timeout") .nick("Timeout")
@ -230,9 +239,19 @@ impl ObjectImpl for QuicSrc {
), ),
} }
} }
"alpn" => { "alpn-protocols" => {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
settings.alpn = value.get::<String>().expect("type checked upstream"); settings.alpns = value
.get::<gst::ArrayRef>()
.expect("type checked upstream")
.as_slice()
.iter()
.map(|alpn| {
alpn.get::<&str>()
.expect("type checked upstream")
.to_string()
})
.collect::<Vec<String>>()
} }
"caps" => { "caps" => {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
@ -281,9 +300,10 @@ impl ObjectImpl for QuicSrc {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
settings.server_address.to_string().to_value() settings.server_address.to_string().to_value()
} }
"alpn" => { "alpn-protocols" => {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
settings.alpn.to_value() let alpns = settings.alpns.iter().map(|v| v.as_str());
gst::Array::new(alpns).to_value()
} }
"caps" => { "caps" => {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
@ -535,7 +555,7 @@ impl QuicSrc {
async fn wait_for_connection(&self) -> Result<(Connection, Option<RecvStream>), WaitError> { async fn wait_for_connection(&self) -> Result<(Connection, Option<RecvStream>), WaitError> {
let server_addr; let server_addr;
let server_name; let server_name;
let alpn; let alpns;
let use_datagram; let use_datagram;
let secure_conn; let secure_conn;
let cert_path; let cert_path;
@ -545,7 +565,7 @@ impl QuicSrc {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
server_addr = settings.server_address; server_addr = settings.server_address;
server_name = settings.server_name.clone(); server_name = settings.server_name.clone();
alpn = settings.alpn.clone(); alpns = settings.alpns.clone();
use_datagram = settings.use_datagram; use_datagram = settings.use_datagram;
secure_conn = settings.secure_conn; secure_conn = settings.secure_conn;
cert_path = settings.certificate_path.clone(); cert_path = settings.certificate_path.clone();
@ -556,7 +576,7 @@ impl QuicSrc {
server_addr, server_addr,
&server_name, &server_name,
secure_conn, secure_conn,
&alpn, alpns,
cert_path, cert_path,
private_key_type, private_key_type,
) )

View file

@ -131,7 +131,7 @@ impl rustls::client::ServerCertVerifier for SkipServerVerification {
} }
} }
fn configure_client(secure_conn: bool, alpn: &str) -> Result<ClientConfig, Box<dyn Error>> { fn configure_client(secure_conn: bool, alpns: Vec<String>) -> Result<ClientConfig, Box<dyn Error>> {
if secure_conn { if secure_conn {
Ok(ClientConfig::with_native_roots()) Ok(ClientConfig::with_native_roots())
} else { } else {
@ -139,7 +139,11 @@ fn configure_client(secure_conn: bool, alpn: &str) -> Result<ClientConfig, Box<d
.with_safe_defaults() .with_safe_defaults()
.with_custom_certificate_verifier(SkipServerVerification::new()) .with_custom_certificate_verifier(SkipServerVerification::new())
.with_no_client_auth(); .with_no_client_auth();
crypto.alpn_protocols = vec![alpn.as_bytes().to_vec()]; let alpn_protocols: Vec<Vec<u8>> = alpns
.iter()
.map(|x| x.as_bytes().to_vec())
.collect::<Vec<_>>();
crypto.alpn_protocols = alpn_protocols;
Ok(ClientConfig::new(Arc::new(crypto))) Ok(ClientConfig::new(Arc::new(crypto)))
} }
@ -202,8 +206,8 @@ fn read_certs_from_file(
fn configure_server( fn configure_server(
server_name: &str, server_name: &str,
secure_conn: bool, secure_conn: bool,
alpn: &str,
certificate_path: Option<PathBuf>, certificate_path: Option<PathBuf>,
alpns: Vec<String>,
private_key_type: QuicPrivateKeyType, private_key_type: QuicPrivateKeyType,
) -> Result<(ServerConfig, Vec<rustls::Certificate>), Box<dyn Error>> { ) -> Result<(ServerConfig, Vec<rustls::Certificate>), Box<dyn Error>> {
let (cert, key) = if secure_conn { let (cert, key) = if secure_conn {
@ -225,7 +229,11 @@ fn configure_server(
.unwrap() .unwrap()
.with_no_client_auth() .with_no_client_auth()
.with_single_cert(cert.clone(), key)?; .with_single_cert(cert.clone(), key)?;
crypto.alpn_protocols = vec![alpn.as_bytes().to_vec()]; let alpn_protocols: Vec<Vec<u8>> = alpns
.iter()
.map(|x| x.as_bytes().to_vec())
.collect::<Vec<_>>();
crypto.alpn_protocols = alpn_protocols;
let mut server_config = ServerConfig::with_crypto(Arc::new(crypto)); let mut server_config = ServerConfig::with_crypto(Arc::new(crypto));
Arc::get_mut(&mut server_config.transport) Arc::get_mut(&mut server_config.transport)
@ -240,12 +248,17 @@ pub fn server_endpoint(
server_addr: SocketAddr, server_addr: SocketAddr,
server_name: &str, server_name: &str,
secure_conn: bool, secure_conn: bool,
alpn: &str, alpns: Vec<String>,
certificate_path: Option<PathBuf>, certificate_path: Option<PathBuf>,
private_key_type: QuicPrivateKeyType, private_key_type: QuicPrivateKeyType,
) -> Result<Endpoint, Box<dyn Error>> { ) -> Result<Endpoint, Box<dyn Error>> {
let (server_config, _) = let (server_config, _) = configure_server(
configure_server(server_name, secure_conn, alpn, certificate_path, private_key_type)?; server_name,
secure_conn,
certificate_path,
alpns,
private_key_type,
)?;
let endpoint = Endpoint::server(server_config, server_addr)?; let endpoint = Endpoint::server(server_config, server_addr)?;
Ok(endpoint) Ok(endpoint)
@ -254,7 +267,7 @@ pub fn server_endpoint(
pub fn client_endpoint( pub fn client_endpoint(
client_addr: SocketAddr, client_addr: SocketAddr,
secure_conn: bool, secure_conn: bool,
alpn: &str, alpn: Vec<String>,
) -> Result<Endpoint, Box<dyn Error>> { ) -> Result<Endpoint, Box<dyn Error>> {
let client_cfg = configure_client(secure_conn, alpn)?; let client_cfg = configure_client(secure_conn, alpn)?;
let mut endpoint = Endpoint::client(client_addr)?; let mut endpoint = Endpoint::client(client_addr)?;