diff --git a/contrib/src/pjproject/0001-rfc6544.patch b/contrib/src/pjproject/0001-rfc6544.patch index 2ee2626c47371dbc86fd45dc23b04e628f385bfb..fe8e05a1e2277dc1af67004e1e50adce809f72c9 100644 --- a/contrib/src/pjproject/0001-rfc6544.patch +++ b/contrib/src/pjproject/0001-rfc6544.patch @@ -1,4 +1,4 @@ -Copyright (C) 2018-2019 Savoir-faire Linux Inc. +Copyright (C) 2018-2020 Savoir-faire Linux Inc. ice: rfc6544 support @@ -18,8 +18,9 @@ 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_session.h | 151 +++- pjnath/include/pjnath/ice_strans.h | 21 + pjnath/include/pjnath/stun_session.h | 75 +- pjnath/include/pjnath/stun_sock.h | 67 +- @@ -27,8 +28,8 @@ on behalf of Savoir-faire Linux. pjnath/src/pjnath-test/concur_test.c | 5 +- pjnath/src/pjnath-test/sess_auth.c | 14 +- pjnath/src/pjnath-test/stun_sock_test.c | 7 +- - pjnath/src/pjnath/ice_session.c | 515 ++++++++++- - pjnath/src/pjnath/ice_strans.c | 773 +++++++++++++--- + pjnath/src/pjnath/ice_session.c | 491 +++++++++-- + pjnath/src/pjnath/ice_strans.c | 745 +++++++++++++--- pjnath/src/pjnath/nat_detect.c | 7 +- pjnath/src/pjnath/stun_session.c | 15 +- pjnath/src/pjnath/stun_sock.c | 1075 +++++++++++++++++++---- @@ -40,16 +41,16 @@ on behalf of Savoir-faire Linux. pjnath/src/pjturn-srv/server.c | 2 +- pjsip-apps/src/samples/icedemo.c | 116 ++- pjsip/src/pjsua-lib/pjsua_core.c | 2 +- - 21 files changed, 2510 insertions(+), 403 deletions(-) + 21 files changed, 2430 insertions(+), 409 deletions(-) diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h -index 8971220f0..39c197c29 100644 +index 8971220f0..4cccd7c64 100644 --- a/pjnath/include/pjnath/ice_session.h +++ b/pjnath/include/pjnath/ice_session.h @@ -163,6 +163,52 @@ typedef enum pj_ice_cand_type - + } pj_ice_cand_type; - + +/** + * ICE candidates types like described by RFC 6544. + */ @@ -96,25 +97,25 @@ index 8971220f0..39c197c29 100644 + +} pj_ice_tp_type; + - + /** Forward declaration for pj_ice_sess */ typedef struct pj_ice_sess pj_ice_sess; @@ -309,6 +355,11 @@ typedef struct pj_ice_sess_cand */ pj_sockaddr rel_addr; - + + /** + * Transport used (TCP or UDP) + */ + pj_ice_cand_transport transport; + } pj_ice_sess_cand; - - + + @@ -324,6 +375,22 @@ typedef enum pj_ice_sess_check_state */ PJ_ICE_SESS_CHECK_STATE_FROZEN, - + + /** + * The following status is used when a packet sent via TURN got a + * "Connection reset by peer". This mean that the peer didn't allow @@ -137,7 +138,7 @@ index 8971220f0..39c197c29 100644 @@ -331,6 +398,12 @@ typedef enum pj_ice_sess_check_state */ PJ_ICE_SESS_CHECK_STATE_WAITING, - + + /** + * A check has not been performed for this pair, but TCP socket + * is currently connecting to the pair. Wait to finish the connection. @@ -147,7 +148,7 @@ index 8971220f0..39c197c29 100644 /** * A check has not been performed for this pair, and can be * performed as soon as it is the highest priority Waiting pair on -@@ -520,6 +593,52 @@ typedef struct pj_ice_sess_cb +@@ -520,6 +593,41 @@ typedef struct pj_ice_sess_cb void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len); @@ -164,17 +165,6 @@ index 8971220f0..39c197c29 100644 + unsigned check_id); + + /** -+ * Select incoming TURN dataconn -+ * -+ * @param ice The ICE session. -+ * @param clist The ICE connection list -+ * @param check_id The wanted check. -+ */ -+ pj_status_t (*select_turn_dataconn)(pj_ice_sess *ice, -+ pj_ice_sess_checklist *clist, -+ unsigned check_id); -+ -+ /** + * Reconnect a resetted TCP connection and send connectivity check + * cf. PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY + * @@ -198,17 +188,17 @@ index 8971220f0..39c197c29 100644 + unsigned check_id); + } pj_ice_sess_cb; - - -@@ -636,6 +755,7 @@ struct pj_ice_sess + + +@@ -636,6 +744,7 @@ struct pj_ice_sess pj_bool_t valid_pair_found; /**< First pair found */ pj_status_t ice_status; /**< Error status. */ pj_timer_entry timer; /**< ICE timer. */ + pj_timer_entry timer_connect; /**< ICE timer tcp timeout*/ pj_ice_sess_cb cb; /**< Callback. */ - + pj_stun_config stun_cfg; /**< STUN settings. */ -@@ -855,6 +975,7 @@ PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, +@@ -855,6 +964,7 @@ PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, * @param rel_addr Optional related address. * @param addr_len Length of addresses. * @param p_cand_id Optional pointer to receive the candidate ID. @@ -216,20 +206,20 @@ index 8971220f0..39c197c29 100644 * * @return PJ_SUCCESS if candidate is successfully added. */ -@@ -868,7 +989,8 @@ PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, +@@ -868,7 +978,8 @@ PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, const pj_sockaddr_t *base_addr, const pj_sockaddr_t *rel_addr, int addr_len, - unsigned *p_cand_id); + unsigned *p_cand_id, + pj_ice_cand_transport transport); - + /** * Find default candidate for the specified component ID, using this -@@ -980,6 +1102,55 @@ PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, +@@ -980,6 +1091,44 @@ PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, const pj_sockaddr_t *src_addr, int src_addr_len); - + +/** + * Notification when ICE session get a new incoming connection + * @@ -268,19 +258,8 @@ index 8971220f0..39c197c29 100644 +PJ_DECL(void) ice_sess_on_peer_packet(pj_ice_sess *ice, + pj_uint8_t transport_id, + pj_sockaddr_t* remote_addr); -+ -+/** -+ * Select dataconn from TURN -+ * -+ * @param ice The ICE session. -+ * @param clist The ice check list -+ * @param check_id The wanted check -+ */ -+PJ_DECL(void) ice_select_incoming_turn(pj_ice_sess *ice, -+ pj_ice_sess_checklist *clist, -+ unsigned check_id); - - + + /** diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h index d0af76679..9eb74b35f 100644 @@ -289,7 +268,7 @@ index d0af76679..9eb74b35f 100644 @@ -274,6 +274,13 @@ typedef struct pj_ice_strans_stun_cfg */ pj_bool_t ignore_stun_error; - + + /** + * Type of connection to the STUN server. + * @@ -298,12 +277,12 @@ index d0af76679..9eb74b35f 100644 + pj_stun_tp_type conn_type; + } pj_ice_strans_stun_cfg; - - + + @@ -289,6 +296,13 @@ typedef struct pj_ice_strans_turn_cfg */ int af; - + + /** + * If we want to use UDP or TCP as described by RFC 6544. + * This will discover candidates via TCP sockets. Then it will @@ -317,7 +296,7 @@ index d0af76679..9eb74b35f 100644 @@ -368,6 +382,13 @@ typedef struct pj_ice_strans_cfg */ int af; - + + /** + * If we want to use UDP or TCP as described by RFC 6544. + * This will discover candidates via TCP sockets. Then it will @@ -335,7 +314,7 @@ index bee630ab4..3f2ecf739 100644 @@ -174,6 +174,29 @@ typedef struct pj_stun_rx_data pj_stun_rx_data; /** Forward declaration for pj_stun_session */ typedef struct pj_stun_session pj_stun_session; - + +/** + * STUN transport types, which will be used both to specify the connection + * type for reaching STUN server and the type of allocation transport to be @@ -359,13 +338,13 @@ index bee630ab4..3f2ecf739 100644 + PJ_STUN_TP_TLS = 255 + +} pj_stun_tp_type; - + /** * This is the callback to be registered to pj_stun_session, to send @@ -307,6 +330,38 @@ typedef struct pj_stun_session_cb const pj_sockaddr_t *src_addr, unsigned src_addr_len); - + + /** + * Notification when STUN session get a ConnectionAttempt indication. + * @@ -399,8 +378,8 @@ index bee630ab4..3f2ecf739 100644 + pj_sockaddr_t* remote_addr); + } pj_stun_session_cb; - - + + @@ -390,6 +445,7 @@ typedef enum pj_stun_sess_msg_log_flag * @param grp_lock Optional group lock to be used by this session. * If NULL, the session will create one itself. @@ -416,13 +395,13 @@ index bee630ab4..3f2ecf739 100644 - pj_stun_session **p_sess); + pj_stun_session **p_sess, + pj_stun_tp_type conn_type); - + /** * Destroy the STUN session and all objects created in the context of @@ -752,6 +809,22 @@ PJ_DECL(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess, pj_stun_tx_data *tdata); - + +/** + * + * @param sess The STUN session. @@ -439,7 +418,7 @@ index bee630ab4..3f2ecf739 100644 + */ +PJ_DECL(pj_stun_tp_type) pj_stun_session_tp_type(pj_stun_session *sess); + - + /** * @} diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h @@ -460,7 +439,7 @@ index fff4df885..bfc9c1415 100644 +#include <pj/pool.h> #include <pj/sock.h> #include <pj/sock_qos.h> - + @@ -87,7 +91,17 @@ typedef enum pj_stun_sock_op /** * IP address change notification from the keep-alive operation. @@ -477,13 +456,13 @@ index fff4df885..bfc9c1415 100644 + * TCP fails to connect + */ + PJ_STUN_TCP_CONNECT_ERROR - - + + } pj_stun_sock_op; @@ -197,6 +211,11 @@ typedef struct pj_stun_sock_info */ pj_sockaddr mapped_addr; - + + /** + * If connected, the remote address will be stored here. + */ @@ -495,19 +474,19 @@ index fff4df885..bfc9c1415 100644 @@ -208,6 +227,11 @@ typedef struct pj_stun_sock_info */ pj_sockaddr aliases[PJ_ICE_ST_MAX_CAND]; - + + /** + * The tranport type of the socket + */ + pj_stun_tp_type conn_type; + } pj_stun_sock_info; - - + + @@ -343,6 +367,9 @@ PJ_DECL(void) pj_stun_sock_cfg_default(pj_stun_sock_cfg *cfg); * the operation of this transport. * @param af Address family of socket. Currently pj_AF_INET() - * and pj_AF_INET6() are supported. + * and pj_AF_INET6() are supported. + * @param conn_type Connection type to the STUN server. Both TCP and UDP are + * supported. + * @@ -525,7 +504,7 @@ index fff4df885..bfc9c1415 100644 @@ -485,6 +513,43 @@ PJ_DECL(pj_status_t) pj_stun_sock_sendto(pj_stun_sock *stun_sock, const pj_sockaddr_t *dst_addr, unsigned addr_len); - + + +#if PJ_HAS_TCP +/** @@ -573,7 +552,7 @@ index e4d306174..35388809f 100644 @@ -623,6 +623,17 @@ PJ_DECL(pj_status_t) pj_turn_sock_bind_channel(pj_turn_sock *turn_sock, const pj_sockaddr_t *peer, unsigned addr_len); - + +/** + * Check if peer is a dataconn + * @@ -585,7 +564,7 @@ index e4d306174..35388809f 100644 +PJ_DECL(pj_bool_t) pj_turn_sock_has_dataconn(pj_turn_sock *turn_sock, + const pj_sockaddr_t *peer); + - + /** * @} diff --git a/pjnath/src/pjnath-test/concur_test.c b/pjnath/src/pjnath-test/concur_test.c @@ -630,7 +609,7 @@ index 055eaad61..1d07bf299 100644 return -200; @@ -575,8 +577,12 @@ static int run_client_test(const char *title, } - + /* Send the request */ - status = pj_stun_session_send_msg(client->sess, NULL, PJ_FALSE, PJ_TRUE, &server->addr, - pj_sockaddr_get_len(&server->addr), tdata); @@ -651,7 +630,7 @@ index fff4fad26..e7f8b84eb 100644 pj_bzero(&cb, sizeof(cb)); cb.on_status = &stun_sock_on_status; cb.on_rx_data = &stun_sock_on_rx_data; -- status = pj_stun_sock_create(cfg, NULL, GET_AF(use_ipv6), &cb, &sock_cfg, +- status = pj_stun_sock_create(cfg, NULL, GET_AF(use_ipv6), &cb, &sock_cfg, - client, &client->sock); + status = pj_stun_sock_create(cfg, NULL, GET_AF(use_ipv6), + PJ_STUN_TP_UDP, @@ -663,17 +642,17 @@ index fff4fad26..e7f8b84eb 100644 PJ_LOG(3,(THIS_FILE, " sending to %s", pj_sockaddr_print(&info.srv_addr, txt, sizeof(txt), 3))); } status = pj_stun_sock_sendto(client->sock, NULL, &ret, sizeof(ret), -- 0, &info.srv_addr, +- 0, &info.srv_addr, + 0, &info.srv_addr, pj_sockaddr_get_len(&info.srv_addr)); if (status != PJ_SUCCESS && status != PJ_EPENDING) { app_perror(" error: server sending data", status); diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c -index 2a4125bc5..85d3234c9 100644 +index 2a4125bc5..c3a06fbc4 100644 --- a/pjnath/src/pjnath/ice_session.c +++ b/pjnath/src/pjnath/ice_session.c @@ -18,6 +18,7 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <pjnath/ice_session.h> +#include <pjnath/stun_session.h> @@ -681,7 +660,7 @@ index 2a4125bc5..85d3234c9 100644 #include <pj/array.h> #include <pj/assert.h> @@ -44,7 +45,10 @@ static const char *cand_type_names[] = - static const char *check_state_name[] = + static const char *check_state_name[] = { "Frozen", + "Needs Retry", @@ -698,9 +677,9 @@ index 2a4125bc5..85d3234c9 100644 - TIMER_KEEP_ALIVE /**< ICE keep-alive timer. */ + TIMER_KEEP_ALIVE, /**< ICE keep-alive timer. */ + TIMER_CONNECTION_TIMEOUT - + }; - + @@ -123,6 +128,8 @@ typedef struct timer_data { pj_ice_sess *ice; @@ -708,10 +687,10 @@ index 2a4125bc5..85d3234c9 100644 + /* TODO (remove), for now, needed for the NEEDS_FIRST_PACKET state */ + unsigned first_packet_counter; } timer_data; - - + + @@ -133,6 +140,7 @@ typedef struct timer_data - + /* Forward declarations */ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te); +static void on_tcp_connect_timeout(pj_ice_sess *ice); @@ -719,7 +698,7 @@ index 2a4125bc5..85d3234c9 100644 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); static void ice_on_destroy(void *obj); @@ -291,7 +299,8 @@ static pj_status_t init_comp(pj_ice_sess *ice, - status = pj_stun_session_create(&ice->stun_cfg, NULL, + status = pj_stun_session_create(&ice->stun_cfg, NULL, &sess_cb, PJ_TRUE, ice->grp_lock, - &comp->stun_sess); @@ -727,8 +706,16 @@ index 2a4125bc5..85d3234c9 100644 + PJ_STUN_TP_UDP); if (status != PJ_SUCCESS) return status; - -@@ -717,7 +726,8 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, + +@@ -359,6 +368,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg, + pj_ice_sess_options_default(&ice->opt); + + pj_timer_entry_init(&ice->timer, TIMER_NONE, (void*)ice, &on_timer); ++ pj_timer_entry_init(&ice->timer_connect, TIMER_NONE, (void*)ice, &on_timer); + + pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), + name, ice); +@@ -717,7 +727,8 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, const pj_sockaddr_t *base_addr, const pj_sockaddr_t *rel_addr, int addr_len, @@ -738,7 +725,7 @@ index 2a4125bc5..85d3234c9 100644 { pj_ice_sess_cand *lcand; pj_status_t status = PJ_SUCCESS; -@@ -740,6 +750,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, +@@ -740,6 +751,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, lcand->comp_id = (pj_uint8_t)comp_id; lcand->transport_id = (pj_uint8_t)transport_id; lcand->type = type; @@ -746,7 +733,17 @@ index 2a4125bc5..85d3234c9 100644 pj_strdup(ice->pool, &lcand->foundation, foundation); lcand->prio = CALC_CAND_PRIO(ice, type, local_pref, lcand->comp_id); pj_sockaddr_cp(&lcand->addr, addr); -@@ -1081,6 +1092,17 @@ static pj_status_t prune_checklist(pj_ice_sess *ice, +@@ -961,7 +973,8 @@ static void check_set_state(pj_ice_sess *ice, pj_ice_sess_check *check, + pj_ice_sess_check_state st, + pj_status_t err_code) + { +- pj_assert(check->state < PJ_ICE_SESS_CHECK_STATE_SUCCEEDED); ++ if (check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED) ++ return; + + LOG5((ice->obj_name, "Check %s: state changed from %s to %s", + dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), &ice->clist, check), +@@ -1081,6 +1094,17 @@ static pj_status_t prune_checklist(pj_ice_sess *ice, return PJNATH_EICENOHOSTCAND; } } @@ -762,9 +759,9 @@ index 2a4125bc5..85d3234c9 100644 + --i; + } } - + /* Next remove a pair if its local and remote candidates are identical -@@ -1183,6 +1205,9 @@ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) +@@ -1183,6 +1207,9 @@ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) case TIMER_KEEP_ALIVE: ice_keep_alive(ice, PJ_TRUE); break; @@ -774,13 +771,13 @@ index 2a4125bc5..85d3234c9 100644 case TIMER_NONE: /* Nothing to do, just to get rid of gcc warning */ break; -@@ -1619,6 +1644,43 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice, +@@ -1619,6 +1646,43 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice, return PJ_FALSE; } - + +static void on_tcp_connect_timeout(pj_ice_sess* ice) +{ -+ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap,&ice->timer, ++ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap,&ice->timer_connect, + TIMER_NONE); + + pj_bool_t first_found = PJ_FALSE, set_timer = PJ_FALSE; @@ -802,7 +799,7 @@ index 2a4125bc5..85d3234c9 100644 + } + } + -+ if (set_timer && ice->timer.id == TIMER_NONE) { ++ if (set_timer && ice->timer_connect.id == TIMER_NONE) { + /* Reschedule */ + pj_time_val delay = { + .sec = 0, @@ -810,18 +807,18 @@ index 2a4125bc5..85d3234c9 100644 + }; + pj_time_val_normalize(&delay); + pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, -+ &ice->timer, &delay, ++ &ice->timer_connect, &delay, + TIMER_CONNECTION_TIMEOUT, + ice->grp_lock); + } +} - + /* Create checklist by pairing local candidates with remote candidates */ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( -@@ -1705,6 +1767,30 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( +@@ -1705,6 +1769,30 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( continue; } - + + /* Section 6.2, RFC 6544 (https://tools.ietf.org/html/rfc6544) + * As with UDP, check lists are formed only by full ICE implementations. + * When forming candidate pairs, the following types of TCP candidates @@ -846,21 +843,21 @@ index 2a4125bc5..85d3234c9 100644 + continue; + } + - + chk->lcand = lcand; chk->rcand = rcand; -@@ -1749,6 +1835,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( +@@ -1749,6 +1837,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( td = PJ_POOL_ZALLOC_T(ice->pool, timer_data); td->ice = ice; td->clist = clist; + td->first_packet_counter = 1; clist->timer.user_data = (void*)td; clist->timer.cb = &periodic_timer; - -@@ -1761,6 +1848,36 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( + +@@ -1761,6 +1850,36 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list( return PJ_SUCCESS; } - + +static pj_status_t send_connectivity_check(pj_ice_sess *ice, + pj_ice_sess_checklist *clist, + unsigned check_id, @@ -892,47 +889,43 @@ index 2a4125bc5..85d3234c9 100644 +} + /* Perform check on the specified candidate pair. */ - static pj_status_t perform_check(pj_ice_sess *ice, + static pj_status_t perform_check(pj_ice_sess *ice, pj_ice_sess_checklist *clist, -@@ -1771,19 +1888,17 @@ static pj_status_t perform_check(pj_ice_sess *ice, +@@ -1771,19 +1890,17 @@ static pj_status_t perform_check(pj_ice_sess *ice, pj_ice_msg_data *msg_data; pj_ice_sess_check *check; const pj_ice_sess_cand *lcand; - const pj_ice_sess_cand *rcand; pj_uint32_t prio; pj_status_t status; - + check = &clist->checks[check_id]; lcand = check->lcand; - rcand = check->rcand; comp = find_comp(ice, lcand->comp_id); - + + pj_log_push_indent(); - LOG5((ice->obj_name, - "Sending connectivity check for check %s", + LOG5((ice->obj_name, + "Sending connectivity check for check %s", dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), clist, check))); - pj_log_push_indent(); - + /* Create request */ - status = pj_stun_session_create_req(comp->stun_sess, -@@ -1831,32 +1946,92 @@ static pj_status_t perform_check(pj_ice_sess *ice, + status = pj_stun_session_create_req(comp->stun_sess, +@@ -1831,32 +1948,71 @@ static pj_status_t perform_check(pj_ice_sess *ice, &ice->tie_breaker); - + } else { + if (nominate) { + check->nominated = PJ_TRUE; + } - pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg, + pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg, PJ_STUN_ATTR_ICE_CONTROLLED, &ice->tie_breaker); } - + +#if PJ_HAS_TCP + switch (lcand->transport) { -+ case PJ_CAND_UDP: -+ status = send_connectivity_check(ice, clist, check_id, -+ nominate, msg_data); -+ break; + case PJ_CAND_TCP_ACTIVE: + switch (check->state) { + case PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY: @@ -944,9 +937,9 @@ index 2a4125bc5..85d3234c9 100644 + break; + default: + pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, -+ &ice->timer, TIMER_NONE); ++ &ice->timer_connect, TIMER_NONE); + status = (*ice->cb.wait_tcp_connection)(ice, clist, check_id); -+ if (ice->timer.id != TIMER_NONE) { ++ if (ice->timer_connect.id != TIMER_NONE) { + pj_assert(!"Not expected any timer active"); + } else { + pj_time_val delay = { @@ -955,7 +948,7 @@ index 2a4125bc5..85d3234c9 100644 + }; + pj_time_val_normalize(&delay); + pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, -+ &ice->timer, &delay, ++ &ice->timer_connect, &delay, + TIMER_CONNECTION_TIMEOUT, + ice->grp_lock); + } @@ -964,39 +957,22 @@ index 2a4125bc5..85d3234c9 100644 + break; + case PJ_CAND_TCP_PASSIVE: + case PJ_CAND_TCP_SO: ++ case PJ_CAND_UDP: + default: -+ if (lcand->type == PJ_ICE_CAND_TYPE_RELAYED) { -+ status = (*ice->cb.select_turn_dataconn)(ice, clist, check_id); -+ if (ice->timer.id == TIMER_NONE) { -+ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, -+ &ice->timer, TIMER_NONE); -+ pj_time_val delay = { -+ .sec = 0, -+ .msec = 1500 -+ }; -+ pj_time_val_normalize(&delay); -+ pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, -+ &ice->timer, &delay, -+ TIMER_CONNECTION_TIMEOUT, -+ ice->grp_lock); -+ } -+ } else { -+ status = send_connectivity_check(ice, clist, check_id, -+ nominate, msg_data); -+ } ++ status = send_connectivity_check(ice, clist, check_id, nominate, msg_data); + break; + } +#else + status = send_connectivity_check(ice, clist, check_id, nominate, msg_data); +#endif - -- /* Note that USERNAME and MESSAGE-INTEGRITY will be added by the + +- /* Note that USERNAME and MESSAGE-INTEGRITY will be added by the - * STUN session. - */ - - /* Initiate STUN transaction to send the request */ -- status = pj_stun_session_send_msg(comp->stun_sess, msg_data, PJ_FALSE, -- PJ_TRUE, &rcand->addr, +- status = pj_stun_session_send_msg(comp->stun_sess, msg_data, PJ_FALSE, +- PJ_TRUE, &rcand->addr, - pj_sockaddr_get_len(&rcand->addr), - check->tdata); - if (status != PJ_SUCCESS) { @@ -1016,24 +992,24 @@ index 2a4125bc5..85d3234c9 100644 - return status; } - -- check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS, +- check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS, - PJ_SUCCESS); pj_log_pop_indent(); - return PJ_SUCCESS; + return status; } - - -@@ -1893,39 +2068,95 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th, + + +@@ -1893,39 +2049,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 - * 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) { @@ -1056,7 +1032,7 @@ index 2a4125bc5..85d3234c9 100644 } + } + } - + - ++start_count; - break; + if (start_count == 0) { @@ -1103,7 +1079,7 @@ index 2a4125bc5..85d3234c9 100644 + } } } - + /* If we don't have anything in Waiting state, perform check to * highest priority pair that is in Frozen state. */ @@ -1112,7 +1088,7 @@ index 2a4125bc5..85d3234c9 100644 + if (start_count == 0) { + for (i = 0; i < clist->count; ++i) { pj_ice_sess_check *check = &clist->checks[i]; - + if (check->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) { status = perform_check(ice, clist, i, ice->is_nominating); - if (status != PJ_SUCCESS) { @@ -1127,7 +1103,7 @@ index 2a4125bc5..85d3234c9 100644 + } + } + } - + + if (start_count == 0) { + // If all sockets are pending, do nothing + for (i = 0; i < clist->count; ++i) { @@ -1136,27 +1112,27 @@ index 2a4125bc5..85d3234c9 100644 ++start_count; break; } -@@ -1933,14 +2164,14 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th, +@@ -1933,14 +2145,14 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th, } - + /* Cannot start check because there's no suitable candidate pair. - */ + */ if (start_count!=0) { /* Schedule for next timer */ pj_time_val timeout = {0, PJ_ICE_TA_VAL}; - + pj_time_val_normalize(&timeout); pj_timer_heap_schedule_w_grp_lock(th, te, &timeout, PJ_TRUE, - ice->grp_lock); + ice->grp_lock); } - + pj_grp_lock_release(ice->grp_lock); -@@ -2181,6 +2412,192 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess, +@@ -2181,6 +2393,179 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess, return status; } - + +static pj_ice_sess_check* get_current_check_at_state(pj_ice_sess *ice, + pj_sockaddr_t *remote_addr, + pj_ice_sess_check_state state, @@ -1326,28 +1302,15 @@ index 2a4125bc5..85d3234c9 100644 + + const pj_ice_sess_cand *rcand = check->rcand; + if (rcand->type == PJ_ICE_CAND_TYPE_RELAYED) { -+ check->state = PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS; + check_set_state(ice, check, + PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS, PJ_SUCCESS); + } +} -+ -+ -+void ice_select_incoming_turn(pj_ice_sess *ice, -+ pj_ice_sess_checklist *clist, -+ unsigned check_id) -+{ -+ check_set_state(ice, &clist->checks[check_id], -+ PJ_ICE_SESS_CHECK_STATE_SUCCEEDED, PJ_SUCCESS); -+ update_comp_check(ice, clist->checks[check_id].lcand->comp_id, -+ &clist->checks[check_id]); -+ on_check_complete(ice, &clist->checks[check_id]); -+} - + /* This callback is called when outgoing STUN request completed */ static void on_stun_request_complete(pj_stun_session *stun_sess, -@@ -2411,7 +2828,9 @@ static void on_stun_request_complete(pj_stun_session *stun_sess, - &check->lcand->base_addr, +@@ -2411,7 +2796,9 @@ static void on_stun_request_complete(pj_stun_session *stun_sess, + &check->lcand->base_addr, &check->lcand->base_addr, pj_sockaddr_get_len(&xaddr->sockaddr), - &cand_id); @@ -1355,27 +1318,40 @@ index 2a4125bc5..85d3234c9 100644 + check->rcand->transport == PJ_CAND_UDP ? + PJ_CAND_UDP : PJ_CAND_TCP_PASSIVE); if (status != PJ_SUCCESS) { - check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, + check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status); -@@ -2673,7 +3092,9 @@ static pj_status_t on_stun_rx_request(pj_stun_session *sess, +@@ -2474,11 +2861,7 @@ static void on_stun_request_complete(pj_stun_session *stun_sess, + /* Perform 7.1.2.2.2. Updating Pair States. + * This may terminate ICE processing. + */ +- if (on_check_complete(ice, check)) { +- /* ICE complete! */ +- pj_grp_lock_release(ice->grp_lock); +- return; +- } ++ on_check_complete(ice, check); + + pj_grp_lock_release(ice->grp_lock); + } +@@ -2673,7 +3056,9 @@ static pj_status_t on_stun_rx_request(pj_stun_session *sess, msg_data->has_req_data = PJ_FALSE; - + /* Send the response */ - status = pj_stun_session_send_msg(sess, msg_data, PJ_TRUE, PJ_TRUE, + status = pj_stun_session_send_msg(sess, msg_data, PJ_TRUE, + pj_stun_session_tp_type(sess) == + PJ_STUN_TP_UDP, src_addr, src_addr_len, tdata); - - -@@ -2794,12 +3215,12 @@ static void handle_incoming_check(pj_ice_sess *ice, + + +@@ -2794,12 +3179,12 @@ static void handle_incoming_check(pj_ice_sess *ice, /* Just get candidate with the highest priority and same transport ID * for the specified component ID in the checklist. */ - for (i=0; i<ice->clist.count; ++i) { - pj_ice_sess_check *c = &ice->clist.checks[i]; - if (c->lcand->comp_id == rcheck->comp_id && -- c->lcand->transport_id == rcheck->transport_id) +- c->lcand->transport_id == rcheck->transport_id) + for (i=0; i<ice->lcand_cnt; ++i) { + pj_ice_sess_cand* lcand_tmp = &ice->lcand[i]; + if (lcand_tmp->comp_id == rcheck->comp_id && @@ -1387,21 +1363,21 @@ index 2a4125bc5..85d3234c9 100644 } } diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c -index 3cb350c2a..bf7f98096 100644 +index 3cb350c2a..d29c1f0db 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -69,6 +69,7 @@ enum tp_type # define RELAY_PREF 0 #endif - + +#define MAX_RTP_SIZE 65536 - + /* The candidate type preference when STUN candidate is used */ static pj_uint8_t srflx_pref_table[PJ_ICE_CAND_TYPE_MAX] = @@ -87,6 +88,14 @@ static pj_uint8_t srflx_pref_table[PJ_ICE_CAND_TYPE_MAX] = #endif }; - + +////////////////////////////////////////////////////////////////////////////// + +static pj_uint16_t GETVAL16H(const pj_uint8_t *buf1, const pj_uint8_t *buf2) @@ -1410,22 +1386,18 @@ index 3cb350c2a..bf7f98096 100644 +} + +////////////////////////////////////////////////////////////////////////////// - + /* ICE callbacks */ static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); -@@ -103,6 +112,24 @@ static void ice_rx_data(pj_ice_sess *ice, +@@ -103,6 +112,20 @@ static void ice_rx_data(pj_ice_sess *ice, const pj_sockaddr_t *src_addr, unsigned src_addr_len); - + +#if PJ_HAS_TCP +static pj_status_t ice_wait_tcp_connection(pj_ice_sess *ice, + pj_ice_sess_checklist *clist, + unsigned check_id); + -+static pj_status_t ice_select_turn_dataconn(pj_ice_sess *ice, -+ pj_ice_sess_checklist *clist, -+ unsigned check_id); -+ +static pj_status_t ice_reconnect_tcp_connection(pj_ice_sess *ice, + pj_ice_sess_checklist *clist, + unsigned check_id); @@ -1435,13 +1407,13 @@ index 3cb350c2a..bf7f98096 100644 + unsigned check_id); +#endif + - + /* STUN socket callbacks */ /* Notification when incoming packet has been received. */ -@@ -182,6 +209,16 @@ typedef struct pj_ice_strans_comp +@@ -182,6 +205,16 @@ typedef struct pj_ice_strans_comp } pj_ice_strans_comp; - - + + +static pj_bool_t add_local_candidate(pj_ice_sess_cand *cand, + unsigned idx, + unsigned i, @@ -1455,7 +1427,7 @@ index 3cb350c2a..bf7f98096 100644 /* Pending send buffer */ typedef struct pending_send { -@@ -225,6 +262,13 @@ struct pj_ice_strans +@@ -225,6 +258,13 @@ struct pj_ice_strans pj_bool_t destroy_req;/**< Destroy has been called? */ pj_bool_t cb_called; /**< Init error callback called?*/ pj_bool_t call_send_cb;/**< Need to call send cb? */ @@ -1467,25 +1439,25 @@ index 3cb350c2a..bf7f98096 100644 + + pj_ssize_t last_data_len; /**< What the application is waiting. */ }; - - -@@ -261,6 +305,7 @@ PJ_DEF(void) pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg) + + +@@ -261,6 +301,7 @@ PJ_DEF(void) pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg) pj_bzero(cfg, sizeof(*cfg)); - + cfg->af = pj_AF_INET(); + cfg->protocol = PJ_ICE_TP_UDP; pj_stun_config_init(&cfg->stun_cfg, NULL, 0, NULL, NULL); pj_ice_strans_stun_cfg_default(&cfg->stun); pj_ice_strans_turn_cfg_default(&cfg->turn); -@@ -278,6 +323,7 @@ PJ_DEF(void) pj_ice_strans_stun_cfg_default(pj_ice_strans_stun_cfg *cfg) +@@ -278,6 +319,7 @@ PJ_DEF(void) pj_ice_strans_stun_cfg_default(pj_ice_strans_stun_cfg *cfg) pj_bzero(cfg, sizeof(*cfg)); - + cfg->af = pj_AF_INET(); + cfg->conn_type = PJ_STUN_TP_UDP; cfg->port = PJ_STUN_PORT; cfg->max_host_cands = 64; cfg->ignore_stun_error = PJ_FALSE; -@@ -421,6 +467,9 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, +@@ -421,6 +463,9 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, cand->transport_id = tp_id; cand->comp_id = (pj_uint8_t) comp->comp_id; new_cand = PJ_TRUE; @@ -1493,12 +1465,12 @@ index 3cb350c2a..bf7f98096 100644 + PJ_CAND_UDP : + PJ_CAND_TCP_PASSIVE; } - + /* Allocate and initialize TURN socket data */ -@@ -428,6 +477,10 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, +@@ -428,6 +473,10 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, data->comp = comp; data->transport_id = cand->transport_id; - + + if (turn_cfg->conn_type == PJ_TURN_TP_TCP) { + turn_cfg->alloc_param.peer_conn_type = PJ_TURN_TP_TCP; + } @@ -1506,20 +1478,20 @@ index 3cb350c2a..bf7f98096 100644 /* Create the TURN transport */ status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, turn_cfg->af, turn_cfg->conn_type, -@@ -465,7 +518,7 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, +@@ -465,7 +514,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, +static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, pj_ice_sess_cand *rcand) { if (lcand == NULL && rcand == NULL){ -@@ -474,23 +527,23 @@ static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand, +@@ -474,23 +523,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 @@ -1533,27 +1505,27 @@ index 3cb350c2a..bf7f98096 100644 { return PJ_FALSE; } -- +- + return PJ_TRUE; } - + - static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, pj_ice_strans_comp *comp, unsigned idx, -@@ -541,6 +594,9 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, +@@ -541,6 +590,9 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, cand->local_pref = SRFLX_PREF; cand->transport_id = CREATE_TP_ID(TP_STUN, idx); cand->comp_id = (pj_uint8_t) comp->comp_id; + cand->transport = stun_cfg->conn_type == PJ_STUN_TP_UDP ? + PJ_CAND_UDP : + PJ_CAND_TCP_PASSIVE; - + /* Allocate and initialize STUN socket data */ data = PJ_POOL_ZALLOC_T(ice_st->pool, sock_user_data); -@@ -549,8 +605,9 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, - +@@ -549,8 +601,9 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, + /* Create the STUN transport */ status = pj_stun_sock_create(&ice_st->cfg.stun_cfg, NULL, - stun_cfg->af, &stun_sock_cb, @@ -1563,10 +1535,10 @@ index 3cb350c2a..bf7f98096 100644 + &comp->stun[idx].sock); if (status != PJ_SUCCESS) return status; - -@@ -635,105 +692,154 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, + +@@ -635,105 +688,154 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st, } - + for (i = 0; i < stun_sock_info.alias_cnt && - cand_cnt < stun_cfg->max_host_cands; ++i) + cand_cnt < stun_cfg->max_host_cands && @@ -1603,17 +1575,17 @@ index 3cb350c2a..bf7f98096 100644 + } + } + } - + - 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() && +- if (stun_cfg->af == pj_AF_INET() && - (pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) - { - continue; @@ -1643,7 +1615,7 @@ index 3cb350c2a..bf7f98096 100644 + 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). - */ @@ -1652,7 +1624,7 @@ index 3cb350c2a..bf7f98096 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; @@ -1663,7 +1635,7 @@ index 3cb350c2a..bf7f98096 100644 - pj_sockaddr_cp(&cand->addr, addr); - pj_sockaddr_cp(&cand->base_addr, addr); - pj_bzero(&cand->rel_addr, sizeof(cand->rel_addr)); -- +- - /* Check if not already in list */ - for (j=0; j<comp->cand_cnt; j++) { - if (ice_cand_equals(cand, &comp->cand_list[j])) { @@ -1675,7 +1647,7 @@ index 3cb350c2a..bf7f98096 100644 + 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", @@ -1698,7 +1670,7 @@ index 3cb350c2a..bf7f98096 100644 + } + } + } - + - pj_bzero(&cand->addr, sizeof(cand->addr)); - pj_bzero(&cand->base_addr, sizeof(cand->base_addr)); - continue; @@ -1707,7 +1679,7 @@ index 3cb350c2a..bf7f98096 100644 - cand_cnt++; - max_cand_cnt--; - } -- +- - pj_ice_calc_foundation(ice_st->pool, &cand->foundation, - cand->type, &cand->base_addr); + /* Ignore IPv6 link-local address, unless it is the default @@ -1718,7 +1690,7 @@ index 3cb350c2a..bf7f98096 100644 + if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80) + return PJ_SUCCESS; + } - + - /* Set default candidate with the preferred default - * address family - */ @@ -1730,10 +1702,10 @@ index 3cb350c2a..bf7f98096 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, +- comp->comp_id, comp->cand_cnt-1, - pj_sockaddr_print(&cand->addr, addrinfo, - sizeof(addrinfo), 3), - cand->transport_id)); @@ -1756,7 +1728,7 @@ index 3cb350c2a..bf7f98096 100644 + return !PJ_SUCCESS; + } } - + - return status; -} + if (cand_duplicate) { @@ -1778,7 +1750,7 @@ index 3cb350c2a..bf7f98096 100644 + + pj_ice_calc_foundation(ice_st->pool, &cand->foundation, + cand->type, &cand->base_addr); -+ + + /* Set default candidate with the preferred default + * address family + */ @@ -1789,7 +1761,7 @@ index 3cb350c2a..bf7f98096 100644 + { + comp->default_cand = (unsigned)(cand - comp->cand_list); + } - ++ + if (transport == PJ_CAND_TCP_ACTIVE) { + // Use the port 9 (DISCARD Protocol) for TCP active candidates. + pj_sockaddr_set_port(&cand->addr, 9); @@ -1803,68 +1775,67 @@ index 3cb350c2a..bf7f98096 100644 + cand->transport_id)); + return PJ_SUCCESS; +} - + /* * Create the component. -@@ -816,7 +922,7 @@ static pj_status_t alloc_send_buf(pj_ice_strans *ice_st, unsigned buf_size) +@@ -816,7 +918,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 +945,7 @@ static pj_status_t alloc_send_buf(pj_ice_strans *ice_st, unsigned buf_size) +@@ -839,7 +941,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 +1012,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_create( const char *name, + +@@ -906,7 +1008,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 && + if (cfg->stun_tp_cnt == 0 && (cfg->stun.server.slen || cfg->stun.max_host_cands)) { ice_st->cfg.stun_tp_cnt = 1; -@@ -1105,7 +1211,7 @@ static void sess_init_update(pj_ice_strans *ice_st) +@@ -1105,7 +1207,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 +1220,7 @@ static void sess_init_update(pj_ice_strans *ice_st) +@@ -1114,7 +1216,7 @@ static void sess_init_update(pj_ice_strans *ice_st) status = PJ_SUCCESS; } } -- +- + if (status != PJ_SUCCESS) break; } -@@ -1207,6 +1313,12 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, +@@ -1207,6 +1309,11 @@ 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; ice_cb.on_tx_pkt = &ice_tx_pkt; +#if PJ_HAS_TCP + ice_cb.wait_tcp_connection = &ice_wait_tcp_connection; -+ ice_cb.select_turn_dataconn = &ice_select_turn_dataconn; + ice_cb.reconnect_tcp_connection = &ice_reconnect_tcp_connection; + ice_cb.close_tcp_connection = &ice_close_tcp_connection; +#endif - + /* Create! */ status = pj_ice_sess_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, role, -@@ -1282,7 +1394,8 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, +@@ -1282,7 +1389,8 @@ PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, &cand->foundation, &cand->addr, &cand->base_addr, &cand->rel_addr, pj_sockaddr_get_len(&cand->addr), @@ -1874,66 +1845,66 @@ index 3cb350c2a..bf7f98096 100644 if (status != PJ_SUCCESS) goto on_error; } -@@ -1544,7 +1657,7 @@ pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st, +@@ -1544,7 +1652,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 +1691,7 @@ static pj_status_t use_buffer( pj_ice_strans *ice_st, +@@ -1578,7 +1686,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 +1706,12 @@ static pj_status_t use_buffer( pj_ice_strans *ice_st, +@@ -1593,12 +1701,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; - -@@ -1651,6 +1764,9 @@ static pj_status_t send_data(pj_ice_strans *ice_st, + +@@ -1651,6 +1759,9 @@ static pj_status_t send_data(pj_ice_strans *ice_st, } } - + + def_cand = &comp->cand_list[comp->default_cand]; + pj_bool_t add_header = def_cand->transport != PJ_CAND_UDP; + /* If ICE is available, send data with ICE, otherwise send with the * default candidate selected during initialization. * -@@ -1659,16 +1775,37 @@ static pj_status_t send_data(pj_ice_strans *ice_st, +@@ -1659,16 +1770,37 @@ 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]; -- +- + /* TCP, add header */ + if (add_header) { + /* @@ -1959,8 +1930,8 @@ index 3cb350c2a..bf7f98096 100644 + if (def_cand->status == PJ_SUCCESS) { unsigned tp_idx = GET_TP_IDX(def_cand->transport_id); - -@@ -1730,6 +1867,11 @@ static pj_status_t send_data(pj_ice_strans *ice_st, + +@@ -1730,6 +1862,11 @@ static pj_status_t send_data(pj_ice_strans *ice_st, status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL, buf, (unsigned)data_len, 0, dest_addr, dest_addr_len); @@ -1971,9 +1942,9 @@ index 3cb350c2a..bf7f98096 100644 + goto on_return; } - -@@ -1738,8 +1880,14 @@ static pj_status_t send_data(pj_ice_strans *ice_st, - + +@@ -1738,8 +1875,14 @@ static pj_status_t send_data(pj_ice_strans *ice_st, + on_return: /* We continue later in on_data_sent() callback. */ - if (status == PJ_EPENDING) @@ -1985,19 +1956,19 @@ index 3cb350c2a..bf7f98096 100644 + } return status; + } - + if (call_cb) { on_data_sent(ice_st, (status == PJ_SUCCESS? data_len: -status)); -@@ -1771,7 +1919,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st, +@@ -1771,7 +1914,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 +1990,22 @@ static void on_ice_complete(pj_ice_sess *ice, pj_status_t status) +@@ -1842,7 +1985,22 @@ static void on_ice_complete(pj_ice_sess *ice, pj_status_t status) sizeof(lip), 3); pj_sockaddr_print(&check->rcand->addr, rip, sizeof(rip), 3); @@ -2021,10 +1992,10 @@ index 3cb350c2a..bf7f98096 100644 if (tp_typ == TP_TURN) { /* Activate channel binding for the remote address * for more efficient data transfer using TURN. -@@ -1936,6 +2099,29 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, +@@ -1936,6 +2094,29 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, pj_sockaddr_get_port(dst_addr), tp_typ)); - + + /* TCP, add header */ + if (comp->ice_st->cfg.stun_tp->conn_type == PJ_STUN_TP_TCP) { + /* @@ -2051,19 +2022,19 @@ index 3cb350c2a..bf7f98096 100644 if (tp_typ == TP_TURN) { if (comp->turn[tp_idx].sock) { status = pj_turn_sock_sendto(comp->turn[tp_idx].sock, -@@ -1958,7 +2144,7 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, +@@ -1958,7 +2139,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 +2155,13 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, +@@ -1969,9 +2150,13 @@ static pj_status_t ice_tx_pkt(pj_ice_sess *ice, dest_addr_len = dst_addr_len; } - + - status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL, - buf, (unsigned)size, 0, - dest_addr, dest_addr_len); @@ -2077,19 +2048,19 @@ index 3cb350c2a..bf7f98096 100644 } else { pj_assert(!"Invalid transport ID"); status = PJ_EINVALIDOP; -@@ -2017,7 +2207,7 @@ static void check_pending_send(pj_ice_strans *ice_st) - +@@ -2017,7 +2202,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 +2221,237 @@ static void check_pending_send(pj_ice_strans *ice_st) +@@ -2031,6 +2216,214 @@ static void check_pending_send(pj_ice_strans *ice_st) } } - + +static void on_peer_connection(pj_stun_session* sess, + pj_status_t status, + pj_sockaddr_t* remote_addr) @@ -2228,29 +2199,6 @@ index 3cb350c2a..bf7f98096 100644 + return PJ_EINVAL; +} + -+static pj_status_t ice_select_turn_dataconn(pj_ice_sess *ice, -+ pj_ice_sess_checklist *clist, -+ unsigned check_id) -+{ -+ pj_ice_sess_check *check = &clist->checks[check_id]; -+ const pj_ice_sess_cand *lcand = check->lcand; -+ const pj_ice_sess_cand *rcand = check->rcand; -+ pj_ice_strans *ice_st = (pj_ice_strans *)ice->user_data; -+ pj_ice_strans_comp *st_comp = ice_st->comp[lcand->comp_id - 1]; -+ -+ for (int i=0; i<ice_st->cfg.turn_tp_cnt; ++i) { -+ pj_turn_session_info info; -+ pj_turn_sock_get_info(st_comp->turn[i].sock, &info); -+ if (st_comp->turn[i].sock -+ && pj_turn_sock_has_dataconn(st_comp->turn[i].sock, &rcand->addr)) { -+ ice_select_incoming_turn(ice, clist, check_id); -+ return PJ_SUCCESS; // Already connected via TURN -+ } -+ } -+ -+ return PJ_EINVAL; -+} -+ +static pj_status_t ice_reconnect_tcp_connection(pj_ice_sess *ice, + pj_ice_sess_checklist *clist, + unsigned check_id) @@ -2324,58 +2272,58 @@ index 3cb350c2a..bf7f98096 100644 /* Notifification when asynchronous send operation via STUN/TURN * has completed. */ -@@ -2039,7 +2460,8 @@ static pj_bool_t on_data_sent(pj_ice_strans *ice_st, pj_ssize_t sent) +@@ -2039,7 +2432,8 @@ static pj_bool_t on_data_sent(pj_ice_strans *ice_st, pj_ssize_t sent) if (ice_st->destroy_req || !ice_st->is_pending) return PJ_TRUE; - + - if (ice_st->call_send_cb && ice_st->cb.on_data_sent) { + if (ice_st->call_send_cb && ice_st->cb.on_data_sent + && sent == ice_st->last_data_len /* Only app data should be announced */) { (*ice_st->cb.on_data_sent)(ice_st, sent); } - -@@ -2196,7 +2618,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, + +@@ -2196,7 +2590,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 +2630,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, - +@@ -2208,7 +2602,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 +2647,7 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, +@@ -2225,7 +2619,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 +2690,11 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, +@@ -2268,11 +2662,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, + (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_ADDR_CHANGE, status); } -@@ -2318,6 +2740,10 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, +@@ -2318,6 +2712,10 @@ static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, } } break; @@ -2384,11 +2332,11 @@ index 3cb350c2a..bf7f98096 100644 + default: + break; } - + return pj_grp_lock_dec_ref(ice_st->grp_lock)? PJ_FALSE : PJ_TRUE; -@@ -2358,14 +2784,103 @@ static void turn_on_rx_data(pj_turn_sock *turn_sock, +@@ -2358,14 +2756,103 @@ static void turn_on_rx_data(pj_turn_sock *turn_sock, } else { - + /* Hand over the packet to ICE */ - status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, - data->transport_id, pkt, pkt_len, @@ -2396,7 +2344,7 @@ index 3cb350c2a..bf7f98096 100644 + 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", @@ -2496,7 +2444,7 @@ index 3cb350c2a..bf7f98096 100644 + status); } } - + diff --git a/pjnath/src/pjnath/nat_detect.c b/pjnath/src/pjnath/nat_detect.c index db0de10bc..808342bec 100644 --- a/pjnath/src/pjnath/nat_detect.c @@ -2510,12 +2458,12 @@ index db0de10bc..808342bec 100644 + PJ_STUN_TP_UDP); if (status != PJ_SUCCESS) goto on_error; - + @@ -875,7 +876,9 @@ static pj_status_t send_test(nat_detect_session *sess, - + /* Send the request */ status = pj_stun_session_send_msg(sess->stun_sess, NULL, PJ_TRUE, -- PJ_TRUE, sess->cur_server, +- PJ_TRUE, sess->cur_server, + (pj_stun_session_tp_type(sess->stun_sess) == + PJ_STUN_TP_UDP), + sess->cur_server, @@ -2527,13 +2475,13 @@ index f2b4f7058..ed17b904f 100644 --- a/pjnath/src/pjnath/stun_session.c +++ b/pjnath/src/pjnath/stun_session.c @@ -49,6 +49,8 @@ struct pj_stun_session - + pj_stun_tx_data pending_request_list; pj_stun_tx_data cached_response_list; + + pj_stun_tp_type conn_type; }; - + #define SNAME(s_) ((s_)->pool->obj_name) @@ -524,7 +526,8 @@ PJ_DEF(pj_status_t) pj_stun_session_create( pj_stun_config *cfg, const pj_stun_session_cb *cb, @@ -2550,13 +2498,13 @@ index f2b4f7058..ed17b904f 100644 sess->use_fingerprint = fingerprint; sess->log_flag = 0xFFFF; + sess->conn_type = conn_type; - + if (grp_lock) { sess->grp_lock = grp_lock; @@ -1538,3 +1542,12 @@ on_return: return status; } - + +PJ_DECL(pj_stun_session_cb *) pj_stun_session_callback(pj_stun_session *sess) +{ + return sess ? &sess->cb : NULL; @@ -2567,13 +2515,13 @@ index f2b4f7058..ed17b904f 100644 + return sess ? sess->conn_type : PJ_STUN_TP_UDP; +} diff --git a/pjnath/src/pjnath/stun_sock.c b/pjnath/src/pjnath/stun_sock.c -index 5fe825cf5..c4cd9b224 100644 +index 5fe825cf5..05461676e 100644 --- a/pjnath/src/pjnath/stun_sock.c +++ b/pjnath/src/pjnath/stun_sock.c @@ -40,6 +40,36 @@ - + enum { MAX_BIND_RETRY = 100 }; - + +#if PJ_HAS_TCP +// The head of a RTP packet is stored in a 16 bits header, so the max size of a +// packet is 65536 @@ -2615,7 +2563,7 @@ index 5fe825cf5..c4cd9b224 100644 + pj_stun_sock_cfg cfg; pj_stun_config stun_cfg; /* STUN config (ioqueue etc)*/ pj_stun_sock_cb cb; /* Application callbacks */ - + @@ -59,6 +91,13 @@ struct pj_stun_sock pj_dns_srv_async_query *q; /* Pending DNS query */ pj_sock_t sock_fd; /* Socket descriptor */ @@ -2633,7 +2581,7 @@ index 5fe825cf5..c4cd9b224 100644 @@ -68,6 +107,15 @@ struct pj_stun_sock pj_grp_lock_t *grp_lock; /* Session group lock */ }; - + +////////////////////////////////////////////////////////////////////////////// + +static pj_uint16_t GETVAL16H(const pj_uint8_t *buf1, const pj_uint8_t *buf2) @@ -2643,13 +2591,13 @@ index 5fe825cf5..c4cd9b224 100644 + +////////////////////////////////////////////////////////////////////////////// + - /* - * Prototypes for static functions + /* + * Prototypes for static functions */ @@ -120,6 +168,24 @@ static void start_ka_timer(pj_stun_sock *stun_sock); /* Keep-alive timer callback */ static void ka_timer_cb(pj_timer_heap_t *th, pj_timer_entry *te); - + + +static pj_bool_t on_stun_sock_ready(pj_activesock_t *asock, + pj_status_t status); @@ -2669,12 +2617,12 @@ index 5fe825cf5..c4cd9b224 100644 + + #define INTERNAL_MSG_TOKEN (void*)(pj_ssize_t)1 - - + + @@ -160,12 +226,183 @@ static pj_bool_t pj_stun_sock_cfg_is_valid(const pj_stun_sock_cfg *cfg) return cfg->max_pkt_size > 1 && cfg->async_cnt >= 1; } - + +/* + * Initialize. + */ @@ -2863,17 +2811,17 @@ index 5fe825cf5..c4cd9b224 100644 - unsigned i; - pj_uint16_t max_bind_retry; pj_status_t status; - + PJ_ASSERT_RETURN(stun_cfg && cb && p_stun_sock, PJ_EINVAL); PJ_ASSERT_RETURN(af==pj_AF_INET()||af==pj_AF_INET6(), PJ_EAFNOTSUP); PJ_ASSERT_RETURN(!cfg || pj_stun_sock_cfg_is_valid(cfg), PJ_EINVAL); PJ_ASSERT_RETURN(cb->on_status, PJ_EINVAL); + PJ_ASSERT_RETURN(conn_type != PJ_STUN_TP_TCP || PJ_HAS_TCP, PJ_EINVAL); - + status = pj_stun_config_check_valid(stun_cfg); if (status != PJ_SUCCESS) return status; - + - if (name == NULL) - name = "stuntp%p"; + if (name == NULL) { @@ -2890,7 +2838,7 @@ index 5fe825cf5..c4cd9b224 100644 + break; + } + } - + if (cfg == NULL) { pj_stun_sock_cfg_default(&default_cfg); @@ -204,9 +451,16 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, @@ -2907,13 +2855,13 @@ index 5fe825cf5..c4cd9b224 100644 pj_memcpy(&stun_sock->cb, cb, sizeof(*cb)); + /* Copy socket settings; QoS parameters etc */ + pj_memcpy(&stun_sock->cfg, cfg, sizeof(*cfg)); - + stun_sock->ka_interval = cfg->ka_interval; if (stun_sock->ka_interval == 0) @@ -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); - + - /* Create socket and bind socket */ - status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd); - if (status != PJ_SUCCESS) @@ -2928,7 +2876,7 @@ index 5fe825cf5..c4cd9b224 100644 + /* 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; @@ -2939,7 +2887,7 @@ index 5fe825cf5..c4cd9b224 100644 - "Failed setting SO_RCVBUF")); - } else { - if (sobuf_size < cfg->so_rcvbuf_size) { -- PJ_LOG(4, (stun_sock->obj_name, +- PJ_LOG(4, (stun_sock->obj_name, - "Warning! Cannot set SO_RCVBUF as configured, " - "now=%d, configured=%d", - sobuf_size, cfg->so_rcvbuf_size)); @@ -2967,7 +2915,7 @@ index 5fe825cf5..c4cd9b224 100644 - "Failed setting SO_SNDBUF")); - } else { - if (sobuf_size < cfg->so_sndbuf_size) { -- PJ_LOG(4, (stun_sock->obj_name, +- PJ_LOG(4, (stun_sock->obj_name, - "Warning! Cannot set SO_SNDBUF as configured, " - "now=%d, configured=%d", - sobuf_size, cfg->so_sndbuf_size)); @@ -2979,13 +2927,13 @@ index 5fe825cf5..c4cd9b224 100644 + return status; } } - + - /* Bind socket */ - max_bind_retry = MAX_BIND_RETRY; - if (cfg->port_range && cfg->port_range < max_bind_retry) - max_bind_retry = cfg->port_range; - pj_sockaddr_init(af, &bound_addr, NULL, 0); -- if (cfg->bound_addr.addr.sa_family == pj_AF_INET() || +- if (cfg->bound_addr.addr.sa_family == pj_AF_INET() || - cfg->bound_addr.addr.sa_family == pj_AF_INET6()) - { - pj_sockaddr_cp(&bound_addr, &cfg->bound_addr); @@ -2995,7 +2943,7 @@ index 5fe825cf5..c4cd9b224 100644 - if (status != PJ_SUCCESS) - goto on_error; + pj_stun_sock_alloc(stun_sock); - + - /* Create more useful information string about this transport */ -#if 0 - { @@ -3005,8 +2953,8 @@ index 5fe825cf5..c4cd9b224 100644 + *p_stun_sock = stun_sock; + return PJ_SUCCESS; +} - -- status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, + +- status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, - &addr_len); - if (status != PJ_SUCCESS) - goto on_error; @@ -3021,9 +2969,9 @@ index 5fe825cf5..c4cd9b224 100644 + 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_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). @@ -3034,7 +2982,7 @@ index 5fe825cf5..c4cd9b224 100644 + return PJ_FALSE; } -#endif - + - /* Init active socket configuration */ - { - pj_activesock_cfg activesock_cfg; @@ -3049,8 +2997,8 @@ index 5fe825cf5..c4cd9b224 100644 - pj_bzero(&activesock_cb, sizeof(activesock_cb)); - activesock_cb.on_data_recvfrom = &on_data_recvfrom; - activesock_cb.on_data_sent = &on_data_sent; -- status = pj_activesock_create(pool, stun_sock->sock_fd, -- pj_SOCK_DGRAM(), +- status = pj_activesock_create(pool, stun_sock->sock_fd, +- pj_SOCK_DGRAM(), - &activesock_cfg, stun_cfg->ioqueue, - &activesock_cb, stun_sock, - &stun_sock->active_sock); @@ -3064,7 +3012,7 @@ index 5fe825cf5..c4cd9b224 100644 - goto on_error; - - /* Init send keys */ -- pj_ioqueue_op_key_init(&stun_sock->send_key, +- pj_ioqueue_op_key_init(&stun_sock->send_key, - sizeof(stun_sock->send_key)); - pj_ioqueue_op_key_init(&stun_sock->int_send_key, - sizeof(stun_sock->int_send_key)); @@ -3073,19 +3021,19 @@ index 5fe825cf5..c4cd9b224 100644 + 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, +- status = pj_stun_session_create(&stun_sock->stun_cfg, - stun_sock->obj_name, -- &sess_cb, PJ_FALSE, +- &sess_cb, PJ_FALSE, - stun_sock->grp_lock, - &stun_sock->stun_sess); - if (status != PJ_SUCCESS) @@ -3097,7 +3045,7 @@ index 5fe825cf5..c4cd9b224 100644 + 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,25 +551,305 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, @@ -3109,12 +3057,12 @@ index 5fe825cf5..c4cd9b224 100644 stun_sock->tsx_id[i] = (pj_uint16_t) pj_rand(); } stun_sock->tsx_id[5] = 0; - + - /* Init timer entry */ stun_sock->ka_timer.cb = &ka_timer_cb; stun_sock->ka_timer.user_data = stun_sock; - + - /* Done */ - *p_stun_sock = stun_sock; - return PJ_SUCCESS; @@ -3123,7 +3071,7 @@ index 5fe825cf5..c4cd9b224 100644 + pj_grp_lock_release(stun_sock->grp_lock); + return status; + } - + -on_error: - pj_stun_sock_destroy(stun_sock); - return status; @@ -3135,7 +3083,7 @@ index 5fe825cf5..c4cd9b224 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, @@ -3416,7 +3364,7 @@ index 5fe825cf5..c4cd9b224 100644 @@ -526,6 +988,26 @@ PJ_DEF(pj_status_t) pj_stun_sock_destroy(pj_stun_sock *stun_sock) stun_sock->sock_fd = PJ_INVALID_SOCKET; } - + + for (int i = 0; i < stun_sock->incoming_nb ; ++i) { + if (stun_sock->incoming_socks[i].sock != NULL) { + stun_sock->incoming_socks[i].fd = PJ_INVALID_SOCKET; @@ -3441,7 +3389,7 @@ index 5fe825cf5..c4cd9b224 100644 pj_stun_session_destroy(stun_sock->stun_sess); } @@ -634,10 +1116,12 @@ static pj_status_t get_mapped_addr(pj_stun_sock *stun_sock) - + /* Send request */ status=pj_stun_session_send_msg(stun_sock->stun_sess, INTERNAL_MSG_TOKEN, - PJ_FALSE, PJ_TRUE, &stun_sock->srv_addr, @@ -3453,12 +3401,12 @@ index 5fe825cf5..c4cd9b224 100644 - if (status != PJ_SUCCESS) + if (status != PJ_SUCCESS && status != PJ_EPENDING) goto on_error; - + return PJ_SUCCESS; @@ -658,6 +1142,8 @@ PJ_DEF(pj_status_t) pj_stun_sock_get_info( pj_stun_sock *stun_sock, - + pj_grp_lock_acquire(stun_sock->grp_lock); - + + info->conn_type = stun_sock->conn_type; + /* Copy STUN server address and mapped address */ @@ -3466,7 +3414,7 @@ index 5fe825cf5..c4cd9b224 100644 sizeof(pj_sockaddr)); @@ -770,13 +1256,241 @@ PJ_DEF(pj_status_t) pj_stun_sock_sendto( pj_stun_sock *stun_sock, send_key = &stun_sock->send_key; - + size = pkt_len; - status = pj_activesock_sendto(stun_sock->active_sock, send_key, - pkt, &size, flag, dst_addr, addr_len); @@ -3615,11 +3563,11 @@ index 5fe825cf5..c4cd9b224 100644 + return status; + } + } - + pj_grp_lock_release(stun_sock->grp_lock); return status; } - + +PJ_DECL(pj_status_t) pj_stun_sock_connect_active(pj_stun_sock *stun_sock, + const pj_sockaddr_t *remote_addr, + int af) @@ -3713,12 +3661,12 @@ index 5fe825cf5..c4cd9b224 100644 pj_stun_sock *stun_sock; pj_ssize_t size; + pj_status_t status; - + stun_sock = (pj_stun_sock *) pj_stun_session_get_user_data(sess); if (!stun_sock || !stun_sock->active_sock) { @@ -800,9 +1515,29 @@ static pj_status_t sess_on_send_msg(pj_stun_session *sess, PJ_UNUSED_ARG(token); - + size = pkt_size; - return pj_activesock_sendto(stun_sock->active_sock, - &stun_sock->int_send_key, @@ -3747,25 +3695,25 @@ index 5fe825cf5..c4cd9b224 100644 +#endif + return status; } - - /* This callback is called by the STUN session when outgoing transaction + + /* This callback is called by the STUN session when outgoing transaction @@ -942,8 +1677,6 @@ static pj_bool_t on_data_recvfrom(pj_activesock_t *asock, pj_status_t status) { pj_stun_sock *stun_sock; - pj_stun_msg_hdr *hdr; - pj_uint16_t type; - + stun_sock = (pj_stun_sock*) pj_activesock_get_user_data(asock); if (!stun_sock) @@ -955,58 +1688,7 @@ static pj_bool_t on_data_recvfrom(pj_activesock_t *asock, return PJ_TRUE; } - + - pj_grp_lock_acquire(stun_sock->grp_lock); - - /* Check that this is STUN message */ -- status = pj_stun_msg_check((const pj_uint8_t*)data, size, +- status = pj_stun_msg_check((const pj_uint8_t*)data, size, - PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET); - if (status != PJ_SUCCESS) { - /* Not STUN -- give it to application */ @@ -3787,7 +3735,7 @@ index 5fe825cf5..c4cd9b224 100644 - */ - if (!PJ_STUN_IS_RESPONSE(type) || - PJ_STUN_GET_METHOD(type) != PJ_STUN_BINDING_METHOD || -- pj_memcmp(hdr->tsx_id, stun_sock->tsx_id, 10) != 0) +- pj_memcmp(hdr->tsx_id, stun_sock->tsx_id, 10) != 0) - { - /* Not STUN Binding response, or STUN transaction ID mismatch. - * This is not our message too -- give it to application. @@ -3816,12 +3764,12 @@ index 5fe825cf5..c4cd9b224 100644 - return status!=PJ_EGONE ? PJ_TRUE : PJ_FALSE; + return parse_rx_packet(asock, data, size, src_addr, addr_len); } - + /* Callback from active socket about send status */ @@ -1047,3 +1729,8 @@ static pj_bool_t on_data_sent(pj_activesock_t *asock, return PJ_TRUE; } - + +pj_stun_session* pj_stun_sock_get_session(pj_stun_sock *stun_sock) +{ + return stun_sock ? stun_sock->stun_sess : NULL; @@ -3861,7 +3809,7 @@ index dc6304d9f..a6e192e9f 100644 +++ b/pjnath/src/pjnath/turn_sock.c @@ -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; - @@ -3871,7 +3819,7 @@ index dc6304d9f..a6e192e9f 100644 - (*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); @@ -3899,9 +3847,9 @@ index 6f9f1ff1a..e56c510c8 100644 --- a/pjnath/src/pjturn-client/client_main.c +++ b/pjnath/src/pjturn-client/client_main.c @@ -155,7 +155,7 @@ static int init() - + name[strlen(name)-1] = '0'+i; - status = pj_stun_sock_create(&g.stun_config, name, pj_AF_INET(), + status = pj_stun_sock_create(&g.stun_config, name, pj_AF_INET(), - &stun_sock_cb, &ss_cfg, + PJ_STUN_TP_UDP, &stun_sock_cb, &ss_cfg, &g.peer[i], &g.peer[i].stun_sock); @@ -3926,7 +3874,7 @@ index 94dda29a3..95ad1793d 100644 --- a/pjnath/src/pjturn-srv/server.c +++ b/pjnath/src/pjturn-srv/server.c @@ -156,7 +156,7 @@ PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, - + status = pj_stun_session_create(&srv->core.stun_cfg, srv->obj_name, &sess_cb, PJ_FALSE, NULL, - &srv->core.stun_sess); @@ -3949,7 +3897,7 @@ index 07ccc31f0..3b93b9417 100644 @@ -341,6 +342,12 @@ static pj_status_t icedemo_init(void) else icedemo.ice_cfg.opt.aggressive = PJ_TRUE; - + + /* Connection type to STUN server */ + if (icedemo.opt.ice_tcp) + icedemo.ice_cfg.stun.conn_type = PJ_STUN_TP_TCP; @@ -3961,7 +3909,7 @@ index 07ccc31f0..3b93b9417 100644 char *pos; @@ -384,7 +391,7 @@ static pj_status_t icedemo_init(void) icedemo.ice_cfg.turn.auth_cred.data.static_cred.data = icedemo.opt.turn_password; - + /* Connection type to TURN server */ - if (icedemo.opt.turn_tcp) + if (icedemo.opt.ice_tcp) @@ -3971,7 +3919,7 @@ index 07ccc31f0..3b93b9417 100644 @@ -395,6 +402,10 @@ static pj_status_t icedemo_init(void) icedemo.ice_cfg.turn.alloc_param.ka_interval = KA_INTERVAL; } - + + if (icedemo.opt.ice_tcp) { + icedemo.ice_cfg.protocol = PJ_ICE_TP_TCP; + } @@ -3982,7 +3930,7 @@ index 07ccc31f0..3b93b9417 100644 @@ -530,10 +541,27 @@ static int print_cand(char buffer[], unsigned maxlen, char *p = buffer; int printed; - + - PRINT("a=candidate:%.*s %u UDP %u %s %u typ ", + /** Section 4.5, RFC 6544 (https://tools.ietf.org/html/rfc6544) + * candidate-attribute = "candidate" ":" foundation SP component-id SP @@ -4006,12 +3954,12 @@ index 07ccc31f0..3b93b9417 100644 (unsigned)cand->comp_id, + cand->transport == PJ_CAND_UDP? "UDP" : "TCP", cand->prio, - pj_sockaddr_print(&cand->addr, ipaddr, + pj_sockaddr_print(&cand->addr, ipaddr, sizeof(ipaddr), 0), @@ -542,6 +570,23 @@ static int print_cand(char buffer[], unsigned maxlen, PRINT("%s\n", pj_ice_get_cand_type_name(cand->type)); - + + if (cand->transport != PJ_CAND_UDP) { + PRINT(" tcptype"); + switch (cand->transport) { @@ -4031,11 +3979,11 @@ index 07ccc31f0..3b93b9417 100644 + if (p == buffer+maxlen) return -PJ_ETOOSMALL; - + @@ -608,6 +653,26 @@ static int encode_session(char buffer[], unsigned maxlen) sizeof(ipaddr), 0)); } - + + if (cand[0].transport != PJ_CAND_UDP) { + /** RFC 6544, Section 4.5: + * If the default candidate is TCP-based, the agent MUST include the @@ -4070,7 +4018,7 @@ index 07ccc31f0..3b93b9417 100644 char comp0_addr[80]; @@ -819,27 +884,43 @@ static void icedemo_input_remote(void) pj_sockaddr_set_port(&icedemo.rem.def_addr[1], (pj_uint16_t)port); - + } else if (strcmp(attr, "candidate")==0) { + /** Section 4.5, RFC 6544 (https://tools.ietf.org/html/rfc6544) + * candidate-attribute = "candidate" ":" foundation SP component-id @@ -4091,7 +4039,7 @@ index 07ccc31f0..3b93b9417 100644 pj_ice_sess_cand *cand; pj_status_t status; + pj_bool_t is_tcp = PJ_FALSE; - + - cnt = sscanf(sdpcand, "%s %d %s %d %s %d typ %s", + cnt = sscanf(sdpcand, "%s %d %s %d %s %d typ %s tcptype %s\n", foundation, @@ -4108,18 +4056,18 @@ index 07ccc31f0..3b93b9417 100644 PJ_LOG(1, (THIS_FILE, "error: Invalid ICE candidate line")); goto on_error; } - + + if (strcmp(transport, "TCP") == 0) { + is_tcp = PJ_TRUE; + } + cand = &icedemo.rem.cand[icedemo.rem.cand_cnt]; pj_bzero(cand, sizeof(*cand)); - + @@ -855,6 +936,23 @@ static void icedemo_input_remote(void) goto on_error; } - + + if (is_tcp) { + if (strcmp(tcp_type, "active") == 0) + cand->transport = PJ_CAND_TCP_ACTIVE; @@ -4141,7 +4089,7 @@ index 07ccc31f0..3b93b9417 100644 pj_strdup2(icedemo.pool, &cand->foundation, foundation); cand->prio = prio; @@ -879,6 +977,10 @@ static void icedemo_input_remote(void) - + if (cand->comp_id > icedemo.rem.comp_cnt) icedemo.rem.comp_cnt = cand->comp_id; + } else if (strcmp(attr, "setup") == 0) { @@ -4164,5 +4112,6 @@ index 474a8d07c..9257f07a4 100644 NULL, sess, &sess->stun_sock); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; --- -2.26.2 +-- +2.25.4 + diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp index 732df49978e24a8deb0ad580ba865b22265c6a96..d12c3cb53e4d265c77f90728d95cfb8d176061fd 100644 --- a/src/ice_transport.cpp +++ b/src/ice_transport.cpp @@ -530,6 +530,7 @@ IceTransport::Impl::onComplete(pj_ice_strans* ice_st, pj_ice_strans_op op, pj_st JAMI_ERR("[ice:%p] %s %s failed: %s", this, (config_.protocol == PJ_ICE_TP_TCP? "TCP" : "UDP"), opname, last_errmsg_.c_str()); } + { std::lock_guard<std::mutex> lk(iceMutex_); if (!icest_.get())