2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 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.
28 * Alternatively, the contents of this file may be used under the terms of the
29 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30 * case the provisions of LGPL are applicable instead of those above. If you
31 * wish to allow use of your version of this file only under the terms of the
32 * LGPL and not to allow others to use your version of this file under the
33 * MPL, indicate your decision by deleting the provisions above and replace
34 * them with the notice and other provisions required by the LGPL. If you do
35 * not delete the provisions above, a recipient may use your version of this
36 * file under either the MPL or the LGPL.
41 * @brief ICE component functions
50 #include "component.h"
51 #include "agent-priv.h"
60 component
= g_slice_new0 (Component
);
62 component
->state
= NICE_COMPONENT_STATE_DISCONNECTED
;
63 component
->restart_candidate
= NULL
;
69 component_free (Component
*cmp
)
73 for (i
= cmp
->local_candidates
; i
; i
= i
->next
) {
74 NiceCandidate
*candidate
= i
->data
;
75 nice_candidate_free (candidate
);
78 for (i
= cmp
->remote_candidates
; i
; i
= i
->next
) {
79 NiceCandidate
*candidate
= i
->data
;
80 nice_candidate_free (candidate
);
83 if (cmp
->restart_candidate
)
84 nice_candidate_free (cmp
->restart_candidate
),
85 cmp
->restart_candidate
= NULL
;
87 for (i
= cmp
->sockets
; i
; i
= i
->next
) {
88 NiceUDPSocket
*udpsocket
= i
->data
;
89 nice_udp_socket_close (udpsocket
);
90 g_slice_free (NiceUDPSocket
, udpsocket
);
93 for (i
= cmp
->gsources
; i
; i
= i
->next
) {
94 GSource
*source
= i
->data
;
95 g_source_destroy (source
);
98 for (i
= cmp
->incoming_checks
; i
; i
= i
->next
) {
99 IncomingCheck
*icheck
= i
->data
;
100 g_slice_free (IncomingCheck
, icheck
);
103 g_slist_free (cmp
->local_candidates
);
104 g_slist_free (cmp
->remote_candidates
);
105 g_slist_free (cmp
->sockets
);
106 g_slist_free (cmp
->gsources
);
107 g_slist_free (cmp
->incoming_checks
);
109 g_free (cmp
->turn_username
);
110 g_free (cmp
->turn_password
);
112 g_slice_free (Component
, cmp
);
116 * Returns a component UDP socket struct that uses handle 'fd'.
118 * Note: there might be multiple sockets using the same
122 component_find_udp_socket_by_fd (Component
*component
, guint fd
)
126 /* XXX: this won't work anymore, a single fd may be used
127 * by multiple candidates */
129 for (i
= component
->sockets
; i
; i
= i
->next
)
131 NiceUDPSocket
*sockptr
= i
->data
;
133 if (sockptr
->fileno
== fd
)
141 * Finds a candidate pair that has matching foundation ids.
143 * @return TRUE if pair found, pointer to pair stored at 'pair'
146 component_find_pair (Component
*cmp
, NiceAgent
*agent
, const gchar
*lfoundation
, const gchar
*rfoundation
, CandidatePair
*pair
)
149 CandidatePair result
= { NULL
, NULL
, 0 };
151 for (i
= cmp
->local_candidates
; i
; i
= i
->next
) {
152 NiceCandidate
*candidate
= i
->data
;
153 if (strncmp (candidate
->foundation
, lfoundation
, NICE_CANDIDATE_MAX_FOUNDATION
) == 0) {
154 result
.local
= candidate
;
159 for (i
= cmp
->remote_candidates
; i
; i
= i
->next
) {
160 NiceCandidate
*candidate
= i
->data
;
161 if (strncmp (candidate
->foundation
, rfoundation
, NICE_CANDIDATE_MAX_FOUNDATION
) == 0) {
162 result
.remote
= candidate
;
167 if (result
.local
&& result
.remote
) {
168 result
.priority
= agent_candidate_pair_priority (agent
, result
.local
, result
.remote
);
178 * Resets the component state to that of a ICE restarted
182 component_restart (Component
*cmp
)
186 for (i
= cmp
->remote_candidates
; i
; i
= i
->next
) {
187 NiceCandidate
*candidate
= i
->data
;
189 /* note: do not remove the remote candidate that is
190 * currently part of the 'selected pair', see ICE
191 * 9.1.1.1. "ICE Restarts" (ID-19) */
192 if (candidate
== cmp
->selected_pair
.remote
) {
193 if (cmp
->restart_candidate
)
194 nice_candidate_free (cmp
->restart_candidate
);
195 cmp
->restart_candidate
= candidate
;
198 nice_candidate_free (candidate
);
200 g_slist_free (cmp
->remote_candidates
),
201 cmp
->remote_candidates
= NULL
;
203 for (i
= cmp
->incoming_checks
; i
; i
= i
->next
) {
204 IncomingCheck
*icheck
= i
->data
;
205 g_slice_free (IncomingCheck
, icheck
);
208 /* note: component state managed by agent */
214 * Changes the selected pair for the component to 'pair'. Does not
215 * emit the "selected-pair-changed" signal.
217 void component_update_selected_pair (Component
*component
, const CandidatePair
*pair
)
219 g_assert (component
);
221 g_debug ("setting SELECTED PAIR for component %u: %s:%s (prio:%lu).",
222 component
->id
, pair
->local
->foundation
, pair
->remote
->foundation
, (long unsigned)pair
->priority
);
223 component
->selected_pair
.local
= pair
->local
;
224 component
->selected_pair
.remote
= pair
->remote
;
225 component
->selected_pair
.priority
= pair
->priority
;
229 * Finds a remote candidate with matching address and
232 * @return pointer to candidate or NULL if not found
235 component_find_remote_candidate (const Component
*component
, const NiceAddress
*addr
, NiceCandidateTransport transport
)
239 for (i
= component
->remote_candidates
; i
; i
= i
->next
) {
240 NiceCandidate
*candidate
= i
->data
;
242 if (nice_address_equal(&candidate
->addr
, addr
) &&
243 candidate
->transport
== transport
)
252 * Sets the desired remote candidate as the selected pair
254 * It will start sending on the highest priority pair available with
259 component_set_selected_remote_candidate (NiceAgent
*agent
, Component
*component
,
260 NiceCandidate
*candidate
)
262 NiceCandidate
*local
= NULL
;
263 NiceCandidate
*remote
= NULL
;
264 guint32 priority
= 0;
267 for (item
= component
->local_candidates
; item
; item
= g_slist_next (item
)) {
268 NiceCandidate
*tmp
= item
->data
;
269 guint32 tmp_prio
= 0;
271 if (tmp
->transport
!= candidate
->transport
||
272 tmp
->addr
.s
.addr
.sa_family
!= candidate
->addr
.s
.addr
.sa_family
||
273 tmp
->type
!= NICE_CANDIDATE_TYPE_HOST
)
276 tmp_prio
= agent_candidate_pair_priority (agent
, tmp
, candidate
);
278 if (tmp_prio
> priority
) {
287 remote
= component_find_remote_candidate (component
, &candidate
->addr
,
288 candidate
->transport
);
291 GSList
*modified_list
= NULL
;
293 remote
= nice_candidate_copy (candidate
);
295 modified_list
= g_slist_append (component
->remote_candidates
,
298 component
->remote_candidates
= modified_list
;
299 agent_signal_new_remote_candidate (agent
, remote
);
301 else { /* error: memory alloc / list */
302 nice_candidate_free (remote
), remote
= NULL
;
307 component
->selected_pair
.local
= local
;
308 component
->selected_pair
.remote
= remote
;
309 component
->selected_pair
.priority
= priority
;