mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
webrtcbin: Start datachannel SCTP elements only after the DTLS connection is established
Otherwise we would start sending data to the DTLS connection before, and the DTLS elements consider this an error. Also RFC 8261 mentions: o A DTLS connection MUST be established before an SCTP association can be set up.
This commit is contained in:
parent
2798a80ebe
commit
0c39068c89
1 changed files with 75 additions and 4 deletions
|
@ -1784,6 +1784,66 @@ _on_sctp_state_notify (GstWebRTCSCTPTransport * sctp, GParamSpec * pspec,
|
|||
}
|
||||
}
|
||||
|
||||
/* Forward declaration so we can easily disconnect the signal handler */
|
||||
static void _on_sctp_notify_dtls_state (GstWebRTCDTLSTransport * transport,
|
||||
GParamSpec * pspec, GstWebRTCBin * webrtc);
|
||||
|
||||
static void
|
||||
_sctp_check_dtls_state_task (GstWebRTCBin * webrtc, gpointer unused)
|
||||
{
|
||||
TransportStream *stream;
|
||||
GstWebRTCDTLSTransport *transport;
|
||||
GstWebRTCDTLSTransportState dtls_state;
|
||||
GstWebRTCSCTPTransport *sctp_transport;
|
||||
|
||||
stream = webrtc->priv->data_channel_transport;
|
||||
transport = stream->transport;
|
||||
|
||||
g_object_get (transport, "state", &dtls_state, NULL);
|
||||
/* Not connected yet so just return */
|
||||
if (dtls_state != GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED) {
|
||||
GST_DEBUG_OBJECT (webrtc,
|
||||
"Data channel DTLS connection is not ready yet: %d", dtls_state);
|
||||
return;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (webrtc, "Data channel DTLS connection is now ready");
|
||||
sctp_transport = webrtc->priv->sctp_transport;
|
||||
|
||||
/* Not locked state anymore so this was already taken care of before */
|
||||
if (!gst_element_is_locked_state (sctp_transport->sctpdec))
|
||||
return;
|
||||
|
||||
/* Start up the SCTP elements now that the DTLS connection is established */
|
||||
gst_element_set_locked_state (sctp_transport->sctpdec, FALSE);
|
||||
gst_element_set_locked_state (sctp_transport->sctpenc, FALSE);
|
||||
|
||||
gst_element_sync_state_with_parent (GST_ELEMENT (sctp_transport->sctpdec));
|
||||
gst_element_sync_state_with_parent (GST_ELEMENT (sctp_transport->sctpenc));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (transport, _on_sctp_notify_dtls_state,
|
||||
webrtc);
|
||||
}
|
||||
|
||||
static void
|
||||
_on_sctp_notify_dtls_state (GstWebRTCDTLSTransport * transport,
|
||||
GParamSpec * pspec, GstWebRTCBin * webrtc)
|
||||
{
|
||||
GstWebRTCDTLSTransportState dtls_state;
|
||||
|
||||
g_object_get (transport, "state", &dtls_state, NULL);
|
||||
|
||||
GST_TRACE_OBJECT (webrtc, "Data channel DTLS state changed to %d",
|
||||
dtls_state);
|
||||
|
||||
/* Connected now, so schedule a task to update the state of the SCTP
|
||||
* elements */
|
||||
if (dtls_state == GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED) {
|
||||
gst_webrtc_bin_enqueue_task (webrtc,
|
||||
(GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static TransportStream *
|
||||
_get_or_create_data_channel_transports (GstWebRTCBin * webrtc, guint session_id)
|
||||
{
|
||||
|
@ -1811,6 +1871,11 @@ _get_or_create_data_channel_transports (GstWebRTCBin * webrtc, guint session_id)
|
|||
g_object_ref (webrtc->priv->data_channel_transport->transport);
|
||||
sctp_transport->webrtcbin = webrtc;
|
||||
|
||||
/* Don't automatically start SCTP elements as part of webrtcbin. We
|
||||
* need to delay this until the DTLS transport is fully connected! */
|
||||
gst_element_set_locked_state (sctp_transport->sctpdec, TRUE);
|
||||
gst_element_set_locked_state (sctp_transport->sctpenc, TRUE);
|
||||
|
||||
gst_bin_add (GST_BIN (webrtc), sctp_transport->sctpdec);
|
||||
gst_bin_add (GST_BIN (webrtc), sctp_transport->sctpenc);
|
||||
}
|
||||
|
@ -1843,10 +1908,16 @@ _get_or_create_data_channel_transports (GstWebRTCBin * webrtc, guint session_id)
|
|||
gst_element_sync_state_with_parent (GST_ELEMENT (stream->receive_bin));
|
||||
|
||||
if (!webrtc->priv->sctp_transport) {
|
||||
gst_element_sync_state_with_parent (GST_ELEMENT
|
||||
(sctp_transport->sctpdec));
|
||||
gst_element_sync_state_with_parent (GST_ELEMENT
|
||||
(sctp_transport->sctpenc));
|
||||
/* Connect to the notify::state signal to get notified when the DTLS
|
||||
* connection is established. Only then can we start the SCTP elements */
|
||||
g_signal_connect (stream->transport, "notify::state",
|
||||
G_CALLBACK (_on_sctp_notify_dtls_state), webrtc);
|
||||
|
||||
/* As this would be racy otherwise, also schedule a task that checks the
|
||||
* current state of the connection already without getting the signal
|
||||
* called */
|
||||
gst_webrtc_bin_enqueue_task (webrtc,
|
||||
(GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL);
|
||||
}
|
||||
|
||||
webrtc->priv->sctp_transport = sctp_transport;
|
||||
|
|
Loading…
Reference in a new issue