* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/50/50b41237e3f9cd430ade1daf49930a8c95c4bf10.svn-base b/jni/pjproject-android/.svn/pristine/50/50b41237e3f9cd430ade1daf49930a8c95c4bf10.svn-base
new file mode 100644
index 0000000..560f0c6
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/50/50b41237e3f9cd430ade1daf49930a8c95c4bf10.svn-base
@@ -0,0 +1,520 @@
+/* $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 "test.h"
+#include <pjlib.h>
+
+/**
+ * \page page_pjlib_activesock_test Test: Active Socket
+ *
+ * This file is <b>pjlib-test/activesock.c</b>
+ *
+ * \include pjlib-test/activesock.c
+ */
+
+#if INCLUDE_ACTIVESOCK_TEST
+
+#define THIS_FILE   "activesock.c"
+
+
+/*******************************************************************
+ * Simple UDP echo server.
+ */
+struct udp_echo_srv
+{
+    pj_activesock_t	*asock;
+    pj_bool_t		 echo_enabled;
+    pj_uint16_t		 port;
+    pj_ioqueue_op_key_t	 send_key;
+    pj_status_t		 status;
+    unsigned		 rx_cnt;
+    unsigned		 rx_err_cnt, tx_err_cnt;
+};
+
+static void udp_echo_err(const char *title, pj_status_t status)
+{
+    char errmsg[PJ_ERR_MSG_SIZE];
+
+    pj_strerror(status, errmsg, sizeof(errmsg));
+    PJ_LOG(3,(THIS_FILE, "   error: %s: %s", title, errmsg));
+}
+
+static pj_bool_t udp_echo_srv_on_data_recvfrom(pj_activesock_t *asock,
+					       void *data,
+					       pj_size_t size,
+					       const pj_sockaddr_t *src_addr,
+					       int addr_len,
+					       pj_status_t status)
+{
+    struct udp_echo_srv *srv;
+    pj_ssize_t sent;
+
+
+    srv = (struct udp_echo_srv*) pj_activesock_get_user_data(asock);
+
+    if (status != PJ_SUCCESS) {
+	srv->status = status;
+	srv->rx_err_cnt++;
+	udp_echo_err("recvfrom() callback", status);
+	return PJ_TRUE;
+    }
+
+    srv->rx_cnt++;
+
+    /* Send back if echo is enabled */
+    if (srv->echo_enabled) {
+	sent = size;
+	srv->status = pj_activesock_sendto(asock, &srv->send_key, data, 
+					   &sent, 0,
+					   src_addr, addr_len);
+	if (srv->status != PJ_SUCCESS) {
+	    srv->tx_err_cnt++;
+	    udp_echo_err("sendto()", status);
+	}
+    }
+
+    return PJ_TRUE;
+}
+
+
+static pj_status_t udp_echo_srv_create(pj_pool_t *pool,
+				       pj_ioqueue_t *ioqueue,
+				       pj_bool_t enable_echo,
+				       struct udp_echo_srv **p_srv)
+{
+    struct udp_echo_srv *srv;
+    pj_sock_t sock_fd = PJ_INVALID_SOCKET;
+    pj_sockaddr addr;
+    pj_activesock_cb activesock_cb;
+    pj_status_t status;
+
+    srv = PJ_POOL_ZALLOC_T(pool, struct udp_echo_srv);
+    srv->echo_enabled = enable_echo;
+
+    pj_sockaddr_in_init(&addr.ipv4, NULL, 0);
+
+    pj_bzero(&activesock_cb, sizeof(activesock_cb));
+    activesock_cb.on_data_recvfrom = &udp_echo_srv_on_data_recvfrom;
+
+    status = pj_activesock_create_udp(pool, &addr, NULL, ioqueue, &activesock_cb, 
+				      srv, &srv->asock, &addr);
+    if (status != PJ_SUCCESS) {
+	pj_sock_close(sock_fd);
+	udp_echo_err("pj_activesock_create()", status);
+	return status;
+    }
+
+    srv->port = pj_ntohs(addr.ipv4.sin_port);
+
+    pj_ioqueue_op_key_init(&srv->send_key, sizeof(srv->send_key));
+
+    status = pj_activesock_start_recvfrom(srv->asock, pool, 32, 0);
+    if (status != PJ_SUCCESS) {
+	pj_activesock_close(srv->asock);
+	udp_echo_err("pj_activesock_start_recvfrom()", status);
+	return status;
+    }
+
+
+    *p_srv = srv;
+    return PJ_SUCCESS;
+}
+
+static void udp_echo_srv_destroy(struct udp_echo_srv *srv)
+{
+    pj_activesock_close(srv->asock);
+}
+
+/*******************************************************************
+ * UDP ping pong test (send packet back and forth between two UDP echo
+ * servers.
+ */
+static int udp_ping_pong_test(void)
+{
+    pj_ioqueue_t *ioqueue = NULL;
+    pj_pool_t *pool = NULL;
+    struct udp_echo_srv *srv1=NULL, *srv2=NULL;
+    pj_bool_t need_send = PJ_TRUE;
+    unsigned data = 0;
+    int count, ret;
+    pj_status_t status;
+
+    pool = pj_pool_create(mem, "pingpong", 512, 512, NULL);
+    if (!pool)
+	return -10;
+
+    status = pj_ioqueue_create(pool, 4, &ioqueue);
+    if (status != PJ_SUCCESS) {
+	ret = -20;
+	udp_echo_err("pj_ioqueue_create()", status);
+	goto on_return;
+    }
+
+    status = udp_echo_srv_create(pool, ioqueue, PJ_TRUE, &srv1);
+    if (status != PJ_SUCCESS) {
+	ret = -30;
+	goto on_return;
+    }
+
+    status = udp_echo_srv_create(pool, ioqueue, PJ_TRUE, &srv2);
+    if (status != PJ_SUCCESS) {
+	ret = -40;
+	goto on_return;
+    }
+
+    /* initiate the first send */
+    for (count=0; count<1000; ++count) {
+	unsigned last_rx1, last_rx2;
+	unsigned i;
+
+	if (need_send) {
+	    pj_str_t loopback;
+	    pj_sockaddr_in addr;
+	    pj_ssize_t sent;
+
+	    ++data;
+
+	    sent = sizeof(data);
+	    loopback = pj_str("127.0.0.1");
+	    pj_sockaddr_in_init(&addr, &loopback, srv2->port);
+	    status = pj_activesock_sendto(srv1->asock, &srv1->send_key,
+					  &data, &sent, 0,
+					  &addr, sizeof(addr));
+	    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+		ret = -50;
+		udp_echo_err("sendto()", status);
+		goto on_return;
+	    }
+
+	    need_send = PJ_FALSE;
+	}
+
+	last_rx1 = srv1->rx_cnt;
+	last_rx2 = srv2->rx_cnt;
+
+	for (i=0; i<10 && last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt; ++i) {
+	    pj_time_val delay = {0, 10};
+#ifdef PJ_SYMBIAN
+	    PJ_UNUSED_ARG(delay);
+	    pj_symbianos_poll(-1, 100);
+#else
+	    pj_ioqueue_poll(ioqueue, &delay);
+#endif
+	}
+
+	if (srv1->rx_err_cnt+srv1->tx_err_cnt != 0 ||
+	    srv2->rx_err_cnt+srv2->tx_err_cnt != 0)
+	{
+	    /* Got error */
+	    ret = -60;
+	    goto on_return;
+	}
+
+	if (last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt) {
+	    /* Packet lost */
+	    ret = -70;
+	    udp_echo_err("packets have been lost", PJ_ETIMEDOUT);
+	    goto on_return;
+	}
+    }
+
+    ret = 0;
+
+on_return:
+    if (srv2)
+	udp_echo_srv_destroy(srv2);
+    if (srv1)
+	udp_echo_srv_destroy(srv1);
+    if (ioqueue)
+	pj_ioqueue_destroy(ioqueue);
+    if (pool)
+	pj_pool_release(pool);
+    
+    return ret;
+}
+
+
+
+#define SIGNATURE   0xdeadbeef
+struct tcp_pkt
+{
+    pj_uint32_t	signature;
+    pj_uint32_t	seq;
+    char	fill[513];
+};
+
+struct tcp_state
+{
+    pj_bool_t	err;
+    pj_bool_t	sent;
+    pj_uint32_t	next_recv_seq;
+    pj_uint8_t	pkt[600];
+};
+
+struct send_key
+{
+    pj_ioqueue_op_key_t	op_key;
+};
+
+
+static pj_bool_t tcp_on_data_read(pj_activesock_t *asock,
+				  void *data,
+				  pj_size_t size,
+				  pj_status_t status,
+				  pj_size_t *remainder)
+{
+    struct tcp_state *st = (struct tcp_state*) pj_activesock_get_user_data(asock);
+    char *next = (char*) data;
+
+    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+	PJ_LOG(1,("", "   err: status=%d", status));
+	st->err = PJ_TRUE;
+	return PJ_FALSE;
+    }
+
+    while (size >= sizeof(struct tcp_pkt)) {
+	struct tcp_pkt *tcp_pkt = (struct tcp_pkt*) next;
+
+	if (tcp_pkt->signature != SIGNATURE) {
+	    PJ_LOG(1,("", "   err: invalid signature at seq=%d", 
+			  st->next_recv_seq));
+	    st->err = PJ_TRUE;
+	    return PJ_FALSE;
+	}
+	if (tcp_pkt->seq != st->next_recv_seq) {
+	    PJ_LOG(1,("", "   err: wrong sequence"));
+	    st->err = PJ_TRUE;
+	    return PJ_FALSE;
+	}
+
+	st->next_recv_seq++;
+	next += sizeof(struct tcp_pkt);
+	size -= sizeof(struct tcp_pkt);
+    }
+
+    if (size) {
+	pj_memmove(data, next, size);
+	*remainder = size;
+    }
+
+    return PJ_TRUE;
+}
+
+static pj_bool_t tcp_on_data_sent(pj_activesock_t *asock,
+				  pj_ioqueue_op_key_t *op_key,
+				  pj_ssize_t sent)
+{
+    struct tcp_state *st=(struct tcp_state*)pj_activesock_get_user_data(asock);
+
+    PJ_UNUSED_ARG(op_key);
+
+    st->sent = 1;
+
+    if (sent < 1) {
+	st->err = PJ_TRUE;
+	return PJ_FALSE;
+    }
+
+    return PJ_TRUE;
+}
+
+static int tcp_perf_test(void)
+{
+    enum { COUNT=10000 };
+    pj_pool_t *pool = NULL;
+    pj_ioqueue_t *ioqueue = NULL;
+    pj_sock_t sock1=PJ_INVALID_SOCKET, sock2=PJ_INVALID_SOCKET;
+    pj_activesock_t *asock1 = NULL, *asock2 = NULL;
+    pj_activesock_cb cb;
+    struct tcp_state *state1, *state2;
+    unsigned i;
+    pj_status_t status;
+
+    pool = pj_pool_create(mem, "tcpperf", 256, 256, NULL);
+
+    status = app_socketpair(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock1, 
+			    &sock2);
+    if (status != PJ_SUCCESS) {
+	status = -100;
+	goto on_return;
+    }
+
+    status = pj_ioqueue_create(pool, 4, &ioqueue);
+    if (status != PJ_SUCCESS) {
+	status = -110;
+	goto on_return;
+    }
+
+    pj_bzero(&cb, sizeof(cb));
+    cb.on_data_read = &tcp_on_data_read;
+    cb.on_data_sent = &tcp_on_data_sent;
+
+    state1 = PJ_POOL_ZALLOC_T(pool, struct tcp_state);
+    status = pj_activesock_create(pool, sock1, pj_SOCK_STREAM(), NULL, ioqueue,
+				  &cb, state1, &asock1);
+    if (status != PJ_SUCCESS) {
+	status = -120;
+	goto on_return;
+    }
+
+    state2 = PJ_POOL_ZALLOC_T(pool, struct tcp_state);
+    status = pj_activesock_create(pool, sock2, pj_SOCK_STREAM(), NULL, ioqueue,
+				  &cb, state2, &asock2);
+    if (status != PJ_SUCCESS) {
+	status = -130;
+	goto on_return;
+    }
+
+    status = pj_activesock_start_read(asock1, pool, 1000, 0);
+    if (status != PJ_SUCCESS) {
+	status = -140;
+	goto on_return;
+    }
+
+    /* Send packet as quickly as possible */
+    for (i=0; i<COUNT && !state1->err && !state2->err; ++i) {
+	struct tcp_pkt *pkt;
+	struct send_key send_key[2], *op_key;
+	pj_ssize_t len;
+
+	pkt = (struct tcp_pkt*)state2->pkt;
+	pkt->signature = SIGNATURE;
+	pkt->seq = i;
+	pj_memset(pkt->fill, 'a', sizeof(pkt->fill));
+
+	op_key = &send_key[i%2];
+	pj_ioqueue_op_key_init(&op_key->op_key, sizeof(*op_key));
+
+	state2->sent = PJ_FALSE;
+	len = sizeof(*pkt);
+	status = pj_activesock_send(asock2, &op_key->op_key, pkt, &len, 0);
+	if (status == PJ_EPENDING) {
+	    do {
+#if PJ_SYMBIAN
+		pj_symbianos_poll(-1, -1);
+#else
+		pj_ioqueue_poll(ioqueue, NULL);
+#endif
+	    } while (!state2->sent);
+	} else {
+#if PJ_SYMBIAN
+		/* The Symbian socket always returns PJ_SUCCESS for TCP send,
+		 * eventhough the remote end hasn't received the data yet.
+		 * If we continue sending, eventually send() will block,
+		 * possibly because the send buffer is full. So we need to
+		 * poll the ioqueue periodically, to let receiver gets the 
+		 * data.
+		 */
+		pj_symbianos_poll(-1, 0);
+#endif
+		if (status != PJ_SUCCESS) {
+		    PJ_LOG(1,("", "   err: send status=%d", status));
+		    status = -180;
+		    break;
+		} else if (status == PJ_SUCCESS) {
+		    if (len != sizeof(*pkt)) {
+			PJ_LOG(1,("", "   err: shouldn't report partial sent"));
+			status = -190;
+			break;
+		    }
+		}
+	}
+
+#ifndef PJ_SYMBIAN
+	for (;;) {
+	    pj_time_val timeout = {0, 10};
+	    if (pj_ioqueue_poll(ioqueue, &timeout) < 1)
+		break;
+	}
+#endif
+
+    }
+
+    /* Wait until everything has been sent/received */
+    if (state1->next_recv_seq < COUNT) {
+#ifdef PJ_SYMBIAN
+	while (pj_symbianos_poll(-1, 1000) == PJ_TRUE)
+	    ;
+#else
+	pj_time_val delay = {0, 100};
+	while (pj_ioqueue_poll(ioqueue, &delay) > 0)
+	    ;
+#endif
+    }
+
+    if (status == PJ_EPENDING)
+	status = PJ_SUCCESS;
+
+    if (status != 0)
+	goto on_return;
+
+    if (state1->err) {
+	status = -183;
+	goto on_return;
+    }
+    if (state2->err) {
+	status = -186;
+	goto on_return;
+    }
+    if (state1->next_recv_seq != COUNT) {
+	PJ_LOG(3,("", "   err: only %u packets received, expecting %u", 
+		      state1->next_recv_seq, COUNT));
+	status = -195;
+	goto on_return;
+    }
+
+on_return:
+    if (asock2)
+	pj_activesock_close(asock2);
+    if (asock1)
+	pj_activesock_close(asock1);
+    if (ioqueue)
+	pj_ioqueue_destroy(ioqueue);
+    if (pool)
+	pj_pool_release(pool);
+
+    return status;
+}
+
+
+
+int activesock_test(void)
+{
+    int ret;
+
+    PJ_LOG(3,("", "..udp ping/pong test"));
+    ret = udp_ping_pong_test();
+    if (ret != 0)
+	return ret;
+
+    PJ_LOG(3,("", "..tcp perf test"));
+    ret = tcp_perf_test();
+    if (ret != 0)
+	return ret;
+
+    return 0;
+}
+
+#else	/* INCLUDE_ACTIVESOCK_TEST */
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled. 
+ */
+int dummy_active_sock_test;
+#endif	/* INCLUDE_ACTIVESOCK_TEST */
+