From b842667be56101509908f4717ca58ca65a0bec67 Mon Sep 17 00:00:00 2001 From: Guido Falsi Date: Wed, 9 Oct 2019 14:33:37 +0000 Subject: [PATCH] Import patches from asterisk project. MFH: 2019Q4 --- net/pjsip/Makefile | 2 +- net/pjsip/files/patch-0030 | 60 ++ net/pjsip/files/patch-0031 | 84 +++ net/pjsip/files/patch-0032 | 64 +++ net/pjsip/files/patch-0033 | 1094 ++++++++++++++++++++++++++++++++++++ 5 files changed, 1303 insertions(+), 1 deletion(-) create mode 100644 net/pjsip/files/patch-0030 create mode 100644 net/pjsip/files/patch-0031 create mode 100644 net/pjsip/files/patch-0032 create mode 100644 net/pjsip/files/patch-0033 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 +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 +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 +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 +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 (;iaddr_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; iref_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; iref_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 (;iref_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; iref_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 +