/*
 * Copyright (c) 2014, Ericsson AB. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this
 * list of conditions and the following disclaimer in the documentation and/or other
 * materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gst/gst.h>

#include "gstdtlsagent.h"

#ifdef __APPLE__
# define __AVAILABILITYMACROS__
# define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif

#include <openssl/err.h>
#include <openssl/ssl.h>

GST_DEBUG_CATEGORY_STATIC (gst_dtls_agent_debug);
#define GST_CAT_DEFAULT gst_dtls_agent_debug

G_DEFINE_TYPE (GstDtlsAgent, gst_dtls_agent, G_TYPE_OBJECT);

#define GST_DTLS_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GST_TYPE_DTLS_AGENT, GstDtlsAgentPrivate))

enum
{
  PROP_0,
  PROP_CERTIFICATE,
  NUM_PROPERTIES
};

static GParamSpec *properties[NUM_PROPERTIES];

struct _GstDtlsAgentPrivate
{
  SSL_CTX *ssl_context;

  GstDtlsCertificate *certificate;
};

static void gst_dtls_agent_finalize (GObject * gobject);
static void gst_dtls_agent_set_property (GObject *, guint prop_id,
    const GValue *, GParamSpec *);
const gchar *gst_dtls_agent_peek_id (GstDtlsAgent *);

#if OPENSSL_VERSION_NUMBER < 0x10100000L
static GRWLock *ssl_locks;

static void
ssl_locking_function (gint mode, gint lock_num, const gchar * file, gint line)
{
  gboolean locking;
  gboolean reading;
  GRWLock *lock;

  locking = mode & CRYPTO_LOCK;
  reading = mode & CRYPTO_READ;
  lock = &ssl_locks[lock_num];

  GST_TRACE_OBJECT (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);
    }
  } else {
    if (reading) {
      g_rw_lock_reader_unlock (lock);
    } else {
      g_rw_lock_writer_unlock (lock);
    }
  }
}

static void
ssl_thread_id_function (CRYPTO_THREADID * id)
{
  CRYPTO_THREADID_set_pointer (id, g_thread_self ());
}
#endif

void
_gst_dtls_init_openssl (void)
{
  static gsize is_init = 0;

  if (g_once_init_enter (&is_init)) {
    GST_DEBUG_CATEGORY_INIT (gst_dtls_agent_debug, "dtlsagent", 0,
        "DTLS Agent");

    if (OPENSSL_VERSION_NUMBER < 0x1000100fL) {
      GST_WARNING_OBJECT (NULL,
          "Incorrect OpenSSL version, should be >= 1.0.1, is %s",
          OPENSSL_VERSION_TEXT);
      g_assert_not_reached ();
    }

    GST_INFO_OBJECT (NULL, "initializing openssl %lx", OPENSSL_VERSION_NUMBER);
    SSL_library_init ();
    SSL_load_error_strings ();
    ERR_load_BIO_strings ();

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    {
      gint i;
      gint num_locks;
      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_THREADID_set_callback (ssl_thread_id_function);
    }
#endif

    g_once_init_leave (&is_init, 1);
  }
}

static void
gst_dtls_agent_class_init (GstDtlsAgentClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  g_type_class_add_private (klass, sizeof (GstDtlsAgentPrivate));

  gobject_class->set_property = gst_dtls_agent_set_property;
  gobject_class->finalize = gst_dtls_agent_finalize;

  properties[PROP_CERTIFICATE] =
      g_param_spec_object ("certificate",
      "GstDtlsCertificate",
      "Sets the certificate of the agent",
      GST_TYPE_DTLS_CERTIFICATE,
      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);

  g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);

  _gst_dtls_init_openssl ();
}

static void
gst_dtls_agent_init (GstDtlsAgent * self)
{
  GstDtlsAgentPrivate *priv = GST_DTLS_AGENT_GET_PRIVATE (self);
  self->priv = priv;

  ERR_clear_error ();

#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
  priv->ssl_context = SSL_CTX_new (DTLS_method ());
#else
  priv->ssl_context = SSL_CTX_new (DTLSv1_method ());
#endif
  if (ERR_peek_error () || !priv->ssl_context) {
    char buf[512];

    priv->ssl_context = NULL;

    GST_WARNING_OBJECT (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);
#endif
}

static void
gst_dtls_agent_finalize (GObject * gobject)
{
  GstDtlsAgentPrivate *priv = GST_DTLS_AGENT (gobject)->priv;

  SSL_CTX_free (priv->ssl_context);
  priv->ssl_context = NULL;

  GST_DEBUG_OBJECT (gobject, "finalized");

  G_OBJECT_CLASS (gst_dtls_agent_parent_class)->finalize (gobject);
}

static void
gst_dtls_agent_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstDtlsAgent *self = GST_DTLS_AGENT (object);
  GstDtlsCertificate *certificate;

  switch (prop_id) {
    case PROP_CERTIFICATE:
      certificate = GST_DTLS_CERTIFICATE (g_value_get_object (value));
      g_return_if_fail (GST_IS_DTLS_CERTIFICATE (certificate));
      g_return_if_fail (self->priv->ssl_context);

      self->priv->certificate = certificate;
      g_object_ref (certificate);

      if (!SSL_CTX_use_certificate (self->priv->ssl_context,
              _gst_dtls_certificate_get_internal_certificate (certificate))) {
        GST_WARNING_OBJECT (self, "could not use certificate");
        g_return_if_reached ();
      }

      if (!SSL_CTX_use_PrivateKey (self->priv->ssl_context,
              _gst_dtls_certificate_get_internal_key (certificate))) {
        GST_WARNING_OBJECT (self, "could not use private key");
        g_return_if_reached ();
      }

      if (!SSL_CTX_check_private_key (self->priv->ssl_context)) {
        GST_WARNING_OBJECT (self, "invalid private key");
        g_return_if_reached ();
      }
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
  }
}

GstDtlsCertificate *
gst_dtls_agent_get_certificate (GstDtlsAgent * self)
{
  g_return_val_if_fail (GST_IS_DTLS_AGENT (self), NULL);
  if (self->priv->certificate) {
    g_object_ref (self->priv->certificate);
  }
  return self->priv->certificate;
}

gchar *
gst_dtls_agent_get_certificate_pem (GstDtlsAgent * self)
{
  gchar *pem;
  g_return_val_if_fail (GST_IS_DTLS_AGENT (self), NULL);
  g_return_val_if_fail (GST_IS_DTLS_CERTIFICATE (self->priv->certificate),
      NULL);

  g_object_get (self->priv->certificate, "pem", &pem, NULL);

  return pem;
}

const GstDtlsAgentContext
_gst_dtls_agent_peek_context (GstDtlsAgent * self)
{
  g_return_val_if_fail (GST_IS_DTLS_AGENT (self), NULL);
  return self->priv->ssl_context;
}
