2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2006-2009 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
25 * Dafydd Harries, Collabora Ltd.
26 * Youness Alaoui, Collabora Ltd.
29 * Alternatively, the contents of this file may be used under the terms of the
30 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
31 * case the provisions of LGPL are applicable instead of those above. If you
32 * wish to allow use of your version of this file only under the terms of the
33 * LGPL and not to allow others to use your version of this file under the
34 * MPL, indicate your decision by deleting the provisions above and replace
35 * them with the notice and other provisions required by the LGPL. If you do
36 * not delete the provisions above, a recipient may use your version of this
37 * file under either the MPL or the LGPL.
42 * @brief ICE component functions
45 /* Simple tracking for the number of alive components. These must be accessed
47 static volatile unsigned int n_components_created = 0;
48 static volatile unsigned int n_components_destroyed = 0;
58 #include "component.h"
59 #include "discovery.h"
60 #include "agent-priv.h"
62 G_DEFINE_TYPE (NiceComponent, nice_component, G_TYPE_OBJECT);
68 } NiceComponentProperty;
71 nice_component_constructed (GObject *obj);
73 nice_component_get_property (GObject *obj,
74 guint property_id, GValue *value, GParamSpec *pspec);
76 nice_component_set_property (GObject *obj,
77 guint property_id, const GValue *value, GParamSpec *pspec);
79 nice_component_finalize (GObject *obj);
82 nice_component_schedule_io_callback (NiceComponent *component);
84 nice_component_deschedule_io_callback (NiceComponent *component);
86 nice_component_detach_socket (NiceComponent *component, NiceSocket *nicesock);
88 nice_component_clear_selected_pair (NiceComponent *component);
92 incoming_check_free (IncomingCheck *icheck)
94 g_free (icheck->username);
95 g_slice_free (IncomingCheck, icheck);
98 /* Must *not* take the agent lock, since it’s called from within
99 * nice_component_set_io_context(), which holds the Component’s I/O lock. */
101 socket_source_attach (SocketSource *socket_source, GMainContext *context)
105 if (socket_source->socket->fileno == NULL)
108 /* Do not create a GSource for UDP turn socket, because it
109 * would duplicate the packets already received on the base
112 if (socket_source->socket->type == NICE_SOCKET_TYPE_UDP_TURN)
115 /* Create a source. */
116 source = g_socket_create_source (socket_source->socket->fileno,
118 g_source_set_callback (source, (GSourceFunc) G_CALLBACK (component_io_cb),
119 socket_source, NULL);
121 /* Add the source. */
122 nice_debug ("Attaching source %p (socket %p, FD %d) to context %p", source,
123 socket_source->socket, g_socket_get_fd (socket_source->socket->fileno),
126 g_assert (socket_source->source == NULL);
127 socket_source->source = source;
128 g_source_attach (source, context);
132 socket_source_detach (SocketSource *source)
134 nice_debug ("Detaching source %p (socket %p, FD %d) from context %p",
135 source->source, source->socket,
136 (source->socket->fileno != NULL) ?
137 g_socket_get_fd (source->socket->fileno) : 0,
138 (source->source != NULL) ? g_source_get_context (source->source) : 0);
140 if (source->source != NULL) {
141 g_source_destroy (source->source);
142 g_source_unref (source->source);
144 source->source = NULL;
148 socket_source_free (SocketSource *source)
150 socket_source_detach (source);
151 nice_socket_free (source->socket);
153 g_slice_free (SocketSource, source);
157 nice_component_new (guint id, NiceAgent *agent, NiceStream *stream)
159 return g_object_new (NICE_TYPE_COMPONENT,
167 nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
173 stream = agent_find_stream (agent, cmp->stream_id);
175 discovery_prune_socket (agent, nsocket);
177 conn_check_prune_socket (agent, stream, cmp, nsocket);
179 for (i = cmp->local_candidates; i;) {
180 NiceCandidate *candidate = i->data;
181 GSList *next = i->next;
183 if (!nice_socket_is_based_on (candidate->sockptr, nsocket)) {
188 if (candidate == cmp->selected_pair.local) {
189 nice_component_clear_selected_pair (cmp);
190 agent_signal_component_state_change (agent, cmp->stream_id,
191 cmp->id, NICE_COMPONENT_STATE_FAILED);
194 refresh_prune_candidate (agent, candidate);
195 if (candidate->sockptr != nsocket && stream) {
196 discovery_prune_socket (agent, candidate->sockptr);
197 conn_check_prune_socket (agent, stream, cmp,
199 nice_component_detach_socket (cmp, candidate->sockptr);
201 agent_remove_local_candidate (agent, candidate);
202 nice_candidate_free (candidate);
204 cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i);
208 /* The nsocket to be removed may also come from a
209 * peer-reflexive remote candidate
211 for (i = cmp->remote_candidates; i;) {
212 NiceCandidate *candidate = i->data;
213 GSList *next = i->next;
215 if (candidate->sockptr != nsocket) {
220 if (candidate == cmp->selected_pair.remote) {
221 nice_component_clear_selected_pair (cmp);
222 agent_signal_component_state_change (agent, cmp->stream_id,
223 cmp->id, NICE_COMPONENT_STATE_FAILED);
227 conn_check_prune_socket (agent, stream, cmp, candidate->sockptr);
229 nice_candidate_free (candidate);
231 cmp->remote_candidates = g_slist_delete_link (cmp->remote_candidates, i);
235 nice_component_detach_socket (cmp, nsocket);
239 on_candidate_refreshes_pruned (NiceAgent *agent, NiceCandidate *candidate)
241 NiceComponent *component;
243 if (agent_find_component (agent, candidate->stream_id,
244 candidate->component_id, NULL, &component)) {
245 nice_component_detach_socket (component, candidate->sockptr);
248 nice_candidate_free (candidate);
250 return G_SOURCE_REMOVE;
254 nice_component_clean_turn_servers (NiceAgent *agent, NiceComponent *cmp)
257 GSList *relay_candidates = NULL;
260 stream = agent_find_stream (agent, cmp->stream_id);
262 g_list_free_full (cmp->turn_servers, (GDestroyNotify) turn_server_unref);
263 cmp->turn_servers = NULL;
265 for (i = cmp->local_candidates; i;) {
266 NiceCandidate *candidate = i->data;
267 GSList *next = i->next;
269 if (candidate->type != NICE_CANDIDATE_TYPE_RELAYED) {
274 /* note: do not remove the remote candidate that is
275 * currently part of the 'selected pair', see ICE
276 * 9.1.1.1. "ICE Restarts" (ID-19)
278 * So what we do instead is that we put the selected candidate
279 * in a special location and keep it "alive" that way. This is
280 * especially important for TURN, because refresh requests to the
281 * server need to keep happening.
283 if (candidate == cmp->selected_pair.local) {
284 if (cmp->turn_candidate) {
285 relay_candidates = g_slist_append(relay_candidates, cmp->turn_candidate);
287 /* Bring the priority down to 0, so that it will be replaced
290 cmp->selected_pair.priority = 0;
291 cmp->turn_candidate = candidate;
293 agent_remove_local_candidate (agent, candidate);
294 relay_candidates = g_slist_append(relay_candidates, candidate);
296 cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i);
300 for (i = relay_candidates; i; i = i->next) {
301 NiceCandidate * candidate = i->data;
303 discovery_prune_socket (agent, candidate->sockptr);
305 conn_check_prune_socket (agent, stream, cmp, candidate->sockptr);
308 refresh_prune_candidate_async (agent, candidate,
309 (NiceTimeoutLockedCallback) on_candidate_refreshes_pruned);
314 nice_component_clear_selected_pair (NiceComponent *component)
316 if (component->selected_pair.keepalive.tick_source != NULL) {
317 g_source_destroy (component->selected_pair.keepalive.tick_source);
318 g_source_unref (component->selected_pair.keepalive.tick_source);
319 component->selected_pair.keepalive.tick_source = NULL;
322 memset (&component->selected_pair, 0, sizeof(CandidatePair));
325 /* Must be called with the agent lock held as it touches internal Component
328 nice_component_close (NiceAgent *agent, NiceComponent *cmp)
330 IOCallbackData *data;
334 /* Start closing the pseudo-TCP socket first. FIXME: There is a very big and
335 * reliably triggerable race here. pseudo_tcp_socket_close() does not block
336 * on the socket closing — it only sends the first packet of the FIN
337 * handshake. nice_component_close() will immediately afterwards close the
338 * underlying component sockets, aborting the handshake.
340 * On the principle that starting the FIN handshake is better than not
341 * starting it, even if it’s later truncated, call pseudo_tcp_socket_close().
342 * A long-term fix is needed in the form of making nice_component_close() (and
343 * all its callers) async, so we can properly block on closure. */
345 pseudo_tcp_socket_close (cmp->tcp, TRUE);
348 if (cmp->restart_candidate)
349 nice_candidate_free (cmp->restart_candidate),
350 cmp->restart_candidate = NULL;
352 if (cmp->turn_candidate)
353 nice_candidate_free (cmp->turn_candidate),
354 cmp->turn_candidate = NULL;
356 while (cmp->local_candidates) {
357 agent_remove_local_candidate (agent, cmp->local_candidates->data);
358 nice_candidate_free (cmp->local_candidates->data);
359 cmp->local_candidates = g_slist_delete_link (cmp->local_candidates,
360 cmp->local_candidates);
363 g_slist_free_full (cmp->remote_candidates,
364 (GDestroyNotify) nice_candidate_free);
365 cmp->remote_candidates = NULL;
366 nice_component_free_socket_sources (cmp);
368 while ((c = g_queue_pop_head (&cmp->incoming_checks)))
369 incoming_check_free (c);
371 nice_component_clean_turn_servers (agent, cmp);
373 if (cmp->tcp_clock) {
374 g_source_destroy (cmp->tcp_clock);
375 g_source_unref (cmp->tcp_clock);
376 cmp->tcp_clock = NULL;
378 if (cmp->tcp_writable_cancellable) {
379 g_cancellable_cancel (cmp->tcp_writable_cancellable);
380 g_clear_object (&cmp->tcp_writable_cancellable);
383 while ((data = g_queue_pop_head (&cmp->pending_io_messages)) != NULL)
384 io_callback_data_free (data);
386 nice_component_deschedule_io_callback (cmp);
388 g_cancellable_cancel (cmp->stop_cancellable);
390 while ((vec = g_queue_pop_head (&cmp->queued_tcp_packets)) != NULL) {
391 g_free ((gpointer) vec->buffer);
392 g_slice_free (GOutputVector, vec);
397 * Finds a candidate pair that has matching foundation ids.
399 * @return TRUE if pair found, pointer to pair stored at 'pair'
402 nice_component_find_pair (NiceComponent *cmp, NiceAgent *agent, const gchar *lfoundation, const gchar *rfoundation, CandidatePair *pair)
405 CandidatePair result = { 0, };
407 for (i = cmp->local_candidates; i; i = i->next) {
408 NiceCandidate *candidate = i->data;
409 if (strncmp (candidate->foundation, lfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
410 result.local = candidate;
415 for (i = cmp->remote_candidates; i; i = i->next) {
416 NiceCandidate *candidate = i->data;
417 if (strncmp (candidate->foundation, rfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
418 result.remote = candidate;
423 if (result.local && result.remote) {
424 result.priority = agent_candidate_pair_priority (agent, result.local, result.remote);
434 * Resets the component state to that of a ICE restarted
438 nice_component_restart (NiceComponent *cmp)
443 for (i = cmp->remote_candidates; i; i = i->next) {
444 NiceCandidate *candidate = i->data;
446 /* note: do not remove the remote candidate that is
447 * currently part of the 'selected pair', see ICE
448 * 9.1.1.1. "ICE Restarts" (ID-19) */
449 if (candidate == cmp->selected_pair.remote) {
450 if (cmp->restart_candidate)
451 nice_candidate_free (cmp->restart_candidate);
452 cmp->restart_candidate = candidate;
455 nice_candidate_free (candidate);
457 g_slist_free (cmp->remote_candidates),
458 cmp->remote_candidates = NULL;
460 while ((c = g_queue_pop_head (&cmp->incoming_checks)))
461 incoming_check_free (c);
463 /* Reset the priority to 0 to make sure we get a new pair */
464 cmp->selected_pair.priority = 0;
466 /* note: component state managed by agent */
470 * Changes the selected pair for the component to 'pair'. Does not
471 * emit the "selected-pair-changed" signal.
474 nice_component_update_selected_pair (NiceAgent *agent, NiceComponent *component, const CandidatePair *pair)
477 gchar priority[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
479 g_assert (component);
482 stream = agent_find_stream (agent, component->stream_id);
484 nice_candidate_pair_priority_to_string (pair->priority, priority);
485 nice_debug ("setting SELECTED PAIR for component %u: %s:%s (prio:%s).",
486 component->id, pair->local->foundation,
487 pair->remote->foundation, priority);
489 if (component->selected_pair.local &&
490 component->selected_pair.local == component->turn_candidate) {
491 discovery_prune_socket (agent,
492 component->turn_candidate->sockptr);
494 conn_check_prune_socket (agent, stream, component,
495 component->turn_candidate->sockptr);
496 refresh_prune_candidate_async (agent, component->turn_candidate,
497 (NiceTimeoutLockedCallback) on_candidate_refreshes_pruned);
498 component->turn_candidate = NULL;
501 nice_component_clear_selected_pair (component);
503 component->selected_pair.local = pair->local;
504 component->selected_pair.remote = pair->remote;
505 component->selected_pair.priority = pair->priority;
506 component->selected_pair.stun_priority = pair->stun_priority;
508 nice_component_add_valid_candidate (agent, component, pair->remote);
512 * Finds a remote candidate with matching address and
515 * @return pointer to candidate or NULL if not found
518 nice_component_find_remote_candidate (NiceComponent *component, const NiceAddress *addr, NiceCandidateTransport transport)
522 for (i = component->remote_candidates; i; i = i->next) {
523 NiceCandidate *candidate = i->data;
525 if (nice_address_equal(&candidate->addr, addr) &&
526 candidate->transport == transport)
535 * Sets the desired remote candidate as the selected pair
537 * It will start sending on the highest priority pair available with
542 nice_component_set_selected_remote_candidate (NiceComponent *component,
543 NiceAgent *agent, NiceCandidate *candidate)
545 NiceCandidate *local = NULL;
546 NiceCandidate *remote = NULL;
547 guint64 priority = 0;
550 g_assert (candidate != NULL);
552 for (item = component->local_candidates; item; item = g_slist_next (item)) {
553 NiceCandidate *tmp = item->data;
554 guint64 tmp_prio = 0;
556 if (tmp->transport != conn_check_match_transport(candidate->transport) ||
557 tmp->addr.s.addr.sa_family != candidate->addr.s.addr.sa_family ||
558 tmp->type != NICE_CANDIDATE_TYPE_HOST)
561 tmp_prio = agent_candidate_pair_priority (agent, tmp, candidate);
563 if (tmp_prio > priority) {
572 remote = nice_component_find_remote_candidate (component, &candidate->addr,
573 candidate->transport);
576 remote = nice_candidate_copy (candidate);
577 component->remote_candidates = g_slist_append (component->remote_candidates,
579 agent_signal_new_remote_candidate (agent, remote);
582 nice_component_clear_selected_pair (component);
584 component->selected_pair.local = local;
585 component->selected_pair.remote = remote;
586 component->selected_pair.priority = priority;
588 /* Get into fallback mode where packets from any source is accepted once
589 * this has been called. This is the expected behavior of pre-ICE SIP.
591 component->fallback_mode = TRUE;
597 _find_socket_source (gconstpointer a, gconstpointer b)
599 const SocketSource *source_a = a;
600 const NiceSocket *socket_b = b;
602 return (source_a->socket == socket_b) ? 0 : 1;
605 /* This takes ownership of the socket.
606 * It creates and attaches a source to the component’s context. */
608 nice_component_attach_socket (NiceComponent *component, NiceSocket *nicesock)
611 SocketSource *socket_source;
613 g_assert (component != NULL);
614 g_assert (nicesock != NULL);
616 g_assert (component->ctx != NULL);
618 /* Find an existing SocketSource in the component which contains @socket, or
621 * Whenever a source is added or remove to socket_sources, socket_sources_age
622 * must be incremented.
624 l = g_slist_find_custom (component->socket_sources, nicesock,
625 _find_socket_source);
627 socket_source = l->data;
629 socket_source = g_slice_new0 (SocketSource);
630 socket_source->socket = nicesock;
631 socket_source->component = component;
632 component->socket_sources =
633 g_slist_prepend (component->socket_sources, socket_source);
634 if (nicesock->fileno != NULL)
635 component->socket_sources_age++;
638 /* Create and attach a source */
639 nice_debug ("Component %p: Attach source (stream %u).",
640 component, component->stream_id);
641 socket_source_attach (socket_source, component->ctx);
644 /* Reattaches socket handles of @component to the main context.
646 * Must *not* take the agent lock, since it’s called from within
647 * nice_component_set_io_context(), which holds the Component’s I/O lock. */
649 nice_component_reattach_all_sockets (NiceComponent *component)
653 for (i = component->socket_sources; i != NULL; i = i->next) {
654 SocketSource *socket_source = i->data;
655 nice_debug ("Reattach source %p.", socket_source->source);
656 socket_source_detach (socket_source);
657 socket_source_attach (socket_source, component->ctx);
662 * nice_component_detach_socket:
663 * @component: a #NiceComponent
664 * @socket: the socket to detach the source for
666 * Detach the #GSource for the single specified @socket. It also closes it
669 * If the @socket doesn’t exist in this @component, do nothing.
672 nice_component_detach_socket (NiceComponent *component, NiceSocket *nicesock)
676 SocketSource *socket_source;
678 nice_debug ("Detach socket %p.", nicesock);
680 /* Remove the socket from various lists. */
681 for (l = component->incoming_checks.head; l != NULL;) {
682 IncomingCheck *icheck = l->data;
683 GList *next = l->next;
685 if (icheck->local_socket == nicesock) {
686 g_queue_delete_link (&component->incoming_checks, l);
687 incoming_check_free (icheck);
693 /* Find the SocketSource for the socket. */
694 s = g_slist_find_custom (component->socket_sources, nicesock,
695 _find_socket_source);
699 /* Detach the source. */
700 socket_source = s->data;
701 component->socket_sources = g_slist_delete_link (component->socket_sources, s);
702 component->socket_sources_age++;
704 socket_source_free (socket_source);
708 * Detaches socket handles of @component from the main context. Leaves the
709 * sockets themselves untouched.
711 * Must *not* take the agent lock, since it’s called from within
712 * nice_component_set_io_context(), which holds the Component’s I/O lock.
715 nice_component_detach_all_sockets (NiceComponent *component)
719 for (i = component->socket_sources; i != NULL; i = i->next) {
720 SocketSource *socket_source = i->data;
721 nice_debug ("Detach source %p, socket %p.", socket_source->source,
722 socket_source->socket);
723 socket_source_detach (socket_source);
728 nice_component_free_socket_sources (NiceComponent *component)
730 nice_debug ("Free socket sources for component %p.", component);
732 g_slist_free_full (component->socket_sources,
733 (GDestroyNotify) socket_source_free);
734 component->socket_sources = NULL;
735 component->socket_sources_age++;
737 nice_component_clear_selected_pair (component);
741 nice_component_dup_io_context (NiceComponent *component)
743 return g_main_context_ref (component->own_ctx);
746 /* If @context is %NULL, it's own context is used, so component->ctx is always
747 * guaranteed to be non-%NULL. */
749 nice_component_set_io_context (NiceComponent *component, GMainContext *context)
751 g_mutex_lock (&component->io_mutex);
753 if (component->ctx != context) {
755 context = g_main_context_ref (component->own_ctx);
757 g_main_context_ref (context);
759 nice_component_detach_all_sockets (component);
760 g_main_context_unref (component->ctx);
762 component->ctx = context;
763 nice_component_reattach_all_sockets (component);
766 g_mutex_unlock (&component->io_mutex);
769 /* (func, user_data) and (recv_messages, n_recv_messages) are mutually
770 * exclusive. At most one of the two must be specified; if both are NULL, the
771 * Component will not receive any data (i.e. reception is paused).
773 * Apart from during setup, this must always be called with the agent lock held,
774 * and the I/O lock released (because it takes the I/O lock itself). Requiring
775 * the agent lock to be held means it can’t be called between a packet being
776 * dequeued from the kernel buffers in agent.c, and an I/O callback being
777 * emitted for it (which could cause data loss if the I/O callback function was
778 * unset in that time). */
780 nice_component_set_io_callback (NiceComponent *component,
781 NiceAgentRecvFunc func, gpointer user_data,
782 NiceInputMessage *recv_messages, guint n_recv_messages,
785 g_assert (func == NULL || recv_messages == NULL);
786 g_assert (n_recv_messages == 0 || recv_messages != NULL);
787 g_assert (error == NULL || *error == NULL);
789 g_mutex_lock (&component->io_mutex);
792 component->io_callback = func;
793 component->io_user_data = user_data;
794 component->recv_messages = NULL;
795 component->n_recv_messages = 0;
797 nice_component_schedule_io_callback (component);
799 component->io_callback = NULL;
800 component->io_user_data = NULL;
801 component->recv_messages = recv_messages;
802 component->n_recv_messages = n_recv_messages;
804 nice_component_deschedule_io_callback (component);
807 nice_input_message_iter_reset (&component->recv_messages_iter);
808 component->recv_buf_error = error;
810 g_mutex_unlock (&component->io_mutex);
814 nice_component_has_io_callback (NiceComponent *component)
816 gboolean has_io_callback;
818 g_mutex_lock (&component->io_mutex);
819 has_io_callback = (component->io_callback != NULL);
820 g_mutex_unlock (&component->io_mutex);
822 return has_io_callback;
826 io_callback_data_new (const guint8 *buf, gsize buf_len)
828 IOCallbackData *data;
830 data = g_slice_new0 (IOCallbackData);
831 data->buf = g_memdup (buf, buf_len);
832 data->buf_len = buf_len;
839 io_callback_data_free (IOCallbackData *data)
842 g_slice_free (IOCallbackData, data);
845 /* This is called with the global agent lock released. It does not take that
846 * lock, but does take the io_mutex. */
848 emit_io_callback_cb (gpointer user_data)
850 NiceComponent *component = user_data;
851 IOCallbackData *data;
852 NiceAgentRecvFunc io_callback;
853 gpointer io_user_data;
854 guint stream_id, component_id;
857 agent = g_weak_ref_get (&component->agent_ref);
859 nice_debug ("Agent for component %p is gone", component);
863 stream_id = component->stream_id;
864 component_id = component->id;
866 g_mutex_lock (&component->io_mutex);
868 /* The members of Component are guaranteed not to have changed since this
869 * GSource was attached in nice_component_emit_io_callback(). The Component’s agent
870 * and stream are immutable after construction, as are the stream and
871 * component IDs. The callback and its user data may have changed, but are
872 * guaranteed to be non-%NULL at the start as the idle source is removed when
873 * the callback is set to %NULL. They may become %NULL during the io_callback,
874 * so must be re-checked every loop iteration. The data buffer is copied into
875 * the #IOCallbackData closure.
877 * If the component is destroyed (which happens if the agent or stream are
878 * destroyed) between attaching the GSource and firing it, the GSource is
879 * detached during dispose and this callback is never invoked. If the
880 * agent is destroyed during an io_callback, its weak pointer will be
881 * nullified. Similarly, the Component needs to be re-queried for after every
882 * iteration, just in case the client has removed the stream in the
885 io_callback = component->io_callback;
886 io_user_data = component->io_user_data;
887 data = g_queue_peek_head (&component->pending_io_messages);
889 if (data == NULL || io_callback == NULL)
892 g_mutex_unlock (&component->io_mutex);
894 io_callback (agent, stream_id, component_id,
895 data->buf_len - data->offset, (gchar *) data->buf + data->offset,
898 /* Check for the user destroying things underneath our feet. */
899 if (!agent_find_component (agent, stream_id, component_id,
901 nice_debug ("%s: Agent or component destroyed.", G_STRFUNC);
905 g_queue_pop_head (&component->pending_io_messages);
906 io_callback_data_free (data);
908 g_mutex_lock (&component->io_mutex);
911 component->io_callback_id = 0;
912 g_mutex_unlock (&component->io_mutex);
915 g_object_unref (agent);
917 return G_SOURCE_REMOVE;
920 /* This must be called with the agent lock *held*. */
922 nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
923 const guint8 *buf, gsize buf_len)
925 guint stream_id, component_id;
926 NiceAgentRecvFunc io_callback;
927 gpointer io_user_data;
929 g_assert (component != NULL);
930 g_assert (buf != NULL);
931 g_assert (buf_len > 0);
933 stream_id = component->stream_id;
934 component_id = component->id;
936 g_mutex_lock (&component->io_mutex);
937 io_callback = component->io_callback;
938 io_user_data = component->io_user_data;
939 g_mutex_unlock (&component->io_mutex);
941 /* Allow this to be called with a NULL io_callback, since the caller can’t
942 * lock io_mutex to check beforehand. */
943 if (io_callback == NULL)
946 g_assert (NICE_IS_AGENT (agent));
947 g_assert_cmpuint (stream_id, >, 0);
948 g_assert_cmpuint (component_id, >, 0);
949 g_assert (io_callback != NULL);
951 /* Only allocate a closure if the callback is being deferred to an idle
953 if (g_main_context_is_owner (component->ctx)) {
954 /* Thread owns the main context, so invoke the callback directly. */
955 agent_unlock_and_emit (agent);
956 io_callback (agent, stream_id,
957 component_id, buf_len, (gchar *) buf, io_user_data);
960 IOCallbackData *data;
962 g_mutex_lock (&component->io_mutex);
964 /* Slow path: Current thread doesn’t own the Component’s context at the
965 * moment, so schedule the callback in an idle handler. */
966 data = io_callback_data_new (buf, buf_len);
967 g_queue_push_tail (&component->pending_io_messages,
968 data); /* transfer ownership */
970 nice_debug ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
972 nice_component_schedule_io_callback (component);
974 g_mutex_unlock (&component->io_mutex);
978 /* Note: Must be called with the io_mutex held. */
980 nice_component_schedule_io_callback (NiceComponent *component)
984 /* Already scheduled or nothing to schedule? */
985 if (component->io_callback_id != 0 ||
986 g_queue_is_empty (&component->pending_io_messages))
989 /* Add the idle callback. If nice_agent_attach_recv() is called with a
990 * NULL callback before this source is dispatched, the source will be
991 * destroyed, but any pending data will remain in
992 * component->pending_io_messages, ready to be picked up when a callback
993 * is re-attached, or if nice_agent_recv() is called. */
994 source = g_idle_source_new ();
995 g_source_set_priority (source, G_PRIORITY_DEFAULT);
996 g_source_set_callback (source, emit_io_callback_cb, component, NULL);
997 component->io_callback_id = g_source_attach (source, component->ctx);
998 g_source_unref (source);
1001 /* Note: Must be called with the io_mutex held. */
1003 nice_component_deschedule_io_callback (NiceComponent *component)
1005 /* Already descheduled? */
1006 if (component->io_callback_id == 0)
1009 g_source_remove (component->io_callback_id);
1010 component->io_callback_id = 0;
1014 nice_component_class_init (NiceComponentClass *klass)
1016 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1018 object_class->constructed = nice_component_constructed;
1019 object_class->get_property = nice_component_get_property;
1020 object_class->set_property = nice_component_set_property;
1021 object_class->finalize = nice_component_finalize;
1026 * The unique numeric ID of the component.
1030 g_object_class_install_property (object_class, PROP_ID,
1034 "The unique numeric ID of the component.",
1036 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1039 * NiceComponent:agent:
1041 * The #NiceAgent this component belongs to.
1045 g_object_class_install_property (object_class, PROP_AGENT,
1046 g_param_spec_object (
1049 "The NiceAgent this component belongs to.",
1051 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1054 * NiceComponent:stream:
1056 * The #NiceStream this component belongs to.
1060 g_object_class_install_property (object_class, PROP_STREAM,
1061 g_param_spec_object (
1064 "The NiceStream this component belongs to.",
1066 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1070 dummy_callback (gpointer data)
1072 return G_SOURCE_CONTINUE;
1076 source_set_dummy_callback (GSource *source)
1078 g_source_set_callback (source, dummy_callback, NULL, NULL);
1082 nice_component_init (NiceComponent *component)
1084 g_atomic_int_inc (&n_components_created);
1085 nice_debug ("Created NiceComponent (%u created, %u destroyed)",
1086 n_components_created, n_components_destroyed);
1089 component->state = NICE_COMPONENT_STATE_DISCONNECTED;
1090 component->restart_candidate = NULL;
1091 component->tcp = NULL;
1092 g_weak_ref_init (&component->agent_ref, NULL);
1094 g_mutex_init (&component->io_mutex);
1095 g_queue_init (&component->pending_io_messages);
1096 component->io_callback_id = 0;
1098 component->own_ctx = g_main_context_new ();
1099 component->stop_cancellable = g_cancellable_new ();
1100 component->stop_cancellable_source =
1101 g_cancellable_source_new (component->stop_cancellable);
1102 source_set_dummy_callback (component->stop_cancellable_source);
1103 g_source_attach (component->stop_cancellable_source, component->own_ctx);
1104 component->ctx = g_main_context_ref (component->own_ctx);
1106 /* Start off with a fresh main context and all I/O paused. This
1107 * will be updated when nice_agent_attach_recv() or nice_agent_recv_messages()
1109 nice_component_set_io_context (component, NULL);
1110 nice_component_set_io_callback (component, NULL, NULL, NULL, 0, NULL);
1112 g_queue_init (&component->queued_tcp_packets);
1113 g_queue_init (&component->incoming_checks);
1117 nice_component_constructed (GObject *obj)
1119 NiceComponent *component;
1122 component = NICE_COMPONENT (obj);
1124 agent = g_weak_ref_get (&component->agent_ref);
1125 g_assert (agent != NULL);
1126 nice_agent_init_stun_agent (agent, &component->stun_agent);
1128 g_object_unref (agent);
1130 G_OBJECT_CLASS (nice_component_parent_class)->constructed (obj);
1134 nice_component_get_property (GObject *obj,
1135 guint property_id, GValue *value, GParamSpec *pspec)
1137 NiceComponent *component;
1139 component = NICE_COMPONENT (obj);
1141 switch ((NiceComponentProperty) property_id)
1144 g_value_set_uint (value, component->id);
1151 agent = g_weak_ref_get (&component->agent_ref);
1153 g_value_take_object (value, agent);
1159 NiceStream *stream = NULL;
1161 agent = g_weak_ref_get (&component->agent_ref);
1163 stream = agent_find_stream (agent, component->stream_id);
1164 g_value_set_object (value, stream);
1165 g_object_unref (agent);
1170 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
1175 nice_component_set_property (GObject *obj,
1176 guint property_id, const GValue *value, GParamSpec *pspec)
1178 NiceComponent *component;
1180 component = NICE_COMPONENT (obj);
1182 switch ((NiceComponentProperty) property_id)
1185 component->id = g_value_get_uint (value);
1189 g_weak_ref_set (&component->agent_ref, g_value_get_object (value));
1194 NiceStream *stream = g_value_get_object (value);
1195 component->stream_id = stream->id;
1200 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
1204 /* Must be called with the agent lock released as it could dispose of
1207 nice_component_finalize (GObject *obj)
1211 cmp = NICE_COMPONENT (obj);
1213 /* Component should have been closed already. */
1214 g_warn_if_fail (cmp->local_candidates == NULL);
1215 g_warn_if_fail (cmp->remote_candidates == NULL);
1216 g_warn_if_fail (g_queue_get_length (&cmp->incoming_checks) == 0);
1218 g_list_free_full (cmp->valid_candidates,
1219 (GDestroyNotify) nice_candidate_free);
1221 g_clear_object (&cmp->tcp);
1222 g_clear_object (&cmp->stop_cancellable);
1223 g_clear_object (&cmp->iostream);
1224 g_mutex_clear (&cmp->io_mutex);
1226 if (cmp->stop_cancellable_source != NULL) {
1227 g_source_destroy (cmp->stop_cancellable_source);
1228 g_source_unref (cmp->stop_cancellable_source);
1231 if (cmp->ctx != NULL) {
1232 g_main_context_unref (cmp->ctx);
1236 g_main_context_unref (cmp->own_ctx);
1238 g_weak_ref_clear (&cmp->agent_ref);
1240 g_atomic_int_inc (&n_components_destroyed);
1241 nice_debug ("Destroyed NiceComponent (%u created, %u destroyed)",
1242 n_components_created, n_components_destroyed);
1244 G_OBJECT_CLASS (nice_component_parent_class)->finalize (obj);
1250 * This is a GSource which wraps a single Component and is dispatched whenever
1251 * any of its NiceSockets are dispatched, i.e. it proxies all poll() events for
1252 * every socket in the Component. It is designed for use by GPollableInputStream
1253 * and GPollableOutputStream, so that a Component can be incorporated into a
1254 * custom main context iteration.
1256 * The callbacks dispatched by a ComponentSource have type GPollableSourceFunc.
1258 * ComponentSource supports adding a GCancellable child source which will
1259 * additionally dispatch if a provided GCancellable is cancelled.
1261 * Internally, ComponentSource adds a new GSocketSource for each socket in the
1262 * Component. Changes to the Component’s list of sockets are detected on each
1263 * call to component_source_prepare(), which compares a stored age with the
1264 * current age of the Component’s socket list — if the socket list has changed,
1265 * the age will have increased (indicating added sockets) or will have been
1266 * reset to 0 (indicating all sockets have been closed).
1271 GObject *pollable_stream; /* owned */
1276 guint component_socket_sources_age;
1278 /* SocketSource, free with free_child_socket_source() */
1279 GSList *socket_sources;
1281 GIOCondition condition;
1285 component_source_prepare (GSource *source, gint *timeout_)
1287 ComponentSource *component_source = (ComponentSource *) source;
1289 NiceComponent *component;
1290 GSList *parentl, *childl;
1292 agent = g_weak_ref_get (&component_source->agent_ref);
1296 /* Needed due to accessing the Component. */
1299 if (!agent_find_component (agent,
1300 component_source->stream_id, component_source->component_id, NULL,
1305 if (component->socket_sources_age ==
1306 component_source->component_socket_sources_age)
1309 /* If the age has changed, either
1310 * - one or more new socket has been prepended
1311 * - old sockets have been removed
1314 /* Add the new child sources. */
1316 for (parentl = component->socket_sources; parentl; parentl = parentl->next) {
1317 SocketSource *parent_socket_source = parentl->data;
1318 SocketSource *child_socket_source;
1320 if (parent_socket_source->socket->fileno == NULL)
1323 /* Iterating the list of socket sources every time isn't a big problem
1324 * because the number of pairs is limited ~100 normally, so there will
1325 * rarely be more than 10.
1327 childl = g_slist_find_custom (component_source->socket_sources,
1328 parent_socket_source->socket, _find_socket_source);
1330 /* If we have reached this state, then all sources new sources have been
1331 * added, because they are always prepended.
1336 child_socket_source = g_slice_new0 (SocketSource);
1337 child_socket_source->socket = parent_socket_source->socket;
1338 child_socket_source->source =
1339 g_socket_create_source (child_socket_source->socket->fileno, G_IO_IN,
1341 source_set_dummy_callback (child_socket_source->source);
1342 g_source_add_child_source (source, child_socket_source->source);
1343 g_source_unref (child_socket_source->source);
1344 component_source->socket_sources =
1345 g_slist_prepend (component_source->socket_sources, child_socket_source);
1349 for (childl = component_source->socket_sources;
1351 SocketSource *child_socket_source = childl->data;
1352 GSList *next = childl->next;
1354 parentl = g_slist_find_custom (component->socket_sources,
1355 child_socket_source->socket, _find_socket_source);
1357 /* If this is not a currently used socket, remove the relevant source */
1359 g_source_remove_child_source (source, child_socket_source->source);
1360 g_slice_free (SocketSource, child_socket_source);
1361 component_source->socket_sources =
1362 g_slist_delete_link (component_source->socket_sources, childl);
1369 /* Update the age. */
1370 component_source->component_socket_sources_age = component->socket_sources_age;
1374 agent_unlock_and_emit (agent);
1375 g_object_unref (agent);
1377 /* We can’t be sure if the ComponentSource itself needs to be dispatched until
1378 * poll() is called on all the child sources. */
1383 component_source_dispatch (GSource *source, GSourceFunc callback,
1386 ComponentSource *component_source = (ComponentSource *) source;
1387 GPollableSourceFunc func = (GPollableSourceFunc) G_CALLBACK (callback);
1389 return func (component_source->pollable_stream, user_data);
1393 free_child_socket_source (gpointer data)
1395 g_slice_free (SocketSource, data);
1399 component_source_finalize (GSource *source)
1401 ComponentSource *component_source = (ComponentSource *) source;
1403 g_slist_free_full (component_source->socket_sources, free_child_socket_source);
1405 g_weak_ref_clear (&component_source->agent_ref);
1406 g_object_unref (component_source->pollable_stream);
1407 component_source->pollable_stream = NULL;
1411 component_source_closure_callback (GObject *pollable_stream, gpointer user_data)
1413 GClosure *closure = user_data;
1414 GValue param_value = G_VALUE_INIT;
1415 GValue result_value = G_VALUE_INIT;
1418 g_value_init (&result_value, G_TYPE_BOOLEAN);
1419 g_value_init (¶m_value, G_TYPE_OBJECT);
1420 g_value_set_object (¶m_value, pollable_stream);
1422 g_closure_invoke (closure, &result_value, 1, ¶m_value, NULL);
1423 retval = g_value_get_boolean (&result_value);
1425 g_value_unset (¶m_value);
1426 g_value_unset (&result_value);
1431 static GSourceFuncs component_source_funcs = {
1432 component_source_prepare,
1434 component_source_dispatch,
1435 component_source_finalize,
1436 (GSourceFunc) G_CALLBACK (component_source_closure_callback),
1440 * nice_component_source_new:
1441 * @agent: a #NiceAgent
1442 * @stream_id: The stream's id
1443 * @component_id: The component's number
1444 * @pollable_stream: a #GPollableInputStream or #GPollableOutputStream to pass
1445 * to dispatched callbacks
1446 * @cancellable: (allow-none): a #GCancellable, or %NULL
1448 * Create a new #ComponentSource, a type of #GSource which proxies poll events
1449 * from all sockets in the given @component.
1451 * A callback function of type #GPollableSourceFunc must be connected to the
1452 * returned #GSource using g_source_set_callback(). @pollable_stream is passed
1453 * to all callbacks dispatched from the #GSource, and a reference is held on it
1456 * The #GSource will automatically update to poll sockets as they’re added to
1457 * the @component (e.g. during peer discovery).
1459 * Returns: (transfer full): a new #ComponentSource; unref with g_source_unref()
1462 nice_component_input_source_new (NiceAgent *agent, guint stream_id,
1463 guint component_id, GPollableInputStream *pollable_istream,
1464 GCancellable *cancellable)
1466 ComponentSource *component_source;
1468 g_assert (G_IS_POLLABLE_INPUT_STREAM (pollable_istream));
1472 g_source_new (&component_source_funcs, sizeof (ComponentSource));
1473 g_source_set_name ((GSource *) component_source, "ComponentSource");
1475 component_source->component_socket_sources_age = 0;
1476 component_source->pollable_stream = g_object_ref (pollable_istream);
1477 g_weak_ref_init (&component_source->agent_ref, agent);
1478 component_source->stream_id = stream_id;
1479 component_source->component_id = component_id;
1481 /* Add a cancellable source. */
1482 if (cancellable != NULL) {
1483 GSource *cancellable_source;
1485 cancellable_source = g_cancellable_source_new (cancellable);
1486 source_set_dummy_callback (cancellable_source);
1487 g_source_add_child_source ((GSource *) component_source,
1488 cancellable_source);
1489 g_source_unref (cancellable_source);
1492 return (GSource *) component_source;
1497 turn_server_new (const gchar *server_ip, guint server_port,
1498 const gchar *username, const gchar *password, NiceRelayType type)
1500 TurnServer *turn = g_slice_new (TurnServer);
1502 nice_address_init (&turn->server);
1504 turn->ref_count = 1;
1505 if (nice_address_set_from_string (&turn->server, server_ip)) {
1506 nice_address_set_port (&turn->server, server_port);
1508 g_slice_free (TurnServer, turn);
1511 turn->username = g_strdup (username);
1512 turn->password = g_strdup (password);
1513 turn->decoded_username =
1514 g_base64_decode ((gchar *)username, &turn->decoded_username_len);
1515 turn->decoded_password =
1516 g_base64_decode ((gchar *)password, &turn->decoded_password_len);
1523 turn_server_ref (TurnServer *turn)
1531 turn_server_unref (TurnServer *turn)
1535 if (turn->ref_count == 0) {
1536 g_free (turn->username);
1537 g_free (turn->password);
1538 g_free (turn->decoded_username);
1539 g_free (turn->decoded_password);
1540 g_slice_free (TurnServer, turn);
1545 nice_component_add_valid_candidate (NiceAgent *agent, NiceComponent *component,
1546 const NiceCandidate *candidate)
1549 GList *item, *last = NULL;
1551 for (item = component->valid_candidates; item; item = item->next) {
1552 NiceCandidate *cand = item->data;
1556 if (nice_candidate_equal_target (cand, candidate))
1562 if (nice_debug_is_enabled ()) {
1563 char str[INET6_ADDRSTRLEN];
1564 nice_address_to_string (&candidate->addr, str);
1565 nice_debug ("Agent %p : %d:%d Adding valid source"
1566 " candidate: %s:%d trans: %d", agent,
1567 candidate->stream_id, candidate->component_id, str,
1568 nice_address_get_port (&candidate->addr), candidate->transport);
1571 component->valid_candidates = g_list_prepend (
1572 component->valid_candidates, nice_candidate_copy (candidate));
1574 /* Delete the last one to make sure we don't have a list that is too long,
1575 * the candidates are not freed on ICE restart as this would be more complex,
1576 * we just keep the list not too long.
1578 if (count > NICE_COMPONENT_MAX_VALID_CANDIDATES) {
1579 NiceCandidate *cand = last->data;
1581 component->valid_candidates = g_list_delete_link (
1582 component->valid_candidates, last);
1583 nice_candidate_free (cand);
1588 nice_component_verify_remote_candidate (NiceComponent *component,
1589 const NiceAddress *address, NiceSocket *nicesock)
1593 if (component->fallback_mode)
1596 for (item = component->valid_candidates; item; item = item->next) {
1597 NiceCandidate *cand = item->data;
1599 if ((((nicesock->type == NICE_SOCKET_TYPE_TCP_BSD ||
1600 nicesock->type == NICE_SOCKET_TYPE_UDP_TURN) &&
1601 (cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ||
1602 cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ||
1603 cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_SO)) ||
1604 cand->transport == NICE_CANDIDATE_TRANSPORT_UDP) &&
1605 nice_address_equal (address, &cand->addr)) {
1606 /* fast return if it's already the first */
1607 if (item == component->valid_candidates)
1610 /* Put the current candidate at the top so that in the normal use-case,
1611 * this function becomes O(1).
1613 component->valid_candidates = g_list_remove_link (
1614 component->valid_candidates, item);
1615 component->valid_candidates = g_list_concat (item,
1616 component->valid_candidates);
1625 /* Must be called with agent lock held */
1626 /* Returns a transfer full GPtrArray of GSocket */
1628 nice_component_get_sockets (NiceComponent *component)
1630 GPtrArray *array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
1633 for (item = component->local_candidates; item; item = item->next) {
1634 NiceCandidate *cand = item->data;
1635 NiceSocket *nicesock = cand->sockptr;
1637 if (nicesock->fileno && !g_ptr_array_find (array, nicesock->fileno, NULL))
1638 g_ptr_array_add (array, g_object_ref (nicesock->fileno));