diff --git a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c index 0ce3368076..bb2b023618 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c @@ -745,35 +745,30 @@ _is_within_max_message_size (WebRTCDataChannel * channel, gsize size) return size <= channel->sctp_transport->max_message_size; } -static void +static gboolean webrtc_data_channel_send_data (GstWebRTCDataChannel * base_channel, - GBytes * bytes) + GBytes * bytes, GError ** error) { WebRTCDataChannel *channel = WEBRTC_DATA_CHANNEL (base_channel); GstSctpSendMetaPartiallyReliability reliability; guint rel_param; guint32 ppid; GstBuffer *buffer; + gsize size = 0; GstFlowReturn ret; if (!bytes) { buffer = gst_buffer_new (); ppid = DATA_CHANNEL_PPID_WEBRTC_BINARY_EMPTY; } else { - gsize size; guint8 *data; data = (guint8 *) g_bytes_get_data (bytes, &size); - g_return_if_fail (data != NULL); + g_return_val_if_fail (data != NULL, FALSE); if (!_is_within_max_message_size (channel, size)) { - GError *error = NULL; - g_set_error (&error, GST_WEBRTC_ERROR, - GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE, + g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_TYPE_ERROR, "Requested to send data that is too large"); - _channel_store_error (channel, error); - _channel_enqueue_task (channel, (ChannelTask) _close_procedure, NULL, - NULL); - return; + return FALSE; } buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, data, size, @@ -789,52 +784,61 @@ webrtc_data_channel_send_data (GstWebRTCDataChannel * base_channel, buffer); GST_WEBRTC_DATA_CHANNEL_LOCK (channel); - channel->parent.buffered_amount += gst_buffer_get_size (buffer); + if (channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) { + channel->parent.buffered_amount += size; + } else { + GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); + g_set_error (error, GST_WEBRTC_ERROR, + GST_WEBRTC_ERROR_INVALID_STATE, "channel is not open"); + return FALSE; + } GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); - g_object_notify (G_OBJECT (&channel->parent), "buffered-amount"); ret = gst_app_src_push_buffer (GST_APP_SRC (channel->appsrc), buffer); - - if (ret != GST_FLOW_OK) { - GError *error = NULL; - g_set_error (&error, GST_WEBRTC_ERROR, + if (ret == GST_FLOW_OK) { + g_object_notify (G_OBJECT (&channel->parent), "buffered-amount"); + } else { + g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE, "Failed to send data"); - _channel_store_error (channel, error); + + GST_WEBRTC_DATA_CHANNEL_LOCK (channel); + channel->parent.buffered_amount -= size; + GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); + _channel_enqueue_task (channel, (ChannelTask) _close_procedure, NULL, NULL); + return FALSE; } + + return TRUE; } -static void +static gboolean webrtc_data_channel_send_string (GstWebRTCDataChannel * base_channel, - const gchar * str) + const gchar * str, GError ** error) { WebRTCDataChannel *channel = WEBRTC_DATA_CHANNEL (base_channel); GstSctpSendMetaPartiallyReliability reliability; guint rel_param; guint32 ppid; GstBuffer *buffer; + gsize size = 0; GstFlowReturn ret; if (!channel->parent.negotiated) - g_return_if_fail (channel->opened); - g_return_if_fail (channel->sctp_transport != NULL); + g_return_val_if_fail (channel->opened, FALSE); + g_return_val_if_fail (channel->sctp_transport != NULL, FALSE); if (!str) { buffer = gst_buffer_new (); ppid = DATA_CHANNEL_PPID_WEBRTC_STRING_EMPTY; } else { - gsize size = strlen (str); gchar *str_copy; + size = strlen (str); if (!_is_within_max_message_size (channel, size)) { - GError *error = NULL; - g_set_error (&error, GST_WEBRTC_ERROR, - GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE, + g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_TYPE_ERROR, "Requested to send a string that is too large"); - _channel_store_error (channel, error); - _channel_enqueue_task (channel, (ChannelTask) _close_procedure, NULL, - NULL); - return; + return FALSE; } str_copy = g_strdup (str); @@ -852,19 +856,32 @@ webrtc_data_channel_send_string (GstWebRTCDataChannel * base_channel, buffer); GST_WEBRTC_DATA_CHANNEL_LOCK (channel); - channel->parent.buffered_amount += gst_buffer_get_size (buffer); + if (channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) { + channel->parent.buffered_amount += size; + } else { + GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); + g_set_error (error, GST_WEBRTC_ERROR, + GST_WEBRTC_ERROR_INVALID_STATE, "channel is not open"); + return FALSE; + } GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); - g_object_notify (G_OBJECT (&channel->parent), "buffered-amount"); ret = gst_app_src_push_buffer (GST_APP_SRC (channel->appsrc), buffer); - - if (ret != GST_FLOW_OK) { - GError *error = NULL; - g_set_error (&error, GST_WEBRTC_ERROR, + if (ret == GST_FLOW_OK) { + g_object_notify (G_OBJECT (&channel->parent), "buffered-amount"); + } else { + g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_DATA_CHANNEL_FAILURE, "Failed to send string"); - _channel_store_error (channel, error); + + GST_WEBRTC_DATA_CHANNEL_LOCK (channel); + channel->parent.buffered_amount -= size; + GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel); + _channel_enqueue_task (channel, (ChannelTask) _close_procedure, NULL, NULL); + return FALSE; } + + return TRUE; } static void diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.c b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.c index e8a141f635..38cd3ce039 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.c @@ -339,7 +339,7 @@ gst_webrtc_data_channel_class_init (GstWebRTCDataChannelClass * klass) */ gst_webrtc_data_channel_signals[SIGNAL_SEND_DATA] = g_signal_new_class_handler ("send-data", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION | G_SIGNAL_DEPRECATED, G_CALLBACK (gst_webrtc_data_channel_send_data), NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BYTES); @@ -524,7 +524,31 @@ gst_webrtc_data_channel_send_data (GstWebRTCDataChannel * channel, g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel)); klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel); - klass->send_data (channel, data); + (void) klass->send_data (channel, data, NULL); +} + +/** + * gst_webrtc_data_channel_send_data_full: + * @channel: a #GstWebRTCDataChannel + * @data: (nullable): a #GBytes or %NULL + * @error: (nullable): location to a #GError or %NULL + * + * Send @data as a data message over @channel. + * + * Returns: TRUE if @channel is open and data could be queued + * + * Since: 1.22 + */ +gboolean +gst_webrtc_data_channel_send_data_full (GstWebRTCDataChannel * channel, + GBytes * data, GError ** error) +{ + GstWebRTCDataChannelClass *klass; + + g_return_val_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel), FALSE); + + klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel); + return klass->send_data (channel, data, error); } /** @@ -543,7 +567,30 @@ gst_webrtc_data_channel_send_string (GstWebRTCDataChannel * channel, g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel)); klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel); - klass->send_string (channel, str); + (void) klass->send_string (channel, str, NULL); +} + +/** + * gst_webrtc_data_channel_send_string_full: + * @channel: a #GstWebRTCDataChannel + * @str: (nullable): a string or %NULL + * + * Send @str as a string message over @channel. + * + * Returns: TRUE if @channel is open and data could be queued + * + * Since: 1.22 + */ +gboolean +gst_webrtc_data_channel_send_string_full (GstWebRTCDataChannel * channel, + const gchar * str, GError ** error) +{ + GstWebRTCDataChannelClass *klass; + + g_return_val_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel), FALSE); + + klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel); + return klass->send_string (channel, str, error); } /** diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.h index 8146c65981..408872aecf 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/datachannel.h @@ -37,14 +37,22 @@ GType gst_webrtc_data_channel_get_type(void); #define GST_WEBRTC_DATA_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_WEBRTC_DATA_CHANNEL,GstWebRTCDataChannelClass)) GST_WEBRTC_API -void gst_webrtc_data_channel_send_data (GstWebRTCDataChannel * channel, GBytes * data); +gboolean gst_webrtc_data_channel_send_data_full (GstWebRTCDataChannel * channel, GBytes * data, GError ** error); GST_WEBRTC_API -void gst_webrtc_data_channel_send_string (GstWebRTCDataChannel * channel, const gchar * str); +gboolean gst_webrtc_data_channel_send_string_full (GstWebRTCDataChannel * channel, const gchar * str, GError ** error); GST_WEBRTC_API void gst_webrtc_data_channel_close (GstWebRTCDataChannel * channel); +#ifndef GST_REMOVE_DEPRECATED +GST_WEBRTC_DEPRECATED_FOR(gst_webrtc_data_channel_send_data_full) +void gst_webrtc_data_channel_send_data (GstWebRTCDataChannel * channel, GBytes * data); + +GST_WEBRTC_DEPRECATED_FOR(gst_webrtc_data_channel_send_string_full) +void gst_webrtc_data_channel_send_string (GstWebRTCDataChannel * channel, const gchar * str); +#endif + G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstWebRTCDataChannel, g_object_unref) G_END_DECLS diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc-priv.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc-priv.h index 3da7669428..67676a38e0 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc-priv.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc-priv.h @@ -222,8 +222,8 @@ struct _GstWebRTCDataChannelClass { GObjectClass parent_class; - void (*send_data) (GstWebRTCDataChannel * channel, GBytes *data); - void (*send_string) (GstWebRTCDataChannel * channel, const gchar *str); + gboolean (*send_data) (GstWebRTCDataChannel * channel, GBytes *data, GError ** error); + gboolean (*send_string) (GstWebRTCDataChannel * channel, const gchar *str, GError ** error); void (*close) (GstWebRTCDataChannel * channel); gpointer _padding[GST_PADDING]; 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 b45242356b..fe20675e1d 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 @@ -40,6 +40,20 @@ # endif #endif +/** + * GST_WEBRTC_DEPRECATED: (attributes doc.skip=true) + */ +/** + * GST_WEBRTC_DEPRECATED_FOR: (attributes doc.skip=true) + */ +#ifndef GST_DISABLE_DEPRECATED +#define GST_WEBRTC_DEPRECATED GST_WEBRTC_API +#define GST_WEBRTC_DEPRECATED_FOR(f) GST_WEBRTC_API +#else +#define GST_WEBRTC_DEPRECATED G_DEPRECATED GST_WEBRTC_API +#define GST_WEBRTC_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) GST_WEBRTC_API +#endif + #include /** @@ -471,6 +485,13 @@ GQuark gst_webrtc_error_quark (void); * * Since: 1.20 */ +/** + * GST_WEBRTC_ERROR_TYPE_ERROR: + * + * type-error (maps to JavaScript TypeError) + * + * Since: 1.22 + */ /** * GST_WEBRTC_ERROR_INVALID_MODIFICATION: * @@ -488,6 +509,7 @@ typedef enum /**/ GST_WEBRTC_ERROR_HARDWARE_ENCODER_NOT_AVAILABLE, GST_WEBRTC_ERROR_ENCODER_ERROR, GST_WEBRTC_ERROR_INVALID_STATE, + GST_WEBRTC_ERROR_TYPE_ERROR, GST_WEBRTC_ERROR_INTERNAL_FAILURE, GST_WEBRTC_ERROR_INVALID_MODIFICATION, } GstWebRTCError; diff --git a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c index e92a659d1b..144b38dae5 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c @@ -2094,13 +2094,16 @@ have_data_channel_transfer_string (struct test_webrtc *t, GstElement * element, { GObject *other = user_data; GstWebRTCDataChannelState state; + GError *error = NULL; g_object_get (our, "ready-state", &state, NULL); fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state); g_object_set_data_full (our, "expected", g_strdup (test_string), g_free); - g_signal_emit_by_name (other, "send-string", test_string); + fail_unless (gst_webrtc_data_channel_send_string_full (GST_WEBRTC_DATA_CHANNEL + (other), test_string, &error)); + g_assert_null (error); } GST_START_TEST (test_data_channel_transfer_string) @@ -2171,6 +2174,7 @@ have_data_channel_transfer_data (struct test_webrtc *t, GstElement * element, GObject *other = user_data; GBytes *data = g_bytes_new_static (test_string, strlen (test_string)); GstWebRTCDataChannelState state; + GError *error = NULL; g_object_get (our, "ready-state", &state, NULL); fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state); @@ -2178,7 +2182,9 @@ have_data_channel_transfer_data (struct test_webrtc *t, GstElement * element, g_object_set_data_full (our, "expected", g_bytes_ref (data), (GDestroyNotify) g_bytes_unref); - g_signal_emit_by_name (other, "send-data", data); + fail_unless (gst_webrtc_data_channel_send_data_full (GST_WEBRTC_DATA_CHANNEL + (other), data, &error)); + g_assert_null (error); g_bytes_unref (data); } @@ -2445,7 +2451,8 @@ have_data_channel_check_low_threshold_emitted (struct test_webrtc *t, g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached), NULL); - g_signal_emit_by_name (our, "send-string", "A"); + gst_webrtc_data_channel_send_string_full (GST_WEBRTC_DATA_CHANNEL (our), "A", + NULL); } GST_START_TEST (test_data_channel_low_threshold) @@ -2483,14 +2490,6 @@ GST_START_TEST (test_data_channel_low_threshold) GST_END_TEST; -static void -on_channel_error (GObject * channel, GError * error, struct test_webrtc *t) -{ - g_assert_nonnull (error); - - test_webrtc_signal_state (t, STATE_CUSTOM); -} - static void have_data_channel_transfer_large_data (struct test_webrtc *t, GstElement * element, GObject * our, gpointer user_data) @@ -2500,6 +2499,7 @@ have_data_channel_transfer_large_data (struct test_webrtc *t, guint8 *random_data = g_new (guint8, size); GBytes *data; gsize i; + GError *error = NULL; for (i = 0; i < size; i++) random_data[i] = (guint8) (i & 0xff); @@ -2511,9 +2511,15 @@ have_data_channel_transfer_large_data (struct test_webrtc *t, (GDestroyNotify) g_bytes_unref); g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t); - g_signal_connect (other, "on-error", G_CALLBACK (on_channel_error), t); - g_signal_emit_by_name (other, "send-data", data); + g_signal_connect (other, "on-error", + G_CALLBACK (on_channel_error_not_reached), NULL); + fail_if (gst_webrtc_data_channel_send_data_full (GST_WEBRTC_DATA_CHANNEL + (other), data, &error)); + g_assert_nonnull (error); + g_clear_error (&error); g_bytes_unref (data); + + test_webrtc_signal_state_unlocked (t, STATE_CUSTOM); } GST_START_TEST (test_data_channel_max_message_size)