mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-22 18:16:28 +00:00
net/quinn: Add stats property for connection statistics
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1613>
This commit is contained in:
parent
2b35f009fb
commit
e00ebca63f
6 changed files with 132 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2704,6 +2704,7 @@ dependencies = [
|
||||||
"gstreamer-check",
|
"gstreamer-check",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"quinn",
|
"quinn",
|
||||||
|
"quinn-proto",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"rustls 0.23.10",
|
"rustls 0.23.10",
|
||||||
"rustls-pemfile 2.1.2",
|
"rustls-pemfile 2.1.2",
|
||||||
|
|
|
@ -4243,6 +4243,18 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"stats": {
|
||||||
|
"blurb": "Connection statistics",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "stats;",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "GstStructure",
|
||||||
|
"writable": false
|
||||||
|
},
|
||||||
"timeout": {
|
"timeout": {
|
||||||
"blurb": "Value in seconds to timeout QUIC endpoint requests (0 = No timeout).",
|
"blurb": "Value in seconds to timeout QUIC endpoint requests (0 = No timeout).",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
@ -4551,6 +4563,18 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"stats": {
|
||||||
|
"blurb": "Connection statistics",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "stats;",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "GstStructure",
|
||||||
|
"writable": false
|
||||||
|
},
|
||||||
"timeout": {
|
"timeout": {
|
||||||
"blurb": "Value in seconds to timeout QUIC endpoint requests (0 = No timeout).",
|
"blurb": "Value in seconds to timeout QUIC endpoint requests (0 = No timeout).",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -17,6 +17,7 @@ once_cell.workspace = true
|
||||||
tokio = { version = "1.36.0", default-features = false, features = ["time", "rt-multi-thread"] }
|
tokio = { version = "1.36.0", default-features = false, features = ["time", "rt-multi-thread"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
quinn = { version = "0.11.2", default-features = true, features = ["ring"]}
|
quinn = { version = "0.11.2", default-features = true, features = ["ring"]}
|
||||||
|
quinn-proto = "0.11.2"
|
||||||
rustls = { version = "0.23", default-features = false, features = ["ring", "std"]}
|
rustls = { version = "0.23", default-features = false, features = ["ring", "std"]}
|
||||||
rustls-pemfile = "2"
|
rustls-pemfile = "2"
|
||||||
rustls-pki-types = "1"
|
rustls-pki-types = "1"
|
||||||
|
|
|
@ -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, QuinnQuicEndpointConfig, WaitError,
|
client_endpoint, get_stats, make_socket_addr, server_endpoint, wait, 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;
|
||||||
|
@ -264,6 +264,11 @@ impl ObjectImpl for QuinnQuicSink {
|
||||||
.nick("Datagram Send Buffer Size")
|
.nick("Datagram Send Buffer Size")
|
||||||
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecBoxed::builder::<gst::Structure>("stats")
|
||||||
|
.nick("Connection statistics")
|
||||||
|
.blurb("Connection statistics")
|
||||||
|
.read_only()
|
||||||
|
.build()
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -399,6 +404,16 @@ impl ObjectImpl for QuinnQuicSink {
|
||||||
"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()
|
||||||
}
|
}
|
||||||
|
"stats" => {
|
||||||
|
let state = self.state.lock().unwrap();
|
||||||
|
match *state {
|
||||||
|
State::Started(ref state) => {
|
||||||
|
let connection = state.connection.clone();
|
||||||
|
get_stats(Some(connection)).to_value()
|
||||||
|
}
|
||||||
|
State::Stopped => get_stats(None).to_value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, QuinnQuicEndpointConfig,
|
client_endpoint, get_stats, make_socket_addr, server_endpoint, wait, Canceller,
|
||||||
WaitError, CONNECTION_CLOSE_CODE, CONNECTION_CLOSE_MSG,
|
QuinnQuicEndpointConfig, WaitError, CONNECTION_CLOSE_CODE, CONNECTION_CLOSE_MSG,
|
||||||
};
|
};
|
||||||
use crate::{common::*, utils};
|
use crate::{common::*, utils};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
@ -273,6 +273,11 @@ impl ObjectImpl for QuinnQuicSrc {
|
||||||
.nick("Datagram Send Buffer Size")
|
.nick("Datagram Send Buffer Size")
|
||||||
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
.blurb("Maximum number of outgoing application datagram bytes to buffer")
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecBoxed::builder::<gst::Structure>("stats")
|
||||||
|
.nick("Connection statistics")
|
||||||
|
.blurb("Connection statistics")
|
||||||
|
.read_only()
|
||||||
|
.build()
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -418,6 +423,16 @@ impl ObjectImpl for QuinnQuicSrc {
|
||||||
"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()
|
||||||
}
|
}
|
||||||
|
"stats" => {
|
||||||
|
let state = self.state.lock().unwrap();
|
||||||
|
match *state {
|
||||||
|
State::Started(ref state) => {
|
||||||
|
let connection = state.connection.clone();
|
||||||
|
get_stats(Some(connection)).to_value()
|
||||||
|
}
|
||||||
|
State::Stopped => get_stats(None).to_value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,10 @@ use gst::ErrorMessage;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use quinn::{
|
use quinn::{
|
||||||
crypto::rustls::QuicClientConfig, crypto::rustls::QuicServerConfig, default_runtime,
|
crypto::rustls::QuicClientConfig, crypto::rustls::QuicServerConfig, default_runtime,
|
||||||
ClientConfig, Endpoint, EndpointConfig, MtuDiscoveryConfig, ServerConfig, TransportConfig,
|
ClientConfig, Connection, Endpoint, EndpointConfig, MtuDiscoveryConfig, ServerConfig,
|
||||||
|
TransportConfig,
|
||||||
};
|
};
|
||||||
|
use quinn_proto::{ConnectionStats, FrameStats, PathStats, UdpStats};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
@ -416,3 +418,72 @@ pub fn client_endpoint(ep_config: &QuinnQuicEndpointConfig) -> Result<Endpoint,
|
||||||
|
|
||||||
Ok(endpoint)
|
Ok(endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_stats(connection: Option<Connection>) -> gst::Structure {
|
||||||
|
match connection {
|
||||||
|
Some(conn) => {
|
||||||
|
// See quinn_proto::ConnectionStats
|
||||||
|
let stats = conn.stats();
|
||||||
|
let udp_stats = |udp: UdpStats, name: String| -> gst::Structure {
|
||||||
|
gst::Structure::builder(name)
|
||||||
|
.field("datagrams", udp.datagrams)
|
||||||
|
.field("bytes", udp.bytes)
|
||||||
|
.field("ios", udp.ios)
|
||||||
|
.build()
|
||||||
|
};
|
||||||
|
let frame_stats = |frame: FrameStats, name: String| -> gst::Structure {
|
||||||
|
gst::Structure::builder(name)
|
||||||
|
.field("acks", frame.acks)
|
||||||
|
.field("ack-frequency", frame.ack_frequency)
|
||||||
|
.field("crypto", frame.crypto)
|
||||||
|
.field("connection-close", frame.connection_close)
|
||||||
|
.field("data-blocked", frame.data_blocked)
|
||||||
|
.field("datagram", frame.datagram)
|
||||||
|
.field("handshake-done", frame.handshake_done)
|
||||||
|
.field("immediate-ack", frame.immediate_ack)
|
||||||
|
.field("max-data", frame.max_data)
|
||||||
|
.field("max-stream-data", frame.max_stream_data)
|
||||||
|
.field("max-streams-bidi", frame.max_streams_bidi)
|
||||||
|
.field("max-streams-uni", frame.max_streams_uni)
|
||||||
|
.field("new-connection-id", frame.new_connection_id)
|
||||||
|
.field("new-token", frame.new_token)
|
||||||
|
.field("path-challenge", frame.path_challenge)
|
||||||
|
.field("path-response", frame.path_response)
|
||||||
|
.field("ping", frame.ping)
|
||||||
|
.field("reset-stream", frame.reset_stream)
|
||||||
|
.field("retire-connection-id", frame.retire_connection_id)
|
||||||
|
.field("stream-data-blocked", frame.stream_data_blocked)
|
||||||
|
.field("streams-blocked-bidi", frame.streams_blocked_bidi)
|
||||||
|
.field("streams-blocked-uni", frame.streams_blocked_uni)
|
||||||
|
.field("stop-sending", frame.stop_sending)
|
||||||
|
.field("stream", frame.stream)
|
||||||
|
.build()
|
||||||
|
};
|
||||||
|
let path_stats = gst::Structure::builder("path")
|
||||||
|
.field("cwnd", stats.path.cwnd)
|
||||||
|
.field("congestion-events", stats.path.congestion_events)
|
||||||
|
.field("lost-packets", stats.path.lost_packets)
|
||||||
|
.field("lost-bytes", stats.path.lost_bytes)
|
||||||
|
.field("sent-packets", stats.path.sent_packets)
|
||||||
|
.field("sent-plpmtud-probes", stats.path.sent_plpmtud_probes)
|
||||||
|
.field("lost-plpmtud-probes", stats.path.lost_plpmtud_probes)
|
||||||
|
.field("black-holes-detected", stats.path.black_holes_detected)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
gst::Structure::builder("stats")
|
||||||
|
.field("udp-tx", udp_stats(stats.udp_tx, "udp-tx".to_string()))
|
||||||
|
.field("udp-rx", udp_stats(stats.udp_rx, "udp-rx".to_string()))
|
||||||
|
.field("path", path_stats)
|
||||||
|
.field(
|
||||||
|
"frame-tx",
|
||||||
|
frame_stats(stats.frame_tx, "frame-tx".to_string()),
|
||||||
|
)
|
||||||
|
.field(
|
||||||
|
"frame-rx",
|
||||||
|
frame_stats(stats.frame_rx, "frame-rx".to_string()),
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
None => gst::Structure::new_empty("stats"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue