#include "debug.h"
#include "component.h"
+#include "discovery.h"
#include "agent-priv.h"
void
component_clean_turn_servers (Component *cmp)
{
+ GSList *i;
g_list_free_full (cmp->turn_servers, (GDestroyNotify) turn_server_unref);
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
nice_candidate_free (cmp->restart_candidate),
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) {
IncomingCheck *icheck = i->data;
g_free (icheck->username);
}
g_slist_free (cmp->local_candidates);
+ cmp->local_candidates = NULL;
g_slist_free (cmp->remote_candidates);
+ cmp->remote_candidates = NULL;
component_free_socket_sources (cmp);
g_slist_free (cmp->incoming_checks);
+ cmp->incoming_checks = NULL;
component_clean_turn_servers (cmp);
for (i = cmp->remote_candidates; i; i = i->next) {
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
* 9.1.1.1. "ICE Restarts" (ID-19) */
if (candidate == cmp->selected_pair.remote) {
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));
component->selected_pair.local = pair->local;
component->selected_pair.remote = pair->remote;
/*
* 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
*/
CandidateRefresh *cand = i->data;
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) {
agent->refresh_list = g_slist_delete_link (agent->refresh_list, i);
refresh_free_item (cand);
}
+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)
{
refresh->agent->refresh_list = g_slist_remove (refresh->agent->refresh_list,
refresh_free_item (refresh);
}
+
/*
* Adds a new local candidate. Implements the candidate pruning
* defined in ICE spec section 4.1.3 "Eliminating Redundant