mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-18 05:45:14 +00:00
net/quinn: Allow setting some parameters from TransportConfig
As of now, we expose the below four properties from `TransportConfig`. - Initial MTU - Minimum MTU - Datagram receive buffer size - Datagram send buffer size Maximum UDP payload size from `EndpointConfig` and upper bound from `MtuDiscoveryConfig` are also exposed as properties. See the below documentation for further details. - https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html - https://docs.rs/quinn/latest/quinn/struct.MtuDiscoveryConfig.html - https://docs.rs/quinn/latest/quinn/struct.EndpointConfig.html While at it, also clean up passing function parameters to the functions in utils.rs. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1613>
This commit is contained in:
parent
bc5ed023e4
commit
cf7172248c
5 changed files with 558 additions and 201 deletions
|
@ -4071,6 +4071,48 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"datagram-receive-buffer-size": {
|
||||||
|
"blurb": "Maximum number of incoming application datagram bytes to buffer",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1250000",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"datagram-send-buffer-size": {
|
||||||
|
"blurb": "Maximum number of outgoing application datagram bytes to buffer",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1048576",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"initial-mtu": {
|
||||||
|
"blurb": "Initial value to be used as the maximum UDP payload size",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1200",
|
||||||
|
"max": "-1",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"keep-alive-interval": {
|
"keep-alive-interval": {
|
||||||
"blurb": "Keeps QUIC connection alive by periodically pinging the server. Value set in ms, 0 disables this feature",
|
"blurb": "Keeps QUIC connection alive by periodically pinging the server. Value set in ms, 0 disables this feature",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4085,6 +4127,34 @@
|
||||||
"type": "guint64",
|
"type": "guint64",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"max-udp-payload-size": {
|
||||||
|
"blurb": "Maximum UDP payload size accepted from peers (excluding UDP and IP overhead)",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "65527",
|
||||||
|
"max": "65527",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"min-mtu": {
|
||||||
|
"blurb": "Maximum UDP payload size guaranteed to be supported by the network, must be <= initial-mtu",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1200",
|
||||||
|
"max": "-1",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"port": {
|
"port": {
|
||||||
"blurb": "Port of the QUIC server e.g. 5000",
|
"blurb": "Port of the QUIC server e.g. 5000",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4187,6 +4257,20 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"upper-bound-mtu": {
|
||||||
|
"blurb": "Upper bound to the max UDP payload size that MTU discovery will search for",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1452",
|
||||||
|
"max": "65527",
|
||||||
|
"min": "1452",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"use-datagram": {
|
"use-datagram": {
|
||||||
"blurb": "Use datagram for lower latency, unreliable messaging",
|
"blurb": "Use datagram for lower latency, unreliable messaging",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4295,6 +4379,48 @@
|
||||||
"type": "gchararray",
|
"type": "gchararray",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"datagram-receive-buffer-size": {
|
||||||
|
"blurb": "Maximum number of incoming application datagram bytes to buffer",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1250000",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"datagram-send-buffer-size": {
|
||||||
|
"blurb": "Maximum number of outgoing application datagram bytes to buffer",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1048576",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"initial-mtu": {
|
||||||
|
"blurb": "Initial value to be used as the maximum UDP payload size",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1200",
|
||||||
|
"max": "-1",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"keep-alive-interval": {
|
"keep-alive-interval": {
|
||||||
"blurb": "Keeps QUIC connection alive by periodically pinging the server. Value set in ms, 0 disables this feature",
|
"blurb": "Keeps QUIC connection alive by periodically pinging the server. Value set in ms, 0 disables this feature",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4309,6 +4435,34 @@
|
||||||
"type": "guint64",
|
"type": "guint64",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"max-udp-payload-size": {
|
||||||
|
"blurb": "Maximum UDP payload size accepted from peers (excluding UDP and IP overhead)",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "65527",
|
||||||
|
"max": "65527",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"min-mtu": {
|
||||||
|
"blurb": "Maximum UDP payload size guaranteed to be supported by the network, must be <= initial-mtu",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1200",
|
||||||
|
"max": "-1",
|
||||||
|
"min": "1200",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"port": {
|
"port": {
|
||||||
"blurb": "Port of the QUIC server e.g. 5000",
|
"blurb": "Port of the QUIC server e.g. 5000",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4411,6 +4565,20 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"upper-bound-mtu": {
|
||||||
|
"blurb": "Upper bound to the max UDP payload size that MTU discovery will search for",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "1452",
|
||||||
|
"max": "65527",
|
||||||
|
"min": "1452",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"use-datagram": {
|
"use-datagram": {
|
||||||
"blurb": "Use datagram for lower latency, unreliable messaging",
|
"blurb": "Use datagram for lower latency, unreliable messaging",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -13,6 +13,13 @@ pub(crate) static DEFAULT_ADDR: &str = "127.0.0.1";
|
||||||
pub(crate) static DEFAULT_PORT: u16 = 5000;
|
pub(crate) static DEFAULT_PORT: u16 = 5000;
|
||||||
pub(crate) static DEFAULT_BIND_ADDR: &str = "0.0.0.0";
|
pub(crate) static DEFAULT_BIND_ADDR: &str = "0.0.0.0";
|
||||||
pub(crate) static DEFAULT_BIND_PORT: u16 = 0;
|
pub(crate) static DEFAULT_BIND_PORT: u16 = 0;
|
||||||
|
pub(crate) static DEFAULT_INITIAL_MTU: u16 = 1200;
|
||||||
|
pub(crate) static DEFAULT_MINIMUM_MTU: u16 = 1200;
|
||||||
|
pub(crate) static DEFAULT_UPPER_BOUND_MTU: u16 = 1452;
|
||||||
|
pub(crate) static DEFAULT_MAX_UPPER_BOUND_MTU: u16 = 65527;
|
||||||
|
pub(crate) static DEFAULT_UDP_PAYLOAD_SIZE: u16 = 1452;
|
||||||
|
pub(crate) static DEFAULT_MIN_UDP_PAYLOAD_SIZE: u16 = 1200;
|
||||||
|
pub(crate) static DEFAULT_MAX_UDP_PAYLOAD_SIZE: u16 = 65527;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For QUIC transport parameters
|
* For QUIC transport parameters
|
||||||
|
@ -36,3 +43,33 @@ pub enum QuinnQuicRole {
|
||||||
#[enum_value(name = "Client: Act as QUIC client.", nick = "client")]
|
#[enum_value(name = "Client: Act as QUIC client.", nick = "client")]
|
||||||
Client,
|
Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
|
pub struct QuinnQuicTransportConfig {
|
||||||
|
pub datagram_receive_buffer_size: usize,
|
||||||
|
pub datagram_send_buffer_size: usize,
|
||||||
|
pub initial_mtu: u16,
|
||||||
|
pub max_udp_payload_size: u16,
|
||||||
|
pub min_mtu: u16,
|
||||||
|
pub upper_bound_mtu: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for QuinnQuicTransportConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
// Copied from Quinn::TransportConfig defaults
|
||||||
|
const EXPECTED_RTT: u32 = 100; // ms
|
||||||
|
const MAX_STREAM_BANDWIDTH: u32 = 12500 * 1000; // bytes/s
|
||||||
|
// Window size needed to avoid pipeline
|
||||||
|
// stalls
|
||||||
|
const STREAM_RWND: u32 = MAX_STREAM_BANDWIDTH / 1000 * EXPECTED_RTT;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
datagram_receive_buffer_size: STREAM_RWND as usize,
|
||||||
|
datagram_send_buffer_size: 1024 * 1024,
|
||||||
|
initial_mtu: DEFAULT_INITIAL_MTU,
|
||||||
|
max_udp_payload_size: DEFAULT_MAX_UDP_PAYLOAD_SIZE,
|
||||||
|
min_mtu: DEFAULT_MINIMUM_MTU,
|
||||||
|
upper_bound_mtu: DEFAULT_UPPER_BOUND_MTU,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
client_endpoint, make_socket_addr, server_endpoint, wait, WaitError, CONNECTION_CLOSE_CODE,
|
client_endpoint, make_socket_addr, server_endpoint, wait, QuinnQuicEndpointConfig, WaitError,
|
||||||
CONNECTION_CLOSE_MSG,
|
CONNECTION_CLOSE_CODE, CONNECTION_CLOSE_MSG,
|
||||||
};
|
};
|
||||||
use crate::{common::*, utils};
|
use crate::{common::*, utils};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
@ -17,7 +17,7 @@ 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 once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use quinn::{Connection, SendStream};
|
use quinn::{Connection, SendStream, TransportConfig};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ enum State {
|
||||||
Started(Started),
|
Started(Started),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
struct Settings {
|
struct Settings {
|
||||||
bind_address: String,
|
bind_address: String,
|
||||||
bind_port: u16,
|
bind_port: u16,
|
||||||
|
@ -58,6 +58,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>,
|
||||||
|
transport_config: QuinnQuicTransportConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
|
@ -76,6 +77,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,
|
||||||
|
transport_config: QuinnQuicTransportConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,6 +230,40 @@ impl ObjectImpl for QuinnQuicSink {
|
||||||
.blurb("Use datagram for lower latency, unreliable messaging")
|
.blurb("Use datagram for lower latency, unreliable messaging")
|
||||||
.default_value(false)
|
.default_value(false)
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("initial-mtu")
|
||||||
|
.nick("Initial MTU")
|
||||||
|
.blurb("Initial value to be used as the maximum UDP payload size")
|
||||||
|
.minimum(DEFAULT_INITIAL_MTU.into())
|
||||||
|
.default_value(DEFAULT_INITIAL_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("min-mtu")
|
||||||
|
.nick("Minimum MTU")
|
||||||
|
.blurb("Maximum UDP payload size guaranteed to be supported by the network, must be <= initial-mtu")
|
||||||
|
.minimum(DEFAULT_MINIMUM_MTU.into())
|
||||||
|
.default_value(DEFAULT_MINIMUM_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("upper-bound-mtu")
|
||||||
|
.nick("Upper bound MTU")
|
||||||
|
.blurb("Upper bound to the max UDP payload size that MTU discovery will search for")
|
||||||
|
.minimum(DEFAULT_UPPER_BOUND_MTU.into())
|
||||||
|
.maximum(DEFAULT_MAX_UPPER_BOUND_MTU.into())
|
||||||
|
.default_value(DEFAULT_UPPER_BOUND_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("max-udp-payload-size")
|
||||||
|
.nick("Maximum UDP payload size")
|
||||||
|
.blurb("Maximum UDP payload size accepted from peers (excluding UDP and IP overhead)")
|
||||||
|
.minimum(DEFAULT_MIN_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.maximum(DEFAULT_MAX_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.default_value(DEFAULT_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt64::builder("datagram-receive-buffer-size")
|
||||||
|
.nick("Datagram Receiver Buffer Size")
|
||||||
|
.blurb("Maximum number of incoming application datagram bytes to buffer")
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt64::builder("datagram-send-buffer-size")
|
||||||
|
.nick("Datagram Send Buffer Size")
|
||||||
|
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -289,6 +325,32 @@ impl ObjectImpl for QuinnQuicSink {
|
||||||
"use-datagram" => {
|
"use-datagram" => {
|
||||||
settings.use_datagram = value.get().expect("type checked upstream");
|
settings.use_datagram = value.get().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
"initial-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.initial_mtu =
|
||||||
|
value.max(DEFAULT_INITIAL_MTU.into()) as u16;
|
||||||
|
}
|
||||||
|
"min-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
let initial_mtu = settings.transport_config.initial_mtu;
|
||||||
|
settings.transport_config.min_mtu = value.min(initial_mtu.into()) as u16;
|
||||||
|
}
|
||||||
|
"upper-bound-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.upper_bound_mtu = value as u16;
|
||||||
|
}
|
||||||
|
"max-udp-payload-size" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.max_udp_payload_size = value as u16;
|
||||||
|
}
|
||||||
|
"datagram-receive-buffer-size" => {
|
||||||
|
let value = value.get::<u64>().expect("type checked upstream");
|
||||||
|
settings.transport_config.datagram_receive_buffer_size = value as usize;
|
||||||
|
}
|
||||||
|
"datagram-send-buffer-size" => {
|
||||||
|
let value = value.get::<u64>().expect("type checked upstream");
|
||||||
|
settings.transport_config.datagram_send_buffer_size = value as usize;
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,6 +387,18 @@ impl ObjectImpl for QuinnQuicSink {
|
||||||
privkey.and_then(|file| file.to_str()).to_value()
|
privkey.and_then(|file| file.to_str()).to_value()
|
||||||
}
|
}
|
||||||
"use-datagram" => settings.use_datagram.to_value(),
|
"use-datagram" => settings.use_datagram.to_value(),
|
||||||
|
"initial-mtu" => (settings.transport_config.initial_mtu as u32).to_value(),
|
||||||
|
"min-mtu" => (settings.transport_config.min_mtu as u32).to_value(),
|
||||||
|
"upper-bound-mtu" => (settings.transport_config.upper_bound_mtu as u32).to_value(),
|
||||||
|
"max-udp-payload-size" => {
|
||||||
|
(settings.transport_config.max_udp_payload_size as u32).to_value()
|
||||||
|
}
|
||||||
|
"datagram-receive-buffer-size" => {
|
||||||
|
(settings.transport_config.datagram_receive_buffer_size as u64).to_value()
|
||||||
|
}
|
||||||
|
"datagram-send-buffer-size" => {
|
||||||
|
(settings.transport_config.datagram_send_buffer_size as u64).to_value()
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,7 +577,7 @@ impl QuinnQuicSink {
|
||||||
if src.len() > size {
|
if src.len() > size {
|
||||||
return Err(Some(gst::error_msg!(
|
return Err(Some(gst::error_msg!(
|
||||||
gst::ResourceError::Failed,
|
gst::ResourceError::Failed,
|
||||||
["Sending data failed, current max datagram size: {size}"]
|
["Sending data failed, current max datagram size: {size}, buffer size: {}", src.len()]
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,93 +619,80 @@ impl QuinnQuicSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init_connection(&self) -> Result<(Connection, Option<SendStream>), WaitError> {
|
async fn init_connection(&self) -> Result<(Connection, Option<SendStream>), WaitError> {
|
||||||
let client_addr;
|
let (role, use_datagram, endpoint_config) = {
|
||||||
let server_addr;
|
|
||||||
let server_name;
|
|
||||||
let alpns;
|
|
||||||
let role;
|
|
||||||
let use_datagram;
|
|
||||||
let keep_alive_interval;
|
|
||||||
let secure_conn;
|
|
||||||
let cert_file;
|
|
||||||
let private_key_file;
|
|
||||||
|
|
||||||
{
|
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
client_addr = make_socket_addr(
|
let client_addr = make_socket_addr(
|
||||||
format!("{}:{}", settings.bind_address, settings.bind_port).as_str(),
|
format!("{}:{}", settings.bind_address, settings.bind_port).as_str(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
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())?;
|
||||||
|
|
||||||
server_name = settings.server_name.clone();
|
let server_name = settings.server_name.clone();
|
||||||
alpns = settings.alpns.clone();
|
let alpns = settings.alpns.clone();
|
||||||
role = settings.role;
|
let role = settings.role;
|
||||||
use_datagram = settings.use_datagram;
|
let use_datagram = settings.use_datagram;
|
||||||
keep_alive_interval = settings.keep_alive_interval;
|
let keep_alive_interval = settings.keep_alive_interval;
|
||||||
secure_conn = settings.secure_conn;
|
let secure_conn = settings.secure_conn;
|
||||||
cert_file = settings.certificate_file.clone();
|
let certificate_file = settings.certificate_file.clone();
|
||||||
private_key_file = settings.private_key_file.clone();
|
let private_key_file = settings.private_key_file.clone();
|
||||||
}
|
let transport_config = settings.transport_config;
|
||||||
|
|
||||||
let connection;
|
(
|
||||||
|
role,
|
||||||
match role {
|
use_datagram,
|
||||||
QuinnQuicRole::Server => {
|
QuinnQuicEndpointConfig {
|
||||||
let endpoint = server_endpoint(
|
|
||||||
server_addr,
|
server_addr,
|
||||||
&server_name,
|
server_name,
|
||||||
|
client_addr,
|
||||||
secure_conn,
|
secure_conn,
|
||||||
alpns,
|
alpns,
|
||||||
cert_file,
|
certificate_file,
|
||||||
private_key_file,
|
private_key_file,
|
||||||
)
|
keep_alive_interval,
|
||||||
.map_err(|err| {
|
transport_config,
|
||||||
WaitError::FutureError(gst::error_msg!(
|
},
|
||||||
gst::ResourceError::Failed,
|
)
|
||||||
["Failed to configure endpoint: {}", err]
|
};
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
let endpoint = match role {
|
||||||
|
QuinnQuicRole::Server => server_endpoint(&endpoint_config).map_err(|err| {
|
||||||
|
WaitError::FutureError(gst::error_msg!(
|
||||||
|
gst::ResourceError::Failed,
|
||||||
|
["Failed to configure endpoint: {}", err]
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
QuinnQuicRole::Client => client_endpoint(&endpoint_config).map_err(|err| {
|
||||||
|
WaitError::FutureError(gst::error_msg!(
|
||||||
|
gst::ResourceError::Failed,
|
||||||
|
["Failed to configure endpoint: {}", err]
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection = match role {
|
||||||
|
QuinnQuicRole::Server => {
|
||||||
let incoming_conn = endpoint.accept().await.unwrap();
|
let incoming_conn = endpoint.accept().await.unwrap();
|
||||||
|
|
||||||
connection = incoming_conn.await.map_err(|err| {
|
incoming_conn.await.map_err(|err| {
|
||||||
WaitError::FutureError(gst::error_msg!(
|
WaitError::FutureError(gst::error_msg!(
|
||||||
gst::ResourceError::Failed,
|
gst::ResourceError::Failed,
|
||||||
["Connection error: {}", err]
|
["Connection error: {}", err]
|
||||||
))
|
))
|
||||||
})?;
|
})?
|
||||||
}
|
}
|
||||||
QuinnQuicRole::Client => {
|
QuinnQuicRole::Client => endpoint
|
||||||
let endpoint = client_endpoint(
|
.connect(endpoint_config.server_addr, &endpoint_config.server_name)
|
||||||
client_addr,
|
.unwrap()
|
||||||
secure_conn,
|
.await
|
||||||
alpns,
|
|
||||||
cert_file,
|
|
||||||
private_key_file,
|
|
||||||
keep_alive_interval,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
WaitError::FutureError(gst::error_msg!(
|
WaitError::FutureError(gst::error_msg!(
|
||||||
gst::ResourceError::Failed,
|
gst::ResourceError::Failed,
|
||||||
["Failed to configure endpoint: {}", err]
|
["Connection error: {}", err]
|
||||||
))
|
))
|
||||||
})?;
|
})?,
|
||||||
|
};
|
||||||
connection = endpoint
|
|
||||||
.connect(server_addr, &server_name)
|
|
||||||
.unwrap()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
WaitError::FutureError(gst::error_msg!(
|
|
||||||
gst::ResourceError::Failed,
|
|
||||||
["Connection error: {}", err]
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = if !use_datagram {
|
let stream = if !use_datagram {
|
||||||
let res = connection.open_uni().await.map_err(|err| {
|
let res = connection.open_uni().await.map_err(|err| {
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
client_endpoint, make_socket_addr, server_endpoint, wait, Canceller, WaitError,
|
client_endpoint, make_socket_addr, server_endpoint, wait, Canceller, QuinnQuicEndpointConfig,
|
||||||
CONNECTION_CLOSE_CODE, CONNECTION_CLOSE_MSG,
|
WaitError, CONNECTION_CLOSE_CODE, CONNECTION_CLOSE_MSG,
|
||||||
};
|
};
|
||||||
use crate::{common::*, utils};
|
use crate::{common::*, utils};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
@ -19,7 +19,7 @@ use gst_base::prelude::*;
|
||||||
use gst_base::subclass::base_src::CreateSuccess;
|
use gst_base::subclass::base_src::CreateSuccess;
|
||||||
use gst_base::subclass::prelude::*;
|
use gst_base::subclass::prelude::*;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use quinn::{Connection, ConnectionError, ReadError, RecvStream};
|
use quinn::{Connection, ConnectionError, ReadError, RecvStream, TransportConfig};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ enum State {
|
||||||
Started(Started),
|
Started(Started),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
struct Settings {
|
struct Settings {
|
||||||
address: String,
|
address: String,
|
||||||
port: u16,
|
port: u16,
|
||||||
|
@ -61,6 +61,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>,
|
||||||
|
transport_config: QuinnQuicTransportConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
|
@ -80,6 +81,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,
|
||||||
|
transport_config: QuinnQuicTransportConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,6 +239,40 @@ impl ObjectImpl for QuinnQuicSrc {
|
||||||
.blurb("Use datagram for lower latency, unreliable messaging")
|
.blurb("Use datagram for lower latency, unreliable messaging")
|
||||||
.default_value(false)
|
.default_value(false)
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("initial-mtu")
|
||||||
|
.nick("Initial MTU")
|
||||||
|
.blurb("Initial value to be used as the maximum UDP payload size")
|
||||||
|
.minimum(DEFAULT_INITIAL_MTU.into())
|
||||||
|
.default_value(DEFAULT_INITIAL_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("min-mtu")
|
||||||
|
.nick("Minimum MTU")
|
||||||
|
.blurb("Maximum UDP payload size guaranteed to be supported by the network, must be <= initial-mtu")
|
||||||
|
.minimum(DEFAULT_MINIMUM_MTU.into())
|
||||||
|
.default_value(DEFAULT_MINIMUM_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("upper-bound-mtu")
|
||||||
|
.nick("Upper bound MTU")
|
||||||
|
.blurb("Upper bound to the max UDP payload size that MTU discovery will search for")
|
||||||
|
.minimum(DEFAULT_UPPER_BOUND_MTU.into())
|
||||||
|
.maximum(DEFAULT_MAX_UPPER_BOUND_MTU.into())
|
||||||
|
.default_value(DEFAULT_UPPER_BOUND_MTU.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt::builder("max-udp-payload-size")
|
||||||
|
.nick("Maximum UDP payload size")
|
||||||
|
.blurb("Maximum UDP payload size accepted from peers (excluding UDP and IP overhead)")
|
||||||
|
.minimum(DEFAULT_MIN_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.maximum(DEFAULT_MAX_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.default_value(DEFAULT_UDP_PAYLOAD_SIZE.into())
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt64::builder("datagram-receive-buffer-size")
|
||||||
|
.nick("Datagram Receiver Buffer Size")
|
||||||
|
.blurb("Maximum number of incoming application datagram bytes to buffer")
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecUInt64::builder("datagram-send-buffer-size")
|
||||||
|
.nick("Datagram Send Buffer Size")
|
||||||
|
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -307,6 +343,32 @@ impl ObjectImpl for QuinnQuicSrc {
|
||||||
"use-datagram" => {
|
"use-datagram" => {
|
||||||
settings.use_datagram = value.get().expect("type checked upstream");
|
settings.use_datagram = value.get().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
"initial-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.initial_mtu =
|
||||||
|
value.max(DEFAULT_INITIAL_MTU.into()) as u16;
|
||||||
|
}
|
||||||
|
"min-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
let initial_mtu = settings.transport_config.initial_mtu;
|
||||||
|
settings.transport_config.min_mtu = value.min(initial_mtu.into()) as u16;
|
||||||
|
}
|
||||||
|
"upper-bound-mtu" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.upper_bound_mtu = value as u16;
|
||||||
|
}
|
||||||
|
"max-udp-payload-size" => {
|
||||||
|
let value = value.get::<u32>().expect("type checked upstream");
|
||||||
|
settings.transport_config.max_udp_payload_size = value as u16;
|
||||||
|
}
|
||||||
|
"datagram-receive-buffer-size" => {
|
||||||
|
let value = value.get::<u64>().expect("type checked upstream");
|
||||||
|
settings.transport_config.datagram_receive_buffer_size = value as usize;
|
||||||
|
}
|
||||||
|
"datagram-send-buffer-size" => {
|
||||||
|
let value = value.get::<u64>().expect("type checked upstream");
|
||||||
|
settings.transport_config.datagram_send_buffer_size = value as usize;
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,6 +406,18 @@ impl ObjectImpl for QuinnQuicSrc {
|
||||||
privkey.and_then(|file| file.to_str()).to_value()
|
privkey.and_then(|file| file.to_str()).to_value()
|
||||||
}
|
}
|
||||||
"use-datagram" => settings.use_datagram.to_value(),
|
"use-datagram" => settings.use_datagram.to_value(),
|
||||||
|
"initial-mtu" => (settings.transport_config.initial_mtu as u32).to_value(),
|
||||||
|
"min-mtu" => (settings.transport_config.min_mtu as u32).to_value(),
|
||||||
|
"upper-bound-mtu" => (settings.transport_config.upper_bound_mtu as u32).to_value(),
|
||||||
|
"max-udp-payload-size" => {
|
||||||
|
(settings.transport_config.max_udp_payload_size as u32).to_value()
|
||||||
|
}
|
||||||
|
"datagram-receive-buffer-size" => {
|
||||||
|
(settings.transport_config.datagram_receive_buffer_size as u64).to_value()
|
||||||
|
}
|
||||||
|
"datagram-send-buffer-size" => {
|
||||||
|
(settings.transport_config.datagram_send_buffer_size as u64).to_value()
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,93 +666,80 @@ impl QuinnQuicSrc {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init_connection(&self) -> Result<(Connection, Option<RecvStream>), WaitError> {
|
async fn init_connection(&self) -> Result<(Connection, Option<RecvStream>), WaitError> {
|
||||||
let server_addr;
|
let (role, use_datagram, endpoint_config) = {
|
||||||
let server_name;
|
|
||||||
let client_addr;
|
|
||||||
let alpns;
|
|
||||||
let role;
|
|
||||||
let use_datagram;
|
|
||||||
let keep_alive_interval;
|
|
||||||
let secure_conn;
|
|
||||||
let cert_file;
|
|
||||||
let private_key_file;
|
|
||||||
|
|
||||||
{
|
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
client_addr = make_socket_addr(
|
let client_addr = make_socket_addr(
|
||||||
format!("{}:{}", settings.bind_address, settings.bind_port).as_str(),
|
format!("{}:{}", settings.bind_address, settings.bind_port).as_str(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
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())?;
|
||||||
|
|
||||||
server_name = settings.server_name.clone();
|
let server_name = settings.server_name.clone();
|
||||||
alpns = settings.alpns.clone();
|
let alpns = settings.alpns.clone();
|
||||||
role = settings.role;
|
let role = settings.role;
|
||||||
use_datagram = settings.use_datagram;
|
let use_datagram = settings.use_datagram;
|
||||||
keep_alive_interval = settings.keep_alive_interval;
|
let keep_alive_interval = settings.keep_alive_interval;
|
||||||
secure_conn = settings.secure_conn;
|
let secure_conn = settings.secure_conn;
|
||||||
cert_file = settings.certificate_file.clone();
|
let certificate_file = settings.certificate_file.clone();
|
||||||
private_key_file = settings.private_key_file.clone();
|
let private_key_file = settings.private_key_file.clone();
|
||||||
}
|
let transport_config = settings.transport_config;
|
||||||
|
|
||||||
let connection;
|
(
|
||||||
|
role,
|
||||||
match role {
|
use_datagram,
|
||||||
QuinnQuicRole::Server => {
|
QuinnQuicEndpointConfig {
|
||||||
let endpoint = server_endpoint(
|
|
||||||
server_addr,
|
server_addr,
|
||||||
&server_name,
|
server_name,
|
||||||
|
client_addr,
|
||||||
secure_conn,
|
secure_conn,
|
||||||
alpns,
|
alpns,
|
||||||
cert_file,
|
certificate_file,
|
||||||
private_key_file,
|
private_key_file,
|
||||||
)
|
keep_alive_interval,
|
||||||
.map_err(|err| {
|
transport_config,
|
||||||
WaitError::FutureError(gst::error_msg!(
|
},
|
||||||
gst::ResourceError::Failed,
|
)
|
||||||
["Failed to configure endpoint: {}", err]
|
};
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
let endpoint = match role {
|
||||||
|
QuinnQuicRole::Server => server_endpoint(&endpoint_config).map_err(|err| {
|
||||||
|
WaitError::FutureError(gst::error_msg!(
|
||||||
|
gst::ResourceError::Failed,
|
||||||
|
["Failed to configure endpoint: {}", err]
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
QuinnQuicRole::Client => client_endpoint(&endpoint_config).map_err(|err| {
|
||||||
|
WaitError::FutureError(gst::error_msg!(
|
||||||
|
gst::ResourceError::Failed,
|
||||||
|
["Failed to configure endpoint: {}", err]
|
||||||
|
))
|
||||||
|
})?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection = match role {
|
||||||
|
QuinnQuicRole::Server => {
|
||||||
let incoming_conn = endpoint.accept().await.unwrap();
|
let incoming_conn = endpoint.accept().await.unwrap();
|
||||||
|
|
||||||
connection = incoming_conn.await.map_err(|err| {
|
incoming_conn.await.map_err(|err| {
|
||||||
WaitError::FutureError(gst::error_msg!(
|
WaitError::FutureError(gst::error_msg!(
|
||||||
gst::ResourceError::Failed,
|
gst::ResourceError::Failed,
|
||||||
["Connection error: {}", err]
|
["Connection error: {}", err]
|
||||||
))
|
))
|
||||||
})?;
|
})?
|
||||||
}
|
}
|
||||||
QuinnQuicRole::Client => {
|
QuinnQuicRole::Client => endpoint
|
||||||
let endpoint = client_endpoint(
|
.connect(endpoint_config.server_addr, &endpoint_config.server_name)
|
||||||
client_addr,
|
.unwrap()
|
||||||
secure_conn,
|
.await
|
||||||
alpns,
|
|
||||||
cert_file,
|
|
||||||
private_key_file,
|
|
||||||
keep_alive_interval,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
WaitError::FutureError(gst::error_msg!(
|
WaitError::FutureError(gst::error_msg!(
|
||||||
gst::ResourceError::Failed,
|
gst::ResourceError::Failed,
|
||||||
["Failed to configure endpoint: {}", err]
|
["Connection error: {}", err]
|
||||||
))
|
))
|
||||||
})?;
|
})?,
|
||||||
|
};
|
||||||
connection = endpoint
|
|
||||||
.connect(server_addr, &server_name)
|
|
||||||
.unwrap()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
WaitError::FutureError(gst::error_msg!(
|
|
||||||
gst::ResourceError::Failed,
|
|
||||||
["Connection error: {}", err]
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = if !use_datagram {
|
let stream = if !use_datagram {
|
||||||
let res = connection.accept_uni().await.map_err(|err| {
|
let res = connection.accept_uni().await.map_err(|err| {
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use crate::common::*;
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use gst::ErrorMessage;
|
use gst::ErrorMessage;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use quinn::{
|
use quinn::{
|
||||||
crypto::rustls::QuicClientConfig, crypto::rustls::QuicServerConfig, ClientConfig, Endpoint,
|
crypto::rustls::QuicClientConfig, crypto::rustls::QuicServerConfig, default_runtime,
|
||||||
ServerConfig, TransportConfig,
|
ClientConfig, Endpoint, EndpointConfig, MtuDiscoveryConfig, ServerConfig, TransportConfig,
|
||||||
};
|
};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -28,6 +29,19 @@ use tokio::runtime;
|
||||||
pub const CONNECTION_CLOSE_CODE: u32 = 0;
|
pub const CONNECTION_CLOSE_CODE: u32 = 0;
|
||||||
pub const CONNECTION_CLOSE_MSG: &str = "Stopped";
|
pub const CONNECTION_CLOSE_MSG: &str = "Stopped";
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct QuinnQuicEndpointConfig {
|
||||||
|
pub server_addr: SocketAddr,
|
||||||
|
pub server_name: String,
|
||||||
|
pub client_addr: SocketAddr,
|
||||||
|
pub secure_conn: bool,
|
||||||
|
pub alpns: Vec<String>,
|
||||||
|
pub certificate_file: Option<PathBuf>,
|
||||||
|
pub private_key_file: Option<PathBuf>,
|
||||||
|
pub keep_alive_interval: u64,
|
||||||
|
pub transport_config: QuinnQuicTransportConfig,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum WaitError {
|
pub enum WaitError {
|
||||||
#[error("Future aborted")]
|
#[error("Future aborted")]
|
||||||
|
@ -196,15 +210,12 @@ impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_client(
|
fn configure_client(ep_config: &QuinnQuicEndpointConfig) -> Result<ClientConfig, Box<dyn Error>> {
|
||||||
secure_conn: bool,
|
let mut crypto = if ep_config.secure_conn {
|
||||||
certificate_file: Option<PathBuf>,
|
let (certs, key) = read_certs_from_file(
|
||||||
private_key_file: Option<PathBuf>,
|
ep_config.certificate_file.clone(),
|
||||||
alpns: Vec<String>,
|
ep_config.private_key_file.clone(),
|
||||||
keep_alive_interval_ms: u64,
|
)?;
|
||||||
) -> Result<ClientConfig, Box<dyn Error>> {
|
|
||||||
let mut crypto = if secure_conn {
|
|
||||||
let (certs, key) = read_certs_from_file(certificate_file, private_key_file)?;
|
|
||||||
let mut cert_store = rustls::RootCertStore::empty();
|
let mut cert_store = rustls::RootCertStore::empty();
|
||||||
cert_store.add_parsable_certificates(certs.clone());
|
cert_store.add_parsable_certificates(certs.clone());
|
||||||
|
|
||||||
|
@ -218,20 +229,41 @@ fn configure_client(
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
};
|
};
|
||||||
|
|
||||||
let alpn_protocols: Vec<Vec<u8>> = alpns
|
let alpn_protocols: Vec<Vec<u8>> = ep_config
|
||||||
|
.alpns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.as_bytes().to_vec())
|
.map(|x| x.as_bytes().to_vec())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
crypto.alpn_protocols = alpn_protocols;
|
crypto.alpn_protocols = alpn_protocols;
|
||||||
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
|
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
|
||||||
|
|
||||||
let mut client_config = ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto)?));
|
let transport_config = {
|
||||||
|
let mtu_config = MtuDiscoveryConfig::default()
|
||||||
if keep_alive_interval_ms > 0 {
|
.upper_bound(ep_config.transport_config.upper_bound_mtu)
|
||||||
|
.to_owned();
|
||||||
let mut transport_config = TransportConfig::default();
|
let mut transport_config = TransportConfig::default();
|
||||||
transport_config.keep_alive_interval(Some(Duration::from_millis(keep_alive_interval_ms)));
|
|
||||||
client_config.transport_config(Arc::new(transport_config));
|
if ep_config.keep_alive_interval > 0 {
|
||||||
}
|
transport_config
|
||||||
|
.keep_alive_interval(Some(Duration::from_millis(ep_config.keep_alive_interval)));
|
||||||
|
}
|
||||||
|
transport_config.initial_mtu(ep_config.transport_config.initial_mtu);
|
||||||
|
transport_config.min_mtu(ep_config.transport_config.min_mtu);
|
||||||
|
transport_config.datagram_receive_buffer_size(Some(
|
||||||
|
ep_config.transport_config.datagram_receive_buffer_size,
|
||||||
|
));
|
||||||
|
transport_config
|
||||||
|
.datagram_send_buffer_size(ep_config.transport_config.datagram_send_buffer_size);
|
||||||
|
transport_config.max_concurrent_bidi_streams(0u32.into());
|
||||||
|
transport_config.max_concurrent_uni_streams(1u32.into());
|
||||||
|
transport_config.mtu_discovery_config(Some(mtu_config));
|
||||||
|
|
||||||
|
transport_config
|
||||||
|
};
|
||||||
|
|
||||||
|
let client_config = ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto)?))
|
||||||
|
.transport_config(Arc::new(transport_config))
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
Ok(client_config)
|
Ok(client_config)
|
||||||
}
|
}
|
||||||
|
@ -294,17 +326,16 @@ fn read_certs_from_file(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_server(
|
fn configure_server(
|
||||||
server_name: &str,
|
ep_config: &QuinnQuicEndpointConfig,
|
||||||
secure_conn: bool,
|
|
||||||
certificate_file: Option<PathBuf>,
|
|
||||||
private_key_file: Option<PathBuf>,
|
|
||||||
alpns: Vec<String>,
|
|
||||||
) -> Result<(ServerConfig, Vec<rustls_pki_types::CertificateDer>), Box<dyn Error>> {
|
) -> Result<(ServerConfig, Vec<rustls_pki_types::CertificateDer>), Box<dyn Error>> {
|
||||||
let (certs, key) = if secure_conn {
|
let (certs, key) = if ep_config.secure_conn {
|
||||||
read_certs_from_file(certificate_file, private_key_file)?
|
read_certs_from_file(
|
||||||
|
ep_config.certificate_file.clone(),
|
||||||
|
ep_config.private_key_file.clone(),
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
let rcgen::CertifiedKey { cert: _, key_pair } =
|
let rcgen::CertifiedKey { cert: _, key_pair } =
|
||||||
rcgen::generate_simple_self_signed(vec![server_name.into()]).unwrap();
|
rcgen::generate_simple_self_signed(vec![ep_config.server_name.clone()]).unwrap();
|
||||||
let cert_der = key_pair.serialize_der();
|
let cert_der = key_pair.serialize_der();
|
||||||
let priv_key = rustls_pki_types::PrivateKeyDer::try_from(cert_der.clone()).unwrap();
|
let priv_key = rustls_pki_types::PrivateKeyDer::try_from(cert_der.clone()).unwrap();
|
||||||
let cert_chain = vec![rustls_pki_types::CertificateDer::from(cert_der)];
|
let cert_chain = vec![rustls_pki_types::CertificateDer::from(cert_der)];
|
||||||
|
@ -312,7 +343,7 @@ fn configure_server(
|
||||||
(cert_chain, priv_key)
|
(cert_chain, priv_key)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut crypto = if secure_conn {
|
let mut crypto = if ep_config.secure_conn {
|
||||||
let mut cert_store = rustls::RootCertStore::empty();
|
let mut cert_store = rustls::RootCertStore::empty();
|
||||||
cert_store.add_parsable_certificates(certs.clone());
|
cert_store.add_parsable_certificates(certs.clone());
|
||||||
|
|
||||||
|
@ -328,59 +359,58 @@ fn configure_server(
|
||||||
.with_single_cert(certs.clone(), key)
|
.with_single_cert(certs.clone(), key)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let alpn_protocols: Vec<Vec<u8>> = alpns
|
let alpn_protocols: Vec<Vec<u8>> = ep_config
|
||||||
|
.alpns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.as_bytes().to_vec())
|
.map(|x| x.as_bytes().to_vec())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
crypto.alpn_protocols = alpn_protocols;
|
crypto.alpn_protocols = alpn_protocols;
|
||||||
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
|
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
|
||||||
let mut server_config =
|
|
||||||
ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(crypto)?));
|
|
||||||
|
|
||||||
Arc::get_mut(&mut server_config.transport)
|
let transport_config = {
|
||||||
.unwrap()
|
let mtu_config = MtuDiscoveryConfig::default()
|
||||||
.max_concurrent_bidi_streams(0_u8.into())
|
.upper_bound(ep_config.transport_config.upper_bound_mtu)
|
||||||
.max_concurrent_uni_streams(1_u8.into());
|
.to_owned();
|
||||||
|
let mut transport_config = TransportConfig::default();
|
||||||
|
|
||||||
|
transport_config.initial_mtu(ep_config.transport_config.initial_mtu);
|
||||||
|
transport_config.min_mtu(ep_config.transport_config.min_mtu);
|
||||||
|
transport_config.datagram_receive_buffer_size(Some(
|
||||||
|
ep_config.transport_config.datagram_receive_buffer_size,
|
||||||
|
));
|
||||||
|
transport_config
|
||||||
|
.datagram_send_buffer_size(ep_config.transport_config.datagram_send_buffer_size);
|
||||||
|
transport_config.max_concurrent_bidi_streams(0u32.into());
|
||||||
|
transport_config.max_concurrent_uni_streams(1u32.into());
|
||||||
|
transport_config.mtu_discovery_config(Some(mtu_config));
|
||||||
|
|
||||||
|
transport_config
|
||||||
|
};
|
||||||
|
|
||||||
|
let server_config = ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(crypto)?))
|
||||||
|
.transport_config(Arc::new(transport_config))
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
Ok((server_config, certs))
|
Ok((server_config, certs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn server_endpoint(
|
pub fn server_endpoint(ep_config: &QuinnQuicEndpointConfig) -> Result<Endpoint, Box<dyn Error>> {
|
||||||
server_addr: SocketAddr,
|
let (server_config, _) = configure_server(ep_config)?;
|
||||||
server_name: &str,
|
let socket = std::net::UdpSocket::bind(ep_config.server_addr)?;
|
||||||
secure_conn: bool,
|
let runtime = default_runtime()
|
||||||
alpns: Vec<String>,
|
.ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "No async runtime found"))?;
|
||||||
certificate_file: Option<PathBuf>,
|
let endpoint_config = EndpointConfig::default()
|
||||||
private_key_file: Option<PathBuf>,
|
.max_udp_payload_size(ep_config.transport_config.max_udp_payload_size)
|
||||||
) -> Result<Endpoint, Box<dyn Error>> {
|
.unwrap()
|
||||||
let (server_config, _) = configure_server(
|
.to_owned();
|
||||||
server_name,
|
let endpoint = Endpoint::new(endpoint_config, Some(server_config), socket, runtime)?;
|
||||||
secure_conn,
|
|
||||||
certificate_file,
|
|
||||||
private_key_file,
|
|
||||||
alpns,
|
|
||||||
)?;
|
|
||||||
let endpoint = Endpoint::server(server_config, server_addr)?;
|
|
||||||
|
|
||||||
Ok(endpoint)
|
Ok(endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_endpoint(
|
pub fn client_endpoint(ep_config: &QuinnQuicEndpointConfig) -> Result<Endpoint, Box<dyn Error>> {
|
||||||
client_addr: SocketAddr,
|
let client_cfg = configure_client(ep_config)?;
|
||||||
secure_conn: bool,
|
let mut endpoint = Endpoint::client(ep_config.client_addr)?;
|
||||||
alpns: Vec<String>,
|
|
||||||
certificate_file: Option<PathBuf>,
|
|
||||||
private_key_file: Option<PathBuf>,
|
|
||||||
keep_alive_interval_ms: u64,
|
|
||||||
) -> Result<Endpoint, Box<dyn Error>> {
|
|
||||||
let client_cfg = configure_client(
|
|
||||||
secure_conn,
|
|
||||||
certificate_file,
|
|
||||||
private_key_file,
|
|
||||||
alpns,
|
|
||||||
keep_alive_interval_ms,
|
|
||||||
)?;
|
|
||||||
let mut endpoint = Endpoint::client(client_addr)?;
|
|
||||||
|
|
||||||
endpoint.set_default_client_config(client_cfg);
|
endpoint.set_default_client_config(client_cfg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue