Skip to content
Snippets Groups Projects
Unverified Commit 3f598a6a authored by Sébastien Blin's avatar Sébastien Blin
Browse files

pjproject: avoid to declare check valid too soon

The relay candidate was declared as suceeded even if not in the valid list.
Because of this, some negotiations were successful but no valid candidates
were given to the app.

Moreover, the connection timeout checks were using the wrong timer. This
avoids to cancel successful negotiations to check a connection timeout.

Finally, some clean is done with this patch

Change-Id: Iacfbf3b9f5faafe1bd05f66157485226761c30bf
Gitlab: #256
parent 9c58e4f0
No related branches found
No related tags found
No related merge requests found
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
......@@ -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())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment