Commit 227c8d1c authored by Adrien Béraud's avatar Adrien Béraud

Revert "sip: negotiate both UDP and TCP for the control channel"

This reverts commit e83a1006.

Reason for revert: some major issues remain

Change-Id: I6c59880ef9aacb1a0646c4879186b3f269b8541e
parent 8b3399e8
......@@ -35,6 +35,7 @@ bash -c "%PATCH_CMD% %UNIXPATH%pjproject/fix_ioqueue_ipv6_sendto.patch"
bash -c "%PATCH_CMD% %UNIXPATH%pjproject/add_dtls_transport.patch"
bash -c "%PATCH_CMD% %UNIXPATH%pjproject/rfc6544.patch"
bash -c "%PATCH_CMD% %UNIXPATH%pjproject/ice_config.patch"
bash -c "%PATCH_CMD% %UNIXPATH%pjproject/win32_ice_tcp_temp_fix.patch"
%APPLY_CMD% %SRC%\pjproject\win32_vs_gnutls.patch
%APPLY_CMD% %SRC%\pjproject\win_config.patch
......
......@@ -17,29 +17,28 @@ on behalf of Savoir-faire Linux.
---
pjnath/include/pjnath/config.h | 13 +-
pjnath/include/pjnath/ice_session.h | 166 ++-
pjnath/include/pjnath/ice_strans.h | 61 +-
pjnath/include/pjnath/stun_session.h | 82 +-
pjnath/include/pjnath/stun_sock.h | 93 +-
pjnath/include/pjnath/ice_session.h | 118 ++++++++++++++---
pjnath/include/pjnath/ice_strans.h | 61 ++++++++-
pjnath/include/pjnath/stun_session.h | 66 ++++++++-
pjnath/include/pjnath/stun_sock.h | 84 +++++++++---
pjnath/src/pjnath-test/concur_test.c | 8 +-
pjnath/src/pjnath-test/sess_auth.c | 12 +-
pjnath/src/pjnath-test/stun_sock_test.c | 7 +-
pjnath/src/pjnath/ice_session.c | 535 +++++++--
pjnath/src/pjnath/ice_strans.c | 958 ++++++++++++-----
pjnath/src/pjnath/ice_session.c | 388 +++++++++++++++++++++++++++++++++++++----------------
pjnath/src/pjnath/ice_strans.c | 741 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
pjnath/src/pjnath/nat_detect.c | 12 +-
pjnath/src/pjnath/stun_session.c | 12 +-
pjnath/src/pjnath/stun_sock.c | 1313 ++++++++++++++++-------
pjnath/src/pjnath/stun_transaction.c | 1 +
pjnath/src/pjnath/stun_sock.c | 1285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------
pjnath/src/pjnath/turn_session.c | 3 +-
pjnath/src/pjturn-client/client_main.c | 11 +-
pjnath/src/pjturn-srv/allocation.c | 2 +-
pjnath/src/pjturn-srv/server.c | 2 +-
pjsip-apps/src/samples/icedemo.c | 671 +++++++-----
pjsip-apps/src/samples/icedemo.c | 671 +++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------
pjsip/src/pjsua-lib/pjsua_core.c | 8 +-
20 files changed, 2877 insertions(+), 1093 deletions(-)
19 files changed, 2424 insertions(+), 1080 deletions(-)
diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h
index fc1e27550..6f17a663b 100644
index fc1e2755..6f17a663 100644
--- a/pjnath/include/pjnath/config.h
+++ b/pjnath/include/pjnath/config.h
@@ -1,5 +1,5 @@
......@@ -85,7 +84,7 @@ index fc1e27550..6f17a663b 100644
diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h
index fa13a3b7c..9644836d0 100644
index fa13a3b7..2e686ea1 100644
--- a/pjnath/include/pjnath/ice_session.h
+++ b/pjnath/include/pjnath/ice_session.h
@@ -163,6 +163,51 @@ typedef enum pj_ice_cand_type
......@@ -152,30 +151,7 @@ index fa13a3b7c..9644836d0 100644
} pj_ice_sess_cand;
@@ -324,6 +374,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
+ * us to connect yet. The socket will be reconnected during the next
+ * loop.
+ */
+ PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY,
+
+ /**
+ * TODO (sblin): REMOVE THIS! - https://github.com/coturn/coturn/issues/408
+ * For now, this status is only used because sometimes, the first packet
+ * doesn't receive any response. So, we retry to send the packet every
+ * 50 loops.
+ */
+ PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET,
+
/**
* A check has not been performed for this pair, and can be
* performed as soon as it is the highest priority Waiting pair on
@@ -331,6 +397,13 @@ typedef enum pj_ice_sess_check_state
@@ -331,6 +381,13 @@ typedef enum pj_ice_sess_check_state
*/
PJ_ICE_SESS_CHECK_STATE_WAITING,
......@@ -189,7 +165,7 @@ index fa13a3b7c..9644836d0 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
@@ -512,6 +585,41 @@ typedef struct pj_ice_sess_cb
@@ -512,6 +569,29 @@ typedef struct pj_ice_sess_cb
void *pkt, pj_size_t size,
const pj_sockaddr_t *src_addr,
unsigned src_addr_len);
......@@ -206,18 +182,6 @@ index fa13a3b7c..9644836d0 100644
+ unsigned check_id);
+
+ /**
+ * Reconnect a resetted TCP connection and send connectivity check
+ * cf. PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY
+ *
+ * @param ice The ICE session.
+ * @param clist The ICE connection list
+ * @param check_id The wanted check.
+ */
+ pj_status_t (*reconnect_tcp_connection)(pj_ice_sess *ice,
+ pj_ice_sess_checklist *clist,
+ unsigned check_id);
+
+ /**
+ * Close TCP socket
+ *
+ * @param ice The ICE session.
......@@ -231,7 +195,7 @@ index fa13a3b7c..9644836d0 100644
} pj_ice_sess_cb;
@@ -627,6 +735,7 @@ struct pj_ice_sess
@@ -627,6 +707,7 @@ struct pj_ice_sess
pj_bool_t is_destroying; /**< Destroy is called */
pj_status_t ice_status; /**< Error status. */
pj_timer_entry timer; /**< ICE timer. */
......@@ -239,7 +203,7 @@ index fa13a3b7c..9644836d0 100644
pj_ice_sess_cb cb; /**< Callback. */
pj_stun_config stun_cfg; /**< STUN settings. */
@@ -669,6 +778,7 @@ struct pj_ice_sess
@@ -669,6 +750,7 @@ struct pj_ice_sess
char txt[128];
char errmsg[PJ_ERR_MSG_SIZE];
} tmp;
......@@ -247,7 +211,7 @@ index fa13a3b7c..9644836d0 100644
};
@@ -826,8 +936,6 @@ PJ_DECL(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice,
@@ -826,8 +908,6 @@ PJ_DECL(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice,
PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice,
const pj_uint8_t prefs[4]);
......@@ -256,7 +220,7 @@ index fa13a3b7c..9644836d0 100644
/**
* Add a candidate to this ICE session. Application must add candidates for
* each components ID before it can start pairing the candidates and
@@ -846,20 +954,17 @@ PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice,
@@ -846,20 +926,17 @@ 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.
......@@ -285,10 +249,12 @@ index fa13a3b7c..9644836d0 100644
/**
* Find default candidate for the specified component ID, using this
@@ -968,7 +1073,42 @@ PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice,
@@ -968,8 +1045,19 @@ 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
+ *
......@@ -302,34 +268,11 @@ index fa13a3b7c..9644836d0 100644
+PJ_DECL(void)
+ice_sess_on_peer_connection(pj_ice_sess *ice,
+ pj_uint8_t transport_id, pj_status_t status, pj_sockaddr_t* remote_addr);
+/**
+ * Notification when ICE session get a new resetted connection
+ * cf PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY
+ *
+ * @param ice The ICE session.
+ * @param transport_id Related transport
+ * @param remote_addr Connected remove address
+ */
+PJ_DECL(void)
+ice_sess_on_peer_reset_connection(pj_ice_sess *ice,
+ pj_uint8_t transport_id, pj_sockaddr_t* remote_addr);
+
+/**
+ * Notification when ICE session get a new packet
+ * Used to remove the PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET status
+ *
+ * @param ice The ICE session.
+ * @param transport_id Related transport
+ * @param remote_addr Connected remove address
+ */
+PJ_DECL(void)
+ice_sess_on_peer_packet(pj_ice_sess *ice, pj_uint8_t transport_id, pj_sockaddr_t* remote_addr);
/**
* @}
*/
diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h
index b4a83067f..2b491e0d0 100644
index b4a83067..2b491e0d 100644
--- a/pjnath/include/pjnath/ice_strans.h
+++ b/pjnath/include/pjnath/ice_strans.h
@@ -1,5 +1,5 @@
......@@ -434,7 +377,7 @@ index b4a83067f..2b491e0d0 100644
/**
* @}
diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h
index f8ea4d1dc..3d42af5a2 100644
index f8ea4d1d..1e95a297 100644
--- a/pjnath/include/pjnath/stun_session.h
+++ b/pjnath/include/pjnath/stun_session.h
@@ -1,5 +1,5 @@
......@@ -474,7 +417,7 @@ index f8ea4d1dc..3d42af5a2 100644
/**
* This is the callback to be registered to pj_stun_session, to send
@@ -307,6 +330,33 @@ typedef struct pj_stun_session_cb
@@ -307,6 +330,17 @@ typedef struct pj_stun_session_cb
const pj_sockaddr_t *src_addr,
unsigned src_addr_len);
......@@ -488,27 +431,11 @@ index f8ea4d1dc..3d42af5a2 100644
+ * @param remote_addr The remote connected
+ */
+ void (*on_peer_connection)(pj_stun_session *sess, pj_status_t status, pj_sockaddr_t* remote_addr);
+
+ /**
+ * Notification when STUN connection is resetted (TCP only).
+ *
+ * @param stun_session The STUN session.
+ * @param remote_addr The remote resetted
+ */
+ void (*on_peer_reset_connection)(pj_stun_session *sess, pj_sockaddr_t* remote_addr);
+
+ /**
+ * Notification when STUN connection is resetted (TCP only).
+ *
+ * @param stun_session The STUN session.
+ * @param remote_addr The remote resetted
+ */
+ void (*on_peer_packet)(pj_stun_session *sess, pj_sockaddr_t* remote_addr);
+
} pj_stun_session_cb;
@@ -388,15 +438,15 @@ typedef enum pj_stun_sess_msg_log_flag
@@ -388,15 +422,15 @@ 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.
* @param p_sess Pointer to receive STUN session instance.
......@@ -530,7 +457,7 @@ index f8ea4d1dc..3d42af5a2 100644
/**
* Destroy the STUN session and all objects created in the context of
@@ -751,6 +801,24 @@ PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess,
@@ -751,6 +785,24 @@ PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess,
pj_stun_tx_data *tdata);
......@@ -556,7 +483,7 @@ index f8ea4d1dc..3d42af5a2 100644
* @}
*/
diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h
index fff4df885..05a61bb11 100644
index fff4df88..d70300bb 100644
--- a/pjnath/include/pjnath/stun_sock.h
+++ b/pjnath/include/pjnath/stun_sock.h
@@ -1,5 +1,5 @@
......@@ -682,7 +609,7 @@ index fff4df885..05a61bb11 100644
*
* @return PJ_SUCCESS if data has been sent immediately, or
* PJ_EPENDING if data cannot be sent immediately. In
@@ -483,7 +502,45 @@ PJ_DECL(pj_status_t) pj_stun_sock_sendto(pj_stun_sock *stun_sock,
@@ -483,7 +502,36 @@ PJ_DECL(pj_status_t) pj_stun_sock_sendto(pj_stun_sock *stun_sock,
unsigned pkt_len,
unsigned flag,
const pj_sockaddr_t *dst_addr,
......@@ -702,15 +629,6 @@ index fff4df885..05a61bb11 100644
+pj_stun_sock_connect_active(pj_stun_sock *stun_sock, const pj_sockaddr_t *remote_addr, int af);
+
+/**
+ * Connect active socket to remote address
+ * @param stun_sock
+ * @param remote_addr the destination
+ * @param af address family
+ */
+PJ_DECL(pj_status_t)
+pj_stun_sock_reconnect_active(pj_stun_sock *stun_sock, const pj_sockaddr_t *remote_addr, int af);
+
+/**
+ * Close active socket
+ * @param stun_sock
+ * @param remote_addr The remote address linked
......@@ -730,7 +648,7 @@ index fff4df885..05a61bb11 100644
/**
* @}
diff --git a/pjnath/src/pjnath-test/concur_test.c b/pjnath/src/pjnath-test/concur_test.c
index c3013d2ab..ebe173922 100644
index c3013d2a..ebe17392 100644
--- a/pjnath/src/pjnath-test/concur_test.c
+++ b/pjnath/src/pjnath-test/concur_test.c
@@ -183,10 +183,10 @@ static int stun_destroy_test_session(struct stun_test_session *test_sess)
......@@ -749,7 +667,7 @@ index c3013d2ab..ebe173922 100644
return -10;
}
diff --git a/pjnath/src/pjnath-test/sess_auth.c b/pjnath/src/pjnath-test/sess_auth.c
index 055eaad61..d1ad137a3 100644
index 055eaad6..d1ad137a 100644
--- a/pjnath/src/pjnath-test/sess_auth.c
+++ b/pjnath/src/pjnath-test/sess_auth.c
@@ -248,7 +248,8 @@ static int create_std_server(pj_stun_auth_type auth_type,
......@@ -786,7 +704,7 @@ index 055eaad61..d1ad137a3 100644
destroy_client_server();
return -270;
diff --git a/pjnath/src/pjnath-test/stun_sock_test.c b/pjnath/src/pjnath-test/stun_sock_test.c
index fff4fad26..a54df74dc 100644
index fff4fad2..a54df74d 100644
--- a/pjnath/src/pjnath-test/stun_sock_test.c
+++ b/pjnath/src/pjnath-test/stun_sock_test.c
@@ -255,8 +255,8 @@ static pj_status_t create_client(pj_stun_config *cfg,
......@@ -813,7 +731,7 @@ index fff4fad26..a54df74dc 100644
app_perror(" error: server sending data", status);
ret = -390;
diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c
index c51dba771..52fa05e3e 100644
index c51dba77..b9639061 100644
--- a/pjnath/src/pjnath/ice_session.c
+++ b/pjnath/src/pjnath/ice_session.c
@@ -1,5 +1,5 @@
......@@ -823,18 +741,15 @@ index c51dba771..52fa05e3e 100644
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
@@ -44,7 +44,10 @@ static const char *cand_type_names[] =
static const char *check_state_name[] =
@@ -45,6 +45,7 @@ static const char *check_state_name[] =
{
"Frozen",
+ "Needs Retry",
+ "Needs First Packet",
"Waiting",
+ "Pending",
"In Progress",
"Succeeded",
"Failed"
@@ -75,8 +78,8 @@ enum timer_type
@@ -75,8 +76,8 @@ enum timer_type
valid check for every components. */
TIMER_START_NOMINATED_CHECK,/**< Controlling agent start connectivity
checks with USE-CANDIDATE flag. */
......@@ -845,15 +760,7 @@ index c51dba771..52fa05e3e 100644
};
/* Candidate type preference */
@@ -123,6 +126,7 @@ typedef struct timer_data
{
pj_ice_sess *ice;
pj_ice_sess_checklist *clist;
+ unsigned first_packet_counter; // TODO (remove), for now, needed for the NEEDS_FIRST_PACKET state
} timer_data;
@@ -133,6 +137,7 @@ typedef struct timer_data
@@ -133,6 +134,7 @@ typedef struct timer_data
/* Forward declarations */
static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te);
......@@ -861,7 +768,7 @@ index c51dba771..52fa05e3e 100644
static void on_ice_complete(pj_ice_sess *ice, pj_status_t status);
static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now);
static void ice_on_destroy(void *obj);
@@ -288,10 +293,9 @@ static pj_status_t init_comp(pj_ice_sess *ice,
@@ -288,10 +290,9 @@ static pj_status_t init_comp(pj_ice_sess *ice,
sess_cb.on_send_msg = &on_stun_send_msg;
/* Create STUN session for this candidate */
......@@ -875,7 +782,7 @@ index c51dba771..52fa05e3e 100644
if (status != PJ_SUCCESS)
return status;
@@ -715,7 +719,8 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice,
@@ -715,7 +716,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,
......@@ -885,7 +792,7 @@ index c51dba771..52fa05e3e 100644
{
pj_ice_sess_cand *lcand;
pj_status_t status = PJ_SUCCESS;
@@ -738,6 +743,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice,
@@ -738,6 +740,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;
......@@ -893,16 +800,15 @@ index c51dba771..52fa05e3e 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);
@@ -959,6 +965,8 @@ static void check_set_state(pj_ice_sess *ice, pj_ice_sess_check *check,
@@ -959,6 +962,7 @@ 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)
{
+ if (check->state == st) return; // nothing to do
+ if (st == PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET && check->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) return;
pj_assert(check->state < PJ_ICE_SESS_CHECK_STATE_SUCCEEDED);
LOG5((ice->obj_name, "Check %s: state changed from %s to %s",
@@ -1079,6 +1087,17 @@ static pj_status_t prune_checklist(pj_ice_sess *ice,
@@ -1079,6 +1083,17 @@ static pj_status_t prune_checklist(pj_ice_sess *ice,
return PJNATH_EICENOHOSTCAND;
}
}
......@@ -920,7 +826,7 @@ index c51dba771..52fa05e3e 100644
}
/* Next remove a pair if its local and remote candidates are identical
@@ -1181,6 +1200,8 @@ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te)
@@ -1181,6 +1196,8 @@ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te)
case TIMER_KEEP_ALIVE:
ice_keep_alive(ice, PJ_TRUE);
break;
......@@ -929,7 +835,29 @@ index c51dba771..52fa05e3e 100644
case TIMER_NONE:
/* Nothing to do, just to get rid of gcc warning */
break;
@@ -1202,9 +1223,9 @@ static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now)
@@ -1189,6 +1206,21 @@ static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te)
pj_grp_lock_release(ice->grp_lock);
}
+static void on_tcp_connect_timeout(pj_ice_sess* ice) {
+ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, TIMER_NONE);
+
+ for (int i = 0; i < ice->clist.count; ++i) {
+ pj_ice_sess_check *check = &ice->clist.checks[i];
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_PENDING) {
+ if (*ice->cb.wait_tcp_connection) {
+ (*ice->cb.close_tcp_connection)(ice, &ice->clist, i);
+ }
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, PJ_ECANCELLED);
+ break;
+ }
+ }
+}
+
/* Send keep-alive */
static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now)
{
@@ -1202,9 +1234,9 @@ static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now)
pj_bool_t saved;
pj_status_t status;
......@@ -942,7 +870,7 @@ index c51dba771..52fa05e3e 100644
/* Create the Binding Indication */
status = pj_stun_session_create_ind(comp->stun_sess,
@@ -1343,7 +1364,6 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
@@ -1343,7 +1375,6 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING, 0);
}
}
......@@ -950,43 +878,7 @@ index c51dba771..52fa05e3e 100644
LOG5((ice->obj_name, "Check %d is successful%s",
GET_CHECK_ID(&ice->clist, check),
(check->nominated ? " and nominated" : "")));
@@ -1609,6 +1629,35 @@ 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, TIMER_NONE);
+
+ pj_bool_t first_found = PJ_FALSE, set_timer = PJ_FALSE;
+
+ for (int i = 0; i < ice->clist.count; ++i) {
+ pj_ice_sess_check *check = &ice->clist.checks[i];
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_PENDING && !first_found) {
+ if (*ice->cb.wait_tcp_connection) (*ice->cb.close_tcp_connection)(ice, &ice->clist, i);
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, PJ_ECANCELLED);
+ on_check_complete(ice, check);
+ first_found = PJ_TRUE;
+ } else if(check->state == PJ_ICE_SESS_CHECK_STATE_PENDING) {
+ set_timer = PJ_TRUE;
+ break;
+ }
+ }
+
+ if (set_timer && ice->timer.id == TIMER_NONE) {
+ // Reschedule
+ pj_time_val delay = {0, 0};
+ delay.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);
+ }
+}
+
/* Create checklist by pairing local candidates with remote candidates */
PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
@@ -1695,6 +1744,25 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
@@ -1695,6 +1726,25 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
continue;
}
......@@ -1012,15 +904,7 @@ index c51dba771..52fa05e3e 100644
chk->lcand = lcand;
chk->rcand = rcand;
@@ -1739,6 +1807,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;
@@ -1751,40 +1820,73 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
@@ -1751,40 +1801,71 @@ PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
return PJ_SUCCESS;
}
......@@ -1058,8 +942,6 @@ index c51dba771..52fa05e3e 100644
+ &rcand->addr, pj_sockaddr_get_len(&rcand->addr), check->tdata);
+ if (status != PJ_SUCCESS) {
+ check->tdata = NULL;
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status);
+ on_check_complete(ice, check);
+ pjnath_perror(ice->obj_name, "Error sending STUN request", status);
+ pj_log_pop_indent();
+ return status;
......@@ -1112,7 +994,7 @@ index c51dba771..52fa05e3e 100644
/* Attach data to be retrieved later when STUN request transaction
* completes and on_stun_request_complete() callback is called.
*/
@@ -1796,57 +1898,84 @@ static pj_status_t perform_check(pj_ice_sess *ice,
@@ -1796,57 +1877,72 @@ static pj_status_t perform_check(pj_ice_sess *ice,
msg_data->data.req.ckid = check_id;
/* Add PRIORITY */
......@@ -1170,24 +1052,17 @@ index c51dba771..52fa05e3e 100644
+ if (lcand->transport == PJ_CAND_UDP) {
+ status = send_connectivity_check(ice, clist, check_id, nominate, msg_data);
+ } else if (lcand->transport == PJ_CAND_TCP_ACTIVE) {
+
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY) {
+ status = (*ice->cb.reconnect_tcp_connection)(ice, clist, check_id);
+ } else if (check->state == PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET) {
+ status = send_connectivity_check(ice, clist, check_id, nominate, msg_data);
+ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, TIMER_NONE);
+ status = (*ice->cb.wait_tcp_connection)(ice, clist, check_id);
+ if (ice->timer.id == TIMER_NONE) {
+ pj_time_val delay = {0, 0};
+ delay.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 {
+ pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, TIMER_NONE);
+ status = (*ice->cb.wait_tcp_connection)(ice, clist, check_id);
+ if (ice->timer.id == TIMER_NONE) {
+ pj_time_val delay = {0, 0};
+ delay.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 if (check->state == PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY) {
+ pj_assert(!"Not expected any timer active");
+ }
+ pj_assert(!"Not expected any timer active");
+ }
}
+#else
......@@ -1213,13 +1088,8 @@ index c51dba771..52fa05e3e 100644
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_PENDING,
+ status);
+ } else {
+ if (check->rcand->type == PJ_ICE_CAND_TYPE_RELAYED) {
+ // TODO (sblin) remove this - https://github.com/coturn/coturn/issues/408
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET, status);
+ } else {
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS,
+ PJ_SUCCESS);
+ }
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS,
+ PJ_SUCCESS);
}
- check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS,
......@@ -1231,55 +1101,16 @@ index c51dba771..52fa05e3e 100644
}
@@ -1882,44 +2011,101 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
LOG5((ice->obj_name, "Starting checklist periodic check"));
pj_log_push_indent();
@@ -1859,7 +1955,7 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
timer_data *td;
pj_ice_sess *ice;
pj_ice_sess_checklist *clist;
- unsigned i, start_count=0;
+ unsigned i, start_count=0, pending_count=0;
pj_status_t status;
+ /* Send STUN Binding request for check with highest priority on
+ * retry state.
+ */
+
+ if (start_count == 0) {
+ for (i = 0; i < clist->count; ++i) {
+ pj_ice_sess_check *check = &clist->checks[i];
+ // Reconnect closed TURN sockets
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_NEEDS_RETRY) {
+ status = perform_check(ice, clist, i, ice->is_nominating);
+ if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED,
+ status);
+ on_check_complete(ice, check);
+ }
+ ++start_count;
+ break;
+ }
+ }
+ }
+
+ if (start_count == 0) {
+ // TODO (sblin) remove - https://github.com/coturn/coturn/issues/408
+ pj_bool_t inc_counter = PJ_TRUE;
+ for (i = 0; i < clist->count; ++i) {
+ pj_ice_sess_check *check = &clist->checks[i];
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_NEEDS_FIRST_PACKET) {
+ if (inc_counter) {
+ td->first_packet_counter += 1;
+ inc_counter = PJ_FALSE;
+ }
+ if (td->first_packet_counter % 50 == 0) {
+ status = perform_check(ice, clist, i, ice->is_nominating);
+ if (status != PJ_SUCCESS && status != PJ_EPENDING) {
+ check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED,
+ status);
+ on_check_complete(ice, check);
+ }
+ }
+ ++start_count;
+ break;
+ }
+ }
+ }
+
td = (struct timer_data*) te->user_data;
@@ -1885,41 +1981,41 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
/* Send STUN Binding request for check with highest priority on
* Waiting state.
*/
......@@ -1323,7 +1154,12 @@ index c51dba771..52fa05e3e 100644
- PJ_ICE_SESS_CHECK_STATE_FAILED, status);
- on_check_complete(ice, check);
- }
+ if (start_count == 0) {
-
- ++start_count;
- break;
- }
- }
+ if (start_count == 0 && pending_count == 0) {
+ for (i = 0; i < clist->count; ++i) {
+ pj_ice_sess_check *check = &clist->checks[i];
+
......@@ -1337,26 +1173,10 @@ index c51dba771..52fa05e3e 100644
+ break;
+ }
+ }
+ }
- ++start_count;
- break;
- }
- }
+ if (start_count == 0) {
+ // If all sockets are pending, do nothing
+ pj_bool_t inc_counter = PJ_TRUE;
+ for (i = 0; i < clist->count; ++i) {
+ pj_ice_sess_check *check = &clist->checks[i];
+ if (check->state == PJ_ICE_SESS_CHECK_STATE_PENDING) {
+ ++start_count;
+ break;
+ }
+ }
}
/* Cannot start check because there's no suitable candidate pair.
@@ -1936,8 +2122,7 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
@@ -1936,8 +2032,7 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
pj_grp_lock_release(ice->grp_lock);
pj_log_pop_indent();
return PJ_SUCCESS;
......@@ -1366,7 +1186,7 @@ index c51dba771..52fa05e3e 100644
/* Start sending connectivity check with USE-CANDIDATE */
static void start_nominated_check(pj_ice_sess *ice)
@@ -2109,13 +2294,13 @@ PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice)
@@ -2109,13 +2204,13 @@ PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice)
/* First, perform all pending triggered checks, simultaneously. */
rcheck = ice->early_check.next;
while (rcheck != &ice->early_check) {
......@@ -1387,7 +1207,7 @@ index c51dba771..52fa05e3e 100644
}
pj_list_init(&ice->early_check);
@@ -2161,7 +2346,7 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess,
@@ -2161,7 +2256,7 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess,
/* Stray retransmit timer that could happen while
* we're being destroyed */
pj_grp_lock_release(ice->grp_lock);
......@@ -1396,33 +1216,10 @@ index c51dba771..52fa05e3e 100644
}
status = (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id,
@@ -2171,6 +2356,136 @@ static pj_status_t on_stun_send_msg(pj_stun_session *sess,
@@ -2171,6 +2266,75 @@ 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, int* current_check)
+{
+ if (!ice || !remote_addr) return NULL;
+ // NOTE: Multiple checks can have the same remote, we only take care of the first
+ // First, check if the TCP is really connected. If not, abort
+ pj_ice_sess_check *check = NULL;
+ for (int i = 0; i < ice->clist.count; ++i) {
+ // Find related check
+ pj_ice_sess_check *c = &ice->clist.checks[i];
+ /* Host candidate not found this this srflx! */
+ if (pj_sockaddr_cmp(remote_addr, &c->rcand->addr) == 0) {
+ if (c->tdata == NULL || c->state != state)
+ continue;
+ /* Match */
+ check = c;
+ if (current_check) *current_check = i;
+ break;
+ }
+ }
+ return check;
+}
+
+void ice_sess_on_peer_connection(pj_ice_sess *ice, pj_uint8_t transport_id,
+ pj_status_t status,
+ pj_sockaddr_t* remote_addr) {
......@@ -1431,15 +1228,27 @@ index c51dba771..52fa05e3e 100644
+ // finished
+ if (!remote_addr) return;
+
+ // First, check if the TCP is really connected. If not, abort
+ pj_ice_sess_check *check = NULL;
+ int current_check = -1;
+ pj_ice_sess_check *check = get_current_check_at_state(ice, remote_addr,
+ PJ_ICE_SESS_CHECK_STATE_PENDING, &current_check);
+ if (!check) {
+ // Handle peer reflexive candidates (incoming are still waiting here)
+ check = get_current_check_at_state(ice, remote_addr, PJ_ICE_SESS_CHECK_STATE_WAITING, &current_check);
+ if (!check) {
+ return;
+ for (int i = 0; i < ice->clist.count; ++i) {
+ // Find related check
+ pj_ice_sess_check *c = &ice->clist.checks[i];
+ /* Host candidate not found this this srflx! */
+ if (pj_sockaddr_cmp(remote_addr, &c->rcand->addr) == 0) {
+ if (c->tdata == NULL) {
+ continue;
+ }
+ /* Match */
+ check = c;
+ current_check = i;
+ break;
+ }
+ }
+
+ // NOTE: Multiple checks can have the same remote, we only take care of the first
+ if (!check) {
+ return;
+ }