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 7 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
99 changes: 92 additions & 7 deletions src/gst-plugins/webrtcendpoint/kmswebrtctransportsink.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,83 @@ 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);
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 +121,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 +143,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 +171,24 @@ kms_webrtc_transport_sink_class_init (KmsWebrtcTransportSinkClass * klass)
"Miguel París Díaz <[email protected]>");
}

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