mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +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
|
||||
GSTPB_REQ=1.3.0.1
|
||||
GSTPG_REQ=1.3.0.1
|
||||
GSTPD_REQ=1.3.0.1
|
||||
|
||||
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_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)
|
||||
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_permissions_unref (permissions);
|
||||
#endif
|
||||
gst_rtsp_media_factory_set_profiles (factory, GST_RTSP_PROFILE_SAVP);
|
||||
|
||||
/* attach the test factory to the /test url */
|
||||
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/sdp/gstmikey.h>
|
||||
|
||||
#include "rtsp-sdp.h"
|
||||
|
||||
static gboolean
|
||||
|
@ -171,6 +173,93 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
|
|||
gst_sdp_media_add_attribute (smedia, "control", 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 */
|
||||
fmtp = g_string_new ("");
|
||||
g_string_append_printf (fmtp, "%d ", caps_pt);
|
||||
|
@ -198,6 +287,10 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPMedia * media,
|
|||
continue;
|
||||
if (!strcmp (fname, "seqnum-base"))
|
||||
continue;
|
||||
if (g_str_has_prefix (fname, "srtp-"))
|
||||
continue;
|
||||
if (g_str_has_prefix (fname, "srtcp-"))
|
||||
continue;
|
||||
|
||||
if (g_str_has_prefix (fname, "a-")) {
|
||||
/* attribute */
|
||||
|
|
|
@ -79,6 +79,10 @@ struct _GstRTSPStreamPrivate
|
|||
/* the RTPSession object */
|
||||
GObject *session;
|
||||
|
||||
/* SRTP encoder/decoder */
|
||||
GstElement *srtpenc;
|
||||
GstElement *srtpdec;
|
||||
|
||||
/* sinks used for sending and receiving RTP and RTCP over ipv4, they share
|
||||
* sockets */
|
||||
GstElement *udpsrc_v4[2];
|
||||
|
@ -1503,6 +1507,87 @@ static GstAppSinkCallbacks sink_cb = {
|
|||
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:
|
||||
* @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_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 */
|
||||
name = g_strdup_printf ("send_rtp_sink_%u", idx);
|
||||
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);
|
||||
priv->caps = NULL;
|
||||
|
||||
if (priv->srtpenc)
|
||||
gst_object_unref (priv->srtpenc);
|
||||
|
||||
priv->is_joined = FALSE;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ TESTS_ENVIRONMENT = \
|
|||
GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \
|
||||
$(REGISTRY_ENVIRONMENT) \
|
||||
GST_PLUGIN_SYSTEM_PATH_1_0= \
|
||||
GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR) \
|
||||
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good"
|
||||
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-plugins-bad"
|
||||
|
||||
|
||||
# ths core dumps of some machines have PIDs appended
|
||||
|
|
Loading…
Reference in a new issue