summaryrefslogtreecommitdiff
path: root/agent/conncheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/conncheck.c')
-rw-r--r--agent/conncheck.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/agent/conncheck.c b/agent/conncheck.c
index e03130a..960698b 100644
--- a/agent/conncheck.c
+++ b/agent/conncheck.c
@@ -630,6 +630,20 @@ candidate_check_pair_fail (NiceStream *stream, NiceAgent *agent, CandidateCheckP
component = nice_stream_find_component_by_id (stream, p->component_id);
SET_PAIR_STATE (agent, p, NICE_CHECK_FAILED);
priv_free_all_stun_transactions (p, component);
+
+ /* Ensure related succeeded-discovered pairs change to state failed
+ * simultaneously, to avoid leaving dangling pointers if one is freeed
+ * while the other is still in the conncheck list. Such transition is
+ * very rare, and only occurs in regular nomination mode, when the
+ * network conditions change between the time the pair is initially
+ * discovered and the time it is rechecked with the use-candidate
+ * flag.
+ */
+ if (p->discovered_pair != NULL) {
+ nice_debug ("Agent %p : related discovered pair %p of pair %p "
+ "will fail too.", agent, p->discovered_pair, p);
+ SET_PAIR_STATE (agent, p->discovered_pair, NICE_CHECK_FAILED);
+ }
}
/*
@@ -3435,6 +3449,14 @@ static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent *
*/
if (new_pair == p)
p->valid = TRUE;
+ else
+ /* this new_pair distinct from p may also be in state failed (if
+ * the related succeeded pair p was in state failed previously, but
+ * retriggered a successful check a bit later), so we force its
+ * state back to discovered there.
+ */
+ SET_PAIR_STATE (agent, new_pair, NICE_CHECK_DISCOVERED);
+
SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
priv_remove_pair_from_triggered_check_queue (agent, p);
priv_free_all_stun_transactions (p, component);