summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/ice/tnet_ice_ctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/ice/tnet_ice_ctx.c')
-rwxr-xr-xtinyNET/src/ice/tnet_ice_ctx.c947
1 files changed, 472 insertions, 475 deletions
diff --git a/tinyNET/src/ice/tnet_ice_ctx.c b/tinyNET/src/ice/tnet_ice_ctx.c
index 94d3042..6e5e5be 100755
--- a/tinyNET/src/ice/tnet_ice_ctx.c
+++ b/tinyNET/src/ice/tnet_ice_ctx.c
@@ -84,8 +84,7 @@ typedef tsk_list_t tnet_ice_servers_L_t;
static const char* foundation_default = tsk_null;
-typedef enum tnet_ice_server_proto_e
-{
+typedef enum tnet_ice_server_proto_e {
tnet_ice_server_proto_none = 0x00,
tnet_ice_server_proto_stun = (0x01 << 0),
tnet_ice_server_proto_turn = (0x01 << 1),
@@ -134,10 +133,9 @@ static int _tnet_ice_ctx_fsm_OnTerminated(struct tnet_ice_ctx_s* self);
static tsk_bool_t _tnet_ice_ctx_fsm_cond_NotStarted(struct tnet_ice_ctx_s* self, const void* _any);
static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs *e);
-typedef struct tnet_ice_server_s
-{
+typedef struct tnet_ice_server_s {
TSK_DECLARE_OBJECT;
-
+
enum tnet_socket_type_e e_transport;
tnet_ice_server_proto_t e_proto;
char* str_server_addr;
@@ -165,13 +163,12 @@ static tsk_object_t* tnet_ice_server_dtor(tsk_object_t * self)
TSK_FREE(ice_server->str_software);
TSK_FREE(ice_server->str_username);
TSK_FREE(ice_server->str_password);
-
+
TSK_DEBUG_INFO("*** ICE server destroyed ***");
}
return self;
}
-static const tsk_object_def_t tnet_ice_server_def_s =
-{
+static const tsk_object_def_t tnet_ice_server_def_s = {
sizeof(tnet_ice_server_t),
tnet_ice_server_ctor,
tnet_ice_server_dtor,
@@ -179,25 +176,25 @@ static const tsk_object_def_t tnet_ice_server_def_s =
};
static tnet_ice_server_t* tnet_ice_server_create(
- enum tnet_ice_server_proto_e e_proto,
- enum tnet_socket_type_e e_transport,
- const char* str_server_addr, uint16_t u_server_port,
- const char* str_software,
- const char* str_username, const char* str_password)
+ enum tnet_ice_server_proto_e e_proto,
+ enum tnet_socket_type_e e_transport,
+ const char* str_server_addr, uint16_t u_server_port,
+ const char* str_software,
+ const char* str_username, const char* str_password)
{
tnet_ice_server_t *ice_server;
struct sockaddr_storage obj_server_addr;
-
+
if (tsk_strnullORempty(str_server_addr) || !u_server_port) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
+
if (tnet_sockaddr_init(str_server_addr, u_server_port, e_transport, &obj_server_addr) != 0) {
TSK_DEBUG_ERROR("Invalid server address (host=%s, port=%d, transport=%d)", str_server_addr, u_server_port, e_transport);
return tsk_null;
}
-
+
if ((ice_server = tsk_object_new(&tnet_ice_server_def_s))) {
ice_server->e_proto = e_proto;
ice_server->e_transport = e_transport;
@@ -211,10 +208,9 @@ static tnet_ice_server_t* tnet_ice_server_create(
return ice_server;
}
-typedef struct tnet_ice_ctx_s
-{
+typedef struct tnet_ice_ctx_s {
TSK_DECLARE_RUNNABLE;
-
+
tsk_bool_t is_started;
tsk_bool_t is_active;
tsk_bool_t is_sync_mode;
@@ -229,7 +225,7 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t unicast;
tsk_bool_t anycast;
tsk_bool_t multicast;
-
+
tsk_bool_t is_connchecking;
tsk_bool_t is_controlling;
tsk_bool_t is_ice_jingle;
@@ -237,19 +233,19 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t is_stun_enabled;
uint64_t tie_breaker;
uint64_t concheck_timeout;
-
+
const void* rtp_callback_data;
tnet_ice_rtp_callback_f rtp_callback;
-
+
tnet_ice_servers_L_t *servers;
-
+
char* ufrag;
char* pwd;
-
+
tsk_timer_manager_handle_t* h_timer_mgr;
-
+
tsk_fsm_t* fsm;
-
+
tsk_condwait_handle_t* condwait_pairs;
tnet_ice_candidates_L_t* candidates_local;
tnet_ice_candidates_L_t* candidates_remote;
@@ -257,23 +253,23 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t have_nominated_offer;
tsk_bool_t have_nominated_answer;
tsk_bool_t have_nominated_symetric; /**< Whether symetic RTP has been negotiated */
-
+
uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond */
uint16_t Rc; /**< Number of retransmissions for UDP in millisecond */
-
+
struct {
char* path_priv;
char* path_pub;
char* path_ca;
tsk_bool_t verify;
} ssl;
-
+
struct {
tsk_bool_t auto_detect;
struct tnet_proxyinfo_s* info;
}
proxy;
-
+
struct {
tsk_condwait_handle_t* condwait;
struct tnet_turn_session_s* ss_nominated_rtp;
@@ -281,21 +277,19 @@ typedef struct tnet_ice_ctx_s
struct tnet_turn_session_s* ss_nominated_rtcp;
tnet_turn_peer_id_t peer_id_rtcp;
} turn;
-
+
TSK_DECLARE_SAFEOBJ;
}
tnet_ice_ctx_t;
-typedef struct tnet_ice_action_s
-{
+typedef struct tnet_ice_action_s {
TSK_DECLARE_OBJECT;
-
+
tsk_fsm_action_id id;
}
tnet_ice_action_t;
-typedef enum _fsm_state_e
-{
+typedef enum _fsm_state_e {
_fsm_state_Started,
_fsm_state_GatheringHostCandidates,
_fsm_state_GatheringHostCandidatesDone,
@@ -310,8 +304,7 @@ typedef enum _fsm_state_e
}
_fsm_state_t;
-typedef enum _fsm_action_e
-{
+typedef enum _fsm_action_e {
_fsm_action_Success,
_fsm_action_Failure,
_fsm_action_GatherHostCandidates,
@@ -327,19 +320,18 @@ _fsm_action_t;
static tsk_object_t* tnet_ice_action_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_action_t *action = self;
- if (action){
+ if (action) {
}
return self;
}
static tsk_object_t* tnet_ice_action_dtor(tsk_object_t * self)
{
tnet_ice_action_t *action = self;
- if (action){
+ if (action) {
}
return self;
}
-static const tsk_object_def_t tnet_ice_action_def_s =
-{
+static const tsk_object_def_t tnet_ice_action_def_s = {
sizeof(tnet_ice_action_t),
tnet_ice_action_ctor,
tnet_ice_action_dtor,
@@ -348,7 +340,7 @@ static const tsk_object_def_t tnet_ice_action_def_s =
static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id)
{
tnet_ice_action_t *action = tsk_object_new(&tnet_ice_action_def_s);
- if (action){
+ if (action) {
action->id = id;
}
return action;
@@ -360,59 +352,59 @@ static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id)
static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_ctx_t *ctx = self;
- if (ctx){
+ if (ctx) {
tsk_safeobj_init(ctx);
-
- if (!(ctx->h_timer_mgr = tsk_timer_manager_create())){
+
+ if (!(ctx->h_timer_mgr = tsk_timer_manager_create())) {
TSK_DEBUG_ERROR("Failed to create timer manager");
return tsk_null;
}
- if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))){
+ if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))) {
TSK_DEBUG_ERROR("Failed to create state machine");
return tsk_null;
}
- if (!(ctx->candidates_local = tsk_list_create())){
+ if (!(ctx->candidates_local = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
- if (!(ctx->candidates_remote = tsk_list_create())){
+ if (!(ctx->candidates_remote = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
- if (!(ctx->candidates_pairs = tsk_list_create())){
+ if (!(ctx->candidates_pairs = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
-
+
// Create condwait for pairs
if (!(ctx->condwait_pairs = tsk_condwait_create())) {
TSK_DEBUG_ERROR("Failed to create condwait for pairs");
return tsk_null;
}
-
+
// Create list objects to hold the servers
- if (!(ctx->servers = tsk_list_create())){
+ if (!(ctx->servers = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create server list");
return tsk_null;
}
-
+
tsk_runnable_set_important(TSK_RUNNABLE(self), tsk_false);
-
+
/* 7.2.1. Sending over UDP
In fixed-line access links, a value of 500 ms is RECOMMENDED.
*/
ctx->RTO = kIceDefaultRTO;
-
+
/* 7.2.1. Sending over UDP
Rc SHOULD be configurable and SHOULD have a default of 7.
*/
ctx->Rc = kIceDefaultRC;
-
+
ctx->tie_breaker = ((tsk_time_now() << 32) ^ tsk_time_now());
ctx->is_ice_jingle = tsk_false;
ctx->is_stun_enabled = kIceDefaultStunEnabled;
ctx->is_turn_enabled = kIceDefaultTurnEnabled;
-
+
ctx->concheck_timeout = LONG_MAX;
}
return self;
@@ -420,17 +412,17 @@ static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app)
static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self)
{
tnet_ice_ctx_t *ctx = self;
- if (ctx){
+ if (ctx) {
tnet_ice_ctx_stop(ctx);
- if (ctx->h_timer_mgr){
+ if (ctx->h_timer_mgr) {
tsk_timer_manager_destroy(&ctx->h_timer_mgr);
}
-
+
TSK_OBJECT_SAFE_FREE(ctx->fsm);
TSK_OBJECT_SAFE_FREE(ctx->candidates_local);
TSK_OBJECT_SAFE_FREE(ctx->candidates_remote);
TSK_OBJECT_SAFE_FREE(ctx->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
if (ctx->turn.condwait) {
@@ -440,20 +432,19 @@ static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self)
tsk_condwait_destroy(&ctx->condwait_pairs);
}
TSK_OBJECT_SAFE_FREE(ctx->servers);
-
+
TSK_OBJECT_SAFE_FREE(ctx->proxy.info);
-
+
TSK_FREE(ctx->ssl.path_priv);
TSK_FREE(ctx->ssl.path_pub);
TSK_FREE(ctx->ssl.path_ca);
-
+
tsk_safeobj_deinit(ctx);
}
TSK_DEBUG_INFO("*** ICE context destroyed ***");
return self;
}
-static const tsk_object_def_t tnet_ice_ctx_def_s =
-{
+static const tsk_object_def_t tnet_ice_ctx_def_s = {
sizeof(tnet_ice_ctx_t),
tnet_ice_ctx_ctor,
tnet_ice_ctx_dtor,
@@ -464,12 +455,12 @@ static const tsk_object_def_t tnet_ice_ctx_def_s =
tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv6, tsk_bool_t use_rtcp, tsk_bool_t is_video, tnet_ice_callback_f callback, const void* userdata)
{
tnet_ice_ctx_t* ctx;
-
- if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))){
+
+ if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))) {
TSK_DEBUG_ERROR("Failed to create ICE context object");
return tsk_null;
}
-
+
ctx->is_ice_jingle = is_ice_jingle;
ctx->use_ipv6 = use_ipv6;
ctx->use_rtcp = use_rtcp;
@@ -479,10 +470,10 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
ctx->unicast = tsk_true;
ctx->anycast = tsk_false;
ctx->multicast = tsk_false;
-
+
tnet_ice_utils_set_ufrag(&ctx->ufrag);
tnet_ice_utils_set_pwd(&ctx->pwd);
-
+
ctx->fsm->debug = TNET_ICE_DEBUG_STATE_MACHINE;
tsk_fsm_set_callback_terminated(ctx->fsm, TSK_FSM_ONTERMINATED_F(_tnet_ice_ctx_fsm_OnTerminated), (const void*)ctx);
tsk_fsm_set(ctx->fsm,
@@ -492,14 +483,14 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Success, _fsm_state_GatheringHostCandidatesDone, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success, "ICE_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success"),
// (GatheringHostCandidates) -> (Failure) -> (Terminated)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure, "ICE_GatheringHostCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringHostCandidatesDone) -> (GatherReflexiveCandidates) -> (GatheringReflexiveCandidates)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidatesDone, _fsm_action_GatherReflexiveCandidates, _fsm_state_GatheringReflexiveCandidates, _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates, "ICE_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates"),
// (GatheringReflexiveCandidates) -> (Success) -> GatheringReflexiveCandidatesDone
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Success, _fsm_state_GatheringReflexiveCandidatesDone, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success, "ICE_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success"),
// (GatheringReflexiveCandidates) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_Terminated_X_Failure, "ICE_GatheringReflexiveCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringReflexiveCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidatesDone, _fsm_action_GatherRelayCandidates, _fsm_state_GatheringRelayCandidates, _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates, "ICE_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates"),
// (GatheringHostCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates)
@@ -508,28 +499,28 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Success, _fsm_state_GatheringRelayCandidatesDone, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success, "ICE_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success"),
// (GatheringRelayCandidates) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_Terminated_X_Failure, "ICE_GatheringRelayCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringComplet) -> (ConnCheck) -> ConnChecking
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringCompleted, _fsm_action_ConnCheck, _fsm_state_ConnChecking, _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck, "ICE_GatheringCompleted_2_ConnChecking_X_ConnCheck"),
// (ConnChecking) -> (Success) -> ConnCheckingCompleted
TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Success, _fsm_state_ConnCheckingCompleted, _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success, "ICE_ConnChecking_2_ConnCheckingCompleted_X_Success"),
// (ConnChecking) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_ConnChecking_2_Terminated_X_Failure, "ICE_ConnChecking_2_Terminated_X_Failure"),
-
+
// (Any) -> (GatheringComplet) -> GatheringCompleted
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_GatheringComplet, _fsm_state_GatheringCompleted, _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet, "ICE_Any_2_GatheringCompleted_X_GatheringComplet"),
// (Any) -> (Cancel) -> Started
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_Cancel, _fsm_state_Started, _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel, "ICE_Any_2_Started_X_Cancel"),
// (Any) -> (AnyNotStarted) -> Terminated
TSK_FSM_ADD(tsk_fsm_state_any, tsk_fsm_action_any, _tnet_ice_ctx_fsm_cond_NotStarted, _fsm_state_Terminated, _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted, "ICE_fsm_Any_2_Terminated_X_AnyNotStarted")
- );
-
+ );
+
return ctx;
}
int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -539,34 +530,34 @@ int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata)
// @deprecated: use "tnet_ice_ctx_add_server()"
int tnet_ice_ctx_set_stun(
- tnet_ice_ctx_t* self,
- const char* server_addr,
- uint16_t server_port,
- const char* software,
- const char* username,
- const char* password)
+ tnet_ice_ctx_t* self,
+ const char* server_addr,
+ uint16_t server_port,
+ const char* software,
+ const char* username,
+ const char* password)
{
_tnet_ice_ctx_servers_clear(self);
return tnet_ice_ctx_add_server(
- self,
- "udp",
- server_addr,
- server_port,
- (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/
- tsk_true, /* use_stun*/
- username,
- password);
+ self,
+ "udp",
+ server_addr,
+ server_port,
+ (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/
+ tsk_true, /* use_stun*/
+ username,
+ password);
}
int tnet_ice_ctx_add_server(
- struct tnet_ice_ctx_s* self,
- const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"
- const char* server_addr,
- uint16_t server_port,
- tsk_bool_t use_turn,
- tsk_bool_t use_stun,
- const char* username,
- const char* password)
+ struct tnet_ice_ctx_s* self,
+ const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"
+ const char* server_addr,
+ uint16_t server_port,
+ tsk_bool_t use_turn,
+ tsk_bool_t use_stun,
+ const char* username,
+ const char* password)
{
tnet_socket_type_t socket_type;
tnet_ice_server_proto_t e_proto = tnet_ice_server_proto_none;
@@ -584,7 +575,7 @@ int tnet_ice_ctx_add_server(
if (use_turn) {
e_proto |= tnet_ice_server_proto_turn;
}
-
+
if (tsk_striequals(transport_proto, "udp")) {
socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4;
}
@@ -612,7 +603,7 @@ int tnet_ice_ctx_add_server(
int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -622,7 +613,7 @@ int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode)
int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_mode)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -633,7 +624,7 @@ int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_
// Whether to gather reflexive candidates
int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_enabled)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -644,7 +635,7 @@ int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_e
// Whether to gather relay candidates
int tnet_ice_ctx_set_turn_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t turn_enabled)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -658,19 +649,19 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self)
tsk_bool_t timer_mgr_started = tsk_false;
tsk_bool_t runnable_started = tsk_false;
const char* err = tsk_null;
-
- if (!self){
+
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
-
+
TSK_DEBUG_INFO("tnet_ice_ctx_start");
-
- if (self->is_started){
+
+ if (self->is_started) {
ret = 0;
- if (!self->is_active){
+ if (!self->is_active) {
TSK_DEBUG_INFO("ICE restart");
ret = _tnet_ice_ctx_restart(self);
}
@@ -678,42 +669,42 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self)
tsk_safeobj_unlock(self);
return ret;
}
-
+
/* === Timer manager === */
- if ((ret = tsk_timer_manager_start(self->h_timer_mgr))){
+ if ((ret = tsk_timer_manager_start(self->h_timer_mgr))) {
err = "Failed to start timer manager";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
timer_mgr_started = tsk_true;
-
+
/* === Runnable === */
TSK_RUNNABLE(self)->run = _tnet_ice_ctx_run;
- if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))){
+ if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))) {
err = "Failed to start runnable";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
runnable_started = tsk_true;
-
+
self->is_started = tsk_true; // needed by FSM -> "Must" be before fsm_ast()
self->is_active = tsk_true;
-
- if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))){
+
+ if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))) {
err = "FSM execution failed";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
-
+
bail:
tsk_safeobj_unlock(self);
-
- if (ret){
+
+ if (ret) {
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_start_failed, err);
- if (timer_mgr_started){
+ if (timer_mgr_started) {
tsk_timer_manager_stop(self->h_timer_mgr);
}
- if (runnable_started){
+ if (runnable_started) {
tsk_runnable_stop(TSK_RUNNABLE(self));
}
self->is_started = tsk_false;
@@ -725,11 +716,11 @@ bail:
// register callback to call when we receive early RTP packets while negotaiating ICE pairs
int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_callback, const void* rtp_callback_data)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->rtp_callback_data = rtp_callback_data;
self->rtp_callback = rtp_callback;
return 0;
@@ -738,13 +729,13 @@ int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_
// timeout (millis): <=0 to disable
int tnet_ice_ctx_set_concheck_timeout(tnet_ice_ctx_t* self, int64_t timeout)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->concheck_timeout = (timeout <= 0 ? LONG_MAX : timeout);
-
+
return 0;
}
@@ -761,34 +752,34 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->is_controlling = is_controlling;
self->is_ice_jingle = is_ice_jingle;
tnet_ice_ctx_set_rtcpmux(self, use_rtcpmux);
-
+
if (tsk_strnullORempty(candidates)) {
// remote party is ICE-lite or doesn't support ICE
return tnet_ice_ctx_cancel(self);
}
-
+
TSK_DEBUG_INFO("tnet_ice_ctx_set_remote_candidates(ufrag=%s, pwd=%s, is_controlling=%d, is_ice_jingle=%d, use_rtcpmux=%d)",
ufrag, pwd, is_controlling, is_ice_jingle, use_rtcpmux);
-
+
tsk_list_lock(self->candidates_pairs);
if (!TSK_LIST_IS_EMPTY(self->candidates_pairs)) {
TSK_DEBUG_WARN("Adding Remote ICE candidates after pairs building");
}
tsk_list_unlock(self->candidates_pairs);
-
+
// active if remote is full-ICE
// in all case we are always full-ICE
// self->is_active = tsk_true;
-
+
tsk_list_lock(self->candidates_remote);
-
+
// clear old candidates
tsk_list_clear_items(self->candidates_remote);
-
+
copy = tsk_strdup(candidates);
size = (tsk_size_t)tsk_strlen(copy);
do {
@@ -819,13 +810,14 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char
}
TSK_OBJECT_SAFE_FREE(candidate);
}
- } while (v && (idx < size));
-
+ }
+ while (v && (idx < size));
+
tsk_list_unlock(self->candidates_remote);
-
+
TSK_FREE(copy);
TSK_OBJECT_SAFE_FREE(added_candidates);
-
+
if (!tnet_ice_ctx_is_connected(self) && tnet_ice_ctx_got_local_candidates(self) && !TSK_LIST_IS_EMPTY(self->candidates_remote)) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck);
}
@@ -866,7 +858,7 @@ int tnet_ice_ctx_set_ssl_certs(struct tnet_ice_ctx_s* self, const char* path_pri
tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
@@ -876,16 +868,16 @@ tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self)
tsk_bool_t tnet_ice_ctx_got_local_candidates(const tnet_ice_ctx_t* self)
{
tsk_fsm_state_id curr_state;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_false;
}
- if (!self->is_started){
+ if (!self->is_started) {
return tsk_false;
}
-
+
curr_state = tsk_fsm_get_current_state(self->fsm);
-
+
return (curr_state >= _fsm_state_GatheringCompleted && curr_state < _fsm_state_Terminated);
}
@@ -893,13 +885,13 @@ const tnet_ice_candidate_t* tnet_ice_ctx_get_local_candidate_at(const tnet_ice_c
{
const tsk_list_item_t *item;
tsk_size_t pos = 0;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
- tsk_list_foreach(item, self->candidates_local){
- if (pos++ == index){
+
+ tsk_list_foreach(item, self->candidates_local) {
+ if (pos++ == index) {
return (const tnet_ice_candidate_t*)item->data;
}
}
@@ -922,9 +914,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtp_active(const struct tnet_ice_ctx_s* self)
{
tsk_bool_t b_active;
return tnet_ice_ctx_is_active(self)
- && self->turn.ss_nominated_rtp
- && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0
- && b_active;
+ && self->turn.ss_nominated_rtp
+ && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0
+ && b_active;
}
tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self)
@@ -935,9 +927,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self)
else {
tsk_bool_t b_active;
return tnet_ice_ctx_is_active(self)
- && self->turn.ss_nominated_rtcp
- && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0
- && b_active;
+ && self->turn.ss_nominated_rtcp
+ && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0
+ && b_active;
}
}
@@ -968,11 +960,11 @@ tsk_bool_t tnet_ice_ctx_use_rtcp(const tnet_ice_ctx_t* self)
}
int tnet_ice_ctx_get_nominated_symetric_candidates(const tnet_ice_ctx_t* self, uint32_t comp_id,
- const tnet_ice_candidate_t** candidate_offer,
- const tnet_ice_candidate_t** candidate_answer_src,
- const tnet_ice_candidate_t** candidate_answer_dest)
+ const tnet_ice_candidate_t** candidate_offer,
+ const tnet_ice_candidate_t** candidate_answer_src,
+ const tnet_ice_candidate_t** candidate_answer_dest)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -993,14 +985,14 @@ int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, ts
int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size)
{
return self->use_rtcpmux
- ? tnet_ice_ctx_send_turn_rtp(self, data, size)
- : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size);
+ ? tnet_ice_ctx_send_turn_rtp(self, data, size)
+ : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size);
}
int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_t* bytes_in, uint64_t* bytes_out)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
@@ -1010,8 +1002,12 @@ int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_
uint64_t _bytes_in, _bytes_out;
ret = tnet_turn_session_get_bytes_count(self->turn.ss_nominated_rtcp, &_bytes_in, &_bytes_out);
if (ret == 0) {
- if (bytes_in) *bytes_in += _bytes_in;
- if (bytes_out) *bytes_out += _bytes_out;
+ if (bytes_in) {
+ *bytes_in += _bytes_in;
+ }
+ if (bytes_out) {
+ *bytes_out += _bytes_out;
+ }
}
}
return ret;
@@ -1058,19 +1054,19 @@ int tnet_ice_ctx_set_proxy_info(struct tnet_ice_ctx_s* self, enum tnet_proxy_typ
int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
if (tsk_fsm_get_current_state(self->fsm) == _fsm_state_Started) {
// Do nothing if already in the "started" state
ret = 0;
goto bail;
}
-
+
self->is_active = tsk_false;
self->have_nominated_symetric = tsk_false;
self->have_nominated_answer = tsk_false;
@@ -1080,7 +1076,7 @@ int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self)
ret = tsk_condwait_broadcast(self->turn.condwait);
}
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Cancel);
-
+
bail:
tsk_safeobj_unlock(self);
return ret;
@@ -1089,18 +1085,18 @@ bail:
int tnet_ice_ctx_stop(tnet_ice_ctx_t* self)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
if (!self->is_started) {
ret = 0;
goto bail;
}
-
+
self->is_started = tsk_false;
tsk_condwait_broadcast(self->condwait_pairs);
if (self->turn.condwait) {
@@ -1108,7 +1104,7 @@ int tnet_ice_ctx_stop(tnet_ice_ctx_t* self)
}
ret = tsk_timer_manager_stop(self->h_timer_mgr);
ret = tsk_runnable_stop(TSK_RUNNABLE(self));
-
+
bail:
tsk_safeobj_unlock(self);
return ret;
@@ -1136,92 +1132,92 @@ static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandi
static const tsk_bool_t dnsserver = tsk_false;
static const long if_index_any = -1; // any interface
static const char* destination = "doubango.org";
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4;
-
+
addresses = tnet_get_addresses((self->use_ipv6 ? AF_INET6 : AF_INET), self->unicast, self->anycast, self->multicast, dnsserver, if_index_any);
- if (!addresses || TSK_LIST_IS_EMPTY(addresses)){
+ if (!addresses || TSK_LIST_IS_EMPTY(addresses)) {
TSK_DEBUG_ERROR("Failed to get addresses");
ret = -1;
goto bail;
}
-
-
+
+
check_best_local_ip = (tnet_getbestsource(destination, 5060, socket_type, &best_local_ip) == 0);
curr_local_pref = local_pref = check_best_local_ip ? 0xFFFE : 0xFFFF;
-
+
// lock-list
tsk_list_lock(self->candidates_local);
// clear-list
tsk_list_clear_items(self->candidates_local);
-
- tsk_list_foreach(item, addresses){
- if (!(address = item->data)){
+
+ tsk_list_foreach(item, addresses) {
+ if (!(address = item->data)) {
continue;
}
-
+
// Skip loopback address to avoid problems :)
- if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))){
+ if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))) {
continue;
}
-
+
// host candidates
ret = tnet_ice_utils_create_sockets(socket_type,
address->ip, &socket_rtp,
self->use_rtcp ? &socket_rtcp : tsk_null);
- if (ret == 0){
+ if (ret == 0) {
const char* foundation_rtp = foundation_default;
tsk_list_lock(self->candidates_local);
- if (socket_rtp){
- if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))){
+ if (socket_rtp) {
+ if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))) {
foundation_rtp = (const char*)candidate->foundation;
- if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))){
+ if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))) {
curr_local_pref = 0xFFFF;
check_best_local_ip = tsk_false;
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_front_data(self->candidates_local, (void**)&candidate);
}
- else{
+ else {
curr_local_pref = local_pref--;
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_back_data(self->candidates_local, (void**)&candidate);
}
}
}
- if (socket_rtcp){
- if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))){
+ if (socket_rtcp) {
+ if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))) {
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_back_data(self->candidates_local, (void**)&candidate);
}
}
tsk_list_unlock(self->candidates_local);
}
-
+
TSK_OBJECT_SAFE_FREE(socket_rtp);
TSK_OBJECT_SAFE_FREE(socket_rtcp);
-
+
// break if no longer running
- if (!self->is_started){
+ if (!self->is_started) {
break;
}
-
+
TSK_DEBUG_INFO("local ip address = %s", address->ip);
}
-
+
// unlock-list
tsk_list_unlock(self->candidates_local);
-
+
bail:
- if (self->is_started){
- if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)){
+ if (self->is_started) {
+ if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success);
}
- else{
+ else {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
TSK_OBJECT_SAFE_FREE(addresses);
return ret;
}
@@ -1231,9 +1227,9 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
{
int ret;
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_succeed, "Gathering host candidates succeed");
if (ret == 0) {
if (self->is_stun_enabled && _tnet_ice_ctx_servers_count_by_proto(self, tnet_ice_server_proto_stun) > 0) {
@@ -1251,7 +1247,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
}
}
}
-
+
return ret;
}
@@ -1259,7 +1255,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure(va_list *app)
{
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_failed, "Gathering host candidates failed");
}
@@ -1287,16 +1283,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
fd_set set;
tsk_size_t srflx_addr_count_added = 0, srflx_addr_count_skipped = 0, host_addr_count = 0;
long tv_sec, tv_usec; //very important to save these values as timeval could be modified by select() - happens on iOS -
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
// Get ICE servers to use to gather reflexive candidates
ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_stun);
if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) { // not expected to be null or empty because we checked the number of such servers before calling this transition
TSK_DEBUG_WARN("No valid STUN server could be used to gather reflexive candidates");
goto bail;
}
-
+
// set all default values to -1
// = {{ -1 }} will only set the first element
for (i = 0; i < sizeof(fds) / sizeof(fds[0]); ++i) {
@@ -1305,17 +1301,17 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
for (i = 0; i < sizeof(fds_skipped) / sizeof(fds_skipped[0]); ++i) {
fds_skipped[i] = TNET_INVALID_FD;
}
-
+
rc = self->Rc;
tv.tv_sec = tv_sec = 0;
tv.tv_usec = tv_usec = 0;
-
+
// load fds for both rtp and rtcp sockets
tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = item->data)) {
continue;
}
-
+
++host_addr_count;
if ((fds_count < sizeof(fds) / sizeof(fds[0])) && candidate->socket) {
fds[fds_count++] = candidate->socket->fd;
@@ -1324,13 +1320,13 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
}
}
}
-
-
+
+
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
-
+
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for (i = 0; (i < rc && self->is_started && ((srflx_addr_count_added + srflx_addr_count_skipped) < host_addr_count)); ++i) {
@@ -1362,16 +1358,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
#else
tv.tv_usec = tv_usec;
#endif
-
+
TSK_DEBUG_INFO("ICE reflexive candidates gathering ...srv_addr=%s,srv_port=%u,tv_sec=%lu,tv_usec=%lu,rto=%d", ice_server->str_server_addr, ice_server->u_server_port, tv_sec, tv_usec, ice_server->rto);
-
+
FD_ZERO(&set);
for (k = 0; k < fds_count; ++k) {
FD_SET(fds[k], &set);
}
-
+
// sends STUN binding requets
- tsk_list_foreach(item, self->candidates_local){
+ tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = (tnet_ice_candidate_t*)item->data)) {
continue;
}
@@ -1379,7 +1375,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
ret = tnet_ice_candidate_send_stun_bind_request(candidate, &ice_server->obj_server_addr, ice_server->str_username, ice_server->str_password);
}
}
-
+
if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) {
TSK_DEBUG_ERROR("select() failed with error code = %d", tnet_geterrno());
goto bail;
@@ -1398,27 +1394,27 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
unsigned int len = 0;
void* data = 0;
const tnet_ice_candidate_t* candidate_curr;
-
+
// Check how many bytes are pending
if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) {
TSK_DEBUG_ERROR("tnet_ioctlt() failed");
continue;
}
-
+
if (len == 0) {
TSK_DEBUG_INFO("tnet_ioctlt() retured zero bytes");
continue;
}
-
+
// Receive pending data
data = tsk_calloc(len, sizeof(uint8_t));
if ((ret = tnet_sockfd_recv(fd, data, len, 0)) < 0) {
TSK_FREE(data);
-
+
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
continue;
}
-
+
// Parse the incoming response
if ((ret = tnet_stun_pkt_read(data, (tsk_size_t)ret, &response))) {
TSK_FREE(data);
@@ -1435,7 +1431,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
tsk_size_t j;
tsk_bool_t already_skipped = tsk_false;
/* refc 5245- 4.1.3. Eliminating Redundant Candidates
-
+
Next, the agent eliminates redundant candidates. A candidate is
redundant if its transport address equals another candidate, and its
base equals the base of that other candidate. Note that two
@@ -1450,7 +1446,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
break;
}
}
-
+
if (!already_skipped) {
++srflx_addr_count_skipped;
fds_skipped[j] = fd;
@@ -1488,19 +1484,21 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
}
} // tsk_list_foreach (item, ice_servers)...
} // for (i = 0; (i < rc....
-
+
bail:
TSK_DEBUG_INFO("srflx_addr_count_added=%u, srflx_addr_count_skipped=%u", (unsigned)srflx_addr_count_added, (unsigned)srflx_addr_count_skipped);
- if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) ret = 0; // Hack the returned value if we have at least one success (happens when timeouts)
+ if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) {
+ ret = 0; // Hack the returned value if we have at least one success (happens when timeouts)
+ }
if (self->is_started) {
if (ret == 0) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success);
}
- else{
+ else {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = (tnet_ice_candidate_t*)item->data)) {
continue;
@@ -1515,9 +1513,9 @@ bail:
static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success(va_list *app)
{
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
if (self->is_started) {
int ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_reflexive_candidates_succeed, "Gathering reflexive candidates succeed");
if (ret == 0) {
@@ -1560,19 +1558,19 @@ static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCa
tnet_ice_servers_L_t* ice_servers = tsk_null;
tnet_ice_server_t* ice_server;
tnet_ice_candidates_L_t* candidates_local_copy = tsk_null;;
-
+
// Create TURN condwait handle if not already done
if (!self->turn.condwait && !(self->turn.condwait = tsk_condwait_create())) {
TSK_DEBUG_ERROR("Failed to create TURN condwait handle");
ret = -2;
goto bail;
}
-
+
// Copy local ICE candidates
tsk_list_lock(self->candidates_local);
candidates_local_copy = tsk_list_clone(self->candidates_local);
tsk_list_unlock(self->candidates_local);
-
+
// Take reference to the TURN servers
ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_turn);
if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) {
@@ -1595,14 +1593,14 @@ next_server:
goto bail;
}
ice_server = (tnet_ice_server_t*)item_server->data;
-
+
// Create TURN sessions for each local host candidate
tsk_list_foreach(item, candidates_local_copy) {
if (!(candidate = item->data)) {
continue;
}
TSK_DEBUG_INFO("Gathering relay candidate: local addr=%s=%d, TURN server=%s:%d", candidate->connection_addr, candidate->port, ice_server->str_server_addr, ice_server->u_server_port);
-
+
// Destroy previvious TURN session (if exist)
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
if (candidate->type_e == tnet_ice_cand_type_host && candidate->socket) { // do not create TURN session for reflexive candidates
@@ -1648,16 +1646,16 @@ next_server:
++host_addr_count;
}
} // tsk_list_foreach(item, self->candidates_local) {
-
+
rto = self->RTO;
rc = self->Rc;
-
+
for (i = 0; (i < rc && self->is_started && ((relay_addr_count_ok + relay_addr_count_nok) < host_addr_count));) {
if (!self->is_started || !self->is_active) {
TSK_DEBUG_INFO("ICE context stopped/cancelled while gathering TURN candidates");
goto bail;
}
-
+
u_t0 = tsk_time_now();
tsk_condwait_timedwait(self->turn.condwait, rto);
u_t1 = tsk_time_now();
@@ -1666,7 +1664,7 @@ next_server:
rto <<= 1;
++i;
}
-
+
// count the number of TURN sessions with alloc() = ok/nok and ignore ones without response
relay_addr_count_ok = 0;
tsk_list_foreach(item, candidates_local_copy) {
@@ -1685,7 +1683,7 @@ next_server:
}
}
}
-
+
// add/delete TURN candidates
tsk_list_foreach(item, candidates_local_copy) {
if (!(candidate = item->data) || !candidate->turn.ss) {
@@ -1701,7 +1699,7 @@ next_server:
tnet_port_t relay_port;
tnet_ice_candidate_t* new_cand = tsk_null;
struct tnet_socket_s* p_lcl_sock = tsk_null;
-
+
if ((ret = tnet_turn_session_get_relayed_addr(candidate->turn.ss, &relay_addr, &relay_port, &__b_ipv6))) {
goto bail;
}
@@ -1733,12 +1731,12 @@ next_server:
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
}
}
-
+
// Try next TURN server
if (self->is_started && item_server && relay_addr_count_added == 0) {
goto next_server;
}
-
+
bail:
if (self->is_started) {
if (ret == 0) {
@@ -1778,34 +1776,34 @@ static int _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel(va_list *app)
{
tnet_ice_ctx_t* self;
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
tsk_list_lock(self->candidates_remote);
tsk_list_clear_items(self->candidates_remote);
tsk_list_unlock(self->candidates_remote);
-
+
tsk_list_lock(self->candidates_pairs);
tsk_list_clear_items(self->candidates_pairs);
tsk_list_unlock(self->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
// Do not clear local candidates because then will be used as fallback if the remote peer is an ICE-lite
// These candidates will be cleared before the next local gathering
// tsk_list_lock(self->candidates_local);
// tsk_list_clear_items(self->candidates_local);
// tsk_list_unlock(self->candidates_local);
-
+
// restore "is_cancelled" until next cancel
// set "is_active" to false to allow ICE re-start
// self->is_cancelled = tsk_false;
// self->is_active = tsk_false;
-
+
// alert user
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_cancelled, "Cancelled");
-
+
return 0;
-
+
}
// Any -> (GatheringComplet) -> GatheringCompleted
@@ -1814,25 +1812,25 @@ static int _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet(va_list
int ret = 0;
tnet_ice_ctx_t* self;
tsk_bool_t has_remote_candidates;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
// alert user
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_completed, "Gathering candidates completed");
-
- if (self->is_started){
+
+ if (self->is_started) {
tsk_list_lock(self->candidates_remote);
has_remote_candidates = !TSK_LIST_IS_EMPTY(self->candidates_remote);
tsk_list_unlock(self->candidates_remote);
-
- if (has_remote_candidates){
+
+ if (has_remote_candidates) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck);
}
}
- else{
+ else {
return -1;
}
-
+
return ret;
}
@@ -1861,42 +1859,42 @@ static int _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck(va_li
void* recvfrom_buff_ptr = tsk_null;
tsk_size_t recvfrom_buff_size = 0, tries_count = 0, tries_count_min = kIceConnCheckMinTriesMin;
enum tnet_stun_state_e e_state;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
self->is_connchecking = tsk_true;
-
+
// "tries_count" and "tries_count_min"
// The connection checks to to the "relay", "prflx", "srflx" and "host" candidates are sent at the same time.
// Because the requests are sent at the same time it's possible to have success check for "relay" (or "srflx") candidates before the "host" candidates.
// "tries_count_min" is the minimum (if success check is not for "host" candidates) tries before giving up.
// The pairs are already sorted ("host"->"srflx"->"prflx", "relay") to make sure to choose the best candidates when there are more than one success conncheck.
-
+
start_conneck:
role_conflict = tsk_false;
restart_conneck = tsk_false;
-
+
tsk_list_lock(self->candidates_pairs);
tsk_list_clear_items(self->candidates_pairs);
tsk_list_unlock(self->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
if ((ret = _tnet_ice_ctx_build_pairs(self, self->candidates_local, self->candidates_remote, self->candidates_pairs, self->is_controlling, self->tie_breaker, self->is_ice_jingle, self->use_rtcpmux))) {
TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
goto bail;
}
-
+
#define _FD_ISSET(_fds, _fds_count, _fd, _isset) { uint16_t __i; *_isset = 0; for (__i = 0; __i < _fds_count; ++__i) { if (_fds[__i] == _fd) { *_isset = 1; break; } } }
-
+
// load fds for both rtp and rtcp sockets / create TURN permissions
tsk_list_lock(self->candidates_pairs);
- tsk_list_foreach(item, self->candidates_pairs){
- if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket){
+ tsk_list_foreach(item, self->candidates_pairs) {
+ if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket) {
continue;
}
-
+
if ((fds_count < sizeof(fds) / sizeof(fds[0])) && pair->candidate_offer->socket) {
if (pair->candidate_offer->turn.ss && (ret = tnet_turn_session_get_state_createperm(pair->candidate_offer->turn.ss, pair->turn_peer_id, &e_state)) == 0) {
if (e_state == tnet_stun_state_none) {
@@ -1924,21 +1922,21 @@ start_conneck:
}
}
tsk_list_unlock(self->candidates_pairs);
-
+
concheck_timeout = self->concheck_timeout;
time_start = time_curr = tsk_time_now();
time_end = (time_start + concheck_timeout);
tries_count_min = fds_turn_count > 0 ? kIceConnCheckMinTriesMax : kIceConnCheckMinTriesMin;
-
+
while (self->is_started && self->is_active && (time_curr < time_end) && !self->have_nominated_symetric) {
tv.tv_sec = 0;
tv.tv_usec = (rto * 1000);
-
+
FD_ZERO(&set);
for (k = 0; k < fds_count; ++k) {
FD_SET(fds[k], &set);
}
-
+
// set new current time here to avoid "continue" skips
// ignore already ellapsed time if new timeout value is defined
time_curr = tsk_time_now();
@@ -1947,7 +1945,7 @@ start_conneck:
time_start = time_curr;
time_end = (time_start + concheck_timeout);
}
-
+
// Send ConnCheck requests
// the pairs are already sorted by priority (from high to low)
if (!self->have_nominated_symetric) {
@@ -1956,21 +1954,22 @@ start_conneck:
continue;
}
switch (pair->state_offer) {
- case tnet_ice_pair_state_failed:
- case tnet_ice_pair_state_succeed:
- continue;
- default: break;
+ case tnet_ice_pair_state_failed:
+ case tnet_ice_pair_state_succeed:
+ continue;
+ default:
+ break;
}
-
+
ret = tnet_ice_pair_send_conncheck((tnet_ice_pair_t *)pair);
}
}
-
+
if (fds_count == 0) {
tsk_thread_sleep(10);
goto check_nomination;
}
-
+
if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) {
TNET_PRINT_LAST_ERROR("select() failed");
goto bail;
@@ -1986,30 +1985,30 @@ start_conneck:
tnet_fd_t fd = fds[k];
unsigned int len = 0;
tsk_size_t read = 0;
-
+
if (!FD_ISSET(fd, &set)) {
continue;
}
-
+
// Check how many bytes are pending
if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) {
continue;
}
-
- if (len == 0){
+
+ if (len == 0) {
// TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
-
+
// Receive pending data
- if (recvfrom_buff_size < len){
- if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))){
+ if (recvfrom_buff_size < len) {
+ if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))) {
recvfrom_buff_size = 0;
goto bail;
}
recvfrom_buff_size = len;
}
-
+
// receive all messages
while (self->is_started && self->is_active && read < len && ret == 0) {
if ((ret = tnet_sockfd_recvfrom(fd, recvfrom_buff_ptr, recvfrom_buff_size, 0, (struct sockaddr *)&remote_addr)) < 0) {
@@ -2024,13 +2023,13 @@ start_conneck:
len = 0;
continue;
}
-
+
TNET_PRINT_LAST_ERROR("Receiving STUN dgrams failed with errno=%d", err);
goto bail;
}
-
+
read += ret;
-
+
// recv() STUN message (request / response)
ret = tnet_ice_ctx_recv_stun_message(self, recvfrom_buff_ptr, (tsk_size_t)ret, fd, &remote_addr, &role_conflict);
if (ret == 0 && role_conflict) {
@@ -2041,13 +2040,13 @@ start_conneck:
}
}
}
-
- check_nomination:
+
+check_nomination:
// check whether we need to re-start connection checking
if (restart_conneck) {
goto start_conneck;
}
-
+
check_rtcp = (self->use_rtcp && !self->use_rtcpmux);
if (!self->have_nominated_offer) {
self->have_nominated_offer = tnet_ice_pairs_have_nominated_offer(self->candidates_pairs, check_rtcp);
@@ -2060,11 +2059,11 @@ start_conneck:
self->have_nominated_symetric &= (got_hosts || ((tries_count++) >= tries_count_min));
}
} // while (self->is_started...
-
+
// "ret" could be "<>0" if last function used was "select()", "recvfrom()", "ioctlt()"...this is why we set the value to #0.
// if there was an error then, we'll jump to "bail:" and next code is skipped
ret = 0;
-
+
bail:
// move to the next state depending on the conncheck result
if (self->is_started) {
@@ -2081,11 +2080,11 @@ bail:
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
TSK_FREE(recvfrom_buff_ptr);
-
+
self->is_connchecking = tsk_false;
-
+
return ret;
}
@@ -2099,19 +2098,19 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
const tnet_ice_candidate_t *candidate;
tsk_list_t* sessions = tsk_list_create(); // for lock-free TURN sessions destroying
int ret;
-
+
// When destroying TURN sessions the transport is locked by shutdown()
// This function locks "self->candidates_pairs"
// TURN callback locks "self->candidates_pairs"
// TURN callback locks the transport
// => We must not lock the candidates when destroying the TURN session
// Test with WES8 if you want to reproduce the issue
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
tsk_list_lock(self->candidates_pairs);
-
+
// take a reference to the negotiated TURN sessions
ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &pair_offer, &pair_answer_src, &pair_answer_dest);
if (ret == 0) {
@@ -2123,8 +2122,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
TSK_DEBUG_INFO("ICE: nominated symetric RTP pairs: offer:%llu, answer-src:%llu, answser-dest:%llu",
pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0);
}
- if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
-
+ if (ret == 0 && pair_offer) {
+ ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
+ }
+
ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &pair_offer, &pair_answer_src, &pair_answer_dest);
if (ret == 0) {
if (pair_offer && pair_offer->candidate_offer && pair_offer->candidate_offer->type_e == tnet_ice_cand_type_relay && pair_offer->candidate_offer->turn.ss) {
@@ -2136,8 +2137,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
self->use_rtcp ? 1 : 0, self->use_rtcpmux ? 1 : 0,
pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0);
}
- if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
-
+ if (ret == 0 && pair_offer) {
+ ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
+ }
+
// collect all useless TURN sessions (pairs)
tsk_list_foreach(item, self->candidates_pairs) {
if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->turn.ss) {
@@ -2148,9 +2151,9 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
TSK_OBJECT_SAFE_FREE(pair->candidate_offer->turn.ss);
}
}
-
+
tsk_list_unlock(self->candidates_pairs);
-
+
// collect all useless TURN sessions (local candidates)
tsk_list_lock(self->candidates_local);
tsk_list_foreach(item, self->candidates_local) {
@@ -2163,7 +2166,7 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
}
}
tsk_list_unlock(self->candidates_local);
-
+
// collect all useless TURN sessions (remote candidates)
tsk_list_lock(self->candidates_remote);
tsk_list_foreach(item, self->candidates_remote) {
@@ -2176,10 +2179,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
}
}
tsk_list_unlock(self->candidates_remote);
-
+
// lock-free destruction
TSK_OBJECT_SAFE_FREE(sessions);
-
+
return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_conncheck_succeed, "ConnCheck succeed");
}
@@ -2203,15 +2206,15 @@ static int _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted(va_list *app)
static int _tnet_ice_ctx_fsm_OnTerminated(tnet_ice_ctx_t* self)
{
TSK_DEBUG_INFO("=== ICE CTX SM Terminated ===");
-
- if (!self){
+
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter.");
return -1;
}
-
+
// still started but no longer active
self->is_active = tsk_false;
-
+
return 0;
}
@@ -2227,10 +2230,10 @@ static int _tnet_ice_ctx_restart(tnet_ice_ctx_t* self)
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
ret = tsk_fsm_set_current_state(self->fsm, _fsm_state_Started);
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates);
-
+
self->is_active = (ret == 0);
return ret;
}
@@ -2243,9 +2246,9 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
*role_conflict = tsk_false;
-
+
if (!TNET_STUN_BUFF_IS_STUN2(((uint8_t*)data), size)) {
if (self->rtp_callback) {
return self->rtp_callback(self->rtp_callback_data, data, size, local_fd, remote_addr);
@@ -2253,12 +2256,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
TSK_DEBUG_INFO("Not STUN message");
return 0;
}
-
+
if (!self->is_active) {
TSK_DEBUG_INFO("ICE context not active yet");
return 0;
}
-
+
if ((ret = tnet_stun_pkt_read(data, size, &message)) == 0 && message) {
if (message->e_type == tnet_stun_pkt_type_binding_request) {
tsk_bool_t is_local_conncheck_started;
@@ -2278,7 +2281,7 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
if (!pair && is_local_conncheck_started) {
pair = tnet_ice_pairs_find_by_fd_and_addr(self->candidates_pairs, local_fd, remote_addr);
}
- if (!pair && !self->have_nominated_symetric && is_local_conncheck_started){ // pair not found and we're still negotiating
+ if (!pair && !self->have_nominated_symetric && is_local_conncheck_started) { // pair not found and we're still negotiating
// rfc 5245 - 7.1.3.2.1. Discovering Peer Reflexive Candidates
tnet_ice_pair_t* pair_peer = tnet_ice_pair_prflx_create(self->candidates_pairs, local_fd, remote_addr);
if (pair_peer) {
@@ -2292,12 +2295,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
char* resp_phrase = tsk_null;
// authenticate the request
tnet_ice_pair_auth_conncheck(pair, message, data, size, &resp_code, &resp_phrase);
- if (resp_code > 0 && resp_phrase){
- if (resp_code >= 200 && resp_code <= 299){
+ if (resp_code > 0 && resp_phrase) {
+ if (resp_code >= 200 && resp_code <= 299) {
// Before sending the success response check that there are no role conflict
- if (self->is_controlling){ // I'm ICE-CONTROLLING
+ if (self->is_controlling) { // I'm ICE-CONTROLLING
const tnet_stun_attr_vdata_t* stun_att_ice_controlling;
- if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling){
+ if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling) {
TSK_DEBUG_WARN("Role conflicts (SEND)");
if (self->tie_breaker >= *((uint64_t*)stun_att_ice_controlling->p_data_ptr)) {
resp_code = kStunErrCodeIceConflict;
@@ -2363,13 +2366,13 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
}
}
TSK_OBJECT_SAFE_FREE(message);
-
+
return ret;
}
static int _tnet_ice_ctx_send_turn_raw(struct tnet_ice_ctx_s* self, struct tnet_turn_session_s* turn_ss, tnet_turn_peer_id_t turn_peer_id, const void* data, tsk_size_t size)
{
- if (!self || !turn_ss || !data || !size){
+ if (!self || !turn_ss || !data || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -2386,21 +2389,21 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
tnet_ice_pair_t *pair;
enum tnet_turn_transport_e e_req_transport;
tnet_family_t addr_family_local, addr_family_remote;
-
+
if (!self || TSK_LIST_IS_EMPTY(local_candidates) || TSK_LIST_IS_EMPTY(remote_candidates) || !result_pairs) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->is_building_pairs = tsk_true;
TSK_DEBUG_INFO("ICE: begin building pairs(is_rtcpmuxed=%d)", is_rtcpmuxed);
-
+
tsk_list_clear_items(result_pairs);
-
+
tsk_list_lock(local_candidates);
tsk_list_lock(remote_candidates);
tsk_list_lock(result_pairs);
-
+
tsk_list_foreach(item_local, local_candidates) {
if (!(cand_local = item_local->data)) {
continue;
@@ -2413,7 +2416,7 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
continue;
}
#endif
-
+
tsk_list_foreach(item_remote, remote_candidates) {
if (!(cand_remote = item_remote->data)) {
continue;
@@ -2423,9 +2426,9 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
TSK_DEBUG_INFO("Skipping remote ICE candidate with port = 0");
continue;
}
-
+
// CompIds(1=RTP, 2=RTCP) must match
- if ((cand_remote->comp_id != cand_local->comp_id)){
+ if ((cand_remote->comp_id != cand_local->comp_id)) {
continue;
}
// IP versions must match. Cannot use IPv4 socket to send/recv to IPv6 address.
@@ -2453,18 +2456,18 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
continue;
}
}
-
+
if ((pair = tnet_ice_pair_create(cand_local, cand_remote, is_controlling, tie_breaker, is_ice_jingle))) {
TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %u %s %d] -> [%s %u %u %s %d]",
pair->id,
pair->priority,
-
+
cand_local->foundation,
cand_local->priority,
cand_local->comp_id,
cand_local->connection_addr,
cand_local->port,
-
+
cand_remote->foundation,
cand_remote->priority,
cand_remote->comp_id,
@@ -2479,31 +2482,31 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
if (!(pair = item_local->data)) {
continue;
}
-
+
TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %s %d] -> [%s %u %s %d]",
pair->id,
pair->priority,
-
+
pair->candidate_offer->foundation,
pair->candidate_offer->comp_id,
pair->candidate_offer->connection_addr,
pair->candidate_offer->port,
-
+
pair->candidate_answer->foundation,
pair->candidate_answer->comp_id,
pair->candidate_answer->connection_addr,
pair->candidate_answer->port);
}
#endif
-
+
tsk_list_unlock(local_candidates);
tsk_list_unlock(remote_candidates);
tsk_list_unlock(result_pairs);
-
+
self->is_building_pairs = tsk_false;
tsk_condwait_broadcast(self->condwait_pairs);
TSK_DEBUG_INFO("ICE: end building pairs");
-
+
return 0;
}
@@ -2514,32 +2517,32 @@ static int _tnet_ice_ctx_fsm_act(tnet_ice_ctx_t* self, tsk_fsm_action_id action_
tnet_ice_event_t* e = tsk_null;
static const char* phrase = "$action$";
int ret = 0;
-
- if (!self || !self->fsm){
+
+ if (!self || !self->fsm) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
- if (!(action = tnet_ice_action_create(action_id))){
+ if (!(action = tnet_ice_action_create(action_id))) {
TSK_DEBUG_ERROR("Failed to create action");
return -2;
}
-
+
if (self->is_sync_mode) {
ret = tsk_fsm_act(self->fsm, action->id, self, action, self, action);
}
else {
- if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))){
+ if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))) {
tnet_ice_event_set_action(e, action);
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e);
goto bail;
}
- else{
+ else {
TSK_DEBUG_ERROR("Failed to create ICE event");
ret = -2;
goto bail;
}
}
-
+
bail:
TSK_OBJECT_SAFE_FREE(e);
TSK_OBJECT_SAFE_FREE(action);
@@ -2549,21 +2552,21 @@ bail:
static int _tnet_ice_ctx_signal_async(tnet_ice_ctx_t* self, tnet_ice_event_type_t type, const char* phrase)
{
tnet_ice_event_t* e;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
if (self->is_silent_mode && type != tnet_ice_event_type_action) { // silent mode ON and not action to move the FSM
TSK_DEBUG_INFO("ICE silent mode ON...to not notify '%d:%s'", type, phrase);
return 0;
}
-
- if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))){
+
+ if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))) {
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e);
return 0;
}
- else{
+ else {
TSK_DEBUG_ERROR("Failed to create ICE event");
return -2;
}
@@ -2574,114 +2577,110 @@ static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs *
tnet_ice_ctx_t *ctx = tsk_object_ref(TSK_OBJECT(e->pc_usr_data));
struct tnet_turn_session_s* session = tsk_object_ref(TSK_OBJECT(e->pc_session));
int ret = 0;
-
+
if (!ctx) {
// the ICE context is being destroyed but TURN session not freed yet
goto bail;
}
-
+
switch (e->e_type) {
- case tnet_turn_session_event_type_alloc_ok:
- case tnet_turn_session_event_type_refresh_ok:
- case tnet_turn_session_event_type_chanbind_ok:
- case tnet_turn_session_event_type_connect_ok:
- default:
- {
- break;
- }
-
- case tnet_turn_session_event_type_alloc_nok:
- case tnet_turn_session_event_type_refresh_nok:
- case tnet_turn_session_event_type_perm_nok:
- case tnet_turn_session_event_type_chanbind_nok:
- case tnet_turn_session_event_type_connect_nok:
- {
- // Do not raise error event if no nominated candidate because
- // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case.
- if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) {
- TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id);
- if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) {
- goto bail;
- }
+ case tnet_turn_session_event_type_alloc_ok:
+ case tnet_turn_session_event_type_refresh_ok:
+ case tnet_turn_session_event_type_chanbind_ok:
+ case tnet_turn_session_event_type_connect_ok:
+ default: {
+ break;
+ }
+
+ case tnet_turn_session_event_type_alloc_nok:
+ case tnet_turn_session_event_type_refresh_nok:
+ case tnet_turn_session_event_type_perm_nok:
+ case tnet_turn_session_event_type_chanbind_nok:
+ case tnet_turn_session_event_type_connect_nok: {
+ // Do not raise error event if no nominated candidate because
+ // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case.
+ if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) {
+ TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id);
+ if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) {
+ goto bail;
}
- break;
}
-
- case tnet_turn_session_event_type_perm_ok:
- {
- enum tnet_turn_transport_e e_req_transport;
- if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) {
+ break;
+ }
+
+ case tnet_turn_session_event_type_perm_ok: {
+ enum tnet_turn_transport_e e_req_transport;
+ if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) {
+ goto bail;
+ }
+
+ if (e_req_transport == tnet_turn_transport_tcp) {
+ // TCP-Connect: rfc6062 - 4.3. Initiating a Connection
+ if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) {
goto bail;
}
-
- if (e_req_transport == tnet_turn_transport_tcp) {
- // TCP-Connect: rfc6062 - 4.3. Initiating a Connection
- if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) {
- goto bail;
- }
+ }
+ else {
+ // Bind a channel (not required). If succeed, will be used to save bandwidth usage.
+ // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed.
+ if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) {
+ goto bail;
}
- else {
- // Bind a channel (not required). If succeed, will be used to save bandwidth usage.
- // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed.
- if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) {
- goto bail;
+ }
+ break;
+ }
+
+ case tnet_turn_session_event_type_recv_data: {
+ tsk_bool_t role_conflict;
+ tnet_ice_pair_t* pair = tsk_null;
+ if (e->u_peer_id != kTurnPeerIdInvalid) {
+ const tsk_list_item_t *item;
+ tsk_list_lock(ctx->candidates_pairs);
+ tsk_list_foreach(item, ctx->candidates_pairs) {
+ if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) {
+ pair = tsk_object_ref((void*)item->data);
+ break;
}
}
- break;
+ tsk_list_unlock(ctx->candidates_pairs);
}
-
- case tnet_turn_session_event_type_recv_data:
- {
- tsk_bool_t role_conflict;
- tnet_ice_pair_t* pair = tsk_null;
- if (e->u_peer_id != kTurnPeerIdInvalid) {
- const tsk_list_item_t *item;
- tsk_list_lock(ctx->candidates_pairs);
- tsk_list_foreach(item, ctx->candidates_pairs) {
- if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) {
- pair = tsk_object_ref((void*)item->data);
- break;
- }
- }
- tsk_list_unlock(ctx->candidates_pairs);
- }
-
- ret = _tnet_ice_ctx_recv_stun_message_for_pair(
- ctx,
- pair,
- e->data.pc_data_ptr, e->data.u_data_size,
- e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD,
- e->pc_enet ? &e->pc_enet->remote_addr : tsk_null,
- &role_conflict);
- TSK_OBJECT_SAFE_FREE(pair);
- if (ret) {
+
+ ret = _tnet_ice_ctx_recv_stun_message_for_pair(
+ ctx,
+ pair,
+ e->data.pc_data_ptr, e->data.u_data_size,
+ e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD,
+ e->pc_enet ? &e->pc_enet->remote_addr : tsk_null,
+ &role_conflict);
+ TSK_OBJECT_SAFE_FREE(pair);
+ if (ret) {
+ goto bail;
+ }
+
+ // rebuild candidates if role conflict
+ if (role_conflict) {
+ tsk_list_lock(ctx->candidates_pairs);
+ tsk_list_clear_items(ctx->candidates_pairs);
+ tsk_list_unlock(ctx->candidates_pairs);
+
+ TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
+ TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
+
+ if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) {
+ TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
goto bail;
}
-
- // rebuild candidates if role conflict
- if (role_conflict) {
- tsk_list_lock(ctx->candidates_pairs);
- tsk_list_clear_items(ctx->candidates_pairs);
- tsk_list_unlock(ctx->candidates_pairs);
-
- TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
- TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
-
- if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) {
- TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
- goto bail;
- }
- }
-
- break;
}
+
+ break;
}
-
+ }
+
// alert() waiting threads
if ((ret = tsk_condwait_broadcast(ctx->turn.condwait))) {
goto bail;
}
-
+
bail:
tsk_object_unref(ctx);
tsk_object_unref(session);
@@ -2694,42 +2693,40 @@ static void* TSK_STDCALL _tnet_ice_ctx_run(void* self)
tsk_list_item_t *curr;
tnet_ice_ctx_t *ctx = (tnet_ice_ctx_t *)(self);
tnet_ice_event_t *e;
-
+
TSK_DEBUG_INFO("ICE CTX::run -- START");
-
+
TSK_RUNNABLE_RUN_BEGIN(ctx);
-
+
// must because "ctx->callback(e);" could call a function trying to free "ctx"
// do not move before "TSK_RUNNABLE_RUN_BEGIN(ctx)", otherwise it'll be required to stop the "runnable" to have "ctx->refCount==0"
ctx = tsk_object_ref(ctx);
-
+
if (ctx->is_started && (curr = TSK_RUNNABLE_POP_FIRST(ctx))) {
e = (tnet_ice_event_t*)curr->data;
switch (e->type) {
- case tnet_ice_event_type_action:
- {
- if (e->action) {
- tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action);
- }
- break;
+ case tnet_ice_event_type_action: {
+ if (e->action) {
+ tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action);
}
- default:
- {
- if (ctx->callback){
- ctx->callback(e);
- }
- break;
+ break;
+ }
+ default: {
+ if (ctx->callback) {
+ ctx->callback(e);
}
+ break;
+ }
}
tsk_object_unref(curr);
}
-
+
if (!(ctx = tsk_object_unref(ctx))) {
goto exit;
}
-
+
TSK_RUNNABLE_RUN_END(ctx);
-
+
exit:
if (ctx) {
tsk_list_clear_items(ctx->candidates_local);
@@ -2738,9 +2735,9 @@ exit:
tsk_list_clear_items(ctx->candidates_pairs);
tsk_list_unlock(ctx->candidates_pairs);
}
-
+
TSK_DEBUG_INFO("ICE CTX::run -- STOP");
-
+
return 0;
}
@@ -2768,7 +2765,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
// TURN requires credentials
if ((e_proto & tnet_ice_server_proto_turn) == tnet_ice_server_proto_turn && (tsk_strnullORempty(str_username) || tsk_strnullORempty(str_password))) {
/* rfc5766 - 4. General Behavior
@@ -2791,7 +2788,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
}
tsk_list_push_back_data(self->servers, (void**)&ice_server);
TSK_OBJECT_SAFE_FREE(ice_server);
-
+
ret = 0;
bail:
tsk_list_unlock(self->servers);
OpenPOWER on IntegriCloud