* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/f8/f81e20ded557e10a2f81596028cae770b3da65f1.svn-base b/jni/pjproject-android/.svn/pristine/f8/f81e20ded557e10a2f81596028cae770b3da65f1.svn-base
new file mode 100644
index 0000000..9695973
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f81e20ded557e10a2f81596028cae770b3da65f1.svn-base
@@ -0,0 +1,1497 @@
+/* $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 <pjnath/stun_session.h>
+#include <pjnath/errno.h>
+#include <pjlib.h>
+
+struct pj_stun_session
+{
+    pj_stun_config	*cfg;
+    pj_pool_t		*pool;
+    pj_grp_lock_t	*grp_lock;
+    pj_stun_session_cb	 cb;
+    void		*user_data;
+    pj_bool_t		 is_destroying;
+
+    pj_bool_t		 use_fingerprint;
+
+    pj_pool_t		*rx_pool;
+
+#if PJ_LOG_MAX_LEVEL >= 5
+    char		 dump_buf[1000];
+#endif
+    unsigned		 log_flag;
+
+    pj_stun_auth_type	 auth_type;
+    pj_stun_auth_cred	 cred;
+    int			 auth_retry;
+    pj_str_t		 next_nonce;
+    pj_str_t		 server_realm;
+
+    pj_str_t		 srv_name;
+
+    pj_stun_tx_data	 pending_request_list;
+    pj_stun_tx_data	 cached_response_list;
+};
+
+#define SNAME(s_)		    ((s_)->pool->obj_name)
+#define THIS_FILE		    "stun_session.c"
+
+#if 1
+#   define TRACE_(expr)		    PJ_LOG(5,expr)
+#else
+#   define TRACE_(expr)
+#endif
+
+#define LOG_ERR_(sess,title,rc) PJ_PERROR(3,(sess->pool->obj_name,rc,title))
+
+#define TDATA_POOL_SIZE		    PJNATH_POOL_LEN_STUN_TDATA
+#define TDATA_POOL_INC		    PJNATH_POOL_INC_STUN_TDATA
+
+
+static void stun_tsx_on_complete(pj_stun_client_tsx *tsx,
+				 pj_status_t status, 
+				 const pj_stun_msg *response,
+				 const pj_sockaddr_t *src_addr,
+				 unsigned src_addr_len);
+static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx,
+					const void *stun_pkt,
+					pj_size_t pkt_size);
+static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx);
+static void stun_sess_on_destroy(void *comp);
+
+static pj_stun_tsx_cb tsx_cb = 
+{
+    &stun_tsx_on_complete,
+    &stun_tsx_on_send_msg,
+    &stun_tsx_on_destroy
+};
+
+
+static pj_status_t tsx_add(pj_stun_session *sess,
+			   pj_stun_tx_data *tdata)
+{
+    pj_list_push_front(&sess->pending_request_list, tdata);
+    return PJ_SUCCESS;
+}
+
+static pj_status_t tsx_erase(pj_stun_session *sess,
+			     pj_stun_tx_data *tdata)
+{
+    PJ_UNUSED_ARG(sess);
+    pj_list_erase(tdata);
+    return PJ_SUCCESS;
+}
+
+static pj_stun_tx_data* tsx_lookup(pj_stun_session *sess,
+				   const pj_stun_msg *msg)
+{
+    pj_stun_tx_data *tdata;
+
+    tdata = sess->pending_request_list.next;
+    while (tdata != &sess->pending_request_list) {
+	pj_assert(sizeof(tdata->msg_key)==sizeof(msg->hdr.tsx_id));
+	if (tdata->msg_magic == msg->hdr.magic &&
+	    pj_memcmp(tdata->msg_key, msg->hdr.tsx_id, 
+		      sizeof(msg->hdr.tsx_id))==0)
+	{
+	    return tdata;
+	}
+	tdata = tdata->next;
+    }
+
+    return NULL;
+}
+
+static pj_status_t create_tdata(pj_stun_session *sess,
+			        pj_stun_tx_data **p_tdata)
+{
+    pj_pool_t *pool;
+    pj_stun_tx_data *tdata;
+
+    /* Create pool and initialize basic tdata attributes */
+    pool = pj_pool_create(sess->cfg->pf, "tdata%p", 
+			  TDATA_POOL_SIZE, TDATA_POOL_INC, NULL);
+    PJ_ASSERT_RETURN(pool, PJ_ENOMEM);
+
+    tdata = PJ_POOL_ZALLOC_T(pool, pj_stun_tx_data);
+    tdata->pool = pool;
+    tdata->sess = sess;
+
+    pj_list_init(tdata);
+
+    *p_tdata = tdata;
+
+    return PJ_SUCCESS;
+}
+
+static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx)
+{
+    pj_stun_tx_data *tdata;
+
+    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx);
+    pj_stun_client_tsx_stop(tsx);
+    if (tdata) {
+	tsx_erase(tdata->sess, tdata);
+	pj_pool_release(tdata->pool);
+    }
+
+    TRACE_((THIS_FILE, "STUN transaction %p destroyed", tsx));
+}
+
+static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force)
+{
+    TRACE_((THIS_FILE, "tdata %p destroy request, force=%d, tsx=%p", tdata,
+	    force, tdata->client_tsx));
+
+    if (tdata->res_timer.id != PJ_FALSE) {
+	pj_timer_heap_cancel_if_active(tdata->sess->cfg->timer_heap,
+	                               &tdata->res_timer, PJ_FALSE);
+	pj_list_erase(tdata);
+    }
+
+    if (force) {
+	pj_list_erase(tdata);
+	if (tdata->client_tsx) {
+	    pj_stun_client_tsx_stop(tdata->client_tsx);
+	    pj_stun_client_tsx_set_data(tdata->client_tsx, NULL);
+	}
+	pj_pool_release(tdata->pool);
+
+    } else {
+	if (tdata->client_tsx) {
+	    /* "Probably" this is to absorb retransmission */
+	    pj_time_val delay = {0, 300};
+	    pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay);
+
+	} else {
+	    pj_pool_release(tdata->pool);
+	}
+    }
+}
+
+/*
+ * Destroy the transmit data.
+ */
+PJ_DEF(void) pj_stun_msg_destroy_tdata( pj_stun_session *sess,
+					pj_stun_tx_data *tdata)
+{
+    PJ_UNUSED_ARG(sess);
+    destroy_tdata(tdata, PJ_FALSE);
+}
+
+
+/* Timer callback to be called when it's time to destroy response cache */
+static void on_cache_timeout(pj_timer_heap_t *timer_heap,
+			     struct pj_timer_entry *entry)
+{
+    pj_stun_tx_data *tdata;
+
+    PJ_UNUSED_ARG(timer_heap);
+
+    entry->id = PJ_FALSE;
+    tdata = (pj_stun_tx_data*) entry->user_data;
+
+    PJ_LOG(5,(SNAME(tdata->sess), "Response cache deleted"));
+
+    pj_list_erase(tdata);
+    destroy_tdata(tdata, PJ_FALSE);
+}
+
+static pj_status_t apply_msg_options(pj_stun_session *sess,
+				     pj_pool_t *pool,
+				     const pj_stun_req_cred_info *auth_info,
+				     pj_stun_msg *msg)
+{
+    pj_status_t status = 0;
+    pj_str_t realm, username, nonce, auth_key;
+
+    /* If the agent is sending a request, it SHOULD add a SOFTWARE attribute
+     * to the request. The server SHOULD include a SOFTWARE attribute in all 
+     * responses.
+     *
+     * If magic value is not PJ_STUN_MAGIC, only apply the attribute for
+     * responses.
+     */
+    if (sess->srv_name.slen && 
+	pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_SOFTWARE, 0)==NULL &&
+	(PJ_STUN_IS_RESPONSE(msg->hdr.type) ||
+	 (PJ_STUN_IS_REQUEST(msg->hdr.type) && msg->hdr.magic==PJ_STUN_MAGIC))) 
+    {
+	pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE,
+				    &sess->srv_name);
+    }
+
+    if (pj_stun_auth_valid_for_msg(msg) && auth_info) {
+	realm = auth_info->realm;
+	username = auth_info->username;
+	nonce = auth_info->nonce;
+	auth_key = auth_info->auth_key;
+    } else {
+	realm.slen = username.slen = nonce.slen = auth_key.slen = 0;
+    }
+
+    /* Create and add USERNAME attribute if needed */
+    if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) {
+	status = pj_stun_msg_add_string_attr(pool, msg,
+					     PJ_STUN_ATTR_USERNAME,
+					     &username);
+	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+    }
+
+    /* Add REALM only when long term credential is used */
+    if (realm.slen &&  PJ_STUN_IS_REQUEST(msg->hdr.type)) {
+	status = pj_stun_msg_add_string_attr(pool, msg,
+					    PJ_STUN_ATTR_REALM,
+					    &realm);
+	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+    }
+
+    /* Add NONCE when desired */
+    if (nonce.slen && 
+	(PJ_STUN_IS_REQUEST(msg->hdr.type) ||
+	 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))) 
+    {
+	status = pj_stun_msg_add_string_attr(pool, msg,
+					    PJ_STUN_ATTR_NONCE,
+					    &nonce);
+    }
+
+    /* Add MESSAGE-INTEGRITY attribute */
+    if (username.slen && auth_key.slen) {
+	status = pj_stun_msg_add_msgint_attr(pool, msg);
+	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+    }
+
+
+    /* Add FINGERPRINT attribute if necessary */
+    if (sess->use_fingerprint) {
+	status = pj_stun_msg_add_uint_attr(pool, msg, 
+					  PJ_STUN_ATTR_FINGERPRINT, 0);
+	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+    }
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t handle_auth_challenge(pj_stun_session *sess,
+					 const pj_stun_tx_data *request,
+					 const pj_stun_msg *response,
+					 const pj_sockaddr_t *src_addr,
+					 unsigned src_addr_len,
+					 pj_bool_t *notify_user)
+{
+    const pj_stun_errcode_attr *ea;
+
+    *notify_user = PJ_TRUE;
+
+    if (response==NULL)
+	return PJ_SUCCESS;
+
+    if (sess->auth_type != PJ_STUN_AUTH_LONG_TERM)
+	return PJ_SUCCESS;
+    
+    if (!PJ_STUN_IS_ERROR_RESPONSE(response->hdr.type)) {
+	sess->auth_retry = 0;
+	return PJ_SUCCESS;
+    }
+
+    ea = (const pj_stun_errcode_attr*)
+	 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_ERROR_CODE, 0);
+    if (!ea) {
+	PJ_LOG(4,(SNAME(sess), "Invalid error response: no ERROR-CODE"
+		  " attribute"));
+	*notify_user = PJ_FALSE;
+	return PJNATH_EINSTUNMSG;
+    }
+
+    if (ea->err_code == PJ_STUN_SC_UNAUTHORIZED || 
+	ea->err_code == PJ_STUN_SC_STALE_NONCE)
+    {
+	const pj_stun_nonce_attr *anonce;
+	const pj_stun_realm_attr *arealm;
+	pj_stun_tx_data *tdata;
+	unsigned i;
+	pj_status_t status;
+
+	anonce = (const pj_stun_nonce_attr*)
+		 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_NONCE, 0);
+	if (!anonce) {
+	    PJ_LOG(4,(SNAME(sess), "Invalid response: missing NONCE"));
+	    *notify_user = PJ_FALSE;
+	    return PJNATH_EINSTUNMSG;
+	}
+
+	/* Bail out if we've supplied the correct nonce */
+	if (pj_strcmp(&anonce->value, &sess->next_nonce)==0) {
+	    return PJ_SUCCESS;
+	}
+
+	/* Bail out if we've tried too many */
+	if (++sess->auth_retry > 3) {
+	    PJ_LOG(4,(SNAME(sess), "Error: authentication failed (too "
+		      "many retries)"));
+	    return PJ_STATUS_FROM_STUN_CODE(401);
+	}
+
+	/* Save next_nonce */
+	pj_strdup(sess->pool, &sess->next_nonce, &anonce->value);
+
+	/* Copy the realm from the response */
+	arealm = (pj_stun_realm_attr*)
+		 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_REALM, 0);
+	if (arealm) {
+	    pj_strdup(sess->pool, &sess->server_realm, &arealm->value);
+	    while (sess->server_realm.slen &&
+		    !sess->server_realm.ptr[sess->server_realm.slen-1])
+	    {
+		--sess->server_realm.slen;
+	    }
+	}
+
+	/* Create new request */
+	status = pj_stun_session_create_req(sess, request->msg->hdr.type,
+					    request->msg->hdr.magic,
+					    NULL, &tdata);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	/* Duplicate all the attributes in the old request, except
+	 * USERNAME, REALM, M-I, and NONCE, which will be filled in
+	 * later.
+	 */
+	for (i=0; i<request->msg->attr_count; ++i) {
+	    const pj_stun_attr_hdr *asrc = request->msg->attr[i];
+
+	    if (asrc->type == PJ_STUN_ATTR_USERNAME ||
+		asrc->type == PJ_STUN_ATTR_REALM ||
+		asrc->type == PJ_STUN_ATTR_MESSAGE_INTEGRITY ||
+		asrc->type == PJ_STUN_ATTR_NONCE)
+	    {
+		continue;
+	    }
+
+	    tdata->msg->attr[tdata->msg->attr_count++] = 
+		pj_stun_attr_clone(tdata->pool, asrc);
+	}
+
+	/* Will retry the request with authentication, no need to
+	 * notify user.
+	 */
+	*notify_user = PJ_FALSE;
+
+	PJ_LOG(4,(SNAME(sess), "Retrying request with new authentication"));
+
+	/* Retry the request */
+	status = pj_stun_session_send_msg(sess, request->token, PJ_TRUE, 
+					  request->retransmit, src_addr, 
+					  src_addr_len, tdata);
+
+    } else {
+	sess->auth_retry = 0;
+    }
+
+    return PJ_SUCCESS;
+}
+
+static void stun_tsx_on_complete(pj_stun_client_tsx *tsx,
+				 pj_status_t status, 
+				 const pj_stun_msg *response,
+				 const pj_sockaddr_t *src_addr,
+				 unsigned src_addr_len)
+{
+    pj_stun_session *sess;
+    pj_bool_t notify_user = PJ_TRUE;
+    pj_stun_tx_data *tdata;
+
+    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx);
+    sess = tdata->sess;
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_stun_msg_destroy_tdata(sess, tdata);
+	pj_grp_lock_release(sess->grp_lock);
+	return;
+    }
+
+    /* Handle authentication challenge */
+    handle_auth_challenge(sess, tdata, response, src_addr,
+		          src_addr_len, &notify_user);
+
+    if (notify_user && sess->cb.on_request_complete) {
+	(*sess->cb.on_request_complete)(sess, status, tdata->token, tdata, 
+					response, src_addr, src_addr_len);
+    }
+
+    /* Destroy the transmit data. This will remove the transaction
+     * from the pending list too. 
+     */
+    if (status == PJNATH_ESTUNTIMEDOUT)
+	destroy_tdata(tdata, PJ_TRUE);
+    else
+	destroy_tdata(tdata, PJ_FALSE);
+    tdata = NULL;
+
+    pj_grp_lock_release(sess->grp_lock);
+}
+
+static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx,
+					const void *stun_pkt,
+					pj_size_t pkt_size)
+{
+    pj_stun_tx_data *tdata;
+    pj_stun_session *sess;
+    pj_status_t status;
+
+    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx);
+    sess = tdata->sess;
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+    
+    if (sess->is_destroying) {
+	/* Stray timer */
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = sess->cb.on_send_msg(tdata->sess, tdata->token, stun_pkt, 
+				  pkt_size, tdata->dst_addr, 
+				  tdata->addr_len);
+    if (pj_grp_lock_release(sess->grp_lock))
+	return PJ_EGONE;
+
+    return status;
+}
+
+/* **************************************************************************/
+
+PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_config *cfg,
+					    const char *name,
+					    const pj_stun_session_cb *cb,
+					    pj_bool_t fingerprint,
+					    pj_grp_lock_t *grp_lock,
+					    pj_stun_session **p_sess)
+{
+    pj_pool_t	*pool;
+    pj_stun_session *sess;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(cfg && cb && p_sess, PJ_EINVAL);
+
+    if (name==NULL)
+	name = "stuse%p";
+
+    pool = pj_pool_create(cfg->pf, name, PJNATH_POOL_LEN_STUN_SESS, 
+			  PJNATH_POOL_INC_STUN_SESS, NULL);
+    PJ_ASSERT_RETURN(pool, PJ_ENOMEM);
+
+    sess = PJ_POOL_ZALLOC_T(pool, pj_stun_session);
+    sess->cfg = cfg;
+    sess->pool = pool;
+    pj_memcpy(&sess->cb, cb, sizeof(*cb));
+    sess->use_fingerprint = fingerprint;
+    sess->log_flag = 0xFFFF;
+
+    if (grp_lock) {
+	sess->grp_lock = grp_lock;
+    } else {
+	status = pj_grp_lock_create(pool, NULL, &sess->grp_lock);
+	if (status != PJ_SUCCESS) {
+	    pj_pool_release(pool);
+	    return status;
+	}
+    }
+
+    pj_grp_lock_add_ref(sess->grp_lock);
+    pj_grp_lock_add_handler(sess->grp_lock, pool, sess,
+                            &stun_sess_on_destroy);
+
+    pj_stun_session_set_software_name(sess, &cfg->software_name);
+
+    sess->rx_pool = pj_pool_create(sess->cfg->pf, name,
+				   PJNATH_POOL_LEN_STUN_TDATA,
+				   PJNATH_POOL_INC_STUN_TDATA, NULL);
+
+    pj_list_init(&sess->pending_request_list);
+    pj_list_init(&sess->cached_response_list);
+
+    *p_sess = sess;
+
+    return PJ_SUCCESS;
+}
+
+static void stun_sess_on_destroy(void *comp)
+{
+    pj_stun_session *sess = (pj_stun_session*)comp;
+
+    while (!pj_list_empty(&sess->pending_request_list)) {
+	pj_stun_tx_data *tdata = sess->pending_request_list.next;
+	destroy_tdata(tdata, PJ_TRUE);
+    }
+
+    while (!pj_list_empty(&sess->cached_response_list)) {
+	pj_stun_tx_data *tdata = sess->cached_response_list.next;
+	destroy_tdata(tdata, PJ_TRUE);
+    }
+
+    if (sess->rx_pool) {
+	pj_pool_release(sess->rx_pool);
+	sess->rx_pool = NULL;
+    }
+
+    pj_pool_release(sess->pool);
+
+    TRACE_((THIS_FILE, "STUN session %p destroyed", sess));
+}
+
+PJ_DEF(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess)
+{
+    pj_stun_tx_data *tdata;
+
+    PJ_ASSERT_RETURN(sess, PJ_EINVAL);
+
+    TRACE_((SNAME(sess), "STUN session %p destroy request, ref_cnt=%d",
+	     sess, pj_grp_lock_get_ref(sess->grp_lock)));
+
+    pj_grp_lock_acquire(sess->grp_lock);
+
+    if (sess->is_destroying) {
+	/* Prevent from decrementing the ref counter more than once */
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    sess->is_destroying = PJ_TRUE;
+
+    /* We need to stop transactions and cached response because they are
+     * holding the group lock's reference counter while retransmitting.
+     */
+    tdata = sess->pending_request_list.next;
+    while (tdata != &sess->pending_request_list) {
+	if (tdata->client_tsx)
+	    pj_stun_client_tsx_stop(tdata->client_tsx);
+	tdata = tdata->next;
+    }
+
+    tdata = sess->cached_response_list.next;
+    while (tdata != &sess->cached_response_list) {
+	pj_timer_heap_cancel_if_active(tdata->sess->cfg->timer_heap,
+				       &tdata->res_timer, PJ_FALSE);
+	tdata = tdata->next;
+    }
+
+    pj_grp_lock_dec_ref(sess->grp_lock);
+    pj_grp_lock_release(sess->grp_lock);
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_stun_session_set_user_data( pj_stun_session *sess,
+						   void *user_data)
+{
+    PJ_ASSERT_RETURN(sess, PJ_EINVAL);
+    pj_grp_lock_acquire(sess->grp_lock);
+    sess->user_data = user_data;
+    pj_grp_lock_release(sess->grp_lock);
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(void*) pj_stun_session_get_user_data(pj_stun_session *sess)
+{
+    PJ_ASSERT_RETURN(sess, NULL);
+    return sess->user_data;
+}
+
+PJ_DEF(pj_grp_lock_t *) pj_stun_session_get_grp_lock(pj_stun_session *sess)
+{
+    PJ_ASSERT_RETURN(sess, NULL);
+    return sess->grp_lock;
+}
+
+PJ_DEF(pj_status_t) pj_stun_session_set_software_name(pj_stun_session *sess,
+						      const pj_str_t *sw)
+{
+    PJ_ASSERT_RETURN(sess, PJ_EINVAL);
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sw && sw->slen)
+	pj_strdup(sess->pool, &sess->srv_name, sw);
+    else
+	sess->srv_name.slen = 0;
+    pj_grp_lock_release(sess->grp_lock);
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_stun_session_set_credential(pj_stun_session *sess,
+						 pj_stun_auth_type auth_type,
+						 const pj_stun_auth_cred *cred)
+{
+    PJ_ASSERT_RETURN(sess, PJ_EINVAL);
+
+    pj_grp_lock_acquire(sess->grp_lock);
+    sess->auth_type = auth_type;
+    if (cred) {
+	pj_stun_auth_cred_dup(sess->pool, &sess->cred, cred);
+    } else {
+	sess->auth_type = PJ_STUN_AUTH_NONE;
+	pj_bzero(&sess->cred, sizeof(sess->cred));
+    }
+    pj_grp_lock_release(sess->grp_lock);
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(void) pj_stun_session_set_log( pj_stun_session *sess,
+				      unsigned flags)
+{
+    PJ_ASSERT_ON_FAIL(sess, return);
+    sess->log_flag = flags;
+}
+
+PJ_DEF(pj_bool_t) pj_stun_session_use_fingerprint(pj_stun_session *sess,
+						  pj_bool_t use)
+{
+    pj_bool_t old_use;
+
+    PJ_ASSERT_RETURN(sess, PJ_FALSE);
+
+    old_use = sess->use_fingerprint;
+    sess->use_fingerprint = use;
+    return old_use;
+}
+
+static pj_status_t get_auth(pj_stun_session *sess,
+			    pj_stun_tx_data *tdata)
+{
+    if (sess->cred.type == PJ_STUN_AUTH_CRED_STATIC) {
+	//tdata->auth_info.realm = sess->cred.data.static_cred.realm;
+	tdata->auth_info.realm = sess->server_realm;
+	tdata->auth_info.username = sess->cred.data.static_cred.username;
+	tdata->auth_info.nonce = sess->cred.data.static_cred.nonce;
+
+	pj_stun_create_key(tdata->pool, &tdata->auth_info.auth_key, 
+			   &tdata->auth_info.realm,
+			   &tdata->auth_info.username,
+			   sess->cred.data.static_cred.data_type,
+			   &sess->cred.data.static_cred.data);
+
+    } else if (sess->cred.type == PJ_STUN_AUTH_CRED_DYNAMIC) {
+	pj_str_t password;
+	void *user_data = sess->cred.data.dyn_cred.user_data;
+	pj_stun_passwd_type data_type = PJ_STUN_PASSWD_PLAIN;
+	pj_status_t rc;
+
+	rc = (*sess->cred.data.dyn_cred.get_cred)(tdata->msg, user_data, 
+						  tdata->pool,
+						  &tdata->auth_info.realm, 
+						  &tdata->auth_info.username,
+						  &tdata->auth_info.nonce, 
+						  &data_type, &password);
+	if (rc != PJ_SUCCESS)
+	    return rc;
+
+	pj_stun_create_key(tdata->pool, &tdata->auth_info.auth_key, 
+			   &tdata->auth_info.realm, &tdata->auth_info.username,
+			   data_type, &password);
+
+    } else {
+	pj_assert(!"Unknown credential type");
+	return PJ_EBUG;
+    }
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess,
+					       int method,
+					       pj_uint32_t magic,
+					       const pj_uint8_t tsx_id[12],
+					       pj_stun_tx_data **p_tdata)
+{
+    pj_stun_tx_data *tdata = NULL;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL);
+
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = create_tdata(sess, &tdata);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Create STUN message */
+    status = pj_stun_msg_create(tdata->pool, method,  magic, 
+				tsx_id, &tdata->msg);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* copy the request's transaction ID as the transaction key. */
+    pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id));
+    tdata->msg_magic = tdata->msg->hdr.magic;
+    pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id,
+	      sizeof(tdata->msg->hdr.tsx_id));
+
+    
+    /* Get authentication information for the request */
+    if (sess->auth_type == PJ_STUN_AUTH_NONE) {
+	/* No authentication */
+
+    } else if (sess->auth_type == PJ_STUN_AUTH_SHORT_TERM) {
+	/* MUST put authentication in request */
+	status = get_auth(sess, tdata);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+    } else if (sess->auth_type == PJ_STUN_AUTH_LONG_TERM) {
+	/* Only put authentication information if we've received
+	 * response from server.
+	 */
+	if (sess->next_nonce.slen != 0) {
+	    status = get_auth(sess, tdata);
+	    if (status != PJ_SUCCESS)
+		goto on_error;
+	    tdata->auth_info.nonce = sess->next_nonce;
+	    tdata->auth_info.realm = sess->server_realm;
+	}
+
+    } else {
+	pj_assert(!"Invalid authentication type");
+	status = PJ_EBUG;
+	goto on_error;
+    }
+
+    *p_tdata = tdata;
+    pj_grp_lock_release(sess->grp_lock);
+    return PJ_SUCCESS;
+
+on_error:
+    if (tdata)
+	pj_pool_release(tdata->pool);
+    pj_grp_lock_release(sess->grp_lock);
+    return status;
+}
+
+PJ_DEF(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess,
+					       int msg_type,
+					       pj_stun_tx_data **p_tdata)
+{
+    pj_stun_tx_data *tdata = NULL;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL);
+
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = create_tdata(sess, &tdata);
+    if (status != PJ_SUCCESS) {
+	pj_grp_lock_release(sess->grp_lock);
+	return status;
+    }
+
+    /* Create STUN message */
+    msg_type |= PJ_STUN_INDICATION_BIT;
+    status = pj_stun_msg_create(tdata->pool, msg_type,  PJ_STUN_MAGIC, 
+				NULL, &tdata->msg);
+    if (status != PJ_SUCCESS) {
+	pj_pool_release(tdata->pool);
+	pj_grp_lock_release(sess->grp_lock);
+	return status;
+    }
+
+    *p_tdata = tdata;
+
+    pj_grp_lock_release(sess->grp_lock);
+    return PJ_SUCCESS;
+}
+
+/*
+ * Create a STUN response message.
+ */
+PJ_DEF(pj_status_t) pj_stun_session_create_res( pj_stun_session *sess,
+						const pj_stun_rx_data *rdata,
+						unsigned err_code,
+						const pj_str_t *err_msg,
+						pj_stun_tx_data **p_tdata)
+{
+    pj_status_t status;
+    pj_stun_tx_data *tdata = NULL;
+
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = create_tdata(sess, &tdata);
+    if (status != PJ_SUCCESS) {
+	pj_grp_lock_release(sess->grp_lock);
+	return status;
+    }
+
+    /* Create STUN response message */
+    status = pj_stun_msg_create_response(tdata->pool, rdata->msg, 
+					 err_code, err_msg, &tdata->msg);
+    if (status != PJ_SUCCESS) {
+	pj_pool_release(tdata->pool);
+	pj_grp_lock_release(sess->grp_lock);
+	return status;
+    }
+
+    /* copy the request's transaction ID as the transaction key. */
+    pj_assert(sizeof(tdata->msg_key)==sizeof(rdata->msg->hdr.tsx_id));
+    tdata->msg_magic = rdata->msg->hdr.magic;
+    pj_memcpy(tdata->msg_key, rdata->msg->hdr.tsx_id, 
+	      sizeof(rdata->msg->hdr.tsx_id));
+
+    /* copy the credential found in the request */
+    pj_stun_req_cred_info_dup(tdata->pool, &tdata->auth_info, &rdata->info);
+
+    *p_tdata = tdata;
+
+    pj_grp_lock_release(sess->grp_lock);
+
+    return PJ_SUCCESS;
+}
+
+
+/* Print outgoing message to log */
+static void dump_tx_msg(pj_stun_session *sess, const pj_stun_msg *msg,
+			unsigned pkt_size, const pj_sockaddr_t *addr)
+{
+    char dst_name[PJ_INET6_ADDRSTRLEN+10];
+    
+    if ((PJ_STUN_IS_REQUEST(msg->hdr.type) && 
+	 (sess->log_flag & PJ_STUN_SESS_LOG_TX_REQ)==0) ||
+	(PJ_STUN_IS_RESPONSE(msg->hdr.type) &&
+	 (sess->log_flag & PJ_STUN_SESS_LOG_TX_RES)==0) ||
+	(PJ_STUN_IS_INDICATION(msg->hdr.type) &&
+	 (sess->log_flag & PJ_STUN_SESS_LOG_TX_IND)==0))
+    {
+	return;
+    }
+
+    pj_sockaddr_print(addr, dst_name, sizeof(dst_name), 3);
+
+    PJ_LOG(5,(SNAME(sess), 
+	      "TX %d bytes STUN message to %s:\n"
+	      "--- begin STUN message ---\n"
+	      "%s"
+	      "--- end of STUN message ---\n",
+	      pkt_size, dst_name, 
+	      pj_stun_msg_dump(msg, sess->dump_buf, sizeof(sess->dump_buf), 
+			       NULL)));
+
+}
+
+
+PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess,
+					      void *token,
+					      pj_bool_t cache_res,
+					      pj_bool_t retransmit,
+					      const pj_sockaddr_t *server,
+					      unsigned addr_len,
+					      pj_stun_tx_data *tdata)
+{
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(sess && addr_len && server && tdata, PJ_EINVAL);
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    pj_log_push_indent();
+
+    /* Allocate packet */
+    tdata->max_len = PJ_STUN_MAX_PKT_LEN;
+    tdata->pkt = pj_pool_alloc(tdata->pool, tdata->max_len);
+
+    tdata->token = token;
+    tdata->retransmit = retransmit;
+
+    /* Apply options */
+    status = apply_msg_options(sess, tdata->pool, &tdata->auth_info, 
+			       tdata->msg);
+    if (status != PJ_SUCCESS) {
+	pj_stun_msg_destroy_tdata(sess, tdata);
+	LOG_ERR_(sess, "Error applying options", status);
+	goto on_return;
+    }
+
+    /* Encode message */
+    status = pj_stun_msg_encode(tdata->msg, (pj_uint8_t*)tdata->pkt, 
+    				tdata->max_len, 0, 
+    				&tdata->auth_info.auth_key,
+				&tdata->pkt_size);
+    if (status != PJ_SUCCESS) {
+	pj_stun_msg_destroy_tdata(sess, tdata);
+	LOG_ERR_(sess, "STUN encode() error", status);
+	goto on_return;
+    }
+
+    /* Dump packet */
+    dump_tx_msg(sess, tdata->msg, (unsigned)tdata->pkt_size, server);
+
+    /* If this is a STUN request message, then send the request with
+     * a new STUN client transaction.
+     */
+    if (PJ_STUN_IS_REQUEST(tdata->msg->hdr.type)) {
+
+	/* Create STUN client transaction */
+	status = pj_stun_client_tsx_create(sess->cfg, tdata->pool,
+	                                   sess->grp_lock,
+					   &tsx_cb, &tdata->client_tsx);
+	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+	pj_stun_client_tsx_set_data(tdata->client_tsx, (void*)tdata);
+
+	/* Save the remote address */
+	tdata->addr_len = addr_len;
+	tdata->dst_addr = server;
+
+	/* Send the request! */
+	status = pj_stun_client_tsx_send_msg(tdata->client_tsx, retransmit,
+					     tdata->pkt, 
+					     (unsigned)tdata->pkt_size);
+	if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+	    pj_stun_msg_destroy_tdata(sess, tdata);
+	    LOG_ERR_(sess, "Error sending STUN request", status);
+	    goto on_return;
+	}
+
+	/* Add to pending request list */
+	tsx_add(sess, tdata);
+
+    } else {
+	if (cache_res && 
+	    (PJ_STUN_IS_SUCCESS_RESPONSE(tdata->msg->hdr.type) ||
+	     PJ_STUN_IS_ERROR_RESPONSE(tdata->msg->hdr.type))) 
+	{
+	    /* Requested to keep the response in the cache */
+	    pj_time_val timeout;
+	    
+	    pj_memset(&tdata->res_timer, 0, sizeof(tdata->res_timer));
+	    pj_timer_entry_init(&tdata->res_timer, PJ_FALSE, tdata,
+				&on_cache_timeout);
+
+	    timeout.sec = sess->cfg->res_cache_msec / 1000;
+	    timeout.msec = sess->cfg->res_cache_msec % 1000;
+
+	    status = pj_timer_heap_schedule_w_grp_lock(sess->cfg->timer_heap,
+	                                               &tdata->res_timer,
+	                                               &timeout, PJ_TRUE,
+	                                               sess->grp_lock);
+	    if (status != PJ_SUCCESS) {
+		pj_stun_msg_destroy_tdata(sess, tdata);
+		LOG_ERR_(sess, "Error scheduling response timer", status);
+		goto on_return;
+	    }
+
+	    pj_list_push_back(&sess->cached_response_list, tdata);
+	}
+    
+	/* Otherwise for non-request message, send directly to transport. */
+	status = sess->cb.on_send_msg(sess, token, tdata->pkt, 
+				      tdata->pkt_size, server, addr_len);
+
+	if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+	    pj_stun_msg_destroy_tdata(sess, tdata);
+	    LOG_ERR_(sess, "Error sending STUN request", status);
+	    goto on_return;
+	}
+
+	/* Destroy only when response is not cached*/
+	if (tdata->res_timer.id == 0) {
+	    pj_stun_msg_destroy_tdata(sess, tdata);
+	}
+    }
+
+on_return:
+    pj_log_pop_indent();
+
+    if (pj_grp_lock_release(sess->grp_lock))
+	return PJ_EGONE;
+
+    return status;
+}
+
+
+/*
+ * Create and send STUN response message.
+ */
+PJ_DEF(pj_status_t) pj_stun_session_respond( pj_stun_session *sess, 
+					     const pj_stun_rx_data *rdata,
+					     unsigned code, 
+					     const char *errmsg,
+					     void *token,
+					     pj_bool_t cache, 
+					     const pj_sockaddr_t *dst_addr, 
+					     unsigned addr_len)
+{
+    pj_status_t status;
+    pj_str_t reason;
+    pj_stun_tx_data *tdata;
+
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = pj_stun_session_create_res(sess, rdata, code, 
+					(errmsg?pj_cstr(&reason,errmsg):NULL), 
+					&tdata);
+    if (status != PJ_SUCCESS) {
+	pj_grp_lock_release(sess->grp_lock);
+	return status;
+    }
+
+    status = pj_stun_session_send_msg(sess, token, cache, PJ_FALSE,
+                                      dst_addr,  addr_len, tdata);
+
+    pj_grp_lock_release(sess->grp_lock);
+    return status;
+}
+
+
+/*
+ * Cancel outgoing STUN transaction. 
+ */
+PJ_DEF(pj_status_t) pj_stun_session_cancel_req( pj_stun_session *sess,
+						pj_stun_tx_data *tdata,
+						pj_bool_t notify,
+						pj_status_t notify_status)
+{
+    PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL);
+    PJ_ASSERT_RETURN(!notify || notify_status!=PJ_SUCCESS, PJ_EINVAL);
+    PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL);
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    if (notify) {
+	(sess->cb.on_request_complete)(sess, notify_status, tdata->token, 
+				       tdata, NULL, NULL, 0);
+    }
+
+    /* Just destroy tdata. This will destroy the transaction as well */
+    pj_stun_msg_destroy_tdata(sess, tdata);
+
+    pj_grp_lock_release(sess->grp_lock);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Explicitly request retransmission of the request.
+ */
+PJ_DEF(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess,
+						   pj_stun_tx_data *tdata,
+                                                   pj_bool_t mod_count)
+{
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL);
+    PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL);
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    status = pj_stun_client_tsx_retransmit(tdata->client_tsx, mod_count);
+
+    pj_grp_lock_release(sess->grp_lock);
+
+    return status;
+}
+
+
+/* Send response */
+static pj_status_t send_response(pj_stun_session *sess, void *token,
+				 pj_pool_t *pool, pj_stun_msg *response,
+				 const pj_stun_req_cred_info *auth_info,
+				 pj_bool_t retransmission,
+				 const pj_sockaddr_t *addr, unsigned addr_len)
+{
+    pj_uint8_t *out_pkt;
+    pj_size_t out_max_len, out_len;
+    pj_status_t status;
+
+    /* Apply options */
+    if (!retransmission) {
+	status = apply_msg_options(sess, pool, auth_info, response);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    /* Alloc packet buffer */
+    out_max_len = PJ_STUN_MAX_PKT_LEN;
+    out_pkt = (pj_uint8_t*) pj_pool_alloc(pool, out_max_len);
+
+    /* Encode */
+    status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 
+				&auth_info->auth_key, &out_len);
+    if (status != PJ_SUCCESS) {
+	LOG_ERR_(sess, "Error encoding message", status);
+	return status;
+    }
+
+    /* Print log */
+    dump_tx_msg(sess, response, (unsigned)out_len, addr);
+
+    /* Send packet */
+    status = sess->cb.on_send_msg(sess, token, out_pkt, (unsigned)out_len, 
+				  addr, addr_len);
+
+    return status;
+}
+
+/* Authenticate incoming message */
+static pj_status_t authenticate_req(pj_stun_session *sess,
+				    void *token,
+				    const pj_uint8_t *pkt,
+				    unsigned pkt_len,
+				    pj_stun_rx_data *rdata,
+				    pj_pool_t *tmp_pool,
+				    const pj_sockaddr_t *src_addr,
+				    unsigned src_addr_len)
+{
+    pj_stun_msg *response;
+    pj_status_t status;
+
+    if (PJ_STUN_IS_ERROR_RESPONSE(rdata->msg->hdr.type) || 
+	sess->auth_type == PJ_STUN_AUTH_NONE)
+    {
+	return PJ_SUCCESS;
+    }
+
+    status = pj_stun_authenticate_request(pkt, pkt_len, rdata->msg, 
+					  &sess->cred, tmp_pool, &rdata->info,
+					  &response);
+    if (status != PJ_SUCCESS && response != NULL) {
+	PJ_LOG(5,(SNAME(sess), "Message authentication failed"));
+	send_response(sess, token, tmp_pool, response, &rdata->info, 
+		      PJ_FALSE, src_addr, src_addr_len);
+    }
+
+    return status;
+}
+
+
+/* Handle incoming response */
+static pj_status_t on_incoming_response(pj_stun_session *sess,
+					unsigned options,
+					const pj_uint8_t *pkt,
+					unsigned pkt_len,
+					pj_stun_msg *msg,
+					const pj_sockaddr_t *src_addr,
+					unsigned src_addr_len)
+{
+    pj_stun_tx_data *tdata;
+    pj_status_t status;
+
+    /* Lookup pending client transaction */
+    tdata = tsx_lookup(sess, msg);
+    if (tdata == NULL) {
+	PJ_LOG(5,(SNAME(sess), 
+		  "Transaction not found, response silently discarded"));
+	return PJ_SUCCESS;
+    }
+
+    if (sess->auth_type == PJ_STUN_AUTH_NONE)
+	options |= PJ_STUN_NO_AUTHENTICATE;
+
+    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE
+     * is specified in the option.
+     */
+    if ((options & PJ_STUN_NO_AUTHENTICATE) == 0 && 
+	tdata->auth_info.auth_key.slen != 0 && 
+	pj_stun_auth_valid_for_msg(msg))
+    {
+	status = pj_stun_authenticate_response(pkt, pkt_len, msg, 
+					       &tdata->auth_info.auth_key);
+	if (status != PJ_SUCCESS) {
+	    PJ_LOG(5,(SNAME(sess), 
+		      "Response authentication failed"));
+	    return status;
+	}
+    }
+
+    /* Pass the response to the transaction. 
+     * If the message is accepted, transaction callback will be called,
+     * and this will call the session callback too.
+     */
+    status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg, 
+					  src_addr, src_addr_len);
+    if (status != PJ_SUCCESS) {
+	return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/* For requests, check if we cache the response */
+static pj_status_t check_cached_response(pj_stun_session *sess,
+					 pj_pool_t *tmp_pool,
+					 const pj_stun_msg *msg,
+					 const pj_sockaddr_t *src_addr,
+					 unsigned src_addr_len)
+{
+    pj_stun_tx_data *t;
+
+    /* First lookup response in response cache */
+    t = sess->cached_response_list.next;
+    while (t != &sess->cached_response_list) {
+	if (t->msg_magic == msg->hdr.magic &&
+	    t->msg->hdr.type == msg->hdr.type &&
+	    pj_memcmp(t->msg_key, msg->hdr.tsx_id, 
+		      sizeof(msg->hdr.tsx_id))==0)
+	{
+	    break;
+	}
+	t = t->next;
+    }
+
+    if (t != &sess->cached_response_list) {
+	/* Found response in the cache */
+
+	PJ_LOG(5,(SNAME(sess), 
+		 "Request retransmission, sending cached response"));
+
+	send_response(sess, t->token, tmp_pool, t->msg, &t->auth_info, 
+		      PJ_TRUE, src_addr, src_addr_len);
+	return PJ_SUCCESS;
+    }
+
+    return PJ_ENOTFOUND;
+}
+
+/* Handle incoming request */
+static pj_status_t on_incoming_request(pj_stun_session *sess,
+				       unsigned options,
+				       void *token,
+				       pj_pool_t *tmp_pool,
+				       const pj_uint8_t *in_pkt,
+				       unsigned in_pkt_len,
+				       pj_stun_msg *msg,
+				       const pj_sockaddr_t *src_addr,
+				       unsigned src_addr_len)
+{
+    pj_stun_rx_data rdata;
+    pj_status_t status;
+
+    /* Init rdata */
+    rdata.msg = msg;
+    pj_bzero(&rdata.info, sizeof(rdata.info));
+
+    if (sess->auth_type == PJ_STUN_AUTH_NONE)
+	options |= PJ_STUN_NO_AUTHENTICATE;
+
+    /* Authenticate the message, unless PJ_STUN_NO_AUTHENTICATE
+     * is specified in the option.
+     */
+    if ((options & PJ_STUN_NO_AUTHENTICATE) == 0) {
+	status = authenticate_req(sess, token, (const pj_uint8_t*) in_pkt, 
+				  in_pkt_len,&rdata, tmp_pool, src_addr, 
+				  src_addr_len);
+	if (status != PJ_SUCCESS) {
+	    return status;
+	}
+    }
+
+    /* Distribute to handler, or respond with Bad Request */
+    if (sess->cb.on_rx_request) {
+	status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, &rdata,
+					   token, src_addr, src_addr_len);
+    } else {
+	pj_str_t err_text;
+	pj_stun_msg *response;
+
+	err_text = pj_str("Callback is not set to handle request");
+	status = pj_stun_msg_create_response(tmp_pool, msg, 
+					     PJ_STUN_SC_BAD_REQUEST, 
+					     &err_text, &response);
+	if (status == PJ_SUCCESS && response) {
+	    status = send_response(sess, token, tmp_pool, response, 
+				   NULL, PJ_FALSE, src_addr, src_addr_len);
+	}
+    }
+
+    return status;
+}
+
+
+/* Handle incoming indication */
+static pj_status_t on_incoming_indication(pj_stun_session *sess,
+					  void *token,
+					  pj_pool_t *tmp_pool,
+					  const pj_uint8_t *in_pkt,
+					  unsigned in_pkt_len,
+					  const pj_stun_msg *msg,
+					  const pj_sockaddr_t *src_addr,
+					  unsigned src_addr_len)
+{
+    PJ_UNUSED_ARG(tmp_pool);
+
+    /* Distribute to handler */
+    if (sess->cb.on_rx_indication) {
+	return (*sess->cb.on_rx_indication)(sess, in_pkt, in_pkt_len, msg,
+					    token, src_addr, src_addr_len);
+    } else {
+	return PJ_SUCCESS;
+    }
+}
+
+
+/* Print outgoing message to log */
+static void dump_rx_msg(pj_stun_session *sess, const pj_stun_msg *msg,
+			unsigned pkt_size, const pj_sockaddr_t *addr)
+{
+    char src_info[PJ_INET6_ADDRSTRLEN+10];
+    
+    if ((PJ_STUN_IS_REQUEST(msg->hdr.type) && 
+	 (sess->log_flag & PJ_STUN_SESS_LOG_RX_REQ)==0) ||
+	(PJ_STUN_IS_RESPONSE(msg->hdr.type) &&
+	 (sess->log_flag & PJ_STUN_SESS_LOG_RX_RES)==0) ||
+	(PJ_STUN_IS_INDICATION(msg->hdr.type) &&
+	 (sess->log_flag & PJ_STUN_SESS_LOG_RX_IND)==0))
+    {
+	return;
+    }
+
+    pj_sockaddr_print(addr, src_info, sizeof(src_info), 3);
+
+    PJ_LOG(5,(SNAME(sess),
+	      "RX %d bytes STUN message from %s:\n"
+	      "--- begin STUN message ---\n"
+	      "%s"
+	      "--- end of STUN message ---\n",
+	      pkt_size, src_info,
+	      pj_stun_msg_dump(msg, sess->dump_buf, sizeof(sess->dump_buf), 
+			       NULL)));
+
+}
+
+/* Incoming packet */
+PJ_DEF(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess,
+					      const void *packet,
+					      pj_size_t pkt_size,
+					      unsigned options,
+					      void *token,
+					      pj_size_t *parsed_len,
+					      const pj_sockaddr_t *src_addr,
+					      unsigned src_addr_len)
+{
+    pj_stun_msg *msg, *response;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(sess && packet && pkt_size, PJ_EINVAL);
+
+    /* Lock the session and prevent user from destroying us in the callback */
+    pj_grp_lock_acquire(sess->grp_lock);
+
+    if (sess->is_destroying) {
+	pj_grp_lock_release(sess->grp_lock);
+	return PJ_EINVALIDOP;
+    }
+
+    pj_log_push_indent();
+
+    /* Reset pool */
+    pj_pool_reset(sess->rx_pool);
+
+    /* Try to parse the message */
+    status = pj_stun_msg_decode(sess->rx_pool, (const pj_uint8_t*)packet,
+			        pkt_size, options, 
+				&msg, parsed_len, &response);
+    if (status != PJ_SUCCESS) {
+	LOG_ERR_(sess, "STUN msg_decode() error", status);
+	if (response) {
+	    send_response(sess, token, sess->rx_pool, response, NULL,
+			  PJ_FALSE, src_addr, src_addr_len);
+	}
+	goto on_return;
+    }
+
+    dump_rx_msg(sess, msg, (unsigned)pkt_size, src_addr);
+
+    /* For requests, check if we have cached response */
+    status = check_cached_response(sess, sess->rx_pool, msg, 
+				   src_addr, src_addr_len);
+    if (status == PJ_SUCCESS) {
+	goto on_return;
+    }
+
+    /* Handle message */
+    if (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) ||
+	PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))
+    {
+	status = on_incoming_response(sess, options, 
+				      (const pj_uint8_t*) packet, 
+				      (unsigned)pkt_size, msg, 
+				      src_addr, src_addr_len);
+
+    } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) {
+
+	status = on_incoming_request(sess, options, token, sess->rx_pool, 
+				     (const pj_uint8_t*) packet, 
+				     (unsigned)pkt_size, 
+				     msg, src_addr, src_addr_len);
+
+    } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) {
+
+	status = on_incoming_indication(sess, token, sess->rx_pool, 
+					(const pj_uint8_t*) packet, 
+					(unsigned)pkt_size, msg, src_addr, 
+					src_addr_len);
+
+    } else {
+	pj_assert(!"Unexpected!");
+	status = PJ_EBUG;
+    }
+
+on_return:
+    pj_log_pop_indent();
+
+    if (pj_grp_lock_release(sess->grp_lock))
+	return PJ_EGONE;
+
+    return status;
+}
+
diff --git a/jni/pjproject-android/.svn/pristine/f8/f838216083b8163c5b79a4cfb9408b62b593c24f.svn-base b/jni/pjproject-android/.svn/pristine/f8/f838216083b8163c5b79a4cfb9408b62b593c24f.svn-base
new file mode 100644
index 0000000..ac38841
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f838216083b8163c5b79a4cfb9408b62b593c24f.svn-base
@@ -0,0 +1,27 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 
+ */
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+    
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    int retVal = UIApplicationMain(argc, argv, nil, nil);
+    [pool release];
+    return retVal;
+}
diff --git a/jni/pjproject-android/.svn/pristine/f8/f84040453d29d4d765e99e0f053d83b6727ba71f.svn-base b/jni/pjproject-android/.svn/pristine/f8/f84040453d29d4d765e99e0f053d83b6727ba71f.svn-base
new file mode 100644
index 0000000..ed18206
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f84040453d29d4d765e99e0f053d83b6727ba71f.svn-base
@@ -0,0 +1,956 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 "test.h"
+
+#if INCLUDE_HTTP_CLIENT_TEST
+
+#define THIS_FILE	    "test_http"
+//#define VERBOSE
+#define STR_PREC(s) (int)s.slen, s.ptr
+#define USE_LOCAL_SERVER
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+
+#define ACTION_REPLY	0
+#define ACTION_IGNORE	-1
+
+static struct server_t
+{
+    pj_sock_t	     sock;
+    pj_uint16_t	     port;
+    pj_thread_t	    *thread;
+
+    /* Action:
+     *	0:    reply with the response in resp.
+     * -1:    ignore query (to simulate timeout).
+     * other: reply with that error
+     */
+    int		    action;
+    pj_bool_t       send_content_length;
+    unsigned	    data_size;
+    unsigned        buf_size;
+} g_server;
+
+static pj_bool_t thread_quit;
+static pj_timer_heap_t *timer_heap;
+static pj_ioqueue_t *ioqueue;
+static pj_pool_t *pool;
+static pj_http_req *http_req;
+static pj_bool_t test_cancel = PJ_FALSE;
+static pj_size_t total_size;
+static pj_size_t send_size = 0;
+static pj_status_t sstatus;
+static pj_sockaddr_in addr;
+static int counter = 0;
+
+static int server_thread(void *p)
+{
+    struct server_t *srv = (struct server_t*)p;
+    char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size);
+    pj_sock_t newsock = PJ_INVALID_SOCKET;
+
+    while (!thread_quit) {
+	pj_ssize_t pkt_len;
+	int rc;
+        pj_fd_set_t rset;
+	pj_time_val timeout = {0, 500};
+
+	while (!thread_quit) {
+	    PJ_FD_ZERO(&rset);
+	    PJ_FD_SET(srv->sock, &rset);
+	    rc = pj_sock_select((int)srv->sock+1, &rset, NULL, NULL, &timeout);
+	    if (rc != 1) {
+		continue;
+	    }
+
+	    rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL);
+	    if (rc == PJ_SUCCESS) {
+		break;
+	    }
+	}
+
+	if (thread_quit)
+	    break;
+
+	while (!thread_quit) {
+            PJ_FD_ZERO(&rset);
+            PJ_FD_SET(newsock, &rset);
+            rc = pj_sock_select((int)newsock+1, &rset, NULL, NULL, &timeout);
+            if (rc != 1) {
+        	PJ_LOG(3,("http test", "client timeout"));
+                continue;
+            }
+
+            pkt_len = srv->buf_size;
+            rc = pj_sock_recv(newsock, pkt, &pkt_len, 0);
+            if (rc == PJ_SUCCESS) {
+                break;
+            }
+        }
+
+	if (thread_quit)
+	    break;
+
+	/* Simulate network RTT */
+	pj_thread_sleep(50);
+
+	if (srv->action == ACTION_IGNORE) {
+	    continue;
+	} else if (srv->action == ACTION_REPLY) {
+            pj_size_t send_size = 0;
+	    unsigned ctr = 0;
+            pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n");
+            if (srv->send_content_length) {
+                pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), 
+                                "Content-Length: %d\r\n",
+                                srv->data_size);
+            }
+            pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n");
+            pkt_len = pj_ansi_strlen(pkt);
+            rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
+            if (rc != PJ_SUCCESS) {
+        	pj_sock_close(newsock);
+        	continue;
+            }
+            while (send_size < srv->data_size) {
+                pkt_len = srv->data_size - send_size;
+                if (pkt_len > (signed)srv->buf_size)
+                    pkt_len = srv->buf_size;
+                send_size += pkt_len;
+                pj_create_random_string(pkt, pkt_len);
+                pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr);
+                pkt[pj_ansi_strlen(pkt)] = '\n';
+		rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
+		if (rc != PJ_SUCCESS)
+		    break;
+            }
+            pj_sock_close(newsock);
+	}
+    }
+
+    return 0;
+}
+
+static void on_data_read(pj_http_req *hreq, void *data, pj_size_t size)
+{
+    PJ_UNUSED_ARG(hreq);
+    PJ_UNUSED_ARG(data);
+
+    PJ_LOG(5, (THIS_FILE, "\nData received: %d bytes", size));
+    if (size > 0) {
+#ifdef VERBOSE
+        printf("%.*s\n", (int)size, (char *)data);
+#endif
+    }
+}
+
+static void on_send_data(pj_http_req *hreq,
+                         void **data, pj_size_t *size)
+{
+    char *sdata;
+    pj_size_t sendsz = 8397;
+
+    PJ_UNUSED_ARG(hreq);
+
+    if (send_size + sendsz > total_size) {
+        sendsz = total_size - send_size;
+    }
+    send_size += sendsz;
+
+    sdata = (char*)pj_pool_alloc(pool, sendsz);
+    pj_create_random_string(sdata, sendsz);
+    pj_ansi_sprintf(sdata, "\nSegment #%d\n", ++counter);
+    *data = sdata;
+    *size = sendsz;
+
+    PJ_LOG(5, (THIS_FILE, "\nSending data progress: %d out of %d bytes", 
+           send_size, total_size));
+}
+
+
+static void on_complete(pj_http_req *hreq, pj_status_t status,
+                        const pj_http_resp *resp)
+{
+    PJ_UNUSED_ARG(hreq);
+
+    if (status == PJ_ECANCELLED) {
+        PJ_LOG(5, (THIS_FILE, "Request cancelled"));
+        return;
+    } else if (status == PJ_ETIMEDOUT) {
+        PJ_LOG(5, (THIS_FILE, "Request timed out!"));
+        return;
+    } else if (status != PJ_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Error %d", status));
+        return;
+    }
+    PJ_LOG(5, (THIS_FILE, "\nData completed: %d bytes", resp->size));
+    if (resp->size > 0 && resp->data) {
+#ifdef VERBOSE
+        printf("%.*s\n", (int)resp->size, (char *)resp->data);
+#endif
+    }
+}
+
+static void on_response(pj_http_req *hreq, const pj_http_resp *resp)
+{
+    pj_size_t i;
+
+    PJ_UNUSED_ARG(hreq);
+    PJ_UNUSED_ARG(resp);
+    PJ_UNUSED_ARG(i);
+
+#ifdef VERBOSE
+    printf("%.*s, %d, %.*s\n", STR_PREC(resp->version),
+           resp->status_code, STR_PREC(resp->reason));
+    for (i = 0; i < resp->headers.count; i++) {
+        printf("%.*s : %.*s\n", 
+               STR_PREC(resp->headers.header[i].name),
+               STR_PREC(resp->headers.header[i].value));
+    }
+#endif
+
+    if (test_cancel) {
+	/* Need to delay closing the client socket here, otherwise the
+	 * server will get SIGPIPE when sending response.
+	 */
+	pj_thread_sleep(100);
+        pj_http_req_cancel(hreq, PJ_TRUE);
+        test_cancel = PJ_FALSE;
+    }
+}
+
+
+pj_status_t parse_url(const char *url, pj_http_url *hurl)
+{
+    pj_str_t surl;
+    pj_status_t status;
+
+    pj_cstr(&surl, url);
+    status = pj_http_req_parse_url(&surl, hurl);
+#ifdef VERBOSE
+    if (!status) {
+        printf("URL: %s\nProtocol: %.*s\nHost: %.*s\nPort: %d\nPath: %.*s\n\n",
+               url, STR_PREC(hurl->protocol), STR_PREC(hurl->host),
+               hurl->port, STR_PREC(hurl->path));
+    } else {
+    }
+#endif
+    return status;
+}
+
+static int parse_url_test()
+{
+    struct test_data
+    {
+	char *url;
+	pj_status_t result;
+	const char *username;
+	const char *passwd;
+	const char *host;
+	int port;
+	const char *path;
+    } test_data[] =
+    {
+	/* Simple URL without '/' in the end */
+        {"http://www.pjsip.org", PJ_SUCCESS, "", "", "www.pjsip.org", 80, "/"},
+
+        /* Simple URL with port number but without '/' in the end */
+        {"http://pjsip.org:8080", PJ_SUCCESS, "", "", "pjsip.org", 8080, "/"},
+
+        /* URL with path */
+        {"http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6",
+        	PJ_SUCCESS, "", "", "127.0.0.1", 280,
+        	"/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6"},
+
+	/* URL with port and path */
+	{"http://pjsip.org:81/about-us/", PJ_SUCCESS, "", "", "pjsip.org", 81, "/about-us/"},
+
+	/* unsupported protocol */
+	{"ftp://www.pjsip.org", PJ_ENOTSUP, "", "", "", 80, ""},
+
+	/* invalid format */
+	{"http:/pjsip.org/about-us/", PJLIB_UTIL_EHTTPINURL, "", "", "", 80, ""},
+
+	/* invalid port number */
+	{"http://pjsip.org:xyz/", PJLIB_UTIL_EHTTPINPORT, "", "", "", 80, ""},
+
+	/* with username and password */
+	{"http://user:pass@pjsip.org", PJ_SUCCESS, "user", "pass", "pjsip.org", 80, "/"},
+
+	/* password only*/
+	{"http://:pass@pjsip.org", PJ_SUCCESS, "", "pass", "pjsip.org", 80, "/"},
+
+	/* user only*/
+	{"http://user:@pjsip.org", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/"},
+
+	/* empty username and passwd*/
+	{"http://:@pjsip.org", PJ_SUCCESS, "", "", "pjsip.org", 80, "/"},
+
+	/* '@' character in username and path */
+	{"http://user@pjsip.org/@", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/@"},
+
+	/* '@' character in path */
+	{"http://pjsip.org/@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/@"},
+
+	/* '@' character in path */
+	{"http://pjsip.org/one@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/one@"},
+
+	/* Invalid URL */
+	{"http://:", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://@", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:/", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:///", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://@/", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:///@", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://:::", PJ_EINVAL, "", "", "", 0, ""},
+    };
+    unsigned i;
+
+    for (i=0; i<PJ_ARRAY_SIZE(test_data); ++i) {
+	struct test_data *ptd;
+	pj_http_url hurl;
+	pj_status_t status;
+
+	ptd = &test_data[i];
+
+	PJ_LOG(3, (THIS_FILE, ".. %s", ptd->url));
+	status = parse_url(ptd->url, &hurl);
+
+	if (status != ptd->result) {
+	    PJ_LOG(3,(THIS_FILE, "%d", status));
+	    return -11;
+	}
+	if (status != PJ_SUCCESS)
+	    continue;
+	if (pj_strcmp2(&hurl.username, ptd->username))
+	    return -12;
+	if (pj_strcmp2(&hurl.passwd, ptd->passwd))
+	    return -13;
+	if (pj_strcmp2(&hurl.host, ptd->host))
+	    return -14;
+	if (hurl.port != ptd->port)
+	    return -15;
+	if (pj_strcmp2(&hurl.path, ptd->path))
+	    return -16;
+    }
+
+    return 0;
+}
+
+/* 
+ * GET request scenario 1: using on_response() and on_data_read()
+ * Server replies with content-length. Application cancels the 
+ * request upon receiving the response, then start it again.
+ */
+int http_client_test1()
+{
+    pj_str_t url;
+    pj_http_req_callback hcb;
+    pj_http_req_param param;
+    char urlbuf[80];
+
+    pj_bzero(&hcb, sizeof(hcb));
+    hcb.on_complete = &on_complete;
+    hcb.on_data_read = &on_data_read;
+    hcb.on_response = &on_response;
+    pj_http_req_param_default(&param);
+
+    /* Create pool, timer, and ioqueue */
+    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+    if (pj_timer_heap_create(pool, 16, &timer_heap))
+        return -31;
+    if (pj_ioqueue_create(pool, 16, &ioqueue))
+        return -32;
+
+#ifdef USE_LOCAL_SERVER
+
+    thread_quit = PJ_FALSE;
+    g_server.action = ACTION_REPLY;
+    g_server.send_content_length = PJ_TRUE;
+    g_server.data_size = 2970;
+    g_server.buf_size = 1024;
+
+    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
+                             &g_server.sock);
+    if (sstatus != PJ_SUCCESS)
+        return -41;
+
+    pj_sockaddr_in_init(&addr, NULL, 0);
+
+    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
+    if (sstatus != PJ_SUCCESS)
+        return -43;
+
+    {
+	pj_sockaddr_in addr;
+	int addr_len = sizeof(addr);
+	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
+	if (sstatus != PJ_SUCCESS)
+	    return -44;
+	g_server.port = pj_sockaddr_in_get_port(&addr);
+	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
+			 "http://127.0.0.1:%d/about-us/",
+			 g_server.port);
+	url = pj_str(urlbuf);
+    }
+
+    sstatus = pj_sock_listen(g_server.sock, 8);
+    if (sstatus != PJ_SUCCESS)
+        return -45;
+
+    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
+                               0, 0, &g_server.thread);
+    if (sstatus != PJ_SUCCESS)
+        return -47;
+
+#else
+    pj_cstr(&url, "http://www.teluu.com/about-us/");
+#endif
+
+    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
+                           &param, &hcb, &http_req))
+        return -33;
+
+    test_cancel = PJ_TRUE;
+    if (pj_http_req_start(http_req))
+        return -35;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+    if (pj_http_req_start(http_req))
+        return -37;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_TRUE;
+    pj_thread_join(g_server.thread);
+    pj_sock_close(g_server.sock);
+#endif
+
+    pj_http_req_destroy(http_req);
+    pj_ioqueue_destroy(ioqueue);
+    pj_timer_heap_destroy(timer_heap);
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+/* 
+ * GET request scenario 2: using on_complete() to get the 
+ * complete data. Server does not reply with content-length.
+ * Request timed out, application sets a longer timeout, then
+ * then restart the request.
+ */
+int http_client_test2()
+{
+    pj_str_t url;
+    pj_http_req_callback hcb;
+    pj_http_req_param param;
+    pj_time_val timeout;
+    char urlbuf[80];
+
+    pj_bzero(&hcb, sizeof(hcb));
+    hcb.on_complete = &on_complete;
+    hcb.on_response = &on_response;
+    pj_http_req_param_default(&param);
+
+    /* Create pool, timer, and ioqueue */
+    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+    if (pj_timer_heap_create(pool, 16, &timer_heap))
+        return -41;
+    if (pj_ioqueue_create(pool, 16, &ioqueue))
+        return -42;
+
+#ifdef USE_LOCAL_SERVER
+
+    pj_cstr(&url, "http://127.0.0.1:380");
+    param.timeout.sec = 0;
+    param.timeout.msec = 2000;
+
+    thread_quit = PJ_FALSE;
+    g_server.action = ACTION_IGNORE;
+    g_server.send_content_length = PJ_FALSE;
+    g_server.data_size = 4173;
+    g_server.buf_size = 1024;
+
+    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
+                             &g_server.sock);
+    if (sstatus != PJ_SUCCESS)
+        return -41;
+
+    pj_sockaddr_in_init(&addr, NULL, 0);
+
+    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
+    if (sstatus != PJ_SUCCESS)
+        return -43;
+
+    {
+	pj_sockaddr_in addr;
+	int addr_len = sizeof(addr);
+	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
+	if (sstatus != PJ_SUCCESS)
+	    return -44;
+	g_server.port = pj_sockaddr_in_get_port(&addr);
+	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
+			 "http://127.0.0.1:%d",
+			 g_server.port);
+	url = pj_str(urlbuf);
+    }
+
+    sstatus = pj_sock_listen(g_server.sock, 8);
+    if (sstatus != PJ_SUCCESS)
+        return -45;
+
+    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
+                               0, 0, &g_server.thread);
+    if (sstatus != PJ_SUCCESS)
+        return -47;
+
+#else
+    pj_cstr(&url, "http://www.google.com.sg");
+    param.timeout.sec = 0;
+    param.timeout.msec = 50;
+#endif
+
+    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept",
+			     (char*)"image/gif, image/x-xbitmap, image/jpeg, "
+				    "image/pjpeg, application/x-ms-application,"
+				    " application/vnd.ms-xpsdocument, "
+			            "application/xaml+xml, "
+			            "application/x-ms-xbap, "
+			            "application/x-shockwave-flash, "
+			            "application/vnd.ms-excel, "
+			            "application/vnd.ms-powerpoint, "
+			            "application/msword, */*");
+    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept-Language",
+	                      (char*)"en-sg");
+    pj_http_headers_add_elmt2(&param.headers, (char*)"User-Agent",
+                              (char*)"Mozilla/4.0 (compatible; MSIE 7.0; "
+                                     "Windows NT 6.0; SLCC1; "
+                                     ".NET CLR 2.0.50727; "
+                                     ".NET CLR 3.0.04506)");
+    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
+                           &param, &hcb, &http_req))
+        return -43;
+
+    if (pj_http_req_start(http_req))
+        return -45;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    g_server.action = ACTION_REPLY;
+#endif
+
+    timeout.sec = 0; timeout.msec = 10000;
+    pj_http_req_set_timeout(http_req, &timeout);
+    if (pj_http_req_start(http_req))
+        return -47;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_TRUE;
+    pj_thread_join(g_server.thread);
+    pj_sock_close(g_server.sock);
+#endif
+
+    pj_http_req_destroy(http_req);
+    pj_ioqueue_destroy(ioqueue);
+    pj_timer_heap_destroy(timer_heap);
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * PUT request scenario 1: sending the whole data at once
+ */
+int http_client_test_put1()
+{
+    pj_str_t url;
+    pj_http_req_callback hcb;
+    pj_http_req_param param;
+    char *data;
+    int length = 3875;
+    char urlbuf[80];
+
+    pj_bzero(&hcb, sizeof(hcb));
+    hcb.on_complete = &on_complete;
+    hcb.on_data_read = &on_data_read;
+    hcb.on_response = &on_response;
+
+    /* Create pool, timer, and ioqueue */
+    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+    if (pj_timer_heap_create(pool, 16, &timer_heap))
+        return -51;
+    if (pj_ioqueue_create(pool, 16, &ioqueue))
+        return -52;
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_FALSE;
+    g_server.action = ACTION_REPLY;
+    g_server.send_content_length = PJ_TRUE;
+    g_server.data_size = 0;
+    g_server.buf_size = 4096;
+
+    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
+                             &g_server.sock);
+    if (sstatus != PJ_SUCCESS)
+        return -41;
+
+    pj_sockaddr_in_init(&addr, NULL, 0);
+
+    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
+    if (sstatus != PJ_SUCCESS)
+        return -43;
+
+    {
+	pj_sockaddr_in addr;
+	int addr_len = sizeof(addr);
+	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
+	if (sstatus != PJ_SUCCESS)
+	    return -44;
+	g_server.port = pj_sockaddr_in_get_port(&addr);
+	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
+			 "http://127.0.0.1:%d/test/test.txt",
+			 g_server.port);
+	url = pj_str(urlbuf);
+    }
+
+    sstatus = pj_sock_listen(g_server.sock, 8);
+    if (sstatus != PJ_SUCCESS)
+        return -45;
+
+    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
+                               0, 0, &g_server.thread);
+    if (sstatus != PJ_SUCCESS)
+        return -47;
+
+#else
+    pj_cstr(&url, "http://127.0.0.1:280/test/test.txt");
+
+#endif
+
+    pj_http_req_param_default(&param);
+    pj_strset2(&param.method, (char*)"PUT");
+    data = (char*)pj_pool_alloc(pool, length);
+    pj_create_random_string(data, length);
+    pj_ansi_sprintf(data, "PUT test\n");
+    param.reqdata.data = data;
+    param.reqdata.size = length;
+    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
+                           &param, &hcb, &http_req))
+        return -53;
+
+    if (pj_http_req_start(http_req))
+        return -55;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_TRUE;
+    pj_thread_join(g_server.thread);
+    pj_sock_close(g_server.sock);
+#endif
+
+    pj_http_req_destroy(http_req);
+    pj_ioqueue_destroy(ioqueue);
+    pj_timer_heap_destroy(timer_heap);
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * PUT request scenario 2: using on_send_data() callback to
+ * sending the data in chunks
+ */
+int http_client_test_put2()
+{
+    pj_str_t url;
+    pj_http_req_callback hcb;
+    pj_http_req_param param;
+    char urlbuf[80];
+
+    pj_bzero(&hcb, sizeof(hcb));
+    hcb.on_complete = &on_complete;
+    hcb.on_send_data = &on_send_data;
+    hcb.on_data_read = &on_data_read;
+    hcb.on_response = &on_response;
+
+    /* Create pool, timer, and ioqueue */
+    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+    if (pj_timer_heap_create(pool, 16, &timer_heap))
+        return -51;
+    if (pj_ioqueue_create(pool, 16, &ioqueue))
+        return -52;
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_FALSE;
+    g_server.action = ACTION_REPLY;
+    g_server.send_content_length = PJ_TRUE;
+    g_server.data_size = 0;
+    g_server.buf_size = 16384;
+
+    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
+                             &g_server.sock);
+    if (sstatus != PJ_SUCCESS)
+        return -41;
+
+    pj_sockaddr_in_init(&addr, NULL, 0);
+
+    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
+    if (sstatus != PJ_SUCCESS)
+        return -43;
+
+    {
+	pj_sockaddr_in addr;
+	int addr_len = sizeof(addr);
+	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
+	if (sstatus != PJ_SUCCESS)
+	    return -44;
+	g_server.port = pj_sockaddr_in_get_port(&addr);
+	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
+			 "http://127.0.0.1:%d/test/test2.txt",
+			 g_server.port);
+	url = pj_str(urlbuf);
+    }
+
+    sstatus = pj_sock_listen(g_server.sock, 8);
+    if (sstatus != PJ_SUCCESS)
+        return -45;
+
+    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
+                               0, 0, &g_server.thread);
+    if (sstatus != PJ_SUCCESS)
+        return -47;
+
+#else
+    pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
+
+#endif
+
+    pj_http_req_param_default(&param);
+    pj_strset2(&param.method, (char*)"PUT");
+    total_size = 15383;
+    send_size = 0;
+    param.reqdata.total_size = total_size;
+    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
+                           &param, &hcb, &http_req))
+        return -53;
+
+    if (pj_http_req_start(http_req))
+        return -55;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_TRUE;
+    pj_thread_join(g_server.thread);
+    pj_sock_close(g_server.sock);
+#endif
+
+    pj_http_req_destroy(http_req);
+    pj_ioqueue_destroy(ioqueue);
+    pj_timer_heap_destroy(timer_heap);
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+int http_client_test_delete()
+{
+    pj_str_t url;
+    pj_http_req_callback hcb;
+    pj_http_req_param param;
+    char urlbuf[80];
+
+    pj_bzero(&hcb, sizeof(hcb));
+    hcb.on_complete = &on_complete;
+    hcb.on_response = &on_response;
+
+    /* Create pool, timer, and ioqueue */
+    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
+    if (pj_timer_heap_create(pool, 16, &timer_heap))
+        return -61;
+    if (pj_ioqueue_create(pool, 16, &ioqueue))
+        return -62;
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_FALSE;
+    g_server.action = ACTION_REPLY;
+    g_server.send_content_length = PJ_TRUE;
+    g_server.data_size = 0;
+    g_server.buf_size = 1024;
+
+    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
+                             &g_server.sock);
+    if (sstatus != PJ_SUCCESS)
+        return -41;
+
+    pj_sockaddr_in_init(&addr, NULL, 0);
+
+    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
+    if (sstatus != PJ_SUCCESS)
+        return -43;
+
+    {
+	pj_sockaddr_in addr;
+	int addr_len = sizeof(addr);
+	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
+	if (sstatus != PJ_SUCCESS)
+	    return -44;
+	g_server.port = pj_sockaddr_in_get_port(&addr);
+	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
+			 "http://127.0.0.1:%d/test/test2.txt",
+			 g_server.port);
+	url = pj_str(urlbuf);
+    }
+
+    sstatus = pj_sock_listen(g_server.sock, 8);
+    if (sstatus != PJ_SUCCESS)
+        return -45;
+
+    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
+                               0, 0, &g_server.thread);
+    if (sstatus != PJ_SUCCESS)
+        return -47;
+
+#else
+    pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
+#endif
+
+    pj_http_req_param_default(&param);
+    pj_strset2(&param.method, (char*)"DELETE");
+    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
+                           &param, &hcb, &http_req))
+        return -63;
+
+    if (pj_http_req_start(http_req))
+        return -65;
+
+    while (pj_http_req_is_running(http_req)) {
+        pj_time_val delay = {0, 50};
+	pj_ioqueue_poll(ioqueue, &delay);
+	pj_timer_heap_poll(timer_heap, NULL);
+    }
+
+#ifdef USE_LOCAL_SERVER
+    thread_quit = PJ_TRUE;
+    pj_thread_join(g_server.thread);
+    pj_sock_close(g_server.sock);
+#endif
+
+    pj_http_req_destroy(http_req);
+    pj_ioqueue_destroy(ioqueue);
+    pj_timer_heap_destroy(timer_heap);
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+int http_client_test()
+{
+    int rc;
+    
+    PJ_LOG(3, (THIS_FILE, "..Testing URL parsing"));
+    rc = parse_url_test();
+    if (rc)
+        return rc;
+
+    PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 1"));
+    rc = http_client_test1();
+    if (rc)
+        return rc;
+
+    PJ_LOG(3, (THIS_FILE, "..Testing GET request scenario 2"));
+    rc = http_client_test2();
+    if (rc)
+        return rc;
+
+    PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 1"));
+    rc = http_client_test_put1();
+    if (rc)
+        return rc;
+
+    PJ_LOG(3, (THIS_FILE, "..Testing PUT request scenario 2"));
+    rc = http_client_test_put2();
+    if (rc)
+        return rc;
+
+    PJ_LOG(3, (THIS_FILE, "..Testing DELETE request"));
+    rc = http_client_test_delete();
+    if (rc)
+        return rc;
+
+    return PJ_SUCCESS;
+}
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_http_client_test;
+#endif	/* INCLUDE_HTTP_CLIENT_TEST */
diff --git a/jni/pjproject-android/.svn/pristine/f8/f85942d3536375cb79ebeb7f2cd722d19db9a282.svn-base b/jni/pjproject-android/.svn/pristine/f8/f85942d3536375cb79ebeb7f2cd722d19db9a282.svn-base
new file mode 100644
index 0000000..8cccd42
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f85942d3536375cb79ebeb7f2cd722d19db9a282.svn-base
@@ -0,0 +1,140 @@
+/* $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 
+ */
+#ifndef __PJ_COMPAT_OS_DARWINOS_H__
+#define __PJ_COMPAT_OS_DARWINOS_H__
+
+/**
+ * @file os_darwinos.h
+ * @brief Describes Darwin/MacOSX operating system specifics.
+ */
+
+#define PJ_OS_NAME		    "darwin"
+
+#define PJ_HAS_ARPA_INET_H	    1
+#define PJ_HAS_ASSERT_H		    1
+#define PJ_HAS_CTYPE_H		    1
+#define PJ_HAS_ERRNO_H		    1
+#define PJ_HAS_LINUX_SOCKET_H	    0
+#define PJ_HAS_MALLOC_H		    0
+#define PJ_HAS_NETDB_H		    1
+#define PJ_HAS_NETINET_IN_H	    1
+#define PJ_HAS_NETINET_TCP_H	    1
+#define PJ_HAS_SETJMP_H		    1
+#define PJ_HAS_STDARG_H		    1
+#define PJ_HAS_STDDEF_H		    1
+#define PJ_HAS_STDIO_H		    1
+#define PJ_HAS_STDLIB_H		    1
+#define PJ_HAS_STRING_H		    1
+#define PJ_HAS_SYS_IOCTL_H	    1
+#define PJ_HAS_SYS_SELECT_H	    1
+#define PJ_HAS_SYS_SOCKET_H	    1
+#define PJ_HAS_SYS_TIME_H	    1
+#define PJ_HAS_SYS_TIMEB_H	    1
+#define PJ_HAS_SYS_TYPES_H	    1
+#define PJ_HAS_TIME_H		    1
+#define PJ_HAS_UNISTD_H		    1
+
+#define PJ_HAS_MSWSOCK_H	    0
+#define PJ_HAS_WINSOCK_H	    0
+#define PJ_HAS_WINSOCK2_H	    0
+
+/* Is errno a good way to retrieve OS errors?
+ */
+#define PJ_HAS_ERRNO_VAR	    1
+
+/* Has inet_aton() ?
+ */   
+#define PJ_SOCK_HAS_INET_ATON	    1
+
+/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
+ * the status of non-blocking connect() operation.
+ */
+#define PJ_HAS_SO_ERROR             1
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket recv() can not return immediate daata.
+ */
+#define PJ_BLOCKING_ERROR_VAL       EWOULDBLOCK
+
+/* This value specifies the value set in errno by the OS when a non-blocking
+ * socket connect() can not get connected immediately.
+ */
+#define PJ_BLOCKING_CONNECT_ERROR_VAL   EINPROGRESS
+
+/* Default threading is enabled, unless it's overridden. */
+#ifndef PJ_HAS_THREADS
+#  define PJ_HAS_THREADS		(1)
+#endif
+
+#define PJ_HAS_HIGH_RES_TIMER		1
+#define PJ_HAS_MALLOC			1
+#ifndef PJ_OS_HAS_CHECK_STACK
+#   define PJ_OS_HAS_CHECK_STACK        0
+#endif
+#define PJ_NATIVE_STRING_IS_UNICODE	0
+
+#define PJ_ATOMIC_VALUE_TYPE		long
+
+/* Set 1 if native sockaddr_in has sin_len member. 
+ * Default: 0
+ */
+#define PJ_SOCKADDR_HAS_LEN		1
+
+/*
+ * gcc complains that it can not use precompiled header because
+ * the value of FD_SETSIZE that we declare in pj/config.h is
+ * different than the value in /usr/include/sys/types.h.
+ *
+ * This changes the default value for Darwin.
+ */
+#define PJ_IOQUEUE_MAX_HANDLES		1024
+
+/**
+ * If this macro is set, it tells select I/O Queue that select() needs to
+ * be given correct value of nfds (i.e. largest fd + 1). This requires
+ * select ioqueue to re-scan the descriptors on each registration and
+ * unregistration.
+ * If this macro is not set, then ioqueue will always give FD_SETSIZE for
+ * nfds argument when calling select().
+ *
+ * Default: 0
+ */
+#define PJ_SELECT_NEEDS_NFDS		0
+
+/* If 1, use Read/Write mutex emulation for platforms that don't support it */
+#define PJ_EMULATE_RWMUTEX		0
+
+/* If 1, pj_thread_create() should enforce the stack size when creating 
+ * threads.
+ * Default: 0 (let OS decide the thread's stack size).
+ */
+#define PJ_THREAD_SET_STACK_SIZE    	0
+
+/* If 1, pj_thread_create() should allocate stack from the pool supplied.
+ * Default: 0 (let OS allocate memory for thread's stack).
+ */
+#define PJ_THREAD_ALLOCATE_STACK    	0
+
+/* MacOS has had socklen since 10.4 */
+#define PJ_HAS_SOCKLEN_T		1
+
+
+#endif	/* __PJ_COMPAT_OS_DARWINOS_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/f8/f8818dc1d63605151861852d88f831d488ae3322.svn-base b/jni/pjproject-android/.svn/pristine/f8/f8818dc1d63605151861852d88f831d488ae3322.svn-base
new file mode 100644
index 0000000..d00ccb6
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f8818dc1d63605151861852d88f831d488ae3322.svn-base
@@ -0,0 +1,163 @@
+# By default, the test application includes main.o.
+# OS make file may override this with os-specific files
+export PJNATH_TEST_OBJS = main.o
+
+include ../../build.mak
+include ../../version.mak
+include $(PJDIR)/build/common.mak
+
+export LIBDIR := ../lib
+export BINDIR := ../bin
+
+RULES_MAK := $(PJDIR)/build/rules.mak
+
+PJLIB_LIB:=../../pjlib/lib/libpj-$(TARGET_NAME)$(LIBEXT)
+PJLIB_UTIL_LIB:=../../pjlib-util/lib/libpjlib-util-$(TARGET_NAME)$(LIBEXT)
+
+export PJNATH_LIB:=libpjnath-$(TARGET_NAME)$(LIBEXT)
+
+ifeq ($(PJ_SHARED_LIBRARIES),)
+else
+export PJNATH_SONAME := libpjnath.$(SHLIB_SUFFIX)
+export PJNATH_SHLIB := $(PJNATH_SONAME).$(PJ_VERSION_MAJOR)
+endif
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS 	:= $(CC_CFLAGS) $(OS_CFLAGS) $(HOST_CFLAGS) $(M_CFLAGS) \
+		   $(CFLAGS) $(CC_INC)../include $(CC_INC)../../pjlib/include \
+		   $(CC_INC)../../pjlib-util/include
+export _CXXFLAGS:= $(_CFLAGS) $(CC_CXXFLAGS) $(OS_CXXFLAGS) $(M_CXXFLAGS) \
+		   $(HOST_CXXFLAGS) $(CXXFLAGS)
+export _LDFLAGS := $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \
+		   $(APP_LDFLAGS) $(LDFLAGS) 
+
+###############################################################################
+# Defines for building PJNATH library
+#
+export PJNATH_SRCDIR = ../src/pjnath
+export PJNATH_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
+		errno.o ice_session.o ice_strans.o nat_detect.o stun_auth.o \
+		stun_msg.o stun_msg_dump.o stun_session.o stun_sock.o \
+		stun_transaction.o turn_session.o turn_sock.o
+export PJNATH_CFLAGS += $(_CFLAGS)
+export PJNATH_CXXFLAGS += $(_CXXFLAGS)
+export PJNATH_LDFLAGS += $(PJLIB_UTIL_LDLIB) $(PJLIB_LDLIB) $(_LDFLAGS)
+
+###############################################################################
+# Defines for building test application
+#
+export PJNATH_TEST_SRCDIR = ../src/pjnath-test
+export PJNATH_TEST_OBJS += ice_test.o stun.o sess_auth.o server.o concur_test.o \
+			    stun_sock_test.o turn_sock_test.o test.o
+export PJNATH_TEST_CFLAGS += $(_CFLAGS)
+export PJNATH_TEST_CXXFLAGS += $(_CXXFLAGS)
+export PJNATH_TEST_LDFLAGS += $(PJNATH_LDLIB) $(PJLIB_UTIL_LDLIB) $(PJLIB_LDLIB) $(_LDFLAGS)
+export PJNATH_TEST_EXE:=pjnath-test-$(TARGET_NAME)$(HOST_EXE)
+
+	
+###############################################################################
+# Defines for building TURN client application
+#
+export PJTURN_CLIENT_SRCDIR = ../src/pjturn-client
+export PJTURN_CLIENT_OBJS += client_main.o
+export PJTURN_CLIENT_CFLAGS += $(_CFLAGS)
+export PJTURN_CLIENT_CXXFLAGS += $(_CXXFLAGS)
+export PJTURN_CLIENT_LDFLAGS += $(PJNATH_LDLIB) $(PJLIB_UTIL_LDLIB) $(PJLIB_LDLIB) $(_LDFLAGS)
+export PJTURN_CLIENT_EXE:=pjturn-client-$(TARGET_NAME)$(HOST_EXE)
+
+###############################################################################
+# Defines for building TURN server application
+#
+export PJTURN_SRV_SRCDIR = ../src/pjturn-srv
+export PJTURN_SRV_OBJS += allocation.o auth.o listener_udp.o \
+			  listener_tcp.o server.o main.o
+export PJTURN_SRV_CFLAGS += $(_CFLAGS)
+export PJTURN_SRV_CXXFLAGS += $(_CXXFLAGS)
+export PJTURN_SRV_LDFLAGS += $(PJNATH_LDLIB) $(PJLIB_UTIL_LDLIB) $(PJLIB_LDLIB) $(_LDFLAGS)
+export PJTURN_SRV_EXE:=pjturn-srv-$(TARGET_NAME)$(HOST_EXE)
+
+	
+	
+export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT 
+###############################################################################
+# Main entry
+#
+# $(TARGET) is defined in os-$(OS_NAME).mak file in current directory.
+#
+TARGETS := $(PJNATH_LIB) $(PJNATH_SONAME) $(PJNATH_TEST_EXE) $(PJTURN_CLIENT_EXE) $(PJTURN_SRV_EXE)
+
+all: $(TARGETS)
+
+doc:
+	cd .. && rm -rf docs/$(PJ_VERSION) && doxygen docs/doxygen.cfg
+	@if [ -n "$(WWWDIR)" ] && ! [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjnath/docs/html" ] ; then \
+		echo "Creating docs/$(PJ_VERSION)/pjnath/docs/html" ; \
+		mkdir -p $(WWWDIR)/docs/$(PJ_VERSION)/pjnath/docs/html ; \
+	fi 
+	@if [ -n "$(WWWDIR)" ] && [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjnath/docs/html" ] ; then \
+		echo "Copying docs/$(PJ_VERSION) to $(WWWDIR)/docs/$(PJ_VERSION)/pjnath/docs/html.." ; \
+		cp -v -a ../docs/$(PJ_VERSION)/html/* $(WWWDIR)/docs/$(PJ_VERSION)/pjnath/docs/html/ ; \
+	fi
+
+dep: depend
+distclean: realclean
+
+.PHONY: all dep depend clean realclean distclean
+.PHONY: $(TARGETS)
+.PHONY: $(PJNATH_LIB) $(PJNATH_SONAME)
+.PHONY: $(PJNATH_TEST_EXE) $(PJTURN_CLIENT_EXE) $(PJTURN_SRV_EXE)
+
+pjnath: $(PJNATH_LIB)
+$(PJNATH_SONAME): $(PJNATH_LIB)
+$(PJNATH_LIB) $(PJNATH_SONAME): $(PJLIB_LIB) $(PJLIB_SONAME) $(PJLIB_UTIL_LIB) $(PJLIB_UTIL_SONAME)
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH app=pjnath $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
+
+pjnath-test: $(PJNATH_TEST_EXE)
+$(PJNATH_TEST_EXE): $(PJNATH_LIB) $(PJNATH_SONAME)
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH_TEST app=pjnath-test $(subst /,$(HOST_PSEP),$(BINDIR)/$@)
+
+pjturn-client: $(PJTURN_CLIENT_EXE)
+$(PJTURN_CLIENT_EXE): $(PJNATH_LIB) $(PJNATH_SONAME)
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_CLIENT app=pjturn-client $(subst /,$(HOST_PSEP),$(BINDIR)/$@)
+
+pjturn-srv: $(PJTURN_SRV_EXE)
+$(PJTURN_SRV_EXE): $(PJNATH_LIB) $(PJNATH_SONAME)
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_SRV app=pjturn-srv $(subst /,$(HOST_PSEP),$(BINDIR)/$@)
+
+.PHONY: pjnath.ko
+pjnath.ko:
+	echo Making $@
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH app=pjnath $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
+
+.PHONY: pjnath-test.ko
+pjnath-test.ko:
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH_TEST app=pjnath-test $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
+
+clean:
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH app=pjnath $@
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH_TEST app=pjnath-test $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_CLIENT app=pjturn-client $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_SRV app=pjturn-srv $@
+
+realclean:
+	$(subst @@,$(subst /,$(HOST_PSEP),.pjnath-$(TARGET_NAME).depend),$(HOST_RMR))
+	$(subst @@,$(subst /,$(HOST_PSEP),.pjnath-test-$(TARGET_NAME).depend),$(HOST_RMR))
+	$(subst @@,$(subst /,$(HOST_PSEP),.pjturn-client-$(TARGET_NAME).depend),$(HOST_RMR))
+	$(subst @@,$(subst /,$(HOST_PSEP),.pjturn-srv-$(TARGET_NAME).depend),$(HOST_RMR))
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH app=pjnath $@
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH_TEST app=pjnath-test $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_CLIENT app=pjturn-client $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_SRV app=pjturn-srv $@
+
+depend:
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH app=pjnath $@
+	$(MAKE) -f $(RULES_MAK) APP=PJNATH_TEST app=pjnath-test $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_CLIENT app=pjturn-client $@
+	$(MAKE) -f $(RULES_MAK) APP=PJTURN_SRV app=pjturn-srv $@
+	echo '$(BINDIR)/$(PJNATH_TEST_EXE): $(LIBDIR)/$(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB)' >> .pjnath-test-$(TARGET_NAME).depend
+	echo '$(BINDIR)/$(PJTURN_CLIENT_EXE): $(LIBDIR)/$(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB)' >> .pjturn-client-$(TARGET_NAME).depend
+	echo '$(BINDIR)/$(PJTURN_SRV_EXE): $(LIBDIR)/$(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB)' >> .pjturn-srv-$(TARGET_NAME).depend
+
+
diff --git a/jni/pjproject-android/.svn/pristine/f8/f888237bd89b873ec98caf6d482bf57507817fff.svn-base b/jni/pjproject-android/.svn/pristine/f8/f888237bd89b873ec98caf6d482bf57507817fff.svn-base
new file mode 100644
index 0000000..d5eed81
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f888237bd89b873ec98caf6d482bf57507817fff.svn-base
@@ -0,0 +1,461 @@
+/****************************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   © 2004 Polycom, Inc.
+**
+**	 All rights reserved.
+**
+****************************************************************************************/
+
+/****************************************************************************************
+  Filename:    common.c    
+
+  Purpose:     Contains the functions used for both G.722.1 Annex C encoder and decoder
+		
+  Design Notes:
+
+****************************************************************************************/
+/****************************************************************************************
+ Include files                                                           
+****************************************************************************************/
+#include "defs.h"
+#include "huff_def.h"
+#include "huff_tab.h"
+#include "tables.h"
+#include "count.h"
+
+/****************************************************************************************
+ Function:    categorize
+
+ Syntax:      void categorize(Word16 number_of_available_bits,   
+                              Word16 number_of_regions,
+                              Word16 num_categorization_control_possibilities,
+                              Word16 rms_index,                  
+                              Word16 power_categories,           
+                              Word16 category_balances)          
+
+                  inputs:   number_of_regions
+                            num_categorization_control_possibilities
+                            number_of_available_bits
+                            rms_index[MAX_NUMBER_OF_REGIONS]                              
+                  
+                  outputs:  power_categories[MAX_NUMBER_OF_REGIONS]                       
+                            category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]
+
+ Description: Computes a series of categorizations 
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.14      |     0.14
+          -------|--------------|----------------  
+            MAX  |    0.15      |     0.15
+          -------|--------------|---------------- 
+   			
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.42      |     0.45       |     0.48   
+          -------|--------------|----------------|----------------
+            MAX  |    0.47      |     0.52       |     0.52   
+          -------|--------------|----------------|----------------
+
+****************************************************************************************/
+void categorize(Word16 number_of_available_bits,
+		        Word16 number_of_regions,
+		        Word16 num_categorization_control_possibilities,
+		        Word16 *rms_index,
+		        Word16 *power_categories,
+		        Word16 *category_balances)
+{
+    
+    Word16 offset;
+    Word16 temp;
+    Word16 frame_size;
+
+    /* At higher bit rates, there is an increase for most categories in average bit
+       consumption per region. We compensate for this by pretending we have fewer
+       available bits. */
+    test();
+    if (number_of_regions == NUMBER_OF_REGIONS)
+    {
+        frame_size = DCT_LENGTH;
+    }
+    else
+    {
+        frame_size = MAX_DCT_LENGTH;
+    }
+
+    temp = sub(number_of_available_bits,frame_size);
+    
+    test();
+    if (temp > 0)
+    {
+        number_of_available_bits = sub(number_of_available_bits,frame_size);
+        number_of_available_bits = extract_l(L_mult0(number_of_available_bits,5));
+        number_of_available_bits = shr_nocheck(number_of_available_bits,3);
+        number_of_available_bits = add(number_of_available_bits,frame_size);
+    }
+
+    /* calculate the offset using the original category assignments */
+    offset = calc_offset(rms_index,number_of_regions,number_of_available_bits);
+
+
+
+    /* compute the power categories based on the uniform offset */
+    compute_raw_pow_categories(power_categories,rms_index,number_of_regions,offset);
+    
+    
+    /* adjust the category assignments */
+    /* compute the new power categories and category balances */
+    comp_powercat_and_catbalance(power_categories,category_balances,rms_index,number_of_available_bits,number_of_regions,num_categorization_control_possibilities,offset);
+
+}
+    
+/***************************************************************************
+ Function:    comp_powercat_and_catbalance
+
+ Syntax:      void comp_powercat_and_catbalance(Word16 *power_categories,
+                                                Word16 *category_balances,
+                                                Word16 *rms_index,  
+                                                Word16 number_of_available_bits,                                  
+                                                Word16 number_of_regions,
+                                                Word16 num_categorization_control_possibilities,
+                                                Word16 offset)                                                    
+
+                
+                inputs:   *rms_index                              
+                          number_of_available_bits                 
+                          number_of_regions
+                          num_categorization_control_possibilities
+                          offset
+                           
+                outputs:  *power_categories  
+                          *category_balances 
+                
+                
+ Description: Computes the power_categories and the category balances
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.10      |     0.10
+          -------|--------------|----------------  
+            MAX  |    0.11      |     0.11
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.32      |     0.35       |     0.38   
+          -------|--------------|----------------|----------------
+            MAX  |    0.38      |     0.42       |     0.43   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void comp_powercat_and_catbalance(Word16 *power_categories,
+                                  Word16 *category_balances,
+                                  Word16 *rms_index,
+                                  Word16 number_of_available_bits,
+                                  Word16 number_of_regions,
+                                  Word16 num_categorization_control_possibilities,
+								  Word16 offset)
+{
+    
+    Word16 expected_number_of_code_bits;
+    Word16 region;
+    Word16 max_region;
+    Word16 j;
+    Word16 max_rate_categories[MAX_NUMBER_OF_REGIONS];
+    Word16 min_rate_categories[MAX_NUMBER_OF_REGIONS];
+    Word16 temp_category_balances[2*MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES];
+    Word16 raw_max, raw_min;
+    Word16 raw_max_index=0, raw_min_index=0;
+    Word16 max_rate_pointer, min_rate_pointer;
+    Word16 max, min;
+    Word16 itemp0;
+    Word16 itemp1;
+    Word16 min_plus_max;
+    Word16 two_x_number_of_available_bits;
+
+    Word16 temp;
+
+    expected_number_of_code_bits = 0;
+    move16();
+
+    for (region=0; region<number_of_regions; region++)
+        expected_number_of_code_bits = add(expected_number_of_code_bits,expected_bits_table[power_categories[region]]);
+
+
+    for (region=0; region<number_of_regions; region++) 
+    {
+        max_rate_categories[region] = power_categories[region];
+        move16();
+        
+        min_rate_categories[region] = power_categories[region];
+        move16();
+    }
+    
+    max = expected_number_of_code_bits;
+    move16();
+    min = expected_number_of_code_bits;
+    move16();
+    max_rate_pointer = num_categorization_control_possibilities;
+    move16();
+    min_rate_pointer = num_categorization_control_possibilities;
+    move16();
+    
+    for (j=0; j<num_categorization_control_possibilities-1; j++) 
+    {
+        min_plus_max = add(max,min);
+        two_x_number_of_available_bits = shl_nocheck(number_of_available_bits,1);
+        
+        temp = sub(min_plus_max,two_x_number_of_available_bits);
+        test();
+        if (temp <= 0) 
+        {
+            raw_min = 99;
+            move16();
+            /* Search from lowest freq regions to highest for best */
+            /* region to reassign to a higher bit rate category.   */
+            for (region=0; region<number_of_regions; region++) 
+            {
+                test();
+                if (max_rate_categories[region] > 0) 
+                {
+                    itemp0 = shl_nocheck(max_rate_categories[region],1);
+                    itemp1 = sub(offset,rms_index[region]);
+                    itemp0 = sub(itemp1,itemp0);
+                    
+                    temp = sub(itemp0,raw_min);
+                    test();
+                    if (temp < 0) 
+                    {
+                        raw_min = itemp0;
+                        raw_min_index = region;
+                    }
+                }
+            }
+            max_rate_pointer = sub(max_rate_pointer,1);
+            temp_category_balances[max_rate_pointer] = raw_min_index;
+            move16();
+
+        	max = sub(max,expected_bits_table[max_rate_categories[raw_min_index]]);
+        	max_rate_categories[raw_min_index] = sub(max_rate_categories[raw_min_index],1);
+        	move16();
+
+            max = add(max,expected_bits_table[max_rate_categories[raw_min_index]]);
+        }
+        else 
+        {
+            raw_max = -99;
+            move16();
+            /* Search from highest freq regions to lowest for best region to reassign to
+            a lower bit rate category. */
+            max_region = sub(number_of_regions,1);
+            for (region= max_region; region >= 0; region--) 
+            {
+                temp = sub(min_rate_categories[region],(NUM_CATEGORIES-1));
+                test();
+                if (temp < 0)
+                {
+                    itemp0 = shl_nocheck(min_rate_categories[region],1);
+                    itemp1 = sub(offset,rms_index[region]);
+                    itemp0 = sub(itemp1,itemp0);
+                    
+                    temp = sub(itemp0,raw_max);
+                    test();
+                    if (temp > 0) 
+                    {
+                        raw_max = itemp0;
+                        move16();
+                        raw_max_index = region;
+                        move16();
+                    }
+                }
+            }
+            temp_category_balances[min_rate_pointer] = raw_max_index;
+            move16();
+            
+            min_rate_pointer = add(min_rate_pointer,1);
+            min = sub(min,expected_bits_table[min_rate_categories[raw_max_index]]);
+            
+            min_rate_categories[raw_max_index] = add(min_rate_categories[raw_max_index],1);
+            move16();
+            
+            min = add(min,expected_bits_table[min_rate_categories[raw_max_index]]);
+        }
+    }
+    
+    for (region=0; region<number_of_regions; region++)
+    {
+        power_categories[region] = max_rate_categories[region];
+        move16();
+    }
+    
+    for (j=0; j<num_categorization_control_possibilities-1; j++)
+    {
+        category_balances[j] = temp_category_balances[max_rate_pointer++];
+        move16();
+    }
+
+}
+/***************************************************************************
+ Function:    calc_offset
+
+ Syntax:      offset=calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)  
+
+                input:  Word16 *rms_index
+                        Word16 number_of_regions
+                        Word16 available_bits
+                        
+                output: Word16 offset                        
+
+ Description: Calculates the the category offset.  This is the shift required
+              To get the most out of the number of available bits.  A binary 
+              type search is used to find the offset.
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.04      |     0.04
+          -------|--------------|----------------  
+            MAX  |    0.04      |     0.04
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.08      |     0.08       |     0.08   
+          -------|--------------|----------------|----------------
+            MAX  |    0.09      |     0.09       |     0.09   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+Word16 calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)    
+{
+
+    Word16 answer;
+    Word16 delta;
+    Word16 test_offset;
+    Word16 region,j;
+    Word16 power_cats[MAX_NUMBER_OF_REGIONS];
+    Word16 bits;
+    Word16 offset;
+    Word16 temp;
+
+    /* initialize vars */
+    answer = -32;
+    move16();
+    delta = 32;
+    move16();
+    
+    do 
+    {
+        test_offset = add(answer,delta);
+        
+        /* obtain a category for each region */
+        /* using the test offset             */
+        for (region=0; region<number_of_regions; region++) 
+        {
+            j = sub(test_offset,rms_index[region]);
+            j = shr_nocheck(j,1);
+            
+            /* Ensure j is between 0 and NUM_CAT-1 */
+            test();
+            if (j < 0) 
+            {
+                j = 0;
+                move16();
+            }
+            temp = sub(j,NUM_CATEGORIES-1);
+            test();
+            if (temp > 0) 
+            {
+                j = sub(NUM_CATEGORIES,1);
+                move16();
+            }
+            power_cats[region] = j;
+            move16();
+        }
+        bits = 0;
+        move16();
+
+        /* compute the number of bits that will be used given the cat assignments */
+        for (region=0; region<number_of_regions; region++)
+            bits = add(bits,expected_bits_table[power_cats[region]]);
+
+        /* if (bits > available_bits - 32) then divide the offset region for the bin search */
+        offset = sub(available_bits,32);
+        temp = sub(bits,offset);
+        test();
+        if (temp >= 0)
+        {
+            answer = test_offset;
+            move16();
+        }
+        delta = shr_nocheck(delta,1);
+        test(); /* for the while loop */
+    } while (delta > 0);
+
+    return(answer);
+}
+/***************************************************************************
+ Function:    compute_raw_pow_categories
+
+ Syntax:      void compute_raw_pow_categories(Word16 *power_categories,
+                                              Word16 *rms_index,
+                                              Word16 number_of_regions,
+                                              Word16 offset)
+              inputs:  *rms_index
+                       number_of_regions
+                       offset
+                    
+              outputs: *power_categories                    
+
+
+
+ Description: This function computes the power categories given the offset
+              This is kind of redundant since they were already computed
+              in calc_offset to determine the offset.
+
+ WMOPS:          |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.01      |     0.01
+          -------|--------------|----------------  
+            MAX  |    0.01      |     0.01
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.01      |     0.01       |     0.01   
+          -------|--------------|----------------|----------------
+            MAX  |    0.01      |     0.01       |     0.01   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void compute_raw_pow_categories(Word16 *power_categories,Word16 *rms_index,Word16 number_of_regions,Word16 offset)
+{
+    Word16 region;
+    Word16 j;
+    Word16 temp;
+
+    for (region=0; region<number_of_regions; region++) 
+    {
+        j = sub(offset,rms_index[region]);
+        j = shr_nocheck(j,1);
+        
+        /* make sure j is between 0 and NUM_CAT-1 */
+        test();
+        if (j < 0) 
+        {
+            j = 0;
+            move16();
+        }
+        temp = sub(j,(NUM_CATEGORIES-1));
+        test();
+        if (temp > 0) 
+            j = sub(NUM_CATEGORIES,1);
+        
+        power_categories[region] = j;
+        move16();
+    }
+}
+
diff --git a/jni/pjproject-android/.svn/pristine/f8/f8b5e580472624433ad17ea70b2c68f4fe2d2de9.svn-base b/jni/pjproject-android/.svn/pristine/f8/f8b5e580472624433ad17ea70b2c68f4fe2d2de9.svn-base
new file mode 100644
index 0000000..7081aed
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f8b5e580472624433ad17ea70b2c68f4fe2d2de9.svn-base
@@ -0,0 +1,226 @@
+# $Id$
+import time
+import imp
+import sys
+import inc_const as const
+from inc_cfg import *
+
+# Load configuration
+cfg_file = imp.load_source("cfg_file", ARGS[1])
+
+# Check media flow between ua1 and ua2
+def check_media(ua1, ua2):
+	ua1.send("#")
+	ua1.expect("#")
+	ua1.send("1122")
+	ua2.expect(const.RX_DTMF + "1")
+	ua2.expect(const.RX_DTMF + "1")
+	ua2.expect(const.RX_DTMF + "2")
+	ua2.expect(const.RX_DTMF + "2")
+
+
+# Test body function
+def test_func(t):
+	callee = t.process[0]
+	caller = t.process[1]
+
+	# if have_reg then wait for couple of seconds for PUBLISH
+	# to complete (just in case pUBLISH is used)
+	if callee.inst_param.have_reg:
+		time.sleep(1)
+	if caller.inst_param.have_reg:
+		time.sleep(1)
+
+	# Caller making call
+	caller.send("m")
+	caller.send(t.inst_params[0].uri)
+	caller.expect(const.STATE_CALLING)
+	
+	# Callee waits for call and answers with 180/Ringing
+	time.sleep(0.2)
+	callee.expect(const.EVENT_INCOMING_CALL)
+	callee.send("a")
+	callee.send("180")
+	callee.expect("SIP/2.0 180")
+	caller.expect("SIP/2.0 180")
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Callee answers with 200/OK
+	callee.send("a")
+	callee.send("200")
+
+	# Wait until call is connected in both endpoints
+	time.sleep(0.2)
+	caller.expect(const.STATE_CONFIRMED)
+	callee.expect(const.STATE_CONFIRMED)
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+	time.sleep(0.1)
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Test that media is okay
+	time.sleep(0.3)
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# Hold call by caller
+	caller.send("H")
+	caller.expect("INVITE sip:")
+	callee.expect("INVITE sip:")
+	caller.expect(const.MEDIA_HOLD)
+	callee.expect(const.MEDIA_HOLD)
+	
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Release hold
+	time.sleep(0.5)
+	caller.send("v")
+	caller.expect("INVITE sip:")
+	callee.expect("INVITE sip:")
+	caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
+	callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Test that media is okay
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Hold call by callee
+	callee.send("H")
+	callee.expect("INVITE sip:")
+	caller.expect("INVITE sip:")
+	caller.expect(const.MEDIA_HOLD)
+	callee.expect(const.MEDIA_HOLD)
+	
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Release hold
+	time.sleep(0.1)
+	callee.send("v")
+	callee.expect("INVITE sip:")
+	caller.expect("INVITE sip:")
+	callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
+	caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold")
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Test that media is okay
+	# Wait for some time for ICE negotiation
+	time.sleep(0.6)
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# UPDATE (by caller)
+	caller.send("U")
+	#caller.sync_stdout()
+	callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
+	caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
+	
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Test that media is okay
+	time.sleep(0.1)
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# UPDATE (by callee)
+	callee.send("U")
+	callee.expect("UPDATE sip:")
+	caller.expect("UPDATE sip:")
+	caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
+	callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE")
+	
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Test that media is okay
+	time.sleep(0.1)
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# Synchronize stdout
+	caller.sync_stdout()
+	callee.sync_stdout()
+
+	# Set codecs in both caller and callee so that there is
+	# no common codec between them.
+	# In caller we only enable PCMU, in callee we only enable PCMA
+	caller.send("Cp")
+	caller.expect("Enter codec")
+	caller.send("* 0")
+	caller.send("Cp")
+	caller.expect("Enter codec")
+	caller.send("pcmu 120")
+	
+	callee.send("Cp")
+	callee.expect("Enter codec")
+	callee.send("* 0")
+	callee.send("Cp")
+	callee.expect("Enter codec")
+	callee.send("pcma 120")
+
+	# Test when UPDATE fails (by callee)
+	callee.send("U")
+	caller.expect("SIP/2.0 488")
+	callee.expect("SIP/2.0 488")
+	callee.sync_stdout()
+	caller.sync_stdout()
+	
+	# Test that media is still okay
+	time.sleep(0.1)
+	check_media(caller, callee)
+	check_media(callee, caller)
+
+	# Test when UPDATE fails (by caller)
+	caller.send("U")
+	caller.expect("UPDATE sip:")
+	callee.expect("UPDATE sip:")
+	callee.expect("SIP/2.0 488")
+	caller.expect("SIP/2.0 488")
+	caller.sync_stdout()
+	callee.sync_stdout()
+	
+	# Test that media is still okay
+	time.sleep(0.1)
+	check_media(callee, caller)
+	check_media(caller, callee)
+
+	# Hangup call
+	time.sleep(0.1)
+	caller.send("h")
+
+	# Wait until calls are cleared in both endpoints
+	caller.expect(const.STATE_DISCONNECTED)
+	callee.expect(const.STATE_DISCONNECTED)
+	
+
+# Here where it all comes together
+test = cfg_file.test_param
+test.test_func = test_func
+
diff --git a/jni/pjproject-android/.svn/pristine/f8/f8c0405be84da517713c762ea3f4fb62ad6065d7.svn-base b/jni/pjproject-android/.svn/pristine/f8/f8c0405be84da517713c762ea3f4fb62ad6065d7.svn-base
new file mode 100644
index 0000000..a77340b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f8c0405be84da517713c762ea3f4fb62ad6065d7.svn-base
@@ -0,0 +1,949 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2012-2012 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 
+ */
+/* This file is the implementation of Android OpenSL ES audio device.
+ * The original code was originally part of CSipSimple
+ * (http://code.google.com/p/csipsimple/) and was kindly donated
+ * by Regis Montoya.
+ */
+
+#include <pjmedia-audiodev/audiodev_imp.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/string.h>
+#include <pjmedia/errno.h>
+
+#if defined(PJMEDIA_AUDIO_DEV_HAS_OPENSL) && PJMEDIA_AUDIO_DEV_HAS_OPENSL != 0
+
+#include <SLES/OpenSLES.h>
+
+#ifdef __ANDROID__
+    #include <SLES/OpenSLES_Android.h>
+    #include <SLES/OpenSLES_AndroidConfiguration.h>
+    #include <sys/system_properties.h>
+    #include <android/api-level.h>
+
+    #define W_SLBufferQueueItf SLAndroidSimpleBufferQueueItf
+    #define W_SLBufferQueueState SLAndroidSimpleBufferQueueState
+    #define W_SL_IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE
+#else
+    #define W_SLBufferQueueItf SLBufferQueueItf
+    #define W_SLBufferQueueState SLBufferQueueState
+    #define W_SL_IID_BUFFERQUEUE SL_IID_BUFFERQUEUE
+#endif
+
+#define THIS_FILE	"opensl_dev.c"
+#define DRIVER_NAME	"OpenSL"
+
+#define NUM_BUFFERS 2
+
+struct opensl_aud_factory
+{
+    pjmedia_aud_dev_factory  base;
+    pj_pool_factory         *pf;
+    pj_pool_t               *pool;
+    
+    SLObjectItf              engineObject;
+    SLEngineItf              engineEngine;
+    SLObjectItf              outputMixObject;
+};
+
+/*
+ * Sound stream descriptor.
+ * This struct may be used for both unidirectional or bidirectional sound
+ * streams.
+ */
+struct opensl_aud_stream
+{
+    pjmedia_aud_stream  base;
+    pj_pool_t          *pool;
+    pj_str_t            name;
+    pjmedia_dir         dir;
+    pjmedia_aud_param   param;
+    
+    void               *user_data;
+    pj_bool_t           quit_flag;
+    pjmedia_aud_rec_cb  rec_cb;
+    pjmedia_aud_play_cb play_cb;
+
+    pj_timestamp	play_timestamp;
+    pj_timestamp	rec_timestamp;
+    
+    pj_bool_t		rec_thread_initialized;
+    pj_thread_desc	rec_thread_desc;
+    pj_thread_t        *rec_thread;
+    
+    pj_bool_t		play_thread_initialized;
+    pj_thread_desc	play_thread_desc;
+    pj_thread_t        *play_thread;
+    
+    /* Player */
+    SLObjectItf         playerObj;
+    SLPlayItf           playerPlay;
+    SLVolumeItf         playerVol;
+    unsigned            playerBufferSize;
+    char               *playerBuffer[NUM_BUFFERS];
+    int                 playerBufIdx;
+    
+    /* Recorder */
+    SLObjectItf         recordObj;
+    SLRecordItf         recordRecord;
+    unsigned            recordBufferSize;
+    char               *recordBuffer[NUM_BUFFERS];
+    int                 recordBufIdx;
+
+    W_SLBufferQueueItf  playerBufQ;
+    W_SLBufferQueueItf  recordBufQ;
+};
+
+/* Factory prototypes */
+static pj_status_t opensl_init(pjmedia_aud_dev_factory *f);
+static pj_status_t opensl_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t opensl_refresh(pjmedia_aud_dev_factory *f);
+static unsigned opensl_get_dev_count(pjmedia_aud_dev_factory *f);
+static pj_status_t opensl_get_dev_info(pjmedia_aud_dev_factory *f,
+                                       unsigned index,
+                                       pjmedia_aud_dev_info *info);
+static pj_status_t opensl_default_param(pjmedia_aud_dev_factory *f,
+                                        unsigned index,
+                                        pjmedia_aud_param *param);
+static pj_status_t opensl_create_stream(pjmedia_aud_dev_factory *f,
+                                        const pjmedia_aud_param *param,
+                                        pjmedia_aud_rec_cb rec_cb,
+                                        pjmedia_aud_play_cb play_cb,
+                                        void *user_data,
+                                        pjmedia_aud_stream **p_aud_strm);
+
+/* Stream prototypes */
+static pj_status_t strm_get_param(pjmedia_aud_stream *strm,
+                                  pjmedia_aud_param *param);
+static pj_status_t strm_get_cap(pjmedia_aud_stream *strm,
+                                pjmedia_aud_dev_cap cap,
+                                void *value);
+static pj_status_t strm_set_cap(pjmedia_aud_stream *strm,
+                                pjmedia_aud_dev_cap cap,
+                                const void *value);
+static pj_status_t strm_start(pjmedia_aud_stream *strm);
+static pj_status_t strm_stop(pjmedia_aud_stream *strm);
+static pj_status_t strm_destroy(pjmedia_aud_stream *strm);
+
+static pjmedia_aud_dev_factory_op opensl_op =
+{
+    &opensl_init,
+    &opensl_destroy,
+    &opensl_get_dev_count,
+    &opensl_get_dev_info,
+    &opensl_default_param,
+    &opensl_create_stream,
+    &opensl_refresh
+};
+
+static pjmedia_aud_stream_op opensl_strm_op =
+{
+    &strm_get_param,
+    &strm_get_cap,
+    &strm_set_cap,
+    &strm_start,
+    &strm_stop,
+    &strm_destroy
+};
+
+/* This callback is called every time a buffer finishes playing. */
+void bqPlayerCallback(W_SLBufferQueueItf bq, void *context)
+{
+    struct opensl_aud_stream *stream = (struct opensl_aud_stream*) context;
+    SLresult result;
+    int status;
+
+    pj_assert(context != NULL);
+    pj_assert(bq == stream->playerBufQ);
+
+    if (stream->play_thread_initialized == 0 || !pj_thread_is_registered())
+    {
+	pj_bzero(stream->play_thread_desc, sizeof(pj_thread_desc));
+	status = pj_thread_register("opensl_play", stream->play_thread_desc,
+				    &stream->play_thread);
+	stream->play_thread_initialized = 1;
+	PJ_LOG(5, (THIS_FILE, "Player thread started"));
+    }
+    
+    if (!stream->quit_flag) {
+        pjmedia_frame frame;
+        char * buf;
+        
+        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+        frame.buf = buf = stream->playerBuffer[stream->playerBufIdx++];
+        frame.size = stream->playerBufferSize;
+        frame.timestamp.u64 = stream->play_timestamp.u64;
+        frame.bit_info = 0;
+        
+        status = (*stream->play_cb)(stream->user_data, &frame);
+        if (status != PJ_SUCCESS || frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
+            pj_bzero(buf, stream->playerBufferSize);
+        
+        stream->play_timestamp.u64 += stream->param.samples_per_frame /
+                                      stream->param.channel_count;
+        
+        result = (*bq)->Enqueue(bq, buf, stream->playerBufferSize);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Unable to enqueue next player buffer !!! %d",
+                                  result));
+        }
+        
+        stream->playerBufIdx %= NUM_BUFFERS;
+    }
+}
+
+/* This callback handler is called every time a buffer finishes recording */
+void bqRecorderCallback(W_SLBufferQueueItf bq, void *context)
+{
+    struct opensl_aud_stream *stream = (struct opensl_aud_stream*) context;
+    SLresult result;
+    int status;
+
+    pj_assert(context != NULL);
+    pj_assert(bq == stream->recordBufQ);
+
+    if (stream->rec_thread_initialized == 0 || !pj_thread_is_registered())
+    {
+	pj_bzero(stream->rec_thread_desc, sizeof(pj_thread_desc));
+	status = pj_thread_register("opensl_rec", stream->rec_thread_desc,
+				    &stream->rec_thread);
+	stream->rec_thread_initialized = 1;
+	PJ_LOG(5, (THIS_FILE, "Recorder thread started")); 
+    }
+    
+    if (!stream->quit_flag) {
+        pjmedia_frame frame;
+        char *buf;
+        
+        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+        frame.buf = buf = stream->recordBuffer[stream->recordBufIdx++];
+        frame.size = stream->recordBufferSize;
+        frame.timestamp.u64 = stream->rec_timestamp.u64;
+        frame.bit_info = 0;
+        
+        status = (*stream->rec_cb)(stream->user_data, &frame);
+        
+        stream->rec_timestamp.u64 += stream->param.samples_per_frame /
+                                     stream->param.channel_count;
+        
+        /* And now enqueue next buffer */
+        result = (*bq)->Enqueue(bq, buf, stream->recordBufferSize);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Unable to enqueue next record buffer !!! %d",
+                                  result));
+        }
+        
+        stream->recordBufIdx %= NUM_BUFFERS;
+    }
+}
+
+pj_status_t opensl_to_pj_error(SLresult code)
+{
+    switch(code) {
+	case SL_RESULT_SUCCESS:
+            return PJ_SUCCESS;
+	case SL_RESULT_PRECONDITIONS_VIOLATED:
+	case SL_RESULT_PARAMETER_INVALID:
+	case SL_RESULT_CONTENT_CORRUPTED:
+	case SL_RESULT_FEATURE_UNSUPPORTED:
+            return PJMEDIA_EAUD_INVOP;
+	case SL_RESULT_MEMORY_FAILURE:
+	case SL_RESULT_BUFFER_INSUFFICIENT:
+            return PJ_ENOMEM;
+	case SL_RESULT_RESOURCE_ERROR:
+	case SL_RESULT_RESOURCE_LOST:
+	case SL_RESULT_CONTROL_LOST:
+            return PJMEDIA_EAUD_NOTREADY;
+	case SL_RESULT_CONTENT_UNSUPPORTED:
+            return PJ_ENOTSUP;
+	default:
+            return PJMEDIA_EAUD_ERR;
+    }
+}
+
+/* Init Android audio driver. */
+pjmedia_aud_dev_factory* pjmedia_opensl_factory(pj_pool_factory *pf)
+{
+    struct opensl_aud_factory *f;
+    pj_pool_t *pool;
+    
+    pool = pj_pool_create(pf, "opensles", 256, 256, NULL);
+    f = PJ_POOL_ZALLOC_T(pool, struct opensl_aud_factory);
+    f->pf = pf;
+    f->pool = pool;
+    f->base.op = &opensl_op;
+    
+    return &f->base;
+}
+
+/* API: Init factory */
+static pj_status_t opensl_init(pjmedia_aud_dev_factory *f)
+{
+    struct opensl_aud_factory *pa = (struct opensl_aud_factory*)f;
+    SLresult result;    
+    
+    /* Create engine */
+    result = slCreateEngine(&pa->engineObject, 0, NULL, 0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Cannot create engine %d ", result));
+        return opensl_to_pj_error(result);
+    }
+    
+    /* Realize the engine */
+    result = (*pa->engineObject)->Realize(pa->engineObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Cannot realize engine"));
+        opensl_destroy(f);
+        return opensl_to_pj_error(result);
+    }
+    
+    /* Get the engine interface, which is needed in order to create
+     * other objects.
+     */
+    result = (*pa->engineObject)->GetInterface(pa->engineObject,
+                                               SL_IID_ENGINE,
+                                               &pa->engineEngine);
+    if (result != SL_RESULT_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Cannot get engine interface"));
+        opensl_destroy(f);
+        return opensl_to_pj_error(result);
+    }
+    
+    /* Create output mix */
+    result = (*pa->engineEngine)->CreateOutputMix(pa->engineEngine,
+                                                  &pa->outputMixObject,
+                                                  0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Cannot create output mix"));
+        opensl_destroy(f);
+        return opensl_to_pj_error(result);
+    }
+    
+    /* Realize the output mix */
+    result = (*pa->outputMixObject)->Realize(pa->outputMixObject,
+                                             SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS) {
+        PJ_LOG(3, (THIS_FILE, "Cannot realize output mix"));
+        opensl_destroy(f);
+        return opensl_to_pj_error(result);
+    }
+    
+    PJ_LOG(4,(THIS_FILE, "OpenSL sound library initialized"));
+    return PJ_SUCCESS;
+}
+
+/* API: Destroy factory */
+static pj_status_t opensl_destroy(pjmedia_aud_dev_factory *f)
+{
+    struct opensl_aud_factory *pa = (struct opensl_aud_factory*)f;
+    pj_pool_t *pool;
+    
+    PJ_LOG(4,(THIS_FILE, "OpenSL sound library shutting down.."));
+    
+    /* Destroy Output Mix object */
+    if (pa->outputMixObject) {
+        (*pa->outputMixObject)->Destroy(pa->outputMixObject);
+        pa->outputMixObject = NULL;
+    }
+    
+    /* Destroy engine object, and invalidate all associated interfaces */
+    if (pa->engineObject) {
+        (*pa->engineObject)->Destroy(pa->engineObject);
+        pa->engineObject = NULL;
+        pa->engineEngine = NULL;
+    }
+    
+    pool = pa->pool;
+    pa->pool = NULL;
+    pj_pool_release(pool);
+    
+    return PJ_SUCCESS;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t opensl_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_SUCCESS;
+}
+
+/* API: Get device count. */
+static unsigned opensl_get_dev_count(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return 1;
+}
+
+/* API: Get device info. */
+static pj_status_t opensl_get_dev_info(pjmedia_aud_dev_factory *f,
+                                       unsigned index,
+                                       pjmedia_aud_dev_info *info)
+{
+    PJ_UNUSED_ARG(f);
+
+    pj_bzero(info, sizeof(*info));
+    
+    pj_ansi_strcpy(info->name, "OpenSL ES Audio");
+    info->default_samples_per_sec = 8000;
+    info->caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
+    info->input_count = 1;
+    info->output_count = 1;
+    
+    return PJ_SUCCESS;
+}
+
+/* API: fill in with default parameter. */
+static pj_status_t opensl_default_param(pjmedia_aud_dev_factory *f,
+                                        unsigned index,
+                                        pjmedia_aud_param *param)
+{
+    
+    pjmedia_aud_dev_info adi;
+    pj_status_t status;
+    
+    status = opensl_get_dev_info(f, index, &adi);
+    if (status != PJ_SUCCESS)
+	return status;
+    
+    pj_bzero(param, sizeof(*param));
+    if (adi.input_count && adi.output_count) {
+        param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+        param->rec_id = index;
+        param->play_id = index;
+    } else if (adi.input_count) {
+        param->dir = PJMEDIA_DIR_CAPTURE;
+        param->rec_id = index;
+        param->play_id = PJMEDIA_AUD_INVALID_DEV;
+    } else if (adi.output_count) {
+        param->dir = PJMEDIA_DIR_PLAYBACK;
+        param->play_id = index;
+        param->rec_id = PJMEDIA_AUD_INVALID_DEV;
+    } else {
+        return PJMEDIA_EAUD_INVDEV;
+    }
+    
+    param->clock_rate = adi.default_samples_per_sec;
+    param->channel_count = 1;
+    param->samples_per_frame = adi.default_samples_per_sec * 20 / 1000;
+    param->bits_per_sample = 16;
+    param->input_latency_ms = PJMEDIA_SND_DEFAULT_REC_LATENCY;
+    param->output_latency_ms = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+    
+    return PJ_SUCCESS;
+}
+
+/* API: create stream */
+static pj_status_t opensl_create_stream(pjmedia_aud_dev_factory *f,
+                                        const pjmedia_aud_param *param,
+                                        pjmedia_aud_rec_cb rec_cb,
+                                        pjmedia_aud_play_cb play_cb,
+                                        void *user_data,
+                                        pjmedia_aud_stream **p_aud_strm)
+{
+    /* Audio sink for recorder and audio source for player */
+#ifdef __ANDROID__
+    SLDataLocator_AndroidSimpleBufferQueue loc_bq =
+        { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
+#else
+    SLDataLocator_BufferQueue loc_bq =
+        { SL_DATALOCATOR_BUFFERQUEUE, NUM_BUFFERS };
+#endif
+    struct opensl_aud_factory *pa = (struct opensl_aud_factory*)f;
+    pj_pool_t *pool;
+    struct opensl_aud_stream *stream;
+    pj_status_t status = PJ_SUCCESS;
+    int i, bufferSize;
+    SLresult result;
+    SLDataFormat_PCM format_pcm;
+    
+    /* Only supports for mono channel for now */
+    PJ_ASSERT_RETURN(param->channel_count == 1, PJ_EINVAL);
+    PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);
+
+    PJ_LOG(4,(THIS_FILE, "Creating OpenSL stream"));
+    
+    pool = pj_pool_create(pa->pf, "openslstrm", 1024, 1024, NULL);
+    if (!pool)
+        return PJ_ENOMEM;
+    
+    stream = PJ_POOL_ZALLOC_T(pool, struct opensl_aud_stream);
+    stream->pool = pool;
+    pj_strdup2_with_null(pool, &stream->name, "OpenSL");
+    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+    pj_memcpy(&stream->param, param, sizeof(*param));
+    stream->user_data = user_data;
+    stream->rec_cb = rec_cb;
+    stream->play_cb = play_cb;
+    bufferSize = param->samples_per_frame * param->bits_per_sample / 8;
+
+    /* Configure audio PCM format */
+    format_pcm.formatType = SL_DATAFORMAT_PCM;
+    format_pcm.numChannels = param->channel_count;
+    /* Here samples per sec should be supported else we will get an error */
+    format_pcm.samplesPerSec  = (SLuint32) param->clock_rate * 1000;
+    format_pcm.bitsPerSample = (SLuint16) param->bits_per_sample;
+    format_pcm.containerSize = (SLuint16) param->bits_per_sample;
+    format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
+    format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
+
+    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
+        /* Audio source */
+        SLDataSource audioSrc = {&loc_bq, &format_pcm};
+        /* Audio sink */
+        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,
+                                              pa->outputMixObject};
+        SLDataSink audioSnk = {&loc_outmix, NULL};
+        /* Audio interface */
+#ifdef __ANDROID__
+        int numIface = 3;
+        const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE,
+                                      SL_IID_VOLUME,
+                                      SL_IID_ANDROIDCONFIGURATION};
+        const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE,
+                                  SL_BOOLEAN_TRUE};
+        SLAndroidConfigurationItf playerConfig;
+        SLint32 streamType = SL_ANDROID_STREAM_VOICE;
+#else
+        int numIface = 2;
+        const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE,
+                                      SL_IID_VOLUME};
+        const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+#endif
+        
+        /* Create audio player */
+        result = (*pa->engineEngine)->CreateAudioPlayer(pa->engineEngine,
+                                                        &stream->playerObj,
+                                                        &audioSrc, &audioSnk,
+                                                        numIface, ids, req);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot create audio player: %d", result));
+            goto on_error;
+        }
+
+#ifdef __ANDROID__
+        /* Set Android configuration */
+        result = (*stream->playerObj)->GetInterface(stream->playerObj,
+                                                    SL_IID_ANDROIDCONFIGURATION,
+                                                    &playerConfig);
+        if (result == SL_RESULT_SUCCESS && playerConfig) {
+            result = (*playerConfig)->SetConfiguration(
+                         playerConfig, SL_ANDROID_KEY_STREAM_TYPE,
+                         &streamType, sizeof(SLint32));
+        }
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android "
+                                  "player configuration"));
+        }
+#endif
+
+        /* Realize the player */
+        result = (*stream->playerObj)->Realize(stream->playerObj,
+                                               SL_BOOLEAN_FALSE);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot realize player : %d", result));
+            goto on_error;
+        }
+        
+        /* Get the play interface */
+        result = (*stream->playerObj)->GetInterface(stream->playerObj,
+                                                    SL_IID_PLAY,
+                                                    &stream->playerPlay);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot get play interface"));
+            goto on_error;
+        }
+        
+        /* Get the buffer queue interface */
+        result = (*stream->playerObj)->GetInterface(stream->playerObj,
+                                                    SL_IID_BUFFERQUEUE,
+                                                    &stream->playerBufQ);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot get buffer queue interface"));
+            goto on_error;
+        }
+        
+        /* Get the volume interface */
+        result = (*stream->playerObj)->GetInterface(stream->playerObj,
+                                                    SL_IID_VOLUME,
+                                                    &stream->playerVol);
+        
+        /* Register callback on the buffer queue */
+        result = (*stream->playerBufQ)->RegisterCallback(stream->playerBufQ,
+                                                         bqPlayerCallback,
+                                                         (void *)stream);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot register player callback"));
+            goto on_error;
+        }
+        
+        stream->playerBufferSize = bufferSize;
+        for (i = 0; i < NUM_BUFFERS; i++) {
+            stream->playerBuffer[i] = (char *)
+                                      pj_pool_alloc(stream->pool,
+                                                    stream->playerBufferSize);
+        }
+    }
+
+    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
+        /* Audio source */
+        SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
+                                          SL_IODEVICE_AUDIOINPUT,
+                                          SL_DEFAULTDEVICEID_AUDIOINPUT,
+                                          NULL};
+        SLDataSource audioSrc = {&loc_dev, NULL};
+        /* Audio sink */
+        SLDataSink audioSnk = {&loc_bq, &format_pcm};
+        /* Audio interface */
+#ifdef __ANDROID__
+        int numIface = 2;
+        const SLInterfaceID ids[2] = {W_SL_IID_BUFFERQUEUE,
+                                      SL_IID_ANDROIDCONFIGURATION};
+        const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+        SLAndroidConfigurationItf recorderConfig;
+#else
+        int numIface = 1;
+        const SLInterfaceID ids[1] = {W_SL_IID_BUFFERQUEUE};
+        const SLboolean req[1] = {SL_BOOLEAN_TRUE};
+#endif
+        
+        /* Create audio recorder
+         * (requires the RECORD_AUDIO permission)
+         */
+        result = (*pa->engineEngine)->CreateAudioRecorder(pa->engineEngine,
+                                                          &stream->recordObj,
+                                                          &audioSrc, &audioSnk,
+                                                          numIface, ids, req);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot create recorder: %d", result));
+            goto on_error;
+        }
+
+#ifdef __ANDROID__
+        /* Set Android configuration */
+        result = (*stream->recordObj)->GetInterface(stream->recordObj,
+                                                    SL_IID_ANDROIDCONFIGURATION,
+                                                    &recorderConfig);
+        if (result == SL_RESULT_SUCCESS) {
+            SLint32 streamType = SL_ANDROID_RECORDING_PRESET_GENERIC;
+#if __ANDROID_API__ >= 14
+            char sdk_version[PROP_VALUE_MAX];
+            pj_str_t pj_sdk_version;
+            int sdk_v;
+
+            __system_property_get("ro.build.version.sdk", sdk_version);
+            pj_sdk_version = pj_str(sdk_version);
+            sdk_v = pj_strtoul(&pj_sdk_version);
+            if (sdk_v >= 14)
+                streamType = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
+            PJ_LOG(4, (THIS_FILE, "Recording stream type %d, SDK : %d",
+                                  streamType, sdk_v));
+#endif
+            result = (*recorderConfig)->SetConfiguration(
+                         recorderConfig, SL_ANDROID_KEY_RECORDING_PRESET,
+                         &streamType, sizeof(SLint32));
+        }
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android "
+                                  "recorder configuration"));
+        }
+#endif
+        
+        /* Realize the recorder */
+        result = (*stream->recordObj)->Realize(stream->recordObj,
+                                               SL_BOOLEAN_FALSE);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot realize recorder : %d", result));
+            goto on_error;
+        }
+        
+        /* Get the record interface */
+        result = (*stream->recordObj)->GetInterface(stream->recordObj,
+                                                    SL_IID_RECORD,
+                                                    &stream->recordRecord);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot get record interface"));
+            goto on_error;
+        }
+        
+        /* Get the buffer queue interface */
+        result = (*stream->recordObj)->GetInterface(
+                     stream->recordObj, W_SL_IID_BUFFERQUEUE,
+                     &stream->recordBufQ);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot get recorder buffer queue iface"));
+            goto on_error;
+        }
+        
+        /* Register callback on the buffer queue */
+        result = (*stream->recordBufQ)->RegisterCallback(stream->recordBufQ,
+                                                         bqRecorderCallback, 
+                                                         (void *) stream);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot register recorder callback"));
+            goto on_error;
+        }
+        
+        stream->recordBufferSize = bufferSize;
+        for (i = 0; i < NUM_BUFFERS; i++) {
+            stream->recordBuffer[i] = (char *)
+                                      pj_pool_alloc(stream->pool,
+                                                    stream->recordBufferSize);
+        }
+
+    }
+    
+    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
+	strm_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
+                     &param->output_vol);
+    }
+    
+    /* Done */
+    stream->base.op = &opensl_strm_op;
+    *p_aud_strm = &stream->base;
+    return PJ_SUCCESS;
+    
+on_error:
+    strm_destroy(&stream->base);
+    return status;
+}
+
+/* API: Get stream parameters */
+static pj_status_t strm_get_param(pjmedia_aud_stream *s,
+                                  pjmedia_aud_param *pi)
+{
+    struct opensl_aud_stream *strm = (struct opensl_aud_stream*)s;
+    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+    pj_memcpy(pi, &strm->param, sizeof(*pi));
+
+    if (strm_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
+                     &pi->output_vol) == PJ_SUCCESS)
+    {
+        pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
+    }    
+    
+    return PJ_SUCCESS;
+}
+
+/* API: get capability */
+static pj_status_t strm_get_cap(pjmedia_aud_stream *s,
+                                pjmedia_aud_dev_cap cap,
+                                void *pval)
+{
+    struct opensl_aud_stream *strm = (struct opensl_aud_stream*)s;    
+    pj_status_t status = PJMEDIA_EAUD_INVCAP;
+    
+    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
+    
+    if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING &&
+	(strm->param.dir & PJMEDIA_DIR_PLAYBACK))
+    {
+        if (strm->playerVol) {
+            SLresult res;
+            SLmillibel vol, mvol;
+            
+            res = (*strm->playerVol)->GetMaxVolumeLevel(strm->playerVol,
+                                                        &mvol);
+            if (res == SL_RESULT_SUCCESS) {
+                res = (*strm->playerVol)->GetVolumeLevel(strm->playerVol,
+                                                         &vol);
+                if (res == SL_RESULT_SUCCESS) {
+                    *(int *)pval = ((int)vol - SL_MILLIBEL_MIN) * 100 /
+                                   ((int)mvol - SL_MILLIBEL_MIN);
+                    return PJ_SUCCESS;
+                }
+            }
+        }
+    }
+    
+    return status;
+}
+
+/* API: set capability */
+static pj_status_t strm_set_cap(pjmedia_aud_stream *s,
+                                pjmedia_aud_dev_cap cap,
+                                const void *value)
+{
+    struct opensl_aud_stream *strm = (struct opensl_aud_stream*)s;
+    
+    PJ_ASSERT_RETURN(s && value, PJ_EINVAL);
+
+    if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING &&
+	(strm->param.dir & PJMEDIA_DIR_PLAYBACK))
+    {
+        if (strm->playerVol) {
+            SLresult res;
+            SLmillibel vol, mvol;
+            
+            res = (*strm->playerVol)->GetMaxVolumeLevel(strm->playerVol,
+                                                        &mvol);
+            if (res == SL_RESULT_SUCCESS) {
+                vol = (SLmillibel)(*(int *)value *
+                      ((int)mvol - SL_MILLIBEL_MIN) / 100 + SL_MILLIBEL_MIN);
+                res = (*strm->playerVol)->SetVolumeLevel(strm->playerVol,
+                                                         vol);
+                if (res == SL_RESULT_SUCCESS)
+                    return PJ_SUCCESS;
+            }
+        }
+    }
+
+    return PJMEDIA_EAUD_INVCAP;
+}
+
+/* API: start stream. */
+static pj_status_t strm_start(pjmedia_aud_stream *s)
+{
+    struct opensl_aud_stream *stream = (struct opensl_aud_stream*)s;
+    int i;
+    SLresult result = SL_RESULT_SUCCESS;
+    
+    PJ_LOG(4, (THIS_FILE, "Starting %s stream..", stream->name.ptr));
+    stream->quit_flag = 0;
+
+    if (stream->recordBufQ && stream->recordRecord) {
+        /* Enqueue an empty buffer to be filled by the recorder
+         * (for streaming recording, we need to enqueue at least 2 empty
+         * buffers to start things off)
+         */
+        for (i = 0; i < NUM_BUFFERS; i++) {
+            result = (*stream->recordBufQ)->Enqueue(stream->recordBufQ,
+                                                stream->recordBuffer[i],
+                                                stream->recordBufferSize);
+            /* The most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
+             * which for this code would indicate a programming error
+             */
+            pj_assert(result == SL_RESULT_SUCCESS);
+        }
+        
+        result = (*stream->recordRecord)->SetRecordState(
+                     stream->recordRecord, SL_RECORDSTATE_RECORDING);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot start recorder"));
+            goto on_error;
+        }
+    }
+    
+    if (stream->playerPlay && stream->playerBufQ) {
+        /* Set the player's state to playing */
+        result = (*stream->playerPlay)->SetPlayState(stream->playerPlay,
+                                                     SL_PLAYSTATE_PLAYING);
+        if (result != SL_RESULT_SUCCESS) {
+            PJ_LOG(3, (THIS_FILE, "Cannot start player"));
+            goto on_error;
+        }
+        
+        for (i = 0; i < NUM_BUFFERS; i++) {
+            pj_bzero(stream->playerBuffer[i], stream->playerBufferSize/100);
+            result = (*stream->playerBufQ)->Enqueue(stream->playerBufQ,
+                                                stream->playerBuffer[i],
+                                                stream->playerBufferSize/100);
+            pj_assert(result == SL_RESULT_SUCCESS);
+        }
+    }
+    
+    PJ_LOG(4, (THIS_FILE, "%s stream started", stream->name.ptr));
+    return PJ_SUCCESS;
+    
+on_error:
+    if (result != SL_RESULT_SUCCESS)
+        strm_stop(&stream->base);
+    return opensl_to_pj_error(result);
+}
+
+/* API: stop stream. */
+static pj_status_t strm_stop(pjmedia_aud_stream *s)
+{
+    struct opensl_aud_stream *stream = (struct opensl_aud_stream*)s;
+    
+    if (stream->quit_flag)
+        return PJ_SUCCESS;
+    
+    PJ_LOG(4, (THIS_FILE, "Stopping stream"));
+    
+    stream->quit_flag = 1;    
+    
+    if (stream->recordBufQ && stream->recordRecord) {
+        /* Stop recording and clear buffer queue */
+        (*stream->recordRecord)->SetRecordState(stream->recordRecord,
+                                                  SL_RECORDSTATE_STOPPED);
+        (*stream->recordBufQ)->Clear(stream->recordBufQ);
+    }
+
+    if (stream->playerBufQ && stream->playerPlay) {
+        /* Wait until the PCM data is done playing, the buffer queue callback
+         * will continue to queue buffers until the entire PCM data has been
+         * played. This is indicated by waiting for the count member of the
+         * SLBufferQueueState to go to zero.
+         */
+/*      
+        SLresult result;
+        W_SLBufferQueueState state;
+
+        result = (*stream->playerBufQ)->GetState(stream->playerBufQ, &state);
+        while (state.count) {
+            (*stream->playerBufQ)->GetState(stream->playerBufQ, &state);
+        } */
+        /* Stop player */
+        (*stream->playerPlay)->SetPlayState(stream->playerPlay,
+                                            SL_PLAYSTATE_STOPPED);
+    }
+
+    PJ_LOG(4,(THIS_FILE, "OpenSL stream stopped"));
+    
+    return PJ_SUCCESS;
+    
+}
+
+/* API: destroy stream. */
+static pj_status_t strm_destroy(pjmedia_aud_stream *s)
+{    
+    struct opensl_aud_stream *stream = (struct opensl_aud_stream*)s;
+    
+    /* Stop the stream */
+    strm_stop(s);
+    
+    if (stream->playerObj) {
+        /* Destroy the player */
+        (*stream->playerObj)->Destroy(stream->playerObj);
+        /* Invalidate all associated interfaces */
+        stream->playerObj = NULL;
+        stream->playerPlay = NULL;
+        stream->playerBufQ = NULL;
+        stream->playerVol = NULL;
+    }
+    
+    if (stream->recordObj) {
+        /* Destroy the recorder */
+        (*stream->recordObj)->Destroy(stream->recordObj);
+        /* Invalidate all associated interfaces */
+        stream->recordObj = NULL;
+        stream->recordRecord = NULL;
+        stream->recordBufQ = NULL;
+    }
+    
+    pj_pool_release(stream->pool);
+    PJ_LOG(4, (THIS_FILE, "OpenSL stream destroyed"));
+    
+    return PJ_SUCCESS;
+}
+
+#endif	/* PJMEDIA_AUDIO_DEV_HAS_OPENSL */
diff --git a/jni/pjproject-android/.svn/pristine/f8/f8d0402ec5efa72af43f4300ac3f14c2d39293aa.svn-base b/jni/pjproject-android/.svn/pristine/f8/f8d0402ec5efa72af43f4300ac3f14c2d39293aa.svn-base
new file mode 100644
index 0000000..1e5f317
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f8d0402ec5efa72af43f4300ac3f14c2d39293aa.svn-base
@@ -0,0 +1 @@
+#include "../../../portaudio/src/common/pa_debugprint.h"
diff --git a/jni/pjproject-android/.svn/pristine/f8/f8d5c8965caf5988a19007da07c0ee5f6b2aef82.svn-base b/jni/pjproject-android/.svn/pristine/f8/f8d5c8965caf5988a19007da07c0ee5f6b2aef82.svn-base
new file mode 100644
index 0000000..3e482af
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f8/f8d5c8965caf5988a19007da07c0ee5f6b2aef82.svn-base
@@ -0,0 +1,92 @@
+EXPORTS
+	pj_cis_add_alpha                         @ 1 NONAME
+	pj_cis_add_cis                           @ 2 NONAME
+	pj_cis_add_num                           @ 3 NONAME
+	pj_cis_add_range                         @ 4 NONAME
+	pj_cis_add_str                           @ 5 NONAME
+	pj_cis_buf_init                          @ 6 NONAME
+	pj_cis_del_range                         @ 7 NONAME
+	pj_cis_del_str                           @ 8 NONAME
+	pj_cis_dup                               @ 9 NONAME
+	pj_cis_init                              @ 10 NONAME
+	pj_cis_invert                            @ 11 NONAME
+	pj_crc32_calc                            @ 12 NONAME
+	pj_crc32_final                           @ 13 NONAME
+	pj_crc32_init                            @ 14 NONAME
+	pj_crc32_update                          @ 15 NONAME
+	pj_dns_dump_packet                       @ 16 NONAME
+	pj_dns_get_type_name                     @ 17 NONAME
+	pj_dns_make_query                        @ 18 NONAME
+	pj_dns_packet_dup                        @ 19 NONAME
+	pj_dns_parse_a_response                  @ 20 NONAME
+	pj_dns_parse_packet                      @ 21 NONAME
+	pj_dns_resolver_add_entry                @ 22 NONAME
+	pj_dns_resolver_cancel_query             @ 23 NONAME
+	pj_dns_resolver_create                   @ 24 NONAME
+	pj_dns_resolver_destroy                  @ 25 NONAME
+	pj_dns_resolver_dump                     @ 26 NONAME
+	pj_dns_resolver_get_cached_count         @ 27 NONAME
+	pj_dns_resolver_get_settings             @ 28 NONAME
+	pj_dns_resolver_handle_events            @ 29 NONAME
+	pj_dns_resolver_set_ns                   @ 30 NONAME
+	pj_dns_resolver_set_settings             @ 31 NONAME
+	pj_dns_resolver_start_query              @ 32 NONAME
+	pj_dns_settings_default                  @ 33 NONAME
+	pj_dns_srv_resolve                       @ 34 NONAME
+	pj_hmac_md5                              @ 35 NONAME
+	pj_hmac_md5_final                        @ 36 NONAME
+	pj_hmac_md5_init                         @ 37 NONAME
+	pj_hmac_md5_update                       @ 38 NONAME
+	pj_hmac_sha1                             @ 39 NONAME
+	pj_hmac_sha1_final                       @ 40 NONAME
+	pj_hmac_sha1_init                        @ 41 NONAME
+	pj_hmac_sha1_update                      @ 42 NONAME
+	pj_md5_final                             @ 43 NONAME
+	pj_md5_init                              @ 44 NONAME
+	pj_md5_update                            @ 45 NONAME
+	pj_scan_advance_n                        @ 46 NONAME
+	pj_scan_fini                             @ 47 NONAME
+	pj_scan_get                              @ 48 NONAME
+	pj_scan_get_char                         @ 49 NONAME
+	pj_scan_get_n                            @ 50 NONAME
+	pj_scan_get_newline                      @ 51 NONAME
+	pj_scan_get_quote                        @ 52 NONAME
+	pj_scan_get_quotes                       @ 53 NONAME
+	pj_scan_get_unescape                     @ 54 NONAME
+	pj_scan_get_until                        @ 55 NONAME
+	pj_scan_get_until_ch                     @ 56 NONAME
+	pj_scan_get_until_chr                    @ 57 NONAME
+	pj_scan_init                             @ 58 NONAME
+	pj_scan_peek                             @ 59 NONAME
+	pj_scan_peek_n                           @ 60 NONAME
+	pj_scan_peek_until                       @ 61 NONAME
+	pj_scan_restore_state                    @ 62 NONAME
+	pj_scan_save_state                       @ 63 NONAME
+	pj_scan_skip_line                        @ 64 NONAME
+	pj_scan_skip_whitespace                  @ 65 NONAME
+	pj_scan_strcmp                           @ 66 NONAME
+	pj_scan_stricmp                          @ 67 NONAME
+	pj_scan_stricmp_alnum                    @ 68 NONAME
+	pj_sha1_final                            @ 69 NONAME
+	pj_sha1_init                             @ 70 NONAME
+	pj_sha1_update                           @ 71 NONAME
+	pj_str_unescape                          @ 72 NONAME
+	pj_strcpy_unescape                       @ 73 NONAME
+	pj_strncpy2_escape                       @ 74 NONAME
+	pj_strncpy_escape                        @ 75 NONAME
+	pj_xml_add_attr                          @ 76 NONAME
+	pj_xml_add_node                          @ 77 NONAME
+	pj_xml_attr_new                          @ 78 NONAME
+	pj_xml_clone                             @ 79 NONAME
+	pj_xml_find                              @ 80 NONAME
+	pj_xml_find_attr                         @ 81 NONAME
+	pj_xml_find_next_node                    @ 82 NONAME
+	pj_xml_find_node                         @ 83 NONAME
+	pj_xml_node_new                          @ 84 NONAME
+	pj_xml_parse                             @ 85 NONAME
+	pj_xml_print                             @ 86 NONAME
+	pjlib_util_init                          @ 87 NONAME
+	pjstun_create_bind_req                   @ 88 NONAME
+	pjstun_get_mapped_addr                   @ 89 NONAME
+	pjstun_msg_find_attr                     @ 90 NONAME
+	pjstun_parse_msg                         @ 91 NONAME