Commit 48dac0d7 authored by Fabrice Bellet's avatar Fabrice Bellet Committed by Olivier Crête

agent: keep a track of the candidate refreshes being pruned

Refreshes with zero lifetime sent over tcp transport may cause the
removal of the underlying socket when the remote peer closes the
connection taking our request into account. These refreshes must be
tracked and freeed on our side to avoid retransmission attempt on a
closed socket and a heap-use-after-free error in that case.
parent e1a84135
...@@ -166,6 +166,7 @@ struct _NiceAgent ...@@ -166,6 +166,7 @@ struct _NiceAgent
GSource *conncheck_timer_source; /* source of conncheck timer */ GSource *conncheck_timer_source; /* source of conncheck timer */
GSource *keepalive_timer_source; /* source of keepalive timer */ GSource *keepalive_timer_source; /* source of keepalive timer */
GSList *refresh_list; /* list of CandidateRefresh items */ GSList *refresh_list; /* list of CandidateRefresh items */
GSList *pruning_refreshes; /* list of Refreshes current being shut down*/
guint64 tie_breaker; /* tie breaker (ICE sect 5.2 guint64 tie_breaker; /* tie breaker (ICE sect 5.2
"Determining Role" ID-19) */ "Determining Role" ID-19) */
NiceCompatibility compatibility; /* property: Compatibility mode */ NiceCompatibility compatibility; /* property: Compatibility mode */
......
...@@ -173,6 +173,7 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp, ...@@ -173,6 +173,7 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
stream = agent_find_stream (agent, cmp->stream_id); stream = agent_find_stream (agent, cmp->stream_id);
discovery_prune_socket (agent, nsocket); discovery_prune_socket (agent, nsocket);
refresh_prune_socket (agent, nsocket);
if (stream) if (stream)
conn_check_prune_socket (agent, stream, cmp, nsocket); conn_check_prune_socket (agent, stream, cmp, nsocket);
......
...@@ -3855,6 +3855,7 @@ priv_add_new_turn_refresh (NiceAgent *agent, CandidateDiscovery *cdisco, ...@@ -3855,6 +3855,7 @@ priv_add_new_turn_refresh (NiceAgent *agent, CandidateDiscovery *cdisco,
nice_debug ("timer source is : %p", cand->timer_source); nice_debug ("timer source is : %p", cand->timer_source);
} else { } else {
agent->pruning_refreshes = g_slist_append (agent->pruning_refreshes, cand);
nice_debug ("Agent %p : Sending request to remove TURN allocation " nice_debug ("Agent %p : Sending request to remove TURN allocation "
"for refresh %p", agent, cand); "for refresh %p", agent, cand);
cand->disposing = TRUE; cand->disposing = TRUE;
......
...@@ -152,6 +152,7 @@ void refresh_free (NiceAgent *agent, CandidateRefresh *cand) ...@@ -152,6 +152,7 @@ void refresh_free (NiceAgent *agent, CandidateRefresh *cand)
nice_debug ("Agent %p : Freeing candidate refresh %p", agent, cand); nice_debug ("Agent %p : Freeing candidate refresh %p", agent, cand);
agent->refresh_list = g_slist_remove (agent->refresh_list, cand); agent->refresh_list = g_slist_remove (agent->refresh_list, cand);
agent->pruning_refreshes = g_slist_remove (agent->pruning_refreshes, cand);
if (cand->timer_source != NULL) { if (cand->timer_source != NULL) {
g_source_destroy (cand->timer_source); g_source_destroy (cand->timer_source);
...@@ -311,6 +312,8 @@ static void refresh_prune_async (NiceAgent *agent, GSList *refreshes, ...@@ -311,6 +312,8 @@ static void refresh_prune_async (NiceAgent *agent, GSList *refreshes,
if (cand->disposing) if (cand->disposing)
continue; continue;
agent->pruning_refreshes = g_slist_append (agent->pruning_refreshes, cand);
timeout += agent->timer_ta; timeout += agent->timer_ta;
cand->disposing = TRUE; cand->disposing = TRUE;
cand->destroy_cb = (GDestroyNotify) on_refresh_removed; cand->destroy_cb = (GDestroyNotify) on_refresh_removed;
...@@ -406,6 +409,34 @@ void refresh_prune_candidate_async (NiceAgent *agent, ...@@ -406,6 +409,34 @@ void refresh_prune_candidate_async (NiceAgent *agent,
g_slist_free (refreshes); g_slist_free (refreshes);
} }
/*
* Removes the candidate refreshes related to 'nicesock'.
*/
void refresh_prune_socket (NiceAgent *agent, NiceSocket *nicesock)
{
GSList *i;
for (i = agent->refresh_list; i;) {
GSList *next = i->next;
CandidateRefresh *refresh = i->data;
if (refresh->nicesock == nicesock)
refresh_free(agent, refresh);
i = next;
}
for (i = agent->pruning_refreshes; i;) {
GSList *next = i->next;
CandidateRefresh *refresh = i->data;
if (refresh->nicesock == nicesock)
refresh_free(agent, refresh);
i = next;
}
}
/* /*
* 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
......
...@@ -94,6 +94,7 @@ void refresh_prune_stream_async (NiceAgent *agent, NiceStream *stream, ...@@ -94,6 +94,7 @@ void refresh_prune_stream_async (NiceAgent *agent, NiceStream *stream,
void refresh_prune_candidate (NiceAgent *agent, NiceCandidateImpl *candidate); void refresh_prune_candidate (NiceAgent *agent, NiceCandidateImpl *candidate);
void refresh_prune_candidate_async (NiceAgent *agent, NiceCandidateImpl *cand, void refresh_prune_candidate_async (NiceAgent *agent, NiceCandidateImpl *cand,
NiceTimeoutLockedCallback function); NiceTimeoutLockedCallback function);
void refresh_prune_socket (NiceAgent *agent, NiceSocket *nicesock);
void discovery_free (NiceAgent *agent); void discovery_free (NiceAgent *agent);
......
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