/*
 * shctx.c - shared context management functions for SSL
 *
 * Copyright (C) 2011-2012 EXCELIANCE
 *
 * Author: Emeric Brun - emeric@exceliance.fr
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <sys/mman.h>
#ifdef USE_SYSCALL_FUTEX
#include <unistd.h>
#ifndef u32
#define u32 unsigned int
#endif
#include <linux/futex.h>
#include <sys/syscall.h>
#else /* USE_SYSCALL_FUTEX */
#include <pthread.h>
#endif /* USE_SYSCALL_FUTEX */

#include "ebmbtree.h"
#include "proto/shctx.h"

struct shared_session {
	struct ebmb_node key;
	unsigned char key_data[SSL_MAX_SSL_SESSION_ID_LENGTH];
	long c_date;
	int data_len;
	unsigned char data[SHSESS_MAX_DATA_LEN];
	struct shared_session *p;
	struct shared_session *n;
};


struct shared_context {
#ifdef USE_SYSCALL_FUTEX
	unsigned int waiters;
#else /* USE_SYSCALL_FUTEX */
	pthread_mutex_t mutex;
#endif
	struct shared_session active;
	struct shared_session free;
};

/* Static shared context */
static struct shared_context *shctx = NULL;

/* Callbacks */
static void (*shared_session_new_cbk)(unsigned char *session, unsigned int session_len, long cdate);


/* Lock functions */
#ifdef USE_SYSCALL_FUTEX
#if defined (__i586__) || defined (__x86_64__)
static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
{
	__asm volatile("lock xchgl %0,%1"
		     : "=r" (x), "+m" (*ptr)
		     : "0" (x)
		     : "memory");
	return x;
}

static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
{
	unsigned int ret;

	__asm volatile("lock cmpxchgl %2,%1"
		     : "=a" (ret), "+m" (*ptr)
		     : "r" (new), "0" (old)
		     : "memory");
	return ret;
}

static inline unsigned char atomic_dec(unsigned int *ptr)
{
	unsigned char ret;
	__asm volatile("lock decl %0\n"
		     "setne %1\n"
		     : "+m" (*ptr), "=qm" (ret)
		     :
		     : "memory");
	return ret;
}

#else /* if no x86_64 or i586 arch: use less optimized gcc >= 4.1 built-ins */
static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
{
	return __sync_lock_test_and_set(ptr, x);
}

static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
{
	return __sync_val_compare_and_swap(ptr, old, new);
}

static inline unsigned char atomic_dec(unsigned int *ptr)
{
	return __sync_sub_and_fetch(ptr, 1) ? 1 : 0;
}

#endif

static inline void shared_context_lock(void)
{
	unsigned int x;

	x = cmpxchg(&shctx->waiters, 0, 1);
	if (x) {
		if (x != 2)
			x = xchg(&shctx->waiters, 2);

		while (x) {
			syscall(SYS_futex, &shctx->waiters, FUTEX_WAIT, 2, NULL, 0, 0);
			x = xchg(&shctx->waiters, 2);
		}
	}
}

static inline void shared_context_unlock(void)
{
	if (atomic_dec(&shctx->waiters)) {
		shctx->waiters = 0;
		syscall(SYS_futex, &shctx->waiters, FUTEX_WAKE, 1, NULL, 0, 0);
	}
}

#else /* USE_SYSCALL_FUTEX */

#define shared_context_lock(v) pthread_mutex_lock(&shctx->mutex)
#define shared_context_unlock(v) pthread_mutex_unlock(&shctx->mutex)

#endif

/* List Macros */

#define shsess_unset(s)		(s)->n->p = (s)->p; \
				(s)->p->n = (s)->n;

#define shsess_set_free(s)	shsess_unset(s) \
				(s)->p = &shctx->free; \
				(s)->n = shctx->free.n; \
				shctx->free.n->p = s; \
				shctx->free.n = s;


#define shsess_set_active(s)	shsess_unset(s) \
				(s)->p = &shctx->active; \
				(s)->n = shctx->active.n; \
				shctx->active.n->p = s; \
				shctx->active.n = s;


#define shsess_get_next()	(shctx->free.p == shctx->free.n) ? \
				     shctx->active.p : shctx->free.p;

/* Tree Macros */

#define shsess_tree_delete(s)	ebmb_delete(&(s)->key);

#define shsess_tree_insert(s)	(struct shared_session *)ebmb_insert(&shctx->active.key.node.branches, \
								     &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);

#define shsess_tree_lookup(k)	(struct shared_session *)ebmb_lookup(&shctx->active.key.node.branches, \
								     (k), SSL_MAX_SSL_SESSION_ID_LENGTH);

/* Other Macros */

#define shsess_set_key(s,k,l)	{ memcpy((s)->key_data, (k), (l)); \
				  if ((l) < SSL_MAX_SSL_SESSION_ID_LENGTH) \
					memset((s)->key_data+(l), 0, SSL_MAX_SSL_SESSION_ID_LENGTH-(l)); };


/* SSL context callbacks */

/* SSL callback used on new session creation */
int shctx_new_cb(SSL *ssl, SSL_SESSION *sess)
{
	struct shared_session *shsess;
	unsigned char *data,*p;
	unsigned int data_len;
	unsigned char encsess[SHSESS_MAX_ENCODED_LEN];
	(void)ssl;

	/* check if session reserved size in aligned buffer is large enougth for the ASN1 encode session */
	data_len=i2d_SSL_SESSION(sess, NULL);
	if(data_len > SHSESS_MAX_DATA_LEN)
		return 0;

	/* process ASN1 session encoding before the lock: lower cost */
	p = data = encsess+SSL_MAX_SSL_SESSION_ID_LENGTH;
	i2d_SSL_SESSION(sess, &p);

	shared_context_lock();

	shsess = shsess_get_next();

	shsess_tree_delete(shsess);

	shsess_set_key(shsess, sess->session_id, sess->session_id_length);

	/* it returns the already existing node or current node if none, never returns null */
	shsess = shsess_tree_insert(shsess);

	/* store ASN1 encoded session into cache */
	shsess->data_len = data_len;
	memcpy(shsess->data, data, data_len);

	/* store creation date */
	shsess->c_date = SSL_SESSION_get_time(sess);

	shsess_set_active(shsess);

	shared_context_unlock();

	if (shared_session_new_cbk) { /* if user level callback is set */
		/* copy sessionid padded with 0 into the sessionid + data aligned buffer */
		memcpy(encsess, sess->session_id, sess->session_id_length);
		if (sess->session_id_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
			memset(encsess+sess->session_id_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sess->session_id_length);

		shared_session_new_cbk(encsess, SSL_MAX_SSL_SESSION_ID_LENGTH+data_len, SSL_SESSION_get_time(sess));
	}

	return 0; /* do not increment session reference count */
}

/* SSL callback used on lookup an existing session cause none found in internal cache */
SSL_SESSION *shctx_get_cb(SSL *ssl, unsigned char *key, int key_len, int *do_copy)
{
	struct shared_session *shsess;
	unsigned char data[SHSESS_MAX_DATA_LEN], *p;
	unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
	unsigned int data_len;
	long cdate;
	SSL_SESSION *sess;
	(void)ssl;

	/* allow the session to be freed automatically by openssl */
	*do_copy = 0;

	/* tree key is zeros padded sessionid */
	if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
		memcpy(tmpkey, key, key_len);
		memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
		key = tmpkey;
	}

	/* lock cache */
	shared_context_lock();

	/* lookup for session */
	shsess = shsess_tree_lookup(key);
	if (!shsess) {
		/* no session found: unlock cache and exit */
		shared_context_unlock();
		return NULL;
	}

	/* backup creation date to reset in session after ASN1 decode */
	cdate = shsess->c_date;

	/* copy ASN1 session data to decode outside the lock */
	data_len = shsess->data_len;
	memcpy(data, shsess->data, shsess->data_len);

	shsess_set_active(shsess);

	shared_context_unlock();

	/* decode ASN1 session */
	p = data;
	sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, data_len);

	/* reset creation date */
	if (sess)
		SSL_SESSION_set_time(sess, cdate);

	return sess;
}

/* SSL callback used to signal session is no more used in internal cache */
void shctx_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
{
	struct shared_session *shsess;
	unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
	unsigned char *key = sess->session_id;
	(void)ctx;

	/* tree key is zeros padded sessionid */
	if (sess->session_id_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
		memcpy(tmpkey, sess->session_id, sess->session_id_length);
		memset(tmpkey+sess->session_id_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sess->session_id_length);
		key = tmpkey;
	}

	shared_context_lock();

	/* lookup for session */
	shsess = shsess_tree_lookup(key);
	if (shsess) {
		shsess_set_free(shsess);
	}

	/* unlock cache */
	shared_context_unlock();
}

/* User level function called to add a session to the cache (remote updates) */
void shctx_sess_add(const unsigned char *encsess, unsigned int len, long cdate)
{
	struct shared_session *shsess;

	/* check buffer is at least padded key long + 1 byte
		and data_len not too long */
	if ((len <= SSL_MAX_SSL_SESSION_ID_LENGTH)
		 || (len > SHSESS_MAX_DATA_LEN+SSL_MAX_SSL_SESSION_ID_LENGTH))
		return;

	shared_context_lock();

	shsess = shsess_get_next();

	shsess_tree_delete(shsess);

	shsess_set_key(shsess, encsess, SSL_MAX_SSL_SESSION_ID_LENGTH);

	/* it returns the already existing node or current node if none, never returns null */
	shsess = shsess_tree_insert(shsess);

	/* store into cache and update earlier on session get events */
	if (cdate)
		shsess->c_date = (long)cdate;

	/* copy ASN1 session data into cache */
	shsess->data_len = len-SSL_MAX_SSL_SESSION_ID_LENGTH;
	memcpy(shsess->data, encsess+SSL_MAX_SSL_SESSION_ID_LENGTH, shsess->data_len);

	shsess_set_active(shsess);

	shared_context_unlock();
}

/* Function used to set a callback on new session creation */
void shsess_set_new_cbk(void (*func)(unsigned char *, unsigned int, long))
{
	shared_session_new_cbk = func;
}

/* Allocate shared memory context.
 * size is maximum cached sessions.
 * if set less or equal to 0, SHCTX_DEFAULT_SIZE is used.
 * Returns: -1 on alloc failure, size if it performs context alloc,
 * and 0 if cache is already allocated */
int shared_context_init(int size)
{
	int i;
#ifndef USE_SYSCALL_FUTEX
	pthread_mutexattr_t attr;
#endif /* USE_SYSCALL_FUTEX */
	struct shared_session *prev,*cur;

	if (shctx)
		return 0;

	if (size<=0)
		size = SHCTX_DEFAULT_SIZE;

	shctx = (struct shared_context *)mmap(NULL, sizeof(struct shared_context)+(size*sizeof(struct shared_session)),
	                                      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
	if (!shctx || shctx == MAP_FAILED) {
		shctx = NULL;
		return -1;
	}

#ifdef USE_SYSCALL_FUTEX
	shctx->waiters = 0;
#else
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
	pthread_mutex_init(&shctx->mutex, &attr);
#endif
	memset(&shctx->active.key, 0, sizeof(struct ebmb_node));
	memset(&shctx->free.key, 0, sizeof(struct ebmb_node));

	/* No duplicate authorized in tree: */
	//shctx->active.key.node.branches.b[1] = (void *)1;
	shctx->active.key.node.branches = EB_ROOT_UNIQUE;

	cur = &shctx->active;
	cur->n = cur->p = cur;

	cur = &shctx->free;
	for (i = 0 ; i < size ; i++) {
		prev = cur;
		cur = (struct shared_session *)((char *)prev + sizeof(struct shared_session));
		prev->n = cur;
		cur->p = prev;
	}
	cur->n = &shctx->free;
	shctx->free.p = cur;

	return size;
}


/* Set session cache mode to server and disable openssl internal cache.
 * Set shared cache callbacks on an ssl context.
 * Shared context MUST be firstly initialized */
void shared_context_set_cache(SSL_CTX *ctx)
{
	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
	                                    SSL_SESS_CACHE_NO_INTERNAL |
	                                    SSL_SESS_CACHE_NO_AUTO_CLEAR);
	if (!shctx)
		return;

	/* Set callbacks */
	SSL_CTX_sess_set_new_cb(ctx, shctx_new_cb);
	SSL_CTX_sess_set_get_cb(ctx, shctx_get_cb);
	SSL_CTX_sess_set_remove_cb(ctx, shctx_remove_cb);
}
