webrtcbin: Prevent critical warning when creating an additional data channel
authorPhilippe Normand <philn@igalia.com>
Mon, 10 Jul 2023 11:03:25 +0000 (12:03 +0100)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 11 Jul 2023 20:39:59 +0000 (20:39 +0000)
The max_channels value wasn't clamped to 65534 in all situations.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5012>

subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c

index d230a44..04efce6 100644 (file)
@@ -7110,6 +7110,10 @@ gst_webrtc_bin_create_data_channel (GstWebRTCBin * webrtc, const gchar * label,
     g_object_get (webrtc->priv->sctp_transport, "max-channels", &max_channels,
         NULL);
 
+    if (max_channels <= 0) {
+      max_channels = 65534;
+    }
+
     g_return_val_if_fail (id <= max_channels, NULL);
   }
 
index 617dee5..21183db 100644 (file)
@@ -2049,6 +2049,69 @@ GST_START_TEST (test_data_channel_create)
 GST_END_TEST;
 
 static void
+signal_data_channel (struct test_webrtc *t,
+    GstElement * element, GObject * our, gpointer user_data)
+{
+  test_webrtc_signal_state_unlocked (t, STATE_CUSTOM);
+}
+
+GST_START_TEST (test_data_channel_create_two_channels)
+{
+  struct test_webrtc *t = test_webrtc_new ();
+  GObject *channel = NULL;
+  GObject *channel2 = NULL;
+  VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
+  VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
+  gchar *label;
+  GstStructure *options = NULL;
+
+  t->on_negotiation_needed = NULL;
+  t->on_ice_candidate = NULL;
+  t->on_prepare_data_channel = have_prepare_data_channel;
+  t->on_data_channel = signal_data_channel;
+
+  fail_if (gst_element_set_state (t->webrtc1, GST_STATE_READY) ==
+      GST_STATE_CHANGE_FAILURE);
+  fail_if (gst_element_set_state (t->webrtc2, GST_STATE_READY) ==
+      GST_STATE_CHANGE_FAILURE);
+
+  g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
+      &channel);
+  g_assert_nonnull (channel);
+  g_object_get (channel, "label", &label, NULL);
+  g_assert_cmpstr (label, ==, "label");
+  g_free (label);
+  g_object_unref (channel);
+
+  fail_if (gst_element_set_state (t->webrtc1, GST_STATE_PLAYING) ==
+      GST_STATE_CHANGE_FAILURE);
+  fail_if (gst_element_set_state (t->webrtc2, GST_STATE_PLAYING) ==
+      GST_STATE_CHANGE_FAILURE);
+
+  /* Wait SCTP transport creation */
+  test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
+
+  /* Create another channel on an existing SCTP transport, forcing an ID that
+     should comply with the max-channels requiremennt, this should not raise a
+     critical warning, the id is beneath the required limits. */
+  options =
+      gst_structure_new ("options", "id", G_TYPE_INT, 2, "negotiated",
+      G_TYPE_BOOLEAN, TRUE, NULL);
+  g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label2", options,
+      &channel2);
+  gst_structure_free (options);
+  g_assert_nonnull (channel2);
+  g_object_get (channel2, "label", &label, NULL);
+  g_assert_cmpstr (label, ==, "label2");
+  g_free (label);
+  g_object_unref (channel2);
+
+  test_webrtc_free (t);
+}
+
+GST_END_TEST;
+
+static void
 have_data_channel (struct test_webrtc *t, GstElement * element,
     GObject * our, gpointer user_data)
 {
@@ -5775,6 +5838,7 @@ webrtcbin_suite (void)
     tcase_add_test (tc, test_msid);
     if (sctpenc && sctpdec) {
       tcase_add_test (tc, test_data_channel_create);
+      tcase_add_test (tc, test_data_channel_create_two_channels);
       tcase_add_test (tc, test_data_channel_remote_notify);
       tcase_add_test (tc, test_data_channel_transfer_string);
       tcase_add_test (tc, test_data_channel_transfer_data);