Commit edadfe7b authored by Kai Vehmanen's avatar Kai Vehmanen

Implement delayed processing of early incoming connectivity checks.

darcs-hash:20071126103228-77cd4-6cbe09665aa050c1b5b577c20886f98203d0ce4e.gz
parent fda1e268
...@@ -996,6 +996,8 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo ...@@ -996,6 +996,8 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo
added = -1; added = -1;
} }
conn_check_remote_candidates_set(agent);
if (added > 0) { if (added > 0) {
gboolean res = conn_check_schedule_next (agent); gboolean res = conn_check_schedule_next (agent);
if (res != TRUE) if (res != TRUE)
......
...@@ -95,12 +95,16 @@ component_free (Component *cmp) ...@@ -95,12 +95,16 @@ component_free (Component *cmp)
g_source_destroy (source); g_source_destroy (source);
} }
g_slist_free (cmp->gsources), for (i = cmp->incoming_checks; i; i = i->next) {
cmp->gsources = NULL; IncomingCheck *icheck = i->data;
g_slice_free (IncomingCheck, icheck);
}
g_slist_free (cmp->local_candidates); g_slist_free (cmp->local_candidates);
g_slist_free (cmp->remote_candidates); g_slist_free (cmp->remote_candidates);
g_slist_free (cmp->sockets); g_slist_free (cmp->sockets);
g_slist_free (cmp->gsources), cmp->gsources = NULL;
g_slist_free (cmp->incoming_checks);
g_slice_free (Component, cmp); g_slice_free (Component, cmp);
} }
...@@ -192,6 +196,11 @@ component_restart (Component *cmp) ...@@ -192,6 +196,11 @@ component_restart (Component *cmp)
g_slist_free (cmp->remote_candidates), g_slist_free (cmp->remote_candidates),
cmp->remote_candidates = NULL; cmp->remote_candidates = NULL;
for (i = cmp->incoming_checks; i; i = i->next) {
IncomingCheck *icheck = i->data;
g_slice_free (IncomingCheck, icheck);
}
/* note: component state managed by agent */ /* note: component state managed by agent */
return TRUE; return TRUE;
......
...@@ -54,6 +54,7 @@ G_BEGIN_DECLS ...@@ -54,6 +54,7 @@ G_BEGIN_DECLS
typedef struct _Component Component; typedef struct _Component Component;
typedef struct _CandidatePair CandidatePair; typedef struct _CandidatePair CandidatePair;
typedef struct _IncomingCheck IncomingCheck;
struct _CandidatePair struct _CandidatePair
{ {
...@@ -62,6 +63,14 @@ struct _CandidatePair ...@@ -62,6 +63,14 @@ struct _CandidatePair
guint64 priority; /**< candidate pair priority */ guint64 priority; /**< candidate pair priority */
}; };
struct _IncomingCheck
{
NiceAddress from;
NiceUDPSocket *local_socket;
uint32_t priority;
gboolean use_candidate;
};
struct _Component struct _Component
{ {
NiceComponentType type; NiceComponentType type;
...@@ -71,6 +80,7 @@ struct _Component ...@@ -71,6 +80,7 @@ struct _Component
GSList *remote_candidates; /**< list of Candidate objs */ GSList *remote_candidates; /**< list of Candidate objs */
GSList *sockets; /**< list of NiceUDPSocket objs */ GSList *sockets; /**< list of NiceUDPSocket objs */
GSList *gsources; /**< list of GSource objs */ GSList *gsources; /**< list of GSource objs */
GSList *incoming_checks; /**< list of IncomingCheck objs */
CandidatePair selected_pair; /**< independent from checklists, CandidatePair selected_pair; /**< independent from checklists,
see ICE 11.1. "Sending Media" (ID-19) */ see ICE 11.1. "Sending Media" (ID-19) */
gboolean media_after_tick; /**< true if media received since last gboolean media_after_tick; /**< true if media received since last
......
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
#include "conncheck.h" #include "conncheck.h"
#include "discovery.h" #include "discovery.h"
static void priv_update_check_list_failed_components (NiceAgent *agent, Stream *stream);
static void priv_prune_pending_checks (Stream *stream, guint component_id);
static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream, Component *component, NiceUDPSocket *local_socket, NiceCandidate *remote_cand, gboolean use_candidate);
static void priv_mark_pair_nominated (NiceAgent *agent, Stream *stream, Component *component, NiceCandidate *remotecand);
static inline int priv_timer_expired (GTimeVal *restrict timer, GTimeVal *restrict now) static inline int priv_timer_expired (GTimeVal *restrict timer, GTimeVal *restrict now)
{ {
return (now->tv_sec == timer->tv_sec) ? return (now->tv_sec == timer->tv_sec) ?
...@@ -62,8 +67,6 @@ static inline int priv_timer_expired (GTimeVal *restrict timer, GTimeVal *restri ...@@ -62,8 +67,6 @@ static inline int priv_timer_expired (GTimeVal *restrict timer, GTimeVal *restri
now->tv_sec >= timer->tv_sec; now->tv_sec >= timer->tv_sec;
} }
static void priv_update_check_list_state (NiceAgent *agent, Stream *stream);
/** /**
* Finds the next connectivity check in WAITING state. * Finds the next connectivity check in WAITING state.
*/ */
...@@ -368,7 +371,7 @@ static gboolean priv_conn_check_tick (gpointer pointer) ...@@ -368,7 +371,7 @@ static gboolean priv_conn_check_tick (gpointer pointer)
g_debug ("%s: stopping conncheck timer", G_STRFUNC); g_debug ("%s: stopping conncheck timer", G_STRFUNC);
for (i = agent->streams; i; i = i->next) { for (i = agent->streams; i; i = i->next) {
Stream *stream = i->data; Stream *stream = i->data;
priv_update_check_list_state (agent, stream); priv_update_check_list_failed_components (agent, stream);
stream->conncheck_state = NICE_CHECKLIST_COMPLETED; stream->conncheck_state = NICE_CHECKLIST_COMPLETED;
} }
conn_check_free (agent); conn_check_free (agent);
...@@ -489,6 +492,84 @@ gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair * ...@@ -489,6 +492,84 @@ gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *
return 0; return 0;
} }
/**
* Preprocesses a new connectivity check by going through list
* of a any stored early incoming connectivity checks from
* the remote peer. If a matching incoming check has been already
* received, update the state of the new outgoing check 'pair'.
*
* @param agent context pointer
* @param stream which stream (of the agent)
* @param component pointer to component object to which 'pair'has been added
* @param pair newly added connectivity check
*/
static void priv_preprocess_conn_check_pending_data (NiceAgent *agent, Stream *stream, Component *component, CandidateCheckPair *pair)
{
GSList *i;
for (i = component->incoming_checks; i; i = i->next) {
IncomingCheck *icheck = i->data;
if (nice_address_equal (&icheck->from, &pair->remote->addr) &&
icheck->local_socket == pair->local->sockptr) {
g_debug ("Updating check %p with stored early-icheck %p, %p/%u/%u (agent/stream/component).", pair, icheck, agent, stream->id, component->id);
if (icheck->use_candidate)
priv_mark_pair_nominated (agent, stream, component, pair->remote);
priv_schedule_triggered_check (agent, stream, component, icheck->local_socket, pair->remote, icheck->use_candidate);
}
}
}
/**
* Handle any processing steps for connectivity checks after
* remote candidates have been set. This function handles
* the special case where answerer has sent us connectivity
* checks before the answer (containing candidate information),
* reaches us. The special case is documented in sect 7.2
* if ICE spec (ID-19).
*/
void conn_check_remote_candidates_set(NiceAgent *agent)
{
GSList *i, *j, *k, *l;
for (i = agent->streams; i ; i = i->next) {
Stream *stream = i->data;
for (j = stream->conncheck_list; j ; j = j->next) {
CandidateCheckPair *pair = j->data;
Component *component = stream_find_component_by_id (stream, pair->component_id);
gboolean match = FALSE;
/* performn delayed processing of spec steps section 7.2.1.4,
and section 7.2.1.5 */
priv_preprocess_conn_check_pending_data (agent, stream, component, pair);
for (k = component->incoming_checks; k; k = k->next) {
IncomingCheck *icheck = k->data;
/* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to
* be handled separately */
for (l = component->remote_candidates; l; l = l->next) {
NiceCandidate *cand = l->data;
if (nice_address_equal (&icheck->from, &cand->addr)) {
match = TRUE;
break;
}
}
if (match != TRUE) {
/* note: we have gotten an incoming connectivity check from
* an address that is not a known remote candidate */
NiceCandidate *candidate =
discovery_learn_remote_peer_reflexive_candidate (agent,
stream,
component,
icheck->priority,
&icheck->from,
icheck->local_socket);
if (candidate) {
priv_schedule_triggered_check (agent, stream, component, icheck->local_socket, candidate, icheck->use_candidate);
}
}
}
}
}
}
/** /**
* Enforces the upper limit for connectivity checks as described * Enforces the upper limit for connectivity checks as described
* in ICE spec section 5.7.3 (ID-19). See also * in ICE spec section 5.7.3 (ID-19). See also
...@@ -529,6 +610,135 @@ static GSList *priv_limit_conn_check_list_size (GSList *conncheck_list, guint up ...@@ -529,6 +610,135 @@ static GSList *priv_limit_conn_check_list_size (GSList *conncheck_list, guint up
return result; return result;
} }
/**
* Changes the selected pair for the component if 'pair' is nominated
* and has higher priority than the currently selected pair. See
* ICE sect 11.1.1. "Procedures for Full Implementations" (ID-19).
*/
static gboolean priv_update_selected_pair (NiceAgent *agent, Component *component, CandidateCheckPair *pair)
{
g_assert (component);
g_assert (pair);
if (pair->priority > component->selected_pair.priority) {
g_debug ("changing SELECTED PAIR for component %u: %s:%s (prio:%lu).",
component->id, pair->local->foundation, pair->remote->foundation, (long unsigned)pair->priority);
component->selected_pair.local = pair->local;
component->selected_pair.remote = pair->remote;
component->selected_pair.priority = pair->priority;
agent_signal_new_selected_pair (agent, pair->stream_id, component->id, pair->local->foundation, pair->remote->foundation);
}
return TRUE;
}
/**
* Updates the check list state.
*
* Implements parts of the algorithm described in
* ICE sect 8.1.2. "Updating States" (ID-19): if for any
* component, all checks have been completed and have
* failed, mark that component's state to NICE_CHECK_FAILED.
*
* Sends a component state changesignal via 'agent'.
*/
static void priv_update_check_list_failed_components (NiceAgent *agent, Stream *stream)
{
GSList *i;
/* note: emitting a signal might cause the client
* to remove the stream, thus the component count
* must be fetched before entering the loop*/
guint c, components = stream->n_components;
/* note: iterate the conncheck list for each component separately */
for (c = 0; c < components; c++) {
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *p = i->data;
if (p->stream_id == stream->id &&
p->component_id == (c + 1)) {
if (p->state != NICE_CHECK_FAILED)
break;
}
}
/* note: all checks have failed */
if (i == NULL)
agent_signal_component_state_change (agent,
stream->id,
(c + 1), /* component-id */
NICE_COMPONENT_STATE_FAILED);
}
}
/**
* Updates the check list state for a stream component.
*
* Implements the algorithm described in ICE sect 8.1.2
* "Updating States" (ID-19) as it applies to checks of
* a certain component. If there are any nominated pairs,
* ICE processing may be concluded, and component state is
* changed to READY.
*
* Sends a component state changesignal via 'agent'.
*/
static void priv_update_check_list_state_for_ready (NiceAgent *agent, Stream *stream, Component *component)
{
GSList *i;
guint succeeded = 0, nominated = 0;
g_assert (component);
/* step: search for at least one nominated pair */
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *p = i->data;
if (p->component_id == component->id) {
if (p->state == NICE_CHECK_SUCCEEDED ||
p->state == NICE_CHECK_DISCOVERED) {
++succeeded;
if (p->nominated == TRUE) {
priv_prune_pending_checks (stream, p->component_id);
agent_signal_component_state_change (agent,
p->stream_id,
p->component_id,
NICE_COMPONENT_STATE_READY);
}
}
}
}
g_debug ("conn.check list status: %u nominated, %u succeeded, c-id %u.", nominated, succeeded, component->id);
}
/**
* The remote party has signalled that the candidate pair
* described by 'component' and 'remotecand' is nominated
* for use.
*/
static void priv_mark_pair_nominated (NiceAgent *agent, Stream *stream, Component *component, NiceCandidate *remotecand)
{
GSList *i;
g_assert (component);
/* step: search for at least one nominated pair */
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *pair = i->data;
/* XXX: hmm, how to figure out to which local candidate the
* check was sent to? let's mark all matching pairs
* as nominated instead */
if (pair->remote == remotecand) {
g_debug ("marking pair %p (%s) as nominated", pair, pair->foundation);
pair->nominated = TRUE;
if (pair->state == NICE_CHECK_SUCCEEDED ||
pair->state == NICE_CHECK_DISCOVERED)
priv_update_selected_pair (agent, component, pair);
priv_update_check_list_state_for_ready (agent, stream, component);
}
}
}
/** /**
* Creates a new connectivity check pair and adds it to * Creates a new connectivity check pair and adds it to
* the agent's list of checks. * the agent's list of checks.
...@@ -539,6 +749,11 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp ...@@ -539,6 +749,11 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp
Stream *stream = agent_find_stream (agent, stream_id); Stream *stream = agent_find_stream (agent, stream_id);
CandidateCheckPair *pair = g_slice_new0 (CandidateCheckPair); CandidateCheckPair *pair = g_slice_new0 (CandidateCheckPair);
if (pair) { if (pair) {
GSList *modified_list =
g_slist_insert_sorted (stream->conncheck_list, pair, (GCompareFunc)conn_check_compare);
if (modified_list) {
/* step: allocation and addition succesful, do rest of the work */
pair->agent = agent; pair->agent = agent;
pair->stream_id = stream_id; pair->stream_id = stream_id;
pair->component_id = component->id;; pair->component_id = component->id;;
...@@ -554,12 +769,8 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp ...@@ -554,12 +769,8 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp
/* note: for the first added check */ /* note: for the first added check */
if (!stream->conncheck_list) if (!stream->conncheck_list)
stream->conncheck_state = NICE_CHECKLIST_RUNNING; stream->conncheck_state = NICE_CHECKLIST_RUNNING;
{
GSList *modified_list =
g_slist_insert_sorted (stream->conncheck_list, pair, (GCompareFunc)conn_check_compare);
if (modified_list) {
stream->conncheck_list = modified_list; stream->conncheck_list = modified_list;
result = TRUE; result = TRUE;
g_debug ("added a new conncheck %p with foundation of '%s' to list %u.", pair, pair->foundation, stream_id); g_debug ("added a new conncheck %p with foundation of '%s' to list %u.", pair, pair->foundation, stream_id);
...@@ -572,12 +783,12 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp ...@@ -572,12 +783,12 @@ static gboolean priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Comp
result = FALSE; result = FALSE;
} }
} }
else { /* memory alloc failed: list insert */ else {
/* memory alloc failed: list insert */
conn_check_free_item (pair, NULL); conn_check_free_item (pair, NULL);
stream->conncheck_state = NICE_CHECKLIST_FAILED; stream->conncheck_state = NICE_CHECKLIST_FAILED;
} }
} }
}
else { /* memory alloc failed: new pair */ else { /* memory alloc failed: new pair */
stream->conncheck_state = NICE_CHECKLIST_FAILED; stream->conncheck_state = NICE_CHECKLIST_FAILED;
} }
...@@ -831,57 +1042,13 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair) ...@@ -831,57 +1042,13 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair)
return 0; return 0;
} }
/**
* Updates the check list state.
*
* Implements parts of the algorithm described in
* ICE sect 8.1.2. "Updating States" (ID-19) that apply
* to the whole check list.
*/
static void priv_update_check_list_state (NiceAgent *agent, Stream *stream)
{
GSList *i;
/* note: emitting a signal might cause the client
* to remove the stream, thus the component count
* must be fetched before entering the loop*/
guint c, components = stream->n_components;
/* note: iterate the conncheck list for each component separately */
for (c = 0; c < components; c++) {
guint not_failed = 0;
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *p = i->data;
if (p->stream_id == stream->id &&
p->component_id == (c + 1)) {
if (p->state != NICE_CHECK_FAILED)
++not_failed;
if ((p->state == NICE_CHECK_SUCCEEDED ||
p->state == NICE_CHECK_DISCOVERED) &&
p->nominated == TRUE)
break;
}
}
/* note: all checks have failed */
if (not_failed == 0)
agent_signal_component_state_change (agent,
stream->id,
(c + 1), /* component-id */
NICE_COMPONENT_STATE_FAILED);
}
}
/** /**
* Implemented the pruning steps described in ICE sect 8.1.2 * Implemented the pruning steps described in ICE sect 8.1.2
* "Updating States" (ID-19) after a pair has been nominated. * "Updating States" (ID-19) after a pair has been nominated.
* *
* @see priv_update_check_list_state_for_component() * @see priv_update_check_list_state_failed_components()
*/ */
static void priv_prune_pending_checks (/*NiceAgent *agent, */Stream *stream, guint component_id) static void priv_prune_pending_checks (Stream *stream, guint component_id)
{ {
GSList *i; GSList *i;
...@@ -904,67 +1071,6 @@ static void priv_prune_pending_checks (/*NiceAgent *agent, */Stream *stream, gui ...@@ -904,67 +1071,6 @@ static void priv_prune_pending_checks (/*NiceAgent *agent, */Stream *stream, gui
} }
} }
/**
* Updates the check list state for a stream component.
*
* Implements the algorithm described in ICE sect 8.1.2
* "Updating States" (ID-19) as it applies to checks of
* a certain component. If any there are any nominated pairs,
* ICE processing may be concluded, and component state is
* changed to READY.
*/
static void priv_update_check_list_state_for_component (NiceAgent *agent, Stream *stream, Component *component)
{
GSList *i;
guint succeeded = 0, nominated = 0;
g_assert (component);
/* step: search for at least one nominated pair */
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *p = i->data;
if (p->component_id == component->id) {
if (p->state == NICE_CHECK_SUCCEEDED ||
p->state == NICE_CHECK_DISCOVERED) {
++succeeded;
if (p->nominated == TRUE) {
priv_prune_pending_checks (/*agent, */stream, p->component_id);
agent_signal_component_state_change (agent,
p->stream_id,
p->component_id,
NICE_COMPONENT_STATE_READY);
}
}
}
}
g_debug ("conn.check list status: %u nominated, %u succeeded, c-id %u.", nominated, succeeded, component->id);
priv_update_check_list_state (agent, stream);
}
/**
* Changes the selected pair for the component if 'pair' is nominated
* and has higher priority than the currently selected pair. See
* ICE sect 11.1.1. "Procedures for Full Implementations" (ID-19).
*/
static gboolean priv_update_selected_pair (NiceAgent *agent, Component *component, CandidateCheckPair *pair)
{
g_assert (component);
g_assert (pair);
if (pair->priority > component->selected_pair.priority) {
g_debug ("changing SELECTED PAIR for component %u: %s:%s (prio:%lu).",
component->id, pair->local->foundation, pair->remote->foundation, (long unsigned)pair->priority);
component->selected_pair.local = pair->local;
component->selected_pair.remote = pair->remote;
component->selected_pair.priority = pair->priority;
agent_signal_new_selected_pair (agent, pair->stream_id, component->id, pair->local->foundation, pair->remote->foundation);
}
return TRUE;
}
/** /**
* Schedules a triggered check after a succesfully inbound * Schedules a triggered check after a succesfully inbound
* connectivity check. Implements ICE sect 7.2.1.4 "Triggered Checks" (ID-19). * connectivity check. Implements ICE sect 7.2.1.4 "Triggered Checks" (ID-19).
...@@ -1002,7 +1108,7 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream, ...@@ -1002,7 +1108,7 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream,
g_debug ("Skipping triggered check, already completed.."); g_debug ("Skipping triggered check, already completed..");
/* note: this is a bit unsure corner-case -- let's do the /* note: this is a bit unsure corner-case -- let's do the
same state update as for processing responses to our own checks */ same state update as for processing responses to our own checks */
priv_update_check_list_state_for_component (agent, stream, component); priv_update_check_list_state_for_ready (agent, stream, component);
/* note: to take care of the controlling-controlling case in /* note: to take care of the controlling-controlling case in
* aggressive nomination mode, send a new triggered * aggressive nomination mode, send a new triggered
...@@ -1026,8 +1132,8 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream, ...@@ -1026,8 +1132,8 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream,
if (local->sockptr == local_socket) if (local->sockptr == local_socket)
break; break;
} }
if (local) { if (i) {
g_debug ("Adding a triggered check to conn.check list."); g_debug ("Adding a triggered check to conn.check list (local=%p).", local);
result = priv_add_new_check_pair (agent, stream->id, component, local, remote_cand, NICE_CHECK_WAITING, use_candidate); result = priv_add_new_check_pair (agent, stream->id, component, local, remote_cand, NICE_CHECK_WAITING, use_candidate);
} }
else else
...@@ -1037,33 +1143,6 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream, ...@@ -1037,33 +1143,6 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream,
return result; return result;
} }
/**
* The remote party has signalled that the candidate pair
* described by 'component' and 'remotecand' is nominated
* for use.
*/
static void priv_mark_pair_nominated (NiceAgent *agent, Stream *stream, Component *component, NiceCandidate *remotecand)
{
GSList *i;
g_assert (component);
/* step: search for at least one nominated pair */
for (i = stream->conncheck_list; i; i = i->next) {
CandidateCheckPair *pair = i->data;
/* XXX: hmm, how to figure out to which local candidate the
* check was sent to? let's mark all matching pairs
* as nominated instead */
if (pair->remote == remotecand) {
g_debug ("marking pair %p (%s) as nominated", pair, pair->foundation);
pair->nominated = TRUE;
if (pair->state == NICE_CHECK_SUCCEEDED ||
pair->state == NICE_CHECK_DISCOVERED)
priv_update_selected_pair (agent, component, pair);
priv_update_check_list_state_for_component (agent, stream, component);
}
}
}
/** /**
* Sends a reply to an succesfully received STUN connectivity * Sends a reply to an succesfully received STUN connectivity
...@@ -1112,6 +1191,42 @@ static void priv_reply_to_conn_check (NiceAgent *agent, Stream *stream, Componen ...@@ -1112,6 +1191,42 @@ static void priv_reply_to_conn_check (NiceAgent *agent, Stream *stream, Componen
} }
} }
/**
* Stores information of an incoming STUN connectivity check
* for later use. This is only needed when a check is received
* before we get information about the remote candidates (via
* SDP or other signaling means).
*
* @return non-zero on error, zero on success
*/
static int priv_store_pending_check (NiceAgent *agent, Component *component, const NiceAddress *from, NiceUDPSocket *udp_socket, uint32_t priority, gboolean use_candidate)
{
IncomingCheck *icheck;
g_debug ("Storing pending check.");
if (component->incoming_checks &&
g_slist_length (component->incoming_checks) >=
NICE_AGENT_MAX_REMOTE_CANDIDATES) {
g_debug ("WARN: unable to store information for early incoming check.");
return -1;
}
icheck = g_slice_new0 (IncomingCheck);
if (icheck) {
GSList *pending = g_slist_append (component->incoming_checks, icheck);
if (pending) {
component->incoming_checks = pending;
icheck->from = *from;
icheck->local_socket = udp_socket;
icheck->priority = priority;
icheck->use_candidate = use_candidate;
return 0;
}
}
return -1;
}
/** /**
* Adds a new pair, discovered from an incoming STUN response, to * Adds a new pair, discovered from an incoming STUN response, to
* the connectivity check list. * the connectivity check list.
...@@ -1303,7 +1418,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream * ...@@ -1303,7 +1418,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
/* step: update pair states (ICE 7.1.2.2.3 "Updating pair /* step: update pair states (ICE 7.1.2.2.3 "Updating pair
states" and 8.1.2 "Updating States", ID-19) */ states" and 8.1.2 "Updating States", ID-19) */
priv_update_check_list_state_for_component (agent, stream, component); priv_update_check_list_state_for_ready (agent, stream, component);
trans_found = TRUE; trans_found = TRUE;
} }
...@@ -1328,7 +1443,6 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream * ...@@ -1328,7 +1443,6 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
} }
else { else {
/* case: STUN could not parse, skip */ /* case: STUN could not parse, skip */
/* XXX: added by Remi, needs review */
g_assert (res == EAGAIN); g_assert (res == EAGAIN);
g_debug ("conncheck %p SKIPPED", p); g_debug ("conncheck %p SKIPPED", p);
...@@ -1438,6 +1552,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo ...@@ -1438,6 +1552,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo
GSList *i; GSList *i;
bool use_candidate = bool use_candidate =
stun_conncheck_use_candidate ((const uint8_t*)buf); stun_conncheck_use_candidate ((const uint8_t*)buf);
uint32_t priority = stun_conncheck_priority ((const uint8_t*)buf);
if (agent->controlling_mode) if (agent->controlling_mode)
use_candidate = TRUE; use_candidate = TRUE;
...@@ -1452,16 +1567,9 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo ...@@ -1452,16 +1567,9 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo
* immediately but postpone all other processing until * immediately but postpone all other processing until
* we get information about the remote candidates */ * we get information about the remote candidates */
/* step: send a reply immediately but postpone other processing */
/* XXX: temporary workaround: ignore connchecks until we
* get the answer... retransmissions will ensure that
* connectivity is establish, just somewhat slower */
agent_signal_initial_binding_request_received (agent, stream);
#if 0
/* step: answer to our offer not yet received, so send
* a reply immediately but postpone other processing */
priv_reply_to_conn_check (agent, stream, component, NULL, from, udp_socket, rbuf_len, rbuf, use_candidate); priv_reply_to_conn_check (agent, stream, component, NULL, from, udp_socket, rbuf_len, rbuf, use_candidate);
#endif priv_store_pending_check (agent, component, from, udp_socket, priority, use_candidate);
} }
else { else {
for (i = component->remote_candidates; i; i = i->next) { for (i = component->remote_candidates; i; i = i->next) {
...@@ -1476,7 +1584,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo ...@@ -1476,7 +1584,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Compo
NiceCandidate *candidate; NiceCandidate *candidate;
g_debug ("No matching remote candidate for incoming check -> peer-reflexive candidate."); g_debug ("No matching remote candidate for incoming check -> peer-reflexive candidate.");
candidate = discovery_learn_remote_peer_reflexive_candidate ( candidate = discovery_learn_remote_peer_reflexive_candidate (
agent, stream, component, stun_conncheck_priority ((const uint8_t*)buf), from, udp_socket); agent, stream, component, priority, from, udp_socket);
if (candidate) if (candidate)
priv_reply_to_conn_check (agent, stream, component, candidate, &candidate->addr, udp_socket, rbuf_len, rbuf, use_candidate); priv_reply_to_conn_check (agent, stream, component, candidate, &candidate->addr, udp_socket, rbuf_len, rbuf, use_candidate);
} }
......
...@@ -85,5 +85,6 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair); ...@@ -85,5 +85,6 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair);
gboolean conn_check_prune_stream (NiceAgent *agent, Stream *stream); gboolean conn_check_prune_stream (NiceAgent *agent, Stream *stream);
gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Component *component, NiceUDPSocket *udp_socket, const NiceAddress *from, gchar *buf, guint len); gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, Component *component, NiceUDPSocket *udp_socket, const NiceAddress *from, gchar *buf, guint len);
gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b); gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b);
void conn_check_remote_candidates_set(NiceAgent *agent);
#endif /*_NICE_CONNCHECK_H */ #endif /*_NICE_CONNCHECK_H */
...@@ -435,6 +435,7 @@ static int run_full_test_delayed_answer (NiceAgent *lagent, NiceAgent *ragent, N ...@@ -435,6 +435,7 @@ static int run_full_test_delayed_answer (NiceAgent *lagent, NiceAgent *ragent, N
g_main_loop_run (global_mainloop); g_main_loop_run (global_mainloop);
g_assert (global_ragent_ibr_received == TRUE); g_assert (global_ragent_ibr_received == TRUE);
g_assert (global_components_failed == 0);
/* note: test payload send and receive */ /* note: test payload send and receive */
global_ragent_read = 0; global_ragent_read = 0;
......
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