Commit 69749bad authored by Olivier Crête's avatar Olivier Crête

component: Clear turn local candidates when clearing turn servers

But keep the turn connection that's currently being used if it is
the selected candidate. Also clear the TURN candidate refresh.
parent 8ccbd8f0
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "debug.h" #include "debug.h"
#include "component.h" #include "component.h"
#include "discovery.h"
#include "agent-priv.h" #include "agent-priv.h"
...@@ -148,9 +149,48 @@ component_new (guint id, NiceAgent *agent, Stream *stream) ...@@ -148,9 +149,48 @@ component_new (guint id, NiceAgent *agent, Stream *stream)
void void
component_clean_turn_servers (Component *cmp) component_clean_turn_servers (Component *cmp)
{ {
GSList *i;
g_list_free_full (cmp->turn_servers, (GDestroyNotify) turn_server_unref); g_list_free_full (cmp->turn_servers, (GDestroyNotify) turn_server_unref);
cmp->turn_servers = NULL; cmp->turn_servers = NULL;
for (i = cmp->local_candidates; i;) {
NiceCandidate *candidate = i->data;
GSList *next = i->next;
if (candidate->type != NICE_CANDIDATE_TYPE_RELAYED) {
i = next;
continue;
}
/* note: do not remove the remote candidate that is
* currently part of the 'selected pair', see ICE
* 9.1.1.1. "ICE Restarts" (ID-19)
*
* So what we do instead is that we put the selected candidate
* in a special location and keep it "alive" that way. This is
* especially important for TURN, because refresh requests to the
* server need to keep happening.
*/
if (candidate == cmp->selected_pair.local) {
if (cmp->turn_candidate) {
refresh_prune_candidate (cmp->agent, cmp->turn_candidate);
component_detach_socket (cmp, cmp->turn_candidate->sockptr);
nice_candidate_free (cmp->turn_candidate);
}
/* Bring the priority down to 0, so that it will be replaced
* on the new run.
*/
cmp->selected_pair.priority = 0;
cmp->turn_candidate = candidate;
} else {
refresh_prune_candidate (cmp->agent, candidate);
component_detach_socket (cmp, candidate->sockptr);
nice_candidate_free (candidate);
}
cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i);
i = next;
}
} }
void void
...@@ -174,6 +214,10 @@ component_free (Component *cmp) ...@@ -174,6 +214,10 @@ component_free (Component *cmp)
nice_candidate_free (cmp->restart_candidate), nice_candidate_free (cmp->restart_candidate),
cmp->restart_candidate = NULL; cmp->restart_candidate = NULL;
if (cmp->turn_candidate)
nice_candidate_free (cmp->turn_candidate),
cmp->turn_candidate = NULL;
for (i = cmp->incoming_checks; i; i = i->next) { for (i = cmp->incoming_checks; i; i = i->next) {
IncomingCheck *icheck = i->data; IncomingCheck *icheck = i->data;
g_free (icheck->username); g_free (icheck->username);
...@@ -181,9 +225,12 @@ component_free (Component *cmp) ...@@ -181,9 +225,12 @@ component_free (Component *cmp)
} }
g_slist_free (cmp->local_candidates); g_slist_free (cmp->local_candidates);
cmp->local_candidates = NULL;
g_slist_free (cmp->remote_candidates); g_slist_free (cmp->remote_candidates);
cmp->remote_candidates = NULL;
component_free_socket_sources (cmp); component_free_socket_sources (cmp);
g_slist_free (cmp->incoming_checks); g_slist_free (cmp->incoming_checks);
cmp->incoming_checks = NULL;
component_clean_turn_servers (cmp); component_clean_turn_servers (cmp);
...@@ -285,7 +332,7 @@ component_restart (Component *cmp) ...@@ -285,7 +332,7 @@ component_restart (Component *cmp)
for (i = cmp->remote_candidates; i; i = i->next) { for (i = cmp->remote_candidates; i; i = i->next) {
NiceCandidate *candidate = i->data; NiceCandidate *candidate = i->data;
/* note: do not remove the remote candidate that is /* note: do not remove the local candidate that is
* currently part of the 'selected pair', see ICE * currently part of the 'selected pair', see ICE
* 9.1.1.1. "ICE Restarts" (ID-19) */ * 9.1.1.1. "ICE Restarts" (ID-19) */
if (candidate == cmp->selected_pair.remote) { if (candidate == cmp->selected_pair.remote) {
......
...@@ -149,7 +149,7 @@ struct _Component ...@@ -149,7 +149,7 @@ struct _Component
CandidatePair selected_pair; /**< independent from checklists, CandidatePair selected_pair; /**< independent from checklists,
see ICE 11.1. "Sending Media" (ID-19) */ see ICE 11.1. "Sending Media" (ID-19) */
NiceCandidate *restart_candidate; /**< for storing active remote candidate during a restart */ NiceCandidate *restart_candidate; /**< for storing active remote candidate during a restart */
NiceCandidate *turn_candidate; /**< for storing active turn candidate if turn servers have been cleared */
/* I/O handling. The main context must always be non-NULL, and is used for all /* I/O handling. The main context must always be non-NULL, and is used for all
* socket recv() operations. All io_callback emissions are invoked in this * socket recv() operations. All io_callback emissions are invoked in this
* context too. * context too.
......
...@@ -1128,6 +1128,14 @@ static gboolean priv_update_selected_pair (NiceAgent *agent, Component *componen ...@@ -1128,6 +1128,14 @@ static gboolean priv_update_selected_pair (NiceAgent *agent, Component *componen
component->selected_pair.keepalive.tick_source = NULL; component->selected_pair.keepalive.tick_source = NULL;
} }
if (component->selected_pair.local &&
component->selected_pair.local == component->turn_candidate) {
refresh_prune_candidate (agent, component->turn_candidate);
component_detach_socket (component, component->turn_candidate->sockptr);
nice_candidate_free (component->turn_candidate);
component->turn_candidate = NULL;
}
memset (&component->selected_pair, 0, sizeof(CandidatePair)); memset (&component->selected_pair, 0, sizeof(CandidatePair));
component->selected_pair.local = pair->local; component->selected_pair.local = pair->local;
component->selected_pair.remote = pair->remote; component->selected_pair.remote = pair->remote;
......
...@@ -206,7 +206,7 @@ void refresh_free (NiceAgent *agent) ...@@ -206,7 +206,7 @@ void refresh_free (NiceAgent *agent)
/* /*
* Prunes the list of discovery processes for items related * Prunes the list of discovery processes for items related
* to stream 'stream_id'. * to stream 'stream_id'.
* *
* @return TRUE on success, FALSE on a fatal error * @return TRUE on success, FALSE on a fatal error
*/ */
...@@ -218,6 +218,9 @@ void refresh_prune_stream (NiceAgent *agent, guint stream_id) ...@@ -218,6 +218,9 @@ void refresh_prune_stream (NiceAgent *agent, guint stream_id)
CandidateRefresh *cand = i->data; CandidateRefresh *cand = i->data;
GSList *next = i->next; GSList *next = i->next;
/* Don't free the candidate refresh to the currently selected local candidate
* unless the whole pair is being destroyed.
*/
if (cand->stream->id == stream_id) { if (cand->stream->id == stream_id) {
agent->refresh_list = g_slist_delete_link (agent->refresh_list, i); agent->refresh_list = g_slist_delete_link (agent->refresh_list, i);
refresh_free_item (cand); refresh_free_item (cand);
...@@ -228,6 +231,23 @@ void refresh_prune_stream (NiceAgent *agent, guint stream_id) ...@@ -228,6 +231,23 @@ void refresh_prune_stream (NiceAgent *agent, guint stream_id)
} }
void refresh_prune_candidate (NiceAgent *agent, NiceCandidate *candidate)
{
GSList *i;
for (i = agent->refresh_list; i;) {
GSList *next = i->next;
CandidateRefresh *refresh = i->data;
if (refresh->candidate == candidate) {
agent->refresh_list = g_slist_delete_link (agent->refresh_list, i);
refresh_free_item (refresh);
}
i = next;
}
}
void refresh_cancel (CandidateRefresh *refresh) void refresh_cancel (CandidateRefresh *refresh)
{ {
refresh->agent->refresh_list = g_slist_remove (refresh->agent->refresh_list, refresh->agent->refresh_list = g_slist_remove (refresh->agent->refresh_list,
...@@ -235,6 +255,7 @@ void refresh_cancel (CandidateRefresh *refresh) ...@@ -235,6 +255,7 @@ void refresh_cancel (CandidateRefresh *refresh)
refresh_free_item (refresh); refresh_free_item (refresh);
} }
/* /*
* Adds a new local candidate. Implements the candidate pruning * Adds a new local candidate. Implements the candidate pruning
* defined in ICE spec section 4.1.3 "Eliminating Redundant * defined in ICE spec section 4.1.3 "Eliminating Redundant
......
...@@ -84,6 +84,7 @@ typedef struct ...@@ -84,6 +84,7 @@ typedef struct
void refresh_free (NiceAgent *agent); void refresh_free (NiceAgent *agent);
void refresh_prune_stream (NiceAgent *agent, guint stream_id); void refresh_prune_stream (NiceAgent *agent, guint stream_id);
void refresh_prune_candidate (NiceAgent *agent, NiceCandidate *candidate);
void refresh_cancel (CandidateRefresh *refresh); void refresh_cancel (CandidateRefresh *refresh);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment