summaryrefslogtreecommitdiff
path: root/ext/webrtc/gstwebrtcbin.c
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.com>2021-03-26 18:15:50 -0400
committerOlivier CrĂȘte <olivier.crete@collabora.com>2021-04-12 17:55:07 -0400
commit08dd305a205060ed50182f9c903d493d559633eb (patch)
tree931bc5e5bd073d9126ccc7784251a43de267e800 /ext/webrtc/gstwebrtcbin.c
parented1f0f33a236a3cc83f522b628d259b14d05cc9c (diff)
downloadgstreamer-plugins-bad-08dd305a205060ed50182f9c903d493d559633eb.tar.gz
webrtcbin: Enforce m-line restrictions when creating offer
First fail the offer creation if the mid of an existing offer doesn't match a forced m-mline. Then, for all newly added mlines, first look for a transceiver that forces this m-line, then add a "floating" one, then the data channel. And repeat this until we're out of transceivers. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2104>
Diffstat (limited to 'ext/webrtc/gstwebrtcbin.c')
-rw-r--r--ext/webrtc/gstwebrtcbin.c119
1 files changed, 93 insertions, 26 deletions
diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c
index a554a7bdb..ad4073c66 100644
--- a/ext/webrtc/gstwebrtcbin.c
+++ b/ext/webrtc/gstwebrtcbin.c
@@ -470,6 +470,9 @@ match_for_mid (GstWebRTCRTPTransceiver * trans, const gchar * mid)
static gboolean
transceiver_match_for_mline (GstWebRTCRTPTransceiver * trans, guint * mline)
{
+ if (trans->stopped)
+ return FALSE;
+
return trans->mline == *mline;
}
@@ -2866,9 +2869,20 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
if (trans->mid && g_strcmp0 (trans->mid, last_mid) == 0) {
GstSDPMedia *media;
const gchar *mid;
+ WebRTCTransceiver *wtrans = WEBRTC_TRANSCEIVER (trans);
g_assert (!g_list_find (seen_transceivers, trans));
+ if (wtrans->mline_locked && trans->mline != media_idx) {
+ g_set_error (error, GST_WEBRTC_BIN_ERROR,
+ GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION,
+ "Previous negotiatied transceiver %"
+ GST_PTR_FORMAT " with mid %s was in mline %d but transceiver"
+ " has locked mline %u", trans, trans->mid, media_idx,
+ trans->mline);
+ goto cancel_offer;
+ }
+
GST_LOG_OBJECT (webrtc, "using previous negotiatied transceiver %"
GST_PTR_FORMAT " with mid %s into media index %u", trans,
trans->mid, media_idx);
@@ -2885,7 +2899,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
g_set_error (error, GST_WEBRTC_BIN_ERROR,
GST_WEBRTC_BIN_ERROR_FAILED,
"Duplicate mid %s when creating offer", mid);
- goto duplicate_mid;
+ goto cancel_offer;
}
g_hash_table_insert (all_mids, g_strdup (mid), NULL);
@@ -2929,27 +2943,94 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
if (g_hash_table_contains (all_mids, trans->mid)) {
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_FAILED,
"Duplicate mid %s when creating offer", trans->mid);
- goto duplicate_mid;
+ goto cancel_offer;
}
g_hash_table_insert (all_mids, g_strdup (trans->mid), NULL);
}
}
+
/* add any extra streams */
- for (i = 0; i < webrtc->priv->transceivers->len; i++) {
- GstWebRTCRTPTransceiver *trans;
+ for (;;) {
+ GstWebRTCRTPTransceiver *trans = NULL;
GstSDPMedia media = { 0, };
- trans = g_ptr_array_index (webrtc->priv->transceivers, i);
+ /* First find a transceiver requesting this m-line */
+ trans = _find_transceiver_for_mline (webrtc, media_idx);
- /* don't add transceivers twice */
- if (g_list_find (seen_transceivers, trans))
- continue;
+ if (trans) {
+ /* We can't have seen it already, because it is locked to this line */
+ g_assert (!g_list_find (seen_transceivers, trans));
+ seen_transceivers = g_list_prepend (seen_transceivers, trans);
+ } else {
+ /* Otherwise find a free transceiver */
+ for (i = 0; i < webrtc->priv->transceivers->len; i++) {
+ WebRTCTransceiver *wtrans;
+
+ trans = g_ptr_array_index (webrtc->priv->transceivers, i);
+ wtrans = WEBRTC_TRANSCEIVER (trans);
+
+ /* don't add transceivers twice */
+ if (g_list_find (seen_transceivers, trans))
+ continue;
+
+ /* Ignore transceivers with a locked mline, as they would have been
+ * found above or will be used later */
+ if (wtrans->mline_locked)
+ continue;
+
+ seen_transceivers = g_list_prepend (seen_transceivers, trans);
+ /* don't add stopped transceivers */
+ if (trans->stopped) {
+ continue;
+ }
- /* don't add stopped transceivers */
- if (trans->stopped)
- continue;
+ /* Otherwise take it */
+ break;
+ }
+
+ /* Stop if we got all transceivers */
+ if (i == webrtc->priv->transceivers->len) {
+
+ /* But try to add a data channel first, we do it here, because
+ * it can allow a locked m-line to be put after, so we need to
+ * do another iteration after.
+ */
+ if (_message_get_datachannel_index (ret) == G_MAXUINT) {
+ GstSDPMedia media = { 0, };
+ gst_sdp_media_init (&media);
+ if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0,
+ bundle_ufrag, bundle_pwd, all_mids)) {
+ gst_sdp_message_add_media (ret, &media);
+ media_idx++;
+ continue;
+ } else {
+ gst_sdp_media_uninit (&media);
+ }
+ }
+
+ /* Verify that we didn't ignore any locked m-line transceivers */
+ for (i = 0; i < webrtc->priv->transceivers->len; i++) {
+ WebRTCTransceiver *wtrans;
+
+ trans = g_ptr_array_index (webrtc->priv->transceivers, i);
+ wtrans = WEBRTC_TRANSCEIVER (trans);
+ /* don't add transceivers twice */
+ if (g_list_find (seen_transceivers, trans))
+ continue;
+ g_assert (wtrans->mline_locked);
+
+ g_set_error (error, GST_WEBRTC_BIN_ERROR,
+ GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION,
+ "Tranceiver %" GST_PTR_FORMAT " with mid %s has locked mline %d"
+ " but the whole offer only has %u sections", trans, trans->mid,
+ trans->mline, media_idx);
+ goto cancel_offer;
+ }
+ break;
+ }
+ }
gst_sdp_media_init (&media);
@@ -2973,7 +3054,6 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
g_array_free (reserved_pts, TRUE);
reserved_pts = NULL;
}
- seen_transceivers = g_list_prepend (seen_transceivers, trans);
}
if (webrtc->bundle_policy != GST_WEBRTC_BUNDLE_POLICY_NONE) {
@@ -2981,19 +3061,6 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
reserved_pts = NULL;
}
- /* add a data channel if exists and not renegotiated */
- if (_message_get_datachannel_index (ret) == G_MAXUINT) {
- GstSDPMedia media = { 0, };
- gst_sdp_media_init (&media);
- if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0,
- bundle_ufrag, bundle_pwd, all_mids)) {
- gst_sdp_message_add_media (ret, &media);
- media_idx++;
- } else {
- gst_sdp_media_uninit (&media);
- }
- }
-
webrtc->priv->max_sink_pad_serial = MAX (webrtc->priv->max_sink_pad_serial,
media_idx);
@@ -3040,7 +3107,7 @@ out:
return ret;
-duplicate_mid:
+cancel_offer:
gst_sdp_message_uninit (ret);
ret = NULL;
goto out;