mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
stream: add SRTP support
Install srtp encoder and decoder elements in rtpbin Add MIKEY in SDP
This commit is contained in:
parent
bfbf393925
commit
3d6175c745
5 changed files with 205 additions and 2 deletions
|
@ -59,6 +59,7 @@ dnl *** required versions of GStreamer stuff ***
|
||||||
GST_REQ=1.3.0.1
|
GST_REQ=1.3.0.1
|
||||||
GSTPB_REQ=1.3.0.1
|
GSTPB_REQ=1.3.0.1
|
||||||
GSTPG_REQ=1.3.0.1
|
GSTPG_REQ=1.3.0.1
|
||||||
|
GSTPD_REQ=1.3.0.1
|
||||||
|
|
||||||
dnl *** autotools stuff ****
|
dnl *** autotools stuff ****
|
||||||
|
|
||||||
|
@ -176,6 +177,11 @@ GSTPG_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-good-$GST_API_VERSION --variabl
|
||||||
AC_SUBST(GSTPG_PLUGINS_DIR)
|
AC_SUBST(GSTPG_PLUGINS_DIR)
|
||||||
AC_MSG_NOTICE(Using GStreamer Good Plugins in $GSTPG_PLUGINS_DIR)
|
AC_MSG_NOTICE(Using GStreamer Good Plugins in $GSTPG_PLUGINS_DIR)
|
||||||
|
|
||||||
|
AG_GST_CHECK_GST_PLUGINS_BAD($GST_API_VERSION, [$GSTPD_REQ], [yes])
|
||||||
|
GSTPD_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-bad-$GST_API_VERSION --variable pluginsdir`
|
||||||
|
AC_SUBST(GSTPD_PLUGINS_DIR)
|
||||||
|
AC_MSG_NOTICE(Using GStreamer Bad Plugins in $GSTPD_PLUGINS_DIR)
|
||||||
|
|
||||||
AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
|
AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
|
||||||
AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
|
AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ main (int argc, char *argv[])
|
||||||
gst_rtsp_media_factory_set_permissions (factory, permissions);
|
gst_rtsp_media_factory_set_permissions (factory, permissions);
|
||||||
gst_rtsp_permissions_unref (permissions);
|
gst_rtsp_permissions_unref (permissions);
|
||||||
#endif
|
#endif
|
||||||
|
gst_rtsp_media_factory_set_profiles (factory, GST_RTSP_PROFILE_SAVP);
|
||||||
|
|
||||||
/* attach the test factory to the /test url */
|
/* attach the test factory to the /test url */
|
||||||
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
|
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gst/sdp/gstmikey.h>
|
||||||
|
|
||||||
#include "rtsp-sdp.h"
|
#include "rtsp-sdp.h"
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -171,6 +173,93 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
|
||||||
gst_sdp_media_add_attribute (smedia, "control", tmp);
|
gst_sdp_media_add_attribute (smedia, "control", tmp);
|
||||||
g_free (tmp);
|
g_free (tmp);
|
||||||
|
|
||||||
|
|
||||||
|
/* check for srtp */
|
||||||
|
do {
|
||||||
|
GstBuffer *srtpkey;
|
||||||
|
const GValue *val;
|
||||||
|
const gchar *srtpcipher, *srtpauth, *srtcpcipher, *srtcpauth;
|
||||||
|
GstMIKEYMessage *msg;
|
||||||
|
GstMIKEYPayload *payload;
|
||||||
|
GBytes *bytes;
|
||||||
|
GstMapInfo info;
|
||||||
|
const guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
gchar *base64;
|
||||||
|
guint8 byte;
|
||||||
|
guint32 ssrc;
|
||||||
|
|
||||||
|
val = gst_structure_get_value (s, "srtp-key");
|
||||||
|
if (val == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
srtpkey = gst_value_get_buffer (val);
|
||||||
|
if (srtpkey == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
srtpcipher = gst_structure_get_string (s, "srtp-cipher");
|
||||||
|
srtpauth = gst_structure_get_string (s, "srtp-auth");
|
||||||
|
srtcpcipher = gst_structure_get_string (s, "srtcp-cipher");
|
||||||
|
srtcpauth = gst_structure_get_string (s, "srtcp-auth");
|
||||||
|
|
||||||
|
if (srtpcipher == NULL || srtpauth == NULL || srtcpcipher == NULL ||
|
||||||
|
srtcpauth == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
msg = gst_mikey_message_new ();
|
||||||
|
/* unencrypted MIKEY message, we send this over TLS so this is allowed */
|
||||||
|
gst_mikey_message_set_info (msg, GST_MIKEY_VERSION, GST_MIKEY_TYPE_PSK_INIT,
|
||||||
|
FALSE, GST_MIKEY_PRF_MIKEY_1, 0, GST_MIKEY_MAP_TYPE_SRTP);
|
||||||
|
/* add policy '0' for our SSRC */
|
||||||
|
gst_rtsp_stream_get_ssrc (stream, &ssrc);
|
||||||
|
gst_mikey_message_add_cs_srtp (msg, 0, ssrc, 0);
|
||||||
|
/* timestamp is now */
|
||||||
|
gst_mikey_message_add_t_now_ntp_utc (msg);
|
||||||
|
/* add some random data */
|
||||||
|
gst_mikey_message_add_rand_len (msg, 16);
|
||||||
|
|
||||||
|
/* the policy '0' is SRTP with the above discovered algorithms */
|
||||||
|
payload = gst_mikey_payload_new (GST_MIKEY_PT_SP);
|
||||||
|
gst_mikey_payload_sp_set (payload, 0, GST_MIKEY_SEC_PROTO_SRTP);
|
||||||
|
|
||||||
|
/* only AES-CM is supported */
|
||||||
|
byte = 1;
|
||||||
|
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_ALG, 1,
|
||||||
|
&byte);
|
||||||
|
/* only HMAC-SHA1 */
|
||||||
|
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_ALG, 1,
|
||||||
|
&byte);
|
||||||
|
/* we enable encryption on RTP and RTCP */
|
||||||
|
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_ENC, 1,
|
||||||
|
&byte);
|
||||||
|
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTCP_ENC, 1,
|
||||||
|
&byte);
|
||||||
|
/* we enable authentication on RTP and RTCP */
|
||||||
|
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_AUTH, 1,
|
||||||
|
&byte);
|
||||||
|
gst_mikey_message_add_payload (msg, payload);
|
||||||
|
|
||||||
|
/* add the key in KEMAC */
|
||||||
|
gst_buffer_map (srtpkey, &info, GST_MAP_READ);
|
||||||
|
gst_mikey_message_add_kemac (msg, GST_MIKEY_ENC_NULL, info.size, info.data,
|
||||||
|
GST_MIKEY_MAC_NULL, NULL);
|
||||||
|
gst_buffer_unmap (srtpkey, &info);
|
||||||
|
|
||||||
|
/* now serialize this to bytes */
|
||||||
|
bytes = gst_mikey_message_to_bytes (msg);
|
||||||
|
gst_mikey_message_free (msg);
|
||||||
|
/* and make it into base64 */
|
||||||
|
data = g_bytes_get_data (bytes, &size);
|
||||||
|
base64 = g_base64_encode (data, size);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
|
||||||
|
tmp = g_strdup_printf ("mikey %s", base64);
|
||||||
|
g_free (base64);
|
||||||
|
|
||||||
|
gst_sdp_media_add_attribute (smedia, "key-mgmt", tmp);
|
||||||
|
g_free (tmp);
|
||||||
|
} while (FALSE);
|
||||||
|
|
||||||
/* collect all other properties and add them to fmtp or attributes */
|
/* collect all other properties and add them to fmtp or attributes */
|
||||||
fmtp = g_string_new ("");
|
fmtp = g_string_new ("");
|
||||||
g_string_append_printf (fmtp, "%d ", caps_pt);
|
g_string_append_printf (fmtp, "%d ", caps_pt);
|
||||||
|
@ -198,6 +287,10 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
|
||||||
continue;
|
continue;
|
||||||
if (!strcmp (fname, "seqnum-base"))
|
if (!strcmp (fname, "seqnum-base"))
|
||||||
continue;
|
continue;
|
||||||
|
if (g_str_has_prefix (fname, "srtp-"))
|
||||||
|
continue;
|
||||||
|
if (g_str_has_prefix (fname, "srtcp-"))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (g_str_has_prefix (fname, "a-")) {
|
if (g_str_has_prefix (fname, "a-")) {
|
||||||
/* attribute */
|
/* attribute */
|
||||||
|
|
|
@ -79,6 +79,10 @@ struct _GstRTSPStreamPrivate
|
||||||
/* the RTPSession object */
|
/* the RTPSession object */
|
||||||
GObject *session;
|
GObject *session;
|
||||||
|
|
||||||
|
/* SRTP encoder/decoder */
|
||||||
|
GstElement *srtpenc;
|
||||||
|
GstElement *srtpdec;
|
||||||
|
|
||||||
/* sinks used for sending and receiving RTP and RTCP over ipv4, they share
|
/* sinks used for sending and receiving RTP and RTCP over ipv4, they share
|
||||||
* sockets */
|
* sockets */
|
||||||
GstElement *udpsrc_v4[2];
|
GstElement *udpsrc_v4[2];
|
||||||
|
@ -1503,6 +1507,87 @@ static GstAppSinkCallbacks sink_cb = {
|
||||||
handle_new_sample,
|
handle_new_sample,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
get_rtp_encoder (GstRTSPStream * stream, guint session)
|
||||||
|
{
|
||||||
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
|
|
||||||
|
if (priv->srtpenc == NULL) {
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
name = g_strdup_printf ("srtpenc_%u", session);
|
||||||
|
priv->srtpenc = gst_element_factory_make ("srtpenc", name);
|
||||||
|
g_free (name);
|
||||||
|
|
||||||
|
g_object_set (priv->srtpenc, "random-key", TRUE, NULL);
|
||||||
|
}
|
||||||
|
return gst_object_ref (priv->srtpenc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
request_rtp_encoder (GstElement * rtpbin, guint session, GstRTSPStream * stream)
|
||||||
|
{
|
||||||
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
|
GstElement *enc;
|
||||||
|
GstPad *pad;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
if (priv->idx != session)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (stream, "make RTP encoder for session %u", session);
|
||||||
|
|
||||||
|
enc = get_rtp_encoder (stream, session);
|
||||||
|
name = g_strdup_printf ("rtp_sink_%d", session);
|
||||||
|
pad = gst_element_get_request_pad (enc, name);
|
||||||
|
g_free (name);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
|
return enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
request_rtcp_encoder (GstElement * rtpbin, guint session,
|
||||||
|
GstRTSPStream * stream)
|
||||||
|
{
|
||||||
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
|
GstElement *enc;
|
||||||
|
GstPad *pad;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
if (priv->idx != session)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (stream, "make RTCP encoder for session %u", session);
|
||||||
|
|
||||||
|
enc = get_rtp_encoder (stream, session);
|
||||||
|
name = g_strdup_printf ("rtcp_sink_%d", session);
|
||||||
|
pad = gst_element_get_request_pad (enc, name);
|
||||||
|
g_free (name);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
|
return enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
request_rtcp_decoder (GstElement * rtpbin, guint session,
|
||||||
|
GstRTSPStream * stream)
|
||||||
|
{
|
||||||
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
|
|
||||||
|
if (priv->idx != session)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (priv->srtpdec == NULL) {
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
name = g_strdup_printf ("srtpdec_%u", session);
|
||||||
|
priv->srtpdec = gst_element_factory_make ("srtpdec", name);
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
return gst_object_ref (priv->srtpdec);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_stream_join_bin:
|
* gst_rtsp_stream_join_bin:
|
||||||
* @stream: a #GstRTSPStream
|
* @stream: a #GstRTSPStream
|
||||||
|
@ -1549,6 +1634,21 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
|
||||||
/* update the dscp qos field in the sinks */
|
/* update the dscp qos field in the sinks */
|
||||||
update_dscp_qos (stream);
|
update_dscp_qos (stream);
|
||||||
|
|
||||||
|
if (priv->profiles & GST_RTSP_PROFILE_SAVP
|
||||||
|
|| priv->profiles & GST_RTSP_PROFILE_SAVPF) {
|
||||||
|
/* For SRTP */
|
||||||
|
g_signal_connect (rtpbin, "request-rtp-encoder",
|
||||||
|
(GCallback) request_rtp_encoder, stream);
|
||||||
|
g_signal_connect (rtpbin, "request-rtcp-encoder",
|
||||||
|
(GCallback) request_rtcp_encoder, stream);
|
||||||
|
#if 0
|
||||||
|
g_signal_connect (rtpbin, "request-rtp-decoder",
|
||||||
|
(GCallback) request_rtp_decoder, stream);
|
||||||
|
#endif
|
||||||
|
g_signal_connect (rtpbin, "request-rtcp-decoder",
|
||||||
|
(GCallback) request_rtcp_decoder, stream);
|
||||||
|
}
|
||||||
|
|
||||||
/* get a pad for sending RTP */
|
/* get a pad for sending RTP */
|
||||||
name = g_strdup_printf ("send_rtp_sink_%u", idx);
|
name = g_strdup_printf ("send_rtp_sink_%u", idx);
|
||||||
priv->send_rtp_sink = gst_element_get_request_pad (rtpbin, name);
|
priv->send_rtp_sink = gst_element_get_request_pad (rtpbin, name);
|
||||||
|
@ -1873,6 +1973,9 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
|
||||||
gst_caps_unref (priv->caps);
|
gst_caps_unref (priv->caps);
|
||||||
priv->caps = NULL;
|
priv->caps = NULL;
|
||||||
|
|
||||||
|
if (priv->srtpenc)
|
||||||
|
gst_object_unref (priv->srtpenc);
|
||||||
|
|
||||||
priv->is_joined = FALSE;
|
priv->is_joined = FALSE;
|
||||||
g_mutex_unlock (&priv->lock);
|
g_mutex_unlock (&priv->lock);
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ TESTS_ENVIRONMENT = \
|
||||||
GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \
|
GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \
|
||||||
$(REGISTRY_ENVIRONMENT) \
|
$(REGISTRY_ENVIRONMENT) \
|
||||||
GST_PLUGIN_SYSTEM_PATH_1_0= \
|
GST_PLUGIN_SYSTEM_PATH_1_0= \
|
||||||
GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR) \
|
GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR):$(GSTPD_PLUGINS_DIR) \
|
||||||
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good"
|
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good:gst-plugins-bad"
|
||||||
|
|
||||||
|
|
||||||
# ths core dumps of some machines have PIDs appended
|
# ths core dumps of some machines have PIDs appended
|
||||||
|
|
Loading…
Reference in a new issue