aboutsummaryrefslogtreecommitdiff
path: root/net/pjsip
diff options
context:
space:
mode:
authorGuido Falsi <madpilot@FreeBSD.org>2019-10-09 14:33:37 +0000
committerGuido Falsi <madpilot@FreeBSD.org>2019-10-09 14:33:37 +0000
commitb842667be56101509908f4717ca58ca65a0bec67 (patch)
treed3dc1298e828b727a6a939bbee4ad3d5ccc7545f /net/pjsip
parent44710045baf8d52d3fd1284428f95a321011f5c4 (diff)
downloadports-b842667be56101509908f4717ca58ca65a0bec67.tar.gz
ports-b842667be56101509908f4717ca58ca65a0bec67.zip
Import patches from asterisk project.
MFH: 2019Q4
Notes
Notes: svn path=/head/; revision=514163
Diffstat (limited to 'net/pjsip')
-rw-r--r--net/pjsip/Makefile2
-rw-r--r--net/pjsip/files/patch-003060
-rw-r--r--net/pjsip/files/patch-003184
-rw-r--r--net/pjsip/files/patch-003264
-rw-r--r--net/pjsip/files/patch-00331094
5 files changed, 1303 insertions, 1 deletions
diff --git a/net/pjsip/Makefile b/net/pjsip/Makefile
index 0067edcb4634..3433ccb6bc37 100644
--- a/net/pjsip/Makefile
+++ b/net/pjsip/Makefile
@@ -2,7 +2,7 @@
PORTNAME= pjsip
PORTVERSION= 2.9
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= net
MASTER_SITES= http://www.pjsip.org/release/${PORTVERSION}/
DISTNAME= pjproject-${DISTVERSION}
diff --git a/net/pjsip/files/patch-0030 b/net/pjsip/files/patch-0030
new file mode 100644
index 000000000000..39931852e3b7
--- /dev/null
+++ b/net/pjsip/files/patch-0030
@@ -0,0 +1,60 @@
+From 8d0652d4a02c7b8da58b1b98421cfda57056184d Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@digium.com>
+Date: Tue, 24 Sep 2019 06:41:16 -0600
+Subject: [PATCH 30/33] Revert "Misc (re #2147): Fixed warnings in SSL socket:
+ redefinition of typedef 'pj_ssl_sock_t' and unused 'get_pem'."
+
+This reverts commit 688a9b0de685328f62b2df86304b44c21e4460ae.
+---
+ pjlib/src/pj/ssl_sock_imp_common.h | 4 ++--
+ pjlib/src/pj/ssl_sock_ossl.c | 5 +----
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/pjlib/src/pj/ssl_sock_imp_common.h b/pjlib/src/pj/ssl_sock_imp_common.h
+index 09f259ef7..4edbb3b82 100644
+--- pjlib/src/pj/ssl_sock_imp_common.h
++++ pjlib/src/pj/ssl_sock_imp_common.h
+@@ -93,7 +93,7 @@ typedef struct circ_buf_t {
+ /*
+ * Secure socket structure definition.
+ */
+-struct pj_ssl_sock_t
++typedef struct pj_ssl_sock_t
+ {
+ pj_pool_t *pool;
+ pj_ssl_sock_t *parent;
+@@ -139,7 +139,7 @@ struct pj_ssl_sock_t
+
+ circ_buf_t circ_buf_output;
+ pj_lock_t *circ_buf_output_mutex;
+-};
++} pj_ssl_sock_t;
+
+
+ /*
+diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
+index b4ac5c15f..debb105b1 100644
+--- pjlib/src/pj/ssl_sock_ossl.c
++++ pjlib/src/pj/ssl_sock_ossl.c
+@@ -37,6 +37,7 @@
+ #if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
+ (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_OPENSSL)
+
++#include "ssl_sock_imp_common.h"
+ #include "ssl_sock_imp_common.c"
+
+ #define THIS_FILE "ssl_sock_ossl.c"
+@@ -1575,10 +1576,6 @@ static void ssl_update_remote_cert_chain_info(pj_pool_t *pool,
+ {
+ int i;
+
+- /* For now, get_pem has to be PJ_TRUE */
+- pj_assert(get_pem);
+- PJ_UNUSED_ARG(get_pem);
+-
+ ci->raw_chain.cert_raw = (pj_str_t *)pj_pool_calloc(pool,
+ sk_X509_num(chain),
+ sizeof(pj_str_t));
+--
+2.21.0
+
diff --git a/net/pjsip/files/patch-0031 b/net/pjsip/files/patch-0031
new file mode 100644
index 000000000000..02eccd9b5233
--- /dev/null
+++ b/net/pjsip/files/patch-0031
@@ -0,0 +1,84 @@
+From 616a13933f33a6d74f84d85b5bfb858279a09e2d Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@digium.com>
+Date: Tue, 24 Sep 2019 06:42:04 -0600
+Subject: [PATCH 31/33] Revert "Fixed #2204: Add OpenSSL remote certificate
+ chain info"
+
+This reverts commit f71d60c866c4572a7c8398fe982416771fc6a7f5.
+---
+ pjlib/src/pj/ssl_sock_ossl.c | 45 ------------------------------------
+ 1 file changed, 45 deletions(-)
+
+diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
+index debb105b1..109c5c1e2 100644
+--- pjlib/src/pj/ssl_sock_ossl.c
++++ pjlib/src/pj/ssl_sock_ossl.c
+@@ -1566,41 +1566,6 @@ static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x,
+ }
+ }
+
+-/* Update remote certificates chain info. This function should be
+- * called after handshake or renegotiation successfully completed.
+- */
+-static void ssl_update_remote_cert_chain_info(pj_pool_t *pool,
+- pj_ssl_cert_info *ci,
+- STACK_OF(X509) *chain,
+- pj_bool_t get_pem)
+-{
+- int i;
+-
+- ci->raw_chain.cert_raw = (pj_str_t *)pj_pool_calloc(pool,
+- sk_X509_num(chain),
+- sizeof(pj_str_t));
+- ci->raw_chain.cnt = sk_X509_num(chain);
+-
+- for (i = 0; i < sk_X509_num(chain); i++) {
+- BIO *bio;
+- BUF_MEM *ptr;
+- X509 *x = sk_X509_value(chain, i);
+-
+- bio = BIO_new(BIO_s_mem());
+-
+- if (!PEM_write_bio_X509(bio, x)) {
+- PJ_LOG(3, (THIS_FILE, "Error retrieving raw certificate info"));
+- ci->raw_chain.cert_raw[i].ptr = NULL;
+- ci->raw_chain.cert_raw[i].slen = 0;
+- } else {
+- BIO_write(bio, "\0", 1);
+- BIO_get_mem_ptr(bio, &ptr);
+- pj_strdup2(pool, &ci->raw_chain.cert_raw[i], ptr->data );
+- }
+-
+- BIO_free(bio);
+- }
+-}
+
+ /* Update local & remote certificates info. This function should be
+ * called after handshake or renegotiation successfully completed.
+@@ -1609,7 +1574,6 @@ static void ssl_update_certs_info(pj_ssl_sock_t *ssock)
+ {
+ ossl_sock_t *ossock = (ossl_sock_t *)ssock;
+ X509 *x;
+- STACK_OF(X509) *chain;
+
+ pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED);
+
+@@ -1631,15 +1595,6 @@ static void ssl_update_certs_info(pj_ssl_sock_t *ssock)
+ } else {
+ pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info));
+ }
+-
+- chain = SSL_get_peer_cert_chain(ossock->ossl_ssl);
+- if (chain) {
+- ssl_update_remote_cert_chain_info(ssock->pool,
+- &ssock->remote_cert_info,
+- chain, PJ_TRUE);
+- } else {
+- ssock->remote_cert_info.raw_chain.cnt = 0;
+- }
+ }
+
+
+--
+2.21.0
+
diff --git a/net/pjsip/files/patch-0032 b/net/pjsip/files/patch-0032
new file mode 100644
index 000000000000..2bd6de083548
--- /dev/null
+++ b/net/pjsip/files/patch-0032
@@ -0,0 +1,64 @@
+From 17cd744e19cd332a219a512770fa6e18453044ba Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@digium.com>
+Date: Tue, 24 Sep 2019 06:45:25 -0600
+Subject: [PATCH 32/33] Revert "Re #2147 (misc): Fix failed pjsip-test
+ (transport_loop_test) caused by r6002."
+
+This reverts commit 342148f5bcf3a6b0029ce834b8567c2cd691b15b.
+---
+ pjsip/src/pjsip/sip_transport.c | 12 +++++-------
+ pjsip/src/pjsip/sip_transport_loop.c | 2 +-
+ pjsip/src/test/transport_loop_test.c | 1 -
+ 3 files changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
+index 65ac823d4..d63823a98 100644
+--- pjsip/src/pjsip/sip_transport.c
++++ pjsip/src/pjsip/sip_transport.c
+@@ -1222,13 +1222,11 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
+
+ pj_lock_release(mgr->lock);
+
+- TRACE_((THIS_FILE, "Transport %s registered: type=%s, remote=%s:%d",
+- tp->obj_name,
+- pjsip_transport_get_type_name(tp->key.type),
+- pj_sockaddr_has_addr(&tp->key.rem_addr)?
+- addr_string(&tp->key.rem_addr):"",
+- pj_sockaddr_has_addr(&tp->key.rem_addr)?
+- pj_sockaddr_get_port(&tp->key.rem_addr):0));
++ TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d",
++ tp->obj_name,
++ pjsip_transport_get_type_name(tp->key.type),
++ addr_string(&tp->key.rem_addr),
++ pj_sockaddr_get_port(&tp->key.rem_addr)));
+
+ return PJ_SUCCESS;
+ }
+diff --git a/pjsip/src/pjsip/sip_transport_loop.c b/pjsip/src/pjsip/sip_transport_loop.c
+index 37e20e69b..24e1a5f69 100644
+--- pjsip/src/pjsip/sip_transport_loop.c
++++ pjsip/src/pjsip/sip_transport_loop.c
+@@ -376,7 +376,7 @@ PJ_DEF(pj_status_t) pjsip_loop_start( pjsip_endpoint *endpt,
+ if (status != PJ_SUCCESS)
+ goto on_error;
+ loop->base.key.type = PJSIP_TRANSPORT_LOOP_DGRAM;
+- //loop->base.key.rem_addr.addr.sa_family = pj_AF_INET();
++ loop->base.key.rem_addr.addr.sa_family = pj_AF_INET();
+ loop->base.type_name = "LOOP-DGRAM";
+ loop->base.info = "LOOP-DGRAM";
+ loop->base.flag = PJSIP_TRANSPORT_DATAGRAM;
+diff --git a/pjsip/src/test/transport_loop_test.c b/pjsip/src/test/transport_loop_test.c
+index 5f2f03904..efa2ea116 100644
+--- pjsip/src/test/transport_loop_test.c
++++ pjsip/src/test/transport_loop_test.c
+@@ -36,7 +36,6 @@ static int datagram_loop_test()
+
+ PJ_LOG(3,(THIS_FILE, "testing datagram loop transport"));
+
+- pj_sockaddr_in_init(&addr, NULL, 0);
+ /* Test acquire transport. */
+ status = pjsip_endpt_acquire_transport( endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
+ &addr, sizeof(addr), NULL, &loop);
+--
+2.21.0
+
diff --git a/net/pjsip/files/patch-0033 b/net/pjsip/files/patch-0033
new file mode 100644
index 000000000000..6c24d01dca07
--- /dev/null
+++ b/net/pjsip/files/patch-0033
@@ -0,0 +1,1094 @@
+From a720f3ffd538d3baef6f8daf78d9d320a4a5c0a0 Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@digium.com>
+Date: Tue, 24 Sep 2019 06:45:59 -0600
+Subject: [PATCH 33/33] Revert "Close #1019: Support for multiple listeners."
+
+This reverts commit 142dd0e96edad15b6b9554636043b5255d5d8adf.
+---
+ pjsip/include/pjsip/sip_config.h | 10 +-
+ pjsip/src/pjsip/sip_transport.c | 318 ++++++++++-----------------
+ pjsip/src/pjsip/sip_transport_loop.c | 2 +-
+ pjsip/src/test/test.c | 3 -
+ pjsip/src/test/transport_tcp_test.c | 193 ++++------------
+ pjsip/src/test/transport_udp_test.c | 148 +++++--------
+ 6 files changed, 215 insertions(+), 459 deletions(-)
+
+diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
+index 585aa722c..904df24e1 100644
+--- pjsip/include/pjsip/sip_config.h
++++ pjsip/include/pjsip/sip_config.h
+@@ -433,7 +433,7 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+ * This option can also be controlled at run-time by the
+ * \a accept_multiple_sdp_answers setting in pjsip_cfg_t.
+ *
+- * Default is PJ_TRUE.
++ * Default is PJ_FALSE.
+ */
+ #ifndef PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS
+ # define PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS PJ_TRUE
+@@ -692,7 +692,7 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+ * will be used as the default value for the "reuse_addr" field in the
+ * pjsip_tcp_transport_cfg structure.
+ *
+- * Default is 0 on Windows and 1 on non-Windows.
++ * Default is FALSE on Windows and TRUE on non-Windows.
+ *
+ * @see PJSIP_TLS_TRANSPORT_REUSEADDR
+ */
+@@ -718,7 +718,7 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+ * pj_getipinterface()/pj_gethostip(), but the address will not be
+ * able to accept connections.
+ *
+- * Default is 0 (listener will be created).
++ * Default is FALSE (listener will be created).
+ */
+ #ifndef PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER
+ # define PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER 0
+@@ -738,7 +738,7 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+ * pj_getipinterface()/pj_gethostip(), but the address will not be
+ * able to accept connections.
+ *
+- * Default is 0 (listener will be created).
++ * Default is FALSE (listener will be created).
+ */
+ #ifndef PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER
+ # define PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER 0
+@@ -881,7 +881,7 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+ /**
+ * Specify whether TLS listener should use SO_REUSEADDR option.
+ *
+- * Default is 0 on Windows and 1 on non-Windows.
++ * Default is FALSE on Windows and TRUE on non-Windows.
+ *
+ * @see PJSIP_TCP_TRANSPORT_REUSEADDR
+ */
+diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
+index d63823a98..54e8be380 100644
+--- pjsip/src/pjsip/sip_transport.c
++++ pjsip/src/pjsip/sip_transport.c
+@@ -54,25 +54,6 @@ static const char *addr_string(const pj_sockaddr_t *addr)
+ # define TRACE_(x)
+ #endif
+
+-/* Specify the initial size of the transport manager's pool. */
+-#ifndef TPMGR_POOL_INIT_SIZE
+-# define TPMGR_POOL_INIT_SIZE 64
+-#endif
+-
+-/* Specify the increment size of the transport manager's pool. */
+-#ifndef TPMGR_POOL_INC_SIZE
+- #define TPMGR_POOL_INC_SIZE 64
+-#endif
+-
+-/* Specify transport entry allocation count. When registering a new transport,
+- * a new entry will be picked from a free list. This setting will determine
+- * the size of the free list size. If all entry is used, then the same number
+- * of entry will be allocated.
+- */
+-#ifndef PJSIP_TRANSPORT_ENTRY_ALLOC_CNT
+-# define PJSIP_TRANSPORT_ENTRY_ALLOC_CNT 16
+-#endif
+-
+ /* Prototype. */
+ static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata);
+
+@@ -100,7 +81,6 @@ static pjsip_module mod_msg_print =
+ typedef struct transport
+ {
+ PJ_DECL_LIST_MEMBER(struct transport);
+- pj_hash_entry_buf tp_buf;
+ pjsip_transport *tp;
+ } transport;
+
+@@ -113,7 +93,6 @@ struct pjsip_tpmgr
+ pj_lock_t *lock;
+ pjsip_endpoint *endpt;
+ pjsip_tpfactory factory_list;
+- pj_pool_t *pool;
+ #if defined(PJ_DEBUG) && PJ_DEBUG!=0
+ pj_atomic_t *tdata_counter;
+ #endif
+@@ -126,9 +105,12 @@ struct pjsip_tpmgr
+ * is destroyed.
+ */
+ pjsip_tx_data tdata_list;
+-
+- /* List of free transport entry. */
+- transport tp_entry_freelist;
++
++ /* List of transports which are NOT stored in the hash table, so
++ * that it can be properly cleaned up when transport manager
++ * is destroyed.
++ */
++ transport tp_list;
+ };
+
+
+@@ -1042,18 +1024,18 @@ static pj_bool_t is_transport_valid(pjsip_transport *tp, pjsip_tpmgr *tpmgr,
+ const pjsip_transport_key *key,
+ int key_len)
+ {
+- transport *tp_entry;
++ transport *tp_iter;
+
+- tp_entry = (transport *)pj_hash_get(tpmgr->table, key, key_len, NULL);
+- if (tp_entry != NULL) {
++ if (pj_hash_get(tpmgr->table, key, key_len, NULL) == (void*)tp) {
++ return PJ_TRUE;
++ }
+
+- transport *tp_iter = tp_entry;
+- do {
+- if (tp_iter->tp == tp) {
+- return PJ_TRUE;
+- }
+- tp_iter = tp_iter->next;
+- } while (tp_iter != tp_entry);
++ tp_iter = tpmgr->tp_list.next;
++ while (tp_iter != &tpmgr->tp_list) {
++ if (tp_iter->tp == tp) {
++ return PJ_TRUE;
++ }
++ tp_iter = tp_iter->next;
+ }
+
+ return PJ_FALSE;
+@@ -1153,9 +1135,8 @@ PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
+ }
+
+ /* Dec ref transport group lock, if any */
+- if (tp->grp_lock) {
++ if (tp->grp_lock)
+ pj_grp_lock_dec_ref(tp->grp_lock);
+- }
+
+ return PJ_SUCCESS;
+ }
+@@ -1169,8 +1150,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
+ {
+ int key_len;
+ pj_uint32_t hval;
+- transport *tp_ref = NULL;
+- transport *tp_add = NULL;
++ void *entry;
+
+ /* Init. */
+ tp->tpmgr = mgr;
+@@ -1178,43 +1158,31 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
+ tp->idle_timer.user_data = tp;
+ tp->idle_timer.cb = &transport_idle_callback;
+
+- /*
++ /*
+ * Register to hash table (see Trac ticket #42).
+ */
+ key_len = sizeof(tp->key.type) + tp->addr_len;
+ pj_lock_acquire(mgr->lock);
+
++ /* If entry already occupied, unregister previous entry */
+ hval = 0;
+- tp_ref = (transport *)pj_hash_get(mgr->table, &tp->key, key_len, &hval);
+-
+- /* Get an empty entry from the freelist. */
+- if (pj_list_empty(&mgr->tp_entry_freelist)) {
+- unsigned i = 0;
+-
+- TRACE_((THIS_FILE, "Transport list is full, allocate new entry"));
+- /* Allocate new entry for the freelist. */
+- for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) {
+- tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport);
+- if (!tp_add)
+- return PJ_ENOMEM;
+- pj_list_init(tp_add);
+- pj_list_push_back(&mgr->tp_entry_freelist, tp_add);
+- }
++ entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
++ if (entry != NULL) {
++ transport *tp_ref;
++
++ tp_ref = PJ_POOL_ZALLOC_T(((pjsip_transport *)entry)->pool, transport);
++
++ /*
++ * Add transport to the list before removing it from the hash table.
++ * See ticket #1774 for more details.
++ */
++ tp_ref->tp = (pjsip_transport *)entry;
++ pj_list_push_back(&mgr->tp_list, tp_ref);
++ pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
+ }
+- tp_add = mgr->tp_entry_freelist.next;
+- tp_add->tp = tp;
+- pj_list_erase(tp_add);
+
+- if (tp_ref) {
+- /* There'a already a transport list from the hash table. Add the
+- * new transport to the list.
+- */
+- pj_list_push_back(tp_ref, tp_add);
+- } else {
+- /* Transport list not found, add it to the hash table. */
+- pj_hash_set_np(mgr->table, &tp->key, key_len, hval, tp_add->tp_buf,
+- tp_add);
+- }
++ /* Register new entry */
++ pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, hval, tp);
+
+ /* Add ref transport group lock, if any */
+ if (tp->grp_lock)
+@@ -1261,46 +1229,26 @@ static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
+ key_len = sizeof(tp->key.type) + tp->addr_len;
+ hval = 0;
+ entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
+- if (entry) {
+- transport *tp_ref = (transport *)entry;
+- transport *tp_iter = tp_ref;
+- /* Search the matching entry from the transport list. */
+- do {
+- if (tp_iter->tp == tp) {
+- transport *tp_next = tp_iter->next;
+-
+- /* Update hash table :
+- * - transport list only contain single element, or
+- * - the entry is the first element of the transport list.
+- */
+- if (tp_iter == tp_ref) {
+- pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval,
+- NULL);
+-
+- if (tp_ref->next != tp_ref) {
+- /* The transport list has multiple entry. */
+- pj_hash_set_np(mgr->table, &tp_next->tp->key, key_len,
+- hval, tp_next->tp_buf, tp_next);
+- }
+- }
+-
+- pj_list_erase(tp_iter);
+- /* Put back to the transport freelist. */
+- pj_list_push_back(&mgr->tp_entry_freelist, tp_iter);
+-
+- break;
+- }
+- tp_iter = tp_iter->next;
+- } while (tp_iter != tp_ref);
++ if (entry == (void*)tp) {
++ pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
++ } else {
++ /* If not found in hash table, remove from the tranport list. */
++ transport *tp_iter = mgr->tp_list.next;
++ while (tp_iter != &mgr->tp_list) {
++ if (tp_iter->tp == tp) {
++ pj_list_erase(tp_iter);
++ break;
++ }
++ tp_iter = tp_iter->next;
++ }
+ }
+
+ pj_lock_release(mgr->lock);
+ pj_lock_release(tp->lock);
+
+ /* Dec ref transport group lock, if any */
+- if (tp->grp_lock) {
++ if (tp->grp_lock)
+ pj_grp_lock_dec_ref(tp->grp_lock);
+- }
+
+ /* Destroy. */
+ return tp->destroy(tp);
+@@ -1414,9 +1362,13 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_register_tpfactory( pjsip_tpmgr *mgr,
+
+ pj_lock_acquire(mgr->lock);
+
+- /* Check that no same factory has been registered. */
++ /* Check that no factory with the same type has been registered. */
+ status = PJ_SUCCESS;
+ for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) {
++ if (p->type == tpf->type) {
++ status = PJSIP_ETYPEEXISTS;
++ break;
++ }
+ if (p == tpf) {
+ status = PJ_EEXISTS;
+ break;
+@@ -1491,8 +1443,6 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
+ {
+ pjsip_tpmgr *mgr;
+ pj_status_t status;
+- unsigned i = 0;
+- pj_pool_t *mgr_pool;
+
+ PJ_ASSERT_RETURN(pool && endpt && rx_cb && p_mgr, PJ_EINVAL);
+
+@@ -1502,42 +1452,24 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
+ return status;
+
+ /* Create and initialize transport manager. */
+- mgr_pool = pjsip_endpt_create_pool(endpt, "tpmgr",
+- TPMGR_POOL_INIT_SIZE,
+- TPMGR_POOL_INC_SIZE);
+- mgr = PJ_POOL_ZALLOC_T(mgr_pool, pjsip_tpmgr);
++ mgr = PJ_POOL_ZALLOC_T(pool, pjsip_tpmgr);
+ mgr->endpt = endpt;
+ mgr->on_rx_msg = rx_cb;
+ mgr->on_tx_msg = tx_cb;
+- mgr->pool = mgr_pool;
+-
+- if (!mgr->pool)
+- return PJ_ENOMEM;
+-
+ pj_list_init(&mgr->factory_list);
+ pj_list_init(&mgr->tdata_list);
+- pj_list_init(&mgr->tp_entry_freelist);
++ pj_list_init(&mgr->tp_list);
+
+- mgr->table = pj_hash_create(mgr->pool, PJSIP_TPMGR_HTABLE_SIZE);
++ mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE);
+ if (!mgr->table)
+ return PJ_ENOMEM;
+
+- status = pj_lock_create_recursive_mutex(mgr->pool, "tmgr%p", &mgr->lock);
++ status = pj_lock_create_recursive_mutex(pool, "tmgr%p", &mgr->lock);
+ if (status != PJ_SUCCESS)
+ return status;
+
+- for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) {
+- transport *tp_add = NULL;
+-
+- tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport);
+- if (!tp_add)
+- return PJ_ENOMEM;
+- pj_list_init(tp_add);
+- pj_list_push_back(&mgr->tp_entry_freelist, tp_add);
+- }
+-
+ #if defined(PJ_DEBUG) && PJ_DEBUG!=0
+- status = pj_atomic_create(mgr->pool, 0, &mgr->tdata_counter);
++ status = pj_atomic_create(pool, 0, &mgr->tdata_counter);
+ if (status != PJ_SUCCESS) {
+ pj_lock_destroy(mgr->lock);
+ return status;
+@@ -1765,16 +1697,15 @@ PJ_DEF(unsigned) pjsip_tpmgr_get_transport_count(pjsip_tpmgr *mgr)
+ pj_hash_iterator_t itr_val;
+ pj_hash_iterator_t *itr;
+ int nr_of_transports = 0;
+-
++
+ pj_lock_acquire(mgr->lock);
+-
++
+ itr = pj_hash_first(mgr->table, &itr_val);
+ while (itr) {
+- transport *tp_entry = (transport *)pj_hash_this(mgr->table, itr);
+- nr_of_transports += pj_list_size(tp_entry);
++ nr_of_transports++;
+ itr = pj_hash_next(mgr->table, itr);
+ }
+-
++
+ pj_lock_release(mgr->lock);
+
+ return nr_of_transports;
+@@ -1791,7 +1722,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
+ pj_hash_iterator_t *itr;
+ pjsip_tpfactory *factory;
+ pjsip_endpoint *endpt = mgr->endpt;
+-
++
+ PJ_LOG(5, (THIS_FILE, "Destroying transport manager"));
+
+ pj_lock_acquire(mgr->lock);
+@@ -1799,21 +1730,39 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
+ /*
+ * Destroy all transports in the hash table.
+ */
+- for (itr = pj_hash_first(mgr->table, &itr_val); itr;
+- itr = pj_hash_first(mgr->table, &itr_val))
+- {
+- transport *tp_ref;
+- tp_ref = pj_hash_this(mgr->table, itr);
+- destroy_transport(mgr, tp_ref->tp);
++ itr = pj_hash_first(mgr->table, &itr_val);
++ while (itr != NULL) {
++ pj_hash_iterator_t *next;
++ pjsip_transport *transport;
++
++ transport = (pjsip_transport*) pj_hash_this(mgr->table, itr);
++
++ next = pj_hash_next(mgr->table, itr);
++
++ destroy_transport(mgr, transport);
++
++ itr = next;
+ }
+
++ /*
++ * Destroy transports in the list.
++ */
++ if (!pj_list_empty(&mgr->tp_list)) {
++ transport *tp_iter = mgr->tp_list.next;
++ while (tp_iter != &mgr->tp_list) {
++ transport *next = tp_iter->next;
++ destroy_transport(mgr, tp_iter->tp);
++ tp_iter = next;
++ }
++ }
++
+ /*
+ * Destroy all factories/listeners.
+ */
+ factory = mgr->factory_list.next;
+ while (factory != &mgr->factory_list) {
+ pjsip_tpfactory *next = factory->next;
+-
++
+ factory->destroy(factory);
+
+ factory = next;
+@@ -1857,10 +1806,6 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
+ pjsip_endpt_unregister_module(endpt, &mod_msg_print);
+ }
+
+- if (mgr->pool) {
+- pjsip_endpt_release_pool( mgr->endpt, mgr->pool );
+- }
+-
+ return PJ_SUCCESS;
+ }
+
+@@ -2221,9 +2166,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+ */
+ pjsip_transport_key key;
+ int key_len;
+- pjsip_transport *tp_ref = NULL;
+- transport *tp_entry = NULL;
+-
++ pjsip_transport *transport = NULL;
+
+ /* If listener is specified, verify that the listener type matches
+ * the destination type.
+@@ -2244,28 +2187,11 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+ key.type = type;
+ pj_memcpy(&key.rem_addr, remote, addr_len);
+
+- tp_entry = (transport *)pj_hash_get(mgr->table, &key, key_len,
+- NULL);
+- if (tp_entry) {
+- if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER) {
+- transport *tp_iter = tp_entry;
+- do {
+- if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
+- sel->u.listener &&
+- tp_iter->tp->factory == sel->u.listener)
+- {
+- tp_ref = tp_iter->tp;
+- break;
+- }
+- tp_iter = tp_iter->next;
+- } while (tp_iter != tp_entry);
+- } else {
+- tp_ref = tp_entry->tp;
+- }
+- }
++ transport = (pjsip_transport*)
++ pj_hash_get(mgr->table, &key, key_len, NULL);
+ }
+
+- if (tp_ref == NULL &&
++ if (transport == NULL &&
+ (!sel || sel->disable_connection_reuse == PJ_FALSE))
+ {
+ unsigned flag = pjsip_transport_get_flag_from_type(type);
+@@ -2280,11 +2206,8 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+
+ pj_bzero(addr, addr_len);
+ key_len = sizeof(key.type) + addr_len;
+- tp_entry = (transport *) pj_hash_get(mgr->table, &key,
+- key_len, NULL);
+- if (tp_entry) {
+- tp_ref = tp_entry->tp;
+- }
++ transport = (pjsip_transport*)
++ pj_hash_get(mgr->table, &key, key_len, NULL);
+ }
+ /* For datagram transports, try lookup with zero address.
+ */
+@@ -2296,34 +2219,31 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+ addr->addr.sa_family = remote_addr->addr.sa_family;
+
+ key_len = sizeof(key.type) + addr_len;
+- tp_entry = (transport *) pj_hash_get(mgr->table, &key,
+- key_len, NULL);
+- if (tp_entry) {
+- tp_ref = tp_entry->tp;
+- }
++ transport = (pjsip_transport*)
++ pj_hash_get(mgr->table, &key, key_len, NULL);
+ }
+ }
+
+ /* If transport is found and listener is specified, verify listener */
+ else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
+- sel->u.listener && tp_ref->factory != sel->u.listener)
++ sel->u.listener && transport->factory != sel->u.listener)
+ {
+- tp_ref = NULL;
++ transport = NULL;
+ /* This will cause a new transport to be created which will be a
+ * 'duplicate' of the existing transport (same type & remote addr,
+ * but different factory).
+ */
+ }
+
+- if (tp_ref!=NULL && !tp_ref->is_shutdown) {
++ if (transport!=NULL && !transport->is_shutdown) {
+ /*
+ * Transport found!
+ */
+- pjsip_transport_add_ref(tp_ref);
++ pjsip_transport_add_ref(transport);
+ pj_lock_release(mgr->lock);
+- *tp = tp_ref;
++ *tp = transport;
+
+- TRACE_((THIS_FILE, "Transport %s acquired", tp_ref->obj_name));
++ TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name));
+ return PJ_SUCCESS;
+ }
+
+@@ -2385,15 +2305,15 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+ /* Request factory to create transport. */
+ if (factory->create_transport2) {
+ status = factory->create_transport2(factory, mgr, mgr->endpt,
+- (const pj_sockaddr*) remote,
++ (const pj_sockaddr*) remote,
+ addr_len, tdata, tp);
+ } else {
+ status = factory->create_transport(factory, mgr, mgr->endpt,
+- (const pj_sockaddr*) remote,
++ (const pj_sockaddr*) remote,
+ addr_len, tp);
+ }
+ if (status == PJ_SUCCESS) {
+- PJ_ASSERT_ON_FAIL(tp!=NULL,
++ PJ_ASSERT_ON_FAIL(tp!=NULL,
+ {pj_lock_release(mgr->lock); return PJ_EBUG;});
+ pjsip_transport_add_ref(*tp);
+ (*tp)->factory = factory;
+@@ -2436,25 +2356,15 @@ PJ_DEF(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr)
+ PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
+
+ do {
+- transport *tp_entry = (transport *) pj_hash_this(mgr->table, itr);
+- if (tp_entry) {
+- transport *tp_iter = tp_entry;
+-
+- do {
+- pjsip_transport *tp_ref = tp_iter->tp;
+-
+- PJ_LOG(3, (THIS_FILE, " %s %s%s%s%s(refcnt=%d%s)",
+- tp_ref->obj_name,
+- tp_ref->info,
+- (tp_ref->factory)?" listener[":"",
+- (tp_ref->factory)?tp_ref->factory->obj_name:"",
+- (tp_ref->factory)?"]":"",
+- pj_atomic_get(tp_ref->ref_cnt),
+- (tp_ref->idle_timer.id ? " [idle]" : "")));
+-
+- tp_iter = tp_iter->next;
+- } while (tp_iter != tp_entry);
+- }
++ pjsip_transport *t = (pjsip_transport*)
++ pj_hash_this(mgr->table, itr);
++
++ PJ_LOG(3, (THIS_FILE, " %s %s (refcnt=%d%s)",
++ t->obj_name,
++ t->info,
++ pj_atomic_get(t->ref_cnt),
++ (t->idle_timer.id ? " [idle]" : "")));
++
+ itr = pj_hash_next(mgr->table, itr);
+ } while (itr);
+ }
+diff --git a/pjsip/src/pjsip/sip_transport_loop.c b/pjsip/src/pjsip/sip_transport_loop.c
+index 24e1a5f69..5cbe26a97 100644
+--- pjsip/src/pjsip/sip_transport_loop.c
++++ pjsip/src/pjsip/sip_transport_loop.c
+@@ -376,7 +376,7 @@ PJ_DEF(pj_status_t) pjsip_loop_start( pjsip_endpoint *endpt,
+ if (status != PJ_SUCCESS)
+ goto on_error;
+ loop->base.key.type = PJSIP_TRANSPORT_LOOP_DGRAM;
+- loop->base.key.rem_addr.addr.sa_family = pj_AF_INET();
++ //loop->base.key.rem_addr.sa_family = pj_AF_INET();
+ loop->base.type_name = "LOOP-DGRAM";
+ loop->base.info = "LOOP-DGRAM";
+ loop->base.flag = PJSIP_TRANSPORT_DATAGRAM;
+diff --git a/pjsip/src/test/test.c b/pjsip/src/test/test.c
+index 3898d45ff..0361e6178 100644
+--- pjsip/src/test/test.c
++++ pjsip/src/test/test.c
+@@ -379,9 +379,6 @@ int test_main(void)
+ on_return:
+ flush_events(500);
+
+- /* Show additional info on the log. e.g: not released memory pool. */
+- pj_log_set_level(4);
+-
+ /* Dumping memory pool usage */
+ PJ_LOG(3,(THIS_FILE, "Peak memory size=%u MB",
+ caching_pool.peak_used_size / 1000000));
+diff --git a/pjsip/src/test/transport_tcp_test.c b/pjsip/src/test/transport_tcp_test.c
+index b10455664..3ff5f8ff4 100644
+--- pjsip/src/test/transport_tcp_test.c
++++ pjsip/src/test/transport_tcp_test.c
+@@ -29,154 +29,64 @@
+ * TCP transport test.
+ */
+ #if PJ_HAS_TCP
+-
+-static pj_status_t multi_listener_test(pjsip_tpfactory *factory[],
+- unsigned num_factory,
+- pjsip_transport *tp[],
+- unsigned *num_tp)
++int transport_tcp_test(void)
+ {
+- pj_status_t status;
+- unsigned i = 0;
+- pj_str_t s;
++ enum { SEND_RECV_LOOP = 8 };
++ pjsip_tpfactory *tpfactory;
+ pjsip_transport *tcp;
+- pjsip_tpfactory *tpfactory = NULL;
+ pj_sockaddr_in rem_addr;
+- pjsip_tpselector tp_sel;
+- unsigned ntp = 0;
+-
+- for (;i<num_factory;++i)
+- {
+- /* Start TCP listener on arbitrary port. */
+- status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory);
+- if (status != PJ_SUCCESS) {
+- app_perror(" Error: unable to start TCP transport", status);
+- return -10;
+- }
++ pj_status_t status;
++ char url[PJSIP_MAX_URL_SIZE];
++ char addr[PJ_INET_ADDRSTRLEN];
++ int rtt[SEND_RECV_LOOP], min_rtt;
++ int i, pkt_lost;
+
+- factory[i] = tpfactory;
++ /* Start TCP listener on arbitrary port. */
++ status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory);
++ if (status != PJ_SUCCESS) {
++ app_perror(" Error: unable to start TCP transport", status);
++ return -10;
+ }
+
+- /* Get the last listener address */
++
++ /* Get the listener address */
+ status = pj_sockaddr_in_init(&rem_addr, &tpfactory->addr_name.host,
+ (pj_uint16_t)tpfactory->addr_name.port);
+ if (status != PJ_SUCCESS) {
+ app_perror(" Error: possibly invalid TCP address name", status);
+- return -11;
++ return -14;
+ }
+
+- /* Acquire transport without selector. */
+- status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP,
+- &rem_addr, sizeof(rem_addr),
+- NULL, &tcp);
+- if (status != PJ_SUCCESS || tcp == NULL) {
+- app_perror(" Error: unable to acquire TCP transport", status);
+- return -12;
+- }
+- tp[ntp++] = tcp;
++ pj_ansi_sprintf(url, "sip:alice@%s:%d;transport=tcp",
++ pj_inet_ntop2(pj_AF_INET(), &rem_addr.sin_addr, addr,
++ sizeof(addr)),
++ pj_ntohs(rem_addr.sin_port));
+
+- /* After pjsip_endpt_acquire_transport, TCP transport must have
+- * reference counter 1.
+- */
+- if (pj_atomic_get(tcp->ref_cnt) != 1)
+- return -13;
+
+- /* Acquire with the same remote address, should return the same tp. */
+- status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP,
++ /* Acquire one TCP transport. */
++ status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP,
+ &rem_addr, sizeof(rem_addr),
+ NULL, &tcp);
+ if (status != PJ_SUCCESS || tcp == NULL) {
+ app_perror(" Error: unable to acquire TCP transport", status);
+- return -14;
+- }
+-
+- /* Should return existing transport. */
+- if (tp[ntp-1] != tcp) {
+- return -15;
++ return -17;
+ }
+
+- /* Using the same TCP transport, it must have reference counter 2.
++ /* After pjsip_endpt_acquire_transport, TCP transport must have
++ * reference counter 1.
+ */
+- if (pj_atomic_get(tcp->ref_cnt) != 2)
+- return -16;
+-
+- /* Decrease the reference. */
+- pjsip_transport_dec_ref(tcp);
++ if (pj_atomic_get(tcp->ref_cnt) != 1)
++ return -20;
+
+ /* Test basic transport attributes */
+ status = generic_transport_test(tcp);
+ if (status != PJ_SUCCESS)
+ return status;
+
++
+ /* Check again that reference counter is 1. */
+ if (pj_atomic_get(tcp->ref_cnt) != 1)
+- return -17;
+-
+- /* Acquire transport test with selector. */
+- pj_bzero(&tp_sel, sizeof(tp_sel));
+- tp_sel.type = PJSIP_TPSELECTOR_LISTENER;
+- tp_sel.u.listener = factory[num_factory/2];
+- pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80);
+- status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP,
+- &rem_addr, sizeof(rem_addr),
+- &tp_sel, &tcp);
+- if (status != PJ_SUCCESS) {
+- app_perror(" Error: unable to acquire TCP transport", status);
+- return -18;
+- }
+-
+- /* The transport should have the same factory set on the selector. */
+- if (tcp->factory != factory[num_factory/2])
+- return -19;
+-
+- /* The transport should be newly created. */
+- for (i = 0; i < ntp; ++i) {
+- if (tp[i] == tcp) {
+- break;
+- }
+- }
+- if (i != ntp)
+- return -20;
+-
+- tp[ntp++] = tcp;
+-
+- for (i = 0; i<ntp; ++i) {
+- if (pj_atomic_get(tp[i]->ref_cnt) != 1)
+- return -21;
+- }
+- *num_tp = ntp;
+-
+- return PJ_SUCCESS;
+-}
+-
+-int transport_tcp_test(void)
+-{
+- enum { SEND_RECV_LOOP = 8 };
+- enum { NUM_LISTENER = 4 };
+- enum { NUM_TP = 8 };
+- pjsip_tpfactory *tpfactory[NUM_LISTENER];
+- pjsip_transport *tcp[NUM_TP];
+- pj_sockaddr_in rem_addr;
+- pj_status_t status;
+- char url[PJSIP_MAX_URL_SIZE];
+- char addr[PJ_INET_ADDRSTRLEN];
+- int rtt[SEND_RECV_LOOP], min_rtt;
+- int pkt_lost;
+- unsigned i;
+- unsigned num_listener = NUM_LISTENER;
+- unsigned num_tp = NUM_TP;
+-
+- status = multi_listener_test(tpfactory, num_listener, tcp, &num_tp);
+- if (status != PJ_SUCCESS)
+- return status;
+-
+- /* Get the last listener address */
+- status = pj_sockaddr_in_init(&rem_addr, &tpfactory[0]->addr_name.host,
+- (pj_uint16_t)tpfactory[0]->addr_name.port);
+-
+- pj_ansi_sprintf(url, "sip:alice@%s:%d;transport=tcp",
+- pj_inet_ntop2(pj_AF_INET(), &rem_addr.sin_addr, addr,
+- sizeof(addr)),
+- pj_ntohs(rem_addr.sin_port));
++ return -40;
+
+ /* Load test */
+ if (transport_load_test(url) != 0)
+@@ -184,13 +94,10 @@ int transport_tcp_test(void)
+
+ /* Basic transport's send/receive loopback test. */
+ for (i=0; i<SEND_RECV_LOOP; ++i) {
+- status = transport_send_recv_test(PJSIP_TRANSPORT_TCP, tcp[0], url,
+- &rtt[i]);
++ status = transport_send_recv_test(PJSIP_TRANSPORT_TCP, tcp, url, &rtt[i]);
+
+ if (status != 0) {
+- for (i = 0; i < num_tp ; ++i) {
+- pjsip_transport_dec_ref(tcp[i]);
+- }
++ pjsip_transport_dec_ref(tcp);
+ flush_events(500);
+ return -72;
+ }
+@@ -208,11 +115,9 @@ int transport_tcp_test(void)
+
+
+ /* Multi-threaded round-trip test. */
+- status = transport_rt_test(PJSIP_TRANSPORT_TCP, tcp[0], url, &pkt_lost);
++ status = transport_rt_test(PJSIP_TRANSPORT_TCP, tcp, url, &pkt_lost);
+ if (status != 0) {
+- for (i = 0; i < num_tp ; ++i) {
+- pjsip_transport_dec_ref(tcp[i]);
+- }
++ pjsip_transport_dec_ref(tcp);
+ return status;
+ }
+
+@@ -220,28 +125,22 @@ int transport_tcp_test(void)
+ PJ_LOG(3,(THIS_FILE, " note: %d packet(s) was lost", pkt_lost));
+
+ /* Check again that reference counter is still 1. */
+- for (i = 0; i < num_tp; ++i) {
+- if (pj_atomic_get(tcp[i]->ref_cnt) != 1)
+- return -80;
+- }
++ if (pj_atomic_get(tcp->ref_cnt) != 1)
++ return -80;
+
+- for (i = 0; i < num_tp; ++i) {
+- /* Destroy this transport. */
+- pjsip_transport_dec_ref(tcp[i]);
++ /* Destroy this transport. */
++ pjsip_transport_dec_ref(tcp);
+
+- /* Force destroy this transport. */
+- status = pjsip_transport_destroy(tcp[i]);
+- if (status != PJ_SUCCESS)
+- return -90;
+- }
++ /* Force destroy this transport. */
++ status = pjsip_transport_destroy(tcp);
++ if (status != PJ_SUCCESS)
++ return -90;
+
+- for (i = 0; i < num_listener; ++i) {
+- /* Unregister factory */
+- status = pjsip_tpmgr_unregister_tpfactory(pjsip_endpt_get_tpmgr(endpt),
+- tpfactory[i]);
+- if (status != PJ_SUCCESS)
+- return -95;
+- }
++ /* Unregister factory */
++ status = pjsip_tpmgr_unregister_tpfactory(pjsip_endpt_get_tpmgr(endpt),
++ tpfactory);
++ if (status != PJ_SUCCESS)
++ return -95;
+
+ /* Flush events. */
+ PJ_LOG(3,(THIS_FILE, " Flushing events, 1 second..."));
+diff --git a/pjsip/src/test/transport_udp_test.c b/pjsip/src/test/transport_udp_test.c
+index 579c7f071..bc0831a38 100644
+--- pjsip/src/test/transport_udp_test.c
++++ pjsip/src/test/transport_udp_test.c
+@@ -24,88 +24,6 @@
+
+ #define THIS_FILE "transport_udp_test.c"
+
+-static pj_status_t multi_transport_test(pjsip_transport *tp[], unsigned num_tp)
+-{
+- pj_status_t status;
+- pj_uint16_t i = 0;
+- pj_str_t s;
+- pjsip_transport *udp_tp;
+- pj_sockaddr_in rem_addr;
+- pjsip_tpselector tp_sel;
+-
+- for (;i<num_tp;++i)
+- {
+- pj_sockaddr_in addr;
+-
+- pj_sockaddr_in_init(&addr, NULL, TEST_UDP_PORT+i);
+-
+- /* Start UDP transport. */
+- status = pjsip_udp_transport_start( endpt, &addr, NULL, 1, &udp_tp);
+- if (status != PJ_SUCCESS) {
+- app_perror(" Error: unable to start UDP transport", status);
+- return -110;
+- }
+-
+- /* UDP transport must have initial reference counter set to 1. */
+- if (pj_atomic_get(udp_tp->ref_cnt) != 1)
+- return -120;
+-
+- /* Test basic transport attributes */
+- status = generic_transport_test(udp_tp);
+- if (status != PJ_SUCCESS)
+- return status;
+-
+- tp[i] = udp_tp;
+- }
+-
+- for (i = 0; i < num_tp; ++i) {
+- udp_tp = tp[i];
+- if (pj_atomic_get(udp_tp->ref_cnt) != 1)
+- return -130;
+- }
+-
+- /* Acquire transport test without selector. */
+- pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80);
+- status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP,
+- &rem_addr, sizeof(rem_addr),
+- NULL, &udp_tp);
+- if (status != PJ_SUCCESS)
+- return -140;
+-
+- for (i = 0; i < num_tp; ++i) {
+- if (udp_tp == tp[i]) {
+- break;
+- }
+- }
+- if (i == num_tp)
+- return -150;
+-
+- pjsip_transport_dec_ref(udp_tp);
+-
+- if (pj_atomic_get(udp_tp->ref_cnt) != 1)
+- return -160;
+-
+- /* Acquire transport test with selector. */
+- pj_bzero(&tp_sel, sizeof(tp_sel));
+- tp_sel.type = PJSIP_TPSELECTOR_TRANSPORT;
+- tp_sel.u.transport = tp[num_tp-1];
+- pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80);
+- status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP,
+- &rem_addr, sizeof(rem_addr),
+- &tp_sel, &udp_tp);
+- if (status != PJ_SUCCESS)
+- return -170;
+-
+- if (udp_tp != tp[num_tp-1])
+- return -180;
+-
+- pjsip_transport_dec_ref(udp_tp);
+-
+- if (pj_atomic_get(udp_tp->ref_cnt) != 1)
+- return -190;
+-
+- return PJ_SUCCESS;
+-}
+
+ /*
+ * UDP transport test.
+@@ -113,22 +31,56 @@ static pj_status_t multi_transport_test(pjsip_transport *tp[], unsigned num_tp)
+ int transport_udp_test(void)
+ {
+ enum { SEND_RECV_LOOP = 8 };
+- enum { NUM_TP = 4 };
+- pjsip_transport *tp[NUM_TP], *udp_tp;
+- pj_sockaddr_in rem_addr;
++ pjsip_transport *udp_tp, *tp;
++ pj_sockaddr_in addr, rem_addr;
+ pj_str_t s;
+ pj_status_t status;
+ int rtt[SEND_RECV_LOOP], min_rtt;
+ int i, pkt_lost;
+
+- status = multi_transport_test(&tp[0], NUM_TP);
++ pj_sockaddr_in_init(&addr, NULL, TEST_UDP_PORT);
++
++ /* Start UDP transport. */
++ status = pjsip_udp_transport_start( endpt, &addr, NULL, 1, &udp_tp);
++ if (status != PJ_SUCCESS) {
++ app_perror(" Error: unable to start UDP transport", status);
++ return -10;
++ }
++
++ /* UDP transport must have initial reference counter set to 1. */
++ if (pj_atomic_get(udp_tp->ref_cnt) != 1)
++ return -20;
++
++ /* Test basic transport attributes */
++ status = generic_transport_test(udp_tp);
+ if (status != PJ_SUCCESS)
+ return status;
+
++ /* Test that transport manager is returning the correct
++ * transport.
++ */
++ pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80);
++ status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP,
++ &rem_addr, sizeof(rem_addr),
++ NULL, &tp);
++ if (status != PJ_SUCCESS)
++ return -50;
++ if (tp != udp_tp)
++ return -60;
++
++ /* pjsip_endpt_acquire_transport() adds reference, so we need
++ * to decrement it.
++ */
++ pjsip_transport_dec_ref(tp);
++
++ /* Check again that reference counter is 1. */
++ if (pj_atomic_get(udp_tp->ref_cnt) != 1)
++ return -70;
++
+ /* Basic transport's send/receive loopback test. */
+ pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "127.0.0.1"), TEST_UDP_PORT);
+ for (i=0; i<SEND_RECV_LOOP; ++i) {
+- status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp[0],
++ status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp,
+ "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR,
+ &rtt[i]);
+ if (status != 0)
+@@ -146,7 +98,7 @@ int transport_udp_test(void)
+
+
+ /* Multi-threaded round-trip test. */
+- status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp[0],
++ status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp,
+ "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR,
+ &pkt_lost);
+ if (status != 0)
+@@ -155,19 +107,17 @@ int transport_udp_test(void)
+ if (pkt_lost != 0)
+ PJ_LOG(3,(THIS_FILE, " note: %d packet(s) was lost", pkt_lost));
+
+- for (i = 0; i < NUM_TP; ++i) {
+- udp_tp = tp[i];
++ /* Check again that reference counter is 1. */
++ if (pj_atomic_get(udp_tp->ref_cnt) != 1)
++ return -80;
+
+- /* Check again that reference counter is 1. */
+- if (pj_atomic_get(udp_tp->ref_cnt) != 1)
+- return -80;
++ /* Destroy this transport. */
++ pjsip_transport_dec_ref(udp_tp);
+
+- /* Destroy this transport. */
+- pjsip_transport_dec_ref(udp_tp);
+- status = pjsip_transport_destroy(udp_tp);
+- if (status != PJ_SUCCESS)
+- return -90;
+- }
++ /* Force destroy this transport. */
++ status = pjsip_transport_destroy(udp_tp);
++ if (status != PJ_SUCCESS)
++ return -90;
+
+ /* Flush events. */
+ PJ_LOG(3,(THIS_FILE, " Flushing events, 1 second..."));
+--
+2.21.0
+