mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-03 17:22:29 +00:00
dtls: Fix indention
This commit is contained in:
parent
1e0ed9af11
commit
6183e99eec
10 changed files with 2725 additions and 2488 deletions
|
@ -40,215 +40,235 @@
|
|||
#include <openssl/ssl.h>
|
||||
|
||||
#if ER_DTLS_USE_GST_LOG
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_agent_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_agent_debug);
|
||||
# define GST_CAT_DEFAULT er_dtls_agent_debug
|
||||
G_DEFINE_TYPE_WITH_CODE(ErDtlsAgent, er_dtls_agent, G_TYPE_OBJECT,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_agent_debug, "gstdtlsagent", 0, "Ericsson DTLS Agent"));
|
||||
G_DEFINE_TYPE_WITH_CODE (ErDtlsAgent, er_dtls_agent, G_TYPE_OBJECT,
|
||||
GST_DEBUG_CATEGORY_INIT (er_dtls_agent_debug, "gstdtlsagent", 0,
|
||||
"Ericsson DTLS Agent"));
|
||||
#else
|
||||
G_DEFINE_TYPE(ErDtlsAgent, er_dtls_agent, G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (ErDtlsAgent, er_dtls_agent, G_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
#define ER_DTLS_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ER_TYPE_DTLS_AGENT, ErDtlsAgentPrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CERTIFICATE,
|
||||
NUM_PROPERTIES
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CERTIFICATE,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
struct _ErDtlsAgentPrivate {
|
||||
SSL_CTX *ssl_context;
|
||||
struct _ErDtlsAgentPrivate
|
||||
{
|
||||
SSL_CTX *ssl_context;
|
||||
|
||||
ErDtlsCertificate *certificate;
|
||||
ErDtlsCertificate *certificate;
|
||||
};
|
||||
|
||||
static void er_dtls_agent_finalize(GObject *gobject);
|
||||
static void er_dtls_agent_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
const gchar *er_dtls_agent_peek_id(ErDtlsAgent *);
|
||||
static void er_dtls_agent_finalize (GObject * gobject);
|
||||
static void er_dtls_agent_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
const gchar *er_dtls_agent_peek_id (ErDtlsAgent *);
|
||||
|
||||
static GRWLock *ssl_locks;
|
||||
|
||||
static void ssl_locking_function(gint mode, gint lock_num, const gchar *file, gint line)
|
||||
static void
|
||||
ssl_locking_function (gint mode, gint lock_num, const gchar * file, gint line)
|
||||
{
|
||||
gboolean locking;
|
||||
gboolean reading;
|
||||
GRWLock *lock;
|
||||
gboolean locking;
|
||||
gboolean reading;
|
||||
GRWLock *lock;
|
||||
|
||||
locking = mode & CRYPTO_LOCK;
|
||||
reading = mode & CRYPTO_READ;
|
||||
lock = &ssl_locks[lock_num];
|
||||
locking = mode & CRYPTO_LOCK;
|
||||
reading = mode & CRYPTO_READ;
|
||||
lock = &ssl_locks[lock_num];
|
||||
|
||||
LOG_LOG(NULL, "%s SSL lock for %s, thread=%p location=%s:%d",
|
||||
locking ? "locking" : "unlocking", reading ? "reading" : "writing",
|
||||
g_thread_self(), file, line);
|
||||
LOG_LOG (NULL, "%s SSL lock for %s, thread=%p location=%s:%d",
|
||||
locking ? "locking" : "unlocking", reading ? "reading" : "writing",
|
||||
g_thread_self (), file, line);
|
||||
|
||||
if (locking) {
|
||||
if (reading) {
|
||||
g_rw_lock_reader_lock(lock);
|
||||
} else {
|
||||
g_rw_lock_writer_lock(lock);
|
||||
}
|
||||
if (locking) {
|
||||
if (reading) {
|
||||
g_rw_lock_reader_lock (lock);
|
||||
} else {
|
||||
if (reading) {
|
||||
g_rw_lock_reader_unlock(lock);
|
||||
} else {
|
||||
g_rw_lock_writer_unlock(lock);
|
||||
}
|
||||
g_rw_lock_writer_lock (lock);
|
||||
}
|
||||
}
|
||||
|
||||
static gulong ssl_thread_id_function(void)
|
||||
{
|
||||
return (gulong) g_thread_self();
|
||||
}
|
||||
|
||||
void _er_dtls_init_openssl()
|
||||
{
|
||||
static gsize is_init = 0;
|
||||
gint i;
|
||||
gint num_locks;
|
||||
|
||||
if (g_once_init_enter(&is_init)) {
|
||||
if (OPENSSL_VERSION_NUMBER < 0x1000100fL) {
|
||||
LOG_WARNING(NULL, "Incorrect OpenSSL version, should be >= 1.0.1, is %s", OPENSSL_VERSION_TEXT);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
LOG_INFO(NULL, "initializing openssl %lx", OPENSSL_VERSION_NUMBER);
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
ERR_load_BIO_strings();
|
||||
|
||||
num_locks = CRYPTO_num_locks();
|
||||
ssl_locks = g_new(GRWLock, num_locks);
|
||||
for (i = 0; i < num_locks; ++i) {
|
||||
g_rw_lock_init(&ssl_locks[i]);
|
||||
}
|
||||
CRYPTO_set_locking_callback(ssl_locking_function);
|
||||
CRYPTO_set_id_callback(ssl_thread_id_function);
|
||||
|
||||
g_once_init_leave(&is_init, 1);
|
||||
} else {
|
||||
if (reading) {
|
||||
g_rw_lock_reader_unlock (lock);
|
||||
} else {
|
||||
g_rw_lock_writer_unlock (lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void er_dtls_agent_class_init(ErDtlsAgentClass *klass)
|
||||
static gulong
|
||||
ssl_thread_id_function (void)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(ErDtlsAgentPrivate));
|
||||
|
||||
gobject_class->set_property = er_dtls_agent_set_property;
|
||||
gobject_class->finalize = er_dtls_agent_finalize;
|
||||
|
||||
properties[PROP_CERTIFICATE] =
|
||||
g_param_spec_object("certificate",
|
||||
"ErDtlsCertificate",
|
||||
"Sets the certificate of the agent",
|
||||
ER_TYPE_DTLS_CERTIFICATE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
_er_dtls_init_openssl();
|
||||
return (gulong) g_thread_self ();
|
||||
}
|
||||
|
||||
static void er_dtls_agent_init(ErDtlsAgent *self)
|
||||
void
|
||||
_er_dtls_init_openssl ()
|
||||
{
|
||||
ErDtlsAgentPrivate *priv = ER_DTLS_AGENT_GET_PRIVATE(self);
|
||||
self->priv = priv;
|
||||
static gsize is_init = 0;
|
||||
gint i;
|
||||
gint num_locks;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
priv->ssl_context = SSL_CTX_new(DTLSv1_method());
|
||||
if (ERR_peek_error() || !priv->ssl_context) {
|
||||
char buf[512];
|
||||
|
||||
priv->ssl_context = NULL;
|
||||
|
||||
LOG_WARNING(self, "Error creating SSL Context: %s", ERR_error_string(ERR_get_error(), buf));
|
||||
|
||||
g_return_if_reached();
|
||||
if (g_once_init_enter (&is_init)) {
|
||||
if (OPENSSL_VERSION_NUMBER < 0x1000100fL) {
|
||||
LOG_WARNING (NULL, "Incorrect OpenSSL version, should be >= 1.0.1, is %s",
|
||||
OPENSSL_VERSION_TEXT);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
SSL_CTX_set_verify_depth(priv->ssl_context, 2);
|
||||
SSL_CTX_set_tlsext_use_srtp(priv->ssl_context, "SRTP_AES128_CM_SHA1_80");
|
||||
SSL_CTX_set_cipher_list(priv->ssl_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
SSL_CTX_set_read_ahead(priv->ssl_context, 1);
|
||||
LOG_INFO (NULL, "initializing openssl %lx", OPENSSL_VERSION_NUMBER);
|
||||
SSL_library_init ();
|
||||
SSL_load_error_strings ();
|
||||
ERR_load_BIO_strings ();
|
||||
|
||||
num_locks = CRYPTO_num_locks ();
|
||||
ssl_locks = g_new (GRWLock, num_locks);
|
||||
for (i = 0; i < num_locks; ++i) {
|
||||
g_rw_lock_init (&ssl_locks[i]);
|
||||
}
|
||||
CRYPTO_set_locking_callback (ssl_locking_function);
|
||||
CRYPTO_set_id_callback (ssl_thread_id_function);
|
||||
|
||||
g_once_init_leave (&is_init, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
er_dtls_agent_class_init (ErDtlsAgentClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ErDtlsAgentPrivate));
|
||||
|
||||
gobject_class->set_property = er_dtls_agent_set_property;
|
||||
gobject_class->finalize = er_dtls_agent_finalize;
|
||||
|
||||
properties[PROP_CERTIFICATE] =
|
||||
g_param_spec_object ("certificate",
|
||||
"ErDtlsCertificate",
|
||||
"Sets the certificate of the agent",
|
||||
ER_TYPE_DTLS_CERTIFICATE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
_er_dtls_init_openssl ();
|
||||
}
|
||||
|
||||
static void
|
||||
er_dtls_agent_init (ErDtlsAgent * self)
|
||||
{
|
||||
ErDtlsAgentPrivate *priv = ER_DTLS_AGENT_GET_PRIVATE (self);
|
||||
self->priv = priv;
|
||||
|
||||
ERR_clear_error ();
|
||||
|
||||
priv->ssl_context = SSL_CTX_new (DTLSv1_method ());
|
||||
if (ERR_peek_error () || !priv->ssl_context) {
|
||||
char buf[512];
|
||||
|
||||
priv->ssl_context = NULL;
|
||||
|
||||
LOG_WARNING (self, "Error creating SSL Context: %s",
|
||||
ERR_error_string (ERR_get_error (), buf));
|
||||
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
SSL_CTX_set_verify_depth (priv->ssl_context, 2);
|
||||
SSL_CTX_set_tlsext_use_srtp (priv->ssl_context, "SRTP_AES128_CM_SHA1_80");
|
||||
SSL_CTX_set_cipher_list (priv->ssl_context,
|
||||
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
SSL_CTX_set_read_ahead (priv->ssl_context, 1);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
|
||||
SSL_CTX_set_ecdh_auto(priv->ssl_context, 1);
|
||||
SSL_CTX_set_ecdh_auto (priv->ssl_context, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void er_dtls_agent_finalize(GObject *gobject)
|
||||
static void
|
||||
er_dtls_agent_finalize (GObject * gobject)
|
||||
{
|
||||
ErDtlsAgentPrivate *priv = ER_DTLS_AGENT(gobject)->priv;
|
||||
ErDtlsAgentPrivate *priv = ER_DTLS_AGENT (gobject)->priv;
|
||||
|
||||
SSL_CTX_free(priv->ssl_context);
|
||||
priv->ssl_context = NULL;
|
||||
SSL_CTX_free (priv->ssl_context);
|
||||
priv->ssl_context = NULL;
|
||||
|
||||
LOG_DEBUG(gobject, "finalized");
|
||||
LOG_DEBUG (gobject, "finalized");
|
||||
|
||||
G_OBJECT_CLASS(er_dtls_agent_parent_class)->finalize(gobject);
|
||||
G_OBJECT_CLASS (er_dtls_agent_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void er_dtls_agent_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
er_dtls_agent_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
ErDtlsAgent *self = ER_DTLS_AGENT(object);
|
||||
ErDtlsCertificate *certificate;
|
||||
ErDtlsAgent *self = ER_DTLS_AGENT (object);
|
||||
ErDtlsCertificate *certificate;
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CERTIFICATE:
|
||||
certificate = ER_DTLS_CERTIFICATE(g_value_get_object(value));
|
||||
g_return_if_fail(ER_IS_DTLS_CERTIFICATE(certificate));
|
||||
g_return_if_fail(self->priv->ssl_context);
|
||||
certificate = ER_DTLS_CERTIFICATE (g_value_get_object (value));
|
||||
g_return_if_fail (ER_IS_DTLS_CERTIFICATE (certificate));
|
||||
g_return_if_fail (self->priv->ssl_context);
|
||||
|
||||
self->priv->certificate = certificate;
|
||||
g_object_ref(certificate);
|
||||
self->priv->certificate = certificate;
|
||||
g_object_ref (certificate);
|
||||
|
||||
if (!SSL_CTX_use_certificate(self->priv->ssl_context, _er_dtls_certificate_get_internal_certificate(certificate))) {
|
||||
LOG_WARNING(self, "could not use certificate");
|
||||
g_return_if_reached();
|
||||
}
|
||||
if (!SSL_CTX_use_certificate (self->priv->ssl_context,
|
||||
_er_dtls_certificate_get_internal_certificate (certificate))) {
|
||||
LOG_WARNING (self, "could not use certificate");
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
if (!SSL_CTX_use_PrivateKey(self->priv->ssl_context, _er_dtls_certificate_get_internal_key(certificate))) {
|
||||
LOG_WARNING(self, "could not use private key");
|
||||
g_return_if_reached();
|
||||
}
|
||||
if (!SSL_CTX_use_PrivateKey (self->priv->ssl_context,
|
||||
_er_dtls_certificate_get_internal_key (certificate))) {
|
||||
LOG_WARNING (self, "could not use private key");
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
if (!SSL_CTX_check_private_key(self->priv->ssl_context)) {
|
||||
LOG_WARNING(self, "invalid private key");
|
||||
g_return_if_reached();
|
||||
}
|
||||
break;
|
||||
if (!SSL_CTX_check_private_key (self->priv->ssl_context)) {
|
||||
LOG_WARNING (self, "invalid private key");
|
||||
g_return_if_reached ();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
ErDtlsCertificate *er_dtls_agent_get_certificate(ErDtlsAgent *self)
|
||||
ErDtlsCertificate *
|
||||
er_dtls_agent_get_certificate (ErDtlsAgent * self)
|
||||
{
|
||||
g_return_val_if_fail(ER_IS_DTLS_AGENT(self), NULL);
|
||||
if (self->priv->certificate) {
|
||||
g_object_ref(self->priv->certificate);
|
||||
}
|
||||
return self->priv->certificate;
|
||||
g_return_val_if_fail (ER_IS_DTLS_AGENT (self), NULL);
|
||||
if (self->priv->certificate) {
|
||||
g_object_ref (self->priv->certificate);
|
||||
}
|
||||
return self->priv->certificate;
|
||||
}
|
||||
|
||||
gchar *er_dtls_agent_get_certificate_pem(ErDtlsAgent *self)
|
||||
gchar *
|
||||
er_dtls_agent_get_certificate_pem (ErDtlsAgent * self)
|
||||
{
|
||||
gchar *pem;
|
||||
g_return_val_if_fail(ER_IS_DTLS_AGENT(self), NULL);
|
||||
g_return_val_if_fail(ER_IS_DTLS_CERTIFICATE(self->priv->certificate), NULL);
|
||||
gchar *pem;
|
||||
g_return_val_if_fail (ER_IS_DTLS_AGENT (self), NULL);
|
||||
g_return_val_if_fail (ER_IS_DTLS_CERTIFICATE (self->priv->certificate), NULL);
|
||||
|
||||
g_object_get(self->priv->certificate, "pem", &pem, NULL);
|
||||
g_object_get (self->priv->certificate, "pem", &pem, NULL);
|
||||
|
||||
return pem;
|
||||
return pem;
|
||||
}
|
||||
|
||||
const ErDtlsAgentContext _er_dtls_agent_peek_context(ErDtlsAgent *self)
|
||||
const ErDtlsAgentContext
|
||||
_er_dtls_agent_peek_context (ErDtlsAgent * self)
|
||||
{
|
||||
g_return_val_if_fail(ER_IS_DTLS_AGENT(self), NULL);
|
||||
return self->priv->ssl_context;
|
||||
g_return_val_if_fail (ER_IS_DTLS_AGENT (self), NULL);
|
||||
return self->priv->ssl_context;
|
||||
}
|
||||
|
|
|
@ -40,268 +40,287 @@
|
|||
#include <openssl/ssl.h>
|
||||
|
||||
#if ER_DTLS_USE_GST_LOG
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_certificate_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_certificate_debug);
|
||||
# define GST_CAT_DEFAULT er_dtls_certificate_debug
|
||||
G_DEFINE_TYPE_WITH_CODE(ErDtlsCertificate, er_dtls_certificate, G_TYPE_OBJECT,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_certificate_debug, "gstdtlscertificate", 0, "Ericsson DTLS Certificate"));
|
||||
G_DEFINE_TYPE_WITH_CODE (ErDtlsCertificate, er_dtls_certificate, G_TYPE_OBJECT,
|
||||
GST_DEBUG_CATEGORY_INIT (er_dtls_certificate_debug, "gstdtlscertificate", 0,
|
||||
"Ericsson DTLS Certificate"));
|
||||
#else
|
||||
G_DEFINE_TYPE(ErDtlsCertificate, er_dtls_certificate, G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (ErDtlsCertificate, er_dtls_certificate, G_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
#define ER_DTLS_CERTIFICATE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ER_TYPE_DTLS_CERTIFICATE, ErDtlsCertificatePrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PEM,
|
||||
NUM_PROPERTIES
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_PEM,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
#define DEFAULT_PEM NULL
|
||||
|
||||
struct _ErDtlsCertificatePrivate {
|
||||
X509 *x509;
|
||||
EVP_PKEY *private_key;
|
||||
struct _ErDtlsCertificatePrivate
|
||||
{
|
||||
X509 *x509;
|
||||
EVP_PKEY *private_key;
|
||||
|
||||
gchar *pem;
|
||||
gchar *pem;
|
||||
};
|
||||
|
||||
static void er_dtls_certificate_finalize(GObject *gobject);
|
||||
static void er_dtls_certificate_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void er_dtls_certificate_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void er_dtls_certificate_finalize (GObject * gobject);
|
||||
static void er_dtls_certificate_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void er_dtls_certificate_get_property (GObject *, guint prop_id,
|
||||
GValue *, GParamSpec *);
|
||||
|
||||
static void init_generated(ErDtlsCertificate *);
|
||||
static void init_from_pem_string(ErDtlsCertificate *, const gchar *pem);
|
||||
static void init_generated (ErDtlsCertificate *);
|
||||
static void init_from_pem_string (ErDtlsCertificate *, const gchar * pem);
|
||||
|
||||
static void er_dtls_certificate_class_init(ErDtlsCertificateClass *klass)
|
||||
static void
|
||||
er_dtls_certificate_class_init (ErDtlsCertificateClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(ErDtlsCertificatePrivate));
|
||||
g_type_class_add_private (klass, sizeof (ErDtlsCertificatePrivate));
|
||||
|
||||
gobject_class->set_property = er_dtls_certificate_set_property;
|
||||
gobject_class->get_property = er_dtls_certificate_get_property;
|
||||
gobject_class->set_property = er_dtls_certificate_set_property;
|
||||
gobject_class->get_property = er_dtls_certificate_get_property;
|
||||
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string("pem",
|
||||
"Pem string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string ("pem",
|
||||
"Pem string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
_er_dtls_init_openssl();
|
||||
_er_dtls_init_openssl ();
|
||||
|
||||
gobject_class->finalize = er_dtls_certificate_finalize;
|
||||
gobject_class->finalize = er_dtls_certificate_finalize;
|
||||
}
|
||||
|
||||
static void er_dtls_certificate_init(ErDtlsCertificate *self)
|
||||
static void
|
||||
er_dtls_certificate_init (ErDtlsCertificate * self)
|
||||
{
|
||||
ErDtlsCertificatePrivate *priv = ER_DTLS_CERTIFICATE_GET_PRIVATE(self);
|
||||
self->priv = priv;
|
||||
ErDtlsCertificatePrivate *priv = ER_DTLS_CERTIFICATE_GET_PRIVATE (self);
|
||||
self->priv = priv;
|
||||
|
||||
priv->x509 = NULL;
|
||||
priv->private_key = NULL;
|
||||
priv->pem = NULL;
|
||||
priv->x509 = NULL;
|
||||
priv->private_key = NULL;
|
||||
priv->pem = NULL;
|
||||
}
|
||||
|
||||
static void er_dtls_certificate_finalize(GObject *gobject)
|
||||
static void
|
||||
er_dtls_certificate_finalize (GObject * gobject)
|
||||
{
|
||||
ErDtlsCertificatePrivate *priv = ER_DTLS_CERTIFICATE(gobject)->priv;
|
||||
ErDtlsCertificatePrivate *priv = ER_DTLS_CERTIFICATE (gobject)->priv;
|
||||
|
||||
X509_free(priv->x509);
|
||||
priv->x509 = NULL;
|
||||
X509_free (priv->x509);
|
||||
priv->x509 = NULL;
|
||||
|
||||
EVP_PKEY_free(priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
EVP_PKEY_free (priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
|
||||
|
||||
g_free(priv->pem);
|
||||
priv->pem = NULL;
|
||||
g_free (priv->pem);
|
||||
priv->pem = NULL;
|
||||
|
||||
G_OBJECT_CLASS(er_dtls_certificate_parent_class)->finalize(gobject);
|
||||
G_OBJECT_CLASS (er_dtls_certificate_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void er_dtls_certificate_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
er_dtls_certificate_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
ErDtlsCertificate *self = ER_DTLS_CERTIFICATE(object);
|
||||
const gchar *pem;
|
||||
ErDtlsCertificate *self = ER_DTLS_CERTIFICATE (object);
|
||||
const gchar *pem;
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_PEM:
|
||||
pem = g_value_get_string(value);
|
||||
if (pem) {
|
||||
init_from_pem_string(self, pem);
|
||||
} else {
|
||||
init_generated(self);
|
||||
}
|
||||
break;
|
||||
pem = g_value_get_string (value);
|
||||
if (pem) {
|
||||
init_from_pem_string (self, pem);
|
||||
} else {
|
||||
init_generated (self);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void er_dtls_certificate_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
er_dtls_certificate_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
ErDtlsCertificate *self = ER_DTLS_CERTIFICATE(object);
|
||||
ErDtlsCertificate *self = ER_DTLS_CERTIFICATE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_PEM:
|
||||
g_return_if_fail(self->priv->pem);
|
||||
g_value_set_string(value, self->priv->pem);
|
||||
break;
|
||||
g_return_if_fail (self->priv->pem);
|
||||
g_value_set_string (value, self->priv->pem);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_generated(ErDtlsCertificate *self)
|
||||
static void
|
||||
init_generated (ErDtlsCertificate * self)
|
||||
{
|
||||
ErDtlsCertificatePrivate *priv = self->priv;
|
||||
RSA *rsa;
|
||||
X509_NAME *name = NULL;
|
||||
ErDtlsCertificatePrivate *priv = self->priv;
|
||||
RSA *rsa;
|
||||
X509_NAME *name = NULL;
|
||||
|
||||
g_return_if_fail(!priv->x509);
|
||||
g_return_if_fail(!priv->private_key);
|
||||
g_return_if_fail (!priv->x509);
|
||||
g_return_if_fail (!priv->private_key);
|
||||
|
||||
priv->private_key = EVP_PKEY_new();
|
||||
priv->private_key = EVP_PKEY_new ();
|
||||
|
||||
if (!priv->private_key) {
|
||||
LOG_WARNING(self, "failed to create private key");
|
||||
return;
|
||||
}
|
||||
if (!priv->private_key) {
|
||||
LOG_WARNING (self, "failed to create private key");
|
||||
return;
|
||||
}
|
||||
|
||||
priv->x509 = X509_new();
|
||||
priv->x509 = X509_new ();
|
||||
|
||||
if (!priv->x509) {
|
||||
LOG_WARNING(self, "failed to create certificate");
|
||||
EVP_PKEY_free(priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
return;
|
||||
}
|
||||
rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
|
||||
if (!priv->x509) {
|
||||
LOG_WARNING (self, "failed to create certificate");
|
||||
EVP_PKEY_free (priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
return;
|
||||
}
|
||||
rsa = RSA_generate_key (2048, RSA_F4, NULL, NULL);
|
||||
|
||||
if (!rsa) {
|
||||
LOG_WARNING(self, "failed to generate RSA");
|
||||
EVP_PKEY_free(priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free(priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
if (!rsa) {
|
||||
LOG_WARNING (self, "failed to generate RSA");
|
||||
EVP_PKEY_free (priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free (priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_assign_RSA(priv->private_key, rsa)) {
|
||||
LOG_WARNING(self, "failed to assign RSA");
|
||||
RSA_free(rsa);
|
||||
rsa = NULL;
|
||||
EVP_PKEY_free(priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free(priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
if (!EVP_PKEY_assign_RSA (priv->private_key, rsa)) {
|
||||
LOG_WARNING (self, "failed to assign RSA");
|
||||
RSA_free (rsa);
|
||||
rsa = NULL;
|
||||
EVP_PKEY_free (priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free (priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
rsa = NULL;
|
||||
|
||||
X509_set_version(priv->x509, 2);
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(priv->x509), 0);
|
||||
X509_gmtime_adj(X509_get_notBefore(priv->x509), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(priv->x509), 31536000L); /* A year */
|
||||
X509_set_pubkey(priv->x509, priv->private_key);
|
||||
X509_set_version (priv->x509, 2);
|
||||
ASN1_INTEGER_set (X509_get_serialNumber (priv->x509), 0);
|
||||
X509_gmtime_adj (X509_get_notBefore (priv->x509), 0);
|
||||
X509_gmtime_adj (X509_get_notAfter (priv->x509), 31536000L); /* A year */
|
||||
X509_set_pubkey (priv->x509, priv->private_key);
|
||||
|
||||
name = X509_get_subject_name(priv->x509);
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*) "SE", -1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*) "OpenWebRTC", -1, -1, 0);
|
||||
X509_set_issuer_name(priv->x509, name);
|
||||
name = NULL;
|
||||
name = X509_get_subject_name (priv->x509);
|
||||
X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *) "SE",
|
||||
-1, -1, 0);
|
||||
X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC,
|
||||
(unsigned char *) "OpenWebRTC", -1, -1, 0);
|
||||
X509_set_issuer_name (priv->x509, name);
|
||||
name = NULL;
|
||||
|
||||
if (!X509_sign(priv->x509, priv->private_key, EVP_sha256())) {
|
||||
LOG_WARNING(self, "failed to sign certificate");
|
||||
EVP_PKEY_free(priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free(priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
if (!X509_sign (priv->x509, priv->private_key, EVP_sha256 ())) {
|
||||
LOG_WARNING (self, "failed to sign certificate");
|
||||
EVP_PKEY_free (priv->private_key);
|
||||
priv->private_key = NULL;
|
||||
X509_free (priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
self->priv->pem = _er_dtls_x509_to_pem(priv->x509);
|
||||
self->priv->pem = _er_dtls_x509_to_pem (priv->x509);
|
||||
}
|
||||
|
||||
static void init_from_pem_string(ErDtlsCertificate *self, const gchar *pem)
|
||||
static void
|
||||
init_from_pem_string (ErDtlsCertificate * self, const gchar * pem)
|
||||
{
|
||||
ErDtlsCertificatePrivate *priv = self->priv;
|
||||
BIO *bio;
|
||||
ErDtlsCertificatePrivate *priv = self->priv;
|
||||
BIO *bio;
|
||||
|
||||
g_return_if_fail(pem);
|
||||
g_return_if_fail(!priv->x509);
|
||||
g_return_if_fail(!priv->private_key);
|
||||
g_return_if_fail (pem);
|
||||
g_return_if_fail (!priv->x509);
|
||||
g_return_if_fail (!priv->private_key);
|
||||
|
||||
bio = BIO_new_mem_buf((gpointer) pem, -1);
|
||||
g_return_if_fail(bio);
|
||||
bio = BIO_new_mem_buf ((gpointer) pem, -1);
|
||||
g_return_if_fail (bio);
|
||||
|
||||
priv->x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||
priv->x509 = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
|
||||
|
||||
if (!priv->x509) {
|
||||
LOG_WARNING(self, "failed to read certificate from pem string");
|
||||
return;
|
||||
}
|
||||
if (!priv->x509) {
|
||||
LOG_WARNING (self, "failed to read certificate from pem string");
|
||||
return;
|
||||
}
|
||||
|
||||
(void) BIO_reset(bio);
|
||||
(void) BIO_reset (bio);
|
||||
|
||||
priv->private_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||
priv->private_key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(bio);
|
||||
bio = NULL;
|
||||
BIO_free (bio);
|
||||
bio = NULL;
|
||||
|
||||
if (!priv->private_key) {
|
||||
LOG_WARNING(self, "failed to read private key from pem string");
|
||||
X509_free(priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
if (!priv->private_key) {
|
||||
LOG_WARNING (self, "failed to read private key from pem string");
|
||||
X509_free (priv->x509);
|
||||
priv->x509 = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
self->priv->pem = g_strdup(pem);
|
||||
self->priv->pem = g_strdup (pem);
|
||||
}
|
||||
|
||||
gchar *_er_dtls_x509_to_pem(gpointer x509)
|
||||
gchar *
|
||||
_er_dtls_x509_to_pem (gpointer x509)
|
||||
{
|
||||
#define ER_DTLS_BIO_BUFFER_SIZE 4096
|
||||
BIO *bio;
|
||||
gchar buffer[ER_DTLS_BIO_BUFFER_SIZE] = {0};
|
||||
gint len;
|
||||
gchar *pem = NULL;
|
||||
BIO *bio;
|
||||
gchar buffer[ER_DTLS_BIO_BUFFER_SIZE] = { 0 };
|
||||
gint len;
|
||||
gchar *pem = NULL;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
g_return_val_if_fail(bio, NULL);
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
g_return_val_if_fail (bio, NULL);
|
||||
|
||||
if (!PEM_write_bio_X509(bio, (X509 *) x509)) {
|
||||
g_warn_if_reached();
|
||||
goto beach;
|
||||
}
|
||||
if (!PEM_write_bio_X509 (bio, (X509 *) x509)) {
|
||||
g_warn_if_reached ();
|
||||
goto beach;
|
||||
}
|
||||
|
||||
len = BIO_read(bio, buffer, ER_DTLS_BIO_BUFFER_SIZE);
|
||||
if (!len) {
|
||||
g_warn_if_reached();
|
||||
goto beach;
|
||||
}
|
||||
len = BIO_read (bio, buffer, ER_DTLS_BIO_BUFFER_SIZE);
|
||||
if (!len) {
|
||||
g_warn_if_reached ();
|
||||
goto beach;
|
||||
}
|
||||
|
||||
pem = g_strndup(buffer, len);
|
||||
pem = g_strndup (buffer, len);
|
||||
|
||||
beach:
|
||||
BIO_free(bio);
|
||||
BIO_free (bio);
|
||||
|
||||
return pem;
|
||||
return pem;
|
||||
}
|
||||
|
||||
ErDtlsCertificateInternalCertificate _er_dtls_certificate_get_internal_certificate(ErDtlsCertificate *self)
|
||||
ErDtlsCertificateInternalCertificate
|
||||
_er_dtls_certificate_get_internal_certificate (ErDtlsCertificate * self)
|
||||
{
|
||||
g_return_val_if_fail(ER_IS_DTLS_CERTIFICATE(self), NULL);
|
||||
return self->priv->x509;
|
||||
g_return_val_if_fail (ER_IS_DTLS_CERTIFICATE (self), NULL);
|
||||
return self->priv->x509;
|
||||
}
|
||||
|
||||
ErDtlsCertificateInternalKey _er_dtls_certificate_get_internal_key(ErDtlsCertificate *self)
|
||||
ErDtlsCertificateInternalKey
|
||||
_er_dtls_certificate_get_internal_key (ErDtlsCertificate * self)
|
||||
{
|
||||
g_return_val_if_fail(ER_IS_DTLS_CERTIFICATE(self), NULL);
|
||||
return self->priv->private_key;
|
||||
g_return_val_if_fail (ER_IS_DTLS_CERTIFICATE (self), NULL);
|
||||
return self->priv->private_key;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,46 +31,46 @@
|
|||
|
||||
#include "gstdtlscertificate.h"
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS("application/x-dtls")
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-dtls")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_dec_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_dec_debug);
|
||||
#define GST_CAT_DEFAULT er_dtls_dec_debug
|
||||
|
||||
#define gst_er_dtls_dec_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE(GstErDtlsDec, gst_er_dtls_dec, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_dec_debug, "erdtlsdec", 0, "Ericsson DTLS Decoder"));
|
||||
G_DEFINE_TYPE_WITH_CODE (GstErDtlsDec, gst_er_dtls_dec, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT (er_dtls_dec_debug, "erdtlsdec", 0,
|
||||
"Ericsson DTLS Decoder"));
|
||||
|
||||
#define UNUSED(param) while (0) { (void)(param); }
|
||||
|
||||
enum {
|
||||
SIGNAL_ON_KEY_RECEIVED,
|
||||
NUM_SIGNALS
|
||||
enum
|
||||
{
|
||||
SIGNAL_ON_KEY_RECEIVED,
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[NUM_SIGNALS];
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_PEM,
|
||||
PROP_PEER_PEM,
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_PEM,
|
||||
PROP_PEER_PEM,
|
||||
|
||||
PROP_DECODER_KEY,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTP_AUTH,
|
||||
NUM_PROPERTIES
|
||||
PROP_DECODER_KEY,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTP_AUTH,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
@ -84,524 +84,565 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
|||
#define DEFAULT_SRTP_AUTH 0
|
||||
|
||||
|
||||
static void gst_er_dtls_dec_finalize(GObject *);
|
||||
static void gst_er_dtls_dec_dispose(GObject *);
|
||||
static void gst_er_dtls_dec_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_dec_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_dec_finalize (GObject *);
|
||||
static void gst_er_dtls_dec_dispose (GObject *);
|
||||
static void gst_er_dtls_dec_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_dec_get_property (GObject *, guint prop_id, GValue *,
|
||||
GParamSpec *);
|
||||
|
||||
static GstStateChangeReturn gst_er_dtls_dec_change_state(GstElement *, GstStateChange);
|
||||
static GstPad *gst_er_dtls_dec_request_new_pad(GstElement *, GstPadTemplate *, const gchar *name, const GstCaps *);
|
||||
static void gst_er_dtls_dec_release_pad(GstElement *, GstPad *);
|
||||
static GstStateChangeReturn gst_er_dtls_dec_change_state (GstElement *,
|
||||
GstStateChange);
|
||||
static GstPad *gst_er_dtls_dec_request_new_pad (GstElement *, GstPadTemplate *,
|
||||
const gchar * name, const GstCaps *);
|
||||
static void gst_er_dtls_dec_release_pad (GstElement *, GstPad *);
|
||||
|
||||
static void on_key_received(ErDtlsConnection *, gpointer key, guint cipher, guint auth, GstErDtlsDec *);
|
||||
static gboolean on_peer_certificate_received(ErDtlsConnection *, gchar *pem, GstErDtlsDec *);
|
||||
static GstFlowReturn sink_chain(GstPad *, GstObject *parent, GstBuffer *);
|
||||
static void on_key_received (ErDtlsConnection *, gpointer key, guint cipher,
|
||||
guint auth, GstErDtlsDec *);
|
||||
static gboolean on_peer_certificate_received (ErDtlsConnection *, gchar * pem,
|
||||
GstErDtlsDec *);
|
||||
static GstFlowReturn sink_chain (GstPad *, GstObject * parent, GstBuffer *);
|
||||
|
||||
static ErDtlsAgent *get_agent_by_pem(const gchar *pem);
|
||||
static void agent_weak_ref_notify(gchar *pem, ErDtlsAgent *);
|
||||
static void create_connection(GstErDtlsDec *, gchar *id);
|
||||
static void connection_weak_ref_notify(gchar *id, ErDtlsConnection *);
|
||||
static ErDtlsAgent *get_agent_by_pem (const gchar * pem);
|
||||
static void agent_weak_ref_notify (gchar * pem, ErDtlsAgent *);
|
||||
static void create_connection (GstErDtlsDec *, gchar * id);
|
||||
static void connection_weak_ref_notify (gchar * id, ErDtlsConnection *);
|
||||
|
||||
static void gst_er_dtls_dec_class_init(GstErDtlsDecClass *klass)
|
||||
static void
|
||||
gst_er_dtls_dec_class_init (GstErDtlsDecClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_finalize);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_dispose);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_get_property);
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_er_dtls_dec_finalize);
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_er_dtls_dec_dispose);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_dec_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_dec_get_property);
|
||||
|
||||
element_class->change_state = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_change_state);
|
||||
element_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_request_new_pad);
|
||||
element_class->release_pad = GST_DEBUG_FUNCPTR(gst_er_dtls_dec_release_pad);
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_dec_change_state);
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_dec_request_new_pad);
|
||||
element_class->release_pad = GST_DEBUG_FUNCPTR (gst_er_dtls_dec_release_pad);
|
||||
|
||||
signals[SIGNAL_ON_KEY_RECEIVED] =
|
||||
g_signal_new("on-key-received", G_TYPE_FROM_CLASS(klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
signals[SIGNAL_ON_KEY_RECEIVED] =
|
||||
g_signal_new ("on-key-received", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string ("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string("pem",
|
||||
"PEM string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string ("pem",
|
||||
"PEM string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_PEER_PEM] =
|
||||
g_param_spec_string("peer-pem",
|
||||
"Peer PEM string",
|
||||
"The X509 certificate received in the DTLS handshake, in PEM format",
|
||||
DEFAULT_PEER_PEM,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_PEER_PEM] =
|
||||
g_param_spec_string ("peer-pem",
|
||||
"Peer PEM string",
|
||||
"The X509 certificate received in the DTLS handshake, in PEM format",
|
||||
DEFAULT_PEER_PEM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_DECODER_KEY] =
|
||||
g_param_spec_boxed("decoder-key",
|
||||
"Decoder key",
|
||||
"SRTP key that should be used by the decider",
|
||||
GST_TYPE_CAPS,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_DECODER_KEY] =
|
||||
g_param_spec_boxed ("decoder-key",
|
||||
"Decoder key",
|
||||
"SRTP key that should be used by the decider",
|
||||
GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_uint("srtp-cipher",
|
||||
"SRTP cipher",
|
||||
"The SRTP cipher selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpCipher.",
|
||||
0, ER_DTLS_SRTP_CIPHER_AES_128_ICM, DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_uint ("srtp-cipher",
|
||||
"SRTP cipher",
|
||||
"The SRTP cipher selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpCipher.",
|
||||
0, ER_DTLS_SRTP_CIPHER_AES_128_ICM, DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_uint("srtp-auth",
|
||||
"SRTP authentication",
|
||||
"The SRTP authentication selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpAuth.",
|
||||
0, ER_DTLS_SRTP_AUTH_HMAC_SHA1_80, DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_uint ("srtp-auth",
|
||||
"SRTP authentication",
|
||||
"The SRTP authentication selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpAuth.",
|
||||
0, ER_DTLS_SRTP_AUTH_HMAC_SHA1_80, DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&src_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata(element_class,
|
||||
"DTLS Decoder",
|
||||
"Decoder/Network/DTLS",
|
||||
"Decodes DTLS packets",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"DTLS Decoder",
|
||||
"Decoder/Network/DTLS",
|
||||
"Decodes DTLS packets", "Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_init(GstErDtlsDec *self)
|
||||
static void
|
||||
gst_er_dtls_dec_init (GstErDtlsDec * self)
|
||||
{
|
||||
GstPad *sink;
|
||||
self->agent = get_agent_by_pem(NULL);
|
||||
self->connection_id = NULL;
|
||||
self->connection = NULL;
|
||||
self->peer_pem = NULL;
|
||||
GstPad *sink;
|
||||
self->agent = get_agent_by_pem (NULL);
|
||||
self->connection_id = NULL;
|
||||
self->connection = NULL;
|
||||
self->peer_pem = NULL;
|
||||
|
||||
self->decoder_key = NULL;
|
||||
self->srtp_cipher = DEFAULT_SRTP_CIPHER;
|
||||
self->srtp_auth = DEFAULT_SRTP_AUTH;
|
||||
|
||||
g_mutex_init (&self->src_mutex);
|
||||
|
||||
self->src = NULL;
|
||||
sink = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||
g_return_if_fail (sink);
|
||||
|
||||
gst_pad_set_chain_function (sink, GST_DEBUG_FUNCPTR (sink_chain));
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT (self), sink);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_er_dtls_dec_finalize (GObject * object)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (object);
|
||||
|
||||
if (self->decoder_key) {
|
||||
gst_buffer_unref (self->decoder_key);
|
||||
self->decoder_key = NULL;
|
||||
self->srtp_cipher = DEFAULT_SRTP_CIPHER;
|
||||
self->srtp_auth = DEFAULT_SRTP_AUTH;
|
||||
}
|
||||
|
||||
g_mutex_init(&self->src_mutex);
|
||||
g_free (self->connection_id);
|
||||
self->connection_id = NULL;
|
||||
|
||||
self->src = NULL;
|
||||
sink = gst_pad_new_from_static_template(&sink_template, "sink");
|
||||
g_return_if_fail(sink);
|
||||
g_free (self->peer_pem);
|
||||
self->peer_pem = NULL;
|
||||
|
||||
gst_pad_set_chain_function(sink, GST_DEBUG_FUNCPTR(sink_chain));
|
||||
g_mutex_clear (&self->src_mutex);
|
||||
|
||||
gst_element_add_pad(GST_ELEMENT(self), sink);
|
||||
GST_LOG_OBJECT (self, "finalized");
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_finalize(GObject *object)
|
||||
static void
|
||||
gst_er_dtls_dec_dispose (GObject * object)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(object);
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (object);
|
||||
|
||||
if (self->decoder_key) {
|
||||
gst_buffer_unref(self->decoder_key);
|
||||
self->decoder_key = NULL;
|
||||
}
|
||||
if (self->agent) {
|
||||
g_object_unref (self->agent);
|
||||
self->agent = NULL;
|
||||
}
|
||||
|
||||
g_free(self->connection_id);
|
||||
self->connection_id = NULL;
|
||||
|
||||
g_free(self->peer_pem);
|
||||
self->peer_pem = NULL;
|
||||
|
||||
g_mutex_clear(&self->src_mutex);
|
||||
|
||||
GST_LOG_OBJECT(self, "finalized");
|
||||
|
||||
G_OBJECT_CLASS(parent_class)->finalize(object);
|
||||
if (self->connection) {
|
||||
g_object_unref (self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_dispose(GObject *object)
|
||||
static void
|
||||
gst_er_dtls_dec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(object);
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (object);
|
||||
|
||||
if (self->agent) {
|
||||
g_object_unref(self->agent);
|
||||
self->agent = NULL;
|
||||
}
|
||||
|
||||
if (self->connection) {
|
||||
g_object_unref(self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
g_free(self->connection_id);
|
||||
self->connection_id = g_value_dup_string(value);
|
||||
g_return_if_fail(self->agent);
|
||||
create_connection(self, self->connection_id);
|
||||
break;
|
||||
g_free (self->connection_id);
|
||||
self->connection_id = g_value_dup_string (value);
|
||||
g_return_if_fail (self->agent);
|
||||
create_connection (self, self->connection_id);
|
||||
break;
|
||||
case PROP_PEM:
|
||||
if (self->agent) {
|
||||
g_object_unref(self->agent);
|
||||
}
|
||||
self->agent = get_agent_by_pem(g_value_get_string(value));
|
||||
if (self->connection_id) {
|
||||
create_connection(self, self->connection_id);
|
||||
}
|
||||
break;
|
||||
if (self->agent) {
|
||||
g_object_unref (self->agent);
|
||||
}
|
||||
self->agent = get_agent_by_pem (g_value_get_string (value));
|
||||
if (self->connection_id) {
|
||||
create_connection (self, self->connection_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(object);
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
g_value_set_string(value, self->connection_id);
|
||||
break;
|
||||
g_value_set_string (value, self->connection_id);
|
||||
break;
|
||||
case PROP_PEM:
|
||||
g_value_take_string(value, er_dtls_agent_get_certificate_pem(self->agent));
|
||||
break;
|
||||
g_value_take_string (value,
|
||||
er_dtls_agent_get_certificate_pem (self->agent));
|
||||
break;
|
||||
case PROP_PEER_PEM:
|
||||
g_value_set_string(value, self->peer_pem);
|
||||
break;
|
||||
g_value_set_string (value, self->peer_pem);
|
||||
break;
|
||||
case PROP_DECODER_KEY:
|
||||
g_value_set_boxed(value, self->decoder_key);
|
||||
break;
|
||||
g_value_set_boxed (value, self->decoder_key);
|
||||
break;
|
||||
case PROP_SRTP_CIPHER:
|
||||
g_value_set_uint(value, self->srtp_cipher);
|
||||
break;
|
||||
g_value_set_uint (value, self->srtp_cipher);
|
||||
break;
|
||||
case PROP_SRTP_AUTH:
|
||||
g_value_set_uint(value, self->srtp_auth);
|
||||
break;
|
||||
g_value_set_uint (value, self->srtp_auth);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static GstStateChangeReturn gst_er_dtls_dec_change_state(GstElement *element, GstStateChange transition)
|
||||
static GstStateChangeReturn
|
||||
gst_er_dtls_dec_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(element);
|
||||
GstStateChangeReturn ret;
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (element);
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
switch (transition) {
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
if (self->connection) {
|
||||
g_signal_connect_object(self->connection,
|
||||
"on-decoder-key", G_CALLBACK(on_key_received), self, 0);
|
||||
g_signal_connect_object(self->connection,
|
||||
"on-peer-certificate", G_CALLBACK(on_peer_certificate_received), self, 0);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "trying to change state to ready without connection id and pem");
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
}
|
||||
break;
|
||||
if (self->connection) {
|
||||
g_signal_connect_object (self->connection,
|
||||
"on-decoder-key", G_CALLBACK (on_key_received), self, 0);
|
||||
g_signal_connect_object (self->connection,
|
||||
"on-peer-certificate", G_CALLBACK (on_peer_certificate_received),
|
||||
self, 0);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"trying to change state to ready without connection id and pem");
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstPad *gst_er_dtls_dec_request_new_pad(GstElement *element,
|
||||
GstPadTemplate *tmpl, const gchar *name, const GstCaps *caps)
|
||||
static GstPad *
|
||||
gst_er_dtls_dec_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * tmpl, const gchar * name, const GstCaps * caps)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(element);
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (element);
|
||||
|
||||
GST_DEBUG_OBJECT(element, "requesting pad");
|
||||
GST_DEBUG_OBJECT (element, "requesting pad");
|
||||
|
||||
g_return_val_if_fail(!self->src, NULL);
|
||||
g_return_val_if_fail(tmpl->direction == GST_PAD_SRC, NULL);
|
||||
g_return_val_if_fail (!self->src, NULL);
|
||||
g_return_val_if_fail (tmpl->direction == GST_PAD_SRC, NULL);
|
||||
|
||||
g_mutex_lock(&self->src_mutex);
|
||||
g_mutex_lock (&self->src_mutex);
|
||||
|
||||
self->src = gst_pad_new_from_template(tmpl, name);
|
||||
g_return_val_if_fail(self->src, NULL);
|
||||
self->src = gst_pad_new_from_template (tmpl, name);
|
||||
g_return_val_if_fail (self->src, NULL);
|
||||
|
||||
if (caps) {
|
||||
g_object_set(self->src, "caps", caps, NULL);
|
||||
}
|
||||
if (caps) {
|
||||
g_object_set (self->src, "caps", caps, NULL);
|
||||
}
|
||||
|
||||
gst_pad_set_active(self->src, TRUE);
|
||||
gst_element_add_pad(element, self->src);
|
||||
gst_pad_set_active (self->src, TRUE);
|
||||
gst_element_add_pad (element, self->src);
|
||||
|
||||
g_mutex_unlock(&self->src_mutex);
|
||||
g_mutex_unlock (&self->src_mutex);
|
||||
|
||||
return self->src;
|
||||
return self->src;
|
||||
}
|
||||
|
||||
static void gst_er_dtls_dec_release_pad(GstElement *element, GstPad *pad)
|
||||
static void
|
||||
gst_er_dtls_dec_release_pad (GstElement * element, GstPad * pad)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(element);
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (element);
|
||||
|
||||
g_mutex_lock(&self->src_mutex);
|
||||
g_mutex_lock (&self->src_mutex);
|
||||
|
||||
g_return_if_fail(self->src == pad);
|
||||
gst_element_remove_pad(element, self->src);
|
||||
self->src = NULL;
|
||||
g_return_if_fail (self->src == pad);
|
||||
gst_element_remove_pad (element, self->src);
|
||||
self->src = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT(self, "releasing src pad");
|
||||
GST_DEBUG_OBJECT (self, "releasing src pad");
|
||||
|
||||
g_mutex_unlock(&self->src_mutex);
|
||||
g_mutex_unlock (&self->src_mutex);
|
||||
|
||||
GST_ELEMENT_GET_CLASS(element)->release_pad(element, pad);
|
||||
GST_ELEMENT_GET_CLASS (element)->release_pad (element, pad);
|
||||
}
|
||||
|
||||
static void on_key_received(ErDtlsConnection *connection, gpointer key, guint cipher, guint auth, GstErDtlsDec *self)
|
||||
static void
|
||||
on_key_received (ErDtlsConnection * connection, gpointer key, guint cipher,
|
||||
guint auth, GstErDtlsDec * self)
|
||||
{
|
||||
gpointer key_dup;
|
||||
gchar *key_str;
|
||||
gpointer key_dup;
|
||||
gchar *key_str;
|
||||
|
||||
UNUSED(connection);
|
||||
g_return_if_fail(GST_IS_ER_DTLS_DEC(self));
|
||||
UNUSED (connection);
|
||||
g_return_if_fail (GST_IS_ER_DTLS_DEC (self));
|
||||
|
||||
self->srtp_cipher = cipher;
|
||||
self->srtp_auth = auth;
|
||||
self->srtp_cipher = cipher;
|
||||
self->srtp_auth = auth;
|
||||
|
||||
key_dup = g_memdup(key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
self->decoder_key = gst_buffer_new_wrapped(key_dup, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
key_dup = g_memdup (key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
self->decoder_key =
|
||||
gst_buffer_new_wrapped (key_dup, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
|
||||
key_str = g_base64_encode(key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
GST_INFO_OBJECT(self, "received key: %s", key_str);
|
||||
g_free(key_str);
|
||||
key_str = g_base64_encode (key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
GST_INFO_OBJECT (self, "received key: %s", key_str);
|
||||
g_free (key_str);
|
||||
|
||||
g_signal_emit(self, signals[SIGNAL_ON_KEY_RECEIVED], 0);
|
||||
g_signal_emit (self, signals[SIGNAL_ON_KEY_RECEIVED], 0);
|
||||
}
|
||||
|
||||
static gboolean signal_peer_certificate_received(GWeakRef *ref)
|
||||
static gboolean
|
||||
signal_peer_certificate_received (GWeakRef * ref)
|
||||
{
|
||||
GstErDtlsDec *self;
|
||||
GstErDtlsDec *self;
|
||||
|
||||
self = g_weak_ref_get(ref);
|
||||
g_weak_ref_clear(ref);
|
||||
g_free(ref);
|
||||
ref = NULL;
|
||||
self = g_weak_ref_get (ref);
|
||||
g_weak_ref_clear (ref);
|
||||
g_free (ref);
|
||||
ref = NULL;
|
||||
|
||||
if (self) {
|
||||
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_PEER_PEM]);
|
||||
g_object_unref(self);
|
||||
self = NULL;
|
||||
}
|
||||
if (self) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PEER_PEM]);
|
||||
g_object_unref (self);
|
||||
self = NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean on_peer_certificate_received(ErDtlsConnection *connection, gchar *pem, GstErDtlsDec *self)
|
||||
static gboolean
|
||||
on_peer_certificate_received (ErDtlsConnection * connection, gchar * pem,
|
||||
GstErDtlsDec * self)
|
||||
{
|
||||
GWeakRef *ref;
|
||||
GWeakRef *ref;
|
||||
|
||||
UNUSED(connection);
|
||||
g_return_val_if_fail(GST_IS_ER_DTLS_DEC(self), TRUE);
|
||||
UNUSED (connection);
|
||||
g_return_val_if_fail (GST_IS_ER_DTLS_DEC (self), TRUE);
|
||||
|
||||
GST_DEBUG_OBJECT(self, "Received peer certificate PEM: \n%s", pem);
|
||||
GST_DEBUG_OBJECT (self, "Received peer certificate PEM: \n%s", pem);
|
||||
|
||||
self->peer_pem = g_strdup(pem);
|
||||
self->peer_pem = g_strdup (pem);
|
||||
|
||||
ref = g_new(GWeakRef, 1);
|
||||
g_weak_ref_init(ref, self);
|
||||
ref = g_new (GWeakRef, 1);
|
||||
g_weak_ref_init (ref, self);
|
||||
|
||||
g_idle_add((GSourceFunc) signal_peer_certificate_received, ref);
|
||||
g_idle_add ((GSourceFunc) signal_peer_certificate_received, ref);
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buffer)
|
||||
static GstFlowReturn
|
||||
sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC(parent);
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstMapInfo map_info = GST_MAP_INFO_INIT;
|
||||
gint size;
|
||||
GstErDtlsDec *self = GST_ER_DTLS_DEC (parent);
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstMapInfo map_info = GST_MAP_INFO_INIT;
|
||||
gint size;
|
||||
|
||||
if (!self->agent) {
|
||||
gst_buffer_unref(buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
if (!self->agent) {
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT(self, "received buffer from %s with length %zd",
|
||||
self->connection_id, gst_buffer_get_size(buffer));
|
||||
GST_DEBUG_OBJECT (self, "received buffer from %s with length %zd",
|
||||
self->connection_id, gst_buffer_get_size (buffer));
|
||||
|
||||
gst_buffer_map(buffer, &map_info, GST_MAP_READWRITE);
|
||||
gst_buffer_map (buffer, &map_info, GST_MAP_READWRITE);
|
||||
|
||||
if (!map_info.size) {
|
||||
gst_buffer_unmap(buffer, &map_info);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
if (!map_info.size) {
|
||||
gst_buffer_unmap (buffer, &map_info);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
size = er_dtls_connection_process(self->connection, map_info.data, map_info.size);
|
||||
gst_buffer_unmap(buffer, &map_info);
|
||||
size =
|
||||
er_dtls_connection_process (self->connection, map_info.data,
|
||||
map_info.size);
|
||||
gst_buffer_unmap (buffer, &map_info);
|
||||
|
||||
if (size <= 0) {
|
||||
gst_buffer_unref(buffer);
|
||||
if (size <= 0) {
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
g_mutex_lock(&self->src_mutex);
|
||||
g_mutex_lock (&self->src_mutex);
|
||||
|
||||
if (self->src) {
|
||||
gst_buffer_set_size(buffer, size);
|
||||
GST_LOG_OBJECT(self, "decoded buffer with length %d, pushing", size);
|
||||
ret = gst_pad_push(self->src, buffer);
|
||||
} else {
|
||||
GST_LOG_OBJECT(self, "dropped buffer with length %d, not linked", size);
|
||||
gst_buffer_unref(buffer);
|
||||
}
|
||||
if (self->src) {
|
||||
gst_buffer_set_size (buffer, size);
|
||||
GST_LOG_OBJECT (self, "decoded buffer with length %d, pushing", size);
|
||||
ret = gst_pad_push (self->src, buffer);
|
||||
} else {
|
||||
GST_LOG_OBJECT (self, "dropped buffer with length %d, not linked", size);
|
||||
gst_buffer_unref (buffer);
|
||||
}
|
||||
|
||||
g_mutex_unlock(&self->src_mutex);
|
||||
g_mutex_unlock (&self->src_mutex);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GHashTable *agent_table = NULL;
|
||||
G_LOCK_DEFINE_STATIC(agent_table);
|
||||
G_LOCK_DEFINE_STATIC (agent_table);
|
||||
|
||||
static ErDtlsAgent *generated_cert_agent = NULL;
|
||||
|
||||
static ErDtlsAgent *get_agent_by_pem(const gchar *pem)
|
||||
static ErDtlsAgent *
|
||||
get_agent_by_pem (const gchar * pem)
|
||||
{
|
||||
ErDtlsAgent *agent;
|
||||
ErDtlsAgent *agent;
|
||||
|
||||
if (!pem) {
|
||||
if (g_once_init_enter (&generated_cert_agent)) {
|
||||
ErDtlsAgent *new_agent;
|
||||
if (!pem) {
|
||||
if (g_once_init_enter (&generated_cert_agent)) {
|
||||
ErDtlsAgent *new_agent;
|
||||
|
||||
new_agent = g_object_new(ER_TYPE_DTLS_AGENT, "certificate",
|
||||
g_object_new(ER_TYPE_DTLS_CERTIFICATE, NULL), NULL);
|
||||
new_agent = g_object_new (ER_TYPE_DTLS_AGENT, "certificate",
|
||||
g_object_new (ER_TYPE_DTLS_CERTIFICATE, NULL), NULL);
|
||||
|
||||
GST_DEBUG_OBJECT(generated_cert_agent, "no agent with generated cert found, creating new");
|
||||
g_once_init_leave (&generated_cert_agent, new_agent);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT(generated_cert_agent, "using agent with generated cert");
|
||||
}
|
||||
|
||||
agent = generated_cert_agent;
|
||||
g_object_ref(agent);
|
||||
GST_DEBUG_OBJECT (generated_cert_agent,
|
||||
"no agent with generated cert found, creating new");
|
||||
g_once_init_leave (&generated_cert_agent, new_agent);
|
||||
} else {
|
||||
G_LOCK(agent_table);
|
||||
|
||||
if (!agent_table) {
|
||||
agent_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
||||
}
|
||||
|
||||
agent = ER_DTLS_AGENT(g_hash_table_lookup(agent_table, pem));
|
||||
|
||||
if (!agent) {
|
||||
agent = g_object_new(ER_TYPE_DTLS_AGENT,
|
||||
"certificate", g_object_new(ER_TYPE_DTLS_CERTIFICATE, "pem", pem, NULL), NULL);
|
||||
|
||||
g_object_weak_ref(G_OBJECT(agent), (GWeakNotify) agent_weak_ref_notify, (gpointer) g_strdup(pem));
|
||||
|
||||
g_hash_table_insert(agent_table, g_strdup(pem), agent);
|
||||
|
||||
GST_DEBUG_OBJECT(agent, "no agent found, created new");
|
||||
} else {
|
||||
g_object_ref(agent);
|
||||
GST_DEBUG_OBJECT(agent, "agent found");
|
||||
}
|
||||
|
||||
G_UNLOCK(agent_table);
|
||||
GST_DEBUG_OBJECT (generated_cert_agent,
|
||||
"using agent with generated cert");
|
||||
}
|
||||
|
||||
agent = generated_cert_agent;
|
||||
g_object_ref (agent);
|
||||
} else {
|
||||
G_LOCK (agent_table);
|
||||
|
||||
return agent;
|
||||
if (!agent_table) {
|
||||
agent_table =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
}
|
||||
|
||||
agent = ER_DTLS_AGENT (g_hash_table_lookup (agent_table, pem));
|
||||
|
||||
if (!agent) {
|
||||
agent = g_object_new (ER_TYPE_DTLS_AGENT,
|
||||
"certificate", g_object_new (ER_TYPE_DTLS_CERTIFICATE, "pem", pem,
|
||||
NULL), NULL);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (agent), (GWeakNotify) agent_weak_ref_notify,
|
||||
(gpointer) g_strdup (pem));
|
||||
|
||||
g_hash_table_insert (agent_table, g_strdup (pem), agent);
|
||||
|
||||
GST_DEBUG_OBJECT (agent, "no agent found, created new");
|
||||
} else {
|
||||
g_object_ref (agent);
|
||||
GST_DEBUG_OBJECT (agent, "agent found");
|
||||
}
|
||||
|
||||
G_UNLOCK (agent_table);
|
||||
}
|
||||
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
||||
static void agent_weak_ref_notify(gchar *pem, ErDtlsAgent *agent)
|
||||
static void
|
||||
agent_weak_ref_notify (gchar * pem, ErDtlsAgent * agent)
|
||||
{
|
||||
UNUSED(agent);
|
||||
UNUSED (agent);
|
||||
|
||||
G_LOCK(agent_table);
|
||||
g_hash_table_remove(agent_table, pem);
|
||||
G_UNLOCK(agent_table);
|
||||
G_LOCK (agent_table);
|
||||
g_hash_table_remove (agent_table, pem);
|
||||
G_UNLOCK (agent_table);
|
||||
|
||||
g_free(pem);
|
||||
pem = NULL;
|
||||
g_free (pem);
|
||||
pem = NULL;
|
||||
}
|
||||
|
||||
static GHashTable *connection_table = NULL;
|
||||
G_LOCK_DEFINE_STATIC(connection_table);
|
||||
G_LOCK_DEFINE_STATIC (connection_table);
|
||||
|
||||
ErDtlsConnection *gst_er_dtls_dec_fetch_connection(gchar *id)
|
||||
ErDtlsConnection *
|
||||
gst_er_dtls_dec_fetch_connection (gchar * id)
|
||||
{
|
||||
ErDtlsConnection *connection;
|
||||
g_return_val_if_fail(id, NULL);
|
||||
ErDtlsConnection *connection;
|
||||
g_return_val_if_fail (id, NULL);
|
||||
|
||||
GST_DEBUG("fetching '%s' from connection table, size is %d",
|
||||
id, g_hash_table_size(connection_table));
|
||||
GST_DEBUG ("fetching '%s' from connection table, size is %d",
|
||||
id, g_hash_table_size (connection_table));
|
||||
|
||||
G_LOCK(connection_table);
|
||||
G_LOCK (connection_table);
|
||||
|
||||
connection = g_hash_table_lookup(connection_table, id);
|
||||
connection = g_hash_table_lookup (connection_table, id);
|
||||
|
||||
if (connection) {
|
||||
g_object_ref(connection);
|
||||
g_hash_table_remove(connection_table, id);
|
||||
} else {
|
||||
GST_WARNING("no connection with id '%s' found", id);
|
||||
}
|
||||
if (connection) {
|
||||
g_object_ref (connection);
|
||||
g_hash_table_remove (connection_table, id);
|
||||
} else {
|
||||
GST_WARNING ("no connection with id '%s' found", id);
|
||||
}
|
||||
|
||||
G_UNLOCK(connection_table);
|
||||
G_UNLOCK (connection_table);
|
||||
|
||||
return connection;
|
||||
return connection;
|
||||
}
|
||||
|
||||
static void create_connection(GstErDtlsDec *self, gchar *id)
|
||||
static void
|
||||
create_connection (GstErDtlsDec * self, gchar * id)
|
||||
{
|
||||
g_return_if_fail(GST_IS_ER_DTLS_DEC(self));
|
||||
g_return_if_fail(ER_IS_DTLS_AGENT(self->agent));
|
||||
g_return_if_fail (GST_IS_ER_DTLS_DEC (self));
|
||||
g_return_if_fail (ER_IS_DTLS_AGENT (self->agent));
|
||||
|
||||
if (self->connection) {
|
||||
g_object_unref(self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
if (self->connection) {
|
||||
g_object_unref (self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
|
||||
G_LOCK(connection_table);
|
||||
G_LOCK (connection_table);
|
||||
|
||||
if (!connection_table) {
|
||||
connection_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
||||
}
|
||||
if (!connection_table) {
|
||||
connection_table =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
}
|
||||
|
||||
if (g_hash_table_contains(connection_table, id)) {
|
||||
G_UNLOCK(connection_table);
|
||||
if (g_hash_table_contains (connection_table, id)) {
|
||||
G_UNLOCK (connection_table);
|
||||
|
||||
g_return_if_reached();
|
||||
}
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
self->connection = g_object_new(ER_TYPE_DTLS_CONNECTION, "agent", self->agent, NULL);
|
||||
self->connection =
|
||||
g_object_new (ER_TYPE_DTLS_CONNECTION, "agent", self->agent, NULL);
|
||||
|
||||
g_object_weak_ref(G_OBJECT(self->connection), (GWeakNotify) connection_weak_ref_notify, g_strdup(id));
|
||||
g_object_weak_ref (G_OBJECT (self->connection),
|
||||
(GWeakNotify) connection_weak_ref_notify, g_strdup (id));
|
||||
|
||||
g_hash_table_insert(connection_table, g_strdup(id), self->connection);
|
||||
g_hash_table_insert (connection_table, g_strdup (id), self->connection);
|
||||
|
||||
G_UNLOCK(connection_table);
|
||||
G_UNLOCK (connection_table);
|
||||
}
|
||||
|
||||
static void connection_weak_ref_notify(gchar *id, ErDtlsConnection *connection)
|
||||
static void
|
||||
connection_weak_ref_notify (gchar * id, ErDtlsConnection * connection)
|
||||
{
|
||||
UNUSED(connection);
|
||||
UNUSED (connection);
|
||||
|
||||
G_LOCK(connection_table);
|
||||
g_hash_table_remove(connection_table, id);
|
||||
G_UNLOCK(connection_table);
|
||||
G_LOCK (connection_table);
|
||||
g_hash_table_remove (connection_table, id);
|
||||
G_UNLOCK (connection_table);
|
||||
|
||||
g_free(id);
|
||||
id = NULL;
|
||||
g_free (id);
|
||||
id = NULL;
|
||||
}
|
||||
|
|
|
@ -31,43 +31,43 @@
|
|||
|
||||
#include "gstdtlsdec.h"
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-dtls")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS("application/x-dtls")
|
||||
);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_enc_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_enc_debug);
|
||||
#define GST_CAT_DEFAULT er_dtls_enc_debug
|
||||
|
||||
#define gst_er_dtls_enc_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE(GstErDtlsEnc, gst_er_dtls_enc, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_enc_debug, "erdtlsenc", 0, "Ericsson DTLS Encoder"));
|
||||
G_DEFINE_TYPE_WITH_CODE (GstErDtlsEnc, gst_er_dtls_enc, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT (er_dtls_enc_debug, "erdtlsenc", 0,
|
||||
"Ericsson DTLS Encoder"));
|
||||
|
||||
enum {
|
||||
SIGNAL_ON_KEY_RECEIVED,
|
||||
NUM_SIGNALS
|
||||
enum
|
||||
{
|
||||
SIGNAL_ON_KEY_RECEIVED,
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[NUM_SIGNALS];
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_IS_CLIENT,
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_IS_CLIENT,
|
||||
|
||||
PROP_ENCODER_KEY,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTP_AUTH,
|
||||
NUM_PROPERTIES
|
||||
PROP_ENCODER_KEY,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTP_AUTH,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
@ -81,434 +81,471 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
|||
|
||||
#define INITIAL_QUEUE_SIZE 64
|
||||
|
||||
static void gst_er_dtls_enc_finalize(GObject *);
|
||||
static void gst_er_dtls_enc_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_enc_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_enc_finalize (GObject *);
|
||||
static void gst_er_dtls_enc_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_enc_get_property (GObject *, guint prop_id, GValue *,
|
||||
GParamSpec *);
|
||||
|
||||
static GstStateChangeReturn gst_er_dtls_enc_change_state(GstElement *, GstStateChange);
|
||||
static GstPad *gst_er_dtls_enc_request_new_pad(GstElement *, GstPadTemplate *, const gchar *name, const GstCaps *);
|
||||
static GstStateChangeReturn gst_er_dtls_enc_change_state (GstElement *,
|
||||
GstStateChange);
|
||||
static GstPad *gst_er_dtls_enc_request_new_pad (GstElement *, GstPadTemplate *,
|
||||
const gchar * name, const GstCaps *);
|
||||
|
||||
static gboolean src_activate_mode(GstPad *, GstObject *, GstPadMode, gboolean active);
|
||||
static void src_task_loop(GstPad *);
|
||||
static gboolean src_activate_mode (GstPad *, GstObject *, GstPadMode,
|
||||
gboolean active);
|
||||
static void src_task_loop (GstPad *);
|
||||
|
||||
static GstFlowReturn sink_chain(GstPad *, GstObject *, GstBuffer *);
|
||||
static GstFlowReturn sink_chain (GstPad *, GstObject *, GstBuffer *);
|
||||
|
||||
static void on_key_received(ErDtlsConnection *, gpointer key, guint cipher, guint auth, GstErDtlsEnc *);
|
||||
static void on_send_data(ErDtlsConnection *, gconstpointer data, gint length, GstErDtlsEnc *);
|
||||
static void on_key_received (ErDtlsConnection *, gpointer key, guint cipher,
|
||||
guint auth, GstErDtlsEnc *);
|
||||
static void on_send_data (ErDtlsConnection *, gconstpointer data, gint length,
|
||||
GstErDtlsEnc *);
|
||||
|
||||
static void gst_er_dtls_enc_class_init(GstErDtlsEncClass *klass)
|
||||
static void
|
||||
gst_er_dtls_enc_class_init (GstErDtlsEncClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_er_dtls_enc_finalize);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_er_dtls_enc_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_er_dtls_enc_get_property);
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_er_dtls_enc_finalize);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_enc_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_enc_get_property);
|
||||
|
||||
element_class->change_state = GST_DEBUG_FUNCPTR(gst_er_dtls_enc_change_state);
|
||||
element_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_er_dtls_enc_request_new_pad);
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_enc_change_state);
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_enc_request_new_pad);
|
||||
|
||||
signals[SIGNAL_ON_KEY_RECEIVED] =
|
||||
g_signal_new("on-key-received", G_TYPE_FROM_CLASS(klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
signals[SIGNAL_ON_KEY_RECEIVED] =
|
||||
g_signal_new ("on-key-received", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string ("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_IS_CLIENT] =
|
||||
g_param_spec_boolean("is-client",
|
||||
"Is client",
|
||||
"Set to true if the decoder should act as"
|
||||
"client and initiate the handshake",
|
||||
DEFAULT_IS_CLIENT,
|
||||
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_IS_CLIENT] =
|
||||
g_param_spec_boolean ("is-client",
|
||||
"Is client",
|
||||
"Set to true if the decoder should act as"
|
||||
"client and initiate the handshake",
|
||||
DEFAULT_IS_CLIENT,
|
||||
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_ENCODER_KEY] =
|
||||
g_param_spec_boxed("encoder-key",
|
||||
"Encoder key",
|
||||
"Master key that should be used by the SRTP encoder",
|
||||
GST_TYPE_BUFFER,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_ENCODER_KEY] =
|
||||
g_param_spec_boxed ("encoder-key",
|
||||
"Encoder key",
|
||||
"Master key that should be used by the SRTP encoder",
|
||||
GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_uint("srtp-cipher",
|
||||
"SRTP cipher",
|
||||
"The SRTP cipher selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpCipher.",
|
||||
0, ER_DTLS_SRTP_CIPHER_AES_128_ICM, DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_uint ("srtp-cipher",
|
||||
"SRTP cipher",
|
||||
"The SRTP cipher selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpCipher.",
|
||||
0, ER_DTLS_SRTP_CIPHER_AES_128_ICM, DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_uint("srtp-auth",
|
||||
"SRTP authentication",
|
||||
"The SRTP authentication selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpAuth.",
|
||||
0, ER_DTLS_SRTP_AUTH_HMAC_SHA1_80, DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_uint ("srtp-auth",
|
||||
"SRTP authentication",
|
||||
"The SRTP authentication selected in the DTLS handshake. "
|
||||
"The value will be set to an ErDtlsSrtpAuth.",
|
||||
0, ER_DTLS_SRTP_AUTH_HMAC_SHA1_80, DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&src_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata(element_class,
|
||||
"DTLS Encoder",
|
||||
"Encoder/Network/DTLS",
|
||||
"Encodes packets with DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"DTLS Encoder",
|
||||
"Encoder/Network/DTLS",
|
||||
"Encodes packets with DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
}
|
||||
|
||||
static void gst_er_dtls_enc_init(GstErDtlsEnc *self)
|
||||
static void
|
||||
gst_er_dtls_enc_init (GstErDtlsEnc * self)
|
||||
{
|
||||
self->connection_id = NULL;
|
||||
self->connection = NULL;
|
||||
self->connection_id = NULL;
|
||||
self->connection = NULL;
|
||||
|
||||
self->is_client = DEFAULT_IS_CLIENT;
|
||||
self->is_client = DEFAULT_IS_CLIENT;
|
||||
|
||||
self->encoder_key = NULL;
|
||||
self->srtp_cipher = DEFAULT_SRTP_CIPHER;
|
||||
self->srtp_auth = DEFAULT_SRTP_AUTH;
|
||||
|
||||
self->queue = g_ptr_array_sized_new (INITIAL_QUEUE_SIZE);
|
||||
|
||||
g_mutex_init (&self->queue_lock);
|
||||
g_cond_init (&self->queue_cond_add);
|
||||
|
||||
self->src = gst_pad_new_from_static_template (&src_template, "src");
|
||||
g_return_if_fail (self->src);
|
||||
|
||||
gst_pad_set_activatemode_function (self->src,
|
||||
GST_DEBUG_FUNCPTR (src_activate_mode));
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT (self), self->src);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_er_dtls_enc_finalize (GObject * object)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (object);
|
||||
|
||||
if (self->encoder_key) {
|
||||
gst_buffer_unref (self->encoder_key);
|
||||
self->encoder_key = NULL;
|
||||
self->srtp_cipher = DEFAULT_SRTP_CIPHER;
|
||||
self->srtp_auth = DEFAULT_SRTP_AUTH;
|
||||
}
|
||||
|
||||
self->queue = g_ptr_array_sized_new(INITIAL_QUEUE_SIZE);
|
||||
g_mutex_lock (&self->queue_lock);
|
||||
|
||||
g_mutex_init(&self->queue_lock);
|
||||
g_cond_init(&self->queue_cond_add);
|
||||
g_ptr_array_set_free_func (self->queue, (GDestroyNotify) gst_buffer_unref);
|
||||
g_ptr_array_unref (self->queue);
|
||||
self->queue = NULL;
|
||||
|
||||
self->src = gst_pad_new_from_static_template(&src_template, "src");
|
||||
g_return_if_fail(self->src);
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
|
||||
gst_pad_set_activatemode_function(self->src, GST_DEBUG_FUNCPTR(src_activate_mode));
|
||||
g_mutex_clear (&self->queue_lock);
|
||||
g_cond_clear (&self->queue_cond_add);
|
||||
|
||||
gst_element_add_pad(GST_ELEMENT(self), self->src);
|
||||
GST_LOG_OBJECT (self, "finalized");
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_enc_finalize(GObject *object)
|
||||
static void
|
||||
gst_er_dtls_enc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(object);
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (object);
|
||||
|
||||
if (self->encoder_key) {
|
||||
gst_buffer_unref(self->encoder_key);
|
||||
self->encoder_key = NULL;
|
||||
}
|
||||
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
|
||||
g_ptr_array_set_free_func(self->queue, (GDestroyNotify) gst_buffer_unref);
|
||||
g_ptr_array_unref(self->queue);
|
||||
self->queue = NULL;
|
||||
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
|
||||
g_mutex_clear(&self->queue_lock);
|
||||
g_cond_clear(&self->queue_cond_add);
|
||||
|
||||
GST_LOG_OBJECT(self, "finalized");
|
||||
|
||||
G_OBJECT_CLASS(parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_enc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
self->connection_id = g_value_dup_string(value);
|
||||
break;
|
||||
self->connection_id = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_IS_CLIENT:
|
||||
self->is_client = g_value_get_boolean(value);
|
||||
break;
|
||||
self->is_client = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_enc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(object);
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
g_value_set_string(value, self->connection_id);
|
||||
break;
|
||||
g_value_set_string (value, self->connection_id);
|
||||
break;
|
||||
case PROP_IS_CLIENT:
|
||||
g_value_set_boolean(value, self->is_client);
|
||||
break;
|
||||
g_value_set_boolean (value, self->is_client);
|
||||
break;
|
||||
case PROP_ENCODER_KEY:
|
||||
g_value_set_boxed(value, self->encoder_key);
|
||||
break;
|
||||
g_value_set_boxed (value, self->encoder_key);
|
||||
break;
|
||||
case PROP_SRTP_CIPHER:
|
||||
g_value_set_uint(value, self->srtp_cipher);
|
||||
break;
|
||||
g_value_set_uint (value, self->srtp_cipher);
|
||||
break;
|
||||
case PROP_SRTP_AUTH:
|
||||
g_value_set_uint(value, self->srtp_auth);
|
||||
break;
|
||||
g_value_set_uint (value, self->srtp_auth);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static GstStateChangeReturn gst_er_dtls_enc_change_state(GstElement *element, GstStateChange transition)
|
||||
static GstStateChangeReturn
|
||||
gst_er_dtls_enc_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(element);
|
||||
GstStateChangeReturn ret;
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (element);
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
switch (transition) {
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
if (self->connection_id) {
|
||||
self->connection = gst_er_dtls_dec_fetch_connection(self->connection_id);
|
||||
if (self->connection_id) {
|
||||
self->connection =
|
||||
gst_er_dtls_dec_fetch_connection (self->connection_id);
|
||||
|
||||
if (!self->connection) {
|
||||
GST_WARNING_OBJECT(self,
|
||||
"invalid connection id: '%s', connection not found or already in use",
|
||||
self->connection_id);
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
}
|
||||
|
||||
g_signal_connect_object(self->connection,
|
||||
"on-encoder-key", G_CALLBACK(on_key_received), self, 0);
|
||||
|
||||
er_dtls_connection_set_send_callback(self->connection,
|
||||
g_cclosure_new(G_CALLBACK(on_send_data), self, NULL));
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "trying to change state to ready without connection id");
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
if (!self->connection) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"invalid connection id: '%s', connection not found or already in use",
|
||||
self->connection_id);
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
g_signal_connect_object (self->connection,
|
||||
"on-encoder-key", G_CALLBACK (on_key_received), self, 0);
|
||||
|
||||
er_dtls_connection_set_send_callback (self->connection,
|
||||
g_cclosure_new (G_CALLBACK (on_send_data), self, NULL));
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"trying to change state to ready without connection id");
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
}
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
GST_DEBUG_OBJECT(self, "starting connection %s", self->connection_id);
|
||||
er_dtls_connection_start(self->connection, self->is_client);
|
||||
GST_DEBUG_OBJECT (self, "starting connection %s", self->connection_id);
|
||||
er_dtls_connection_start (self->connection, self->is_client);
|
||||
|
||||
gst_pad_set_active(self->src, TRUE);
|
||||
break;
|
||||
gst_pad_set_active (self->src, TRUE);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
GST_DEBUG_OBJECT(self, "stopping connection %s", self->connection_id);
|
||||
gst_pad_set_active(self->src, FALSE);
|
||||
GST_DEBUG_OBJECT (self, "stopping connection %s", self->connection_id);
|
||||
gst_pad_set_active (self->src, FALSE);
|
||||
|
||||
er_dtls_connection_stop(self->connection);
|
||||
break;
|
||||
er_dtls_connection_stop (self->connection);
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
GST_DEBUG_OBJECT(self, "closing connection %s", self->connection_id);
|
||||
GST_DEBUG_OBJECT (self, "closing connection %s", self->connection_id);
|
||||
|
||||
if (self->connection) {
|
||||
er_dtls_connection_close(self->connection);
|
||||
er_dtls_connection_set_send_callback(self->connection, NULL);
|
||||
g_object_unref(self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
break;
|
||||
if (self->connection) {
|
||||
er_dtls_connection_close (self->connection);
|
||||
er_dtls_connection_set_send_callback (self->connection, NULL);
|
||||
g_object_unref (self->connection);
|
||||
self->connection = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstPad *gst_er_dtls_enc_request_new_pad(GstElement *element,
|
||||
GstPadTemplate *templ, const gchar *name, const GstCaps *caps)
|
||||
static GstPad *
|
||||
gst_er_dtls_enc_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
|
||||
{
|
||||
GstPad *sink;
|
||||
gboolean ret;
|
||||
GstPad *sink;
|
||||
gboolean ret;
|
||||
|
||||
GST_DEBUG_OBJECT(element, "sink pad requested");
|
||||
GST_DEBUG_OBJECT (element, "sink pad requested");
|
||||
|
||||
g_return_val_if_fail(templ->direction == GST_PAD_SINK, NULL);
|
||||
g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
|
||||
|
||||
sink = gst_pad_new_from_template(templ, name);
|
||||
g_return_val_if_fail(sink, NULL);
|
||||
sink = gst_pad_new_from_template (templ, name);
|
||||
g_return_val_if_fail (sink, NULL);
|
||||
|
||||
if (caps) {
|
||||
g_object_set(sink, "caps", caps, NULL);
|
||||
}
|
||||
if (caps) {
|
||||
g_object_set (sink, "caps", caps, NULL);
|
||||
}
|
||||
|
||||
gst_pad_set_chain_function(sink, GST_DEBUG_FUNCPTR(sink_chain));
|
||||
gst_pad_set_chain_function (sink, GST_DEBUG_FUNCPTR (sink_chain));
|
||||
|
||||
ret = gst_pad_set_active(sink, TRUE);
|
||||
g_warn_if_fail(ret);
|
||||
ret = gst_pad_set_active (sink, TRUE);
|
||||
g_warn_if_fail (ret);
|
||||
|
||||
gst_element_add_pad(element, sink);
|
||||
gst_element_add_pad (element, sink);
|
||||
|
||||
return sink;
|
||||
return sink;
|
||||
}
|
||||
|
||||
static gboolean src_activate_mode(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean active)
|
||||
static gboolean
|
||||
src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
|
||||
gboolean active)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (parent);
|
||||
gboolean success = TRUE;
|
||||
g_return_val_if_fail(mode == GST_PAD_MODE_PUSH, FALSE);
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (parent);
|
||||
gboolean success = TRUE;
|
||||
g_return_val_if_fail (mode == GST_PAD_MODE_PUSH, FALSE);
|
||||
|
||||
if (active) {
|
||||
GST_DEBUG_OBJECT(self, "src pad activating in push mode");
|
||||
if (active) {
|
||||
GST_DEBUG_OBJECT (self, "src pad activating in push mode");
|
||||
|
||||
self->send_initial_events = TRUE;
|
||||
success = gst_pad_start_task(pad, (GstTaskFunction) src_task_loop, self->src, NULL);
|
||||
if (!success) {
|
||||
GST_WARNING_OBJECT(self, "failed to activate pad task");
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT(self, "deactivating src pad");
|
||||
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
GST_PAD_MODE(pad) = GST_PAD_MODE_NONE;
|
||||
g_cond_signal(&self->queue_cond_add);
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
success = gst_pad_stop_task(pad);
|
||||
if (!success) {
|
||||
GST_WARNING_OBJECT(self, "failed to deactivate pad task");
|
||||
}
|
||||
self->send_initial_events = TRUE;
|
||||
success =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) src_task_loop, self->src,
|
||||
NULL);
|
||||
if (!success) {
|
||||
GST_WARNING_OBJECT (self, "failed to activate pad task");
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self, "deactivating src pad");
|
||||
|
||||
return success;
|
||||
g_mutex_lock (&self->queue_lock);
|
||||
GST_PAD_MODE (pad) = GST_PAD_MODE_NONE;
|
||||
g_cond_signal (&self->queue_cond_add);
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
success = gst_pad_stop_task (pad);
|
||||
if (!success) {
|
||||
GST_WARNING_OBJECT (self, "failed to deactivate pad task");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void src_task_loop(GstPad *pad)
|
||||
static void
|
||||
src_task_loop (GstPad * pad)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(GST_PAD_PARENT(pad));
|
||||
GstFlowReturn ret;
|
||||
GstPad *peer;
|
||||
gboolean peer_is_active;
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (GST_PAD_PARENT (pad));
|
||||
GstFlowReturn ret;
|
||||
GstPad *peer;
|
||||
gboolean peer_is_active;
|
||||
|
||||
GST_TRACE_OBJECT(self, "src loop: acquiring lock");
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
GST_TRACE_OBJECT(self, "src loop: acquired lock");
|
||||
GST_TRACE_OBJECT (self, "src loop: acquiring lock");
|
||||
g_mutex_lock (&self->queue_lock);
|
||||
GST_TRACE_OBJECT (self, "src loop: acquired lock");
|
||||
|
||||
if (!gst_pad_is_active(pad)) {
|
||||
GST_LOG_OBJECT(self, "src task loop entered on inactive pad");
|
||||
GST_TRACE_OBJECT(self, "src loop: releasing lock");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
return;
|
||||
if (!gst_pad_is_active (pad)) {
|
||||
GST_LOG_OBJECT (self, "src task loop entered on inactive pad");
|
||||
GST_TRACE_OBJECT (self, "src loop: releasing lock");
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!self->queue->len) {
|
||||
GST_TRACE_OBJECT (self, "src loop: queue empty, waiting for add");
|
||||
g_cond_wait (&self->queue_cond_add, &self->queue_lock);
|
||||
GST_TRACE_OBJECT (self, "src loop: add signaled");
|
||||
|
||||
if (!gst_pad_is_active (pad)) {
|
||||
GST_LOG_OBJECT (self, "pad inactive, task returning");
|
||||
GST_TRACE_OBJECT (self, "src loop: releasing lock");
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GST_TRACE_OBJECT (self, "src loop: queue has element");
|
||||
|
||||
while (!self->queue->len) {
|
||||
GST_TRACE_OBJECT(self, "src loop: queue empty, waiting for add");
|
||||
g_cond_wait(&self->queue_cond_add, &self->queue_lock);
|
||||
GST_TRACE_OBJECT(self, "src loop: add signaled");
|
||||
peer = gst_pad_get_peer (pad);
|
||||
peer_is_active = gst_pad_is_active (peer);
|
||||
gst_object_unref (peer);
|
||||
|
||||
if (!gst_pad_is_active(pad)) {
|
||||
GST_LOG_OBJECT(self, "pad inactive, task returning");
|
||||
GST_TRACE_OBJECT(self, "src loop: releasing lock");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GST_TRACE_OBJECT(self, "src loop: queue has element");
|
||||
|
||||
peer = gst_pad_get_peer(pad);
|
||||
peer_is_active = gst_pad_is_active(peer);
|
||||
gst_object_unref(peer);
|
||||
|
||||
if (peer_is_active) {
|
||||
GstBuffer *buffer;
|
||||
gboolean start_connection_timeout = FALSE;
|
||||
|
||||
if (self->send_initial_events) {
|
||||
GstSegment segment;
|
||||
gchar s_id[32];
|
||||
GstCaps *caps;
|
||||
|
||||
g_snprintf (s_id, sizeof (s_id), "erdtlsenc-%08x", g_random_int ());
|
||||
gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
|
||||
caps = gst_caps_new_empty_simple ("application/x-dtls");
|
||||
gst_pad_push_event (self->src, gst_event_new_caps (caps));
|
||||
gst_caps_unref (caps);
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event (self->src, gst_event_new_segment (&segment));
|
||||
self->send_initial_events = FALSE;
|
||||
start_connection_timeout = TRUE;
|
||||
}
|
||||
|
||||
buffer = g_ptr_array_remove_index(self->queue, 0);
|
||||
|
||||
GST_TRACE_OBJECT(self, "src loop: releasing lock");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
|
||||
ret = gst_pad_push(self->src, buffer);
|
||||
if (start_connection_timeout)
|
||||
er_dtls_connection_start_timeout (self->connection);
|
||||
|
||||
if (G_UNLIKELY(ret != GST_FLOW_OK)) {
|
||||
GST_WARNING_OBJECT(self, "failed to push buffer on src pad: %s", gst_flow_get_name(ret));
|
||||
}
|
||||
} else {
|
||||
g_warn_if_reached();
|
||||
GST_TRACE_OBJECT(self, "src loop: releasing lock");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buffer)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC(parent);
|
||||
GstMapInfo map_info;
|
||||
gint ret;
|
||||
|
||||
gst_buffer_map(buffer, &map_info, GST_MAP_READ);
|
||||
|
||||
if (map_info.size) {
|
||||
ret = er_dtls_connection_send(self->connection, map_info.data, map_info.size);
|
||||
if (ret != map_info.size) {
|
||||
GST_WARNING_OBJECT(self, "error sending data: %d B were written, expected value was %zd B",
|
||||
ret, map_info.size);
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap(buffer, &map_info);
|
||||
|
||||
gst_buffer_unref(buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void on_key_received(ErDtlsConnection *connection, gpointer key, guint cipher, guint auth, GstErDtlsEnc *self)
|
||||
{
|
||||
gpointer key_dup;
|
||||
gchar *key_str;
|
||||
|
||||
g_return_if_fail(GST_IS_ER_DTLS_ENC(self));
|
||||
g_return_if_fail(ER_IS_DTLS_CONNECTION(connection));
|
||||
|
||||
self->srtp_cipher = cipher;
|
||||
self->srtp_auth = auth;
|
||||
|
||||
key_dup = g_memdup(key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
self->encoder_key = gst_buffer_new_wrapped(key_dup, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
|
||||
key_str = g_base64_encode(key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
GST_INFO_OBJECT(self, "received key: %s", key_str);
|
||||
g_free(key_str);
|
||||
|
||||
g_signal_emit(self, signals[SIGNAL_ON_KEY_RECEIVED], 0);
|
||||
}
|
||||
|
||||
static void on_send_data(ErDtlsConnection *connection, gconstpointer data, gint length, GstErDtlsEnc *self)
|
||||
{
|
||||
if (peer_is_active) {
|
||||
GstBuffer *buffer;
|
||||
gboolean start_connection_timeout = FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT(self, "sending data from %s with length %d", self->connection_id, length);
|
||||
if (self->send_initial_events) {
|
||||
GstSegment segment;
|
||||
gchar s_id[32];
|
||||
GstCaps *caps;
|
||||
|
||||
buffer = gst_buffer_new_wrapped(g_memdup(data, length), length);
|
||||
g_snprintf (s_id, sizeof (s_id), "erdtlsenc-%08x", g_random_int ());
|
||||
gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
|
||||
caps = gst_caps_new_empty_simple ("application/x-dtls");
|
||||
gst_pad_push_event (self->src, gst_event_new_caps (caps));
|
||||
gst_caps_unref (caps);
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event (self->src, gst_event_new_segment (&segment));
|
||||
self->send_initial_events = FALSE;
|
||||
start_connection_timeout = TRUE;
|
||||
}
|
||||
|
||||
GST_TRACE_OBJECT(self, "send data: acquiring lock");
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
GST_TRACE_OBJECT(self, "send data: acquired lock");
|
||||
buffer = g_ptr_array_remove_index (self->queue, 0);
|
||||
|
||||
g_ptr_array_add(self->queue, buffer);
|
||||
GST_TRACE_OBJECT (self, "src loop: releasing lock");
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
|
||||
GST_TRACE_OBJECT(self, "send data: signaling add");
|
||||
g_cond_signal(&self->queue_cond_add);
|
||||
ret = gst_pad_push (self->src, buffer);
|
||||
if (start_connection_timeout)
|
||||
er_dtls_connection_start_timeout (self->connection);
|
||||
|
||||
GST_TRACE_OBJECT(self, "send data: releasing lock");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
||||
GST_WARNING_OBJECT (self, "failed to push buffer on src pad: %s",
|
||||
gst_flow_get_name (ret));
|
||||
}
|
||||
} else {
|
||||
g_warn_if_reached ();
|
||||
GST_TRACE_OBJECT (self, "src loop: releasing lock");
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstErDtlsEnc *self = GST_ER_DTLS_ENC (parent);
|
||||
GstMapInfo map_info;
|
||||
gint ret;
|
||||
|
||||
gst_buffer_map (buffer, &map_info, GST_MAP_READ);
|
||||
|
||||
if (map_info.size) {
|
||||
ret =
|
||||
er_dtls_connection_send (self->connection, map_info.data,
|
||||
map_info.size);
|
||||
if (ret != map_info.size) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"error sending data: %d B were written, expected value was %zd B",
|
||||
ret, map_info.size);
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buffer, &map_info);
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_received (ErDtlsConnection * connection, gpointer key, guint cipher,
|
||||
guint auth, GstErDtlsEnc * self)
|
||||
{
|
||||
gpointer key_dup;
|
||||
gchar *key_str;
|
||||
|
||||
g_return_if_fail (GST_IS_ER_DTLS_ENC (self));
|
||||
g_return_if_fail (ER_IS_DTLS_CONNECTION (connection));
|
||||
|
||||
self->srtp_cipher = cipher;
|
||||
self->srtp_auth = auth;
|
||||
|
||||
key_dup = g_memdup (key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
self->encoder_key =
|
||||
gst_buffer_new_wrapped (key_dup, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
|
||||
key_str = g_base64_encode (key, ER_DTLS_SRTP_MASTER_KEY_LENGTH);
|
||||
GST_INFO_OBJECT (self, "received key: %s", key_str);
|
||||
g_free (key_str);
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_ON_KEY_RECEIVED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_send_data (ErDtlsConnection * connection, gconstpointer data, gint length,
|
||||
GstErDtlsEnc * self)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "sending data from %s with length %d",
|
||||
self->connection_id, length);
|
||||
|
||||
buffer = gst_buffer_new_wrapped (g_memdup (data, length), length);
|
||||
|
||||
GST_TRACE_OBJECT (self, "send data: acquiring lock");
|
||||
g_mutex_lock (&self->queue_lock);
|
||||
GST_TRACE_OBJECT (self, "send data: acquired lock");
|
||||
|
||||
g_ptr_array_add (self->queue, buffer);
|
||||
|
||||
GST_TRACE_OBJECT (self, "send data: signaling add");
|
||||
g_cond_signal (&self->queue_cond_add);
|
||||
|
||||
GST_TRACE_OBJECT (self, "send data: releasing lock");
|
||||
g_mutex_unlock (&self->queue_lock);
|
||||
}
|
||||
|
|
|
@ -31,17 +31,18 @@
|
|||
#include "gstdtlssrtpbin.h"
|
||||
|
||||
#define gst_er_dtls_srtp_bin_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE(GstErDtlsSrtpBin, gst_er_dtls_srtp_bin, GST_TYPE_BIN);
|
||||
G_DEFINE_ABSTRACT_TYPE (GstErDtlsSrtpBin, gst_er_dtls_srtp_bin, GST_TYPE_BIN);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_KEY,
|
||||
PROP_SRTP_AUTH,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTCP_AUTH,
|
||||
PROP_SRTCP_CIPHER,
|
||||
NUM_PROPERTIES
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CONNECTION_ID,
|
||||
PROP_KEY,
|
||||
PROP_SRTP_AUTH,
|
||||
PROP_SRTP_CIPHER,
|
||||
PROP_SRTCP_AUTH,
|
||||
PROP_SRTCP_CIPHER,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
@ -53,179 +54,189 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
|||
#define DEFAULT_SRTCP_AUTH NULL
|
||||
#define DEFAULT_SRTCP_CIPHER NULL
|
||||
|
||||
static void gst_er_dtls_srtp_bin_finalize(GObject *);
|
||||
static void gst_er_dtls_srtp_bin_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_bin_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_bin_finalize (GObject *);
|
||||
static void gst_er_dtls_srtp_bin_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_bin_get_property (GObject *, guint prop_id,
|
||||
GValue *, GParamSpec *);
|
||||
|
||||
static void gst_er_dtls_srtp_bin_class_init(GstErDtlsSrtpBinClass *klass)
|
||||
static void
|
||||
gst_er_dtls_srtp_bin_class_init (GstErDtlsSrtpBinClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_bin_finalize);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_bin_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_bin_get_property);
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_bin_finalize);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_bin_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_bin_get_property);
|
||||
|
||||
klass->remove_dtls_element = NULL;
|
||||
klass->remove_dtls_element = NULL;
|
||||
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_CONNECTION_ID] =
|
||||
g_param_spec_string ("connection-id",
|
||||
"Connection id",
|
||||
"Every encoder/decoder pair should have the same, unique, connection-id",
|
||||
DEFAULT_CONNECTION_ID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_KEY] =
|
||||
g_param_spec_boxed("key",
|
||||
"Key",
|
||||
"SRTP master key, if this property is set, DTLS will be disabled",
|
||||
GST_TYPE_BUFFER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_KEY] =
|
||||
g_param_spec_boxed ("key",
|
||||
"Key",
|
||||
"SRTP master key, if this property is set, DTLS will be disabled",
|
||||
GST_TYPE_BUFFER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_string("srtp-cipher",
|
||||
"SRTP Cipher",
|
||||
"SRTP cipher name, should be 'null' or 'aes-128-icm', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_CIPHER] =
|
||||
g_param_spec_string ("srtp-cipher",
|
||||
"SRTP Cipher",
|
||||
"SRTP cipher name, should be 'null' or 'aes-128-icm', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTP_CIPHER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTCP_CIPHER] =
|
||||
g_param_spec_string("srtcp-cipher",
|
||||
"SRTCP Cipher",
|
||||
"SRTCP cipher name, should be 'null' or 'aes-128-icm', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTCP_CIPHER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTCP_CIPHER] =
|
||||
g_param_spec_string ("srtcp-cipher",
|
||||
"SRTCP Cipher",
|
||||
"SRTCP cipher name, should be 'null' or 'aes-128-icm', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTCP_CIPHER,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_string("srtp-auth",
|
||||
"SRTP Auth",
|
||||
"SRTP auth name, should be 'null', 'hmac-sha1-32' or 'hmac-sha1-80', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTP_AUTH] =
|
||||
g_param_spec_string ("srtp-auth",
|
||||
"SRTP Auth",
|
||||
"SRTP auth name, should be 'null', 'hmac-sha1-32' or 'hmac-sha1-80', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTP_AUTH,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SRTCP_AUTH] =
|
||||
g_param_spec_string("srtcp-auth",
|
||||
"SRTCP Auth",
|
||||
"SRTCP auth name, should be 'null', 'hmac-sha1-32' or 'hmac-sha1-80', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTCP_AUTH,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_SRTCP_AUTH] =
|
||||
g_param_spec_string ("srtcp-auth",
|
||||
"SRTCP Auth",
|
||||
"SRTCP auth name, should be 'null', 'hmac-sha1-32' or 'hmac-sha1-80', "
|
||||
"if this property is set, DTLS will be disabled",
|
||||
DEFAULT_SRTCP_AUTH,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_bin_init(GstErDtlsSrtpBin *self)
|
||||
static void
|
||||
gst_er_dtls_srtp_bin_init (GstErDtlsSrtpBin * self)
|
||||
{
|
||||
self->key = NULL;
|
||||
self->key_is_set = FALSE;
|
||||
self->srtp_auth = NULL;
|
||||
self->srtp_cipher = NULL;
|
||||
self->srtcp_auth = NULL;
|
||||
self->srtcp_cipher = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_er_dtls_srtp_bin_finalize (GObject * object)
|
||||
{
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN (object);
|
||||
|
||||
if (self->key) {
|
||||
gst_buffer_unref (self->key);
|
||||
self->key = NULL;
|
||||
self->key_is_set = FALSE;
|
||||
self->srtp_auth = NULL;
|
||||
self->srtp_cipher = NULL;
|
||||
self->srtcp_auth = NULL;
|
||||
self->srtcp_cipher = NULL;
|
||||
}
|
||||
g_free (self->srtp_auth);
|
||||
self->srtp_auth = NULL;
|
||||
g_free (self->srtp_cipher);
|
||||
self->srtp_cipher = NULL;
|
||||
g_free (self->srtcp_auth);
|
||||
self->srtcp_auth = NULL;
|
||||
g_free (self->srtcp_cipher);
|
||||
self->srtcp_cipher = NULL;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_bin_finalize(GObject *object)
|
||||
static void
|
||||
gst_er_dtls_srtp_bin_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN(object);
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN (object);
|
||||
GstErDtlsSrtpBinClass *klass = GST_ER_DTLS_SRTP_BIN_GET_CLASS (self);
|
||||
|
||||
if (self->key) {
|
||||
gst_buffer_unref(self->key);
|
||||
self->key = NULL;
|
||||
}
|
||||
g_free(self->srtp_auth);
|
||||
self->srtp_auth = NULL;
|
||||
g_free(self->srtp_cipher);
|
||||
self->srtp_cipher = NULL;
|
||||
g_free(self->srtcp_auth);
|
||||
self->srtcp_auth = NULL;
|
||||
g_free(self->srtcp_cipher);
|
||||
self->srtcp_cipher = NULL;
|
||||
|
||||
G_OBJECT_CLASS(parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_bin_set_property(GObject *object,
|
||||
guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN(object);
|
||||
GstErDtlsSrtpBinClass *klass = GST_ER_DTLS_SRTP_BIN_GET_CLASS(self);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
if (self->dtls_element) {
|
||||
g_object_set_property(G_OBJECT(self->dtls_element), "connection-id", value);
|
||||
} else {
|
||||
g_warning("tried to set connection-id after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->dtls_element) {
|
||||
g_object_set_property (G_OBJECT (self->dtls_element), "connection-id",
|
||||
value);
|
||||
} else {
|
||||
g_warning ("tried to set connection-id after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
case PROP_KEY:
|
||||
if (self->key) {
|
||||
gst_buffer_unref(self->key);
|
||||
}
|
||||
self->key = g_value_dup_boxed(value);
|
||||
self->key_is_set = TRUE;
|
||||
klass->remove_dtls_element(self);
|
||||
break;
|
||||
if (self->key) {
|
||||
gst_buffer_unref (self->key);
|
||||
}
|
||||
self->key = g_value_dup_boxed (value);
|
||||
self->key_is_set = TRUE;
|
||||
klass->remove_dtls_element (self);
|
||||
break;
|
||||
case PROP_SRTP_AUTH:
|
||||
g_free(self->srtp_auth);
|
||||
self->srtp_auth = g_value_dup_string(value);
|
||||
klass->remove_dtls_element(self);
|
||||
break;
|
||||
g_free (self->srtp_auth);
|
||||
self->srtp_auth = g_value_dup_string (value);
|
||||
klass->remove_dtls_element (self);
|
||||
break;
|
||||
case PROP_SRTP_CIPHER:
|
||||
g_free(self->srtp_cipher);
|
||||
self->srtp_cipher = g_value_dup_string(value);
|
||||
klass->remove_dtls_element(self);
|
||||
break;
|
||||
g_free (self->srtp_cipher);
|
||||
self->srtp_cipher = g_value_dup_string (value);
|
||||
klass->remove_dtls_element (self);
|
||||
break;
|
||||
case PROP_SRTCP_AUTH:
|
||||
g_free(self->srtcp_auth);
|
||||
self->srtcp_auth = g_value_dup_string(value);
|
||||
klass->remove_dtls_element(self);
|
||||
break;
|
||||
g_free (self->srtcp_auth);
|
||||
self->srtcp_auth = g_value_dup_string (value);
|
||||
klass->remove_dtls_element (self);
|
||||
break;
|
||||
case PROP_SRTCP_CIPHER:
|
||||
g_free(self->srtcp_cipher);
|
||||
self->srtcp_cipher = g_value_dup_string(value);
|
||||
klass->remove_dtls_element(self);
|
||||
break;
|
||||
g_free (self->srtcp_cipher);
|
||||
self->srtcp_cipher = g_value_dup_string (value);
|
||||
klass->remove_dtls_element (self);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_bin_get_property(GObject *object,
|
||||
guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_srtp_bin_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN(object);
|
||||
GstErDtlsSrtpBin *self = GST_ER_DTLS_SRTP_BIN (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION_ID:
|
||||
if (self->dtls_element) {
|
||||
g_object_get_property(G_OBJECT(self->dtls_element), "connection-id", value);
|
||||
} else {
|
||||
g_warning("tried to get connection-id after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->dtls_element) {
|
||||
g_object_get_property (G_OBJECT (self->dtls_element), "connection-id",
|
||||
value);
|
||||
} else {
|
||||
g_warning ("tried to get connection-id after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
case PROP_KEY:
|
||||
if (self->key) {
|
||||
g_value_set_boxed(value, self->key);
|
||||
}
|
||||
break;
|
||||
if (self->key) {
|
||||
g_value_set_boxed (value, self->key);
|
||||
}
|
||||
break;
|
||||
case PROP_SRTP_AUTH:
|
||||
g_value_set_string(value, self->srtp_auth);
|
||||
break;
|
||||
g_value_set_string (value, self->srtp_auth);
|
||||
break;
|
||||
case PROP_SRTP_CIPHER:
|
||||
g_value_set_string(value, self->srtp_cipher);
|
||||
break;
|
||||
g_value_set_string (value, self->srtp_cipher);
|
||||
break;
|
||||
case PROP_SRTCP_AUTH:
|
||||
g_value_set_string(value, self->srtcp_auth);
|
||||
break;
|
||||
g_value_set_string (value, self->srtcp_auth);
|
||||
break;
|
||||
case PROP_SRTCP_CIPHER:
|
||||
g_value_set_string(value, self->srtcp_cipher);
|
||||
break;
|
||||
g_value_set_string (value, self->srtcp_cipher);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,41 +31,40 @@
|
|||
|
||||
#include "gstdtlsconnection.h"
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate rtp_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("rtp_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS("application/x-rtp;application/x-rtcp")
|
||||
GST_STATIC_PAD_TEMPLATE ("rtp_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp;application/x-rtcp")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate data_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("data_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GST_STATIC_PAD_TEMPLATE ("data_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_srtp_dec_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_srtp_dec_debug);
|
||||
#define GST_CAT_DEFAULT er_dtls_srtp_dec_debug
|
||||
|
||||
#define gst_er_dtls_srtp_dec_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE(GstErDtlsSrtpDec, gst_er_dtls_srtp_dec, GST_TYPE_ER_DTLS_SRTP_BIN,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_srtp_dec_debug, "erdtlssrtpdec", 0, "Ericsson DTLS Decoder"));
|
||||
G_DEFINE_TYPE_WITH_CODE (GstErDtlsSrtpDec, gst_er_dtls_srtp_dec,
|
||||
GST_TYPE_ER_DTLS_SRTP_BIN, GST_DEBUG_CATEGORY_INIT (er_dtls_srtp_dec_debug,
|
||||
"erdtlssrtpdec", 0, "Ericsson DTLS Decoder"));
|
||||
|
||||
#define UNUSED(param) while (0) { (void)(param); }
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PEM,
|
||||
PROP_PEER_PEM,
|
||||
NUM_PROPERTIES
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_PEM,
|
||||
PROP_PEER_PEM,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
@ -73,71 +72,82 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
|||
#define DEFAULT_PEM NULL
|
||||
#define DEFAULT_PEER_PEM NULL
|
||||
|
||||
static void gst_er_dtls_srtp_dec_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_dec_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_dec_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_dec_get_property (GObject *, guint prop_id,
|
||||
GValue *, GParamSpec *);
|
||||
|
||||
static GstPad *gst_er_dtls_srtp_dec_request_new_pad(GstElement *, GstPadTemplate *, const gchar *name, const GstCaps *);
|
||||
static GstCaps *on_decoder_request_key(GstElement *srtp_decoder, guint ssrc, GstErDtlsSrtpBin *);
|
||||
static void on_peer_pem(GstElement *srtp_decoder, GParamSpec *pspec, GstErDtlsSrtpDec *self);
|
||||
static GstPad *gst_er_dtls_srtp_dec_request_new_pad (GstElement *,
|
||||
GstPadTemplate *, const gchar * name, const GstCaps *);
|
||||
static GstCaps *on_decoder_request_key (GstElement * srtp_decoder, guint ssrc,
|
||||
GstErDtlsSrtpBin *);
|
||||
static void on_peer_pem (GstElement * srtp_decoder, GParamSpec * pspec,
|
||||
GstErDtlsSrtpDec * self);
|
||||
|
||||
static void gst_er_dtls_srtp_dec_remove_dtls_element(GstErDtlsSrtpBin *);
|
||||
static GstPadProbeReturn remove_dtls_decoder_probe_callback(GstPad *, GstPadProbeInfo *, GstElement *);
|
||||
static void gst_er_dtls_srtp_dec_remove_dtls_element (GstErDtlsSrtpBin *);
|
||||
static GstPadProbeReturn remove_dtls_decoder_probe_callback (GstPad *,
|
||||
GstPadProbeInfo *, GstElement *);
|
||||
|
||||
static GstPadProbeReturn drop_funnel_rtcp_caps(GstPad *, GstPadProbeInfo *, gpointer);
|
||||
static GstPadProbeReturn drop_funnel_rtcp_caps (GstPad *, GstPadProbeInfo *,
|
||||
gpointer);
|
||||
|
||||
static void gst_er_dtls_srtp_dec_class_init(GstErDtlsSrtpDecClass *klass)
|
||||
static void
|
||||
gst_er_dtls_srtp_dec_class_init (GstErDtlsSrtpDecClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GstErDtlsSrtpBinClass *dtls_srtp_bin_class;
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GstErDtlsSrtpBinClass *dtls_srtp_bin_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
dtls_srtp_bin_class = (GstErDtlsSrtpBinClass *) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
dtls_srtp_bin_class = (GstErDtlsSrtpBinClass *) klass;
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_dec_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_dec_get_property);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_dec_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_dec_get_property);
|
||||
|
||||
element_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_dec_request_new_pad);
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_dec_request_new_pad);
|
||||
|
||||
dtls_srtp_bin_class->remove_dtls_element = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_dec_remove_dtls_element);
|
||||
dtls_srtp_bin_class->remove_dtls_element =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_dec_remove_dtls_element);
|
||||
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string("pem",
|
||||
"PEM string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_PEM] =
|
||||
g_param_spec_string ("pem",
|
||||
"PEM string",
|
||||
"A string containing a X509 certificate and RSA private key in PEM format",
|
||||
DEFAULT_PEM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_PEER_PEM] =
|
||||
g_param_spec_string("peer-pem",
|
||||
"Peer PEM string",
|
||||
"The X509 certificate received in the DTLS handshake, in PEM format",
|
||||
DEFAULT_PEER_PEM,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_PEER_PEM] =
|
||||
g_param_spec_string ("peer-pem",
|
||||
"Peer PEM string",
|
||||
"The X509 certificate received in the DTLS handshake, in PEM format",
|
||||
DEFAULT_PEER_PEM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&sink_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&rtp_src_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&data_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&rtp_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&data_src_template));
|
||||
|
||||
gst_element_class_set_static_metadata(element_class,
|
||||
"DTLS-SRTP Decoder",
|
||||
"Decoder/Network/DTLS/SRTP",
|
||||
"Decodes SRTP packets with a key received from DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"DTLS-SRTP Decoder",
|
||||
"Decoder/Network/DTLS/SRTP",
|
||||
"Decodes SRTP packets with a key received from DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_dec_init(GstErDtlsSrtpDec *self)
|
||||
static void
|
||||
gst_er_dtls_srtp_dec_init (GstErDtlsSrtpDec * self)
|
||||
{
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS(GST_ELEMENT(self));
|
||||
GstPadTemplate *templ;
|
||||
GstPad *target_pad, *ghost_pad, *pad;
|
||||
gboolean ret;
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (self));
|
||||
GstPadTemplate *templ;
|
||||
GstPad *target_pad, *ghost_pad, *pad;
|
||||
gboolean ret;
|
||||
|
||||
/*
|
||||
+--------------------+
|
||||
|
@ -151,303 +161,319 @@ static void gst_er_dtls_srtp_dec_init(GstErDtlsSrtpDec *self)
|
|||
+-----------+ +-----------+
|
||||
*/
|
||||
|
||||
self->srtp_dec = gst_element_factory_make("srtpdec", "srtp-decoder");
|
||||
if (!self->srtp_dec) {
|
||||
GST_ERROR_OBJECT(self, "failed to create srtp_dec, is the srtp plugin registered?");
|
||||
return;
|
||||
}
|
||||
self->dtls_srtp_demux = gst_element_factory_make("erdtlssrtpdemux", "dtls-srtp-demux");
|
||||
if (!self->dtls_srtp_demux) {
|
||||
GST_ERROR_OBJECT(self, "failed to create dtls_srtp_demux");
|
||||
return;
|
||||
}
|
||||
self->bin.dtls_element = gst_element_factory_make("erdtlsdec", "dtls-decoder");
|
||||
if (!self->bin.dtls_element) {
|
||||
GST_ERROR_OBJECT(self, "failed to create dtls_dec");
|
||||
return;
|
||||
}
|
||||
self->funnel = gst_element_factory_make("funnel", "funnel");
|
||||
if (!self->funnel) {
|
||||
GST_ERROR_OBJECT(self, "failed to create funnel");
|
||||
return;
|
||||
}
|
||||
self->srtp_dec = gst_element_factory_make ("srtpdec", "srtp-decoder");
|
||||
if (!self->srtp_dec) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"failed to create srtp_dec, is the srtp plugin registered?");
|
||||
return;
|
||||
}
|
||||
self->dtls_srtp_demux =
|
||||
gst_element_factory_make ("erdtlssrtpdemux", "dtls-srtp-demux");
|
||||
if (!self->dtls_srtp_demux) {
|
||||
GST_ERROR_OBJECT (self, "failed to create dtls_srtp_demux");
|
||||
return;
|
||||
}
|
||||
self->bin.dtls_element =
|
||||
gst_element_factory_make ("erdtlsdec", "dtls-decoder");
|
||||
if (!self->bin.dtls_element) {
|
||||
GST_ERROR_OBJECT (self, "failed to create dtls_dec");
|
||||
return;
|
||||
}
|
||||
self->funnel = gst_element_factory_make ("funnel", "funnel");
|
||||
if (!self->funnel) {
|
||||
GST_ERROR_OBJECT (self, "failed to create funnel");
|
||||
return;
|
||||
}
|
||||
|
||||
gst_bin_add_many(GST_BIN(self),
|
||||
self->dtls_srtp_demux,
|
||||
self->bin.dtls_element,
|
||||
self->srtp_dec,
|
||||
self->funnel,
|
||||
NULL);
|
||||
gst_bin_add_many (GST_BIN (self),
|
||||
self->dtls_srtp_demux,
|
||||
self->bin.dtls_element, self->srtp_dec, self->funnel, NULL);
|
||||
|
||||
ret = gst_element_link_pads(self->dtls_srtp_demux, "dtls_src", self->bin.dtls_element, NULL);
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_link_pads(self->dtls_srtp_demux, "rtp_src", self->srtp_dec, "rtp_sink");
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_link_pads(self->srtp_dec, "rtp_src", self->funnel, "sink_0");
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_link_pads(self->srtp_dec, "rtcp_src", self->funnel, "sink_1");
|
||||
g_return_if_fail(ret);
|
||||
ret =
|
||||
gst_element_link_pads (self->dtls_srtp_demux, "dtls_src",
|
||||
self->bin.dtls_element, NULL);
|
||||
g_return_if_fail (ret);
|
||||
ret =
|
||||
gst_element_link_pads (self->dtls_srtp_demux, "rtp_src", self->srtp_dec,
|
||||
"rtp_sink");
|
||||
g_return_if_fail (ret);
|
||||
ret =
|
||||
gst_element_link_pads (self->srtp_dec, "rtp_src", self->funnel, "sink_0");
|
||||
g_return_if_fail (ret);
|
||||
ret =
|
||||
gst_element_link_pads (self->srtp_dec, "rtcp_src", self->funnel,
|
||||
"sink_1");
|
||||
g_return_if_fail (ret);
|
||||
|
||||
pad = gst_element_get_static_pad(self->funnel, "sink_1");
|
||||
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, drop_funnel_rtcp_caps, NULL, NULL);
|
||||
gst_object_unref(pad);
|
||||
pad = gst_element_get_static_pad (self->funnel, "sink_1");
|
||||
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
|
||||
drop_funnel_rtcp_caps, NULL, NULL);
|
||||
gst_object_unref (pad);
|
||||
|
||||
templ = gst_element_class_get_pad_template(klass, "rtp_src");
|
||||
target_pad = gst_element_get_static_pad(self->funnel, "src");
|
||||
ghost_pad = gst_ghost_pad_new_from_template("rtp_src", target_pad, templ);
|
||||
gst_object_unref(target_pad);
|
||||
g_return_if_fail(ghost_pad);
|
||||
templ = gst_element_class_get_pad_template (klass, "rtp_src");
|
||||
target_pad = gst_element_get_static_pad (self->funnel, "src");
|
||||
ghost_pad = gst_ghost_pad_new_from_template ("rtp_src", target_pad, templ);
|
||||
gst_object_unref (target_pad);
|
||||
g_return_if_fail (ghost_pad);
|
||||
|
||||
ret = gst_element_add_pad(GST_ELEMENT(self), ghost_pad);
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_add_pad (GST_ELEMENT (self), ghost_pad);
|
||||
g_return_if_fail (ret);
|
||||
|
||||
templ = gst_element_class_get_pad_template(klass, "sink");
|
||||
target_pad = gst_element_get_static_pad(self->dtls_srtp_demux, "sink");
|
||||
ghost_pad = gst_ghost_pad_new_from_template("sink", target_pad, templ);
|
||||
gst_object_unref(target_pad);
|
||||
g_return_if_fail(ghost_pad);
|
||||
templ = gst_element_class_get_pad_template (klass, "sink");
|
||||
target_pad = gst_element_get_static_pad (self->dtls_srtp_demux, "sink");
|
||||
ghost_pad = gst_ghost_pad_new_from_template ("sink", target_pad, templ);
|
||||
gst_object_unref (target_pad);
|
||||
g_return_if_fail (ghost_pad);
|
||||
|
||||
ret = gst_element_add_pad(GST_ELEMENT(self), ghost_pad);
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_add_pad (GST_ELEMENT (self), ghost_pad);
|
||||
g_return_if_fail (ret);
|
||||
|
||||
g_signal_connect(self->srtp_dec, "request-key", G_CALLBACK(on_decoder_request_key), self);
|
||||
g_signal_connect(self->bin.dtls_element, "notify::peer-pem", G_CALLBACK(on_peer_pem), self);
|
||||
g_signal_connect (self->srtp_dec, "request-key",
|
||||
G_CALLBACK (on_decoder_request_key), self);
|
||||
g_signal_connect (self->bin.dtls_element, "notify::peer-pem",
|
||||
G_CALLBACK (on_peer_pem), self);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_dec_set_property(GObject *object,
|
||||
guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_srtp_dec_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC(object);
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_PEM:
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_set_property(G_OBJECT(self->bin.dtls_element), "pem", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "tried to set pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_set_property (G_OBJECT (self->bin.dtls_element), "pem", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self, "tried to set pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_dec_get_property(GObject *object,
|
||||
guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_srtp_dec_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC(object);
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_PEM:
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property(G_OBJECT(self->bin.dtls_element), "pem", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "tried to get pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property (G_OBJECT (self->bin.dtls_element), "pem", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self, "tried to get pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
case PROP_PEER_PEM:
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property(G_OBJECT(self->bin.dtls_element), "peer-pem", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "tried to get peer-pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property (G_OBJECT (self->bin.dtls_element), "peer-pem",
|
||||
value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self, "tried to get peer-pem after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static GstPad *gst_er_dtls_srtp_dec_request_new_pad(GstElement *element,
|
||||
GstPadTemplate *templ, const gchar *name, const GstCaps *caps)
|
||||
static GstPad *
|
||||
gst_er_dtls_srtp_dec_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
|
||||
{
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC(element);
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS(element);
|
||||
GstPad *ghost_pad = NULL;
|
||||
gboolean ret;
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC (element);
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
||||
GstPad *ghost_pad = NULL;
|
||||
gboolean ret;
|
||||
|
||||
GST_DEBUG_OBJECT(element, "pad requested");
|
||||
GST_DEBUG_OBJECT (element, "pad requested");
|
||||
|
||||
g_return_val_if_fail(self->bin.dtls_element, NULL);
|
||||
g_return_val_if_fail(!self->bin.key_is_set, NULL);
|
||||
g_return_val_if_fail (self->bin.dtls_element, NULL);
|
||||
g_return_val_if_fail (!self->bin.key_is_set, NULL);
|
||||
|
||||
if (templ == gst_element_class_get_pad_template(klass, "data_src")) {
|
||||
GstPad *target_pad;
|
||||
if (templ == gst_element_class_get_pad_template (klass, "data_src")) {
|
||||
GstPad *target_pad;
|
||||
|
||||
target_pad = gst_element_get_request_pad(self->bin.dtls_element, "src");
|
||||
target_pad = gst_element_get_request_pad (self->bin.dtls_element, "src");
|
||||
|
||||
ghost_pad = gst_ghost_pad_new_from_template(name, target_pad, templ);
|
||||
gst_object_unref(target_pad);
|
||||
g_return_val_if_fail(ghost_pad, NULL);
|
||||
ghost_pad = gst_ghost_pad_new_from_template (name, target_pad, templ);
|
||||
gst_object_unref (target_pad);
|
||||
g_return_val_if_fail (ghost_pad, NULL);
|
||||
|
||||
ret = gst_pad_set_active(ghost_pad, TRUE);
|
||||
g_return_val_if_fail(ret, NULL);
|
||||
ret = gst_element_add_pad(element, ghost_pad);
|
||||
g_return_val_if_fail(ret, NULL);
|
||||
ret = gst_pad_set_active (ghost_pad, TRUE);
|
||||
g_return_val_if_fail (ret, NULL);
|
||||
ret = gst_element_add_pad (element, ghost_pad);
|
||||
g_return_val_if_fail (ret, NULL);
|
||||
|
||||
GST_LOG_OBJECT(self, "added data src pad");
|
||||
GST_LOG_OBJECT (self, "added data src pad");
|
||||
|
||||
if (caps) {
|
||||
g_object_set(ghost_pad, "caps", caps, NULL);
|
||||
}
|
||||
|
||||
return ghost_pad;
|
||||
if (caps) {
|
||||
g_object_set (ghost_pad, "caps", caps, NULL);
|
||||
}
|
||||
|
||||
g_return_val_if_reached(NULL);
|
||||
return ghost_pad;
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
static GstCaps *on_decoder_request_key(GstElement *srtp_decoder,
|
||||
guint ssrc, GstErDtlsSrtpBin *bin)
|
||||
static GstCaps *
|
||||
on_decoder_request_key (GstElement * srtp_decoder,
|
||||
guint ssrc, GstErDtlsSrtpBin * bin)
|
||||
{
|
||||
GstCaps *key_caps;
|
||||
GstBuffer *key_buffer = NULL;
|
||||
guint cipher;
|
||||
guint auth;
|
||||
GstCaps *key_caps;
|
||||
GstBuffer *key_buffer = NULL;
|
||||
guint cipher;
|
||||
guint auth;
|
||||
|
||||
if (bin->key_is_set) {
|
||||
if (bin->key) {
|
||||
if (bin->srtp_cipher && bin->srtp_auth && bin->srtcp_cipher && bin->srtcp_auth) {
|
||||
GST_DEBUG_OBJECT(bin, "setting srtp key");
|
||||
return gst_caps_new_simple("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, gst_buffer_copy(bin->key),
|
||||
"srtp-auth", G_TYPE_STRING, bin->srtp_auth,
|
||||
"srtcp-auth", G_TYPE_STRING, bin->srtcp_auth,
|
||||
"srtp-cipher", G_TYPE_STRING, bin->srtp_cipher,
|
||||
"srtcp-cipher", G_TYPE_STRING, bin->srtcp_cipher,
|
||||
NULL);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(bin, "srtp key is set but not all ciphers and auths");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT(bin, "setting srtp key to null");
|
||||
return gst_caps_new_simple("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, NULL,
|
||||
"srtp-auth", G_TYPE_STRING, "null",
|
||||
"srtcp-auth", G_TYPE_STRING, "null",
|
||||
"srtp-cipher", G_TYPE_STRING, "null",
|
||||
"srtcp-cipher", G_TYPE_STRING, "null",
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (bin->dtls_element) {
|
||||
g_object_get(bin->dtls_element,
|
||||
"decoder-key", &key_buffer,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (key_buffer) {
|
||||
g_object_get(bin->dtls_element,
|
||||
"srtp-cipher", &cipher,
|
||||
"srtp-auth", &auth,
|
||||
NULL);
|
||||
|
||||
g_return_val_if_fail(cipher == ER_DTLS_SRTP_CIPHER_AES_128_ICM, NULL);
|
||||
|
||||
key_caps = gst_caps_new_simple("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, key_buffer,
|
||||
"srtp-cipher", G_TYPE_STRING, "aes-128-icm",
|
||||
"srtcp-cipher", G_TYPE_STRING, "aes-128-icm",
|
||||
NULL);
|
||||
|
||||
switch (auth) {
|
||||
case ER_DTLS_SRTP_AUTH_HMAC_SHA1_32:
|
||||
gst_caps_set_simple(key_caps,
|
||||
"srtp-auth", G_TYPE_STRING, "hmac-sha1-32",
|
||||
"srtcp-auth", G_TYPE_STRING, "hmac-sha1-32",
|
||||
NULL);
|
||||
break;
|
||||
case ER_DTLS_SRTP_AUTH_HMAC_SHA1_80:
|
||||
gst_caps_set_simple(key_caps,
|
||||
"srtp-auth", G_TYPE_STRING, "hmac-sha1-80",
|
||||
"srtcp-auth", G_TYPE_STRING, "hmac-sha1-80",
|
||||
NULL);
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached(NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return key_caps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void on_peer_pem(GstElement *srtp_decoder, GParamSpec *pspec, GstErDtlsSrtpDec *self)
|
||||
{
|
||||
UNUSED(srtp_decoder);
|
||||
UNUSED(pspec);
|
||||
g_return_if_fail(self);
|
||||
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_PEER_PEM]);
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_dec_remove_dtls_element(GstErDtlsSrtpBin *bin)
|
||||
{
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC(bin);
|
||||
GstPad *demux_pad;
|
||||
gulong id;
|
||||
|
||||
if (!bin->dtls_element) {
|
||||
return;
|
||||
}
|
||||
|
||||
demux_pad = gst_element_get_static_pad(self->dtls_srtp_demux, "dtls_src");
|
||||
|
||||
id = gst_pad_add_probe(demux_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
|
||||
(GstPadProbeCallback) remove_dtls_decoder_probe_callback, bin->dtls_element, NULL);
|
||||
g_return_if_fail(id);
|
||||
bin->dtls_element = NULL;
|
||||
|
||||
gst_pad_push_event(demux_pad, gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("dummy")));
|
||||
|
||||
gst_object_unref(demux_pad);
|
||||
}
|
||||
|
||||
static GstPadProbeReturn remove_dtls_decoder_probe_callback(GstPad *pad,
|
||||
GstPadProbeInfo *info, GstElement *element)
|
||||
{
|
||||
gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(element), GST_STATE_NULL);
|
||||
gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(element)), element);
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
static GstPadProbeReturn drop_funnel_rtcp_caps(GstPad *pad, GstPadProbeInfo *info, gpointer data)
|
||||
{
|
||||
/* FIXME: This is needed for setting the proper caps until
|
||||
* GStreamer supports MIXED caps or another mechanism to
|
||||
* prevent renegotiation all the time when two different caps
|
||||
* are going over the same pad
|
||||
*/
|
||||
if (GST_EVENT_TYPE (info->data) == GST_EVENT_CAPS) {
|
||||
GstCaps *caps, *peercaps;
|
||||
GstStructure *s;
|
||||
|
||||
gst_event_parse_caps (GST_EVENT (info->data), &caps);
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
if (gst_structure_has_name (s, "application/x-rtcp")) {
|
||||
peercaps = gst_pad_query_caps (pad, NULL);
|
||||
|
||||
/* If the peer does not accept RTCP, we are linked to
|
||||
* the RTP sinkpad of rtpbin. In that case we have to
|
||||
* drop the RTCP caps and assume that we sent RTP caps
|
||||
* before here, which is very likely but not guaranteed
|
||||
* if for some reason we receive RTCP before any RTP.
|
||||
* In that unlikely case we will get event misordering
|
||||
* warnings later, instead of getting them always as
|
||||
* happens now.
|
||||
*/
|
||||
if (peercaps && !gst_caps_is_subset (caps, peercaps)) {
|
||||
gst_caps_unref (peercaps);
|
||||
return GST_PAD_PROBE_DROP;
|
||||
}
|
||||
gst_caps_replace (&peercaps, NULL);
|
||||
if (bin->key_is_set) {
|
||||
if (bin->key) {
|
||||
if (bin->srtp_cipher && bin->srtp_auth && bin->srtcp_cipher
|
||||
&& bin->srtcp_auth) {
|
||||
GST_DEBUG_OBJECT (bin, "setting srtp key");
|
||||
return gst_caps_new_simple ("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, gst_buffer_copy (bin->key),
|
||||
"srtp-auth", G_TYPE_STRING, bin->srtp_auth,
|
||||
"srtcp-auth", G_TYPE_STRING, bin->srtcp_auth,
|
||||
"srtp-cipher", G_TYPE_STRING, bin->srtp_cipher,
|
||||
"srtcp-cipher", G_TYPE_STRING, bin->srtcp_cipher, NULL);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (bin,
|
||||
"srtp key is set but not all ciphers and auths");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
GST_DEBUG_OBJECT (bin, "setting srtp key to null");
|
||||
return gst_caps_new_simple ("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, NULL,
|
||||
"srtp-auth", G_TYPE_STRING, "null",
|
||||
"srtcp-auth", G_TYPE_STRING, "null",
|
||||
"srtp-cipher", G_TYPE_STRING, "null",
|
||||
"srtcp-cipher", G_TYPE_STRING, "null", NULL);
|
||||
}
|
||||
|
||||
if (bin->dtls_element) {
|
||||
g_object_get (bin->dtls_element, "decoder-key", &key_buffer, NULL);
|
||||
}
|
||||
|
||||
if (key_buffer) {
|
||||
g_object_get (bin->dtls_element,
|
||||
"srtp-cipher", &cipher, "srtp-auth", &auth, NULL);
|
||||
|
||||
g_return_val_if_fail (cipher == ER_DTLS_SRTP_CIPHER_AES_128_ICM, NULL);
|
||||
|
||||
key_caps = gst_caps_new_simple ("application/x-srtp",
|
||||
"srtp-key", GST_TYPE_BUFFER, key_buffer,
|
||||
"srtp-cipher", G_TYPE_STRING, "aes-128-icm",
|
||||
"srtcp-cipher", G_TYPE_STRING, "aes-128-icm", NULL);
|
||||
|
||||
switch (auth) {
|
||||
case ER_DTLS_SRTP_AUTH_HMAC_SHA1_32:
|
||||
gst_caps_set_simple (key_caps,
|
||||
"srtp-auth", G_TYPE_STRING, "hmac-sha1-32",
|
||||
"srtcp-auth", G_TYPE_STRING, "hmac-sha1-32", NULL);
|
||||
break;
|
||||
case ER_DTLS_SRTP_AUTH_HMAC_SHA1_80:
|
||||
gst_caps_set_simple (key_caps,
|
||||
"srtp-auth", G_TYPE_STRING, "hmac-sha1-80",
|
||||
"srtcp-auth", G_TYPE_STRING, "hmac-sha1-80", NULL);
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return key_caps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_peer_pem (GstElement * srtp_decoder, GParamSpec * pspec,
|
||||
GstErDtlsSrtpDec * self)
|
||||
{
|
||||
UNUSED (srtp_decoder);
|
||||
UNUSED (pspec);
|
||||
g_return_if_fail (self);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PEER_PEM]);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_er_dtls_srtp_dec_remove_dtls_element (GstErDtlsSrtpBin * bin)
|
||||
{
|
||||
GstErDtlsSrtpDec *self = GST_ER_DTLS_SRTP_DEC (bin);
|
||||
GstPad *demux_pad;
|
||||
gulong id;
|
||||
|
||||
if (!bin->dtls_element) {
|
||||
return;
|
||||
}
|
||||
|
||||
demux_pad = gst_element_get_static_pad (self->dtls_srtp_demux, "dtls_src");
|
||||
|
||||
id = gst_pad_add_probe (demux_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
|
||||
(GstPadProbeCallback) remove_dtls_decoder_probe_callback,
|
||||
bin->dtls_element, NULL);
|
||||
g_return_if_fail (id);
|
||||
bin->dtls_element = NULL;
|
||||
|
||||
gst_pad_push_event (demux_pad,
|
||||
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
|
||||
gst_structure_new_empty ("dummy")));
|
||||
|
||||
gst_object_unref (demux_pad);
|
||||
}
|
||||
|
||||
static GstPadProbeReturn
|
||||
remove_dtls_decoder_probe_callback (GstPad * pad,
|
||||
GstPadProbeInfo * info, GstElement * element)
|
||||
{
|
||||
gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
|
||||
|
||||
gst_element_set_state (GST_ELEMENT (element), GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (GST_ELEMENT_PARENT (element)), element);
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
static GstPadProbeReturn
|
||||
drop_funnel_rtcp_caps (GstPad * pad, GstPadProbeInfo * info, gpointer data)
|
||||
{
|
||||
/* FIXME: This is needed for setting the proper caps until
|
||||
* GStreamer supports MIXED caps or another mechanism to
|
||||
* prevent renegotiation all the time when two different caps
|
||||
* are going over the same pad
|
||||
*/
|
||||
if (GST_EVENT_TYPE (info->data) == GST_EVENT_CAPS) {
|
||||
GstCaps *caps, *peercaps;
|
||||
GstStructure *s;
|
||||
|
||||
gst_event_parse_caps (GST_EVENT (info->data), &caps);
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
if (gst_structure_has_name (s, "application/x-rtcp")) {
|
||||
peercaps = gst_pad_query_caps (pad, NULL);
|
||||
|
||||
/* If the peer does not accept RTCP, we are linked to
|
||||
* the RTP sinkpad of rtpbin. In that case we have to
|
||||
* drop the RTCP caps and assume that we sent RTP caps
|
||||
* before here, which is very likely but not guaranteed
|
||||
* if for some reason we receive RTCP before any RTP.
|
||||
* In that unlikely case we will get event misordering
|
||||
* warnings later, instead of getting them always as
|
||||
* happens now.
|
||||
*/
|
||||
if (peercaps && !gst_caps_is_subset (caps, peercaps)) {
|
||||
gst_caps_unref (peercaps);
|
||||
return GST_PAD_PROBE_DROP;
|
||||
}
|
||||
gst_caps_replace (&peercaps, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
|
|
@ -32,108 +32,109 @@
|
|||
#define PACKET_IS_DTLS(b) (b > 0x13 && b < 0x40)
|
||||
#define PACKET_IS_RTP(b) (b > 0x7f && b < 0xc0)
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate rtp_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("rtp_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS(
|
||||
"application/x-rtp;"
|
||||
"application/x-rtcp;"
|
||||
"application/x-srtp;"
|
||||
"application/x-srtcp")
|
||||
GST_STATIC_PAD_TEMPLATE ("rtp_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp;"
|
||||
"application/x-rtcp;" "application/x-srtp;" "application/x-srtcp")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate dtls_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("dtls_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS("application/x-dtls")
|
||||
GST_STATIC_PAD_TEMPLATE ("dtls_src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-dtls")
|
||||
);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(er_er_dtls_srtp_demux_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_er_dtls_srtp_demux_debug);
|
||||
#define GST_CAT_DEFAULT er_er_dtls_srtp_demux_debug
|
||||
|
||||
#define gst_er_dtls_srtp_demux_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE(GstErDtlsSrtpDemux, gst_er_dtls_srtp_demux, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT(er_er_dtls_srtp_demux_debug, "erdtlssrtpdemux", 0, "Ericsson DTLS SRTP Demultiplexer"));
|
||||
G_DEFINE_TYPE_WITH_CODE (GstErDtlsSrtpDemux, gst_er_dtls_srtp_demux,
|
||||
GST_TYPE_ELEMENT, GST_DEBUG_CATEGORY_INIT (er_er_dtls_srtp_demux_debug,
|
||||
"erdtlssrtpdemux", 0, "Ericsson DTLS SRTP Demultiplexer"));
|
||||
|
||||
static GstFlowReturn sink_chain(GstPad *, GstObject *self, GstBuffer *);
|
||||
static GstFlowReturn sink_chain (GstPad *, GstObject * self, GstBuffer *);
|
||||
|
||||
static void gst_er_dtls_srtp_demux_class_init(GstErDtlsSrtpDemuxClass *klass)
|
||||
static void
|
||||
gst_er_dtls_srtp_demux_class_init (GstErDtlsSrtpDemuxClass * klass)
|
||||
{
|
||||
GstElementClass *element_class;
|
||||
GstElementClass *element_class;
|
||||
|
||||
element_class = (GstElementClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&sink_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&rtp_src_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&dtls_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&rtp_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&dtls_src_template));
|
||||
|
||||
gst_element_class_set_static_metadata(element_class,
|
||||
"DTLS SRTP Demultiplexer",
|
||||
"DTLS/SRTP/Demux",
|
||||
"Demultiplexes DTLS and SRTP packets",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"DTLS SRTP Demultiplexer",
|
||||
"DTLS/SRTP/Demux",
|
||||
"Demultiplexes DTLS and SRTP packets",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_demux_init(GstErDtlsSrtpDemux *self)
|
||||
static void
|
||||
gst_er_dtls_srtp_demux_init (GstErDtlsSrtpDemux * self)
|
||||
{
|
||||
GstPad *sink;
|
||||
GstPad *sink;
|
||||
|
||||
sink = gst_pad_new_from_static_template(&sink_template, "sink");
|
||||
self->rtp_src = gst_pad_new_from_static_template(&rtp_src_template, "rtp_src");
|
||||
self->dtls_src = gst_pad_new_from_static_template(&dtls_src_template, "dtls_src");
|
||||
g_return_if_fail(sink);
|
||||
g_return_if_fail(self->rtp_src);
|
||||
g_return_if_fail(self->dtls_src);
|
||||
sink = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||
self->rtp_src =
|
||||
gst_pad_new_from_static_template (&rtp_src_template, "rtp_src");
|
||||
self->dtls_src =
|
||||
gst_pad_new_from_static_template (&dtls_src_template, "dtls_src");
|
||||
g_return_if_fail (sink);
|
||||
g_return_if_fail (self->rtp_src);
|
||||
g_return_if_fail (self->dtls_src);
|
||||
|
||||
gst_pad_set_chain_function(sink, GST_DEBUG_FUNCPTR(sink_chain));
|
||||
gst_pad_set_chain_function (sink, GST_DEBUG_FUNCPTR (sink_chain));
|
||||
|
||||
gst_element_add_pad(GST_ELEMENT(self), sink);
|
||||
gst_element_add_pad(GST_ELEMENT(self), self->rtp_src);
|
||||
gst_element_add_pad(GST_ELEMENT(self), self->dtls_src);
|
||||
gst_element_add_pad (GST_ELEMENT (self), sink);
|
||||
gst_element_add_pad (GST_ELEMENT (self), self->rtp_src);
|
||||
gst_element_add_pad (GST_ELEMENT (self), self->dtls_src);
|
||||
}
|
||||
|
||||
static GstFlowReturn sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buffer)
|
||||
static GstFlowReturn
|
||||
sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstErDtlsSrtpDemux *self = GST_ER_DTLS_SRTP_DEMUX(parent);
|
||||
guint8 first_byte;
|
||||
GstErDtlsSrtpDemux *self = GST_ER_DTLS_SRTP_DEMUX (parent);
|
||||
guint8 first_byte;
|
||||
|
||||
if (gst_buffer_get_size(buffer) == 0) {
|
||||
GST_LOG_OBJECT(self, "received buffer with size 0");
|
||||
gst_buffer_unref(buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (gst_buffer_extract(buffer, 0, &first_byte, 1) != 1) {
|
||||
GST_WARNING_OBJECT(self, "could not extract first byte from buffer");
|
||||
gst_buffer_unref(buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (PACKET_IS_DTLS(first_byte)) {
|
||||
GST_LOG_OBJECT(self, "pushing dtls packet");
|
||||
|
||||
return gst_pad_push(self->dtls_src, buffer);
|
||||
}
|
||||
|
||||
if (PACKET_IS_RTP(first_byte)) {
|
||||
GST_LOG_OBJECT(self, "pushing rtp packet");
|
||||
|
||||
return gst_pad_push(self->rtp_src, buffer);
|
||||
}
|
||||
|
||||
GST_WARNING_OBJECT(self, "received invalid buffer: %x", first_byte);
|
||||
gst_buffer_unref(buffer);
|
||||
if (gst_buffer_get_size (buffer) == 0) {
|
||||
GST_LOG_OBJECT (self, "received buffer with size 0");
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (gst_buffer_extract (buffer, 0, &first_byte, 1) != 1) {
|
||||
GST_WARNING_OBJECT (self, "could not extract first byte from buffer");
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (PACKET_IS_DTLS (first_byte)) {
|
||||
GST_LOG_OBJECT (self, "pushing dtls packet");
|
||||
|
||||
return gst_pad_push (self->dtls_src, buffer);
|
||||
}
|
||||
|
||||
if (PACKET_IS_RTP (first_byte)) {
|
||||
GST_LOG_OBJECT (self, "pushing rtp packet");
|
||||
|
||||
return gst_pad_push (self->rtp_src, buffer);
|
||||
}
|
||||
|
||||
GST_WARNING_OBJECT (self, "received invalid buffer: %x", first_byte);
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
|
|
@ -32,123 +32,135 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static GstStaticPadTemplate rtp_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("rtp_sink_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS("application/x-rtp;application/x-rtcp")
|
||||
GST_STATIC_PAD_TEMPLATE ("rtp_sink_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("application/x-rtp;application/x-rtcp")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate rtcp_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("rtcp_sink_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS("application/x-rtp;application/x-rtcp")
|
||||
GST_STATIC_PAD_TEMPLATE ("rtcp_sink_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("application/x-rtp;application/x-rtcp")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate data_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE("data_sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
GST_STATIC_PAD_TEMPLATE ("data_sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY
|
||||
);
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC(er_dtls_srtp_enc_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (er_dtls_srtp_enc_debug);
|
||||
#define GST_CAT_DEFAULT er_dtls_srtp_enc_debug
|
||||
|
||||
#define gst_er_dtls_srtp_enc_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE(GstErDtlsSrtpEnc, gst_er_dtls_srtp_enc, GST_TYPE_ER_DTLS_SRTP_BIN,
|
||||
GST_DEBUG_CATEGORY_INIT(er_dtls_srtp_enc_debug, "erdtlssrtpenc", 0, "Ericsson DTLS Decoder"));
|
||||
G_DEFINE_TYPE_WITH_CODE (GstErDtlsSrtpEnc, gst_er_dtls_srtp_enc,
|
||||
GST_TYPE_ER_DTLS_SRTP_BIN, GST_DEBUG_CATEGORY_INIT (er_dtls_srtp_enc_debug,
|
||||
"erdtlssrtpenc", 0, "Ericsson DTLS Decoder"));
|
||||
|
||||
enum {
|
||||
SIGNAL_ON_KEY_SET,
|
||||
NUM_SIGNALS
|
||||
enum
|
||||
{
|
||||
SIGNAL_ON_KEY_SET,
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[NUM_SIGNALS];
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_IS_CLIENT,
|
||||
NUM_PROPERTIES
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_IS_CLIENT,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
#define DEFAULT_IS_CLIENT FALSE
|
||||
|
||||
static gboolean transform_enum(GBinding *, const GValue *source_value, GValue *target_value, GEnumClass *);
|
||||
static gboolean transform_enum (GBinding *, const GValue * source_value,
|
||||
GValue * target_value, GEnumClass *);
|
||||
|
||||
static void gst_er_dtls_srtp_enc_set_property(GObject *, guint prop_id, const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_enc_get_property(GObject *, guint prop_id, GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_enc_set_property (GObject *, guint prop_id,
|
||||
const GValue *, GParamSpec *);
|
||||
static void gst_er_dtls_srtp_enc_get_property (GObject *, guint prop_id,
|
||||
GValue *, GParamSpec *);
|
||||
|
||||
static GstPad *add_ghost_pad(GstElement *, const gchar *name, GstPad *, GstPadTemplate *);
|
||||
static GstPad *gst_er_dtls_srtp_enc_request_new_pad(GstElement *, GstPadTemplate *, const gchar *name, const GstCaps *);
|
||||
static GstPad *add_ghost_pad (GstElement *, const gchar * name, GstPad *,
|
||||
GstPadTemplate *);
|
||||
static GstPad *gst_er_dtls_srtp_enc_request_new_pad (GstElement *,
|
||||
GstPadTemplate *, const gchar * name, const GstCaps *);
|
||||
|
||||
static void on_key_received(GObject *encoder, GstErDtlsSrtpEnc *);
|
||||
static void on_key_received (GObject * encoder, GstErDtlsSrtpEnc *);
|
||||
|
||||
static void gst_er_dtls_srtp_enc_remove_dtls_element(GstErDtlsSrtpBin *);
|
||||
static GstPadProbeReturn remove_dtls_encoder_probe_callback(GstPad *, GstPadProbeInfo *, GstElement *);
|
||||
static void gst_er_dtls_srtp_enc_remove_dtls_element (GstErDtlsSrtpBin *);
|
||||
static GstPadProbeReturn remove_dtls_encoder_probe_callback (GstPad *,
|
||||
GstPadProbeInfo *, GstElement *);
|
||||
|
||||
static void gst_er_dtls_srtp_enc_class_init(GstErDtlsSrtpEncClass *klass)
|
||||
static void
|
||||
gst_er_dtls_srtp_enc_class_init (GstErDtlsSrtpEncClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GstErDtlsSrtpBinClass *dtls_srtp_bin_class;
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GstErDtlsSrtpBinClass *dtls_srtp_bin_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
dtls_srtp_bin_class = (GstErDtlsSrtpBinClass *) klass;
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
dtls_srtp_bin_class = (GstErDtlsSrtpBinClass *) klass;
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_enc_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_enc_get_property);
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_enc_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_enc_get_property);
|
||||
|
||||
element_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_enc_request_new_pad);
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_enc_request_new_pad);
|
||||
|
||||
dtls_srtp_bin_class->remove_dtls_element = GST_DEBUG_FUNCPTR(gst_er_dtls_srtp_enc_remove_dtls_element);
|
||||
dtls_srtp_bin_class->remove_dtls_element =
|
||||
GST_DEBUG_FUNCPTR (gst_er_dtls_srtp_enc_remove_dtls_element);
|
||||
|
||||
signals[SIGNAL_ON_KEY_SET] =
|
||||
g_signal_new("on-key-set", G_TYPE_FROM_CLASS(klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
signals[SIGNAL_ON_KEY_SET] =
|
||||
g_signal_new ("on-key-set", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_generic, G_TYPE_NONE, 0);
|
||||
|
||||
properties[PROP_IS_CLIENT] =
|
||||
g_param_spec_boolean("is-client",
|
||||
"Is client",
|
||||
"Set to true if the decoder should act as "
|
||||
"client and initiate the handshake",
|
||||
DEFAULT_IS_CLIENT,
|
||||
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
properties[PROP_IS_CLIENT] =
|
||||
g_param_spec_boolean ("is-client",
|
||||
"Is client",
|
||||
"Set to true if the decoder should act as "
|
||||
"client and initiate the handshake",
|
||||
DEFAULT_IS_CLIENT,
|
||||
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(gobject_class, NUM_PROPERTIES, properties);
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&rtp_sink_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&rtcp_sink_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&data_sink_template));
|
||||
gst_element_class_add_pad_template(element_class,
|
||||
gst_static_pad_template_get(&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&rtp_sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&rtcp_sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&data_sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
|
||||
gst_element_class_set_static_metadata(element_class,
|
||||
"DTLS-SRTP Encoder",
|
||||
"Encoder/Network/DTLS/SRTP",
|
||||
"Encodes SRTP packets with a key received from DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"DTLS-SRTP Encoder",
|
||||
"Encoder/Network/DTLS/SRTP",
|
||||
"Encodes SRTP packets with a key received from DTLS",
|
||||
"Patrik Oldsberg patrik.oldsberg@ericsson.com");
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_enc_init(GstErDtlsSrtpEnc *self)
|
||||
static void
|
||||
gst_er_dtls_srtp_enc_init (GstErDtlsSrtpEnc * self)
|
||||
{
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS(GST_ELEMENT(self));
|
||||
static GEnumClass *cipher_enum_class, *auth_enum_class;
|
||||
gboolean ret;
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (self));
|
||||
static GEnumClass *cipher_enum_class, *auth_enum_class;
|
||||
gboolean ret;
|
||||
|
||||
/*
|
||||
+--------------------+ +-----------------+
|
||||
|
@ -162,275 +174,295 @@ static void gst_er_dtls_srtp_enc_init(GstErDtlsSrtpEnc *self)
|
|||
+--------------------+ +-----------------+
|
||||
*/
|
||||
|
||||
self->srtp_enc = gst_element_factory_make("srtpenc", "srtp-encoder");
|
||||
if (!self->srtp_enc) {
|
||||
GST_ERROR_OBJECT(self, "failed to create srtp encoder, is the srtp plugin registered?");
|
||||
return;
|
||||
}
|
||||
g_return_if_fail(self->srtp_enc);
|
||||
self->bin.dtls_element = gst_element_factory_make("erdtlsenc", "dtls-encoder");
|
||||
if (!self->bin.dtls_element) {
|
||||
GST_ERROR_OBJECT(self, "failed to create dtls encoder");
|
||||
return;
|
||||
}
|
||||
self->funnel = gst_element_factory_make("funnel", "funnel");
|
||||
if (!self->funnel) {
|
||||
GST_ERROR_OBJECT(self, "failed to create funnel");
|
||||
return;
|
||||
}
|
||||
self->srtp_enc = gst_element_factory_make ("srtpenc", "srtp-encoder");
|
||||
if (!self->srtp_enc) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"failed to create srtp encoder, is the srtp plugin registered?");
|
||||
return;
|
||||
}
|
||||
g_return_if_fail (self->srtp_enc);
|
||||
self->bin.dtls_element =
|
||||
gst_element_factory_make ("erdtlsenc", "dtls-encoder");
|
||||
if (!self->bin.dtls_element) {
|
||||
GST_ERROR_OBJECT (self, "failed to create dtls encoder");
|
||||
return;
|
||||
}
|
||||
self->funnel = gst_element_factory_make ("funnel", "funnel");
|
||||
if (!self->funnel) {
|
||||
GST_ERROR_OBJECT (self, "failed to create funnel");
|
||||
return;
|
||||
}
|
||||
|
||||
gst_bin_add_many(GST_BIN(self), self->bin.dtls_element, self->srtp_enc, self->funnel, NULL);
|
||||
gst_bin_add_many (GST_BIN (self), self->bin.dtls_element, self->srtp_enc,
|
||||
self->funnel, NULL);
|
||||
|
||||
ret = gst_element_link(self->bin.dtls_element, self->funnel);
|
||||
g_return_if_fail(ret);
|
||||
ret = gst_element_link (self->bin.dtls_element, self->funnel);
|
||||
g_return_if_fail (ret);
|
||||
|
||||
add_ghost_pad(GST_ELEMENT(self), "src",
|
||||
gst_element_get_static_pad(self->funnel, "src"),
|
||||
gst_element_class_get_pad_template(klass, "src"));
|
||||
add_ghost_pad (GST_ELEMENT (self), "src",
|
||||
gst_element_get_static_pad (self->funnel, "src"),
|
||||
gst_element_class_get_pad_template (klass, "src"));
|
||||
|
||||
g_signal_connect(self->bin.dtls_element, "on-key-received", G_CALLBACK(on_key_received), self);
|
||||
g_signal_connect (self->bin.dtls_element, "on-key-received",
|
||||
G_CALLBACK (on_key_received), self);
|
||||
|
||||
if (g_once_init_enter(&cipher_enum_class)) {
|
||||
GType type = g_type_from_name("GstSrtpCipherType");
|
||||
g_assert(type);
|
||||
g_once_init_leave(&cipher_enum_class, g_type_class_peek(type));
|
||||
}
|
||||
if (g_once_init_enter(&auth_enum_class)) {
|
||||
GType type = g_type_from_name("GstSrtpAuthType");
|
||||
g_assert(type);
|
||||
g_once_init_leave(&auth_enum_class, g_type_class_peek(type));
|
||||
}
|
||||
if (g_once_init_enter (&cipher_enum_class)) {
|
||||
GType type = g_type_from_name ("GstSrtpCipherType");
|
||||
g_assert (type);
|
||||
g_once_init_leave (&cipher_enum_class, g_type_class_peek (type));
|
||||
}
|
||||
if (g_once_init_enter (&auth_enum_class)) {
|
||||
GType type = g_type_from_name ("GstSrtpAuthType");
|
||||
g_assert (type);
|
||||
g_once_init_leave (&auth_enum_class, g_type_class_peek (type));
|
||||
}
|
||||
|
||||
g_object_set(self->srtp_enc, "random-key", TRUE, NULL);
|
||||
g_object_set (self->srtp_enc, "random-key", TRUE, NULL);
|
||||
|
||||
g_object_bind_property(G_OBJECT(self), "key", self->srtp_enc, "key", G_BINDING_DEFAULT);
|
||||
g_object_bind_property_full(G_OBJECT(self), "srtp-cipher", self->srtp_enc, "rtp-cipher", G_BINDING_DEFAULT,
|
||||
(GBindingTransformFunc) transform_enum, NULL, cipher_enum_class, NULL);
|
||||
g_object_bind_property_full(G_OBJECT(self), "srtcp-cipher", self->srtp_enc, "rtcp-cipher", G_BINDING_DEFAULT,
|
||||
(GBindingTransformFunc) transform_enum, NULL, cipher_enum_class, NULL);
|
||||
g_object_bind_property_full(G_OBJECT(self), "srtp-auth", self->srtp_enc, "rtp-auth", G_BINDING_DEFAULT,
|
||||
(GBindingTransformFunc) transform_enum, NULL, auth_enum_class, NULL);
|
||||
g_object_bind_property_full(G_OBJECT(self), "srtcp-auth", self->srtp_enc, "rtcp-auth", G_BINDING_DEFAULT,
|
||||
(GBindingTransformFunc) transform_enum, NULL, auth_enum_class, NULL);
|
||||
g_object_bind_property (G_OBJECT (self), "key", self->srtp_enc, "key",
|
||||
G_BINDING_DEFAULT);
|
||||
g_object_bind_property_full (G_OBJECT (self), "srtp-cipher", self->srtp_enc,
|
||||
"rtp-cipher", G_BINDING_DEFAULT, (GBindingTransformFunc) transform_enum,
|
||||
NULL, cipher_enum_class, NULL);
|
||||
g_object_bind_property_full (G_OBJECT (self), "srtcp-cipher", self->srtp_enc,
|
||||
"rtcp-cipher", G_BINDING_DEFAULT, (GBindingTransformFunc) transform_enum,
|
||||
NULL, cipher_enum_class, NULL);
|
||||
g_object_bind_property_full (G_OBJECT (self), "srtp-auth", self->srtp_enc,
|
||||
"rtp-auth", G_BINDING_DEFAULT, (GBindingTransformFunc) transform_enum,
|
||||
NULL, auth_enum_class, NULL);
|
||||
g_object_bind_property_full (G_OBJECT (self), "srtcp-auth", self->srtp_enc,
|
||||
"rtcp-auth", G_BINDING_DEFAULT, (GBindingTransformFunc) transform_enum,
|
||||
NULL, auth_enum_class, NULL);
|
||||
}
|
||||
|
||||
static gboolean transform_enum(GBinding *binding, const GValue *source_value, GValue *target_value, GEnumClass *enum_class)
|
||||
static gboolean
|
||||
transform_enum (GBinding * binding, const GValue * source_value,
|
||||
GValue * target_value, GEnumClass * enum_class)
|
||||
{
|
||||
GEnumValue *enum_value;
|
||||
const gchar *nick;
|
||||
GEnumValue *enum_value;
|
||||
const gchar *nick;
|
||||
|
||||
nick = g_value_get_string(source_value);
|
||||
g_return_val_if_fail(nick, FALSE);
|
||||
nick = g_value_get_string (source_value);
|
||||
g_return_val_if_fail (nick, FALSE);
|
||||
|
||||
enum_value = g_enum_get_value_by_nick(enum_class, nick);
|
||||
g_return_val_if_fail(enum_value, FALSE);
|
||||
enum_value = g_enum_get_value_by_nick (enum_class, nick);
|
||||
g_return_val_if_fail (enum_value, FALSE);
|
||||
|
||||
GST_DEBUG_OBJECT(g_binding_get_source(binding),
|
||||
"transforming enum from %s to %d", nick, enum_value->value);
|
||||
GST_DEBUG_OBJECT (g_binding_get_source (binding),
|
||||
"transforming enum from %s to %d", nick, enum_value->value);
|
||||
|
||||
g_value_set_enum(target_value, enum_value->value);
|
||||
g_value_set_enum (target_value, enum_value->value);
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_enc_set_property(GObject *object,
|
||||
guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_srtp_enc_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC(object);
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_IS_CLIENT:
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_set_property(G_OBJECT(self->bin.dtls_element), "is-client", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "tried to set is-client after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_set_property (G_OBJECT (self->bin.dtls_element), "is-client",
|
||||
value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"tried to set is-client after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_enc_get_property(GObject *object,
|
||||
guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_er_dtls_srtp_enc_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC(object);
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id) {
|
||||
case PROP_IS_CLIENT:
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property(G_OBJECT(self->bin.dtls_element), "is-client", value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT(self, "tried to get is-client after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
if (self->bin.dtls_element) {
|
||||
g_object_get_property (G_OBJECT (self->bin.dtls_element), "is-client",
|
||||
value);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"tried to get is-client after disabling DTLS");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
|
||||
}
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static GstPad *add_ghost_pad(GstElement *element,
|
||||
const gchar *name, GstPad *target, GstPadTemplate *templ)
|
||||
static GstPad *
|
||||
add_ghost_pad (GstElement * element,
|
||||
const gchar * name, GstPad * target, GstPadTemplate * templ)
|
||||
{
|
||||
GstPad *pad;
|
||||
gboolean ret;
|
||||
GstPad *pad;
|
||||
gboolean ret;
|
||||
|
||||
pad = gst_ghost_pad_new_from_template(name, target, templ);
|
||||
gst_object_unref(target);
|
||||
target = NULL;
|
||||
pad = gst_ghost_pad_new_from_template (name, target, templ);
|
||||
gst_object_unref (target);
|
||||
target = NULL;
|
||||
|
||||
ret = gst_pad_set_active(pad, TRUE);
|
||||
g_warn_if_fail(ret);
|
||||
ret = gst_pad_set_active (pad, TRUE);
|
||||
g_warn_if_fail (ret);
|
||||
|
||||
ret = gst_element_add_pad(element, pad);
|
||||
g_warn_if_fail(ret);
|
||||
ret = gst_element_add_pad (element, pad);
|
||||
g_warn_if_fail (ret);
|
||||
|
||||
return pad;
|
||||
return pad;
|
||||
}
|
||||
|
||||
static GstPad *gst_er_dtls_srtp_enc_request_new_pad(GstElement *element,
|
||||
GstPadTemplate *templ, const gchar *name, const GstCaps *caps)
|
||||
static GstPad *
|
||||
gst_er_dtls_srtp_enc_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
|
||||
{
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC(element);
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS(element);
|
||||
GstPad *target_pad;
|
||||
GstPad *ghost_pad = NULL;
|
||||
guint pad_n;
|
||||
gchar *srtp_src_name;
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC (element);
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
||||
GstPad *target_pad;
|
||||
GstPad *ghost_pad = NULL;
|
||||
guint pad_n;
|
||||
gchar *srtp_src_name;
|
||||
|
||||
GST_DEBUG_OBJECT(element, "pad requested");
|
||||
GST_DEBUG_OBJECT (element, "pad requested");
|
||||
|
||||
g_return_val_if_fail(templ->direction == GST_PAD_SINK, NULL);
|
||||
g_return_val_if_fail(self->srtp_enc, NULL);
|
||||
g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
|
||||
g_return_val_if_fail (self->srtp_enc, NULL);
|
||||
|
||||
if (templ == gst_element_class_get_pad_template(klass, "rtp_sink_%d")) {
|
||||
target_pad = gst_element_get_request_pad(self->srtp_enc, name);
|
||||
g_return_val_if_fail(target_pad, NULL);
|
||||
if (templ == gst_element_class_get_pad_template (klass, "rtp_sink_%d")) {
|
||||
target_pad = gst_element_get_request_pad (self->srtp_enc, name);
|
||||
g_return_val_if_fail (target_pad, NULL);
|
||||
|
||||
sscanf(GST_PAD_NAME(target_pad), "rtp_sink_%d", &pad_n);
|
||||
srtp_src_name = g_strdup_printf("rtp_src_%d", pad_n);
|
||||
sscanf (GST_PAD_NAME (target_pad), "rtp_sink_%d", &pad_n);
|
||||
srtp_src_name = g_strdup_printf ("rtp_src_%d", pad_n);
|
||||
|
||||
gst_element_link_pads(self->srtp_enc, srtp_src_name, self->funnel, NULL);
|
||||
gst_element_link_pads (self->srtp_enc, srtp_src_name, self->funnel, NULL);
|
||||
|
||||
g_free(srtp_src_name);
|
||||
g_free (srtp_src_name);
|
||||
|
||||
ghost_pad = add_ghost_pad(element, name, target_pad, templ);
|
||||
ghost_pad = add_ghost_pad (element, name, target_pad, templ);
|
||||
|
||||
GST_LOG_OBJECT(self, "added rtp sink pad");
|
||||
} else if (templ == gst_element_class_get_pad_template(klass, "rtcp_sink_%d")) {
|
||||
target_pad = gst_element_get_request_pad(self->srtp_enc, name);
|
||||
g_return_val_if_fail(target_pad, NULL);
|
||||
GST_LOG_OBJECT (self, "added rtp sink pad");
|
||||
} else if (templ == gst_element_class_get_pad_template (klass,
|
||||
"rtcp_sink_%d")) {
|
||||
target_pad = gst_element_get_request_pad (self->srtp_enc, name);
|
||||
g_return_val_if_fail (target_pad, NULL);
|
||||
|
||||
sscanf(GST_PAD_NAME(target_pad), "rtcp_sink_%d", &pad_n);
|
||||
srtp_src_name = g_strdup_printf("rtcp_src_%d", pad_n);
|
||||
sscanf (GST_PAD_NAME (target_pad), "rtcp_sink_%d", &pad_n);
|
||||
srtp_src_name = g_strdup_printf ("rtcp_src_%d", pad_n);
|
||||
|
||||
gst_element_link_pads(self->srtp_enc, srtp_src_name, self->funnel, NULL);
|
||||
gst_element_link_pads (self->srtp_enc, srtp_src_name, self->funnel, NULL);
|
||||
|
||||
g_free(srtp_src_name);
|
||||
g_free (srtp_src_name);
|
||||
|
||||
ghost_pad = add_ghost_pad(element, name, target_pad, templ);
|
||||
ghost_pad = add_ghost_pad (element, name, target_pad, templ);
|
||||
|
||||
GST_LOG_OBJECT(self, "added rtcp sink pad");
|
||||
} else if (templ == gst_element_class_get_pad_template(klass, "data_sink")) {
|
||||
g_return_val_if_fail(self->bin.dtls_element, NULL);
|
||||
target_pad = gst_element_get_request_pad(self->bin.dtls_element, "sink");
|
||||
GST_LOG_OBJECT (self, "added rtcp sink pad");
|
||||
} else if (templ == gst_element_class_get_pad_template (klass, "data_sink")) {
|
||||
g_return_val_if_fail (self->bin.dtls_element, NULL);
|
||||
target_pad = gst_element_get_request_pad (self->bin.dtls_element, "sink");
|
||||
|
||||
ghost_pad = add_ghost_pad(element, name, target_pad, templ);
|
||||
ghost_pad = add_ghost_pad (element, name, target_pad, templ);
|
||||
|
||||
GST_LOG_OBJECT(self, "added data sink pad");
|
||||
} else {
|
||||
g_warn_if_reached();
|
||||
}
|
||||
GST_LOG_OBJECT (self, "added data sink pad");
|
||||
} else {
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
if (caps && ghost_pad) {
|
||||
g_object_set(ghost_pad, "caps", caps, NULL);
|
||||
}
|
||||
if (caps && ghost_pad) {
|
||||
g_object_set (ghost_pad, "caps", caps, NULL);
|
||||
}
|
||||
|
||||
return ghost_pad;
|
||||
return ghost_pad;
|
||||
}
|
||||
|
||||
static void on_key_received(GObject *encoder, GstErDtlsSrtpEnc *self)
|
||||
static void
|
||||
on_key_received (GObject * encoder, GstErDtlsSrtpEnc * self)
|
||||
{
|
||||
GstErDtlsSrtpBin *bin = GST_ER_DTLS_SRTP_BIN(self);
|
||||
GstBuffer *buffer = NULL;
|
||||
guint cipher, auth;
|
||||
GstErDtlsSrtpBin *bin = GST_ER_DTLS_SRTP_BIN (self);
|
||||
GstBuffer *buffer = NULL;
|
||||
guint cipher, auth;
|
||||
|
||||
if (!(bin->key_is_set || bin->srtp_cipher || bin->srtp_auth
|
||||
|| bin->srtcp_cipher || bin->srtcp_auth)) {
|
||||
g_object_get(encoder,
|
||||
"encoder-key", &buffer,
|
||||
"srtp-cipher", &cipher,
|
||||
"srtp-auth", &auth,
|
||||
NULL);
|
||||
if (!(bin->key_is_set || bin->srtp_cipher || bin->srtp_auth
|
||||
|| bin->srtcp_cipher || bin->srtcp_auth)) {
|
||||
g_object_get (encoder,
|
||||
"encoder-key", &buffer,
|
||||
"srtp-cipher", &cipher, "srtp-auth", &auth, NULL);
|
||||
|
||||
g_object_set(self->srtp_enc,
|
||||
"rtp-cipher", cipher,
|
||||
"rtcp-cipher", cipher,
|
||||
"rtp-auth", auth,
|
||||
"rtcp-auth", auth,
|
||||
"key", buffer,
|
||||
"random-key", FALSE,
|
||||
NULL);
|
||||
g_object_set (self->srtp_enc,
|
||||
"rtp-cipher", cipher,
|
||||
"rtcp-cipher", cipher,
|
||||
"rtp-auth", auth,
|
||||
"rtcp-auth", auth, "key", buffer, "random-key", FALSE, NULL);
|
||||
|
||||
g_signal_emit(self, signals[SIGNAL_ON_KEY_SET], 0);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT(self, "ignoring keys received from DTLS handshake, key struct is set");
|
||||
}
|
||||
g_signal_emit (self, signals[SIGNAL_ON_KEY_SET], 0);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"ignoring keys received from DTLS handshake, key struct is set");
|
||||
}
|
||||
}
|
||||
|
||||
static void gst_er_dtls_srtp_enc_remove_dtls_element(GstErDtlsSrtpBin *bin)
|
||||
static void
|
||||
gst_er_dtls_srtp_enc_remove_dtls_element (GstErDtlsSrtpBin * bin)
|
||||
{
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC(bin);
|
||||
GstPad *dtls_sink_pad, *peer_pad;
|
||||
gulong id;
|
||||
guint rtp_cipher = 1, rtcp_cipher = 1, rtp_auth = 1, rtcp_auth = 1;
|
||||
GstErDtlsSrtpEnc *self = GST_ER_DTLS_SRTP_ENC (bin);
|
||||
GstPad *dtls_sink_pad, *peer_pad;
|
||||
gulong id;
|
||||
guint rtp_cipher = 1, rtcp_cipher = 1, rtp_auth = 1, rtcp_auth = 1;
|
||||
|
||||
if (!bin->dtls_element) {
|
||||
return;
|
||||
}
|
||||
if (!bin->dtls_element) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get(self->srtp_enc,
|
||||
"rtp-cipher", &rtp_cipher,
|
||||
"rtcp-cipher", &rtcp_cipher,
|
||||
"rtp-auth", &rtp_auth,
|
||||
"rtcp-auth", &rtcp_auth,
|
||||
NULL);
|
||||
g_object_get (self->srtp_enc,
|
||||
"rtp-cipher", &rtp_cipher,
|
||||
"rtcp-cipher", &rtcp_cipher,
|
||||
"rtp-auth", &rtp_auth, "rtcp-auth", &rtcp_auth, NULL);
|
||||
|
||||
if (!rtp_cipher && !rtcp_cipher && !rtp_auth && !rtcp_auth) {
|
||||
g_object_set(self->srtp_enc, "random-key", FALSE, NULL);
|
||||
}
|
||||
if (!rtp_cipher && !rtcp_cipher && !rtp_auth && !rtcp_auth) {
|
||||
g_object_set (self->srtp_enc, "random-key", FALSE, NULL);
|
||||
}
|
||||
|
||||
dtls_sink_pad = gst_element_get_static_pad(bin->dtls_element, "sink");
|
||||
dtls_sink_pad = gst_element_get_static_pad (bin->dtls_element, "sink");
|
||||
|
||||
if (!dtls_sink_pad) {
|
||||
gst_element_set_state(GST_ELEMENT(bin->dtls_element), GST_STATE_NULL);
|
||||
gst_bin_remove(GST_BIN(self), bin->dtls_element);
|
||||
bin->dtls_element = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
peer_pad = gst_pad_get_peer(dtls_sink_pad);
|
||||
g_return_if_fail(peer_pad);
|
||||
gst_object_unref(dtls_sink_pad);
|
||||
dtls_sink_pad = NULL;
|
||||
|
||||
id = gst_pad_add_probe(peer_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
|
||||
(GstPadProbeCallback) remove_dtls_encoder_probe_callback, bin->dtls_element, NULL);
|
||||
g_return_if_fail(id);
|
||||
if (!dtls_sink_pad) {
|
||||
gst_element_set_state (GST_ELEMENT (bin->dtls_element), GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (self), bin->dtls_element);
|
||||
bin->dtls_element = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
gst_pad_push_event(peer_pad, gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("dummy")));
|
||||
peer_pad = gst_pad_get_peer (dtls_sink_pad);
|
||||
g_return_if_fail (peer_pad);
|
||||
gst_object_unref (dtls_sink_pad);
|
||||
dtls_sink_pad = NULL;
|
||||
|
||||
gst_object_unref(peer_pad);
|
||||
id = gst_pad_add_probe (peer_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
|
||||
(GstPadProbeCallback) remove_dtls_encoder_probe_callback,
|
||||
bin->dtls_element, NULL);
|
||||
g_return_if_fail (id);
|
||||
bin->dtls_element = NULL;
|
||||
|
||||
gst_pad_push_event (peer_pad,
|
||||
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
|
||||
gst_structure_new_empty ("dummy")));
|
||||
|
||||
gst_object_unref (peer_pad);
|
||||
}
|
||||
|
||||
static GstPadProbeReturn remove_dtls_encoder_probe_callback(GstPad *pad,
|
||||
GstPadProbeInfo *info, GstElement *element)
|
||||
static GstPadProbeReturn
|
||||
remove_dtls_encoder_probe_callback (GstPad * pad,
|
||||
GstPadProbeInfo * info, GstElement * element)
|
||||
{
|
||||
gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
|
||||
gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
|
||||
|
||||
gst_element_set_state(GST_ELEMENT(element), GST_STATE_NULL);
|
||||
gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(element)), element);
|
||||
gst_element_set_state (GST_ELEMENT (element), GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (GST_ELEMENT_PARENT (element)), element);
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
|
|
@ -35,13 +35,19 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
static gboolean plugin_init(GstPlugin *plugin)
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
return gst_element_register(plugin, "erdtlsenc", GST_RANK_NONE, GST_TYPE_ER_DTLS_ENC)
|
||||
&& gst_element_register(plugin, "erdtlsdec", GST_RANK_NONE, GST_TYPE_ER_DTLS_DEC)
|
||||
&& gst_element_register(plugin, "erdtlssrtpdec", GST_RANK_NONE, GST_TYPE_ER_DTLS_SRTP_DEC)
|
||||
&& gst_element_register(plugin, "erdtlssrtpenc", GST_RANK_NONE, GST_TYPE_ER_DTLS_SRTP_ENC)
|
||||
&& gst_element_register(plugin, "erdtlssrtpdemux", GST_RANK_NONE, GST_TYPE_ER_DTLS_SRTP_DEMUX);
|
||||
return gst_element_register (plugin, "erdtlsenc", GST_RANK_NONE,
|
||||
GST_TYPE_ER_DTLS_ENC)
|
||||
&& gst_element_register (plugin, "erdtlsdec", GST_RANK_NONE,
|
||||
GST_TYPE_ER_DTLS_DEC)
|
||||
&& gst_element_register (plugin, "erdtlssrtpdec", GST_RANK_NONE,
|
||||
GST_TYPE_ER_DTLS_SRTP_DEC)
|
||||
&& gst_element_register (plugin, "erdtlssrtpenc", GST_RANK_NONE,
|
||||
GST_TYPE_ER_DTLS_SRTP_ENC)
|
||||
&& gst_element_register (plugin, "erdtlssrtpdemux", GST_RANK_NONE,
|
||||
GST_TYPE_ER_DTLS_SRTP_DEMUX);
|
||||
}
|
||||
|
||||
/* PACKAGE: this is usually set by autotools depending on some _INIT macro
|
||||
|
@ -55,14 +61,10 @@ static gboolean plugin_init(GstPlugin *plugin)
|
|||
|
||||
/* gstreamer looks for this structure to register plugins
|
||||
*/
|
||||
GST_PLUGIN_DEFINE(
|
||||
GST_VERSION_MAJOR,
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
erdtls,
|
||||
"Ericsson DTLS decoder and encoder plugins",
|
||||
plugin_init,
|
||||
PACKAGE_VERSION,
|
||||
"BSD",
|
||||
"OpenWebRTC GStreamer plugins",
|
||||
"http://www.openwebrtc.io/"
|
||||
)
|
||||
"BSD", "OpenWebRTC GStreamer plugins", "http://www.openwebrtc.io/")
|
||||
|
|
Loading…
Reference in a new issue