GST_FLOW_WRONG_STATE -> GST_FLOW_FLUSHING
[sipe-libnice.git] / agent / component.c
blobcd5db9a9614c5d679d4dc87f4878d1e2c0fe48f4
1 /*
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
17 * License.
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.
24 * Contributors:
25 * Dafydd Harries, Collabora Ltd.
26 * Youness Alaoui, Collabora Ltd.
27 * Kai Vehmanen, Nokia
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.
41 * @file component.c
42 * @brief ICE component functions
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif
49 #include <string.h>
51 #include "debug.h"
53 #include "component.h"
54 #include "agent-priv.h"
56 Component *
57 component_new (guint id)
59 Component *component;
61 component = g_slice_new0 (Component);
62 component->id = id;
63 component->state = NICE_COMPONENT_STATE_DISCONNECTED;
64 component->restart_candidate = NULL;
65 component->tcp = NULL;
67 return component;
71 void
72 component_free (Component *cmp)
74 GSList *i;
75 GList *item;
77 for (i = cmp->local_candidates; i; i = i->next) {
78 NiceCandidate *candidate = i->data;
79 nice_candidate_free (candidate);
82 for (i = cmp->remote_candidates; i; i = i->next) {
83 NiceCandidate *candidate = i->data;
84 nice_candidate_free (candidate);
87 if (cmp->restart_candidate)
88 nice_candidate_free (cmp->restart_candidate),
89 cmp->restart_candidate = NULL;
91 for (i = cmp->sockets; i; i = i->next) {
92 NiceSocket *udpsocket = i->data;
93 nice_socket_free (udpsocket);
96 for (i = cmp->gsources; i; i = i->next) {
97 GSource *source = i->data;
98 g_source_destroy (source);
99 g_source_unref (source);
102 for (i = cmp->incoming_checks; i; i = i->next) {
103 IncomingCheck *icheck = i->data;
104 g_free (icheck->username);
105 g_slice_free (IncomingCheck, icheck);
108 g_slist_free (cmp->local_candidates);
109 g_slist_free (cmp->remote_candidates);
110 g_slist_free (cmp->sockets);
111 g_slist_free (cmp->gsources);
112 g_slist_free (cmp->incoming_checks);
114 for (item = cmp->turn_servers; item; item = g_list_next (item)) {
115 TurnServer *turn = item->data;
116 g_free (turn->username);
117 g_free (turn->password);
118 g_slice_free (TurnServer, turn);
120 g_list_free (cmp->turn_servers);
122 if (cmp->selected_pair.keepalive.tick_source != NULL) {
123 g_source_destroy (cmp->selected_pair.keepalive.tick_source);
124 g_source_unref (cmp->selected_pair.keepalive.tick_source);
125 cmp->selected_pair.keepalive.tick_source = NULL;
128 if (cmp->tcp_clock) {
129 g_source_destroy (cmp->tcp_clock);
130 g_source_unref (cmp->tcp_clock);
131 cmp->tcp_clock = NULL;
133 if (cmp->tcp) {
134 pseudo_tcp_socket_close (cmp->tcp, TRUE);
135 g_object_unref (cmp->tcp);
136 cmp->tcp = NULL;
138 if (cmp->tcp_data != NULL) {
139 g_slice_free (TcpUserData, cmp->tcp_data);
140 cmp->tcp_data = NULL;
143 if (cmp->ctx != NULL) {
144 g_main_context_unref (cmp->ctx);
145 cmp->ctx = NULL;
148 g_slice_free (Component, cmp);
152 * Finds a candidate pair that has matching foundation ids.
154 * @return TRUE if pair found, pointer to pair stored at 'pair'
156 gboolean
157 component_find_pair (Component *cmp, NiceAgent *agent, const gchar *lfoundation, const gchar *rfoundation, CandidatePair *pair)
159 GSList *i;
160 CandidatePair result;
162 memset (&result, 0, sizeof(result));
164 for (i = cmp->local_candidates; i; i = i->next) {
165 NiceCandidate *candidate = i->data;
166 if (strncmp (candidate->foundation, lfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
167 result.local = candidate;
168 break;
172 for (i = cmp->remote_candidates; i; i = i->next) {
173 NiceCandidate *candidate = i->data;
174 if (strncmp (candidate->foundation, rfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
175 result.remote = candidate;
176 break;
180 if (result.local && result.remote) {
181 result.priority = agent_candidate_pair_priority (agent, result.local, result.remote);
182 if (pair)
183 *pair = result;
184 return TRUE;
187 return FALSE;
191 * Resets the component state to that of a ICE restarted
192 * session.
194 gboolean
195 component_restart (Component *cmp)
197 GSList *i;
199 for (i = cmp->remote_candidates; i; i = i->next) {
200 NiceCandidate *candidate = i->data;
202 /* note: do not remove the remote candidate that is
203 * currently part of the 'selected pair', see ICE
204 * 9.1.1.1. "ICE Restarts" (ID-19) */
205 if (candidate == cmp->selected_pair.remote) {
206 if (cmp->restart_candidate)
207 nice_candidate_free (cmp->restart_candidate);
208 cmp->restart_candidate = candidate;
210 else
211 nice_candidate_free (candidate);
213 g_slist_free (cmp->remote_candidates),
214 cmp->remote_candidates = NULL;
216 for (i = cmp->incoming_checks; i; i = i->next) {
217 IncomingCheck *icheck = i->data;
218 g_free (icheck->username);
219 g_slice_free (IncomingCheck, icheck);
221 g_slist_free (cmp->incoming_checks);
222 cmp->incoming_checks = NULL;
224 /* note: component state managed by agent */
226 return TRUE;
230 * Changes the selected pair for the component to 'pair'. Does not
231 * emit the "selected-pair-changed" signal.
233 void component_update_selected_pair (Component *component, const CandidatePair *pair)
235 g_assert (component);
236 g_assert (pair);
237 nice_debug ("setting SELECTED PAIR for component %u: %s:%s (prio:%"
238 G_GUINT64_FORMAT ").", component->id, pair->local->foundation,
239 pair->remote->foundation, pair->priority);
241 if (component->selected_pair.keepalive.tick_source != NULL) {
242 g_source_destroy (component->selected_pair.keepalive.tick_source);
243 g_source_unref (component->selected_pair.keepalive.tick_source);
244 component->selected_pair.keepalive.tick_source = NULL;
247 memset (&component->selected_pair, 0, sizeof(CandidatePair));
249 component->selected_pair.local = pair->local;
250 component->selected_pair.remote = pair->remote;
251 component->selected_pair.priority = pair->priority;
256 * Finds a remote candidate with matching address and
257 * transport.
259 * @return pointer to candidate or NULL if not found
261 NiceCandidate *
262 component_find_remote_candidate (const Component *component, const NiceAddress *addr, NiceCandidateTransport transport)
264 GSList *i;
266 for (i = component->remote_candidates; i; i = i->next) {
267 NiceCandidate *candidate = i->data;
269 if (nice_address_equal(&candidate->addr, addr) &&
270 candidate->transport == transport)
271 return candidate;
275 return NULL;
279 * Sets the desired remote candidate as the selected pair
281 * It will start sending on the highest priority pair available with
282 * this candidate.
285 NiceCandidate *
286 component_set_selected_remote_candidate (NiceAgent *agent, Component *component,
287 NiceCandidate *candidate)
289 NiceCandidate *local = NULL;
290 NiceCandidate *remote = NULL;
291 guint64 priority = 0;
292 GSList *item = NULL;
294 for (item = component->local_candidates; item; item = g_slist_next (item)) {
295 NiceCandidate *tmp = item->data;
296 guint64 tmp_prio = 0;
298 if (tmp->transport != candidate->transport ||
299 tmp->addr.s.addr.sa_family != candidate->addr.s.addr.sa_family ||
300 tmp->type != NICE_CANDIDATE_TYPE_HOST)
301 continue;
303 tmp_prio = agent_candidate_pair_priority (agent, tmp, candidate);
305 if (tmp_prio > priority) {
306 priority = tmp_prio;
307 local = tmp;
311 if (local == NULL)
312 return NULL;
314 remote = component_find_remote_candidate (component, &candidate->addr,
315 candidate->transport);
317 if (!remote) {
318 remote = nice_candidate_copy (candidate);
319 component->remote_candidates = g_slist_append (component->remote_candidates,
320 remote);
321 agent_signal_new_remote_candidate (agent, remote);
324 if (component->selected_pair.keepalive.tick_source != NULL) {
325 g_source_destroy (component->selected_pair.keepalive.tick_source);
326 g_source_unref (component->selected_pair.keepalive.tick_source);
327 component->selected_pair.keepalive.tick_source = NULL;
330 memset (&component->selected_pair, 0, sizeof(CandidatePair));
331 component->selected_pair.local = local;
332 component->selected_pair.remote = remote;
333 component->selected_pair.priority = priority;
335 return local;