* #27232: jni: added pjproject checkout as regular git content
We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/.svn/pristine/c0/c010b202e72fc19904befc46db5996a505b03bce.svn-base b/jni/pjproject-android/.svn/pristine/c0/c010b202e72fc19904befc46db5996a505b03bce.svn-base
new file mode 100644
index 0000000..ec4b0fd
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c010b202e72fc19904befc46db5996a505b03bce.svn-base
@@ -0,0 +1,23 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=pjmedia
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 4000 RTP/AVP 0
+"""
+
+pjsua_args = "--null-audio --auto-answer 200"
+extra_headers = "Replaces: abcd;from_tag=1\r\nReplaces: efgh;from_tag=2\r\n"
+include = []
+exclude = []
+
+sendto_cfg = sip.SendtoCfg("Duplicate replaces header", pjsua_args, sdp, 400,
+ extra_headers=extra_headers,
+ resp_inc=include, resp_exc=exclude)
+
diff --git a/jni/pjproject-android/.svn/pristine/c0/c03bf19e26731344e6f1a85d9b9368ff93017c5c.svn-base b/jni/pjproject-android/.svn/pristine/c0/c03bf19e26731344e6f1a85d9b9368ff93017c5c.svn-base
new file mode 100644
index 0000000..252f7fc
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c03bf19e26731344e6f1a85d9b9368ff93017c5c.svn-base
@@ -0,0 +1,1932 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Contributors:
+ * - Thanks for Zetron, Inc. (Phil Torre, ptorre@zetron.com) for donating
+ * the RTEMS port.
+ */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <pj/os.h>
+#include <pj/assert.h>
+#include <pj/pool.h>
+#include <pj/log.h>
+#include <pj/rand.h>
+#include <pj/string.h>
+#include <pj/guid.h>
+#include <pj/except.h>
+#include <pj/errno.h>
+
+#if defined(PJ_HAS_SEMAPHORE_H) && PJ_HAS_SEMAPHORE_H != 0
+# include <semaphore.h>
+#endif
+
+#include <unistd.h> // getpid()
+#include <errno.h> // errno
+
+#include <pthread.h>
+
+#define THIS_FILE "os_core_unix.c"
+
+#define SIGNATURE1 0xDEAFBEEF
+#define SIGNATURE2 0xDEADC0DE
+
+struct pj_thread_t
+{
+ char obj_name[PJ_MAX_OBJ_NAME];
+ pthread_t thread;
+ pj_thread_proc *proc;
+ void *arg;
+ pj_uint32_t signature1;
+ pj_uint32_t signature2;
+
+ pj_mutex_t *suspended_mutex;
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ pj_uint32_t stk_size;
+ pj_uint32_t stk_max_usage;
+ char *stk_start;
+ const char *caller_file;
+ int caller_line;
+#endif
+};
+
+struct pj_atomic_t
+{
+ pj_mutex_t *mutex;
+ pj_atomic_value_t value;
+};
+
+struct pj_mutex_t
+{
+ pthread_mutex_t mutex;
+ char obj_name[PJ_MAX_OBJ_NAME];
+#if PJ_DEBUG
+ int nesting_level;
+ pj_thread_t *owner;
+ char owner_name[PJ_MAX_OBJ_NAME];
+#endif
+};
+
+#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
+struct pj_sem_t
+{
+ sem_t *sem;
+ char obj_name[PJ_MAX_OBJ_NAME];
+};
+#endif /* PJ_HAS_SEMAPHORE */
+
+#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
+struct pj_event_t
+{
+ enum event_state {
+ EV_STATE_OFF,
+ EV_STATE_SET,
+ EV_STATE_PULSED
+ } state;
+
+ pj_mutex_t mutex;
+ pthread_cond_t cond;
+
+ pj_bool_t auto_reset;
+ unsigned threads_waiting;
+ unsigned threads_to_release;
+};
+#endif /* PJ_HAS_EVENT_OBJ */
+
+
+/*
+ * Flag and reference counter for PJLIB instance.
+ */
+static int initialized;
+
+#if PJ_HAS_THREADS
+ static pj_thread_t main_thread;
+ static long thread_tls_id;
+ static pj_mutex_t critical_section;
+#else
+# define MAX_THREADS 32
+ static int tls_flag[MAX_THREADS];
+ static void *tls[MAX_THREADS];
+#endif
+
+static unsigned atexit_count;
+static void (*atexit_func[32])(void);
+
+static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name, int type);
+
+/*
+ * pj_init(void).
+ * Init PJLIB!
+ */
+PJ_DEF(pj_status_t) pj_init(void)
+{
+ char dummy_guid[PJ_GUID_MAX_LENGTH];
+ pj_str_t guid;
+ pj_status_t rc;
+
+ /* Check if PJLIB have been initialized */
+ if (initialized) {
+ ++initialized;
+ return PJ_SUCCESS;
+ }
+
+#if PJ_HAS_THREADS
+ /* Init this thread's TLS. */
+ if ((rc=pj_thread_init()) != 0) {
+ return rc;
+ }
+
+ /* Critical section. */
+ if ((rc=init_mutex(&critical_section, "critsec", PJ_MUTEX_RECURSE)) != 0)
+ return rc;
+
+#endif
+
+ /* Init logging */
+ pj_log_init();
+
+ /* Initialize exception ID for the pool.
+ * Must do so after critical section is configured.
+ */
+ rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);
+ if (rc != PJ_SUCCESS)
+ return rc;
+
+ /* Init random seed. */
+ /* Or probably not. Let application in charge of this */
+ /* pj_srand( clock() ); */
+
+ /* Startup GUID. */
+ guid.ptr = dummy_guid;
+ pj_generate_unique_string( &guid );
+
+ /* Startup timestamp */
+#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
+ {
+ pj_timestamp dummy_ts;
+ if ((rc=pj_get_timestamp(&dummy_ts)) != 0) {
+ return rc;
+ }
+ }
+#endif
+
+ /* Flag PJLIB as initialized */
+ ++initialized;
+ pj_assert(initialized == 1);
+
+ PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",
+ PJ_VERSION));
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_atexit()
+ */
+PJ_DEF(pj_status_t) pj_atexit(void (*func)(void))
+{
+ if (atexit_count >= PJ_ARRAY_SIZE(atexit_func))
+ return PJ_ETOOMANY;
+
+ atexit_func[atexit_count++] = func;
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_shutdown(void)
+ */
+PJ_DEF(void) pj_shutdown()
+{
+ int i;
+
+ /* Only perform shutdown operation when 'initialized' reaches zero */
+ pj_assert(initialized > 0);
+ if (--initialized != 0)
+ return;
+
+ /* Call atexit() functions */
+ for (i=atexit_count-1; i>=0; --i) {
+ (*atexit_func[i])();
+ }
+ atexit_count = 0;
+
+ /* Free exception ID */
+ if (PJ_NO_MEMORY_EXCEPTION != -1) {
+ pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION);
+ PJ_NO_MEMORY_EXCEPTION = -1;
+ }
+
+#if PJ_HAS_THREADS
+ /* Destroy PJLIB critical section */
+ pj_mutex_destroy(&critical_section);
+
+ /* Free PJLIB TLS */
+ if (thread_tls_id != -1) {
+ pj_thread_local_free(thread_tls_id);
+ thread_tls_id = -1;
+ }
+
+ /* Ticket #1132: Assertion when (re)starting PJLIB on different thread */
+ pj_bzero(&main_thread, sizeof(main_thread));
+#endif
+
+ /* Clear static variables */
+ pj_errno_clear_handlers();
+}
+
+
+/*
+ * pj_getpid(void)
+ */
+PJ_DEF(pj_uint32_t) pj_getpid(void)
+{
+ PJ_CHECK_STACK();
+ return getpid();
+}
+
+/*
+ * Check if this thread has been registered to PJLIB.
+ */
+PJ_DEF(pj_bool_t) pj_thread_is_registered(void)
+{
+#if PJ_HAS_THREADS
+ return pj_thread_local_get(thread_tls_id) != 0;
+#else
+ pj_assert("pj_thread_is_registered() called in non-threading mode!");
+ return PJ_TRUE;
+#endif
+}
+
+
+/*
+ * Get thread priority value for the thread.
+ */
+PJ_DEF(int) pj_thread_get_prio(pj_thread_t *thread)
+{
+#if PJ_HAS_THREADS
+ struct sched_param param;
+ int policy;
+ int rc;
+
+ rc = pthread_getschedparam (thread->thread, &policy, ¶m);
+ if (rc != 0)
+ return -1;
+
+ return param.sched_priority;
+#else
+ PJ_UNUSED_ARG(thread);
+ return 1;
+#endif
+}
+
+
+/*
+ * Set the thread priority.
+ */
+PJ_DEF(pj_status_t) pj_thread_set_prio(pj_thread_t *thread, int prio)
+{
+#if PJ_HAS_THREADS
+ struct sched_param param;
+ int policy;
+ int rc;
+
+ rc = pthread_getschedparam (thread->thread, &policy, ¶m);
+ if (rc != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+
+ param.sched_priority = prio;
+
+ rc = pthread_setschedparam(thread->thread, policy, ¶m);
+ if (rc != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+
+ return PJ_SUCCESS;
+#else
+ PJ_UNUSED_ARG(thread);
+ PJ_UNUSED_ARG(prio);
+ pj_assert("pj_thread_set_prio() called in non-threading mode!");
+ return 1;
+#endif
+}
+
+
+/*
+ * Get the lowest priority value available on this system.
+ */
+PJ_DEF(int) pj_thread_get_prio_min(pj_thread_t *thread)
+{
+ struct sched_param param;
+ int policy;
+ int rc;
+
+ rc = pthread_getschedparam(thread->thread, &policy, ¶m);
+ if (rc != 0)
+ return -1;
+
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+ return sched_get_priority_min(policy);
+#elif defined __OpenBSD__
+ /* Thread prio min/max are declared in OpenBSD private hdr */
+ return 0;
+#else
+ pj_assert("pj_thread_get_prio_min() not supported!");
+ return 0;
+#endif
+}
+
+
+/*
+ * Get the highest priority value available on this system.
+ */
+PJ_DEF(int) pj_thread_get_prio_max(pj_thread_t *thread)
+{
+ struct sched_param param;
+ int policy;
+ int rc;
+
+ rc = pthread_getschedparam(thread->thread, &policy, ¶m);
+ if (rc != 0)
+ return -1;
+
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+ return sched_get_priority_max(policy);
+#elif defined __OpenBSD__
+ /* Thread prio min/max are declared in OpenBSD private hdr */
+ return 31;
+#else
+ pj_assert("pj_thread_get_prio_max() not supported!");
+ return 0;
+#endif
+}
+
+
+/*
+ * Get native thread handle
+ */
+PJ_DEF(void*) pj_thread_get_os_handle(pj_thread_t *thread)
+{
+ PJ_ASSERT_RETURN(thread, NULL);
+
+#if PJ_HAS_THREADS
+ return &thread->thread;
+#else
+ pj_assert("pj_thread_is_registered() called in non-threading mode!");
+ return NULL;
+#endif
+}
+
+/*
+ * pj_thread_register(..)
+ */
+PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
+ pj_thread_desc desc,
+ pj_thread_t **ptr_thread)
+{
+#if PJ_HAS_THREADS
+ char stack_ptr;
+ pj_status_t rc;
+ pj_thread_t *thread = (pj_thread_t *)desc;
+ pj_str_t thread_name = pj_str((char*)cstr_thread_name);
+
+ /* Size sanity check. */
+ if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {
+ pj_assert(!"Not enough pj_thread_desc size!");
+ return PJ_EBUG;
+ }
+
+ /* Warn if this thread has been registered before */
+ if (pj_thread_local_get (thread_tls_id) != 0) {
+ // 2006-02-26 bennylp:
+ // This wouldn't work in all cases!.
+ // If thread is created by external module (e.g. sound thread),
+ // thread may be reused while the pool used for the thread descriptor
+ // has been deleted by application.
+ //*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
+ //return PJ_SUCCESS;
+ PJ_LOG(4,(THIS_FILE, "Info: possibly re-registering existing "
+ "thread"));
+ }
+
+ /* On the other hand, also warn if the thread descriptor buffer seem to
+ * have been used to register other threads.
+ */
+ pj_assert(thread->signature1 != SIGNATURE1 ||
+ thread->signature2 != SIGNATURE2 ||
+ (thread->thread == pthread_self()));
+
+ /* Initialize and set the thread entry. */
+ pj_bzero(desc, sizeof(struct pj_thread_t));
+ thread->thread = pthread_self();
+ thread->signature1 = SIGNATURE1;
+ thread->signature2 = SIGNATURE2;
+
+ if(cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1)
+ pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name),
+ cstr_thread_name, thread->thread);
+ else
+ pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name),
+ "thr%p", (void*)thread->thread);
+
+ rc = pj_thread_local_set(thread_tls_id, thread);
+ if (rc != PJ_SUCCESS) {
+ pj_bzero(desc, sizeof(struct pj_thread_t));
+ return rc;
+ }
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ thread->stk_start = &stack_ptr;
+ thread->stk_size = 0xFFFFFFFFUL;
+ thread->stk_max_usage = 0;
+#else
+ stack_ptr = '\0';
+#endif
+
+ *ptr_thread = thread;
+ return PJ_SUCCESS;
+#else
+ pj_thread_t *thread = (pj_thread_t*)desc;
+ *ptr_thread = thread;
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_thread_init(void)
+ */
+pj_status_t pj_thread_init(void)
+{
+#if PJ_HAS_THREADS
+ pj_status_t rc;
+ pj_thread_t *dummy;
+
+ rc = pj_thread_local_alloc(&thread_tls_id );
+ if (rc != PJ_SUCCESS) {
+ return rc;
+ }
+ return pj_thread_register("thr%p", (long*)&main_thread, &dummy);
+#else
+ PJ_LOG(2,(THIS_FILE, "Thread init error. Threading is not enabled!"));
+ return PJ_EINVALIDOP;
+#endif
+}
+
+#if PJ_HAS_THREADS
+/*
+ * thread_main()
+ *
+ * This is the main entry for all threads.
+ */
+static void *thread_main(void *param)
+{
+ pj_thread_t *rec = (pj_thread_t*)param;
+ void *result;
+ pj_status_t rc;
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ rec->stk_start = (char*)&rec;
+#endif
+
+ /* Set current thread id. */
+ rc = pj_thread_local_set(thread_tls_id, rec);
+ if (rc != PJ_SUCCESS) {
+ pj_assert(!"Thread TLS ID is not set (pj_init() error?)");
+ }
+
+ /* Check if suspension is required. */
+ if (rec->suspended_mutex) {
+ pj_mutex_lock(rec->suspended_mutex);
+ pj_mutex_unlock(rec->suspended_mutex);
+ }
+
+ PJ_LOG(6,(rec->obj_name, "Thread started"));
+
+ /* Call user's entry! */
+ result = (void*)(long)(*rec->proc)(rec->arg);
+
+ /* Done. */
+ PJ_LOG(6,(rec->obj_name, "Thread quitting"));
+
+ return result;
+}
+#endif
+
+/*
+ * pj_thread_create(...)
+ */
+PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool,
+ const char *thread_name,
+ pj_thread_proc *proc,
+ void *arg,
+ pj_size_t stack_size,
+ unsigned flags,
+ pj_thread_t **ptr_thread)
+{
+#if PJ_HAS_THREADS
+ pj_thread_t *rec;
+ pthread_attr_t thread_attr;
+ void *stack_addr;
+ int rc;
+
+ PJ_UNUSED_ARG(stack_addr);
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL);
+
+ /* Create thread record and assign name for the thread */
+ rec = (struct pj_thread_t*) pj_pool_zalloc(pool, sizeof(pj_thread_t));
+ PJ_ASSERT_RETURN(rec, PJ_ENOMEM);
+
+ /* Set name. */
+ if (!thread_name)
+ thread_name = "thr%p";
+
+ if (strchr(thread_name, '%')) {
+ pj_ansi_snprintf(rec->obj_name, PJ_MAX_OBJ_NAME, thread_name, rec);
+ } else {
+ strncpy(rec->obj_name, thread_name, PJ_MAX_OBJ_NAME);
+ rec->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
+ }
+
+ /* Set default stack size */
+ if (stack_size == 0)
+ stack_size = PJ_THREAD_DEFAULT_STACK_SIZE;
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+ rec->stk_size = stack_size;
+ rec->stk_max_usage = 0;
+#endif
+
+ /* Emulate suspended thread with mutex. */
+ if (flags & PJ_THREAD_SUSPENDED) {
+ rc = pj_mutex_create_simple(pool, NULL, &rec->suspended_mutex);
+ if (rc != PJ_SUCCESS) {
+ return rc;
+ }
+
+ pj_mutex_lock(rec->suspended_mutex);
+ } else {
+ pj_assert(rec->suspended_mutex == NULL);
+ }
+
+
+ /* Init thread attributes */
+ pthread_attr_init(&thread_attr);
+
+#if defined(PJ_THREAD_SET_STACK_SIZE) && PJ_THREAD_SET_STACK_SIZE!=0
+ /* Set thread's stack size */
+ rc = pthread_attr_setstacksize(&thread_attr, stack_size);
+ if (rc != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+#endif /* PJ_THREAD_SET_STACK_SIZE */
+
+
+#if defined(PJ_THREAD_ALLOCATE_STACK) && PJ_THREAD_ALLOCATE_STACK!=0
+ /* Allocate memory for the stack */
+ stack_addr = pj_pool_alloc(pool, stack_size);
+ PJ_ASSERT_RETURN(stack_addr, PJ_ENOMEM);
+
+ rc = pthread_attr_setstackaddr(&thread_attr, stack_addr);
+ if (rc != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+#endif /* PJ_THREAD_ALLOCATE_STACK */
+
+
+ /* Create the thread. */
+ rec->proc = proc;
+ rec->arg = arg;
+ rc = pthread_create( &rec->thread, &thread_attr, &thread_main, rec);
+ if (rc != 0) {
+ return PJ_RETURN_OS_ERROR(rc);
+ }
+
+ *ptr_thread = rec;
+
+ PJ_LOG(6, (rec->obj_name, "Thread created"));
+ return PJ_SUCCESS;
+#else
+ pj_assert(!"Threading is disabled!");
+ return PJ_EINVALIDOP;
+#endif
+}
+
+/*
+ * pj_thread-get_name()
+ */
+PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p)
+{
+#if PJ_HAS_THREADS
+ pj_thread_t *rec = (pj_thread_t*)p;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(p, "");
+
+ return rec->obj_name;
+#else
+ return "";
+#endif
+}
+
+/*
+ * pj_thread_resume()
+ */
+PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p)
+{
+ pj_status_t rc;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(p, PJ_EINVAL);
+
+ rc = pj_mutex_unlock(p->suspended_mutex);
+
+ return rc;
+}
+
+/*
+ * pj_thread_this()
+ */
+PJ_DEF(pj_thread_t*) pj_thread_this(void)
+{
+#if PJ_HAS_THREADS
+ pj_thread_t *rec = (pj_thread_t*)pj_thread_local_get(thread_tls_id);
+
+ if (rec == NULL) {
+ pj_assert(!"Calling pjlib from unknown/external thread. You must "
+ "register external threads with pj_thread_register() "
+ "before calling any pjlib functions.");
+ }
+
+ /*
+ * MUST NOT check stack because this function is called
+ * by PJ_CHECK_STACK() itself!!!
+ *
+ */
+
+ return rec;
+#else
+ pj_assert(!"Threading is not enabled!");
+ return NULL;
+#endif
+}
+
+/*
+ * pj_thread_join()
+ */
+PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p)
+{
+#if PJ_HAS_THREADS
+ pj_thread_t *rec = (pj_thread_t *)p;
+ void *ret;
+ int result;
+
+ PJ_CHECK_STACK();
+
+ PJ_LOG(6, (pj_thread_this()->obj_name, "Joining thread %s", p->obj_name));
+ result = pthread_join( rec->thread, &ret);
+
+ if (result == 0)
+ return PJ_SUCCESS;
+ else {
+ /* Calling pthread_join() on a thread that no longer exists and
+ * getting back ESRCH isn't an error (in this context).
+ * Thanks Phil Torre <ptorre@zetron.com>.
+ */
+ return result==ESRCH ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(result);
+ }
+#else
+ PJ_CHECK_STACK();
+ pj_assert(!"No multithreading support!");
+ return PJ_EINVALIDOP;
+#endif
+}
+
+/*
+ * pj_thread_destroy()
+ */
+PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *p)
+{
+ PJ_CHECK_STACK();
+
+ /* Destroy mutex used to suspend thread */
+ if (p->suspended_mutex) {
+ pj_mutex_destroy(p->suspended_mutex);
+ p->suspended_mutex = NULL;
+ }
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_thread_sleep()
+ */
+PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec)
+{
+/* TODO: should change this to something like PJ_OS_HAS_NANOSLEEP */
+#if defined(PJ_RTEMS) && PJ_RTEMS!=0
+ enum { NANOSEC_PER_MSEC = 1000000 };
+ struct timespec req;
+
+ PJ_CHECK_STACK();
+ req.tv_sec = msec / 1000;
+ req.tv_nsec = (msec % 1000) * NANOSEC_PER_MSEC;
+
+ if (nanosleep(&req, NULL) == 0)
+ return PJ_SUCCESS;
+
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+ PJ_CHECK_STACK();
+
+ pj_set_os_error(0);
+
+ usleep(msec * 1000);
+
+ /* MacOS X (reported on 10.5) seems to always set errno to ETIMEDOUT.
+ * It does so because usleep() is declared to return int, and we're
+ * supposed to check for errno only when usleep() returns non-zero.
+ * Unfortunately, usleep() is declared to return void in other platforms
+ * so it's not possible to always check for the return value (unless
+ * we add a detection routine in autoconf).
+ *
+ * As a workaround, here we check if ETIMEDOUT is returned and
+ * return successfully if it is.
+ */
+ if (pj_get_native_os_error() == ETIMEDOUT)
+ return PJ_SUCCESS;
+
+ return pj_get_os_error();
+
+#endif /* PJ_RTEMS */
+}
+
+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
+/*
+ * pj_thread_check_stack()
+ * Implementation for PJ_CHECK_STACK()
+ */
+PJ_DEF(void) pj_thread_check_stack(const char *file, int line)
+{
+ char stk_ptr;
+ pj_uint32_t usage;
+ pj_thread_t *thread = pj_thread_this();
+
+ /* Calculate current usage. */
+ usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :
+ thread->stk_start - &stk_ptr;
+
+ /* Assert if stack usage is dangerously high. */
+ pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));
+
+ /* Keep statistic. */
+ if (usage > thread->stk_max_usage) {
+ thread->stk_max_usage = usage;
+ thread->caller_file = file;
+ thread->caller_line = line;
+ }
+}
+
+/*
+ * pj_thread_get_stack_max_usage()
+ */
+PJ_DEF(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread)
+{
+ return thread->stk_max_usage;
+}
+
+/*
+ * pj_thread_get_stack_info()
+ */
+PJ_DEF(pj_status_t) pj_thread_get_stack_info( pj_thread_t *thread,
+ const char **file,
+ int *line )
+{
+ pj_assert(thread);
+
+ *file = thread->caller_file;
+ *line = thread->caller_line;
+ return 0;
+}
+
+#endif /* PJ_OS_HAS_CHECK_STACK */
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * pj_atomic_create()
+ */
+PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,
+ pj_atomic_value_t initial,
+ pj_atomic_t **ptr_atomic)
+{
+ pj_status_t rc;
+ pj_atomic_t *atomic_var;
+
+ atomic_var = PJ_POOL_ZALLOC_T(pool, pj_atomic_t);
+
+ PJ_ASSERT_RETURN(atomic_var, PJ_ENOMEM);
+
+#if PJ_HAS_THREADS
+ rc = pj_mutex_create(pool, "atm%p", PJ_MUTEX_SIMPLE, &atomic_var->mutex);
+ if (rc != PJ_SUCCESS)
+ return rc;
+#endif
+ atomic_var->value = initial;
+
+ *ptr_atomic = atomic_var;
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_atomic_destroy()
+ */
+PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var )
+{
+ PJ_ASSERT_RETURN(atomic_var, PJ_EINVAL);
+#if PJ_HAS_THREADS
+ return pj_mutex_destroy( atomic_var->mutex );
+#else
+ return 0;
+#endif
+}
+
+/*
+ * pj_atomic_set()
+ */
+PJ_DEF(void) pj_atomic_set(pj_atomic_t *atomic_var, pj_atomic_value_t value)
+{
+ PJ_CHECK_STACK();
+
+#if PJ_HAS_THREADS
+ pj_mutex_lock( atomic_var->mutex );
+#endif
+ atomic_var->value = value;
+#if PJ_HAS_THREADS
+ pj_mutex_unlock( atomic_var->mutex);
+#endif
+}
+
+/*
+ * pj_atomic_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
+{
+ pj_atomic_value_t oldval;
+
+ PJ_CHECK_STACK();
+
+#if PJ_HAS_THREADS
+ pj_mutex_lock( atomic_var->mutex );
+#endif
+ oldval = atomic_var->value;
+#if PJ_HAS_THREADS
+ pj_mutex_unlock( atomic_var->mutex);
+#endif
+ return oldval;
+}
+
+/*
+ * pj_atomic_inc_and_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
+{
+ pj_atomic_value_t new_value;
+
+ PJ_CHECK_STACK();
+
+#if PJ_HAS_THREADS
+ pj_mutex_lock( atomic_var->mutex );
+#endif
+ new_value = ++atomic_var->value;
+#if PJ_HAS_THREADS
+ pj_mutex_unlock( atomic_var->mutex);
+#endif
+
+ return new_value;
+}
+/*
+ * pj_atomic_inc()
+ */
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+{
+ pj_atomic_inc_and_get(atomic_var);
+}
+
+/*
+ * pj_atomic_dec_and_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
+{
+ pj_atomic_value_t new_value;
+
+ PJ_CHECK_STACK();
+
+#if PJ_HAS_THREADS
+ pj_mutex_lock( atomic_var->mutex );
+#endif
+ new_value = --atomic_var->value;
+#if PJ_HAS_THREADS
+ pj_mutex_unlock( atomic_var->mutex);
+#endif
+
+ return new_value;
+}
+
+/*
+ * pj_atomic_dec()
+ */
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+{
+ pj_atomic_dec_and_get(atomic_var);
+}
+
+/*
+ * pj_atomic_add_and_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value )
+{
+ pj_atomic_value_t new_value;
+
+#if PJ_HAS_THREADS
+ pj_mutex_lock(atomic_var->mutex);
+#endif
+
+ atomic_var->value += value;
+ new_value = atomic_var->value;
+
+#if PJ_HAS_THREADS
+ pj_mutex_unlock(atomic_var->mutex);
+#endif
+
+ return new_value;
+}
+
+/*
+ * pj_atomic_add()
+ */
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value )
+{
+ pj_atomic_add_and_get(atomic_var, value);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * pj_thread_local_alloc()
+ */
+PJ_DEF(pj_status_t) pj_thread_local_alloc(long *p_index)
+{
+#if PJ_HAS_THREADS
+ pthread_key_t key;
+ int rc;
+
+ PJ_ASSERT_RETURN(p_index != NULL, PJ_EINVAL);
+
+ pj_assert( sizeof(pthread_key_t) <= sizeof(long));
+ if ((rc=pthread_key_create(&key, NULL)) != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+
+ *p_index = key;
+ return PJ_SUCCESS;
+#else
+ int i;
+ for (i=0; i<MAX_THREADS; ++i) {
+ if (tls_flag[i] == 0)
+ break;
+ }
+ if (i == MAX_THREADS)
+ return PJ_ETOOMANY;
+
+ tls_flag[i] = 1;
+ tls[i] = NULL;
+
+ *p_index = i;
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_thread_local_free()
+ */
+PJ_DEF(void) pj_thread_local_free(long index)
+{
+ PJ_CHECK_STACK();
+#if PJ_HAS_THREADS
+ pthread_key_delete(index);
+#else
+ tls_flag[index] = 0;
+#endif
+}
+
+/*
+ * pj_thread_local_set()
+ */
+PJ_DEF(pj_status_t) pj_thread_local_set(long index, void *value)
+{
+ //Can't check stack because this function is called in the
+ //beginning before main thread is initialized.
+ //PJ_CHECK_STACK();
+#if PJ_HAS_THREADS
+ int rc=pthread_setspecific(index, value);
+ return rc==0 ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(rc);
+#else
+ pj_assert(index >= 0 && index < MAX_THREADS);
+ tls[index] = value;
+ return PJ_SUCCESS;
+#endif
+}
+
+PJ_DEF(void*) pj_thread_local_get(long index)
+{
+ //Can't check stack because this function is called
+ //by PJ_CHECK_STACK() itself!!!
+ //PJ_CHECK_STACK();
+#if PJ_HAS_THREADS
+ return pthread_getspecific(index);
+#else
+ pj_assert(index >= 0 && index < MAX_THREADS);
+ return tls[index];
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PJ_DEF(void) pj_enter_critical_section(void)
+{
+#if PJ_HAS_THREADS
+ pj_mutex_lock(&critical_section);
+#endif
+}
+
+PJ_DEF(void) pj_leave_critical_section(void)
+{
+#if PJ_HAS_THREADS
+ pj_mutex_unlock(&critical_section);
+#endif
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+#if defined(PJ_LINUX) && PJ_LINUX!=0
+PJ_BEGIN_DECL
+PJ_DECL(int) pthread_mutexattr_settype(pthread_mutexattr_t*,int);
+PJ_END_DECL
+#endif
+
+static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name, int type)
+{
+#if PJ_HAS_THREADS
+ pthread_mutexattr_t attr;
+ int rc;
+
+ PJ_CHECK_STACK();
+
+ rc = pthread_mutexattr_init(&attr);
+ if (rc != 0)
+ return PJ_RETURN_OS_ERROR(rc);
+
+ if (type == PJ_MUTEX_SIMPLE) {
+#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
+ defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_FAST_NP);
+#elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
+ defined(PJ_PTHREAD_MUTEXATTR_T_HAS_RECURSIVE)
+ /* Nothing to do, default is simple */
+#else
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+#endif
+ } else {
+#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
+ defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+#elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
+ defined(PJ_PTHREAD_MUTEXATTR_T_HAS_RECURSIVE)
+ // Phil Torre <ptorre@zetron.com>:
+ // The RTEMS implementation of POSIX mutexes doesn't include
+ // pthread_mutexattr_settype(), so what follows is a hack
+ // until I get RTEMS patched to support the set/get functions.
+ //
+ // More info:
+ // newlib's pthread also lacks pthread_mutexattr_settype(),
+ // but it seems to have mutexattr.recursive.
+ PJ_TODO(FIX_RTEMS_RECURSIVE_MUTEX_TYPE)
+ attr.recursive = 1;
+#else
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+#endif
+ }
+
+ if (rc != 0) {
+ return PJ_RETURN_OS_ERROR(rc);
+ }
+
+ rc = pthread_mutex_init(&mutex->mutex, &attr);
+ if (rc != 0) {
+ return PJ_RETURN_OS_ERROR(rc);
+ }
+
+ rc = pthread_mutexattr_destroy(&attr);
+ if (rc != 0) {
+ pj_status_t status = PJ_RETURN_OS_ERROR(rc);
+ pthread_mutex_destroy(&mutex->mutex);
+ return status;
+ }
+
+#if PJ_DEBUG
+ /* Set owner. */
+ mutex->nesting_level = 0;
+ mutex->owner = NULL;
+#endif
+
+ /* Set name. */
+ if (!name) {
+ name = "mtx%p";
+ }
+ if (strchr(name, '%')) {
+ pj_ansi_snprintf(mutex->obj_name, PJ_MAX_OBJ_NAME, name, mutex);
+ } else {
+ strncpy(mutex->obj_name, name, PJ_MAX_OBJ_NAME);
+ mutex->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
+ }
+
+ PJ_LOG(6, (mutex->obj_name, "Mutex created"));
+ return PJ_SUCCESS;
+#else /* PJ_HAS_THREADS */
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_mutex_create()
+ */
+PJ_DEF(pj_status_t) pj_mutex_create(pj_pool_t *pool,
+ const char *name,
+ int type,
+ pj_mutex_t **ptr_mutex)
+{
+#if PJ_HAS_THREADS
+ pj_status_t rc;
+ pj_mutex_t *mutex;
+
+ PJ_ASSERT_RETURN(pool && ptr_mutex, PJ_EINVAL);
+
+ mutex = PJ_POOL_ALLOC_T(pool, pj_mutex_t);
+ PJ_ASSERT_RETURN(mutex, PJ_ENOMEM);
+
+ if ((rc=init_mutex(mutex, name, type)) != PJ_SUCCESS)
+ return rc;
+
+ *ptr_mutex = mutex;
+ return PJ_SUCCESS;
+#else /* PJ_HAS_THREADS */
+ *ptr_mutex = (pj_mutex_t*)1;
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_mutex_create_simple()
+ */
+PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool,
+ const char *name,
+ pj_mutex_t **mutex )
+{
+ return pj_mutex_create(pool, name, PJ_MUTEX_SIMPLE, mutex);
+}
+
+/*
+ * pj_mutex_create_recursive()
+ */
+PJ_DEF(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
+ const char *name,
+ pj_mutex_t **mutex )
+{
+ return pj_mutex_create(pool, name, PJ_MUTEX_RECURSE, mutex);
+}
+
+/*
+ * pj_mutex_lock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex)
+{
+#if PJ_HAS_THREADS
+ pj_status_t status;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+#if PJ_DEBUG
+ PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting (mutex owner=%s)",
+ pj_thread_this()->obj_name,
+ mutex->owner_name));
+#else
+ PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting",
+ pj_thread_this()->obj_name));
+#endif
+
+ status = pthread_mutex_lock( &mutex->mutex );
+
+
+#if PJ_DEBUG
+ if (status == PJ_SUCCESS) {
+ mutex->owner = pj_thread_this();
+ pj_ansi_strcpy(mutex->owner_name, mutex->owner->obj_name);
+ ++mutex->nesting_level;
+ }
+
+ PJ_LOG(6,(mutex->obj_name,
+ (status==0 ?
+ "Mutex acquired by thread %s (level=%d)" :
+ "Mutex acquisition FAILED by %s (level=%d)"),
+ pj_thread_this()->obj_name,
+ mutex->nesting_level));
+#else
+ PJ_LOG(6,(mutex->obj_name,
+ (status==0 ? "Mutex acquired by thread %s" : "FAILED by %s"),
+ pj_thread_this()->obj_name));
+#endif
+
+ if (status == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(status);
+#else /* PJ_HAS_THREADS */
+ pj_assert( mutex == (pj_mutex_t*)1 );
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_mutex_unlock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex)
+{
+#if PJ_HAS_THREADS
+ pj_status_t status;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+#if PJ_DEBUG
+ pj_assert(mutex->owner == pj_thread_this());
+ if (--mutex->nesting_level == 0) {
+ mutex->owner = NULL;
+ mutex->owner_name[0] = '\0';
+ }
+
+ PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s (level=%d)",
+ pj_thread_this()->obj_name,
+ mutex->nesting_level));
+#else
+ PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s",
+ pj_thread_this()->obj_name));
+#endif
+
+ status = pthread_mutex_unlock( &mutex->mutex );
+ if (status == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(status);
+
+#else /* PJ_HAS_THREADS */
+ pj_assert( mutex == (pj_mutex_t*)1 );
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_mutex_trylock()
+ */
+PJ_DEF(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex)
+{
+#if PJ_HAS_THREADS
+ int status;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+ PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is trying",
+ pj_thread_this()->obj_name));
+
+ status = pthread_mutex_trylock( &mutex->mutex );
+
+ if (status==0) {
+#if PJ_DEBUG
+ mutex->owner = pj_thread_this();
+ pj_ansi_strcpy(mutex->owner_name, mutex->owner->obj_name);
+ ++mutex->nesting_level;
+
+ PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s (level=%d)",
+ pj_thread_this()->obj_name,
+ mutex->nesting_level));
+#else
+ PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s",
+ pj_thread_this()->obj_name));
+#endif
+ } else {
+ PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s's trylock() failed",
+ pj_thread_this()->obj_name));
+ }
+
+ if (status==0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(status);
+#else /* PJ_HAS_THREADS */
+ pj_assert( mutex == (pj_mutex_t*)1);
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_mutex_destroy()
+ */
+PJ_DEF(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex)
+{
+ enum { RETRY = 4 };
+ int status = 0;
+ unsigned retry;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
+
+#if PJ_HAS_THREADS
+ PJ_LOG(6,(mutex->obj_name, "Mutex destroyed by thread %s",
+ pj_thread_this()->obj_name));
+
+ for (retry=0; retry<RETRY; ++retry) {
+ status = pthread_mutex_destroy( &mutex->mutex );
+ if (status == PJ_SUCCESS)
+ break;
+ else if (retry<RETRY-1 && status == EBUSY)
+ pthread_mutex_unlock(&mutex->mutex);
+ }
+
+ if (status == 0)
+ return PJ_SUCCESS;
+ else {
+ return PJ_RETURN_OS_ERROR(status);
+ }
+#else
+ pj_assert( mutex == (pj_mutex_t*)1 );
+ status = PJ_SUCCESS;
+ return status;
+#endif
+}
+
+#if PJ_DEBUG
+PJ_DEF(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex)
+{
+#if PJ_HAS_THREADS
+ return mutex->owner == pj_thread_this();
+#else
+ return 1;
+#endif
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * Include Read/Write mutex emulation for POSIX platforms that lack it (e.g.
+ * RTEMS). Otherwise use POSIX rwlock.
+ */
+#if defined(PJ_EMULATE_RWMUTEX) && PJ_EMULATE_RWMUTEX!=0
+ /* We need semaphore functionality to emulate rwmutex */
+# if !defined(PJ_HAS_SEMAPHORE) || PJ_HAS_SEMAPHORE==0
+# error "Semaphore support needs to be enabled to emulate rwmutex"
+# endif
+# include "os_rwmutex.c"
+#else
+struct pj_rwmutex_t
+{
+ pthread_rwlock_t rwlock;
+};
+
+PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
+ pj_rwmutex_t **p_mutex)
+{
+ pj_rwmutex_t *rwm;
+ pj_status_t status;
+
+ PJ_UNUSED_ARG(name);
+
+ rwm = PJ_POOL_ALLOC_T(pool, pj_rwmutex_t);
+ PJ_ASSERT_RETURN(rwm, PJ_ENOMEM);
+
+ status = pthread_rwlock_init(&rwm->rwlock, NULL);
+ if (status != 0)
+ return PJ_RETURN_OS_ERROR(status);
+
+ *p_mutex = rwm;
+ return PJ_SUCCESS;
+}
+
+/*
+ * Lock the mutex for reading.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex)
+{
+ pj_status_t status;
+
+ status = pthread_rwlock_rdlock(&mutex->rwlock);
+ if (status != 0)
+ return PJ_RETURN_OS_ERROR(status);
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Lock the mutex for writing.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex)
+{
+ pj_status_t status;
+
+ status = pthread_rwlock_wrlock(&mutex->rwlock);
+ if (status != 0)
+ return PJ_RETURN_OS_ERROR(status);
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Release read lock.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex)
+{
+ return pj_rwmutex_unlock_write(mutex);
+}
+
+/*
+ * Release write lock.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex)
+{
+ pj_status_t status;
+
+ status = pthread_rwlock_unlock(&mutex->rwlock);
+ if (status != 0)
+ return PJ_RETURN_OS_ERROR(status);
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Destroy reader/writer mutex.
+ *
+ */
+PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex)
+{
+ pj_status_t status;
+
+ status = pthread_rwlock_destroy(&mutex->rwlock);
+ if (status != 0)
+ return PJ_RETURN_OS_ERROR(status);
+
+ return PJ_SUCCESS;
+}
+
+#endif /* PJ_EMULATE_RWMUTEX */
+
+
+///////////////////////////////////////////////////////////////////////////////
+#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
+
+/*
+ * pj_sem_create()
+ */
+PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool,
+ const char *name,
+ unsigned initial,
+ unsigned max,
+ pj_sem_t **ptr_sem)
+{
+#if PJ_HAS_THREADS
+ pj_sem_t *sem;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(pool != NULL && ptr_sem != NULL, PJ_EINVAL);
+
+ sem = PJ_POOL_ALLOC_T(pool, pj_sem_t);
+ PJ_ASSERT_RETURN(sem, PJ_ENOMEM);
+
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+ /* MacOS X doesn't support anonymous semaphore */
+ {
+ char sem_name[PJ_GUID_MAX_LENGTH+1];
+ pj_str_t nam;
+
+ /* We should use SEM_NAME_LEN, but this doesn't seem to be
+ * declared anywhere? The value here is just from trial and error
+ * to get the longest name supported.
+ */
+# define MAX_SEM_NAME_LEN 23
+
+ /* Create a unique name for the semaphore. */
+ if (PJ_GUID_STRING_LENGTH <= MAX_SEM_NAME_LEN) {
+ nam.ptr = sem_name;
+ pj_generate_unique_string(&nam);
+ sem_name[nam.slen] = '\0';
+ } else {
+ pj_create_random_string(sem_name, MAX_SEM_NAME_LEN);
+ sem_name[MAX_SEM_NAME_LEN] = '\0';
+ }
+
+ /* Create semaphore */
+ sem->sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR,
+ initial);
+ if (sem->sem == SEM_FAILED)
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+
+ /* And immediately release the name as we don't need it */
+ sem_unlink(sem_name);
+ }
+#else
+ sem->sem = PJ_POOL_ALLOC_T(pool, sem_t);
+ if (sem_init( sem->sem, 0, initial) != 0)
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#endif
+
+ /* Set name. */
+ if (!name) {
+ name = "sem%p";
+ }
+ if (strchr(name, '%')) {
+ pj_ansi_snprintf(sem->obj_name, PJ_MAX_OBJ_NAME, name, sem);
+ } else {
+ strncpy(sem->obj_name, name, PJ_MAX_OBJ_NAME);
+ sem->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';
+ }
+
+ PJ_LOG(6, (sem->obj_name, "Semaphore created"));
+
+ *ptr_sem = sem;
+ return PJ_SUCCESS;
+#else
+ *ptr_sem = (pj_sem_t*)1;
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_sem_wait()
+ */
+PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
+{
+#if PJ_HAS_THREADS
+ int result;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(sem, PJ_EINVAL);
+
+ PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting",
+ pj_thread_this()->obj_name));
+
+ result = sem_wait( sem->sem );
+
+ if (result == 0) {
+ PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s",
+ pj_thread_this()->obj_name));
+ } else {
+ PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s FAILED to acquire",
+ pj_thread_this()->obj_name));
+ }
+
+ if (result == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+ pj_assert( sem == (pj_sem_t*) 1 );
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_sem_trywait()
+ */
+PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
+{
+#if PJ_HAS_THREADS
+ int result;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(sem, PJ_EINVAL);
+
+ result = sem_trywait( sem->sem );
+
+ if (result == 0) {
+ PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s",
+ pj_thread_this()->obj_name));
+ }
+ if (result == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+ pj_assert( sem == (pj_sem_t*)1 );
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_sem_post()
+ */
+PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
+{
+#if PJ_HAS_THREADS
+ int result;
+ PJ_LOG(6, (sem->obj_name, "Semaphore released by thread %s",
+ pj_thread_this()->obj_name));
+ result = sem_post( sem->sem );
+
+ if (result == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+ pj_assert( sem == (pj_sem_t*) 1);
+ return PJ_SUCCESS;
+#endif
+}
+
+/*
+ * pj_sem_destroy()
+ */
+PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
+{
+#if PJ_HAS_THREADS
+ int result;
+
+ PJ_CHECK_STACK();
+ PJ_ASSERT_RETURN(sem, PJ_EINVAL);
+
+ PJ_LOG(6, (sem->obj_name, "Semaphore destroyed by thread %s",
+ pj_thread_this()->obj_name));
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+ result = sem_close( sem->sem );
+#else
+ result = sem_destroy( sem->sem );
+#endif
+
+ if (result == 0)
+ return PJ_SUCCESS;
+ else
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#else
+ pj_assert( sem == (pj_sem_t*) 1 );
+ return PJ_SUCCESS;
+#endif
+}
+
+#endif /* PJ_HAS_SEMAPHORE */
+
+///////////////////////////////////////////////////////////////////////////////
+#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
+
+/*
+ * pj_event_create()
+ */
+PJ_DEF(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,
+ pj_bool_t manual_reset, pj_bool_t initial,
+ pj_event_t **ptr_event)
+{
+ pj_event_t *event;
+
+ event = PJ_POOL_ALLOC_T(pool, pj_event_t);
+
+ init_mutex(&event->mutex, name, PJ_MUTEX_SIMPLE);
+ pthread_cond_init(&event->cond, 0);
+ event->auto_reset = !manual_reset;
+ event->threads_waiting = 0;
+
+ if (initial) {
+ event->state = EV_STATE_SET;
+ event->threads_to_release = 1;
+ } else {
+ event->state = EV_STATE_OFF;
+ event->threads_to_release = 0;
+ }
+
+ *ptr_event = event;
+ return PJ_SUCCESS;
+}
+
+static void event_on_one_release(pj_event_t *event)
+{
+ if (event->state == EV_STATE_SET) {
+ if (event->auto_reset) {
+ event->threads_to_release = 0;
+ event->state = EV_STATE_OFF;
+ } else {
+ /* Manual reset remains on */
+ }
+ } else {
+ if (event->auto_reset) {
+ /* Only release one */
+ event->threads_to_release = 0;
+ event->state = EV_STATE_OFF;
+ } else {
+ event->threads_to_release--;
+ pj_assert(event->threads_to_release >= 0);
+ if (event->threads_to_release==0)
+ event->state = EV_STATE_OFF;
+ }
+ }
+}
+
+/*
+ * pj_event_wait()
+ */
+PJ_DEF(pj_status_t) pj_event_wait(pj_event_t *event)
+{
+ pthread_mutex_lock(&event->mutex.mutex);
+ event->threads_waiting++;
+ while (event->state == EV_STATE_OFF)
+ pthread_cond_wait(&event->cond, &event->mutex.mutex);
+ event->threads_waiting--;
+ event_on_one_release(event);
+ pthread_mutex_unlock(&event->mutex.mutex);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_event_trywait()
+ */
+PJ_DEF(pj_status_t) pj_event_trywait(pj_event_t *event)
+{
+ pj_status_t status;
+
+ pthread_mutex_lock(&event->mutex.mutex);
+ status = event->state != EV_STATE_OFF ? PJ_SUCCESS : -1;
+ if (status==PJ_SUCCESS) {
+ event_on_one_release(event);
+ }
+ pthread_mutex_unlock(&event->mutex.mutex);
+
+ return status;
+}
+
+/*
+ * pj_event_set()
+ */
+PJ_DEF(pj_status_t) pj_event_set(pj_event_t *event)
+{
+ pthread_mutex_lock(&event->mutex.mutex);
+ event->threads_to_release = 1;
+ event->state = EV_STATE_SET;
+ if (event->auto_reset)
+ pthread_cond_signal(&event->cond);
+ else
+ pthread_cond_broadcast(&event->cond);
+ pthread_mutex_unlock(&event->mutex.mutex);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_event_pulse()
+ */
+PJ_DEF(pj_status_t) pj_event_pulse(pj_event_t *event)
+{
+ pthread_mutex_lock(&event->mutex.mutex);
+ if (event->threads_waiting) {
+ event->threads_to_release = event->auto_reset ? 1 :
+ event->threads_waiting;
+ event->state = EV_STATE_PULSED;
+ if (event->threads_to_release==1)
+ pthread_cond_signal(&event->cond);
+ else
+ pthread_cond_broadcast(&event->cond);
+ }
+ pthread_mutex_unlock(&event->mutex.mutex);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_event_reset()
+ */
+PJ_DEF(pj_status_t) pj_event_reset(pj_event_t *event)
+{
+ pthread_mutex_lock(&event->mutex.mutex);
+ event->state = EV_STATE_OFF;
+ event->threads_to_release = 0;
+ pthread_mutex_unlock(&event->mutex.mutex);
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_event_destroy()
+ */
+PJ_DEF(pj_status_t) pj_event_destroy(pj_event_t *event)
+{
+ pj_mutex_destroy(&event->mutex);
+ pthread_cond_destroy(&event->cond);
+ return PJ_SUCCESS;
+}
+
+#endif /* PJ_HAS_EVENT_OBJ */
+
+///////////////////////////////////////////////////////////////////////////////
+#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
+/*
+ * Terminal
+ */
+
+/**
+ * Set terminal color.
+ */
+PJ_DEF(pj_status_t) pj_term_set_color(pj_color_t color)
+{
+ /* put bright prefix to ansi_color */
+ char ansi_color[12] = "\033[01;3";
+
+ if (color & PJ_TERM_COLOR_BRIGHT) {
+ color ^= PJ_TERM_COLOR_BRIGHT;
+ } else {
+ strcpy(ansi_color, "\033[00;3");
+ }
+
+ switch (color) {
+ case 0:
+ /* black color */
+ strcat(ansi_color, "0m");
+ break;
+ case PJ_TERM_COLOR_R:
+ /* red color */
+ strcat(ansi_color, "1m");
+ break;
+ case PJ_TERM_COLOR_G:
+ /* green color */
+ strcat(ansi_color, "2m");
+ break;
+ case PJ_TERM_COLOR_B:
+ /* blue color */
+ strcat(ansi_color, "4m");
+ break;
+ case PJ_TERM_COLOR_R | PJ_TERM_COLOR_G:
+ /* yellow color */
+ strcat(ansi_color, "3m");
+ break;
+ case PJ_TERM_COLOR_R | PJ_TERM_COLOR_B:
+ /* magenta color */
+ strcat(ansi_color, "5m");
+ break;
+ case PJ_TERM_COLOR_G | PJ_TERM_COLOR_B:
+ /* cyan color */
+ strcat(ansi_color, "6m");
+ break;
+ case PJ_TERM_COLOR_R | PJ_TERM_COLOR_G | PJ_TERM_COLOR_B:
+ /* white color */
+ strcat(ansi_color, "7m");
+ break;
+ default:
+ /* default console color */
+ strcpy(ansi_color, "\033[00m");
+ break;
+ }
+
+ fputs(ansi_color, stdout);
+
+ return PJ_SUCCESS;
+}
+
+/**
+ * Get current terminal foreground color.
+ */
+PJ_DEF(pj_color_t) pj_term_get_color(void)
+{
+ return 0;
+}
+
+#endif /* PJ_TERM_HAS_COLOR */
+
+#if !defined(PJ_DARWINOS) || PJ_DARWINOS == 0
+/*
+ * pj_run_app()
+ */
+PJ_DEF(int) pj_run_app(pj_main_func_ptr main_func, int argc, char *argv[],
+ unsigned flags)
+{
+ return (*main_func)(argc, argv);
+}
+#endif
diff --git a/jni/pjproject-android/.svn/pristine/c0/c03d15fba78b2609ec859b84a121be2bda692f35.svn-base b/jni/pjproject-android/.svn/pristine/c0/c03d15fba78b2609ec859b84a121be2bda692f35.svn-base
new file mode 100644
index 0000000..6cfd5a3
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c03d15fba78b2609ec859b84a121be2bda692f35.svn-base
@@ -0,0 +1,176 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+
+ File: buffer.c
+ This is a very simple ring buffer implementation. It is not thread-safe
+ so you need to do your own locking.
+
+ 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.
+
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "os_support.h"
+#include "arch.h"
+#include <speex/speex_buffer.h>
+
+struct SpeexBuffer_ {
+ char *data;
+ int size;
+ int read_ptr;
+ int write_ptr;
+ int available;
+};
+
+EXPORT SpeexBuffer *speex_buffer_init(int size)
+{
+ SpeexBuffer *st = speex_alloc(sizeof(SpeexBuffer));
+ st->data = speex_alloc(size);
+ st->size = size;
+ st->read_ptr = 0;
+ st->write_ptr = 0;
+ st->available = 0;
+ return st;
+}
+
+EXPORT void speex_buffer_destroy(SpeexBuffer *st)
+{
+ speex_free(st->data);
+ speex_free(st);
+}
+
+EXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len)
+{
+ int end;
+ int end1;
+ char *data = _data;
+ if (len > st->size)
+ {
+ data += len-st->size;
+ len = st->size;
+ }
+ end = st->write_ptr + len;
+ end1 = end;
+ if (end1 > st->size)
+ end1 = st->size;
+ SPEEX_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr);
+ if (end > st->size)
+ {
+ end -= st->size;
+ SPEEX_COPY(st->data, data+end1 - st->write_ptr, end);
+ }
+ st->available += len;
+ if (st->available > st->size)
+ {
+ st->available = st->size;
+ st->read_ptr = st->write_ptr;
+ }
+ st->write_ptr += len;
+ if (st->write_ptr > st->size)
+ st->write_ptr -= st->size;
+ return len;
+}
+
+EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len)
+{
+ /* This is almost the same as for speex_buffer_write() but using
+ SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */
+ int end;
+ int end1;
+ if (len > st->size)
+ {
+ len = st->size;
+ }
+ end = st->write_ptr + len;
+ end1 = end;
+ if (end1 > st->size)
+ end1 = st->size;
+ SPEEX_MEMSET(st->data + st->write_ptr, 0, end1 - st->write_ptr);
+ if (end > st->size)
+ {
+ end -= st->size;
+ SPEEX_MEMSET(st->data, 0, end);
+ }
+ st->available += len;
+ if (st->available > st->size)
+ {
+ st->available = st->size;
+ st->read_ptr = st->write_ptr;
+ }
+ st->write_ptr += len;
+ if (st->write_ptr > st->size)
+ st->write_ptr -= st->size;
+ return len;
+}
+
+EXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len)
+{
+ int end, end1;
+ char *data = _data;
+ if (len > st->available)
+ {
+ SPEEX_MEMSET(data+st->available, 0, st->size-st->available);
+ len = st->available;
+ }
+ end = st->read_ptr + len;
+ end1 = end;
+ if (end1 > st->size)
+ end1 = st->size;
+ SPEEX_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr);
+
+ if (end > st->size)
+ {
+ end -= st->size;
+ SPEEX_COPY(data+end1 - st->read_ptr, st->data, end);
+ }
+ st->available -= len;
+ st->read_ptr += len;
+ if (st->read_ptr > st->size)
+ st->read_ptr -= st->size;
+ return len;
+}
+
+EXPORT int speex_buffer_get_available(SpeexBuffer *st)
+{
+ return st->available;
+}
+
+EXPORT int speex_buffer_resize(SpeexBuffer *st, int len)
+{
+ int old_len = st->size;
+ if (len > old_len)
+ {
+ st->data = speex_realloc(st->data, len);
+ /* FIXME: move data/pointers properly for growing the buffer */
+ } else {
+ /* FIXME: move data/pointers properly for shrinking the buffer */
+ st->data = speex_realloc(st->data, len);
+ }
+ return len;
+}
diff --git a/jni/pjproject-android/.svn/pristine/c0/c04ab7fdfc2cc95f000a0d1e339e8d95c29a6d6e.svn-base b/jni/pjproject-android/.svn/pristine/c0/c04ab7fdfc2cc95f000a0d1e339e8d95c29a6d6e.svn-base
new file mode 100644
index 0000000..fa128b6
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c04ab7fdfc2cc95f000a0d1e339e8d95c29a6d6e.svn-base
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+ "Callee=optional SRTP, caller=no SRTP",
+ [
+ InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"),
+ InstanceParam("caller", "--null-audio --max-calls=1")
+ ]
+ )
diff --git a/jni/pjproject-android/.svn/pristine/c0/c058f799da1e9c6a98763be2ec3e1802b616c69e.svn-base b/jni/pjproject-android/.svn/pristine/c0/c058f799da1e9c6a98763be2ec3e1802b616c69e.svn-base
new file mode 100644
index 0000000..ae9cf83
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c058f799da1e9c6a98763be2ec3e1802b616c69e.svn-base
@@ -0,0 +1,112 @@
+/* Copyright (C) 2005 Analog Devices */
+/**
+ @author Jean-Marc Valin
+ @file cb_search_bfin.h
+ @brief Fixed codebook functions (Blackfin version)
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ - Neither the name of the Xiph.org Foundation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ 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 FOUNDATION 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.
+*/
+
+#define OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK
+void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack)
+{
+ int i;
+ for (i=0;i<shape_cb_size;i++)
+ {
+ __asm__ __volatile__ (
+ "P0 = %0;\n\t"
+ "LC0 = P0;\n\t"
+ "P1 = %1;\n\t"
+ "P2 = %2;\n\t"
+ "P3 = %3;\n\t"
+ "P0 = 1;\n\t"
+ "L0 = 0;\n\t"
+ "L1 = 0;\n\t"
+ "R2 = 0;\n\t"
+ "A1 = 0;\n\t"
+ "LOOP outter%= LC0;\n\t"
+ "LOOP_BEGIN outter%=;\n\t"
+ "A0 = 0;\n\t"
+ "P4 = P1;\n\t"
+ "I1 = P2;\n\t"
+ "R0 = B[P4++] (X) || R1.L = W[I1--];\n\t"
+ "LOOP inner%= LC1 = P0;\n\t"
+ "LOOP_BEGIN inner%=;\n\t"
+ "A0 += R0.L*R1.L (IS) || R0 = B[P4++] (X) || R1.L = W[I1--];\n\t"
+ "LOOP_END inner%=;\n\t"
+ "R0 = A0;\n\t"
+ "R0 >>>= 13;\n\t"
+ "A1 += R0.L*R0.L (IS);\n\t"
+ "W[P3++] = R0;\n\t"
+ "P0 += 1;\n\t"
+ "P2 += 2;\n\t"
+ "LOOP_END outter%=;\n\t"
+ "P4 = %4;\n\t"
+ "R1 = A1;\n\t"
+ "[P4] = R1;\n\t"
+ :
+ : "m" (subvect_size), "m" (shape_cb), "m" (r), "m" (resp), "m" (E)
+ : "A0", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "I0", "I1", "L0",
+ "L1", "A0", "A1", "memory"
+#if !(__GNUC__ == 3)
+ , "LC0", "LC1" /* gcc 3.4 doesn't know about LC registers */
+#endif
+ );
+ shape_cb += subvect_size;
+ resp += subvect_size;
+ E++;
+ }
+}
+
+#define OVERRIDE_TARGET_UPDATE
+static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len)
+{
+ if (!len)
+ return;
+ __asm__ __volatile__
+ (
+ "I0 = %0;\n\t"
+ "I1 = %1;\n\t"
+ "L0 = 0;\n\t"
+ "L1 = 0;\n\t"
+ "R2 = 4096;\n\t"
+ "LOOP tupdate%= LC0 = %3;\n\t"
+ "LOOP_BEGIN tupdate%=;\n\t"
+ "R0.L = W[I0] || R1.L = W[I1++];\n\t"
+ "R1 = (A1 = R1.L*%2.L) (IS);\n\t"
+ "R1 = R1 + R2;\n\t"
+ "R1 >>>= 13;\n\t"
+ "R0.L = R0.L - R1.L;\n\t"
+ "W[I0++] = R0.L;\n\t"
+ "LOOP_END tupdate%=;\n\t"
+ :
+ : "a" (t), "a" (r), "d" (g), "a" (len)
+ : "R0", "R1", "R2", "A1", "I0", "I1", "L0", "L1"
+ );
+}
diff --git a/jni/pjproject-android/.svn/pristine/c0/c0684132ddb0a58573e1fda83efd5d7c28838044.svn-base b/jni/pjproject-android/.svn/pristine/c0/c0684132ddb0a58573e1fda83efd5d7c28838044.svn-base
new file mode 100644
index 0000000..81985c0
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c0684132ddb0a58573e1fda83efd5d7c28838044.svn-base
@@ -0,0 +1,310 @@
+
+ /******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBC_test.c
+
+ Copyright (C) The Internet Society (2004).
+ All Rights Reserved.
+
+ ******************************************************************/
+
+ #include <math.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include "iLBC_define.h"
+ #include "iLBC_encode.h"
+ #include "iLBC_decode.h"
+
+ /* Runtime statistics */
+ #include <time.h>
+
+ #define ILBCNOOFWORDS_MAX (NO_OF_BYTES_30MS/2)
+
+ /*----------------------------------------------------------------*
+ * Encoder interface function
+
+
+
+
+
+ *---------------------------------------------------------------*/
+
+ short encode( /* (o) Number of bytes encoded */
+ iLBC_Enc_Inst_t *iLBCenc_inst,
+ /* (i/o) Encoder instance */
+ short *encoded_data, /* (o) The encoded bytes */
+ short *data /* (i) The signal block to encode*/
+ ){
+ float block[BLOCKL_MAX];
+ int k;
+
+ /* convert signal to float */
+
+ for (k=0; k<iLBCenc_inst->blockl; k++)
+ block[k] = (float)data[k];
+
+ /* do the actual encoding */
+
+ iLBC_encode((unsigned char *)encoded_data, block, iLBCenc_inst);
+
+
+ return (iLBCenc_inst->no_of_bytes);
+ }
+
+ /*----------------------------------------------------------------*
+ * Decoder interface function
+ *---------------------------------------------------------------*/
+
+ short decode( /* (o) Number of decoded samples */
+ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */
+ short *decoded_data, /* (o) Decoded signal block*/
+ short *encoded_data, /* (i) Encoded bytes */
+ short mode /* (i) 0=PL, 1=Normal */
+ ){
+ int k;
+ float decblock[BLOCKL_MAX], dtmp;
+
+ /* check if mode is valid */
+
+ if (mode<0 || mode>1) {
+ printf("\nERROR - Wrong mode - 0, 1 allowed\n"); exit(3);}
+
+ /* do actual decoding of block */
+
+ iLBC_decode(decblock, (unsigned char *)encoded_data,
+ iLBCdec_inst, mode);
+
+ /* convert to short */
+
+
+
+
+
+ for (k=0; k<iLBCdec_inst->blockl; k++){
+ dtmp=decblock[k];
+
+ if (dtmp<MIN_SAMPLE)
+ dtmp=MIN_SAMPLE;
+ else if (dtmp>MAX_SAMPLE)
+ dtmp=MAX_SAMPLE;
+ decoded_data[k] = (short) dtmp;
+ }
+
+ return (iLBCdec_inst->blockl);
+ }
+
+ /*---------------------------------------------------------------*
+ * Main program to test iLBC encoding and decoding
+ *
+ * Usage:
+ * exefile_name.exe <infile> <bytefile> <outfile> <channel>
+ *
+ * <infile> : Input file, speech for encoder (16-bit pcm file)
+ * <bytefile> : Bit stream output from the encoder
+ * <outfile> : Output file, decoded speech (16-bit pcm file)
+ * <channel> : Bit error file, optional (16-bit)
+ * 1 - Packet received correctly
+ * 0 - Packet Lost
+ *
+ *--------------------------------------------------------------*/
+
+ int main(int argc, char* argv[])
+ {
+
+ /* Runtime statistics */
+
+ float starttime;
+ float runtime;
+ float outtime;
+
+ FILE *ifileid,*efileid,*ofileid, *cfileid;
+ short data[BLOCKL_MAX];
+ short encoded_data[ILBCNOOFWORDS_MAX], decoded_data[BLOCKL_MAX];
+ int len;
+ short pli, mode;
+ int blockcount = 0;
+ int packetlosscount = 0;
+
+ /* Create structs */
+ iLBC_Enc_Inst_t Enc_Inst;
+ iLBC_Dec_Inst_t Dec_Inst;
+
+
+
+
+
+ /* get arguments and open files */
+
+ if ((argc!=5) && (argc!=6)) {
+ fprintf(stderr,
+ "\n*-----------------------------------------------*\n");
+ fprintf(stderr,
+ " %s <20,30> input encoded decoded (channel)\n\n",
+ argv[0]);
+ fprintf(stderr,
+ " mode : Frame size for the encoding/decoding\n");
+ fprintf(stderr,
+ " 20 - 20 ms\n");
+ fprintf(stderr,
+ " 30 - 30 ms\n");
+ fprintf(stderr,
+ " input : Speech for encoder (16-bit pcm file)\n");
+ fprintf(stderr,
+ " encoded : Encoded bit stream\n");
+ fprintf(stderr,
+ " decoded : Decoded speech (16-bit pcm file)\n");
+ fprintf(stderr,
+ " channel : Packet loss pattern, optional (16-bit)\n");
+ fprintf(stderr,
+ " 1 - Packet received correctly\n");
+ fprintf(stderr,
+ " 0 - Packet Lost\n");
+ fprintf(stderr,
+ "*-----------------------------------------------*\n\n");
+ exit(1);
+ }
+ mode=atoi(argv[1]);
+ if (mode != 20 && mode != 30) {
+ fprintf(stderr,"Wrong mode %s, must be 20, or 30\n",
+ argv[1]);
+ exit(2);
+ }
+ if ( (ifileid=fopen(argv[2],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open input file %s\n", argv[2]);
+ exit(2);}
+ if ( (efileid=fopen(argv[3],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open encoded file %s\n",
+ argv[3]); exit(1);}
+ if ( (ofileid=fopen(argv[4],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open decoded file %s\n",
+ argv[4]); exit(1);}
+ if (argc==6) {
+ if( (cfileid=fopen(argv[5],"rb")) == NULL) {
+ fprintf(stderr, "Cannot open channel file %s\n",
+
+
+
+
+
+ argv[5]);
+ exit(1);
+ }
+ } else {
+ cfileid=NULL;
+ }
+
+ /* print info */
+
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* iLBC test program *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,"\nMode : %2d ms\n", mode);
+ fprintf(stderr,"Input file : %s\n", argv[2]);
+ fprintf(stderr,"Encoded file : %s\n", argv[3]);
+ fprintf(stderr,"Output file : %s\n", argv[4]);
+ if (argc==6) {
+ fprintf(stderr,"Channel file : %s\n", argv[5]);
+ }
+ fprintf(stderr,"\n");
+
+ /* Initialization */
+
+ initEncode(&Enc_Inst, mode);
+ initDecode(&Dec_Inst, mode, 1);
+
+ /* Runtime statistics */
+
+ starttime=clock()/(float)CLOCKS_PER_SEC;
+
+ /* loop over input blocks */
+
+ while (fread(data,sizeof(short),Enc_Inst.blockl,ifileid)==
+ (size_t)Enc_Inst.blockl) {
+
+ blockcount++;
+
+ /* encoding */
+
+
+
+
+
+ fprintf(stderr, "--- Encoding block %i --- ",blockcount);
+ len=encode(&Enc_Inst, encoded_data, data);
+ fprintf(stderr, "\r");
+
+ /* write byte file */
+
+ fwrite(encoded_data, sizeof(unsigned char), len, efileid);
+
+ /* get channel data if provided */
+ if (argc==6) {
+ if (fread(&pli, sizeof(short), 1, cfileid)) {
+ if ((pli!=0)&&(pli!=1)) {
+ fprintf(stderr, "Error in channel file\n");
+ exit(0);
+ }
+ if (pli==0) {
+ /* Packet loss -> remove info from frame */
+ memset(encoded_data, 0,
+ sizeof(short)*ILBCNOOFWORDS_MAX);
+ packetlosscount++;
+ }
+ } else {
+ fprintf(stderr, "Error. Channel file too short\n");
+ exit(0);
+ }
+ } else {
+ pli=1;
+ }
+
+ /* decoding */
+
+ fprintf(stderr, "--- Decoding block %i --- ",blockcount);
+
+ len=decode(&Dec_Inst, decoded_data, encoded_data, pli);
+ fprintf(stderr, "\r");
+
+ /* write output file */
+
+ fwrite(decoded_data,sizeof(short),len,ofileid);
+ }
+
+ /* Runtime statistics */
+
+ runtime = (float)(clock()/(float)CLOCKS_PER_SEC-starttime);
+ outtime = (float)((float)blockcount*(float)mode/1000.0);
+ printf("\n\nLength of speech file: %.1f s\n", outtime);
+ printf("Packet loss : %.1f%%\n",
+ 100.0*(float)packetlosscount/(float)blockcount);
+
+
+
+
+
+ printf("Time to run iLBC :");
+ printf(" %.1f s (%.1f %% of realtime)\n\n", runtime,
+ (100*runtime/outtime));
+
+ /* close files */
+
+ fclose(ifileid); fclose(efileid); fclose(ofileid);
+ if (argc==6) {
+ fclose(cfileid);
+ }
+ return(0);
+ }
+
diff --git a/jni/pjproject-android/.svn/pristine/c0/c0a5700d902be76ad8d726b2ffe9ffac0e2c760a.svn-base b/jni/pjproject-android/.svn/pristine/c0/c0a5700d902be76ad8d726b2ffe9ffac0e2c760a.svn-base
new file mode 100644
index 0000000..93be0a8
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c0a5700d902be76ad8d726b2ffe9ffac0e2c760a.svn-base
@@ -0,0 +1,587 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsip.h>
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+
+/* Options */
+static struct global_struct
+{
+ pj_caching_pool cp;
+ pjsip_endpoint *endpt;
+ int port;
+ pj_pool_t *pool;
+
+ pj_thread_t *thread;
+ pj_bool_t quit_flag;
+
+ pj_bool_t record_route;
+
+ unsigned name_cnt;
+ pjsip_host_port name[16];
+} global;
+
+
+
+static void app_perror(const char *msg, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(THIS_FILE, "%s: %s", msg, errmsg));
+}
+
+
+static void usage(void)
+{
+ puts("Options:\n"
+ "\n"
+ " -p, --port N Set local listener port to N\n"
+ " -R, --rr Perform record routing\n"
+ " -L, --log-level N Set log level to N (default: 4)\n"
+ " -h, --help Show this help screen\n"
+ );
+}
+
+
+static pj_status_t init_options(int argc, char *argv[])
+{
+ struct pj_getopt_option long_opt[] = {
+ { "port", 1, 0, 'p'},
+ { "rr", 0, 0, 'R'},
+ { "log-level", 1, 0, 'L'},
+ { "help", 0, 0, 'h'},
+ { NULL, 0, 0, 0}
+ };
+ int c;
+ int opt_ind;
+
+ pj_optind = 0;
+ while((c=pj_getopt_long(argc, argv, "p:L:Rh", long_opt, &opt_ind))!=-1) {
+ switch (c) {
+ case 'p':
+ global.port = atoi(pj_optarg);
+ printf("Port is set to %d\n", global.port);
+ break;
+
+ case 'R':
+ global.record_route = PJ_TRUE;
+ printf("Using record route mode\n");
+ break;
+
+ case 'L':
+ pj_log_set_level(atoi(pj_optarg));
+ break;
+
+ case 'h':
+ usage();
+ return -1;
+
+ default:
+ puts("Unknown option. Run with --help for help.");
+ return -1;
+ }
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This is a very simple PJSIP module, whose sole purpose is to display
+ * incoming and outgoing messages to log. This module will have priority
+ * higher than transport layer, which means:
+ *
+ * - incoming messages will come to this module first before reaching
+ * transaction layer.
+ *
+ * - outgoing messages will come to this module last, after the message
+ * has been 'printed' to contiguous buffer by transport layer and
+ * appropriate transport instance has been decided for this message.
+ *
+ */
+
+/* Notification on incoming messages */
+static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module mod_msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-msg-logger", 14 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logging_on_rx_msg, /* on_rx_request() */
+ &logging_on_rx_msg, /* on_rx_response() */
+ &logging_on_tx_msg, /* on_tx_request. */
+ &logging_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+static pj_status_t init_stack(void)
+{
+ pj_status_t status;
+
+ /* Must init PJLIB first: */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Then init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+
+ /* Must create a pool factory before we can allocate any memory. */
+ pj_caching_pool_init(&global.cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create the endpoint: */
+ status = pjsip_endpt_create(&global.cp.factory, NULL, &global.endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ /* Init transaction layer for stateful proxy only */
+#if STATEFUL
+ status = pjsip_tsx_layer_init_module(global.endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
+ /* Create listening transport */
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = pj_AF_INET();
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons((pj_uint16_t)global.port);
+
+ status = pjsip_udp_transport_start( global.endpt, &addr,
+ NULL, 1, NULL);
+ if (status != PJ_SUCCESS)
+ return status;
+ }
+
+ /* Create pool for the application */
+ global.pool = pj_pool_create(&global.cp.factory, "proxyapp",
+ 4000, 4000, NULL);
+
+ /* Register the logger module */
+ pjsip_endpt_register_module(global.endpt, &mod_msg_logger);
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t init_proxy(void)
+{
+ pj_sockaddr pri_addr;
+ pj_sockaddr addr_list[16];
+ unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list);
+ unsigned i;
+
+ /* List all names matching local endpoint.
+ * Note that PJLIB version 0.6 and newer has a function to
+ * enumerate local IP interface (pj_enum_ip_interface()), so
+ * by using it would be possible to list all IP interfaces in
+ * this host.
+ */
+
+ /* The first address is important since this would be the one
+ * to be added in Record-Route.
+ */
+ if (pj_gethostip(pj_AF_INET(), &pri_addr)==PJ_SUCCESS) {
+ pj_strdup2(global.pool, &global.name[global.name_cnt].host,
+ pj_inet_ntoa(pri_addr.ipv4.sin_addr));
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+ }
+
+ /* Get the rest of IP interfaces */
+ if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS) {
+ for (i=0; i<addr_cnt; ++i) {
+
+ if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr)
+ continue;
+
+ pj_strdup2(global.pool, &global.name[global.name_cnt].host,
+ pj_inet_ntoa(addr_list[i].ipv4.sin_addr));
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+ }
+ }
+
+ /* Add loopback address. */
+#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
+ global.name[global.name_cnt].host = pj_str("127.0.0.1");
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+#endif
+
+ global.name[global.name_cnt].host = *pj_gethostname();
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+
+ global.name[global.name_cnt].host = pj_str("localhost");
+ global.name[global.name_cnt].port = global.port;
+ global.name_cnt++;
+
+ PJ_LOG(3,(THIS_FILE, "Proxy started, listening on port %d", global.port));
+ PJ_LOG(3,(THIS_FILE, "Local host aliases:"));
+ for (i=0; i<global.name_cnt; ++i) {
+ PJ_LOG(3,(THIS_FILE, " %.*s:%d",
+ (int)global.name[i].host.slen,
+ global.name[i].host.ptr,
+ global.name[i].port));
+ }
+
+ if (global.record_route) {
+ PJ_LOG(3,(THIS_FILE, "Using Record-Route mode"));
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+#if PJ_HAS_THREADS
+static int worker_thread(void *p)
+{
+ pj_time_val delay = {0, 10};
+
+ PJ_UNUSED_ARG(p);
+
+ while (!global.quit_flag) {
+ pjsip_endpt_handle_events(global.endpt, &delay);
+ }
+
+ return 0;
+}
+#endif
+
+
+/* Utility to determine if URI is local to this host. */
+static pj_bool_t is_uri_local(const pjsip_sip_uri *uri)
+{
+ unsigned i;
+ for (i=0; i<global.name_cnt; ++i) {
+ if ((uri->port == global.name[i].port ||
+ (uri->port==0 && global.name[i].port==5060)) &&
+ pj_stricmp(&uri->host, &global.name[i].host)==0)
+ {
+ /* Match */
+ return PJ_TRUE;
+ }
+ }
+
+ /* Doesn't match */
+ return PJ_FALSE;
+}
+
+
+/* Proxy utility to verify incoming requests.
+ * Return non-zero if verification failed.
+ */
+static pj_status_t proxy_verify_request(pjsip_rx_data *rdata)
+{
+ const pj_str_t STR_PROXY_REQUIRE = {"Proxy-Require", 13};
+
+ /* RFC 3261 Section 16.3 Request Validation */
+
+ /* Before an element can proxy a request, it MUST verify the message's
+ * validity. A valid message must pass the following checks:
+ *
+ * 1. Reasonable Syntax
+ * 2. URI scheme
+ * 3. Max-Forwards
+ * 4. (Optional) Loop Detection
+ * 5. Proxy-Require
+ * 6. Proxy-Authorization
+ */
+
+ /* 1. Reasonable Syntax.
+ * This would have been checked by transport layer.
+ */
+
+ /* 2. URI scheme.
+ * We only want to support "sip:"/"sips:" URI scheme for this simple proxy.
+ */
+ if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.msg->line.req.uri) &&
+ !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri))
+ {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_UNSUPPORTED_URI_SCHEME, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_UNSUPPORTED_URI_SCHEME);
+ }
+
+ /* 3. Max-Forwards.
+ * Send error if Max-Forwards is 1 or lower.
+ */
+ if (rdata->msg_info.max_fwd && rdata->msg_info.max_fwd->ivalue <= 1) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_TOO_MANY_HOPS, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TOO_MANY_HOPS);
+ }
+
+ /* 4. (Optional) Loop Detection.
+ * Nah, we don't do that with this simple proxy.
+ */
+
+ /* 5. Proxy-Require */
+ if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_PROXY_REQUIRE,
+ NULL) != NULL)
+ {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_BAD_EXTENSION, NULL,
+ NULL, NULL);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION);
+ }
+
+ /* 6. Proxy-Authorization.
+ * Nah, we don't require any authorization with this sample.
+ */
+
+ return PJ_SUCCESS;
+}
+
+
+/* Process route information in the reqeust */
+static pj_status_t proxy_process_routing(pjsip_tx_data *tdata)
+{
+ pjsip_sip_uri *target;
+ pjsip_route_hdr *hroute;
+
+ /* RFC 3261 Section 16.4 Route Information Preprocessing */
+
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+
+ /* The proxy MUST inspect the Request-URI of the request. If the
+ * Request-URI of the request contains a value this proxy previously
+ * placed into a Record-Route header field (see Section 16.6 item 4),
+ * the proxy MUST replace the Request-URI in the request with the last
+ * value from the Route header field, and remove that value from the
+ * Route header field. The proxy MUST then proceed as if it received
+ * this modified request.
+ */
+ if (is_uri_local(target)) {
+ pjsip_route_hdr *r;
+ pjsip_sip_uri *uri;
+
+ /* Find the first Route header */
+ r = hroute = (pjsip_route_hdr*)
+ pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
+ if (r == NULL) {
+ /* No Route header. This request is destined for this proxy. */
+ return PJ_SUCCESS;
+ }
+
+ /* Find the last Route header */
+ while ( (r=(pjsip_route_hdr*)pjsip_msg_find_hdr(tdata->msg,
+ PJSIP_H_ROUTE,
+ r->next)) != NULL )
+ {
+ hroute = r;
+ }
+
+ /* If the last Route header doesn't have ";lr" parameter, then
+ * this is a strict-routed request indeed, and we follow the steps
+ * in processing strict-route requests above.
+ *
+ * But if it does contain ";lr" parameter, skip the strict-route
+ * processing.
+ */
+ uri = (pjsip_sip_uri*)
+ pjsip_uri_get_uri(&hroute->name_addr);
+ if (uri->lr_param == 0) {
+ /* Yes this is strict route, so:
+ * - replace req URI with the URI in Route header,
+ * - remove the Route header,
+ * - proceed as if it received this modified request.
+ */
+ tdata->msg->line.req.uri = hroute->name_addr.uri;
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+ pj_list_erase(hroute);
+ }
+ }
+
+ /* If the Request-URI contains a maddr parameter, the proxy MUST check
+ * to see if its value is in the set of addresses or domains the proxy
+ * is configured to be responsible for. If the Request-URI has a maddr
+ * parameter with a value the proxy is responsible for, and the request
+ * was received using the port and transport indicated (explicitly or by
+ * default) in the Request-URI, the proxy MUST strip the maddr and any
+ * non-default port or transport parameter and continue processing as if
+ * those values had not been present in the request.
+ */
+ if (target->maddr_param.slen != 0) {
+ pjsip_sip_uri maddr_uri;
+
+ maddr_uri.host = target->maddr_param;
+ maddr_uri.port = global.port;
+
+ if (is_uri_local(&maddr_uri)) {
+ target->maddr_param.slen = 0;
+ target->port = 0;
+ target->transport_param.slen = 0;
+ }
+ }
+
+ /* If the first value in the Route header field indicates this proxy,
+ * the proxy MUST remove that value from the request.
+ */
+ hroute = (pjsip_route_hdr*)
+ pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);
+ if (hroute && is_uri_local((pjsip_sip_uri*)hroute->name_addr.uri)) {
+ pj_list_erase(hroute);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/* Postprocess the request before forwarding it */
+static void proxy_postprocess(pjsip_tx_data *tdata)
+{
+ /* Optionally record-route */
+ if (global.record_route) {
+ char uribuf[128];
+ pj_str_t uri;
+ const pj_str_t H_RR = { "Record-Route", 12 };
+ pjsip_generic_string_hdr *rr;
+
+ pj_ansi_snprintf(uribuf, sizeof(uribuf), "<sip:%.*s:%d;lr>",
+ (int)global.name[0].host.slen,
+ global.name[0].host.ptr,
+ global.name[0].port);
+ uri = pj_str(uribuf);
+ rr = pjsip_generic_string_hdr_create(tdata->pool,
+ &H_RR, &uri);
+ pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)rr);
+ }
+}
+
+
+/* Calculate new target for the request */
+static pj_status_t proxy_calculate_target(pjsip_rx_data *rdata,
+ pjsip_tx_data *tdata)
+{
+ pjsip_sip_uri *target;
+
+ /* RFC 3261 Section 16.5 Determining Request Targets */
+
+ target = (pjsip_sip_uri*) tdata->msg->line.req.uri;
+
+ /* If the Request-URI of the request contains an maddr parameter, the
+ * Request-URI MUST be placed into the target set as the only target
+ * URI, and the proxy MUST proceed to Section 16.6.
+ */
+ if (target->maddr_param.slen) {
+ proxy_postprocess(tdata);
+ return PJ_SUCCESS;
+ }
+
+
+ /* If the domain of the Request-URI indicates a domain this element is
+ * not responsible for, the Request-URI MUST be placed into the target
+ * set as the only target, and the element MUST proceed to the task of
+ * Request Forwarding (Section 16.6).
+ */
+ if (!is_uri_local(target)) {
+ proxy_postprocess(tdata);
+ return PJ_SUCCESS;
+ }
+
+ /* If the target set for the request has not been predetermined as
+ * described above, this implies that the element is responsible for the
+ * domain in the Request-URI, and the element MAY use whatever mechanism
+ * it desires to determine where to send the request.
+ */
+
+ /* We're not interested to receive request destined to us, so
+ * respond with 404/Not Found (only if request is not ACK!).
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ pjsip_endpt_respond_stateless(global.endpt, rdata,
+ PJSIP_SC_NOT_FOUND, NULL,
+ NULL, NULL);
+ }
+
+ /* Delete the request since we're not forwarding it */
+ pjsip_tx_data_dec_ref(tdata);
+
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_FOUND);
+}
+
+
+/* Destroy stack */
+static void destroy_stack(void)
+{
+ pjsip_endpt_destroy(global.endpt);
+ pj_pool_release(global.pool);
+ pj_caching_pool_destroy(&global.cp);
+
+ pj_shutdown();
+}
+
diff --git a/jni/pjproject-android/.svn/pristine/c0/c0d071c727381f84cfd788bebdba1be9168686f4.svn-base b/jni/pjproject-android/.svn/pristine/c0/c0d071c727381f84cfd788bebdba1be9168686f4.svn-base
new file mode 100644
index 0000000..d7a68cd
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c0d071c727381f84cfd788bebdba1be9168686f4.svn-base
@@ -0,0 +1,170 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pj/file_io.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <stdio.h>
+#include <errno.h>
+
+PJ_DEF(pj_status_t) pj_file_open( pj_pool_t *pool,
+ const char *pathname,
+ unsigned flags,
+ pj_oshandle_t *fd)
+{
+ char mode[8];
+ char *p = mode;
+
+ PJ_ASSERT_RETURN(pathname && fd, PJ_EINVAL);
+ PJ_UNUSED_ARG(pool);
+
+ if ((flags & PJ_O_APPEND) == PJ_O_APPEND) {
+ if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) {
+ *p++ = 'a';
+ if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY)
+ *p++ = '+';
+ } else {
+ /* This is invalid.
+ * Can not specify PJ_O_RDONLY with PJ_O_APPEND!
+ */
+ }
+ } else {
+ if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
+ *p++ = 'r';
+ if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY)
+ *p++ = '+';
+ } else {
+ *p++ = 'w';
+ }
+ }
+
+ if (p==mode)
+ return PJ_EINVAL;
+
+ *p++ = 'b';
+ *p++ = '\0';
+
+ *fd = fopen(pathname, mode);
+ if (*fd == NULL)
+ return PJ_RETURN_OS_ERROR(errno);
+
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd)
+{
+ PJ_ASSERT_RETURN(fd, PJ_EINVAL);
+ if (fclose((FILE*)fd) != 0)
+ return PJ_RETURN_OS_ERROR(errno);
+
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd,
+ const void *data,
+ pj_ssize_t *size)
+{
+ size_t written;
+
+ clearerr((FILE*)fd);
+ written = fwrite(data, 1, *size, (FILE*)fd);
+ if (ferror((FILE*)fd)) {
+ *size = -1;
+ return PJ_RETURN_OS_ERROR(errno);
+ }
+
+ *size = written;
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd,
+ void *data,
+ pj_ssize_t *size)
+{
+ size_t bytes;
+
+ clearerr((FILE*)fd);
+ bytes = fread(data, 1, *size, (FILE*)fd);
+ if (ferror((FILE*)fd)) {
+ *size = -1;
+ return PJ_RETURN_OS_ERROR(errno);
+ }
+
+ *size = bytes;
+ return PJ_SUCCESS;
+}
+
+/*
+PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
+{
+ PJ_UNUSED_ARG(access);
+ return feof((FILE*)fd) ? PJ_TRUE : 0;
+}
+*/
+
+PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd,
+ pj_off_t offset,
+ enum pj_file_seek_type whence)
+{
+ int mode;
+
+ switch (whence) {
+ case PJ_SEEK_SET:
+ mode = SEEK_SET; break;
+ case PJ_SEEK_CUR:
+ mode = SEEK_CUR; break;
+ case PJ_SEEK_END:
+ mode = SEEK_END; break;
+ default:
+ pj_assert(!"Invalid whence in file_setpos");
+ return PJ_EINVAL;
+ }
+
+ if (fseek((FILE*)fd, (long)offset, mode) != 0)
+ return PJ_RETURN_OS_ERROR(errno);
+
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd,
+ pj_off_t *pos)
+{
+ long offset;
+
+ offset = ftell((FILE*)fd);
+ if (offset == -1) {
+ *pos = -1;
+ return PJ_RETURN_OS_ERROR(errno);
+ }
+
+ *pos = offset;
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_file_flush(pj_oshandle_t fd)
+{
+ int rc;
+
+ rc = fflush((FILE*)fd);
+ if (rc == EOF) {
+ return PJ_RETURN_OS_ERROR(errno);
+ }
+
+ return PJ_SUCCESS;
+}
diff --git a/jni/pjproject-android/.svn/pristine/c0/c0dd8052eb7d05dc0c0a892e15b459d2bd64433e.svn-base b/jni/pjproject-android/.svn/pristine/c0/c0dd8052eb7d05dc0c0a892e15b459d2bd64433e.svn-base
new file mode 100644
index 0000000..2b64c30
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c0/c0dd8052eb7d05dc0c0a892e15b459d2bd64433e.svn-base
@@ -0,0 +1,12 @@
+# $Id$
+#
+from inc_cfg import *
+
+# Simple call
+test_param = TestParam(
+ "tel: URI in From",
+ [
+ InstanceParam("callee", "--null-audio --max-calls=1 --id tel:+111"),
+ InstanceParam("caller", "--null-audio --max-calls=1")
+ ]
+ )