/*
 * 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_LOG_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 gulong
ssl_thread_id_function (void)
{
  return (gulong) 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_set_id_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;
}
