Commit 857ae67e authored by Kai Vehmanen's avatar Kai Vehmanen

Added API and initial implementation for ICE restarts.

darcs-hash:20070717181854-77cd4-0794ecc4d25586d2add1f88f083271048f2364b6.gz
parent 8cb7f95f
...@@ -1362,6 +1362,37 @@ nice_agent_get_remote_candidates ( ...@@ -1362,6 +1362,37 @@ nice_agent_get_remote_candidates (
return g_slist_copy (component->remote_candidates); return g_slist_copy (component->remote_candidates);
} }
/**
* nice_agent_restart
* @agent: A NiceAgent
*
* Restarts the session as defined in ICE spec (ID-17). This function
* needs to be called both when initiating (ICE spec section 9.1.1.1.
* "ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
* "Detecting ICE Restart") to a restart.
*
* Returns: FALSE on error
**/
gboolean
nice_agent_restart (
NiceAgent *agent)
{
GSList *i;
gboolean res = TRUE;
/* clean up all connectivity checks */
conn_check_free (agent);
for (i = agent->streams; i && res; i = i->next) {
Stream *stream = i->data;
/* reset local credentials */
res = stream_restart (stream, agent->rng);
}
return res;
}
static void static void
nice_agent_dispose (GObject *object) nice_agent_dispose (GObject *object)
{ {
......
...@@ -213,6 +213,10 @@ nice_agent_get_remote_candidates ( ...@@ -213,6 +213,10 @@ nice_agent_get_remote_candidates (
guint stream_id, guint stream_id,
guint component_id); guint component_id);
gboolean
nice_agent_restart (
NiceAgent *agent);
gboolean gboolean
nice_agent_main_context_attach ( nice_agent_main_context_attach (
NiceAgent *agent, NiceAgent *agent,
......
...@@ -56,6 +56,8 @@ component_new ( ...@@ -56,6 +56,8 @@ component_new (
component = g_slice_new0 (Component); component = g_slice_new0 (Component);
component->id = id; component->id = id;
component->state = NICE_COMPONENT_STATE_DISCONNECTED;
component->restart_candidate = NULL;
return component; return component;
} }
...@@ -75,6 +77,10 @@ component_free (Component *cmp) ...@@ -75,6 +77,10 @@ component_free (Component *cmp)
nice_candidate_free (candidate); nice_candidate_free (candidate);
} }
if (cmp->restart_candidate)
nice_candidate_free (cmp->restart_candidate),
cmp->restart_candidate = NULL;
for (i = cmp->sockets; i; i = i->next) { for (i = cmp->sockets; i; i = i->next) {
NiceUDPSocket *udpsocket = i->data; NiceUDPSocket *udpsocket = i->data;
nice_udp_socket_close (udpsocket); nice_udp_socket_close (udpsocket);
...@@ -119,3 +125,34 @@ component_find_udp_socket_by_fd (Component *component, guint fd) ...@@ -119,3 +125,34 @@ component_find_udp_socket_by_fd (Component *component, guint fd)
return NULL; return NULL;
} }
/**
* Resets the component state to that of a ICE restarted
* session.
*/
gboolean
component_restart (Component *cmp)
{
GSList *i;
for (i = cmp->remote_candidates; i; i = i->next) {
NiceCandidate *candidate = i->data;
/* note: do not remove the remote candidate that is
* currently part of the 'selected pair', see ICE
* 9.1.1.1. "ICE Restarts" (ID-17) */
if (candidate == cmp->selected_pair.remote) {
if (cmp->restart_candidate)
nice_candidate_free (cmp->restart_candidate);
cmp->restart_candidate = candidate;
}
else
nice_candidate_free (candidate);
}
g_slist_free (cmp->remote_candidates),
cmp->remote_candidates = NULL;
/* note: component state managed by agent */
return TRUE;
}
...@@ -75,6 +75,7 @@ struct _Component ...@@ -75,6 +75,7 @@ struct _Component
see ICE 11.1. "Sending Media" (ID-17) */ see ICE 11.1. "Sending Media" (ID-17) */
gboolean media_after_tick; /**< true if media received since last gboolean media_after_tick; /**< true if media received since last
keepalive tick */ keepalive tick */
NiceCandidate *restart_candidate; /**< for storing active remote candidate during a restart */
}; };
Component * Component *
...@@ -88,6 +89,9 @@ component_free (Component *cmp); ...@@ -88,6 +89,9 @@ component_free (Component *cmp);
NiceUDPSocket * NiceUDPSocket *
component_find_udp_socket_by_fd (Component *component, guint fd); component_find_udp_socket_by_fd (Component *component, guint fd);
gboolean
component_restart (Component *cmp);
G_END_DECLS G_END_DECLS
#endif /* _NICE_COMPONENT_H */ #endif /* _NICE_COMPONENT_H */
......
...@@ -150,3 +150,38 @@ stream_find_component_by_fd (const Stream *stream, guint fd) ...@@ -150,3 +150,38 @@ stream_find_component_by_fd (const Stream *stream, guint fd)
return NULL; return NULL;
} }
/**
* Initialized the local crendentials for the stream.
*/
void stream_initialize_credentials (Stream *stream, NiceRNG *rng)
{
/* note: generate ufrag/pwd for the stream (see ICE 15.4.
* '"ice-ufrag" and "ice-pwd" Attributes', ID-17) */
nice_rng_generate_bytes_print (rng, NICE_STREAM_DEF_UFRAG - 1, stream->local_ufrag);
nice_rng_generate_bytes_print (rng, NICE_STREAM_DEF_PWD - 1, stream->local_password);
}
/**
* Resets the stream state to that of a ICE restarted
* session.
*/
gboolean
stream_restart (Stream *stream, NiceRNG *rng)
{
GSList *i;
gboolean res = TRUE;
stream->initial_binding_request_received = FALSE;
stream_initialize_credentials (stream, rng);
for (i = stream->components; i && res; i = i->next) {
Component *component = i->data;
res = component_restart (component);
}
return res;
}
...@@ -59,7 +59,7 @@ struct _Stream ...@@ -59,7 +59,7 @@ struct _Stream
guint id; guint id;
guint n_components; guint n_components;
gboolean initial_binding_request_received; gboolean initial_binding_request_received;
GSList *components; /* list of components */ GSList *components; /* list of 'Component' structs */
gchar local_ufrag[NICE_STREAM_MAX_UFRAG]; gchar local_ufrag[NICE_STREAM_MAX_UFRAG];
gchar local_password[NICE_STREAM_MAX_PWD]; gchar local_password[NICE_STREAM_MAX_PWD];
gchar remote_ufrag[NICE_STREAM_MAX_UFRAG]; gchar remote_ufrag[NICE_STREAM_MAX_UFRAG];
...@@ -81,6 +81,12 @@ stream_find_component_by_id (const Stream *stream, guint id); ...@@ -81,6 +81,12 @@ stream_find_component_by_id (const Stream *stream, guint id);
Component * Component *
stream_find_component_by_fd (const Stream *stream, guint fd); stream_find_component_by_fd (const Stream *stream, guint fd);
void
stream_initialize_credentials (Stream *stream, NiceRNG *rng);
gboolean
stream_restart (Stream *stream, NiceRNG *rng);
G_END_DECLS G_END_DECLS
#endif /* _NICE_STREAM_H */ #endif /* _NICE_STREAM_H */
......
...@@ -152,12 +152,17 @@ Special considerations for a SIP client: ...@@ -152,12 +152,17 @@ Special considerations for a SIP client:
Restarting ICE: Restarting ICE:
- ICE processing can be restarted by calling nice_agent_set_remote_candidates() - ICE processing can be restarted by calling nice_agent_restart()
again for a stream. - Restart will clean the set of remote candidates, so client must
- To use the "dribble" mode, client first has to restart the stream with afterwards call nice_agent_set_remote_candidates() after receiving
a new offer/answer for the restarted ICE session.
- Restart will reinitialize the local credentials (see
nice_agent_get_local_credentials()).
- To use the "dribble" mode, client first has to initialize the stream with
calling nice_agent_set_remote_candidates() with an empty set of calling nice_agent_set_remote_candidates() with an empty set of
candidates, and then start adding new remote candidates with candidates, and then start adding new remote candidates with
nice_agent_add_remote_candidate(). nice_agent_add_remote_candidate().
- XXX: initial plan, needs review...
Notes about sending media: Notes about sending media:
......
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