Commit cadf5118 authored by Fabrice Bellet's avatar Fabrice Bellet
Browse files

conncheck: better handle remote tcp disconnection

With this patch, we handle tcp disconnections in a more robust way.
Such disconnections cause the underlying socket to be detached, and
various related pairs have to be discarded from the conncheck list.
This may cause unexpected behaviour, like a previously connected
component to come back in state connecting, if the selected pair
is concerned by a tcp disconnection for example.
parent 804a4c09
Pipeline #240336 failed with stages
in 17 minutes and 45 seconds
......@@ -2557,7 +2557,10 @@ void agent_signal_component_state_change (NiceAgent *agent, guint stream_id, gui
TRANSITION (FAILED, GATHERING) ||
/* Possible by calling set_remote_candidates() without calling
* nice_agent_gather_candidates(): */
TRANSITION (DISCONNECTED, CONNECTING));
TRANSITION (DISCONNECTED, CONNECTING) ||
/* If a tcp socket of connected pair is disconnected, in
* conn_check_prune_socket(): */
TRANSITION (CONNECTED, CONNECTING));
#undef TRANSITION
......
......@@ -185,11 +185,8 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
continue;
}
if (candidate == cmp->selected_pair.local) {
if (candidate == cmp->selected_pair.local)
nice_component_clear_selected_pair (cmp);
agent_signal_component_state_change (agent, cmp->stream_id,
cmp->id, NICE_COMPONENT_STATE_FAILED);
}
refresh_prune_candidate (agent, candidate);
if (candidate->sockptr != nsocket && stream) {
......@@ -217,11 +214,8 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
continue;
}
if (candidate == cmp->selected_pair.remote) {
if (candidate == cmp->selected_pair.remote)
nice_component_clear_selected_pair (cmp);
agent_signal_component_state_change (agent, cmp->stream_id,
cmp->id, NICE_COMPONENT_STATE_FAILED);
}
if (stream)
conn_check_prune_socket (agent, stream, cmp, candidate->sockptr);
......
......@@ -4852,14 +4852,20 @@ conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *co
{
GSList *l;
gboolean pair_failed = FALSE;
gboolean selected_pair_failed = FALSE;
guint p_nominated = 0, p_count = 0;
if (component->selected_pair.local &&
component->selected_pair.local->sockptr == sock &&
component->state == NICE_COMPONENT_STATE_READY) {
component->selected_pair.local->sockptr == sock) {
nice_debug ("Agent %p: Selected pair socket %p has been destroyed, "
"declaring failed", agent, sock);
agent_signal_component_state_change (agent,
stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
selected_pair_failed = TRUE;
if (component->state == NICE_COMPONENT_STATE_READY)
agent_signal_component_state_change (agent,
stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
else if (component->state == NICE_COMPONENT_STATE_CONNECTED)
agent_signal_component_state_change (agent,
stream->id, component->id, NICE_COMPONENT_STATE_CONNECTING);
}
/* Prune from the candidate check pairs. */
......@@ -4867,20 +4873,45 @@ conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *co
CandidateCheckPair *p = l->data;
GSList *next = l->next;
if (p->component_id != component->id) {
l = next;
continue;
}
if (selected_pair_failed && !p->retransmit && p->stun_transactions)
p->retransmit = TRUE;
if ((p->local != NULL && ((NiceCandidateImpl*) p->local)->sockptr == sock) ||
(p->remote != NULL && ((NiceCandidateImpl*)p->remote)->sockptr == sock) ||
(p->sockptr == sock)) {
nice_debug ("Agent %p : Retransmissions failed, giving up on pair %p",
agent, p);
if (component->selected_pair.local == ((NiceCandidateImpl *)p->local) &&
component->selected_pair.remote == ((NiceCandidateImpl *)p->remote))
selected_pair_failed = TRUE;
candidate_check_pair_fail (stream, agent, p);
candidate_check_pair_free (agent, p);
stream->conncheck_list = g_slist_delete_link (stream->conncheck_list, l);
pair_failed = TRUE;
} else {
p_count++;
if (p->nominated)
p_nominated++;
}
l = next;
}
if (pair_failed) {
if (p_count == 0)
agent_signal_component_state_change (agent,
stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
else if (p_nominated == 0 &&
component->state >= NICE_COMPONENT_STATE_CONNECTED)
agent_signal_component_state_change (agent,
stream->id, component->id, NICE_COMPONENT_STATE_CONNECTING);
}
/* outside of the previous loop, because it may
* remove pairs from the conncheck list
*/
......
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