Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

WebRTC DTLS handsake quick connection #37

Merged
merged 8 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/gst-plugins/webrtcendpoint/kmswebrtcbundleconnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ kms_webrtc_bundle_connection_add (KmsIRtpConnection * base_rtp_conn,
KmsWebRtcBundleConnectionPrivate *priv = self->priv;
KmsWebRtcTransport *tr = priv->tr;

g_object_set (G_OBJECT (tr->sink->dtlssrtpenc), "is-client", active, NULL);
kms_webrtc_transport_sink_set_dtls_is_client (tr->sink, active);

gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->src)));
gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->sink)));
Expand Down
2 changes: 1 addition & 1 deletion src/gst-plugins/webrtcendpoint/kmswebrtcconnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ kms_webrtc_connection_get_certificate_pem (KmsWebRtcBaseConnection * base_conn)
static void
add_tr (KmsWebRtcTransport * tr, GstBin * bin, gboolean is_client)
{
g_object_set (G_OBJECT (tr->sink->dtlssrtpenc), "is-client", is_client, NULL);
kms_webrtc_transport_sink_set_dtls_is_client(tr->sink, is_client);

gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->src)));
gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->sink)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ kms_webrtc_rtcp_mux_connection_add (KmsIRtpConnection * base_rtp_conn,
KmsWebRtcTransport *tr = priv->tr;

/* srcs */
g_object_set (G_OBJECT (tr->sink->dtlssrtpenc), "is-client", active, NULL);
kms_webrtc_transport_sink_set_dtls_is_client(tr->sink, active);

gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->src)));
gst_bin_add (bin, GST_ELEMENT (g_object_ref (tr->sink)));
Expand Down
2 changes: 1 addition & 1 deletion src/gst-plugins/webrtcendpoint/kmswebrtcsctpconnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ kms_webrtc_sctp_connection_add (KmsIRtpConnection * base_conn, GstBin * bin,
KmsWebRtcSctpConnectionPrivate *priv = self->priv;
KmsWebRtcTransport *tr = priv->tr;

g_object_set (G_OBJECT (tr->sink->dtlssrtpenc), "is-client", active, NULL);
kms_webrtc_transport_sink_set_dtls_is_client(tr->sink, active);

gst_bin_add (bin, GST_ELEMENT (g_object_ref (self->priv->tr->src)));
gst_bin_add (bin, GST_ELEMENT (g_object_ref (self->priv->tr->sink)));
Expand Down
104 changes: 97 additions & 7 deletions src/gst-plugins/webrtcendpoint/kmswebrtctransportsink.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,88 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define kms_webrtc_transport_sink_parent_class parent_class
G_DEFINE_TYPE (KmsWebrtcTransportSink, kms_webrtc_transport_sink, GST_TYPE_BIN);

#define FUNNEL_NAME "funnel"
#define SRTPENC_NAME "srtp-encoder"
#define FUNNEL_FACTORY_NAME "funnel"
#define SRTPENC_FACTORY_NAME "srtpenc"
#define DTLS_ENCODER_FACTORY_NAME "dtlsenc"



static GstElement*
kms_webrtc_transport_sink_get_element_in_dtlssrtpenc (KmsWebrtcTransportSink *self, const gchar *factory_name)
{
GstIterator *iterator;
GValue item = G_VALUE_INIT;
GstElement *element;
GstElementFactory *factory;

factory = gst_element_factory_find (factory_name);

if (factory == NULL) {
GST_WARNING_OBJECT(self, "Factory %s not installed", factory_name);
return NULL;
}

// Until KMS is updated to GStreamer 1.18 and method https://gstreamer.freedesktop.org/documentation/gstreamer/gstbin.html#gst_bin_iterate_all_by_element_factory_name
// is available, this will do
iterator = gst_bin_iterate_elements (GST_BIN(self->dtlssrtpenc));
while (gst_iterator_next (iterator, &item) == GST_ITERATOR_OK) {
element = (GstElement *) g_value_get_object (&item);
if (factory == gst_element_get_factory (element)) {
break;
} else {
element = NULL;
}
}
gst_iterator_free (iterator);
g_object_unref (factory);

if (element != NULL) {
element = g_value_dup_object (&item);
g_value_unset (&item);
}
return element;
}

static void
kms_webrtc_transport_sink_init (KmsWebrtcTransportSink * self)
{
GstElement *dtls_encoder;

self->dtlssrtpenc = gst_element_factory_make ("dtlssrtpenc", NULL);
dtls_encoder = kms_webrtc_transport_sink_get_element_in_dtlssrtpenc (self, DTLS_ENCODER_FACTORY_NAME);
if (dtls_encoder != NULL) {
gst_element_set_locked_state (dtls_encoder, TRUE);
g_object_unref (dtls_encoder);
} else {
GST_WARNING_OBJECT (self, "Cannot get DTLS encoder");
}
}

void
kms_webrtc_transport_sink_connect_elements (KmsWebrtcTransportSink * self)
kms_webrtc_transport_sink_connect_elements (KmsWebrtcTransportSink *self)
{
GstElement *funnel, *srtpenc;

gst_bin_add_many (GST_BIN (self), self->dtlssrtpenc, self->sink, NULL);
gst_element_link (self->dtlssrtpenc, self->sink);

funnel = gst_bin_get_by_name (GST_BIN (self->dtlssrtpenc), FUNNEL_NAME);
funnel = kms_webrtc_transport_sink_get_element_in_dtlssrtpenc (self, FUNNEL_FACTORY_NAME);
if (funnel != NULL) {
g_object_set (funnel, "forward-sticky-events-mode", 0 /* never */ , NULL);
g_object_unref (funnel);
} else {
GST_WARNING ("Cannot get funnel with name %s", FUNNEL_NAME);
GST_WARNING ("Cannot get funnel with factory %s", FUNNEL_FACTORY_NAME);
}

srtpenc = gst_bin_get_by_name (GST_BIN (self->dtlssrtpenc), SRTPENC_NAME);
srtpenc = kms_webrtc_transport_sink_get_element_in_dtlssrtpenc (self, SRTPENC_FACTORY_NAME);
if (srtpenc != NULL) {
g_object_set (srtpenc, "allow-repeat-tx", TRUE, "replay-window-size",
RTP_RTX_SIZE, NULL);
g_object_unref (srtpenc);
} else {
GST_WARNING ("Cannot get srtpenc with name %s", SRTPENC_NAME);
GST_WARNING ("Cannot get srtpenc with factory %s", SRTPENC_FACTORY_NAME);
}

}

void
Expand All @@ -77,6 +126,18 @@ kms_webrtc_transport_sink_configure_default (KmsWebrtcTransportSink * self,
}
}

void
kms_webrtc_transport_sink_set_dtls_is_client_default (KmsWebrtcTransportSink * self,
gboolean is_client)
{
g_object_set (G_OBJECT (self->dtlssrtpenc), "is-client", is_client, NULL);
if (is_client) {
GST_DEBUG_OBJECT(self, "Set as DTLS client (handshake initiator)");
} else {
GST_DEBUG_OBJECT(self, "Set as DTLS server (wait for handshake)");
}
}

void
kms_webrtc_transport_sink_configure (KmsWebrtcTransportSink * self,
KmsIceBaseAgent * agent, const char *stream_id, guint component_id)
Expand All @@ -87,12 +148,23 @@ kms_webrtc_transport_sink_configure (KmsWebrtcTransportSink * self,
klass->configure (self, agent, stream_id, component_id);
}

void
kms_webrtc_transport_sink_set_dtls_is_client (KmsWebrtcTransportSink * self,
gboolean is_client)
{
KmsWebrtcTransportSinkClass *klass =
KMS_WEBRTC_TRANSPORT_SINK_CLASS (G_OBJECT_GET_CLASS (self));

klass->set_dtls_is_client (self, is_client);
}

static void
kms_webrtc_transport_sink_class_init (KmsWebrtcTransportSinkClass * klass)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);

klass->configure = kms_webrtc_transport_sink_configure_default;
klass->set_dtls_is_client = kms_webrtc_transport_sink_set_dtls_is_client_default;

GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
GST_DEFAULT_NAME);
Expand All @@ -104,6 +176,24 @@ kms_webrtc_transport_sink_class_init (KmsWebrtcTransportSinkClass * klass)
"Miguel París Díaz <mparisdiaz@gmail.com>");
}

void
kms_webrtc_transport_sink_start_dtls (KmsWebrtcTransportSink * self)
{
GstElement *dtls_encoder;

dtls_encoder = kms_webrtc_transport_sink_get_element_in_dtlssrtpenc (self, DTLS_ENCODER_FACTORY_NAME);
if (dtls_encoder != NULL) {
gst_element_set_locked_state (dtls_encoder, FALSE);
gst_element_sync_state_with_parent (dtls_encoder);
GST_DEBUG_OBJECT(self, "Starting DTLS");

g_object_unref (dtls_encoder);
} else {
GST_WARNING_OBJECT ("Cannot get DTLS encoder with factory %s", DTLS_ENCODER_FACTORY_NAME);
}
}


KmsWebrtcTransportSink *
kms_webrtc_transport_sink_new ()
{
Expand Down
7 changes: 7 additions & 0 deletions src/gst-plugins/webrtcendpoint/kmswebrtctransportsink.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ struct _KmsWebrtcTransportSinkClass
KmsIceBaseAgent *agent,
const char *stream_id,
guint component_id);

void (*set_dtls_is_client) (KmsWebrtcTransportSink * self,
gboolean is_client);
};

GType kms_webrtc_transport_sink_get_type (void);
Expand All @@ -65,5 +68,9 @@ void kms_webrtc_transport_sink_configure (KmsWebrtcTransportSink * self,
KmsIceBaseAgent *agent,
const char *stream_id,
guint component_id);
void kms_webrtc_transport_sink_set_dtls_is_client (KmsWebrtcTransportSink * self,
gboolean is_client);
void kms_webrtc_transport_sink_start_dtls (KmsWebrtcTransportSink * self);

G_END_DECLS
#endif /* __KMS_WEBRTC_TRANSPORT_SINK_H__ */
40 changes: 40 additions & 0 deletions src/gst-plugins/webrtcendpoint/kmswebrtctransportsinknice.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ kms_webrtc_transport_sink_nice_init (KmsWebrtcTransportSinkNice * self)
kms_webrtc_transport_sink_connect_elements (parent);
}

static void
kms_webrtc_transport_sink_nice_component_state_changed (KmsIceBaseAgent * agent,
char *stream_id, guint component_id, IceState state,
KmsWebrtcTransportSink * self)
{
gboolean is_client;

GST_LOG_OBJECT (self,
"[IceComponentStateChanged] state: %s, stream_id: %s, component_id: %u",
kms_ice_base_agent_state_to_string (state), stream_id, component_id);

g_object_get (G_OBJECT (self->dtlssrtpenc), "is-client",
&is_client, NULL);

if ((state == ICE_STATE_CONNECTED) && is_client) {
kms_webrtc_transport_sink_start_dtls (self);
}
}

void
kms_webrtc_transport_sink_nice_configure (KmsWebrtcTransportSink * self,
KmsIceBaseAgent * agent, const char *stream_id, guint component_id)
Expand All @@ -53,6 +72,26 @@ kms_webrtc_transport_sink_nice_configure (KmsWebrtcTransportSink * self,
"agent", kms_ice_nice_agent_get_agent (nice_agent),
"stream", id, "component", component_id,
"sync", FALSE, "async", FALSE, NULL);

g_signal_connect (nice_agent, "on-ice-component-state-changed",
G_CALLBACK (kms_webrtc_transport_sink_nice_component_state_changed), self);
}

void
kms_webrtc_transport_sink_nice_set_dtls_is_client (KmsWebrtcTransportSink * self,
gboolean is_client)
{
KmsWebrtcTransportSinkNiceClass *klass =
KMS_WEBRTC_TRANSPORT_SINK_NICE_CLASS (G_OBJECT_GET_CLASS (self));
KmsWebrtcTransportSinkClass *parent_klass =
KMS_WEBRTC_TRANSPORT_SINK_CLASS (g_type_class_peek_parent(klass));

parent_klass->set_dtls_is_client (self, is_client);

if (!is_client) {
kms_webrtc_transport_sink_start_dtls (self);
}

}

static void
Expand All @@ -64,6 +103,7 @@ kms_webrtc_transport_sink_nice_class_init (KmsWebrtcTransportSinkNiceClass *

base_class = KMS_WEBRTC_TRANSPORT_SINK_CLASS (klass);
base_class->configure = kms_webrtc_transport_sink_nice_configure;
base_class->set_dtls_is_client = kms_webrtc_transport_sink_nice_set_dtls_is_client;

GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
GST_DEFAULT_NAME);
Expand Down
1 change: 1 addition & 0 deletions tests/check/element/webrtcendpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,7 @@ test_data_channels (gboolean bundle)

GST_WARNING ("Finishing test");

g_usleep (500000);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_bus_remove_signal_watch (bus);
g_object_unref (bus);
Expand Down
Loading