#include "types.h"
#include "mpool.h"
#include "tktree.h"
#include "clstree.h"
#include "sha1.h"
#include "listen.h"
#include "ssl_conf.h"
#include "rovm.h"

#include "thread.h"
#include "thread_mutex.h"
#include "thread_cond.h"

#include "mpm_worker_fdqueue.h"
#include "mpm_worker_pod.h"
#include "mpm_worker.h"

#include "connection.h"
#include "request.h"
#include "proc_rc.h"

#include "log.h"
#include "common.h"
#include "ticket.h"

int 
ssl_mutex_init (struct rovm *r, apr_pool_t *p)
{
  SSLModConfigRec *mc = myModConfig(r);
  apr_status_t rv;
  
  if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
    return TRUE;
  
  if (mc->pMutex)
    return TRUE;
  
  if ((rv = apr_global_mutex_create(&mc->pMutex, mc->szMutexFile,
                                    mc->nMutexMech, ROVM_POOL (r)))
      != APR_SUCCESS) 
    {
      if (mc->szMutexFile)
        rovm_log (NULL, ROVMLOG_ERR, ROVMLOG_MARK, 
                  "Cannot create SSLMutex with file `%s'",
                  mc->szMutexFile);
      else
        rovm_log (NULL, ROVMLOG_ERR, ROVMLOG_MARK, 
                  "Cannot create SSLMutex");
      return FALSE;
    }
  
#ifdef AP_NEED_SET_MUTEX_PERMS
  rv = unixd_set_global_mutex_perms(mc->pMutex);
  if (rv != APR_SUCCESS) 
    {
      rovm_log (NULL, ROVMLOG_ERR, ROVMLOG_MARK, 
                "Could not set permissions on ssl_mutex; check User "
                "and Group directives");
      return FALSE;
    }
#endif

  return TRUE;
}

int 
ssl_mutex_reinit(struct rovm *r, apr_pool_t *p)
{
  SSLModConfigRec *mc = myModConfig(r);
  apr_status_t rv;
  
  if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
    return TRUE;
  
  if ((rv = apr_global_mutex_child_init(&mc->pMutex,
                                        mc->szMutexFile, p)) != APR_SUCCESS) 
    {
      if (mc->szMutexFile)
        rovm_log (NULL, ROVMLOG_ERR, ROVMLOG_MARK, 
                  "Cannot reinit SSLMutex with file `%s'",
                  mc->szMutexFile);
      else
        rovm_log (NULL, ROVMLOG_WARNING, ROVMLOG_MARK, 
                  "Cannot reinit SSLMutex");
      return FALSE;
    }

  return TRUE;
}

int
ssl_mutex_on (struct rovm *r)
{
  SSLModConfigRec *mc = myModConfig (r);
  apr_status_t rv;
  
  if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
    return TRUE;

  if ((rv = apr_global_mutex_lock(mc->pMutex)) != APR_SUCCESS) 
    {
      rovm_log (NULL, ROVMLOG_WARNING, ROVMLOG_MARK, 
                "Failed to acquire SSL session cache lock");
      return FALSE;
    }

  return TRUE;
}

int 
ssl_mutex_off (struct rovm *r)
{
  SSLModConfigRec *mc = myModConfig(r);
  apr_status_t rv;
  
  if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
    return TRUE;
  if ((rv = apr_global_mutex_unlock(mc->pMutex)) != APR_SUCCESS) 
    {
      rovm_log (NULL, ROVMLOG_WARNING, ROVMLOG_MARK, 
                "Failed to release SSL session cache lock");
      return FALSE;
    }

  return TRUE;
}
