GParamSpec * pspec, GstWebRTCBin * webrtc)
{
GstWebRTCDataChannelState ready_state;
- guint i;
g_object_get (channel, "ready-state", &ready_state, NULL);
if (ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
- gboolean found = FALSE;
-
- for (i = 0; i < webrtc->priv->pending_data_channels->len; i++) {
- WebRTCDataChannel *c;
+ gboolean found;
- c = g_ptr_array_index (webrtc->priv->pending_data_channels, i);
- if (c == channel) {
- found = TRUE;
- g_ptr_array_remove_index (webrtc->priv->pending_data_channels, i);
- break;
- }
- }
+ found = g_ptr_array_remove (webrtc->priv->pending_data_channels, channel);
if (found == FALSE) {
GST_FIXME_OBJECT (webrtc, "Received open for unknown data channel");
return;
}
- g_ptr_array_add (webrtc->priv->data_channels, channel);
+ g_ptr_array_add (webrtc->priv->data_channels, gst_object_ref (channel));
gst_webrtc_bin_update_sctp_priority (webrtc);
g_signal_emit (webrtc, gst_webrtc_bin_signals[ON_DATA_CHANNEL_SIGNAL], 0,
- gst_object_ref (channel));
+ channel);
+ } else if (ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED) {
+ gboolean found;
+
+ found = g_ptr_array_remove (webrtc->priv->pending_data_channels, channel)
+ || g_ptr_array_remove (webrtc->priv->data_channels, channel);
+
+ if (found == FALSE) {
+ GST_FIXME_OBJECT (webrtc, "Received close for unknown data channel");
+ }
}
}
enum
{
SIGNAL_0,
- ON_RESET_STREAM_SIGNAL,
+ ON_STREAM_RESET_SIGNAL,
LAST_SIGNAL,
};
guint stream_id = GPOINTER_TO_UINT (user_data);
g_signal_emit (sctp,
- gst_webrtc_sctp_transport_signals[ON_RESET_STREAM_SIGNAL], 0, stream_id);
+ gst_webrtc_sctp_transport_signals[ON_STREAM_RESET_SIGNAL], 0, stream_id);
}
static void
sctp->sctpenc =
g_object_ref_sink (gst_element_factory_make ("sctpenc", NULL));
g_object_set (sctp->sctpenc, "sctp-association-id", association_id, NULL);
+ g_object_set (sctp->sctpenc, "use-sock-stream", TRUE, NULL);
g_signal_connect (sctp->sctpdec, "pad-removed",
G_CALLBACK (_on_sctp_dec_pad_removed), sctp);
0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
- * GstWebRTCSCTPTransport::reset-stream:
+ * GstWebRTCSCTPTransport::stream-reset:
* @object: the #GstWebRTCSCTPTransport
* @stream_id: the SCTP stream that was reset
*/
- gst_webrtc_sctp_transport_signals[ON_RESET_STREAM_SIGNAL] =
+ gst_webrtc_sctp_transport_signals[ON_STREAM_RESET_SIGNAL] =
g_signal_new ("stream-reset", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
}
_transport_closed (WebRTCDataChannel * channel)
{
GError *error;
+ gboolean both_sides_closed;
GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
error = channel->stored_error;
channel->stored_error = NULL;
+
+ both_sides_closed =
+ channel->peer_closed && channel->parent.buffered_amount <= 0;
+ if (both_sides_closed || error) {
+ channel->peer_closed = FALSE;
+ }
GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
if (error) {
gst_webrtc_data_channel_on_error (GST_WEBRTC_DATA_CHANNEL (channel), error);
g_clear_error (&error);
}
- gst_webrtc_data_channel_on_close (GST_WEBRTC_DATA_CHANNEL (channel));
+ if (both_sides_closed || error) {
+ gst_webrtc_data_channel_on_close (GST_WEBRTC_DATA_CHANNEL (channel));
+ }
}
static void
{
GstPad *pad, *peer;
+ GST_INFO_OBJECT (channel, "Closing outgoing SCTP stream %i label \"%s\"",
+ channel->parent.id, channel->parent.label);
+
pad = gst_element_get_static_pad (channel->appsrc, "src");
peer = gst_pad_get_peer (pad);
gst_object_unref (pad);
{
/* https://www.w3.org/TR/webrtc/#data-transport-closing-procedure */
GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
- if (channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED
- || channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING) {
+ if (channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED) {
GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
return;
- }
- channel->parent.ready_state = GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING;
- GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
- g_object_notify (G_OBJECT (channel), "ready-state");
+ } else if (channel->parent.ready_state ==
+ GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING) {
+ _channel_enqueue_task (channel, (ChannelTask) _transport_closed, NULL,
+ NULL);
+ } else if (channel->parent.ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
+ channel->parent.ready_state = GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING;
+ GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
+ g_object_notify (G_OBJECT (channel), "ready-state");
- GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
- if (channel->parent.buffered_amount <= 0) {
- _channel_enqueue_task (channel, (ChannelTask) _close_sctp_stream,
- NULL, NULL);
+ GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
+ if (channel->parent.buffered_amount <= 0) {
+ _channel_enqueue_task (channel, (ChannelTask) _close_sctp_stream,
+ NULL, NULL);
+ }
}
GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
}
static void
-_on_sctp_reset_stream (GstWebRTCSCTPTransport * sctp, guint stream_id,
+_on_sctp_stream_reset (GstWebRTCSCTPTransport * sctp, guint stream_id,
WebRTCDataChannel * channel)
{
- if (channel->parent.id == stream_id)
- _channel_enqueue_task (channel, (ChannelTask) _transport_closed,
+ if (channel->parent.id == stream_id) {
+ GST_INFO_OBJECT (channel,
+ "Received channel close for SCTP stream %i label \"%s\"",
+ channel->parent.id, channel->parent.label);
+
+ GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
+ channel->peer_closed = TRUE;
+ GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
+
+ _channel_enqueue_task (channel, (ChannelTask) _close_procedure,
GUINT_TO_POINTER (stream_id), NULL);
+ }
}
static void
channel->opened = TRUE;
GST_INFO_OBJECT (channel, "Received channel open for SCTP stream %i "
- "label %s protocol %s ordered %s", channel->parent.id,
+ "label \"%s\" protocol %s ordered %s", channel->parent.id,
channel->parent.label, channel->parent.protocol,
channel->parent.ordered ? "true" : "false");
buffer = construct_open_packet (channel);
GST_INFO_OBJECT (channel, "Sending channel open for SCTP stream %i "
- "label %s protocol %s ordered %s", channel->parent.id,
+ "label \"%s\" protocol %s ordered %s", channel->parent.id,
channel->parent.label, channel->parent.protocol,
channel->parent.ordered ? "true" : "false");
GST_OBJECT (sctp));
if (sctp) {
- g_signal_connect (sctp, "stream-reset", G_CALLBACK (_on_sctp_reset_stream),
+ g_signal_connect (sctp, "stream-reset", G_CALLBACK (_on_sctp_stream_reset),
channel);
g_signal_connect (sctp, "notify::state", G_CALLBACK (_on_sctp_notify_state),
channel);