#endif
#include <glib.h>
+#include <gobject/gvaluecollector.h>
#include <string.h>
#include <errno.h>
#endif
+typedef struct {
+ guint signal_id;
+ GSignalQuery query;
+ GValue *params;
+} QueuedSignal;
+
+
+static void
+free_queued_signal (QueuedSignal *sig)
+{
+ guint i;
+
+ for (i = 0; i < sig->query.n_params; i++) {
+ if (G_VALUE_HOLDS_POINTER (&sig->params[i]))
+ g_free (g_value_get_pointer (&sig->params[i]));
+ g_value_unset (&sig->params[i]);
+ }
+
+ g_slice_free1 (sizeof(GValue) * (sig->query.n_params + 1), sig->params);
+ g_slice_free (QueuedSignal, sig);
+}
+
+void
+agent_unlock_and_emit (NiceAgent *agent)
+{
+ GQueue queue = G_QUEUE_INIT;
+ QueuedSignal *sig;
+
+ queue = agent->pending_signals;
+ g_queue_init (&agent->pending_signals);
+
+ agent_unlock ();
+
+ while ((sig = g_queue_pop_head (&queue))) {
+ g_signal_emitv (sig->params, sig->signal_id, 0, NULL);
+
+ free_queued_signal (sig);
+ }
+}
+
+static void
+agent_queue_signal (NiceAgent *agent, guint signal_id, ...)
+{
+ QueuedSignal *sig;
+ guint i;
+ gchar *error = NULL;
+ va_list var_args;
+
+ sig = g_slice_new (QueuedSignal);
+ g_signal_query (signal_id, &sig->query);
+
+ sig->signal_id = signal_id;
+ sig->params = g_slice_alloc0 (sizeof(GValue) * (sig->query.n_params + 1));
+
+ g_value_init (&sig->params[0], G_TYPE_OBJECT);
+ g_value_set_object (&sig->params[0], agent);
+
+ va_start (var_args, signal_id);
+ for (i = 0; i < sig->query.n_params; i++) {
+ G_VALUE_COLLECT_INIT (&sig->params[i + 1], sig->query.param_types[i],
+ var_args, 0, &error);
+ if (error)
+ break;
+ }
+ va_end (var_args);
+
+ if (error) {
+ free_queued_signal (sig);
+ g_critical ("Error collecting values for signal: %s", error);
+ g_free (error);
+ return;
+ }
+
+ g_queue_push_tail (&agent->pending_signals, sig);
+}
+
+
StunUsageIceCompatibility
agent_to_ice_compatibility (NiceAgent *agent)
{
agent->rng = nice_rng_new ();
priv_generate_tie_breaker (agent);
+
+ g_queue_init (&agent->pending_signals);
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
- agent_unlock();
+ agent_unlock_and_emit(agent);
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
}
nice_debug ("Agent %p: s%d:%d pseudo Tcp socket Opened", agent,
stream->id, component->id);
g_cancellable_cancel (component->tcp_writable_cancellable);
- g_signal_emit (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE], 0,
+
+ agent_queue_signal (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE],
stream->id, component->id);
}
nice_debug ("Agent %p: s%d:%d pseudo Tcp socket writable", agent,
stream->id, component->id);
g_cancellable_cancel (component->tcp_writable_cancellable);
- g_signal_emit (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE], 0,
+ agent_queue_signal (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE],
stream->id, component->id);
}
pseudo_tcp_socket_notify_clock (component->tcp);
adjust_tcp_clock (agent, stream, component);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return G_SOURCE_CONTINUE;
}
Stream *stream = i->data;
if (stream->gathering) {
stream->gathering = FALSE;
- g_signal_emit (agent, signals[SIGNAL_CANDIDATE_GATHERING_DONE], 0, stream->id);
+ agent_queue_signal (agent, signals[SIGNAL_CANDIDATE_GATHERING_DONE],
+ stream->id);
}
}
}
{
if (stream->initial_binding_request_received != TRUE) {
stream->initial_binding_request_received = TRUE;
- g_signal_emit (agent, signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED], 0, stream->id);
+ agent_queue_signal (agent, signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED],
+ stream->id);
}
}
lf_copy = g_strdup (local_foundation);
rf_copy = g_strdup (remote_foundation);
- g_signal_emit (agent, signals[SIGNAL_NEW_SELECTED_PAIR], 0,
+ agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR],
stream_id, component_id, lf_copy, rf_copy);
g_free (lf_copy);
void agent_signal_new_candidate (NiceAgent *agent, NiceCandidate *candidate)
{
- g_signal_emit (agent, signals[SIGNAL_NEW_CANDIDATE], 0,
- candidate->stream_id,
- candidate->component_id,
- candidate->foundation);
+ agent_queue_signal (agent, signals[SIGNAL_NEW_CANDIDATE],
+ candidate->stream_id, candidate->component_id, candidate->foundation);
}
void agent_signal_new_remote_candidate (NiceAgent *agent, NiceCandidate *candidate)
{
- g_signal_emit (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE], 0,
- candidate->stream_id,
- candidate->component_id,
- candidate->foundation);
+ agent_queue_signal (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE],
+ candidate->stream_id, candidate->component_id, candidate->foundation);
}
static const gchar *
process_queued_tcp_packets (agent, stream, component);
- g_signal_emit (agent, signals[SIGNAL_COMPONENT_STATE_CHANGED], 0,
- stream_id, component_id, state);
+ agent_queue_signal (agent, signals[SIGNAL_COMPONENT_STATE_CHANGED],
+ stream_id, component_id, state);
}
}
ret = stream->id;
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
nice_address_set_port (&turn->server, server_port);
} else {
g_slice_free (TurnServer, turn);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return FALSE;
}
component->turn_servers = g_list_append (component->turn_servers, turn);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
return TRUE;
}
agent_gathering_done (agent);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return FALSE;
}
agent_gathering_done (agent);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
}
static void _upnp_error_mapping_port (GUPnPSimpleIgd *self, GError *error,
}
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
}
#endif
stream = agent_find_stream (agent, stream_id);
if (stream == NULL) {
- agent_unlock();
+ agent_unlock_and_emit (agent);
return FALSE;
}
discovery_prune_stream (agent, stream_id);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
stream = agent_find_stream (agent, stream_id);
if (!stream) {
- agent_unlock ();
+ agent_unlock_and_emit (agent);
return;
}
if (!agent->streams)
priv_remove_keepalive_timer (agent);
- agent_unlock ();
-
- g_signal_emit (agent, signals[SIGNAL_STREAMS_REMOVED], 0, stream_ids);
+ agent_queue_signal (agent, signals[SIGNAL_STREAMS_REMOVED], stream_ids);
+ agent_unlock_and_emit (agent);
return;
}
component->max_port = max_port;
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
}
NICEAPI_EXPORT gboolean
nice_address_set_port (dup, 0);
agent->local_addresses = g_slist_append (agent->local_addresses, dup);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return TRUE;
}
}
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
added = _set_remote_candidates_locked (agent, stream, component, candidates);
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return added;
}
memcpy (&prev_recv_messages_iter, &component->recv_messages_iter,
sizeof (NiceInputMessageIter));
- agent_unlock ();
+
+ agent_unlock_and_emit (agent);
g_main_context_iteration (context, blocking);
agent_lock ();
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
+ "Component removed during call.");
+ goto done;
+ }
+
received_enough =
nice_input_message_iter_is_at_end (&component->recv_messages_iter,
component->recv_messages, component->n_recv_messages);
if (child_error != NULL)
g_propagate_error (error, child_error);
- agent_unlock ();
+ agent_unlock_and_emit (agent);
if (messages_orig) {
for (i = 0; i < n_messages; i++) {
if (child_error != NULL)
g_propagate_error (error, child_error);
- agent_unlock ();
+ agent_unlock_and_emit (agent);
return n_sent;
}
ret = g_slist_append (ret, nice_candidate_copy (item->data));
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
ret = g_slist_append (ret, nice_candidate_copy (item->data));
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
res = stream_restart (stream, agent->rng);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
return res;
}
done:
g_object_unref (agent);
- agent_unlock ();
+ agent_unlock_and_emit (agent);
return !remove_source;
}
}
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
ret = TRUE;
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
}
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
g_socket = g_object_ref (nice_socket->fileno);
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return g_socket;
}
ret = TRUE;
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
}
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
}
NICEAPI_EXPORT void
stun_agent_set_software (&agent->stun_agent, agent->software_attribute);
- agent_unlock ();
+ agent_unlock_and_emit (agent);
}
NICEAPI_EXPORT gboolean
ret = TRUE;
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
name = stream->name;
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return name;
}
default_candidate = nice_candidate_copy (default_candidate);
done:
- agent_unlock ();
+ agent_unlock_and_emit (agent);
return default_candidate;
}
_generate_stream_sdp (agent, stream, sdp, TRUE);
}
- agent_unlock();
+ agent_unlock_and_emit (agent);
return g_string_free (sdp, FALSE);
}
ret = g_string_free (sdp, FALSE);
done:
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
sdp = g_string_new (NULL);
_generate_candidate_sdp (agent, candidate, sdp);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return g_string_free (sdp, FALSE);
}
if (sdp_lines)
g_strfreev(sdp_lines);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return ret;
}
if (sdp_lines)
g_strfreev(sdp_lines);
- agent_unlock();
+ agent_unlock_and_emit (agent);
return candidates;
}
iostream = g_object_ref (component->iostream);
done:
- agent_unlock ();
+ agent_unlock_and_emit (agent);
return iostream;
}