webrtc: always reply to a promise

Otherwise, we defeat the purpose of a promise.

We were not replying when the state was closed.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1240>
This commit is contained in:
Matthew Waters 2020-05-06 00:30:34 +10:00 committed by GStreamer Merge Bot
parent 1f395e3ddb
commit 50644f5718
5 changed files with 112 additions and 28 deletions

View file

@ -745,6 +745,18 @@ _execute_op (GstWebRTCBinTask * op)
{ {
PC_LOCK (op->webrtc); PC_LOCK (op->webrtc);
if (op->webrtc->priv->is_closed) { if (op->webrtc->priv->is_closed) {
if (op->promise) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"webrtcbin is closed. aborting execution.");
GstStructure *s =
gst_structure_new ("application/x-gstwebrtcbin-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (op->promise, s);
g_clear_error (&error);
}
GST_DEBUG_OBJECT (op->webrtc, GST_DEBUG_OBJECT (op->webrtc,
"Peerconnection is closed, aborting execution"); "Peerconnection is closed, aborting execution");
goto out; goto out;
@ -762,29 +774,39 @@ _free_op (GstWebRTCBinTask * op)
{ {
if (op->notify) if (op->notify)
op->notify (op->data); op->notify (op->data);
if (op->promise)
gst_promise_unref (op->promise);
g_free (op); g_free (op);
} }
void /*
* @promise is for correctly signalling the failure case to the caller when
* the user supplies it. Without passing it in, the promise would never
* be replied to in the case that @webrtc becomes closed between the idle
* source addition and the the execution of the idle source.
*/
gboolean
gst_webrtc_bin_enqueue_task (GstWebRTCBin * webrtc, GstWebRTCBinFunc func, gst_webrtc_bin_enqueue_task (GstWebRTCBin * webrtc, GstWebRTCBinFunc func,
gpointer data, GDestroyNotify notify) gpointer data, GDestroyNotify notify, GstPromise * promise)
{ {
GstWebRTCBinTask *op; GstWebRTCBinTask *op;
GSource *source; GSource *source;
g_return_if_fail (GST_IS_WEBRTC_BIN (webrtc)); g_return_val_if_fail (GST_IS_WEBRTC_BIN (webrtc), FALSE);
if (webrtc->priv->is_closed) { if (webrtc->priv->is_closed) {
GST_DEBUG_OBJECT (webrtc, "Peerconnection is closed, aborting execution"); GST_DEBUG_OBJECT (webrtc, "Peerconnection is closed, aborting execution");
if (notify) if (notify)
notify (data); notify (data);
return; return FALSE;
} }
op = g_new0 (GstWebRTCBinTask, 1); op = g_new0 (GstWebRTCBinTask, 1);
op->webrtc = webrtc; op->webrtc = webrtc;
op->op = func; op->op = func;
op->data = data; op->data = data;
op->notify = notify; op->notify = notify;
if (promise)
op->promise = gst_promise_ref (promise);
source = g_idle_source_new (); source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_DEFAULT); g_source_set_priority (source, G_PRIORITY_DEFAULT);
@ -792,6 +814,8 @@ gst_webrtc_bin_enqueue_task (GstWebRTCBin * webrtc, GstWebRTCBinFunc func,
(GDestroyNotify) _free_op); (GDestroyNotify) _free_op);
g_source_attach (source, webrtc->priv->main_context); g_source_attach (source, webrtc->priv->main_context);
g_source_unref (source); g_source_unref (source);
return TRUE;
} }
/* https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate */ /* https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate */
@ -1200,7 +1224,7 @@ static void
_update_ice_gathering_state (GstWebRTCBin * webrtc) _update_ice_gathering_state (GstWebRTCBin * webrtc)
{ {
gst_webrtc_bin_enqueue_task (webrtc, _update_ice_gathering_state_task, NULL, gst_webrtc_bin_enqueue_task (webrtc, _update_ice_gathering_state_task, NULL,
NULL); NULL, NULL);
} }
static void static void
@ -1235,7 +1259,7 @@ static void
_update_ice_connection_state (GstWebRTCBin * webrtc) _update_ice_connection_state (GstWebRTCBin * webrtc)
{ {
gst_webrtc_bin_enqueue_task (webrtc, _update_ice_connection_state_task, NULL, gst_webrtc_bin_enqueue_task (webrtc, _update_ice_connection_state_task, NULL,
NULL); NULL, NULL);
} }
static void static void
@ -1270,7 +1294,7 @@ static void
_update_peer_connection_state (GstWebRTCBin * webrtc) _update_peer_connection_state (GstWebRTCBin * webrtc)
{ {
gst_webrtc_bin_enqueue_task (webrtc, _update_peer_connection_state_task, gst_webrtc_bin_enqueue_task (webrtc, _update_peer_connection_state_task,
NULL, NULL); NULL, NULL, NULL);
} }
static gboolean static gboolean
@ -1506,7 +1530,7 @@ _update_need_negotiation (GstWebRTCBin * webrtc)
/* Queue a task to check connection's [[ needNegotiation]] slot and, if still /* Queue a task to check connection's [[ needNegotiation]] slot and, if still
* true, fire a simple event named negotiationneeded at connection. */ * true, fire a simple event named negotiationneeded at connection. */
gst_webrtc_bin_enqueue_task (webrtc, _check_need_negotiation_task, NULL, gst_webrtc_bin_enqueue_task (webrtc, _check_need_negotiation_task, NULL,
NULL); NULL, NULL);
} }
static GstCaps * static GstCaps *
@ -1884,7 +1908,7 @@ _on_sctp_notify_dtls_state (GstWebRTCDTLSTransport * transport,
* elements */ * elements */
if (dtls_state == GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED) { if (dtls_state == GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED) {
gst_webrtc_bin_enqueue_task (webrtc, gst_webrtc_bin_enqueue_task (webrtc,
(GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL); (GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL, NULL);
} }
} }
@ -1990,7 +2014,7 @@ _get_or_create_data_channel_transports (GstWebRTCBin * webrtc, guint session_id)
* current state of the connection already without getting the signal * current state of the connection already without getting the signal
* called */ * called */
gst_webrtc_bin_enqueue_task (webrtc, gst_webrtc_bin_enqueue_task (webrtc,
(GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL); (GstWebRTCBinFunc) _sctp_check_dtls_state_task, NULL, NULL, NULL);
} }
webrtc->priv->sctp_transport = sctp_transport; webrtc->priv->sctp_transport = sctp_transport;
@ -3336,8 +3360,19 @@ gst_webrtc_bin_create_offer (GstWebRTCBin * webrtc,
data->promise = gst_promise_ref (promise); data->promise = gst_promise_ref (promise);
data->type = GST_WEBRTC_SDP_TYPE_OFFER; data->type = GST_WEBRTC_SDP_TYPE_OFFER;
gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _create_sdp_task, if (!gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _create_sdp_task,
data, (GDestroyNotify) _free_create_sdp_data); data, (GDestroyNotify) _free_create_sdp_data, promise)) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"Could not create offer. webrtcbin is closed");
GstStructure *s =
gst_structure_new ("application/x-gstwebrtcbin-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (promise, s);
g_clear_error (&error);
}
} }
static void static void
@ -3351,8 +3386,19 @@ gst_webrtc_bin_create_answer (GstWebRTCBin * webrtc,
data->promise = gst_promise_ref (promise); data->promise = gst_promise_ref (promise);
data->type = GST_WEBRTC_SDP_TYPE_ANSWER; data->type = GST_WEBRTC_SDP_TYPE_ANSWER;
gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _create_sdp_task, if (!gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _create_sdp_task,
data, (GDestroyNotify) _free_create_sdp_data); data, (GDestroyNotify) _free_create_sdp_data, promise)) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"Could not create answer. webrtcbin is closed.");
GstStructure *s =
gst_structure_new ("application/x-gstwebrtcbin-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (promise, s);
g_clear_error (&error);
}
} }
static GstWebRTCBinPad * static GstWebRTCBinPad *
@ -3970,7 +4016,7 @@ _generate_data_channel_id (GstWebRTCBin * webrtc)
} }
/* client must generate even ids, server must generate odd ids */ /* client must generate even ids, server must generate odd ids */
if (new_id % 2 == !!is_client) if (new_id % 2 == ! !is_client)
continue; continue;
channel = _find_data_channel_for_id (webrtc, new_id); channel = _find_data_channel_for_id (webrtc, new_id);
@ -4634,8 +4680,20 @@ gst_webrtc_bin_set_remote_description (GstWebRTCBin * webrtc,
sd->source = SDP_REMOTE; sd->source = SDP_REMOTE;
sd->sdp = gst_webrtc_session_description_copy (remote_sdp); sd->sdp = gst_webrtc_session_description_copy (remote_sdp);
gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _set_description_task, if (!gst_webrtc_bin_enqueue_task (webrtc,
sd, (GDestroyNotify) _free_set_description_data); (GstWebRTCBinFunc) _set_description_task, sd,
(GDestroyNotify) _free_set_description_data, promise)) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"Could not set remote description. webrtcbin is closed.");
GstStructure *s =
gst_structure_new ("application/x-gstwebrtcbin-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (promise, s);
g_clear_error (&error);
}
return; return;
@ -4663,8 +4721,20 @@ gst_webrtc_bin_set_local_description (GstWebRTCBin * webrtc,
sd->source = SDP_LOCAL; sd->source = SDP_LOCAL;
sd->sdp = gst_webrtc_session_description_copy (local_sdp); sd->sdp = gst_webrtc_session_description_copy (local_sdp);
gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _set_description_task, if (!gst_webrtc_bin_enqueue_task (webrtc,
sd, (GDestroyNotify) _free_set_description_data); (GstWebRTCBinFunc) _set_description_task, sd,
(GDestroyNotify) _free_set_description_data, promise)) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"Could not set remote description. webrtcbin is closed");
GstStructure *s =
gst_structure_new ("application/x-gstwebrtcbin-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (promise, s);
g_clear_error (&error);
}
return; return;
@ -4712,7 +4782,7 @@ gst_webrtc_bin_add_ice_candidate (GstWebRTCBin * webrtc, guint mline,
item->candidate = g_strdup_printf ("a=%s", attr); item->candidate = g_strdup_printf ("a=%s", attr);
gst_webrtc_bin_enqueue_task (webrtc, gst_webrtc_bin_enqueue_task (webrtc,
(GstWebRTCBinFunc) _add_ice_candidate_task, item, (GstWebRTCBinFunc) _add_ice_candidate_task, item,
(GDestroyNotify) _free_ice_candidate_item); (GDestroyNotify) _free_ice_candidate_item, NULL);
} }
static void static void
@ -4796,7 +4866,7 @@ _on_local_ice_candidate_cb (GstWebRTCICE * ice, guint session_id,
if (queue_task) { if (queue_task) {
GST_TRACE_OBJECT (webrtc, "Queueing on_ice_candidate_task"); GST_TRACE_OBJECT (webrtc, "Queueing on_ice_candidate_task");
gst_webrtc_bin_enqueue_task (webrtc, gst_webrtc_bin_enqueue_task (webrtc,
(GstWebRTCBinFunc) _on_local_ice_candidate_task, NULL, NULL); (GstWebRTCBinFunc) _on_local_ice_candidate_task, NULL, NULL, NULL);
} }
} }
@ -4866,8 +4936,18 @@ gst_webrtc_bin_get_stats (GstWebRTCBin * webrtc, GstPad * pad,
if (pad) if (pad)
stats->pad = gst_object_ref (pad); stats->pad = gst_object_ref (pad);
gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _get_stats_task, if (!gst_webrtc_bin_enqueue_task (webrtc, (GstWebRTCBinFunc) _get_stats_task,
stats, (GDestroyNotify) _free_get_stats); stats, (GDestroyNotify) _free_get_stats, promise)) {
GError *error =
g_error_new (GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_CLOSED,
"Could not retrieve statistics. webrtcbin is closed.");
GstStructure *s = gst_structure_new ("application/x-gst-promise-error",
"error", G_TYPE_ERROR, error, NULL);
gst_promise_reply (promise, s);
g_clear_error (&error);
}
} }
static GstWebRTCRTPTransceiver * static GstWebRTCRTPTransceiver *

View file

@ -149,13 +149,14 @@ typedef struct
GstWebRTCBinFunc op; GstWebRTCBinFunc op;
gpointer data; gpointer data;
GDestroyNotify notify; GDestroyNotify notify;
// GstPromise *promise; /* FIXME */ GstPromise *promise;
} GstWebRTCBinTask; } GstWebRTCBinTask;
void gst_webrtc_bin_enqueue_task (GstWebRTCBin * pc, gboolean gst_webrtc_bin_enqueue_task (GstWebRTCBin * pc,
GstWebRTCBinFunc func, GstWebRTCBinFunc func,
gpointer data, gpointer data,
GDestroyNotify notify); GDestroyNotify notify,
GstPromise *promise);
G_END_DECLS G_END_DECLS

View file

@ -91,7 +91,8 @@ _sctp_enqueue_task (GstWebRTCSCTPTransport * sctp, SCTPTask func,
task->notify = notify; task->notify = notify;
gst_webrtc_bin_enqueue_task (sctp->webrtcbin, gst_webrtc_bin_enqueue_task (sctp->webrtcbin,
(GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task); (GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task,
NULL);
} }
static void static void

View file

@ -39,6 +39,7 @@ typedef enum
GST_WEBRTC_BIN_ERROR_FINGERPRINT, GST_WEBRTC_BIN_ERROR_FINGERPRINT,
GST_WEBRTC_BIN_ERROR_SCTP_FAILURE, GST_WEBRTC_BIN_ERROR_SCTP_FAILURE,
GST_WEBRTC_BIN_ERROR_DATA_CHANNEL_FAILURE, GST_WEBRTC_BIN_ERROR_DATA_CHANNEL_FAILURE,
GST_WEBRTC_BIN_ERROR_CLOSED,
} GstWebRTCError; } GstWebRTCError;
GstPadTemplate * _find_pad_template (GstElement * element, GstPadTemplate * _find_pad_template (GstElement * element,

View file

@ -283,7 +283,8 @@ _channel_enqueue_task (GstWebRTCDataChannel * channel, ChannelTask func,
task->notify = notify; task->notify = notify;
gst_webrtc_bin_enqueue_task (channel->webrtcbin, gst_webrtc_bin_enqueue_task (channel->webrtcbin,
(GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task); (GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task,
NULL);
} }
static void static void