2 * GStreamer - GStreamer SRTP decoder
4 * Copyright 2009-2011 Collabora Ltd.
5 * @author: Gabriel Millaire <gabriel.millaire@collabora.co.uk>
6 * @author: Olivier Crete <olivier.crete@collabora.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * Alternatively, the contents of this file may be used under the
27 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28 * which case the following provisions apply instead of the ones
31 * This library is free software; you can redistribute it and/or
32 * modify it under the terms of the GNU Library General Public
33 * License as published by the Free Software Foundation; either
34 * version 2 of the License, or (at your option) any later version.
36 * This library is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 * Library General Public License for more details.
41 * You should have received a copy of the GNU Library General Public
42 * License along with this library; if not, write to the
43 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44 * Boston, MA 02111-1307, USA.
48 * SECTION:element-srtpdec
52 * gstrtpdec acts as a decoder that removes security from SRTP and SRTCP
53 * packets (encryption and authentication) and out RTP and RTCP. It
54 * receives packet of type 'application/x-srtp' or 'application/x-srtcp'
55 * on its sink pad, and outs packets of type 'application/x-rtp' or
56 * 'application/x-rtcp' on its source pad.
58 * For each packet received, it checks if the internal SSRC is in the list
59 * of streams already in use. If this is not the case, it sends a signal to
60 * the user to get the needed parameters to create a new stream : master
61 * key, encryption and authentication mechanisms for both RTP and RTCP. If
62 * the user can't provide those parameters, the buffer is dropped and a
65 * This element uses libsrtp library. The encryption and authentication
66 * mechanisms available are :
69 * - AES_ICM 256 bits (maximum security)
70 * - AES_ICM 128 bits (default)
74 * - HMAC_SHA1 80 bits (default, maximum protection)
78 * Note that for SRTP protection, authentication is mandatory (non-null)
79 * if encryption is used (non-null).
81 * Each packet received is first analysed (checked for valid SSRC) then
82 * its buffer is unprotected with libsrtp, then pushed on the source pad.
83 * If protection failed or the stream could not be created, the buffer
84 * is dropped and a warning is emitted.
86 * When the maximum usage of the master key is reached, a soft-limit
87 * signal is sent to the user, and new parameters (master key) are needed
88 * in return. If the hard limit is reached, a flag is set and every
89 * subsequent packet is dropped, until a new key is set and the stream
92 * If a stream is to be shared between multiple clients the SRTP
93 * rollover counter for a given SSRC must be set in the caps "roc" field
94 * when the request-key signal is emitted by the decoder. The rollover
95 * counters should have been transmitted by a signaling protocol by some
96 * other means. If no rollover counter is provided by the user, 0 is
99 * It is possible to receive a stream protected by multiple master keys, each buffer
100 * then contains a Master Key Identifier (MKI) to identify which key was used for this
101 * buffer. If multiple keys are needed, the first key can be specified in the caps as
102 * "srtp-key=(buffer)key1data, mki=(buffer)mki1data", then the second one can be given in
103 * the same caps as "srtp-key2=(buffer)key2data, mki2=(buffer)mki2data", and more can
106 * ## Example pipelines
108 * gst-launch-1.0 udpsrc port=5004 caps='application/x-srtp, payload=(int)8, ssrc=(uint)1356955624, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, srtp-cipher=(string)aes-128-icm, srtp-auth=(string)hmac-sha1-80, srtcp-cipher=(string)aes-128-icm, srtcp-auth=(string)hmac-sha1-80' ! srtpdec ! rtppcmadepay ! alawdec ! pulsesink
109 * ]| Receive PCMA SRTP packets through UDP using caps to specify
110 * master key and protection.
112 * gst-launch-1.0 audiotestsrc ! alawenc ! rtppcmapay ! 'application/x-rtp, payload=(int)8, ssrc=(uint)1356955624' ! srtpenc key="012345678901234567890123456789012345678901234567890123456789" ! udpsink port=5004
113 * ]| Send PCMA SRTP packets through UDP, nothing how the SSRC is forced so
114 * that the receiver will recognize it.
118 #include "gstsrtpelements.h"
119 #include "gstsrtpdec.h"
120 #include <gst/rtp/gstrtpbuffer.h>
123 GST_DEBUG_CATEGORY_STATIC (gst_srtp_dec_debug);
124 #define GST_CAT_DEFAULT gst_srtp_dec_debug
126 #define DEFAULT_REPLAY_WINDOW_SIZE 128
128 /* Filter signals and args */
131 SIGNAL_REQUEST_KEY = 1,
142 PROP_REPLAY_WINDOW_SIZE,
146 /* the capabilities of the inputs and outputs.
148 * describe the real formats here.
150 static GstStaticPadTemplate rtp_sink_template =
151 GST_STATIC_PAD_TEMPLATE ("rtp_sink",
154 GST_STATIC_CAPS ("application/x-srtp")
157 static GstStaticPadTemplate rtp_src_template =
158 GST_STATIC_PAD_TEMPLATE ("rtp_src",
161 GST_STATIC_CAPS ("application/x-rtp")
164 static GstStaticPadTemplate rtcp_sink_template =
165 GST_STATIC_PAD_TEMPLATE ("rtcp_sink",
168 GST_STATIC_CAPS ("application/x-srtcp")
171 static GstStaticPadTemplate rtcp_src_template =
172 GST_STATIC_PAD_TEMPLATE ("rtcp_src",
175 GST_STATIC_CAPS ("application/x-rtcp")
178 static guint gst_srtp_dec_signals[LAST_SIGNAL] = { 0 };
180 G_DEFINE_TYPE_WITH_CODE (GstSrtpDec, gst_srtp_dec, GST_TYPE_ELEMENT,
181 GST_DEBUG_CATEGORY_INIT (gst_srtp_dec_debug, "srtpdec", 0, "SRTP dec");
183 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (srtpdec, "srtpdec", GST_RANK_NONE,
184 GST_TYPE_SRTP_DEC, srtp_element_init (plugin));
186 static void gst_srtp_dec_set_property (GObject * object, guint prop_id,
187 const GValue * value, GParamSpec * pspec);
188 static void gst_srtp_dec_get_property (GObject * object, guint prop_id,
189 GValue * value, GParamSpec * pspec);
191 static void gst_srtp_dec_clear_streams (GstSrtpDec * filter);
192 static void gst_srtp_dec_remove_stream (GstSrtpDec * filter, guint ssrc);
194 static gboolean gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent,
196 static gboolean gst_srtp_dec_sink_event_rtcp (GstPad * pad, GstObject * parent,
199 static gboolean gst_srtp_dec_sink_query_rtp (GstPad * pad, GstObject * parent,
201 static gboolean gst_srtp_dec_sink_query_rtcp (GstPad * pad,
202 GstObject * parent, GstQuery * query);
205 static GstIterator *gst_srtp_dec_iterate_internal_links_rtp (GstPad * pad,
207 static GstIterator *gst_srtp_dec_iterate_internal_links_rtcp (GstPad * pad,
210 static GstFlowReturn gst_srtp_dec_chain_rtp (GstPad * pad,
211 GstObject * parent, GstBuffer * buf);
212 static GstFlowReturn gst_srtp_dec_chain_rtcp (GstPad * pad,
213 GstObject * parent, GstBuffer * buf);
215 static GstStateChangeReturn gst_srtp_dec_change_state (GstElement * element,
216 GstStateChange transition);
218 static GstSrtpDecSsrcStream *request_key_with_signal (GstSrtpDec * filter,
219 guint32 ssrc, gint signal);
221 struct _GstSrtpDecSsrcStream
227 GstSrtpCipherType rtp_cipher;
228 GstSrtpAuthType rtp_auth;
229 GstSrtpCipherType rtcp_cipher;
230 GstSrtpAuthType rtcp_auth;
233 guint recv_drop_count;
244 #define STREAM_HAS_CRYPTO(stream) \
245 (stream->rtp_cipher != GST_SRTP_CIPHER_NULL || \
246 stream->rtcp_cipher != GST_SRTP_CIPHER_NULL || \
247 stream->rtp_auth != GST_SRTP_AUTH_NULL || \
248 stream->rtcp_auth != GST_SRTP_AUTH_NULL)
251 /* initialize the srtpdec's class */
253 gst_srtp_dec_class_init (GstSrtpDecClass * klass)
255 GObjectClass *gobject_class;
256 GstElementClass *gstelement_class;
258 gobject_class = (GObjectClass *) klass;
259 gstelement_class = (GstElementClass *) klass;
261 gobject_class->set_property = gst_srtp_dec_set_property;
262 gobject_class->get_property = gst_srtp_dec_get_property;
264 gst_element_class_add_static_pad_template (gstelement_class,
266 gst_element_class_add_static_pad_template (gstelement_class,
268 gst_element_class_add_static_pad_template (gstelement_class,
270 gst_element_class_add_static_pad_template (gstelement_class,
271 &rtcp_sink_template);
273 gst_element_class_set_static_metadata (gstelement_class, "SRTP decoder",
274 "Filter/Network/SRTP",
275 "A SRTP and SRTCP decoder",
276 "Gabriel Millaire <millaire.gabriel@collabora.com>");
278 /* Install callbacks */
279 gstelement_class->change_state =
280 GST_DEBUG_FUNCPTR (gst_srtp_dec_change_state);
282 klass->clear_streams = GST_DEBUG_FUNCPTR (gst_srtp_dec_clear_streams);
283 klass->remove_stream = GST_DEBUG_FUNCPTR (gst_srtp_dec_remove_stream);
285 /* Install properties */
286 g_object_class_install_property (gobject_class, PROP_REPLAY_WINDOW_SIZE,
287 g_param_spec_uint ("replay-window-size", "Replay window size",
288 "Size of the replay protection window",
289 64, 0x8000, DEFAULT_REPLAY_WINDOW_SIZE,
290 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
291 g_object_class_install_property (gobject_class, PROP_STATS,
292 g_param_spec_boxed ("stats", "Statistics", "Various statistics",
293 GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
295 /* Install signals */
297 * GstSrtpDec::request-key:
298 * @gstsrtpdec: the element on which the signal is emitted
299 * @ssrc: The unique SSRC of the stream
301 * Signal emitted to get the parameters relevant to stream
302 * with @ssrc. User should provide the key and the RTP and
303 * RTCP encryption ciphers and authentication, and return
304 * them wrapped in a GstCaps.
306 gst_srtp_dec_signals[SIGNAL_REQUEST_KEY] =
307 g_signal_new ("request-key", G_TYPE_FROM_CLASS (klass),
308 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
311 * GstSrtpDec::clear-keys:
312 * @gstsrtpdec: the element on which the signal is emitted
314 * Clear the internal list of streams
316 gst_srtp_dec_signals[SIGNAL_CLEAR_KEYS] =
317 g_signal_new ("clear-keys", G_TYPE_FROM_CLASS (klass),
318 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
319 G_STRUCT_OFFSET (GstSrtpDecClass, clear_streams), NULL, NULL, NULL,
320 G_TYPE_NONE, 0, G_TYPE_NONE);
323 * GstSrtpDec::soft-limit:
324 * @gstsrtpdec: the element on which the signal is emitted
325 * @ssrc: The unique SSRC of the stream
327 * Signal emitted when the stream with @ssrc has reached the
328 * soft limit of utilisation of it's master encryption key.
329 * User should provide a new key and new RTP and RTCP encryption
330 * ciphers and authentication, and return them wrapped in a
333 gst_srtp_dec_signals[SIGNAL_SOFT_LIMIT] =
334 g_signal_new ("soft-limit", G_TYPE_FROM_CLASS (klass),
335 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
338 * GstSrtpDec::hard-limit:
339 * @gstsrtpdec: the element on which the signal is emitted
340 * @ssrc: The unique SSRC of the stream
342 * Signal emitted when the stream with @ssrc has reached the
343 * hard limit of utilisation of it's master encryption key.
344 * User should provide a new key and new RTP and RTCP encryption
345 * ciphers and authentication, and return them wrapped in a
346 * GstCaps. If user could not provide those parameters or signal
347 * is not answered, the buffers of this stream will be dropped.
349 gst_srtp_dec_signals[SIGNAL_HARD_LIMIT] =
350 g_signal_new ("hard-limit", G_TYPE_FROM_CLASS (klass),
351 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
354 * GstSrtpDec::remove-key:
355 * @gstsrtpdec: the element on which the signal is emitted
356 * @ssrc: The SSRC for which to remove the key.
358 * Removes keys for a specific SSRC
360 gst_srtp_dec_signals[SIGNAL_REMOVE_KEY] =
361 g_signal_new ("remove-key", G_TYPE_FROM_CLASS (klass),
362 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
363 G_STRUCT_OFFSET (GstSrtpDecClass, remove_stream), NULL, NULL, NULL,
364 G_TYPE_NONE, 1, G_TYPE_UINT);
368 /* initialize the new element
369 * instantiate pads and add them to element
370 * set pad callback functions
371 * initialize instance structure
374 gst_srtp_dec_init (GstSrtpDec * filter)
376 filter->replay_window_size = DEFAULT_REPLAY_WINDOW_SIZE;
378 filter->rtp_sinkpad =
379 gst_pad_new_from_static_template (&rtp_sink_template, "rtp_sink");
380 gst_pad_set_event_function (filter->rtp_sinkpad,
381 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_event_rtp));
382 gst_pad_set_query_function (filter->rtp_sinkpad,
383 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_query_rtp));
384 gst_pad_set_iterate_internal_links_function (filter->rtp_sinkpad,
385 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtp));
386 gst_pad_set_chain_function (filter->rtp_sinkpad,
387 GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtp));
390 gst_pad_new_from_static_template (&rtp_src_template, "rtp_src");
391 gst_pad_set_iterate_internal_links_function (filter->rtp_srcpad,
392 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtp));
394 gst_pad_set_element_private (filter->rtp_sinkpad, filter->rtp_srcpad);
395 gst_pad_set_element_private (filter->rtp_srcpad, filter->rtp_sinkpad);
397 gst_element_add_pad (GST_ELEMENT (filter), filter->rtp_sinkpad);
398 gst_element_add_pad (GST_ELEMENT (filter), filter->rtp_srcpad);
401 filter->rtcp_sinkpad =
402 gst_pad_new_from_static_template (&rtcp_sink_template, "rtcp_sink");
403 gst_pad_set_event_function (filter->rtcp_sinkpad,
404 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_event_rtcp));
405 gst_pad_set_query_function (filter->rtcp_sinkpad,
406 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_query_rtcp));
407 gst_pad_set_iterate_internal_links_function (filter->rtcp_sinkpad,
408 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtcp));
409 gst_pad_set_chain_function (filter->rtcp_sinkpad,
410 GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtcp));
412 filter->rtcp_srcpad =
413 gst_pad_new_from_static_template (&rtcp_src_template, "rtcp_src");
414 gst_pad_set_iterate_internal_links_function (filter->rtcp_srcpad,
415 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtcp));
417 gst_pad_set_element_private (filter->rtcp_sinkpad, filter->rtcp_srcpad);
418 gst_pad_set_element_private (filter->rtcp_srcpad, filter->rtcp_sinkpad);
420 gst_element_add_pad (GST_ELEMENT (filter), filter->rtcp_sinkpad);
421 gst_element_add_pad (GST_ELEMENT (filter), filter->rtcp_srcpad);
423 filter->first_session = TRUE;
426 static GstStructure *
427 gst_srtp_dec_create_stats (GstSrtpDec * filter)
430 GValue va = G_VALUE_INIT;
431 GValue v = G_VALUE_INIT;
433 s = gst_structure_new_empty ("application/x-srtp-decoder-stats");
435 g_value_init (&va, GST_TYPE_ARRAY);
436 g_value_init (&v, GST_TYPE_STRUCTURE);
438 if (filter->session) {
442 g_hash_table_iter_init (&iter, filter->streams);
443 while (g_hash_table_iter_next (&iter, &key, &value)) {
444 GstSrtpDecSsrcStream *stream = value;
446 guint32 ssrc = GPOINTER_TO_UINT (key);
447 srtp_err_status_t status;
450 status = srtp_get_stream_roc (filter->session, ssrc, &roc);
451 if (status != srtp_err_status_ok) {
455 ss = gst_structure_new ("application/x-srtp-stream",
456 "ssrc", G_TYPE_UINT, ssrc, "roc", G_TYPE_UINT, roc, "recv-count",
457 G_TYPE_UINT, stream->recv_count, "recv-drop-count", G_TYPE_UINT,
458 stream->recv_drop_count, NULL);
460 g_value_take_boxed (&v, ss);
461 gst_value_array_append_value (&va, &v);
465 gst_structure_take_value (s, "streams", &va);
466 gst_structure_set (s, "recv-count", G_TYPE_UINT, filter->recv_count, NULL);
467 gst_structure_set (s, "recv-drop-count", G_TYPE_UINT,
468 filter->recv_drop_count, NULL);
469 GST_LOG_OBJECT (filter, "stats: recv-count %u recv-drop-count %u",
470 filter->recv_count, filter->recv_drop_count);
477 gst_srtp_dec_set_property (GObject * object, guint prop_id,
478 const GValue * value, GParamSpec * pspec)
480 GstSrtpDec *filter = GST_SRTP_DEC (object);
482 GST_OBJECT_LOCK (filter);
485 case PROP_REPLAY_WINDOW_SIZE:
486 filter->replay_window_size = g_value_get_uint (value);
489 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
493 GST_OBJECT_UNLOCK (filter);
497 gst_srtp_dec_get_property (GObject * object, guint prop_id,
498 GValue * value, GParamSpec * pspec)
500 GstSrtpDec *filter = GST_SRTP_DEC (object);
502 GST_OBJECT_LOCK (filter);
505 case PROP_REPLAY_WINDOW_SIZE:
506 g_value_set_uint (value, filter->replay_window_size);
509 g_value_take_boxed (value, gst_srtp_dec_create_stats (filter));
512 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
516 GST_OBJECT_UNLOCK (filter);
520 gst_srtp_dec_remove_stream (GstSrtpDec * filter, guint ssrc)
522 GstSrtpDecSsrcStream *stream = NULL;
524 if (filter->streams == NULL)
527 stream = g_hash_table_lookup (filter->streams, GUINT_TO_POINTER (ssrc));
530 srtp_remove_stream (filter->session, ssrc);
531 g_hash_table_remove (filter->streams, GUINT_TO_POINTER (ssrc));
535 static GstSrtpDecSsrcStream *
536 find_stream_by_ssrc (GstSrtpDec * filter, guint32 ssrc)
538 return g_hash_table_lookup (filter->streams, GUINT_TO_POINTER (ssrc));
543 clear_key (gpointer data)
545 struct GstSrtpDecKey *key = data;
547 gst_clear_buffer (&key->mki);
548 gst_clear_buffer (&key->key);
553 /* get info from buffer caps
555 static GstSrtpDecSsrcStream *
556 get_stream_from_caps (GstSrtpDec * filter, GstCaps * caps, guint32 ssrc)
558 GstSrtpDecSsrcStream *stream;
561 const gchar *rtp_cipher, *rtp_auth, *rtcp_cipher, *rtcp_auth;
563 /* Create new stream structure and set default values */
564 stream = g_slice_new0 (GstSrtpDecSsrcStream);
568 /* Get info from caps */
569 s = gst_caps_get_structure (caps, 0);
573 rtp_cipher = gst_structure_get_string (s, "srtp-cipher");
574 rtp_auth = gst_structure_get_string (s, "srtp-auth");
575 rtcp_cipher = gst_structure_get_string (s, "srtcp-cipher");
576 rtcp_auth = gst_structure_get_string (s, "srtcp-auth");
577 if (!rtp_cipher || !rtp_auth || !rtcp_cipher || !rtcp_auth)
580 gst_structure_get_uint (s, "roc", &stream->roc);
582 stream->rtp_cipher = enum_value_from_nick (GST_TYPE_SRTP_CIPHER_TYPE,
584 stream->rtp_auth = enum_value_from_nick (GST_TYPE_SRTP_AUTH_TYPE, rtp_auth);
585 stream->rtcp_cipher = enum_value_from_nick (GST_TYPE_SRTP_CIPHER_TYPE,
587 stream->rtcp_auth = enum_value_from_nick (GST_TYPE_SRTP_AUTH_TYPE, rtcp_auth);
589 if ((gint) stream->rtp_cipher == -1 || (gint) stream->rtp_auth == -1 ||
590 (gint) stream->rtcp_cipher == -1 || (gint) stream->rtcp_auth == -1) {
591 GST_WARNING_OBJECT (filter, "Invalid caps for stream,"
592 " unknown cipher or auth type");
596 /* RFC 3711 says in "3. SRTP Framework" that SRTCP message authentication
597 * is MANDATORY. In case of GCM let the pipeline handle any errors.
599 if (stream->rtcp_cipher != GST_SRTP_CIPHER_AES_128_GCM
600 && stream->rtcp_cipher != GST_SRTP_CIPHER_AES_256_GCM
601 && stream->rtcp_cipher != GST_SRTP_CIPHER_NULL
602 && stream->rtcp_auth == GST_SRTP_AUTH_NULL) {
603 GST_WARNING_OBJECT (filter,
604 "Cannot have SRTP NULL authentication with a not-NULL encryption"
609 if (gst_structure_get (s, "srtp-key", GST_TYPE_BUFFER, &buf, NULL) && buf) {
611 GstBuffer *mki = NULL;
616 GST_DEBUG_OBJECT (filter, "Got key [%p] for SSRC %u", buf, ssrc);
619 if (gst_structure_get (s, "mki", GST_TYPE_BUFFER, &mki, NULL) && mki) {
620 struct GstSrtpDecKey key = {.mki = mki,.key = buf };
622 mki_size = gst_buffer_get_size (mki);
623 if (mki_size > SRTP_MAX_MKI_LEN) {
624 GST_WARNING_OBJECT (filter, "MKI is longer than allowed (%"
625 G_GSIZE_FORMAT " > %d).", mki_size, SRTP_MAX_MKI_LEN);
626 gst_buffer_unref (mki);
627 gst_buffer_unref (buf);
632 g_array_sized_new (FALSE, TRUE, sizeof (struct GstSrtpDecKey), 2);
633 g_array_set_clear_func (stream->keys, clear_key);
635 g_array_append_val (stream->keys, key);
637 /* Append more MKIs */
638 for (i = 1; i < SRTP_MAX_NUM_MASTER_KEYS; i++) {
641 g_snprintf (mki_id, 16, "mki%d", i + 1);
642 g_snprintf (key_id, 16, "srtp-key%d", i + 1);
644 if (gst_structure_get (s, mki_id, GST_TYPE_BUFFER, &mki,
645 key_id, GST_TYPE_BUFFER, &buf, NULL)) {
646 if (gst_buffer_get_size (mki) != mki_size) {
647 GST_WARNING_OBJECT (filter,
648 "MKIs need to all have the same size (first was %"
649 G_GSIZE_FORMAT ", current is %" G_GSIZE_FORMAT ").",
650 mki_size, gst_buffer_get_size (mki));
651 gst_buffer_unref (mki);
652 gst_buffer_unref (buf);
657 g_array_append_val (stream->keys, key);
667 } else if (STREAM_HAS_CRYPTO (stream)) {
674 g_slice_free (GstSrtpDecSsrcStream, stream);
678 /* Get SRTP params by signal
681 signal_get_srtp_params (GstSrtpDec * filter, guint32 ssrc, gint signal)
683 GstCaps *caps = NULL;
685 g_signal_emit (filter, gst_srtp_dec_signals[signal], 0, ssrc, &caps);
688 GST_DEBUG_OBJECT (filter, "Caps received");
693 /* Create a stream in the session
695 static srtp_err_status_t
696 init_session_stream (GstSrtpDec * filter, guint32 ssrc,
697 GstSrtpDecSsrcStream * stream)
699 srtp_err_status_t ret;
700 srtp_policy_t policy;
704 GstMapInfo *key_maps = NULL;
705 GstMapInfo *mki_maps = NULL;
708 memset (&policy, 0, sizeof (srtp_policy_t));
711 return srtp_err_status_bad_param;
713 GST_INFO_OBJECT (filter, "Setting RTP policy...");
714 set_crypto_policy_cipher_auth (stream->rtp_cipher, stream->rtp_auth,
716 GST_INFO_OBJECT (filter, "Setting RTCP policy...");
717 set_crypto_policy_cipher_auth (stream->rtcp_cipher, stream->rtcp_auth,
723 srtp_master_key_t *keys;
725 keys = g_alloca (sizeof (srtp_master_key_t) * stream->keys->len);
726 policy.keys = g_alloca (sizeof (gpointer) * stream->keys->len);
727 key_maps = g_alloca (sizeof (GstMapInfo) * stream->keys->len);
728 mki_maps = g_alloca (sizeof (GstMapInfo) * stream->keys->len);
730 for (i = 0; i < stream->keys->len; i++) {
731 struct GstSrtpDecKey *key =
732 &g_array_index (stream->keys, struct GstSrtpDecKey, i);
733 policy.keys[i] = &keys[i];
735 gst_buffer_map (key->mki, &mki_maps[i], GST_MAP_READ);
736 gst_buffer_map (key->key, &key_maps[i], GST_MAP_READ);
738 policy.keys[i]->key = (guchar *) key_maps[i].data;
739 policy.keys[i]->mki_id = (guchar *) mki_maps[i].data;
740 policy.keys[i]->mki_size = mki_maps[i].size;
742 policy.num_master_keys = stream->keys->len;
746 gst_buffer_map (stream->key, &map, GST_MAP_READ);
747 policy.key = (guchar *) map.data;
752 policy.ssrc.value = ssrc;
753 policy.ssrc.type = ssrc_specific;
754 policy.window_size = filter->replay_window_size;
757 /* If it is the first stream, create the session
758 * If not, add the stream policy to the session
760 if (filter->first_session)
761 ret = srtp_create (&filter->session, &policy);
763 ret = srtp_add_stream (filter->session, &policy);
766 gst_buffer_unmap (stream->key, &map);
772 for (i = 0; i < stream->keys->len; i++) {
773 struct GstSrtpDecKey *key = &g_array_index (stream->keys,
774 struct GstSrtpDecKey, i);
775 gst_buffer_unmap (key->mki, &mki_maps[i]);
776 gst_buffer_unmap (key->key, &key_maps[i]);
782 if (ret == srtp_err_status_ok) {
783 srtp_err_status_t status;
785 status = srtp_set_stream_roc (filter->session, ssrc, stream->roc);
787 (void) status; /* Ignore unused variable */
789 if (status == srtp_err_status_ok) {
790 /* Here, we just set the ROC, but we also need to set the initial
791 * RTP sequence number later, otherwise libsrtp will not be able
792 * to get the right packet index. */
793 g_hash_table_add (filter->streams_roc_changed, GUINT_TO_POINTER (ssrc));
797 filter->first_session = FALSE;
798 g_hash_table_insert (filter->streams, GUINT_TO_POINTER (stream->ssrc),
805 /* Return a stream structure for a given buffer
807 static GstSrtpDecSsrcStream *
808 validate_buffer (GstSrtpDec * filter, GstBuffer * buf, guint32 * ssrc,
811 GstSrtpDecSsrcStream *stream = NULL;
812 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
814 if (gst_rtp_buffer_map (buf,
815 GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf)) {
816 if (gst_rtp_buffer_get_payload_type (&rtpbuf) < 64
817 || gst_rtp_buffer_get_payload_type (&rtpbuf) > 80) {
818 *ssrc = gst_rtp_buffer_get_ssrc (&rtpbuf);
820 gst_rtp_buffer_unmap (&rtpbuf);
824 gst_rtp_buffer_unmap (&rtpbuf);
827 if (rtcp_buffer_get_ssrc (buf, ssrc)) {
830 GST_WARNING_OBJECT (filter, "No SSRC found in buffer");
836 stream = find_stream_by_ssrc (filter, *ssrc);
841 return request_key_with_signal (filter, *ssrc, SIGNAL_REQUEST_KEY);
845 free_stream (GstSrtpDecSsrcStream * stream)
848 gst_buffer_unref (stream->key);
850 g_array_free (stream->keys, TRUE);
851 g_slice_free (GstSrtpDecSsrcStream, stream);
855 buffers_are_equal (GstBuffer * a, GstBuffer * b)
862 if (a == NULL || b == NULL)
865 if (gst_buffer_get_size (a) != gst_buffer_get_size (b))
868 if (gst_buffer_map (a, &info, GST_MAP_READ)) {
871 equal = (gst_buffer_memcmp (b, 0, info.data, info.size) == 0);
872 gst_buffer_unmap (a, &info);
881 keys_are_equal (GArray * a, GArray * b)
889 if (a == NULL || b == NULL)
892 if (a->len != b->len)
895 for (i = 0; i < a->len; i++) {
896 struct GstSrtpDecKey *key_a = &g_array_index (a,
897 struct GstSrtpDecKey, i);
898 struct GstSrtpDecKey *key_b = &g_array_index (b,
899 struct GstSrtpDecKey, i);
901 if (!buffers_are_equal (key_a->mki, key_b->mki))
904 if (!buffers_are_equal (key_a->key, key_b->key))
914 /* Create new stream from params in caps
916 static GstSrtpDecSsrcStream *
917 update_session_stream_from_caps (GstSrtpDec * filter, guint32 ssrc,
920 GstSrtpDecSsrcStream *stream = NULL;
921 GstSrtpDecSsrcStream *old_stream = NULL;
922 srtp_err_status_t err;
924 g_return_val_if_fail (GST_IS_SRTP_DEC (filter), NULL);
925 g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
927 stream = get_stream_from_caps (filter, caps, ssrc);
929 old_stream = find_stream_by_ssrc (filter, ssrc);
930 if (stream && old_stream &&
931 stream->rtp_cipher == old_stream->rtp_cipher &&
932 stream->rtcp_cipher == old_stream->rtcp_cipher &&
933 stream->rtp_auth == old_stream->rtp_auth &&
934 stream->rtcp_auth == old_stream->rtcp_auth &&
935 ((stream->keys && keys_are_equal (stream->keys, old_stream->keys)) ||
936 buffers_are_equal (stream->key, old_stream->key))) {
937 free_stream (stream);
941 /* Remove existing stream, if any */
942 gst_srtp_dec_remove_stream (filter, ssrc);
945 /* Create new session stream */
946 err = init_session_stream (filter, ssrc, stream);
948 if (err != srtp_err_status_ok) {
949 GST_WARNING_OBJECT (filter, "Failed to create the stream (err: %d)", err);
951 gst_buffer_unref (stream->key);
952 g_slice_free (GstSrtpDecSsrcStream, stream);
961 remove_yes (gpointer key, gpointer value, gpointer user_data)
966 /* Clear the policy list
969 gst_srtp_dec_clear_streams (GstSrtpDec * filter)
973 GST_OBJECT_LOCK (filter);
975 if (!filter->first_session) {
976 srtp_dealloc (filter->session);
977 filter->session = NULL;
981 nb = g_hash_table_foreach_remove (filter->streams, remove_yes, NULL);
983 filter->first_session = TRUE;
985 GST_OBJECT_UNLOCK (filter);
987 GST_DEBUG_OBJECT (filter, "Cleared %d streams", nb);
992 static GstSrtpDecSsrcStream *
993 request_key_with_signal (GstSrtpDec * filter, guint32 ssrc, gint signal)
996 GstSrtpDecSsrcStream *stream = NULL;
998 caps = signal_get_srtp_params (filter, ssrc, signal);
1001 stream = update_session_stream_from_caps (filter, ssrc, caps);
1003 GST_DEBUG_OBJECT (filter, "New stream set with SSRC %u", ssrc);
1005 GST_WARNING_OBJECT (filter, "Could not set stream with SSRC %u", ssrc);
1006 gst_caps_unref (caps);
1008 GST_WARNING_OBJECT (filter, "Could not get caps for stream with SSRC %u",
1016 gst_srtp_dec_sink_setcaps (GstPad * pad, GstObject * parent,
1017 GstCaps * caps, gboolean is_rtcp)
1019 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1022 gboolean ret = FALSE;
1024 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
1026 ps = gst_caps_get_structure (caps, 0);
1028 if (gst_structure_has_field_typed (ps, "ssrc", G_TYPE_UINT) &&
1029 gst_structure_has_field_typed (ps, "srtp-cipher", G_TYPE_STRING) &&
1030 gst_structure_has_field_typed (ps, "srtp-auth", G_TYPE_STRING) &&
1031 gst_structure_has_field_typed (ps, "srtcp-cipher", G_TYPE_STRING) &&
1032 gst_structure_has_field_typed (ps, "srtcp-auth", G_TYPE_STRING)) {
1035 gst_structure_get_uint (ps, "ssrc", &ssrc);
1037 if (!update_session_stream_from_caps (filter, ssrc, caps)) {
1038 GST_WARNING_OBJECT (pad, "Could not create session from pad caps: %"
1039 GST_PTR_FORMAT, caps);
1044 caps = gst_caps_copy (caps);
1045 ps = gst_caps_get_structure (caps, 0);
1046 gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher", "srtp-auth",
1047 "srtcp-cipher", "srtcp-auth", "mki", NULL);
1050 gst_structure_set_name (ps, "application/x-rtcp");
1052 gst_structure_set_name (ps, "application/x-rtp");
1054 otherpad = gst_pad_get_element_private (pad);
1056 ret = gst_pad_set_caps (otherpad, caps);
1058 gst_caps_unref (caps);
1064 gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent, GstEvent * event)
1068 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1070 switch (GST_EVENT_TYPE (event)) {
1071 case GST_EVENT_CAPS:
1072 gst_event_parse_caps (event, &caps);
1073 ret = gst_srtp_dec_sink_setcaps (pad, parent, caps, FALSE);
1074 gst_event_unref (event);
1076 case GST_EVENT_SEGMENT:
1077 /* Make sure to send a caps event downstream before the segment event,
1078 * even if upstream didn't */
1079 if (!gst_pad_has_current_caps (filter->rtp_srcpad)) {
1080 GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtp");
1082 gst_pad_set_caps (filter->rtp_srcpad, caps);
1083 gst_caps_unref (caps);
1085 filter->rtp_has_segment = TRUE;
1087 case GST_EVENT_FLUSH_STOP:
1088 filter->rtp_has_segment = FALSE;
1094 return gst_pad_event_default (pad, parent, event);
1098 gst_srtp_dec_sink_event_rtcp (GstPad * pad, GstObject * parent,
1103 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1105 switch (GST_EVENT_TYPE (event)) {
1106 case GST_EVENT_CAPS:
1107 gst_event_parse_caps (event, &caps);
1108 ret = gst_srtp_dec_sink_setcaps (pad, parent, caps, TRUE);
1109 gst_event_unref (event);
1111 case GST_EVENT_SEGMENT:
1112 /* Make sure to send a caps event downstream before the segment event,
1113 * even if upstream didn't */
1114 if (!gst_pad_has_current_caps (filter->rtcp_srcpad)) {
1115 GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtcp");
1117 gst_pad_set_caps (filter->rtcp_srcpad, caps);
1118 gst_caps_unref (caps);
1120 filter->rtcp_has_segment = TRUE;
1122 case GST_EVENT_FLUSH_STOP:
1123 filter->rtcp_has_segment = FALSE;
1129 return gst_pad_event_default (pad, parent, event);
1133 gst_srtp_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query,
1136 switch (GST_QUERY_TYPE (query)) {
1137 case GST_QUERY_CAPS:
1139 GstCaps *filter = NULL;
1140 GstCaps *other_filter = NULL;
1141 GstCaps *template_caps;
1143 GstCaps *other_caps;
1147 gst_query_parse_caps (query, &filter);
1149 otherpad = (GstPad *) gst_pad_get_element_private (pad);
1152 other_filter = gst_caps_copy (filter);
1154 for (i = 0; i < gst_caps_get_size (other_filter); i++) {
1155 GstStructure *ps = gst_caps_get_structure (other_filter, i);
1157 gst_structure_set_name (ps, "application/x-rtcp");
1159 gst_structure_set_name (ps, "application/x-rtp");
1160 gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher",
1161 "srtp-auth", "srtcp-cipher", "srtcp-auth", "mki", NULL);
1166 other_caps = gst_pad_peer_query_caps (otherpad, other_filter);
1168 gst_caps_unref (other_filter);
1170 goto return_template;
1173 template_caps = gst_pad_get_pad_template_caps (otherpad);
1174 ret = gst_caps_intersect_full (other_caps, template_caps,
1175 GST_CAPS_INTERSECT_FIRST);
1176 gst_caps_unref (other_caps);
1177 gst_caps_unref (template_caps);
1179 ret = gst_caps_make_writable (ret);
1181 for (i = 0; i < gst_caps_get_size (ret); i++) {
1182 GstStructure *ps = gst_caps_get_structure (ret, i);
1184 gst_structure_set_name (ps, "application/x-srtcp");
1186 gst_structure_set_name (ps, "application/x-srtp");
1192 tmp = gst_caps_intersect (ret, filter);
1193 gst_caps_unref (ret);
1197 gst_query_set_caps_result (query, ret);
1198 gst_caps_unref (ret);
1203 ret = gst_pad_get_pad_template_caps (pad);
1204 gst_query_set_caps_result (query, ret);
1205 gst_caps_unref (ret);
1209 return gst_pad_query_default (pad, parent, query);
1214 gst_srtp_dec_sink_query_rtp (GstPad * pad, GstObject * parent, GstQuery * query)
1216 return gst_srtp_dec_sink_query (pad, parent, query, FALSE);
1220 gst_srtp_dec_sink_query_rtcp (GstPad * pad, GstObject * parent,
1223 return gst_srtp_dec_sink_query (pad, parent, query, TRUE);
1226 static GstIterator *
1227 gst_srtp_dec_iterate_internal_links (GstPad * pad, GstObject * parent,
1230 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1231 GstPad *otherpad = NULL;
1232 GstIterator *it = NULL;
1234 otherpad = (GstPad *) gst_pad_get_element_private (pad);
1239 g_value_init (&val, GST_TYPE_PAD);
1240 g_value_set_object (&val, otherpad);
1241 it = gst_iterator_new_single (GST_TYPE_PAD, &val);
1242 g_value_unset (&val);
1244 GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), CORE, PAD, (NULL),
1245 ("Unable to get linked pad"));
1251 static GstIterator *
1252 gst_srtp_dec_iterate_internal_links_rtp (GstPad * pad, GstObject * parent)
1254 return gst_srtp_dec_iterate_internal_links (pad, parent, FALSE);
1257 static GstIterator *
1258 gst_srtp_dec_iterate_internal_links_rtcp (GstPad * pad, GstObject * parent)
1260 return gst_srtp_dec_iterate_internal_links (pad, parent, TRUE);
1263 /* Partial backport to 1.22 of `gst_element_decorate_stream_id_internal`,
1264 * which was introduced in 1.23 */
1266 decorate_stream_id_private (GstElement * element, const gchar * stream_id)
1268 gchar *upstream_stream_id = NULL, *new_stream_id;
1272 /* Try to generate a stream-id from the URI query and
1273 * if it fails take a random number instead */
1274 query = gst_query_new_uri ();
1275 if (gst_element_query (element, query)) {
1276 gst_query_parse_uri (query, &uri);
1282 /* And then generate an SHA256 sum of the URI */
1283 cs = g_checksum_new (G_CHECKSUM_SHA256);
1284 g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1286 upstream_stream_id = g_strdup (g_checksum_get_string (cs));
1287 g_checksum_free (cs);
1289 /* Just get some random number if the URI query fails */
1290 GST_FIXME_OBJECT (element, "Creating random stream-id, consider "
1291 "implementing a deterministic way of creating a stream-id");
1292 upstream_stream_id =
1293 g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1294 g_random_int (), g_random_int ());
1297 gst_query_unref (query);
1300 new_stream_id = g_strconcat (upstream_stream_id, "/", stream_id, NULL);
1302 new_stream_id = g_strdup (upstream_stream_id);
1305 g_free (upstream_stream_id);
1307 return new_stream_id;
1311 gst_srtp_dec_push_early_events (GstSrtpDec * filter, GstPad * pad,
1312 GstPad * otherpad, gboolean is_rtcp)
1314 GstEvent *otherev, *ev;
1316 ev = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0);
1318 gst_event_unref (ev);
1320 gchar *new_stream_id;
1322 otherev = gst_pad_get_sticky_event (otherpad, GST_EVENT_STREAM_START, 0);
1325 const gchar *other_stream_id;
1327 gst_event_parse_stream_start (otherev, &other_stream_id);
1329 new_stream_id = g_strdup_printf ("%s/%s", other_stream_id,
1330 is_rtcp ? "rtcp" : "rtp");
1331 gst_event_unref (otherev);
1333 new_stream_id = decorate_stream_id_private (GST_ELEMENT (filter),
1334 is_rtcp ? "rtcp" : "rtp");
1337 ev = gst_event_new_stream_start (new_stream_id);
1338 g_free (new_stream_id);
1340 gst_pad_push_event (pad, ev);
1343 ev = gst_pad_get_sticky_event (pad, GST_EVENT_CAPS, 0);
1345 gst_event_unref (ev);
1350 caps = gst_caps_new_empty_simple ("application/x-rtcp");
1352 caps = gst_caps_new_empty_simple ("application/x-rtp");
1354 ev = gst_event_new_caps (caps);
1355 gst_pad_push_event (pad, ev);
1356 gst_caps_unref (caps);
1359 ev = gst_pad_get_sticky_event (pad, GST_EVENT_SEGMENT, 0);
1361 gst_event_unref (ev);
1363 ev = gst_pad_get_sticky_event (otherpad, GST_EVENT_SEGMENT, 0);
1366 gst_pad_push_event (pad, ev);
1367 } else if (GST_PAD_IS_FLUSHING (otherpad)) {
1368 /* We didn't get a Segment event from otherpad
1369 * and otherpad is flushing => we are most likely shutting down */
1372 GST_WARNING_OBJECT (filter, "No Segment event to push");
1378 filter->rtcp_has_segment = TRUE;
1380 filter->rtp_has_segment = TRUE;
1389 * This function should be called while holding the filter lock
1392 gst_srtp_dec_decode_buffer (GstSrtpDec * filter, GstPad * pad, GstBuffer * buf,
1393 gboolean is_rtcp, guint32 ssrc)
1396 srtp_err_status_t err;
1398 GstSrtpDecSsrcStream *stream;
1400 GST_LOG_OBJECT (pad, "Received %s buffer of size %" G_GSIZE_FORMAT
1401 " with SSRC = %u", is_rtcp ? "RTCP" : "RTP", gst_buffer_get_size (buf),
1403 filter->recv_count++;
1404 /* Change buffer to remove protection */
1405 buf = gst_buffer_make_writable (buf);
1407 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
1412 gst_srtp_init_event_reporter ();
1416 stream = find_stream_by_ssrc (filter, ssrc);
1418 err = srtp_unprotect_rtcp_mki (filter->session, map.data, &size,
1419 stream && stream->keys);
1421 err = srtp_unprotect_rtcp (filter->session, map.data, &size);
1425 /* If ROC has changed, we know we need to set the initial RTP
1426 * sequence number too. */
1427 if (g_hash_table_contains (filter->streams_roc_changed,
1428 GUINT_TO_POINTER (ssrc))) {
1429 srtp_stream_t stream;
1431 stream = srtp_get_stream (filter->session, htonl (ssrc));
1435 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
1437 gst_rtp_buffer_map (buf,
1438 GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf);
1439 seqnum = gst_rtp_buffer_get_seq (&rtpbuf);
1440 gst_rtp_buffer_unmap (&rtpbuf);
1442 /* We finally add the RTP sequence number to the current
1443 * rollover counter. */
1444 stream->rtp_rdbx.index &= ~0xFFFF;
1445 stream->rtp_rdbx.index |= seqnum;
1448 g_hash_table_remove (filter->streams_roc_changed,
1449 GUINT_TO_POINTER (ssrc));
1455 stream = find_stream_by_ssrc (filter, ssrc);
1457 err = srtp_unprotect_mki (filter->session, map.data, &size,
1458 stream && stream->keys);
1461 err = srtp_unprotect (filter->session, map.data, &size);
1464 stream = find_stream_by_ssrc (filter, ssrc);
1465 if (stream == NULL) {
1466 GST_WARNING_OBJECT (filter, "Could not find matching stream, dropping");
1469 stream->recv_count++;
1470 /* Signal user depending on type of error */
1472 case srtp_err_status_ok:
1475 case srtp_err_status_replay_fail:
1476 GST_DEBUG_OBJECT (filter,
1477 "Dropping replayed packet, probably retransmission");
1478 stream->recv_drop_count++;
1480 case srtp_err_status_replay_old:
1481 GST_DEBUG_OBJECT (filter,
1482 "Dropping replayed old packet, probably retransmission");
1483 stream->recv_drop_count++;
1485 case srtp_err_status_key_expired:{
1487 GST_OBJECT_UNLOCK (filter);
1488 stream = request_key_with_signal (filter, ssrc, SIGNAL_HARD_LIMIT);
1489 GST_OBJECT_LOCK (filter);
1491 /* Check the key request created a new stream */
1492 if (stream == NULL) {
1493 GST_WARNING_OBJECT (filter, "Hard limit reached, no new key, dropping");
1499 case srtp_err_status_auth_fail:
1500 GST_WARNING_OBJECT (filter, "Error authentication packet, dropping");
1501 stream->recv_drop_count++;
1503 case srtp_err_status_cipher_fail:
1504 GST_WARNING_OBJECT (filter, "Error while decrypting packet, dropping");
1505 stream->recv_drop_count++;
1508 GST_WARNING_OBJECT (pad,
1509 "Unable to unprotect buffer (unprotect failed code %d)", err);
1510 stream->recv_drop_count++;
1513 gst_buffer_unmap (buf, &map);
1514 gst_buffer_set_size (buf, size);
1518 filter->recv_drop_count++;
1519 gst_buffer_unmap (buf, &map);
1523 static GstFlowReturn
1524 gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
1527 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1529 GstSrtpDecSsrcStream *stream = NULL;
1530 GstFlowReturn ret = GST_FLOW_OK;
1533 GST_OBJECT_LOCK (filter);
1535 /* Check if this stream exists, if not create a new stream */
1537 if (!(stream = validate_buffer (filter, buf, &ssrc, &is_rtcp))) {
1538 GST_OBJECT_UNLOCK (filter);
1539 GST_WARNING_OBJECT (filter, "Invalid buffer, dropping");
1543 if (!STREAM_HAS_CRYPTO (stream)) {
1544 GST_OBJECT_UNLOCK (filter);
1548 if (!gst_srtp_dec_decode_buffer (filter, pad, buf, is_rtcp, ssrc)) {
1549 GST_OBJECT_UNLOCK (filter);
1553 GST_OBJECT_UNLOCK (filter);
1555 /* If all is well, we may have reached soft limit */
1556 if (gst_srtp_get_soft_limit_reached ())
1557 request_key_with_signal (filter, ssrc, SIGNAL_SOFT_LIMIT);
1560 /* Push buffer to source pad */
1562 otherpad = filter->rtcp_srcpad;
1563 if (!filter->rtcp_has_segment) {
1564 if (!gst_srtp_dec_push_early_events (filter, filter->rtcp_srcpad,
1565 filter->rtp_srcpad, TRUE)) {
1566 ret = GST_FLOW_FLUSHING;
1571 otherpad = filter->rtp_srcpad;
1572 if (!filter->rtp_has_segment) {
1573 if (!gst_srtp_dec_push_early_events (filter, filter->rtp_srcpad,
1574 filter->rtcp_srcpad, FALSE)) {
1575 ret = GST_FLOW_FLUSHING;
1581 ret = gst_pad_push (otherpad, buf);
1586 /* Drop buffer, except if gst_pad_push returned OK or an error */
1588 gst_buffer_unref (buf);
1593 static GstFlowReturn
1594 gst_srtp_dec_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1596 return gst_srtp_dec_chain (pad, parent, buf, FALSE);
1599 static GstFlowReturn
1600 gst_srtp_dec_chain_rtcp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1602 return gst_srtp_dec_chain (pad, parent, buf, TRUE);
1605 static GstStateChangeReturn
1606 gst_srtp_dec_change_state (GstElement * element, GstStateChange transition)
1608 GstStateChangeReturn res;
1611 filter = GST_SRTP_DEC (element);
1612 GST_OBJECT_LOCK (filter);
1614 switch (transition) {
1615 case GST_STATE_CHANGE_READY_TO_PAUSED:
1616 filter->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1617 NULL, (GDestroyNotify) free_stream);
1620 filter->streams_roc_changed =
1621 g_hash_table_new (g_direct_hash, g_direct_equal);
1624 filter->rtp_has_segment = FALSE;
1625 filter->rtcp_has_segment = FALSE;
1626 filter->recv_count = 0;
1627 filter->recv_drop_count = 0;
1629 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1635 GST_OBJECT_UNLOCK (filter);
1637 res = GST_ELEMENT_CLASS (gst_srtp_dec_parent_class)->change_state (element,
1640 switch (transition) {
1641 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1643 case GST_STATE_CHANGE_PAUSED_TO_READY:
1644 gst_srtp_dec_clear_streams (filter);
1645 g_hash_table_unref (filter->streams);
1646 filter->streams = NULL;
1648 g_hash_table_unref (filter->streams_roc_changed);
1649 filter->streams_roc_changed = NULL;
1653 case GST_STATE_CHANGE_READY_TO_NULL: