agent: keep a track of the candidate refreshes being pruned
authorFabrice Bellet <fabrice@bellet.info>
Mon, 6 Jul 2020 11:53:44 +0000 (13:53 +0200)
committerOlivier CrĂȘte <olivier.crete@ocrete.ca>
Tue, 20 Apr 2021 14:07:39 +0000 (14:07 +0000)
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.

agent/agent-priv.h
agent/component.c
agent/conncheck.c
agent/discovery.c
agent/discovery.h

index 1e9387c..a40363f 100644 (file)
@@ -166,6 +166,7 @@ struct _NiceAgent
   GSource *conncheck_timer_source; /* source of conncheck timer */
   GSource *keepalive_timer_source; /* source of keepalive timer */
   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
                                     "Determining Role" ID-19) */
   NiceCompatibility compatibility; /* property: Compatibility mode */
index 5e86b15..2006c42 100644 (file)
@@ -173,6 +173,7 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
   stream = agent_find_stream (agent, cmp->stream_id);
 
   discovery_prune_socket (agent, nsocket);
+  refresh_prune_socket (agent, nsocket);
   if (stream)
     conn_check_prune_socket (agent, stream, cmp, nsocket);
 
index 689ec48..39ef78f 100644 (file)
@@ -3855,6 +3855,7 @@ priv_add_new_turn_refresh (NiceAgent *agent, CandidateDiscovery *cdisco,
 
     nice_debug ("timer source is : %p", cand->timer_source);
   } else {
+    agent->pruning_refreshes = g_slist_append (agent->pruning_refreshes, cand);
     nice_debug ("Agent %p : Sending request to remove TURN allocation "
         "for refresh %p", agent, cand);
     cand->disposing = TRUE;
index dc28291..aa3ab96 100644 (file)
@@ -152,6 +152,7 @@ void refresh_free (NiceAgent *agent, CandidateRefresh *cand)
   nice_debug ("Agent %p : Freeing candidate refresh %p", agent, 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) {
     g_source_destroy (cand->timer_source);
@@ -311,6 +312,8 @@ static void refresh_prune_async (NiceAgent *agent, GSList *refreshes,
     if (cand->disposing)
       continue;
 
+    agent->pruning_refreshes = g_slist_append (agent->pruning_refreshes, cand);
+
     timeout += agent->timer_ta;
     cand->disposing = TRUE;
     cand->destroy_cb = (GDestroyNotify) on_refresh_removed;
@@ -407,6 +410,34 @@ void refresh_prune_candidate_async (NiceAgent *agent,
 }
 
 /*
+ * 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
  * defined in ICE spec section 4.1.3 "Eliminating Redundant
  * Candidates" (ID-19).
index aea526e..703fff6 100644 (file)
@@ -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_async (NiceAgent *agent, NiceCandidateImpl *cand,
   NiceTimeoutLockedCallback function);
+void refresh_prune_socket (NiceAgent *agent, NiceSocket *nicesock);
 
 
 void discovery_free (NiceAgent *agent);