[Nice] [nice/master] Adding compatibility mode and improvements on the main loop integration.
Youness Alaoui
youness.alaoui at collabora.co.uk
Wed Nov 5 14:00:59 PST 2008
darcs-hash:20080422161414-4f0f6-388208b2ac7bb2a7ab06e48151e2152fc0621331.gz
---
agent/agent-priv.h | 4 +-
agent/agent.c | 192 +++++++++++++++++++++++++++++++---------------------
agent/agent.h | 14 +++-
agent/candidate.c | 15 ++++
agent/candidate.h | 3 +
agent/component.h | 1 +
agent/conncheck.c | 26 +++++--
agent/discovery.c | 6 +-
nice/libnice.sym | 2 +-
9 files changed, 169 insertions(+), 94 deletions(-)
diff --git a/agent/agent-priv.h b/agent/agent-priv.h
index 32b7198..e766cf9 100644
--- a/agent/agent-priv.h
+++ b/agent/agent-priv.h
@@ -80,10 +80,7 @@ struct _NiceAgent
GSList *local_addresses; /**< list of NiceAddresses for local
interfaces */
GSList *streams; /**< list of Stream objects */
- gboolean main_context_set; /**< is the main context set */
GMainContext *main_context; /**< main context pointer */
- NiceAgentRecvFunc read_func; /**< callback for media deliver */
- gpointer read_func_data; /**< media delivery callback context */
guint next_candidate_id; /**< id of next created candidate */
guint next_stream_id; /**< id of next created candidate */
NiceRNG *rng; /**< random number generator */
@@ -95,6 +92,7 @@ struct _NiceAgent
guint64 tie_breaker; /**< tie breaker (ICE sect 5.2
"Determining Role" ID-19) */
GMutex * mutex; /* Mutex used for thread-safe lib */
+ NiceCompatibility compatibility; /* property: Compatibility mode */
/* XXX: add pointer to internal data struct for ABI-safe extensions */
};
diff --git a/agent/agent.c b/agent/agent.c
index 4e632ff..325c86f 100644
--- a/agent/agent.c
+++ b/agent/agent.c
@@ -74,7 +74,8 @@ G_DEFINE_TYPE (NiceAgent, nice_agent, G_TYPE_OBJECT);
enum
{
PROP_SOCKET_FACTORY = 1,
- PROP_STUN_SERVER,
+ PROP_COMPATIBILITY,
+ PROP_STUN_SERVER,
PROP_STUN_SERVER_PORT,
PROP_TURN_SERVER,
PROP_TURN_SERVER_PORT,
@@ -99,8 +100,13 @@ enum
static guint signals[N_SIGNALS];
-static gboolean priv_attach_new_stream (NiceAgent *agent, Stream *stream);
-static void priv_deattach_stream (Stream *stream);
+static gboolean priv_attach_stream_component (NiceAgent *agent,
+ Stream *stream,
+ Component *component,
+ GMainContext *ctx,
+ NiceAgentRecvFunc func,
+ gpointer data );
+static void priv_dettach_stream_component (Stream *stream, Component *component);
Stream *agent_find_stream (NiceAgent *agent, guint stream_id)
{
@@ -179,6 +185,15 @@ nice_agent_class_init (NiceAgentClass *klass)
"The socket factory used to create new UDP sockets",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class, PROP_COMPATIBILITY,
+ g_param_spec_uint (
+ "compatibility",
+ "ICE specification compatibility",
+ "The compatibility mode for the agent",
+ NICE_COMPATIBILITY_ID19, NICE_COMPATIBILITY_MSN,
+ NICE_COMPATIBILITY_ID19,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
g_object_class_install_property (gobject_class, PROP_STUN_SERVER,
g_param_spec_string (
"stun-server",
@@ -366,6 +381,7 @@ nice_agent_init (NiceAgent *agent)
agent->discovery_timer_id = 0;
agent->conncheck_timer_id = 0;
agent->keepalive_timer_id = 0;
+ agent->compatibility = NICE_COMPATIBILITY_ID19;
agent->rng = nice_rng_new ();
priv_generate_tie_breaker (agent);
@@ -382,11 +398,17 @@ nice_agent_init (NiceAgent *agent)
* Returns: the new agent
**/
NICEAPI_EXPORT NiceAgent *
-nice_agent_new (NiceUDPSocketFactory *factory)
+nice_agent_new (NiceUDPSocketFactory *factory,
+ GMainContext *ctx, NiceCompatibility compat)
{
- return g_object_new (NICE_TYPE_AGENT,
+ NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
"socket-factory", factory,
+ "compatibility", compat,
NULL);
+
+ agent->main_context = ctx;
+
+ return agent;
}
@@ -407,6 +429,10 @@ nice_agent_get_property (
g_value_set_pointer (value, agent->socket_factory);
break;
+ case PROP_COMPATIBILITY:
+ g_value_set_uint (value, agent->compatibility);
+ break;
+
case PROP_STUN_SERVER:
g_value_set_string (value, agent->stun_server_ip);
break;
@@ -465,6 +491,10 @@ nice_agent_set_property (
agent->socket_factory = g_value_get_pointer (value);
break;
+ case PROP_COMPATIBILITY:
+ agent->compatibility = g_value_get_uint (value);
+ break;
+
case PROP_STUN_SERVER:
agent->stun_server_ip = g_value_dup_string (value);
break;
@@ -690,11 +720,6 @@ nice_agent_add_stream (
}
- /* step: attach the newly created sockets to the mainloop
- * context */
- if (agent->main_context_set && stream->id > 0)
- priv_attach_new_stream (agent, stream);
-
/* note: no async discoveries pending, signal that we are ready */
if (agent->discovery_unsched_items == 0)
agent_signal_gathering_done (agent);
@@ -728,6 +753,7 @@ nice_agent_remove_stream (
/* note that streams/candidates can be in use by other threads */
Stream *stream;
+ GSList *i;
g_mutex_lock (agent->mutex);
stream = agent_find_stream (agent, stream_id);
@@ -742,7 +768,10 @@ nice_agent_remove_stream (
discovery_prune_stream (agent, stream_id);
/* remove the stream itself */
- priv_deattach_stream (stream);
+ for (i = stream->components; i; i = i->next) {
+ priv_dettach_stream_component (stream, (Component *) i->data);
+ }
+
agent->streams = g_slist_remove (agent->streams, stream);
stream_free (stream);
@@ -943,9 +972,11 @@ nice_agent_get_local_credentials (
guint stream_id,
const gchar **ufrag, const gchar **pwd)
{
- Stream *stream = agent_find_stream (agent, stream_id);
+ Stream *stream;
g_mutex_lock (agent->mutex);
+
+ stream = agent_find_stream (agent, stream_id);
if (stream == NULL) {
g_mutex_unlock (agent->mutex);
return FALSE;
@@ -990,6 +1021,10 @@ nice_agent_add_remote_candidate (
const gchar *password)
{
+ /* XXX: to be deprecated */
+
+ g_mutex_lock (agent->mutex);
+
/* XXX: should we allow use of this method without an
* initial call to nice_agent_set_remote_candidates()
* with an empty set? */
@@ -1037,8 +1072,11 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo
const GSList *i;
int added = 0;
- /* XXX: clean up existing remote candidates, and abort any
- * connectivity checks using these candidates */
+
+ if (agent->discovery_unsched_items > 0)
+ return -1;
+
+ g_mutex_lock (agent->mutex);
for (i = candidates; i && added >= 0; i = i->next) {
NiceCandidateDesc *d = (NiceCandidateDesc*) i->data;
@@ -1589,6 +1627,8 @@ struct _IOCtx
Stream *stream;
Component *component;
NiceUDPSocket *socket;
+ NiceAgentRecvFunc recv_func;
+ gpointer recv_data;
};
@@ -1597,7 +1637,9 @@ io_ctx_new (
NiceAgent *agent,
Stream *stream,
Component *component,
- NiceUDPSocket *socket)
+ NiceUDPSocket *socket,
+ NiceAgentRecvFunc func,
+ gpointer data)
{
IOCtx *ctx;
@@ -1607,6 +1649,8 @@ io_ctx_new (
ctx->stream = stream;
ctx->component = component;
ctx->socket = socket;
+ ctx->recv_func = func;
+ ctx->recv_data = data;
}
return ctx;
}
@@ -1643,8 +1687,8 @@ nice_agent_g_source_cb (
MAX_STUN_DATAGRAM_PAYLOAD, buf);
if (len > 0)
- agent->read_func (agent, stream->id, component->id,
- len, buf, agent->read_func_data);
+ ctx->recv_func (agent, stream->id, component->id,
+ len, buf, ctx->recv_data);
g_mutex_unlock (agent->mutex);
return TRUE;
@@ -1654,38 +1698,38 @@ nice_agent_g_source_cb (
* Attaches socket handles of 'stream' to the main eventloop
* context.
*
- * @pre agent->main_context_set == TRUE
*/
-static gboolean priv_attach_new_stream (NiceAgent *agent, Stream *stream)
+static gboolean priv_attach_stream_component (NiceAgent *agent,
+ Stream *stream,
+ Component *component,
+ GMainContext *context,
+ NiceAgentRecvFunc func,
+ gpointer data)
{
- GSList *i, *j;
+ GSList *i;
- for (i = stream->components; i; i = i->next) {
- Component *component = i->data;
-
- for (j = component->sockets; j; j = j->next) {
- NiceUDPSocket *udp_socket = j->data;
- GIOChannel *io;
- GSource *source;
- IOCtx *ctx;
- GSList *modified_list;
-
- io = g_io_channel_unix_new (udp_socket->fileno);
- /* note: without G_IO_ERR the glib mainloop goes into
- * busyloop if errors are encountered */
- source = g_io_create_watch (io, G_IO_IN | G_IO_ERR);
- ctx = io_ctx_new (agent, stream, component, udp_socket);
- g_source_set_callback (source, (GSourceFunc) nice_agent_g_source_cb,
- ctx, (GDestroyNotify) io_ctx_free);
- g_debug ("Attach source %p (stream %u).", source, stream->id);
- g_source_attach (source, NULL);
- modified_list = g_slist_append (component->gsources, source);
- if (!modified_list) {
- g_source_destroy (source);
- return FALSE;
- }
- component->gsources = modified_list;
+ for (i = component->sockets; i; i = i->next) {
+ NiceUDPSocket *udp_socket = i->data;
+ GIOChannel *io;
+ GSource *source;
+ IOCtx *ctx;
+ GSList *modified_list;
+
+ io = g_io_channel_unix_new (udp_socket->fileno);
+ /* note: without G_IO_ERR the glib mainloop goes into
+ * busyloop if errors are encountered */
+ source = g_io_create_watch (io, G_IO_IN | G_IO_ERR);
+ ctx = io_ctx_new (agent, stream, component, udp_socket, func, data);
+ g_source_set_callback (source, (GSourceFunc) nice_agent_g_source_cb,
+ ctx, (GDestroyNotify) io_ctx_free);
+ g_debug ("Attach source %p (stream %u).", source, stream->id);
+ g_source_attach (source, context);
+ modified_list = g_slist_append (component->gsources, source);
+ if (!modified_list) {
+ g_source_destroy (source);
+ return FALSE;
}
+ component->gsources = modified_list;
}
return TRUE;
@@ -1695,59 +1739,51 @@ static gboolean priv_attach_new_stream (NiceAgent *agent, Stream *stream)
* Detaches socket handles of 'stream' from the main eventloop
* context.
*
- * @pre agent->main_context_set == TRUE
*/
-static void priv_deattach_stream (Stream *stream)
+static void priv_dettach_stream_component (Stream *stream, Component *component)
{
- GSList *i, *j;
-
- for (i = stream->components; i; i = i->next) {
- Component *component = i->data;
-
- for (j = component->gsources; j; j = j->next) {
- GSource *source = j->data;
- g_debug ("Detach source %p (stream %u).", source, stream->id);
- g_source_destroy (source);
- }
+ GSList *i;
- g_slist_free (component->gsources),
- component->gsources = NULL;
+ for (i = component->gsources; i; i = i->next) {
+ GSource *source = i->data;
+ g_debug ("Detach source %p (stream %u).", source, stream->id);
+ g_source_destroy (source);
}
+
+ g_slist_free (component->gsources);
+ component->gsources = NULL;
}
NICEAPI_EXPORT gboolean
-nice_agent_main_context_attach (
+nice_agent_attach_recv (
NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
GMainContext *ctx,
NiceAgentRecvFunc func,
gpointer data)
{
- GSList *i;
+ Component *component = NULL;
+ Stream *stream = NULL;
+ gboolean res = TRUE;
g_mutex_lock (agent->mutex);
- if (agent->main_context_set) {
- g_mutex_unlock (agent->mutex);
- return FALSE;
- }
/* attach candidates */
- for (i = agent->streams; i; i = i->next) {
- Stream *stream = i->data;
- gboolean res = priv_attach_new_stream (agent, stream);
- if (!res) {
- g_mutex_unlock (agent->mutex);
- return FALSE;
- }
+ /* step: check that params specify an existing pair */
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component) || component == NULL) {
+ g_mutex_unlock (agent->mutex);
+ return FALSE;
}
-
- agent->main_context = ctx;
- agent->main_context_set = TRUE;
- agent->read_func = func;
- agent->read_func_data = data;
+
+ priv_dettach_stream_component (stream, component);
+ if (func != NULL)
+ res = priv_attach_stream_component (agent, stream, component, ctx, func, data);
g_mutex_unlock (agent->mutex);
- return TRUE;
+ return res;
}
/**
diff --git a/agent/agent.h b/agent/agent.h
index 961cd96..72a14b1 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -96,6 +96,13 @@ typedef enum
NICE_COMPONENT_TYPE_RTCP = 2
} NiceComponentType;
+typedef enum
+{
+ NICE_COMPATIBILITY_ID19 = 1,
+ NICE_COMPATIBILITY_GOOGLE = 2,
+ NICE_COMPATIBILITY_MSN = 3
+} NiceCompatibility;
+
typedef struct _NiceCandidateDesc NiceCandidateDesc;
struct _NiceCandidateDesc {
@@ -125,7 +132,8 @@ struct _NiceAgentClass
GType nice_agent_get_type (void);
NiceAgent *
-nice_agent_new (NiceUDPSocketFactory *factory);
+nice_agent_new (NiceUDPSocketFactory *factory,
+ GMainContext *ctx, NiceCompatibility compat);
gboolean
nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr);
@@ -218,8 +226,10 @@ nice_agent_restart (
NiceAgent *agent);
gboolean
-nice_agent_main_context_attach (
+nice_agent_attach_recv (
NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
GMainContext *ctx,
NiceAgentRecvFunc func,
gpointer data);
diff --git a/agent/candidate.c b/agent/candidate.c
index b0d3025..4e180c8 100644
--- a/agent/candidate.c
+++ b/agent/candidate.c
@@ -94,6 +94,21 @@ nice_candidate_jingle_priority (NiceCandidate *candidate)
return 0;
}
+NICEAPI_EXPORT gfloat
+nice_candidate_msn_priority (NiceCandidate *candidate)
+{
+ switch (candidate->type)
+ {
+ case NICE_CANDIDATE_TYPE_HOST: return 0.830;
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: return 0.550;
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: return 0.550;
+ case NICE_CANDIDATE_TYPE_RELAYED: return 0.450;
+ }
+
+ /* appease GCC */
+ return 0;
+}
+
/**
* ICE 4.1.2.1. "Recommended Formula" (ID-19):
diff --git a/agent/candidate.h b/agent/candidate.h
index 2f1de45..4c89851 100644
--- a/agent/candidate.h
+++ b/agent/candidate.h
@@ -91,6 +91,9 @@ nice_candidate_free (NiceCandidate *candidate);
gfloat
nice_candidate_jingle_priority (NiceCandidate *candidate);
+gfloat
+nice_candidate_msn_priority (NiceCandidate *candidate);
+
guint32
nice_candidate_ice_priority_full (guint type_pref, guint local_pref, guint component_id);
diff --git a/agent/component.h b/agent/component.h
index fd42810..4b7bf85 100644
--- a/agent/component.h
+++ b/agent/component.h
@@ -46,6 +46,7 @@
G_BEGIN_DECLS
+
/* (ICE §4.1.1.1, ID-19) ""For RTP-based media streams, the RTP itself has a component
* ID of 1, and RTCP a component ID of 2. If an agent is using RTCP it MUST
* obtain a candidate for it. If an agent is using both RTP and RTCP, it
diff --git a/agent/conncheck.c b/agent/conncheck.c
index e53742b..fe64a95 100644
--- a/agent/conncheck.c
+++ b/agent/conncheck.c
@@ -481,14 +481,20 @@ gboolean conn_check_schedule_next (NiceAgent *agent)
res = priv_conn_check_tick_unlocked ((gpointer) agent);
/* step: schedule timer if not running yet */
- if (res && agent->conncheck_timer_id == 0)
- agent->conncheck_timer_id =
- g_timeout_add (agent->timer_ta, priv_conn_check_tick, agent);
+ if (res && agent->conncheck_timer_id == 0) {
+ GSource *source = g_timeout_source_new (agent->timer_ta);
+ g_source_set_callback (source, priv_conn_check_tick, agent, NULL);
+ agent->conncheck_timer_id = g_source_attach (source, agent->main_context);
+ g_source_unref (source);
+ }
/* step: also start the keepalive timer */
- if (agent->keepalive_timer_id == 0)
- agent->keepalive_timer_id =
- g_timeout_add (NICE_AGENT_TIMER_TR_DEFAULT, priv_conn_keepalive_tick, agent);
+ if (agent->keepalive_timer_id == 0) {
+ GSource *source = g_timeout_source_new (NICE_AGENT_TIMER_TR_DEFAULT);
+ g_source_set_callback (source, priv_conn_keepalive_tick, agent, NULL);
+ agent->keepalive_timer_id = g_source_attach (source, agent->main_context);
+ g_source_unref (source);
+ }
}
@@ -950,13 +956,17 @@ static gboolean priv_create_check_username (NiceAgent *agent, CandidateCheckPair
if (pair &&
pair->remote && pair->remote->username &&
pair->local && pair->local->username) {
- g_snprintf (dest, dest_len, "%s:%s", pair->remote->username, pair->local->username);
+ g_snprintf (dest, dest_len, "%s%s%s", pair->remote->username,
+ agent->compatibility == NICE_COMPATIBILITY_ID19 ? ":" : "",
+ pair->local->username);
return TRUE;
}
stream = agent_find_stream (agent, pair->stream_id);
if (stream) {
- g_snprintf (dest, dest_len, "%s:%s", stream->remote_ufrag, stream->local_ufrag);
+ g_snprintf (dest, dest_len, "%s%s%s", stream->remote_ufrag,
+ agent->compatibility == NICE_COMPATIBILITY_ID19 ? ":" : "",
+ stream->local_ufrag);
return TRUE;
}
diff --git a/agent/discovery.c b/agent/discovery.c
index 14d0d9c..17d86b3 100644
--- a/agent/discovery.c
+++ b/agent/discovery.c
@@ -597,8 +597,10 @@ void discovery_schedule (NiceAgent *agent)
/* step: run first iteration immediately */
gboolean res = priv_discovery_tick_unlocked (agent);
if (res == TRUE) {
- agent->discovery_timer_id =
- g_timeout_add (agent->timer_ta, priv_discovery_tick, agent);
+ GSource *source = g_timeout_source_new (agent->timer_ta);
+ g_source_set_callback (source, priv_discovery_tick, agent, NULL);
+ agent->discovery_timer_id = g_source_attach (source, agent->main_context);
+ g_source_unref (source);
}
}
}
diff --git a/nice/libnice.sym b/nice/libnice.sym
index aa3ac1d..1c201de 100644
--- a/nice/libnice.sym
+++ b/nice/libnice.sym
@@ -14,11 +14,11 @@ nice_address_to_string
nice_agent_add_local_address
nice_agent_add_remote_candidate
nice_agent_add_stream
+nice_agent_attach_recv
nice_agent_get_local_candidates
nice_agent_get_local_credentials
nice_agent_get_remote_candidates
nice_agent_get_type
-nice_agent_main_context_attach
nice_agent_new
nice_agent_poll_read
nice_agent_recv
--
1.5.6.5
More information about the Nice
mailing list