@@ -92,6 +92,7 @@ juice_agent_t *agent_create(const juice_config_t *config) {
9292	}
9393
9494	bool  alloc_failed  =  false;
95+ 	agent -> ice_tcp_mode  =  JUICE_ICE_TCP_MODE_NONE ;
9596	agent -> config .concurrency_mode  =  config -> concurrency_mode ;
9697	agent -> config .stun_server_host  =  alloc_string_copy (config -> stun_server_host , & alloc_failed );
9798	agent -> config .stun_server_port  =  config -> stun_server_port ;
@@ -211,6 +212,20 @@ static thread_return_t THREAD_CALL resolver_thread_entry(void *arg) {
211212	return  (thread_return_t )0 ;
212213}
213214
215+ void  agent_add_ice_tcp_local_candidate (juice_agent_t  * agent , addr_record_t  * record ) {
216+ 	ice_candidate_t  candidate ;
217+ 	if  (ice_create_local_candidate (ICE_CANDIDATE_TYPE_HOST , 1 , agent -> local .candidates_count , record , & candidate , ICE_CANDIDATE_TRANSPORT_TCP_TYPE_ACTIVE )) {
218+         JLOG_ERROR ("Failed to create ice-tcp candidate" );
219+ 		return ;
220+ 	}
221+ 
222+ 	if  (ice_add_candidate (& candidate , & agent -> local )) {
223+ 		JLOG_ERROR ("Failed to add ice-tcp candidate to local description" );
224+ 	}
225+ 
226+ 	return ;
227+ }
228+ 
214229int  agent_gather_candidates (juice_agent_t  * agent ) {
215230	JLOG_VERBOSE ("Gathering candidates" );
216231	if  (agent -> conn_impl ) {
@@ -252,7 +267,7 @@ int agent_gather_candidates(juice_agent_t *agent) {
252267	for  (int  i  =  0 ; i  <  records_count ; ++ i ) {
253268		ice_candidate_t  candidate ;
254269		if  (ice_create_local_candidate (ICE_CANDIDATE_TYPE_HOST , 1 , agent -> local .candidates_count ,
255- 		                               records  +  i , & candidate )) {
270+ 		                               records  +  i , & candidate ,  ICE_CANDIDATE_TRANSPORT_UDP )) {
256271			JLOG_ERROR ("Failed to create host candidate" );
257272			continue ;
258273		}
@@ -266,6 +281,15 @@ int agent_gather_candidates(juice_agent_t *agent) {
266281		}
267282	}
268283
284+ 	if  (agent -> ice_tcp_mode  ==  JUICE_ICE_TCP_MODE_ACTIVE ) {
285+ 		if  (records_count  >  0 ) {
286+ 			addr_set_port ((struct  sockaddr  * )& records [0 ].addr , 9 );
287+ 			agent_add_ice_tcp_local_candidate (agent , & records [0 ]);
288+ 		} else  {
289+ 			JLOG_WARN ("No local host candidates gathered, unable to add ice-tcp" );
290+ 		}
291+ 	}
292+ 
269293	ice_sort_candidates (& agent -> local );
270294
271295	for  (int  i  =  0 ; i  <  agent -> entries_count ; ++ i )
@@ -341,7 +365,7 @@ int agent_resolve_servers(juice_agent_t *agent) {
341365			conn_unlock (agent );
342366
343367			addr_record_t  records [DEFAULT_MAX_RECORDS_COUNT ];
344- 			int  records_count  =  addr_resolve (hostname , service , records , DEFAULT_MAX_RECORDS_COUNT );
368+ 			int  records_count  =  addr_resolve (hostname , service , SOCK_DGRAM ,  records , DEFAULT_MAX_RECORDS_COUNT );
345369
346370			conn_lock (agent );
347371
@@ -426,7 +450,7 @@ int agent_resolve_servers(juice_agent_t *agent) {
426450		conn_unlock (agent );
427451
428452		addr_record_t  records [MAX_STUN_SERVER_RECORDS_COUNT ];
429- 		int  records_count  =  addr_resolve (hostname , service , records , MAX_STUN_SERVER_RECORDS_COUNT );
453+ 		int  records_count  =  addr_resolve (hostname , service , SOCK_DGRAM ,  records , MAX_STUN_SERVER_RECORDS_COUNT );
430454
431455		conn_lock (agent );
432456
@@ -825,6 +849,34 @@ int agent_input(juice_agent_t *agent, char *buf, size_t len, const addr_record_t
825849	return  -1 ;
826850}
827851
852+ void  agent_register_entry_for_candidate_pair (juice_agent_t  * agent , ice_candidate_pair_t  * pair , agent_stun_entry_t  * relay_entry ) {
853+ 	JLOG_VERBOSE ("Registering STUN entry %d for candidate pair checking" , agent -> entries_count );
854+ 	agent_stun_entry_t  * entry  =  agent -> entries  +  agent -> entries_count ;
855+ 	entry -> type  =  AGENT_STUN_ENTRY_TYPE_CHECK ;
856+ 	entry -> state  =  AGENT_STUN_ENTRY_STATE_IDLE ;
857+ 	entry -> mode  =  AGENT_MODE_UNKNOWN ;
858+ 	entry -> pair  =  pair ;
859+ 	entry -> record  =  pair -> remote -> resolved ;
860+ 	entry -> relay_entry  =  relay_entry ;
861+ 	juice_random (entry -> transaction_id , STUN_TRANSACTION_ID_SIZE );
862+ 	entry -> transaction_id_expired  =  false;
863+ 	++ agent -> entries_count ;
864+ 
865+ 	if  (pair -> remote -> type  ==  ICE_CANDIDATE_TYPE_HOST )
866+ 		agent_translate_host_candidate_entry (agent , entry );
867+ }
868+ 
869+ void  agent_tcp_conn_connected (juice_agent_t  * agent ) {
870+ 	for  (int  i  =  0 ; i  <  agent -> entries_count ; ++ i ) {
871+ 		agent_stun_entry_t  * entry  =  agent -> entries  +  i ;
872+ 		if  (entry -> pair -> remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_UDP ) {
873+ 			entry -> pair -> tcp_connected  =  true;
874+ 			entry -> next_transmission  =  current_timestamp ();
875+ 		}
876+ 	}
877+ 	conn_interrupt (agent );
878+ }
879+ 
828880int  agent_bookkeeping (juice_agent_t  * agent , timestamp_t  * next_timestamp ) {
829881	JLOG_VERBOSE ("Bookkeeping..." );
830882
@@ -837,8 +889,10 @@ int agent_bookkeeping(juice_agent_t *agent, timestamp_t *next_timestamp) {
837889	for  (int  i  =  0 ; i  <  agent -> entries_count ; ++ i ) {
838890		agent_stun_entry_t  * entry  =  agent -> entries  +  i ;
839891
840- 		// STUN requests transmission or retransmission 
841- 		if  (entry -> state  ==  AGENT_STUN_ENTRY_STATE_PENDING ) {
892+ 		if  (entry -> pair  &&  entry -> pair -> remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_UDP  &&  entry -> pair -> tcp_connected  ==  false) {
893+ 			conn_tcp_connect (agent , & entry -> pair -> remote -> resolved , agent_tcp_conn_connected );
894+ 			entry -> next_transmission  =  now  +  LAST_STUN_RETRANSMISSION_TIMEOUT ;
895+ 		} else  if  (entry -> state  ==  AGENT_STUN_ENTRY_STATE_PENDING ) { // STUN requests transmission or retransmission 
842896			if  (entry -> next_transmission  >  now )
843897				continue ;
844898
@@ -1629,7 +1683,7 @@ int agent_send_stun_binding(juice_agent_t *agent, agent_stun_entry_t *entry, stu
16291683			                ? (int )(entry -> pair -> local  -  agent -> local .candidates )
16301684			                : 0 ;
16311685			msg .priority  = 
1632- 			    ice_compute_priority (ICE_CANDIDATE_TYPE_PEER_REFLEXIVE , family , 1 , index );
1686+ 			    ice_compute_priority (ICE_CANDIDATE_TYPE_PEER_REFLEXIVE , family , 1 , index , false );
16331687
16341688			// RFC 8445 8.1.1. Nominating Pairs: 
16351689			// Once the controlling agent has picked a valid pair for nomination, it repeats the 
@@ -2177,7 +2231,7 @@ int agent_add_local_relayed_candidate(juice_agent_t *agent, const addr_record_t
21772231	}
21782232	ice_candidate_t  candidate ;
21792233	if  (ice_create_local_candidate (ICE_CANDIDATE_TYPE_RELAYED , 1 , agent -> local .candidates_count ,
2180- 	                               record , & candidate )) {
2234+ 	                               record , & candidate ,  ICE_CANDIDATE_TRANSPORT_UDP )) {
21812235		JLOG_ERROR ("Failed to create relayed candidate" );
21822236		return  -1 ;
21832237	}
@@ -2220,7 +2274,7 @@ int agent_add_local_reflexive_candidate(juice_agent_t *agent, ice_candidate_type
22202274		return  0 ;
22212275	}
22222276	ice_candidate_t  candidate ;
2223- 	if  (ice_create_local_candidate (type , 1 , agent -> local .candidates_count , record , & candidate )) {
2277+ 	if  (ice_create_local_candidate (type , 1 , agent -> local .candidates_count , record , & candidate ,  ICE_CANDIDATE_TRANSPORT_UDP )) {
22242278		JLOG_ERROR ("Failed to create reflexive candidate" );
22252279		return  -1 ;
22262280	}
@@ -2260,7 +2314,7 @@ int agent_add_remote_reflexive_candidate(juice_agent_t *agent, ice_candidate_typ
22602314		return  0 ;
22612315	}
22622316	ice_candidate_t  candidate ;
2263- 	if  (ice_create_local_candidate (type , 1 , agent -> local .candidates_count , record , & candidate )) {
2317+ 	if  (ice_create_local_candidate (type , 1 , agent -> local .candidates_count , record , & candidate ,  ICE_CANDIDATE_TRANSPORT_UDP )) {
22642318		JLOG_ERROR ("Failed to create reflexive candidate" );
22652319		return  -1 ;
22662320	}
@@ -2297,6 +2351,26 @@ int agent_add_candidate_pair(juice_agent_t *agent, ice_candidate_t *local, // lo
22972351		return  -1 ;
22982352	}
22992353
2354+ 	if  (remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_UDP ) {
2355+ 		if  (agent -> ice_tcp_mode  !=  JUICE_ICE_TCP_MODE_ACTIVE ) {
2356+ 			JLOG_WARN ("ICE-TCP is disabled ignoring TCP Candidate" );
2357+ 			return  0 ;
2358+ 		}
2359+ 
2360+ 		if  (remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_TCP_TYPE_PASSIVE  &&  remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_TCP_TYPE_SO ) {
2361+ 			JLOG_INFO ("Ignoring ICE-TCP Candidate that is not passive or simultaneous open" );
2362+ 			return  0 ;
2363+ 		}
2364+ 
2365+ 		for  (int  i  =  0 ; i  <  agent -> candidate_pairs_count ; ++ i ) {
2366+ 			ice_candidate_pair_t  * pair  =  & agent -> candidate_pairs [i ];
2367+ 			if  (pair -> remote -> transport  !=  ICE_CANDIDATE_TRANSPORT_UDP ) {
2368+ 				JLOG_INFO ("Only one ICE-TCP remote candidate is supported ignoring TCP Candidate" );
2369+ 				return  0 ;
2370+ 			}
2371+ 		}
2372+ 	}
2373+ 
23002374	JLOG_VERBOSE ("Adding new candidate pair, priority=%"  PRIu64 , pair .priority );
23012375
23022376	// Add pair 
@@ -2327,20 +2401,7 @@ int agent_add_candidate_pair(juice_agent_t *agent, ice_candidate_t *local, // lo
23272401		}
23282402	}
23292403
2330- 	JLOG_VERBOSE ("Registering STUN entry %d for candidate pair checking" , agent -> entries_count );
2331- 	agent_stun_entry_t  * entry  =  agent -> entries  +  agent -> entries_count ;
2332- 	entry -> type  =  AGENT_STUN_ENTRY_TYPE_CHECK ;
2333- 	entry -> state  =  AGENT_STUN_ENTRY_STATE_IDLE ;
2334- 	entry -> mode  =  AGENT_MODE_UNKNOWN ;
2335- 	entry -> pair  =  pos ;
2336- 	entry -> record  =  pos -> remote -> resolved ;
2337- 	entry -> relay_entry  =  relay_entry ;
2338- 	juice_random (entry -> transaction_id , STUN_TRANSACTION_ID_SIZE );
2339- 	entry -> transaction_id_expired  =  false;
2340- 	++ agent -> entries_count ;
2341- 
2342- 	if  (remote -> type  ==  ICE_CANDIDATE_TYPE_HOST )
2343- 		agent_translate_host_candidate_entry (agent , entry );
2404+ 	agent_register_entry_for_candidate_pair (agent , pos , relay_entry );
23442405
23452406	if  (agent -> mode  ==  AGENT_MODE_CONTROLLING ) {
23462407		for  (int  i  =  0 ; i  <  agent -> candidate_pairs_count ; ++ i ) {
@@ -2623,6 +2684,17 @@ agent_stun_entry_t *agent_find_entry_from_record(juice_agent_t *agent, const add
26232684	return  NULL ;
26242685}
26252686
2687+ int  agent_set_ice_tcp_mode (juice_agent_t  * agent , juice_ice_tcp_mode_t  ice_tcp_mode )
2688+ {
2689+ 	if  (agent -> conn_impl ) {
2690+ 		JLOG_WARN ("Unable to set ICE attributes, candidates gathering already started" );
2691+ 		return  JUICE_ERR_FAILED ;
2692+ 	}
2693+ 
2694+ 	agent -> ice_tcp_mode  =  ice_tcp_mode ;
2695+ 	return  JUICE_ERR_SUCCESS ;
2696+ }
2697+ 
26262698void  agent_translate_host_candidate_entry (juice_agent_t  * agent , agent_stun_entry_t  * entry ) {
26272699	if  (!entry -> pair  ||  entry -> pair -> remote -> type  !=  ICE_CANDIDATE_TYPE_HOST )
26282700		return ;
0 commit comments