freeswitch/libs/libzrtp/src/zrtp_iface_sys.c
Travis Cross d2edcad66e Merge Phil Zimmermann's libzrtp as a FreeSWITCH library
Thanks to Phil Zimmermann for the code and for the license exception
we needed to include it.

There remains some build system integration work to be done before
this code will build properly in the FreeSWITCH tree.
2012-03-31 23:42:27 +00:00

490 lines
12 KiB
C

/*
* libZRTP SDK library, implements the ZRTP secure VoIP protocol.
* Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved.
* Contact: http://philzimmermann.com
* For licensing and other legal details, see the file zrtp_legal.c.
*
* Viktor Krykun <v.krikun at zfoneproject.com>
*/
#include "zrtp.h"
#if (defined(ZRTP_USE_BUILTIN) && (ZRTP_USE_BUILTIN == 1))
/*============================================================================*/
/* Default realization of Mutexes synchronization routine */
/*============================================================================*/
/*---------------------------------------------------------------------------*/
#if (ZRTP_PLATFORM == ZP_WIN32_KERNEL)
#include <Ndis.h>
struct zrtp_mutex_t
{
NDIS_SPIN_LOCK mutex;
};
zrtp_status_t zrtp_mutex_init(zrtp_mutex_t **mutex)
{
zrtp_mutex_t* new_mutex = zrtp_sys_alloc(sizeof(zrtp_mutex_t));
if (!new_mutex)
return zrtp_status_alloc_fail;
NdisAllocateSpinLock(&new_mutex->mutex);
*mutex = new_mutex;
return zrtp_status_ok;
}
zrtp_status_t zrtp_mutex_destroy(zrtp_mutex_t* mutex)
{
NdisFreeSpinLock(&mutex->mutex);
zrtp_sys_free(mutex);
return zrtp_status_ok;
}
zrtp_status_t zrtp_mutex_lock(zrtp_mutex_t* mutex)
{
NdisAcquireSpinLock(&mutex->mutex);
return zrtp_status_ok;
}
zrtp_status_t zrtp_mutex_unlock(zrtp_mutex_t* mutex)
{
NdisReleaseSpinLock(&mutex->mutex);
return zrtp_status_ok;
}
/*---------------------------------------------------------------------------*/
#elif (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WIN64) || (ZRTP_PLATFORM == ZP_WINCE)
#include <Windows.h>
struct zrtp_mutex_t
{
HANDLE mutex;
};
zrtp_status_t zrtp_mutex_init(zrtp_mutex_t** mutex)
{
zrtp_mutex_t* new_mutex = zrtp_sys_alloc(sizeof(zrtp_mutex_t));
if (!new_mutex)
return zrtp_status_alloc_fail;
new_mutex->mutex = CreateMutex(NULL, FALSE, NULL);
if (!new_mutex->mutex) {
zrtp_sys_free(new_mutex);
return zrtp_status_fail;
}
*mutex = new_mutex;
return zrtp_status_ok;
}
zrtp_status_t zrtp_mutex_destroy(zrtp_mutex_t* mutex)
{
zrtp_status_t s = (0 == CloseHandle(mutex->mutex)) ? zrtp_status_fail : zrtp_status_ok;
zrtp_sys_free(mutex);
return s;
}
zrtp_status_t zrtp_mutex_lock(zrtp_mutex_t* mutex)
{
return (WaitForSingleObject(mutex->mutex, INFINITE) == WAIT_FAILED) ? zrtp_status_fail : zrtp_status_ok;
}
zrtp_status_t zrtp_mutex_unlock(zrtp_mutex_t* mutex)
{
return (0 == ReleaseMutex(mutex->mutex)) ? zrtp_status_fail : zrtp_status_ok;
}
/*---------------------------------------------------------------------------*/
#elif (ZRTP_PLATFORM == ZP_LINUX) || (ZRTP_PLATFORM == ZP_DARWIN) || (ZRTP_PLATFORM == ZP_BSD) || (ZRTP_PLATFORM == ZP_ANDROID)
#if defined ZRTP_HAVE_PTHREAD_H
# include <pthread.h>
#endif
struct zrtp_mutex_t
{
pthread_mutex_t mutex;
};
zrtp_status_t zrtp_mutex_init(zrtp_mutex_t** mutex)
{
zrtp_mutex_t* new_mutex = zrtp_sys_alloc(sizeof(zrtp_mutex_t));
if (new_mutex) {
zrtp_status_t s = pthread_mutex_init(&new_mutex->mutex, NULL) == 0 ? zrtp_status_ok : zrtp_status_fail;
if (s == zrtp_status_fail)
zrtp_sys_free(new_mutex);
else
*mutex = new_mutex;
return s;
}
return zrtp_status_alloc_fail;
}
zrtp_status_t zrtp_mutex_destroy(zrtp_mutex_t* mutex)
{
zrtp_status_t s = (pthread_mutex_destroy(&mutex->mutex) == 0) ? zrtp_status_ok : zrtp_status_fail;
zrtp_sys_free(mutex);
return s;
}
zrtp_status_t zrtp_mutex_lock(zrtp_mutex_t* mutex)
{
return (pthread_mutex_lock(&mutex->mutex) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_mutex_unlock(zrtp_mutex_t* mutex)
{
return (pthread_mutex_unlock(&mutex->mutex) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
#endif
/*============================================================================*/
/* Default realization of Semaphores synchronization routine */
/*============================================================================*/
#if (ZRTP_PLATFORM == ZP_WIN32_KERNEL)
struct zrtp_sem_t
{
KSEMAPHORE sem;
};
zrtp_status_t zrtp_sem_init(zrtp_sem_t** sem, uint32_t val, uint32_t limit)
{
zrtp_sem_t *new_sem = zrtp_sys_alloc(sizeof(zrtp_sem_t));
if (NULL == new_sem) {
return zrtp_status_alloc_fail;
}
KeInitializeSemaphore(&new_sem->sem, val, limit);
*sem = new_sem;
return zrtp_status_ok;
}
zrtp_status_t zrtp_sem_destroy(zrtp_sem_t* sem)
{
return zrtp_status_ok;
}
zrtp_status_t zrtp_sem_wait(zrtp_sem_t* sem)
{
return KeWaitForSingleObject(&sem->sem, Executive, KernelMode, FALSE, NULL) == STATUS_SUCCESS ?
zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_trtwait(zrtp_sem_t* sem)
{
LARGE_INTEGER timeout;
timeout.QuadPart = 0;
return KeWaitForSingleObject(&sem->sem, Executive, KernelMode, FALSE, &timeout) == STATUS_SUCCESS ?
zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_post(zrtp_sem_t* sem)
{
KeReleaseSemaphore(&sem->sem, IO_NO_INCREMENT, 1, FALSE);
return zrtp_status_ok;
}
#elif (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WIN64) || (ZRTP_PLATFORM == ZP_WINCE)
struct zrtp_sem_t
{
HANDLE sem;
};
zrtp_status_t zrtp_sem_init(zrtp_sem_t** sem, uint32_t val, uint32_t limit)
{
zrtp_sem_t *new_sem = zrtp_sys_alloc(sizeof(zrtp_sem_t));
if (NULL == new_sem) {
return zrtp_status_alloc_fail;
}
new_sem->sem = CreateSemaphore(NULL, val, limit, NULL);
if (!new_sem->sem) {
zrtp_sys_free(new_sem);
return zrtp_status_fail;
}
*sem = new_sem;
return zrtp_status_ok;
}
zrtp_status_t zrtp_sem_destroy(zrtp_sem_t* sem)
{
zrtp_status_t s = (0 == CloseHandle(sem->sem)) ? zrtp_status_fail : zrtp_status_ok;
zrtp_sys_free(sem);
return s;
}
zrtp_status_t zrtp_sem_wait(zrtp_sem_t* sem)
{
return (WaitForSingleObject(sem->sem, INFINITE) == WAIT_FAILED) ? zrtp_status_fail : zrtp_status_ok;
}
zrtp_status_t zrtp_sem_trtwait(zrtp_sem_t* sem)
{
return (WaitForSingleObject(sem->sem, 0) == WAIT_OBJECT_0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_post(zrtp_sem_t* sem)
{
return (0 == ReleaseSemaphore(sem->sem, 1, NULL)) ? zrtp_status_fail : zrtp_status_ok;
}
#elif (ZRTP_PLATFORM == ZP_LINUX) || (ZRTP_PLATFORM == ZP_DARWIN) || (ZRTP_PLATFORM == ZP_BSD) || (ZRTP_PLATFORM == ZP_ANDROID)
#if defined ZRTP_HAVE_STDIO_H
# include <stdio.h>
#endif
#if ZRTP_HAVE_SEMAPHORE_H
# include <semaphore.h>
#endif
#if ZRTP_HAVE_FCNTL_H
# include <fcntl.h>
#endif
#if ZRTP_HAVE_ERRNO_H
# include <errno.h>
#endif
#if (ZRTP_PLATFORM == ZP_DARWIN)
struct zrtp_sem_t
{
sem_t* sem;
};
zrtp_status_t zrtp_sem_init(zrtp_sem_t** sem, uint32_t value, uint32_t limit)
{
zrtp_status_t s = zrtp_status_ok;
char name_buff[48];
zrtp_time_t now = zrtp_time_now();
zrtp_sem_t *new_sem = (zrtp_sem_t*)zrtp_sys_alloc(sizeof(zrtp_sem_t));
if (0 == new_sem) {
return zrtp_status_alloc_fail;
}
/*
* This bogusness is to follow what appears to be the lowest common
* denominator in Posix semaphore naming:
* - start with '/'
* - be at most 15 chars
* - be unique and not match anything on the filesystem
* We suppose to generate unique name for every semaphore in the system.
*/
sprintf(name_buff, "/libzrtp.%llxZ%llx", now/1000, now);
new_sem->sem = sem_open(name_buff, O_CREAT | O_EXCL, S_IRUSR|S_IWUSR, value);
if ((sem_t *)SEM_FAILED == new_sem->sem) {
if (errno == ENAMETOOLONG) {
name_buff[13] = '\0';
} else if (errno == EEXIST) {
sprintf(name_buff, "/libzrtp.%llxZ%llx", now, now/1000);
} else {
s = zrtp_status_fail;
}
new_sem->sem = sem_open(name_buff, O_CREAT | O_EXCL, 0644, value);
}
if (new_sem->sem == (sem_t *)SEM_FAILED) {
s = zrtp_status_fail;
zrtp_sys_free(new_sem);
} else {
sem_unlink(name_buff);
*sem = new_sem;
}
return s;
}
zrtp_status_t zrtp_sem_destroy(zrtp_sem_t* sem)
{
zrtp_status_t s = sem_close(sem->sem);
zrtp_sys_free(sem);
if (0 != s) {
s = zrtp_status_fail;
}
return s;
}
zrtp_status_t zrtp_sem_wait(zrtp_sem_t* sem)
{
return (sem_wait(sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_trtwait(zrtp_sem_t* sem)
{
return (sem_trywait(sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_post(zrtp_sem_t* sem)
{
return (sem_post(sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
#else
struct zrtp_sem_t
{
sem_t sem;
};
zrtp_status_t zrtp_sem_init(zrtp_sem_t** sem, uint32_t value, uint32_t limit)
{
zrtp_sem_t *new_sem = (zrtp_sem_t*)zrtp_sys_alloc(sizeof(zrtp_sem_t));
if (NULL == new_sem) {
return zrtp_status_alloc_fail;
}
if (sem_init(&new_sem->sem, 0, value) != 0) {
zrtp_sys_free(new_sem);
return zrtp_status_fail;
}
*sem = new_sem;
return zrtp_status_ok;
}
zrtp_status_t zrtp_sem_destroy(zrtp_sem_t* sem)
{
zrtp_status_t s = sem_destroy(&sem->sem) == 0 ? zrtp_status_ok : zrtp_status_fail;
zrtp_sys_free(sem);
return s;
}
zrtp_status_t zrtp_sem_wait(zrtp_sem_t* sem)
{
return (sem_wait(&sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_trtwait(zrtp_sem_t* sem)
{
return (sem_trywait(&sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
zrtp_status_t zrtp_sem_post(zrtp_sem_t* sem)
{
return (sem_post(&sem->sem) == 0) ? zrtp_status_ok : zrtp_status_fail;
}
#endif
#endif
/*============================================================================*/
/* Default realization of general routine */
/*============================================================================*/
#if defined ZRTP_HAVE_STRING_H
# include <string.h> /* for memset() and memcpy() */
#endif
/*----------------------------------------------------------------------------*/
#if (ZRTP_PLATFORM == ZP_WIN32_KERNEL)
void* zrtp_sys_alloc(unsigned int size)
{
void *VA;
return (NDIS_STATUS_SUCCESS != NdisAllocateMemoryWithTag(&VA, size, (ULONG)"zrtp")) ? NULL : VA;
}
void zrtp_sys_free(void* obj)
{
/* Length is 0 because memory was allocated with TAG */
NdisFreeMemory(obj, 0, 0);
}
void* zrtp_memcpy(void* dest, const void* src, unsigned int length)
{
return memcpy(dest,src,length);
}
void *zrtp_memset(void *s, int c, unsigned int n)
{
return memset(s, c, n);
}
zrtp_time_t zrtp_time_now()
{
LARGE_INTEGER ft;
KeQuerySystemTime(&ft);
ft.QuadPart -= 116444736000000000;
return (zrtp_time_t)(ft.QuadPart) / 10000;
}
#else
/*---------------------------------------------------------------------------*/
#if (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WIN64) || (ZRTP_PLATFORM == ZP_WINCE)
zrtp_time_t zrtp_time_now()
{
LONGLONG ft;
#if ZRTP_PLATFORM != ZP_WINCE
GetSystemTimeAsFileTime((LPFILETIME)&ft);
#else
SYSTEMTIME SystemTime;
GetSystemTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, (LPFILETIME)&ft);
#endif
ft -= 116444736000000000;
return (zrtp_time_t)(ft) / 10000;
}
/*---------------------------------------------------------------------------*/
#elif (ZRTP_PLATFORM == ZP_LINUX) || (ZRTP_PLATFORM == ZP_DARWIN) || (ZRTP_PLATFORM == ZP_SYMBIAN) || (ZRTP_PLATFORM == ZP_BSD) || (ZRTP_PLATFORM == ZP_ANDROID)
#if defined ZRTP_HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
zrtp_time_t zrtp_time_now()
{
struct timeval tv;
if (0 == gettimeofday(&tv, 0)) {
return (zrtp_time_t)(tv.tv_sec)*1000 + (zrtp_time_t)(tv.tv_usec)/1000;
}
return 0;
}
#endif
void *zrtp_memset(void *s, int c, unsigned int n)
{
memset(s, c, n);
return s;
}
void* zrtp_memcpy(void* dest, const void* src, unsigned int length)
{
memcpy(dest, src, (size_t)length);
return dest;
}
void* zrtp_sys_alloc(unsigned int size)
{
return malloc((size_t)size);
}
void zrtp_sys_free(void* obj)
{
free(obj);
}
#endif /* default platform-dependent components realizations */
#endif /*ZRTP_USE_BUILTIN*/