diff --git a/girs/GstWebRTC-1.0.gir b/girs/GstWebRTC-1.0.gir index 76a9410d9a..acf46f8dc7 100644 --- a/girs/GstWebRTC-1.0.gir +++ b/girs/GstWebRTC-1.0.gir @@ -190,6 +190,97 @@ and/or use gtk-doc annotations. --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1482,37 +1573,67 @@ stops automatic ICE gathering. - + + The network port number used by the candidate (Since: 1.22) + A string that uniquely identifies the object that is being + monitored to produce this set of statistics (Since: 1.22) + The candidate type (Since: 1.22) + A string specifying the protocol (tcp or udp) used to transmit data +on the @port (Since: 1.22) + The candidate's priority, corresponding to RTCIceCandidate.priority (Since: 1.22) + For local candidates, the url property is the URL of the ICE server +from which the candidate was received (Since: 1.22) - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c index d781204fe7..7f806f6b4a 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c @@ -9256,6 +9256,11 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass) * "protocol" G_TYPE_STRING Either "udp" or "tcp". Based on the "transport" defined in RFC 5245 * "relay-protocol" G_TYPE_STRING protocol used by the endpoint to communicate with the TURN server. Only present for local candidates. Either "udp", "tcp" or "tls" * "url" G_TYPE_STRING URL of the ICE server from which the candidate was obtained. Only present for local candidates + * "foundation" G_TYPE_STRING ICE foundation as defined in RFC 5245 section 15.1 (Since: 1.28) + * "related-address" G_TYPE_STRING ICE rel-addr as defined in RFC 5245 section 15.1. Only set for server-reflexive, peer-reflexive and relay candidates (Since: 1.28) + * "related-port" G_TYPE_UINT ICE rel-port as defined in RFC 5245 section 15.1. Only set for serverreflexive, peer-reflexive and relay candidates (Since: 1.28) + * "username-fragment" G_TYPE_STRING ICE username fragment as defined in RFC 5245 section 7.1.2.3 (Since: 1.28) + * "tcp-type" G_TYPE_STRING ICE candidate TCP type as defined in RTCIceTcpCandidateType (Since: 1.28) * * RTCIceCandidatePairStats supported fields (https://www.w3.org/TR/webrtc-stats/#candidatepair-dict*) (Since: 1.22) * diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c index a6ecec0357..3fce94863c 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c @@ -615,6 +615,11 @@ _get_stats_from_ice_candidates (GstWebRTCBin * webrtc, long priority; DOMString url; DOMString relayProtocol; + DOMString foundation; + DOMString relatedAddress; + long relatedPort; + DOMString usernameFragment; + RTCIceTcpCandidateType tcpType; */ if (transport_id) @@ -630,6 +635,21 @@ _get_stats_from_ice_candidates (GstWebRTCBin * webrtc, NULL); if (can->url) gst_structure_set (stats, "url", G_TYPE_STRING, can->url, NULL); + if (can->ABI.abi.foundation) + gst_structure_set (stats, "foundation", G_TYPE_STRING, + can->ABI.abi.foundation, NULL); + if (can->ABI.abi.related_address) + gst_structure_set (stats, "related-address", G_TYPE_STRING, + can->ABI.abi.related_address, NULL); + if (can->ABI.abi.related_port) + gst_structure_set (stats, "related-port", G_TYPE_UINT, + can->ABI.abi.related_port, NULL); + if (can->ABI.abi.username_fragment) + gst_structure_set (stats, "username-fragment", G_TYPE_STRING, + can->ABI.abi.username_fragment, NULL); + if (can->ABI.abi.tcp_type) + gst_structure_set (stats, "tcp-type", G_TYPE_STRING, can->ABI.abi.tcp_type, + NULL); gst_structure_set (s, id, GST_TYPE_STRUCTURE, stats, NULL); gst_structure_free (stats); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c index f35652a27f..fc62cb9bb8 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c @@ -341,6 +341,9 @@ gst_webrtc_ice_candidate_stats_free (GstWebRTCICECandidateStats * stats) if (stats) { g_free (stats->ipaddr); g_free (stats->url); + g_free (stats->ABI.abi.foundation); + g_free (stats->ABI.abi.related_address); + g_free (stats->ABI.abi.username_fragment); } g_free (stats); @@ -364,6 +367,9 @@ gst_webrtc_ice_candidate_stats_copy (GstWebRTCICECandidateStats * stats) copy->ipaddr = g_strdup (stats->ipaddr); copy->url = g_strdup (stats->url); + copy->ABI.abi.foundation = g_strdup (stats->ABI.abi.foundation); + copy->ABI.abi.related_address = g_strdup (stats->ABI.abi.related_address); + copy->ABI.abi.username_fragment = g_strdup (stats->ABI.abi.username_fragment); return copy; } diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h index e1422f37a2..32e21fbc62 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h @@ -47,6 +47,30 @@ struct _GstWebRTCICE gpointer _gst_reserved[GST_PADDING]; }; +/** + * GstWebRTCICECandidateStats: + * @ipadd: A string containing the address of the candidate. This value may be + * an IPv4 address, an IPv6 address, or a fully-qualified domain name (Since: 1.22) + * @port: The network port number used by the candidate (Since: 1.22) + * @stream_id: A string that uniquely identifies the object that is being + * monitored to produce this set of statistics (Since: 1.22) + * @type: The candidate type (Since: 1.22) + * @proto: A string specifying the protocol (tcp or udp) used to transmit data + * on the @port (Since: 1.22) + * @replay_proto: A string identifying the protocol used by the endpoint for + * communicating with the TURN server; valid values are tcp, udp, and tls (Since: 1.22) + * @prio: The candidate's priority, corresponding to RTCIceCandidate.priority (Since: 1.22) + * @url: For local candidates, the url property is the URL of the ICE server + * from which the candidate was received (Since: 1.22) + * @foundation: The ICE foundation as defined in RFC5245 section 15.1 (Since: 1.28) + * @related_address: The ICE rel-addr defined in RFC5245 section 15.1 Only + * set for serverreflexive, peerreflexive and relay candidates. (Since: 1.28) + * @related_port: The ICE rel-addr defined in RFC5245 section 15.1. Only set + * for serverreflexive, peerreflexive and relay candidates. (Since: 1.28) + * @username_fragment: The ICE username fragment as defined in RFC5245 section 7.1.2.3 (Since: 1.28) + * @tcp_type: The ICE candidate TCP type, (Since: 1.28) + * + */ struct _GstWebRTCICECandidateStats { gchar *ipaddr; @@ -58,9 +82,99 @@ struct _GstWebRTCICECandidateStats guint prio; gchar *url; - gpointer _gst_reserved[GST_PADDING_LARGE]; + union { + struct { + gchar *foundation; + gchar *related_address; + guint related_port; + gchar *username_fragment; + const gchar *tcp_type; + } abi; + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; + } ABI; }; +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS(c) ((c)->ipaddr) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_PORT: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_PORT(c) ((c)->port) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID(c) ((c)->stream_id) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE(c) ((c)->type) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL(c) ((c)->proto) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL(c) ((c)->relay_proto) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY(c) ((c)->prio) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_URL: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_URL(c) ((c)->url) + +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION(c) ((c)->ABI.abi.foundation) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS(c) ((c)->ABI.abi.related_address) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT(c) ((c)->ABI.abi.related_port) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT(c) ((c)->ABI.abi.username_fragment) +/** + * GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE: + * + * Since: 1.28 + */ +#define GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE(c) ((c)->ABI.abi.tcp_type) + /** * GstWebRTCICEOnCandidateFunc: * @ice: The #GstWebRTCICE diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c index de6283e589..08251ba93f 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c @@ -551,6 +551,31 @@ gst_webrtc_nice_add_stream (GstWebRTCICE * ice, guint session_id) return item->stream; } +static void +_fill_candidate_credentials (NiceAgent * agent, NiceCandidate * candidate) +{ + + if (!candidate->username || !candidate->password) { + gboolean got_credentials; + gchar *ufrag, *password; + + got_credentials = + nice_agent_get_local_credentials (agent, candidate->stream_id, &ufrag, + &password); + g_warn_if_fail (got_credentials); + + if (!candidate->username) + candidate->username = ufrag; + else + g_free (ufrag); + + if (!candidate->password) + candidate->password = password; + else + g_free (password); + } +} + static void _on_new_candidate (NiceAgent * agent, NiceCandidate * candidate, GstWebRTCNice * ice) @@ -565,24 +590,7 @@ _on_new_candidate (NiceAgent * agent, NiceCandidate * candidate, return; } - if (!candidate->username || !candidate->password) { - gboolean got_credentials; - gchar *ufrag, *password; - - got_credentials = nice_agent_get_local_credentials (ice->priv->nice_agent, - candidate->stream_id, &ufrag, &password); - g_warn_if_fail (got_credentials); - - if (!candidate->username) - candidate->username = ufrag; - else - g_free (ufrag); - - if (!candidate->password) - candidate->password = password; - else - g_free (password); - } + _fill_candidate_credentials (agent, candidate); attr = nice_agent_generate_local_candidate_sdp (agent, candidate); @@ -1084,18 +1092,52 @@ _populate_candidate_stats (GstWebRTCNice * ice, NiceCandidate * cand, g_assert (cand != NULL); nice_address_to_string (&cand->addr, ipaddr); - stats->port = nice_address_get_port (&cand->addr); - stats->ipaddr = g_strdup (ipaddr); - stats->stream_id = stream->stream_id; - stats->type = nice_candidate_type_to_string (cand->type); - stats->prio = cand->priority; - stats->proto = + GST_WEBRTC_ICE_CANDIDATE_STATS_PORT (stats) = + nice_address_get_port (&cand->addr); + GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS (stats) = g_strdup (ipaddr); + GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID (stats) = stream->stream_id; + GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE (stats) = + nice_candidate_type_to_string (cand->type); + GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY (stats) = cand->priority; + GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL (stats) = cand->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "udp" : "tcp"; if (is_local) { - if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) - stats->relay_proto = gst_webrtc_nice_get_candidate_relay_protocol (ice->priv->turn_server); - stats->url = gst_webrtc_nice_get_candidate_server_url (ice, cand); + if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) { + NiceAddress relay_address; + nice_candidate_relay_address (cand, &relay_address); + + GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS (stats) = + nice_address_dup_string (&relay_address); + GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT (stats) = + nice_address_get_port (&relay_address); + + GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL (stats) = + gst_webrtc_nice_get_candidate_relay_protocol (ice->priv->turn_server); + } + GST_WEBRTC_ICE_CANDIDATE_STATS_URL (stats) = + gst_webrtc_nice_get_candidate_server_url (ice, cand); } + + GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION (stats) = + g_strdup (cand->foundation); + + switch (cand->transport) { + case NICE_CANDIDATE_TRANSPORT_UDP: + GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = NULL; + break; + case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE: + GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "active"; + break; + case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE: + GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "passive"; + break; + case NICE_CANDIDATE_TRANSPORT_TCP_SO: + GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "so"; + break; + }; + + GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT (stats) = + g_strdup (cand->username); } static void @@ -1166,6 +1208,9 @@ gst_webrtc_nice_get_selected_pair (GstWebRTCICE * ice, if (stream) { if (nice_agent_get_selected_pair (nice->priv->nice_agent, stream->stream_id, NICE_COMPONENT_TYPE_RTP, &local_cand, &remote_cand)) { + _fill_candidate_credentials (nice->priv->nice_agent, local_cand); + _fill_candidate_credentials (nice->priv->nice_agent, remote_cand); + *local_stats = g_new0 (GstWebRTCICECandidateStats, 1); _populate_candidate_stats (nice, local_cand, stream, *local_stats, TRUE); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h index 0bb01f3241..492981ae8a 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h @@ -70,11 +70,6 @@ typedef struct _GstWebRTCDTLSTransportClass GstWebRTCDTLSTransportClass; typedef struct _GstWebRTCICE GstWebRTCICE; typedef struct _GstWebRTCICEClass GstWebRTCICEClass; -/** - * GstWebRTCICECandidateStats: - * - * Since: 1.22 - */ typedef struct _GstWebRTCICECandidateStats GstWebRTCICECandidateStats; /** diff --git a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c index ca73b149b3..78a6149a55 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c @@ -1748,6 +1748,7 @@ validate_candidate_stats (const GstStructure * s, const GstStructure * stats) guint port; guint64 priority; gchar *address, *candidateType, *protocol; + gchar *foundation, *username_fragment; fail_unless (gst_structure_get (s, "address", G_TYPE_STRING, &address, NULL)); fail_unless (gst_structure_get (s, "port", G_TYPE_UINT, &port, NULL)); @@ -1759,9 +1760,39 @@ validate_candidate_stats (const GstStructure * s, const GstStructure * stats) fail_unless (strcmp (protocol, "udp") || strcmp (protocol, "tcp")); + fail_unless (gst_structure_get (s, "foundation", G_TYPE_STRING, &foundation, + NULL)); + fail_unless (gst_structure_get (s, "username-fragment", G_TYPE_STRING, + &username_fragment, NULL)); + + if (strcmp (candidateType, "host")) { + guint related_port; + gchar *related_address; + fail_unless (gst_structure_get (s, "related-address", G_TYPE_STRING, + &related_address, NULL)); + fail_unless (gst_structure_get (s, "related-port", G_TYPE_UINT, + &related_port, NULL)); + g_free (related_address); + } else { + fail_if (gst_structure_has_field (s, "related-address")); + fail_if (gst_structure_has_field (s, "related-port")); + } + + if (!strcmp (protocol, "tcp")) { + gchar *tcp_type; + fail_unless (gst_structure_get (s, "tcp-type", G_TYPE_STRING, &tcp_type, + NULL)); + fail_unless (strcmp (tcp_type, "so") || strcmp (tcp_type, "active") + || strcmp (tcp_type, "passive")); + g_free (tcp_type); + } else { + fail_if (gst_structure_has_field (s, "tcp-type")); + } g_free (address); g_free (candidateType); g_free (protocol); + g_free (foundation); + g_free (username_fragment); } static void