diff --git a/contrib/src/pjproject/0001-rfc6544.patch b/contrib/src/pjproject/0001-rfc6544.patch index 182478456618d4502fe52b6f55af0c68a1091527..480c6a510302a11e7580ca275302735cee714400 100644 --- a/contrib/src/pjproject/0001-rfc6544.patch +++ b/contrib/src/pjproject/0001-rfc6544.patch @@ -1,31 +1,47 @@ -From bbf656dd46216c2551895abfb487b51ff786d1ae Mon Sep 17 00:00:00 2001 -From: jrun <darwinskernel@gmail.com> -Date: Wed, 26 Feb 2020 13:27:51 -0500 -Subject: [PATCH] rfc6544 +Copyright (C) 2018-2019 Savoir-faire Linux Inc. + +ice: rfc6544 support + +This patch is an implementation proposal of the RFC 6544 into PJNATH. +This allow PJNATH to support TCP ICE candidates and open a direct TCP +connection between peers. + ++ BUG (semi-fixed with this patch): If an active_sock is busy due to +a pending packet and receives a new packet to send, the final sent +packet will be a mix between the pending packet and the new one. +To avoid this, pj_ice_strans_sendto2 is now introduced. + +Written by +Sébastien Blin <sebastien.blin@savoirfairelinux.com> +on behalf of Savoir-faire Linux. + +Rebased for pjsip 2.10 by Peymane Marandi +<paymon@savoirfairelinux.com> +on behalf of Savoir-faire Linux. --- - pjnath/include/pjnath/ice_session.h | 173 +++- - pjnath/include/pjnath/ice_strans.h | 21 + - pjnath/include/pjnath/stun_session.h | 75 +- - pjnath/include/pjnath/stun_sock.h | 67 +- - pjnath/include/pjnath/turn_sock.h | 11 + + pjnath/include/pjnath/ice_session.h | 173 ++++++++++++++++++++++++++++++- + pjnath/include/pjnath/ice_strans.h | 21 ++++ + pjnath/include/pjnath/stun_session.h | 75 +++++++++++++- + pjnath/include/pjnath/stun_sock.h | 67 +++++++++++- + pjnath/include/pjnath/turn_sock.h | 11 ++ pjnath/src/pjnath-test/concur_test.c | 5 +- - pjnath/src/pjnath-test/sess_auth.c | 14 +- + pjnath/src/pjnath-test/sess_auth.c | 14 ++- pjnath/src/pjnath-test/stun_sock_test.c | 7 +- - pjnath/src/pjnath/ice_session.c | 513 ++++++++++- - pjnath/src/pjnath/ice_strans.c | 727 ++++++++++++--- + pjnath/src/pjnath/ice_session.c | 513 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- + pjnath/src/pjnath/ice_strans.c | 759 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- pjnath/src/pjnath/nat_detect.c | 7 +- - pjnath/src/pjnath/stun_session.c | 15 +- - pjnath/src/pjnath/stun_sock.c | 1076 +++++++++++++++++++---- + pjnath/src/pjnath/stun_session.c | 15 ++- + pjnath/src/pjnath/stun_sock.c | 1074 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- pjnath/src/pjnath/stun_transaction.c | 3 + pjnath/src/pjnath/turn_session.c | 3 +- - pjnath/src/pjnath/turn_sock.c | 17 + + pjnath/src/pjnath/turn_sock.c | 24 +++-- pjnath/src/pjturn-client/client_main.c | 2 +- pjnath/src/pjturn-srv/allocation.c | 3 +- pjnath/src/pjturn-srv/server.c | 2 +- - pjsip-apps/src/samples/icedemo.c | 116 ++- + pjsip-apps/src/samples/icedemo.c | 116 +++++++++++++++++++-- pjsip/src/pjsua-lib/pjsua_core.c | 2 +- - 21 files changed, 2481 insertions(+), 378 deletions(-) + 21 files changed, 2497 insertions(+), 399 deletions(-) diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h index 8971220f0..39c197c29 100644 @@ -1009,14 +1025,22 @@ index 2a4125bc5..cd9e32e25 100644 } -@@ -1892,40 +2067,96 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th, - LOG5((ice->obj_name, "Starting checklist periodic check")); +@@ -1893,39 +2068,95 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th, pj_log_push_indent(); -+ /* Send STUN Binding request for check with highest priority on + /* Send STUN Binding request for check with highest priority on +- * Waiting state. + * Retry state. -+ */ -+ + */ +- for (i=0; i<clist->count; ++i) { +- pj_ice_sess_check *check = &clist->checks[i]; + +- if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) { +- status = perform_check(ice, clist, i, ice->is_nominating); +- if (status != PJ_SUCCESS) { +- check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, +- status); +- on_check_complete(ice, check); + if (start_count == 0) { + for (i = 0; i < clist->count; ++i) { + pj_ice_sess_check *check = &clist->checks[i]; @@ -1030,10 +1054,12 @@ index 2a4125bc5..cd9e32e25 100644 + } + ++start_count; + break; -+ } + } + } + } -+ + +- ++start_count; +- break; + if (start_count == 0) { + // TODO (sblin) remove - https://github.com/coturn/coturn/issues/408 + pj_bool_t inc_counter = PJ_TRUE; @@ -1058,18 +1084,10 @@ index 2a4125bc5..cd9e32e25 100644 + } + } + - /* Send STUN Binding request for check with highest priority on - * Waiting state. - */ -- for (i=0; i<clist->count; ++i) { -- pj_ice_sess_check *check = &clist->checks[i]; - -- if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) { -- status = perform_check(ice, clist, i, ice->is_nominating); -- if (status != PJ_SUCCESS) { -- check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, -- status); -- on_check_complete(ice, check); ++ /* Send STUN Binding request for check with highest priority on ++ * Waiting state. ++ */ ++ + if (start_count == 0) { + for (i = 0; i < clist->count; ++i) { + pj_ice_sess_check *check = &clist->checks[i]; @@ -1083,10 +1101,7 @@ index 2a4125bc5..cd9e32e25 100644 + } + ++start_count; + break; - } -- -- ++start_count; -- break; ++ } } } @@ -1371,7 +1386,7 @@ index 2a4125bc5..cd9e32e25 100644 } } diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c -index 3cb350c2a..1cb6a6d14 100644 +index 3cb350c2a..40ae403d0 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -69,6 +69,7 @@ enum tp_type @@ -1489,7 +1504,24 @@ index 3cb350c2a..1cb6a6d14 100644 /* Create the TURN transport */ status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, turn_cfg->af, turn_cfg->conn_type, -@@ -481,6 +533,7 @@ static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, +@@ -465,7 +517,7 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, + return PJ_SUCCESS; + } + +-static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, ++static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, + pj_ice_sess_cand *rcand) + { + if (lcand == NULL && rcand == NULL){ +@@ -474,23 +526,23 @@ static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, + if (lcand == NULL || rcand == NULL){ + return PJ_FALSE; + } +- ++ + if (lcand->type != rcand->type + || lcand->status != rcand->status + || lcand->comp_id != rcand->comp_id || lcand->transport_id != rcand->transport_id || lcand->local_pref != rcand->local_pref || lcand->prio != rcand->prio @@ -1497,7 +1529,10 @@ index 3cb350c2a..1cb6a6d14 100644 || pj_sockaddr_cmp(&lcand->addr, &rcand->addr) != 0 || pj_sockaddr_cmp(&lcand->base_addr, &rcand->base_addr) != 0) { -@@ -490,7 +543,6 @@ static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, + return PJ_FALSE; + } +- ++ return PJ_TRUE; } @@ -1539,12 +1574,41 @@ index 3cb350c2a..1cb6a6d14 100644 - pj_bool_t cand_duplicate = PJ_FALSE; - char addrinfo[PJ_INET6_ADDRSTRLEN+10]; - const pj_sockaddr *addr = &stun_sock_info.aliases[i]; -- ++ status = !PJ_SUCCESS; ++ if (stun_sock_info.conn_type == PJ_STUN_TP_UDP) { ++ status = add_local_candidate(cand, idx, i, ++ &cand_cnt, &max_cand_cnt, ++ stun_sock_info, ice_st, comp, ++ PJ_CAND_UDP); ++ } else { ++ status = add_local_candidate(cand, idx, i, ++ &cand_cnt, &max_cand_cnt, ++ stun_sock_info, ice_st, comp, ++ PJ_CAND_TCP_PASSIVE); ++ /** RFC 6544, Section 4.1: ++ * First, agents SHOULD obtain host candidates as described in ++ * Section 5.1. Then, each agent SHOULD "obtain" (allocate a ++ * placeholder for) an active host candidate for each component of ++ * each TCP-capable media stream on each interface that the host ++ * has. The agent does not yet have to actually allocate a port for ++ * these candidates, but they are used for the creation of the check ++ * lists. ++ */ ++ status = add_local_candidate(cand, idx, i, ++ &cand_cnt, &max_cand_cnt, ++ stun_sock_info, ice_st, comp, ++ PJ_CAND_TCP_ACTIVE); ++ } ++ } ++ } + - if (max_cand_cnt==0) { - PJ_LOG(4,(ice_st->obj_name, "Too many host candidates")); - break; - } -- ++ return status; ++} + - /* Ignore loopback addresses if cfg->stun.loop_addr is unset */ - if (stun_cfg->loop_addr==PJ_FALSE) { - if (stun_cfg->af == pj_AF_INET() && @@ -1562,7 +1626,22 @@ index 3cb350c2a..1cb6a6d14 100644 - } - } - } -- ++static pj_bool_t add_local_candidate(pj_ice_sess_cand *cand, ++ unsigned idx, ++ unsigned i, ++ unsigned *cand_cnt, ++ unsigned *max_cand_cnt, ++ pj_stun_sock_info stun_sock_info, ++ pj_ice_strans *ice_st, ++ pj_ice_strans_comp *comp, ++ pj_ice_cand_transport transport) ++{ ++ unsigned j; ++ pj_bool_t cand_duplicate = PJ_FALSE; ++ char addrinfo[PJ_INET6_ADDRSTRLEN+10]; ++ const pj_sockaddr *addr = &stun_sock_info.aliases[i]; ++ pj_ice_strans_stun_cfg *stun_cfg = &ice_st->cfg.stun_tp[idx]; + - /* Ignore IPv6 link-local address, unless it is the default - * address (first alias). - */ @@ -1571,7 +1650,7 @@ index 3cb350c2a..1cb6a6d14 100644 - if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80) - continue; - } -- + - cand = &comp->cand_list[comp->cand_cnt]; - - cand->type = PJ_ICE_CAND_TYPE_HOST; @@ -1590,13 +1669,34 @@ index 3cb350c2a..1cb6a6d14 100644 - break; - } - } -- ++ if (*max_cand_cnt==0) { ++ PJ_LOG(4,(ice_st->obj_name, "Too many host candidates")); ++ return !PJ_SUCCESS; ++ } + - if (cand_duplicate) { - PJ_LOG(4, (ice_st->obj_name, - "Comp %d: host candidate %s (tpid=%d) is a duplicate", - comp->comp_id, pj_sockaddr_print(&cand->addr, addrinfo, - sizeof(addrinfo), 3), cand->transport_id)); -- ++ /* Ignore loopback addresses if cfg->stun.loop_addr is unset */ ++ if (stun_cfg->loop_addr==PJ_FALSE) { ++ if (stun_cfg->af == pj_AF_INET() && ++ (pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) ++ { ++ return PJ_SUCCESS; ++ } ++ else if (stun_cfg->af == pj_AF_INET6()) { ++ pj_in6_addr in6addr = {{0}}; ++ in6addr.s6_addr[15] = 1; ++ if (pj_memcmp(&in6addr, &addr->ipv6.sin6_addr, ++ sizeof(in6addr))==0) ++ { ++ return PJ_SUCCESS; ++ } ++ } ++ } + - pj_bzero(&cand->addr, sizeof(cand->addr)); - pj_bzero(&cand->base_addr, sizeof(cand->base_addr)); - continue; @@ -1608,7 +1708,15 @@ index 3cb350c2a..1cb6a6d14 100644 - - pj_ice_calc_foundation(ice_st->pool, &cand->foundation, - cand->type, &cand->base_addr); -- ++ /* Ignore IPv6 link-local address, unless it is the default ++ * address (first alias). ++ */ ++ if (stun_cfg->af == pj_AF_INET6() && i != 0) { ++ const pj_in6_addr *a = &addr->ipv6.sin6_addr; ++ if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80) ++ return PJ_SUCCESS; ++ } + - /* Set default candidate with the preferred default - * address family - */ @@ -1619,7 +1727,8 @@ index 3cb350c2a..1cb6a6d14 100644 - { - comp->default_cand = (unsigned)(cand - comp->cand_list); - } -- ++ cand = &comp->cand_list[comp->cand_cnt]; + - PJ_LOG(4,(ice_st->obj_name, - "Comp %d/%d: host candidate %s (tpid=%d) added", - comp->comp_id, comp->cand_cnt-1, @@ -1627,88 +1736,6 @@ index 3cb350c2a..1cb6a6d14 100644 - sizeof(addrinfo), 3), - cand->transport_id)); - } -+ status = !PJ_SUCCESS; -+ if (stun_sock_info.conn_type == PJ_STUN_TP_UDP) { -+ status = add_local_candidate(cand, idx, i, -+ &cand_cnt, &max_cand_cnt, -+ stun_sock_info, ice_st, comp, -+ PJ_CAND_UDP); -+ } else { -+ status = add_local_candidate(cand, idx, i, -+ &cand_cnt, &max_cand_cnt, -+ stun_sock_info, ice_st, comp, -+ PJ_CAND_TCP_PASSIVE); -+ /** RFC 6544, Section 4.1: -+ * First, agents SHOULD obtain host candidates as described in -+ * Section 5.1. Then, each agent SHOULD "obtain" (allocate a -+ * placeholder for) an active host candidate for each component of -+ * each TCP-capable media stream on each interface that the host -+ * has. The agent does not yet have to actually allocate a port for -+ * these candidates, but they are used for the creation of the check -+ * lists. -+ */ -+ status = add_local_candidate(cand, idx, i, -+ &cand_cnt, &max_cand_cnt, -+ stun_sock_info, ice_st, comp, -+ PJ_CAND_TCP_ACTIVE); -+ } -+ } - } - - return status; - } - -+static pj_bool_t add_local_candidate(pj_ice_sess_cand *cand, -+ unsigned idx, -+ unsigned i, -+ unsigned *cand_cnt, -+ unsigned *max_cand_cnt, -+ pj_stun_sock_info stun_sock_info, -+ pj_ice_strans *ice_st, -+ pj_ice_strans_comp *comp, -+ pj_ice_cand_transport transport) -+{ -+ unsigned j; -+ pj_bool_t cand_duplicate = PJ_FALSE; -+ char addrinfo[PJ_INET6_ADDRSTRLEN+10]; -+ const pj_sockaddr *addr = &stun_sock_info.aliases[i]; -+ pj_ice_strans_stun_cfg *stun_cfg = &ice_st->cfg.stun_tp[idx]; -+ -+ -+ if (*max_cand_cnt==0) { -+ PJ_LOG(4,(ice_st->obj_name, "Too many host candidates")); -+ return !PJ_SUCCESS; -+ } -+ -+ /* Ignore loopback addresses if cfg->stun.loop_addr is unset */ -+ if (stun_cfg->loop_addr==PJ_FALSE) { -+ if (stun_cfg->af == pj_AF_INET() && -+ (pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) -+ { -+ return PJ_SUCCESS; -+ } -+ else if (stun_cfg->af == pj_AF_INET6()) { -+ pj_in6_addr in6addr = {{0}}; -+ in6addr.s6_addr[15] = 1; -+ if (pj_memcmp(&in6addr, &addr->ipv6.sin6_addr, -+ sizeof(in6addr))==0) -+ { -+ return PJ_SUCCESS; -+ } -+ } -+ } -+ -+ /* Ignore IPv6 link-local address, unless it is the default -+ * address (first alias). -+ */ -+ if (stun_cfg->af == pj_AF_INET6() && i != 0) { -+ const pj_in6_addr *a = &addr->ipv6.sin6_addr; -+ if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80) -+ return PJ_SUCCESS; -+ } -+ -+ cand = &comp->cand_list[comp->cand_cnt]; -+ + cand->type = PJ_ICE_CAND_TYPE_HOST; + cand->status = PJ_SUCCESS; + cand->local_pref = HOST_PREF; @@ -1726,8 +1753,10 @@ index 3cb350c2a..1cb6a6d14 100644 + cand_duplicate = PJ_TRUE; + return !PJ_SUCCESS; + } -+ } -+ + } + +- return status; +-} + if (cand_duplicate) { + PJ_LOG(4, (ice_st->obj_name, + "Comp %d: host candidate %s (tpid=%d) is a duplicate", @@ -1744,7 +1773,7 @@ index 3cb350c2a..1cb6a6d14 100644 + (*cand_cnt)++; + (*max_cand_cnt)--; + } -+ + + pj_ice_calc_foundation(ice_st->pool, &cand->foundation, + cand->type, &cand->base_addr); + @@ -1775,6 +1804,51 @@ index 3cb350c2a..1cb6a6d14 100644 /* * Create the component. +@@ -816,7 +921,7 @@ static pj_status_t alloc_send_buf(pj_ice_strans *ice_st, unsigned buf_size) + { + if (buf_size > ice_st->buf_size) { + unsigned i; +- ++ + if (ice_st->is_pending) { + /* The current buffer is insufficient, but still currently used.*/ + return PJ_EBUSY; +@@ -839,7 +944,7 @@ static pj_status_t alloc_send_buf(pj_ice_strans *ice_st, unsigned buf_size) + } + ice_st->buf_idx = ice_st->empty_idx = 0; + } +- ++ + return PJ_SUCCESS; + } + +@@ -906,7 +1011,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_create( const char *name, + /* To maintain backward compatibility, check if old/deprecated setting is set + * and the new setting is not, copy the value to the new setting. + */ +- if (cfg->stun_tp_cnt == 0 && ++ if (cfg->stun_tp_cnt == 0 && + (cfg->stun.server.slen || cfg->stun.max_host_cands)) + { + ice_st->cfg.stun_tp_cnt = 1; +@@ -1105,7 +1210,7 @@ static void sess_init_update(pj_ice_strans *ice_st) + pj_ice_get_cand_type_name(cand->type))); + return; + } +- ++ + if (status == PJ_EUNKNOWN) { + status = cand->status; + } else { +@@ -1114,7 +1219,7 @@ static void sess_init_update(pj_ice_strans *ice_st) + status = PJ_SUCCESS; + } + } +- ++ + if (status != PJ_SUCCESS) + break; + } @@ -1207,6 +1312,12 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, ice_cb.on_ice_complete = &on_ice_complete; ice_cb.on_rx_data = &ice_rx_data; @@ -1798,7 +1872,52 @@ index 3cb350c2a..1cb6a6d14 100644 if (status != PJ_SUCCESS) goto on_error; } -@@ -1668,7 +1780,31 @@ static pj_status_t send_data(pj_ice_strans *ice_st, +@@ -1544,7 +1656,7 @@ pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st, + PJ_DEF(pj_status_t) pj_ice_strans_stop_ice(pj_ice_strans *ice_st) + { + PJ_ASSERT_RETURN(ice_st, PJ_EINVAL); +- ++ + /* Protect with group lock, since this may cause race condition with + * pj_ice_strans_sendto2(). + * See ticket #1877. +@@ -1578,7 +1690,7 @@ static pj_status_t use_buffer( pj_ice_strans *ice_st, + status = alloc_send_buf(ice_st, data_len); + if (status != PJ_SUCCESS) + return status; +- ++ + if (ice_st->is_pending && ice_st->empty_idx == ice_st->buf_idx) { + /* We don't use buffer or there's no more empty buffer. */ + return PJ_EBUSY; +@@ -1593,12 +1705,12 @@ static pj_status_t use_buffer( pj_ice_strans *ice_st, + pj_sockaddr_cp(&ice_st->send_buf[idx].dst_addr, dst_addr); + ice_st->send_buf[idx].dst_addr_len = dst_addr_len; + *buffer = ice_st->send_buf[idx].buffer; +- ++ + if (ice_st->is_pending) { + /* We'll continue later since there's still a pending send. */ + return PJ_EPENDING; + } +- ++ + ice_st->is_pending = PJ_TRUE; + ice_st->buf_idx = idx; + +@@ -1659,16 +1771,40 @@ static pj_status_t send_data(pj_ice_strans *ice_st, + */ + if (ice_st->ice && ice_st->state == PJ_ICE_STRANS_STATE_RUNNING) { + status = pj_ice_sess_send_data(ice_st->ice, comp_id, buf, data_len); +- ++ + pj_grp_lock_release(ice_st->grp_lock); +- ++ + goto on_return; +- } ++ } + pj_grp_lock_release(ice_st->grp_lock); def_cand = &comp->cand_list[comp->default_cand]; @@ -1843,6 +1962,15 @@ index 3cb350c2a..1cb6a6d14 100644 goto on_return; } +@@ -1771,7 +1912,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st, + dst_addr_len, PJ_TRUE, PJ_FALSE); + if (status == PJ_EPENDING) + status = PJ_SUCCESS; +- ++ + return status; + } + #endif @@ -1842,7 +1983,22 @@ static void on_ice_complete(pj_ice_sess *ice, pj_status_t status) sizeof(lip), 3); pj_sockaddr_print(&check->rcand->addr, rip, @@ -1897,6 +2025,15 @@ index 3cb350c2a..1cb6a6d14 100644 if (tp_typ == TP_TURN) { if (comp->turn[tp_idx].sock) { status = pj_turn_sock_sendto(comp->turn[tp_idx].sock, +@@ -1958,7 +2137,7 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, + if (status != PJ_SUCCESS) { + goto on_return; + } +- ++ + pj_sockaddr_cp(&comp->dst_addr, dst_addr); + comp->synth_addr_len = pj_sockaddr_get_len(&comp->synth_addr); + } @@ -1969,9 +2148,13 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, dest_addr_len = dst_addr_len; } @@ -1914,6 +2051,15 @@ index 3cb350c2a..1cb6a6d14 100644 } else { pj_assert(!"Invalid transport ID"); status = PJ_EINVALIDOP; +@@ -2017,7 +2200,7 @@ static void check_pending_send(pj_ice_strans *ice_st) + + if (ice_st->num_buf > 0) + ice_st->buf_idx = (ice_st->buf_idx + 1) % ice_st->num_buf; +- ++ + if (ice_st->num_buf > 0 && ice_st->buf_idx != ice_st->empty_idx) { + /* There's some pending send. Send it one by one. */ + pending_send *ps = &ice_st->send_buf[ice_st->buf_idx]; @@ -2031,6 +2214,237 @@ static void check_pending_send(pj_ice_strans *ice_st) } } @@ -2152,6 +2298,47 @@ index 3cb350c2a..1cb6a6d14 100644 /* Notifification when asynchronous send operation via STUN/TURN * has completed. */ +@@ -2196,7 +2610,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, + { + /* We get an IPv4 mapped address for our IPv6 + * host address. +- */ ++ */ + comp->ipv4_mapped = PJ_TRUE; + + /* Find other host candidates with the same (IPv6) +@@ -2208,7 +2622,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, + + if (comp->cand_list[i].type != PJ_ICE_CAND_TYPE_HOST) + continue; +- ++ + a1 = &comp->cand_list[i].addr; + a2 = &cand->base_addr; + if (pj_memcmp(pj_sockaddr_get_addr(a1), +@@ -2225,7 +2639,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, + pj_sockaddr_cp(&cand->base_addr, &info.mapped_addr); + pj_sockaddr_cp(&cand->rel_addr, &info.mapped_addr); + } +- ++ + /* Eliminate the srflx candidate if the address is + * equal to other (host) candidates. + */ +@@ -2268,11 +2682,11 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, + sizeof(ipaddr), 3))); + + sess_init_update(ice_st); +- ++ + if (op == PJ_STUN_SOCK_MAPPED_ADDR_CHANGE && + ice_st->cb.on_ice_complete) + { +- (*ice_st->cb.on_ice_complete)(ice_st, ++ (*ice_st->cb.on_ice_complete)(ice_st, + PJ_ICE_STRANS_OP_ADDR_CHANGE, + status); + } @@ -2318,6 +2732,10 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, } } @@ -2170,15 +2357,14 @@ index 3cb350c2a..1cb6a6d14 100644 - status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, - data->transport_id, pkt, pkt_len, - peer_addr, addr_len); -- ++ if (comp->ice_st->cfg.turn_tp->conn_type == PJ_TURN_TP_TCP && pkt_len > 0) { ++ unsigned parsed = 0; ++ pj_status_t status; + - if (status != PJ_SUCCESS) { - ice_st_perror(comp->ice_st, - "Error processing packet from TURN relay", - status); -+ if (comp->ice_st->cfg.turn_tp->conn_type == PJ_TURN_TP_TCP && pkt_len > 0) { -+ unsigned parsed = 0; -+ pj_status_t status; -+ + do { + pj_uint16_t leftover = pkt_len - parsed; + pj_uint8_t *current_packet = ((pj_uint8_t *)(pkt)) + parsed; @@ -2688,7 +2874,7 @@ index 5fe825cf5..c4519f82e 100644 stun_sock->ka_interval = cfg->ka_interval; if (stun_sock->ka_interval == 0) -@@ -226,125 +480,6 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, +@@ -226,140 +480,68 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, pj_grp_lock_add_handler(stun_sock->grp_lock, pool, stun_sock, &stun_sock_destructor); @@ -2703,7 +2889,10 @@ index 5fe825cf5..c4519f82e 100644 - NULL); - if (status != PJ_SUCCESS && !cfg->qos_ignore_error) - goto on_error; -- ++ /* Create STUN session */ ++ { ++ pj_stun_session_cb sess_cb; + - /* Apply socket buffer size */ - if (cfg->so_rcvbuf_size > 0) { - unsigned sobuf_size = cfg->so_rcvbuf_size; @@ -2728,7 +2917,16 @@ index 5fe825cf5..c4519f82e 100644 - unsigned sobuf_size = cfg->so_sndbuf_size; - status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_SNDBUF(), - PJ_TRUE, &sobuf_size); -- if (status != PJ_SUCCESS) { ++ pj_bzero(&sess_cb, sizeof(sess_cb)); ++ sess_cb.on_request_complete = &sess_on_request_complete; ++ sess_cb.on_send_msg = &sess_on_send_msg; ++ status = pj_stun_session_create(&stun_sock->stun_cfg, ++ stun_sock->obj_name, ++ &sess_cb, PJ_FALSE, ++ stun_sock->grp_lock, ++ &stun_sock->stun_sess, ++ conn_type); + if (status != PJ_SUCCESS) { - PJ_PERROR(3, (stun_sock->obj_name, status, - "Failed setting SO_SNDBUF")); - } else { @@ -2741,9 +2939,11 @@ index 5fe825cf5..c4519f82e 100644 - PJ_LOG(5, (stun_sock->obj_name, "SO_SNDBUF set to %d", - sobuf_size)); - } -- } -- } -- ++ pj_stun_sock_destroy(stun_sock); ++ return status; + } + } + - /* Bind socket */ - max_bind_retry = MAX_BIND_RETRY; - if (cfg->port_range && cfg->port_range < max_bind_retry) @@ -2758,24 +2958,47 @@ index 5fe825cf5..c4519f82e 100644 - cfg->port_range, max_bind_retry); - if (status != PJ_SUCCESS) - goto on_error; -- ++ pj_stun_sock_alloc(stun_sock); + - /* Create more useful information string about this transport */ -#if 0 - { - pj_sockaddr bound_addr; - int addr_len = sizeof(bound_addr); -- ++ /* Done */ ++ *p_stun_sock = stun_sock; ++ return PJ_SUCCESS; ++} + - status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, - &addr_len); - if (status != PJ_SUCCESS) - goto on_error; -- ++/* ++ * Notification when outgoing TCP socket has been connected. ++ */ ++static pj_bool_t on_stun_sock_ready(pj_activesock_t *asock, pj_status_t status) ++{ ++ pj_stun_sock *stun_sock; ++ stun_sock = (pj_stun_sock *)pj_activesock_get_user_data(asock); ++ if (!stun_sock) ++ return PJ_FALSE; ++ ++ pj_grp_lock_acquire(stun_sock->grp_lock); + - stun_sock->info = pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+10); - pj_sockaddr_print(&bound_addr, stun_sock->info, - PJ_INET6_ADDRSTRLEN, 3); -- } ++ /* TURN session may have already been destroyed here. ++ * See ticket #1557 (http://trac.pjsip.org/repos/ticket/1557). ++ */ ++ if (!stun_sock->stun_sess) { ++ sess_fail(stun_sock, PJ_STUN_SESS_DESTROYED, status); ++ pj_grp_lock_release(stun_sock->grp_lock); ++ return PJ_FALSE; + } -#endif -- + - /* Init active socket configuration */ - { - pj_activesock_cfg activesock_cfg; @@ -2809,74 +3032,39 @@ index 5fe825cf5..c4519f82e 100644 - sizeof(stun_sock->send_key)); - pj_ioqueue_op_key_init(&stun_sock->int_send_key, - sizeof(stun_sock->int_send_key)); -- } -- - /* Create STUN session */ - { - pj_stun_session_cb sess_cb; -@@ -356,11 +491,58 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, - stun_sock->obj_name, - &sess_cb, PJ_FALSE, - stun_sock->grp_lock, -- &stun_sock->stun_sess); -- if (status != PJ_SUCCESS) -- goto on_error; -+ &stun_sock->stun_sess, -+ conn_type); -+ if (status != PJ_SUCCESS) { -+ pj_stun_sock_destroy(stun_sock); -+ return status; -+ } - } - -+ pj_stun_sock_alloc(stun_sock); -+ -+ /* Done */ -+ *p_stun_sock = stun_sock; -+ return PJ_SUCCESS; -+} -+ -+/* -+ * Notification when outgoing TCP socket has been connected. -+ */ -+static pj_bool_t on_stun_sock_ready(pj_activesock_t *asock, pj_status_t status) -+{ -+ pj_stun_sock *stun_sock; -+ stun_sock = (pj_stun_sock *)pj_activesock_get_user_data(asock); -+ if (!stun_sock) -+ return PJ_FALSE; -+ -+ pj_grp_lock_acquire(stun_sock->grp_lock); -+ -+ /* TURN session may have already been destroyed here. -+ * See ticket #1557 (http://trac.pjsip.org/repos/ticket/1557). -+ */ -+ if (!stun_sock->stun_sess) { -+ sess_fail(stun_sock, PJ_STUN_SESS_DESTROYED, status); -+ pj_grp_lock_release(stun_sock->grp_lock); -+ return PJ_FALSE; -+ } -+ + if (status != PJ_SUCCESS) { + sess_fail(stun_sock, PJ_STUN_TCP_CONNECT_ERROR, status); + pj_grp_lock_release(stun_sock->grp_lock); + return PJ_FALSE; -+ } -+ + } + +- /* Create STUN session */ +- { +- pj_stun_session_cb sess_cb; + if (stun_sock->conn_type != PJ_STUN_TP_UDP) + PJ_LOG(5,(stun_sock->obj_name, "TCP connected")); -+ + +- pj_bzero(&sess_cb, sizeof(sess_cb)); +- sess_cb.on_request_complete = &sess_on_request_complete; +- sess_cb.on_send_msg = &sess_on_send_msg; +- status = pj_stun_session_create(&stun_sock->stun_cfg, +- stun_sock->obj_name, +- &sess_cb, PJ_FALSE, +- stun_sock->grp_lock, +- &stun_sock->stun_sess); +- if (status != PJ_SUCCESS) +- goto on_error; +- } + /* Start asynchronous read operations */ + pj_status_t result; + result = pj_activesock_start_recvfrom(asock, stun_sock->pool, + stun_sock->cfg.max_pkt_size, 0); + if (result != PJ_SUCCESS) + return PJ_FALSE; -+ + /* Associate us with the STUN session */ pj_stun_session_set_user_data(stun_sock->stun_sess, stun_sock); - -@@ -369,24 +551,303 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, +@@ -369,25 +551,304 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, * STUN messages we sent with STUN messages that the application sends. * The last 16bit value in the array is a counter. */ @@ -2910,8 +3098,8 @@ index 5fe825cf5..c4519f82e 100644 + + pj_grp_lock_release(stun_sock->grp_lock); + return PJ_TRUE; -+} -+ + } + +static pj_bool_t parse_rx_packet(pj_activesock_t *asock, + void *data, + pj_size_t size, @@ -3182,11 +3370,12 @@ index 5fe825cf5..c4519f82e 100644 + return PJ_FALSE; + + return PJ_TRUE; - } ++} +#endif - ++ /* Start socket. */ PJ_DEF(pj_status_t) pj_stun_sock_start( pj_stun_sock *stun_sock, + const pj_str_t *domain, @@ -526,6 +987,26 @@ PJ_DEF(pj_status_t) pj_stun_sock_destroy(pj_stun_sock *stun_sock) stun_sock->sock_fd = PJ_INVALID_SOCKET; } @@ -3630,10 +3819,24 @@ index a378b8672..88985af69 100644 do_destroy(sess); return status; diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c -index dc6304d9f..9b69a6a21 100644 +index dc6304d9f..a6e192e9f 100644 --- a/pjnath/src/pjnath/turn_sock.c +++ b/pjnath/src/pjnath/turn_sock.c -@@ -1766,3 +1766,20 @@ static void turn_on_connection_bind_status(pj_turn_session *sess, +@@ -894,12 +894,7 @@ static pj_bool_t on_data_sent(pj_turn_sock *turn_sock, + } + + if (turn_sock->cb.on_data_sent) { +- pj_ssize_t header_len, sent_size; +- +- /* Remove the length of packet header from sent size. */ +- header_len = turn_sock->pkt_len - turn_sock->body_len; +- sent_size = (sent > header_len)? (sent - header_len) : 0; +- (*turn_sock->cb.on_data_sent)(turn_sock, sent_size); ++ (*turn_sock->cb.on_data_sent)(turn_sock, sent); + } + + return PJ_TRUE; +@@ -1766,3 +1761,20 @@ static void turn_on_connection_bind_status(pj_turn_session *sess, peer_addr, addr_len); } } @@ -3924,6 +4127,3 @@ index 474a8d07c..9257f07a4 100644 NULL, sess, &sess->stun_sock); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; --- -2.24.1 -