7ba378b4ba1b99649d32ef5abee4fde1d990ac4c
[platform/upstream/libnice.git] / agent / conncheck.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2006-2009 Collabora Ltd.
5  *  Contact: Youness Alaoui
6  * (C) 2006-2009 Nokia Corporation. All rights reserved.
7  *  Contact: Kai Vehmanen
8  *
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/
13  *
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.
18  *
19  * The Original Code is the Nice GLib ICE library.
20  *
21  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22  * Corporation. All Rights Reserved.
23  *
24  * Contributors:
25  *   Kai Vehmanen, Nokia
26  *   Youness Alaoui, Collabora Ltd.
27  *   Dafydd Harries, Collabora Ltd.
28  *
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.
38  */
39
40 /*
41  * @file conncheck.c
42  * @brief ICE connectivity checks
43  */
44
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif
48
49 #include <errno.h>
50 #include <string.h>
51
52 #include <glib.h>
53
54 #include "debug.h"
55
56 #include "agent.h"
57 #include "agent-priv.h"
58 #include "conncheck.h"
59 #include "discovery.h"
60 #include "stun/stun5389.h"
61 #include "stun/usages/ice.h"
62 #include "stun/usages/bind.h"
63 #include "stun/usages/turn.h"
64
65 static void priv_update_check_list_failed_components (NiceAgent *agent, NiceStream *stream);
66 static guint priv_prune_pending_checks (NiceAgent *agent, NiceStream *stream, NiceComponent *component);
67 static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *local_socket, NiceCandidate *remote_cand);
68 static void priv_mark_pair_nominated (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceCandidate *localcand, NiceCandidate *remotecand);
69 static size_t priv_create_username (NiceAgent *agent, NiceStream *stream,
70     guint component_id, NiceCandidate *remote, NiceCandidate *local,
71     uint8_t *dest, guint dest_len, gboolean inbound);
72 static size_t priv_get_password (NiceAgent *agent, NiceStream *stream,
73     NiceCandidate *remote, uint8_t **password);
74 static void candidate_check_pair_free (NiceAgent *agent,
75     CandidateCheckPair *pair);
76 static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched (
77     NiceAgent *agent, guint stream_id, NiceComponent *component,
78     NiceCandidate *local, NiceCandidate *remote, NiceCheckState initial_state);
79 static gboolean priv_conn_keepalive_tick_agent_locked (NiceAgent *agent,
80     gpointer pointer);
81
82 static gint64 priv_timer_remainder (gint64 timer, gint64 now)
83 {
84   if (now >= timer)
85     return 0;
86
87   return (timer - now) / 1000;
88 }
89
90 static gchar
91 priv_state_to_gchar (NiceCheckState state)
92 {
93   switch (state) {
94     case NICE_CHECK_WAITING:
95       return 'W';
96     case NICE_CHECK_IN_PROGRESS:
97       return 'I';
98     case NICE_CHECK_SUCCEEDED:
99       return 'S';
100     case NICE_CHECK_FAILED:
101       return 'F';
102     case NICE_CHECK_FROZEN:
103       return 'Z';
104     case NICE_CHECK_DISCOVERED:
105       return 'D';
106     default:
107       g_assert_not_reached ();
108   }
109 }
110
111 static const gchar *
112 priv_state_to_string (NiceCheckState state)
113 {
114   switch (state) {
115     case NICE_CHECK_WAITING:
116       return "WAITING";
117     case NICE_CHECK_IN_PROGRESS:
118       return "IN_PROGRESS";
119     case NICE_CHECK_SUCCEEDED:
120       return "SUCCEEDED";
121     case NICE_CHECK_FAILED:
122       return "FAILED";
123     case NICE_CHECK_FROZEN:
124       return "FROZEN";
125     case NICE_CHECK_DISCOVERED:
126       return "DISCOVERED";
127     default:
128       g_assert_not_reached ();
129   }
130 }
131
132 #define SET_PAIR_STATE( a, p, s ) G_STMT_START{\
133   g_assert (p); \
134   p->state = s; \
135   nice_debug ("Agent %p : pair %p state %s (%s)", \
136       a, p, priv_state_to_string (s), G_STRFUNC); \
137 }G_STMT_END
138
139 static const gchar *
140 priv_ice_return_to_string (StunUsageIceReturn ice_return)
141 {
142   switch (ice_return) {
143     case STUN_USAGE_ICE_RETURN_SUCCESS:
144       return "success";
145     case STUN_USAGE_ICE_RETURN_ERROR:
146       return "error";
147     case STUN_USAGE_ICE_RETURN_INVALID:
148       return "invalid";
149     case STUN_USAGE_ICE_RETURN_ROLE_CONFLICT:
150       return "role conflict";
151     case STUN_USAGE_ICE_RETURN_INVALID_REQUEST:
152       return "invalid request";
153     case STUN_USAGE_ICE_RETURN_INVALID_METHOD:
154       return "invalid method";
155     case STUN_USAGE_ICE_RETURN_MEMORY_ERROR:
156       return "memory error";
157     case STUN_USAGE_ICE_RETURN_INVALID_ADDRESS:
158       return "invalid address";
159     case STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS:
160       return "no mapped address";
161     default:
162       g_assert_not_reached ();
163   }
164 }
165
166 static const gchar *
167 priv_candidate_type_to_string (NiceCandidateType type)
168 {
169   switch (type) {
170     case NICE_CANDIDATE_TYPE_HOST:
171       return "host";
172     case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
173       return "srflx";
174     case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
175       return "prflx";
176     case NICE_CANDIDATE_TYPE_RELAYED:
177       return "relay";
178     default:
179       g_assert_not_reached ();
180   }
181 }
182
183 static const gchar *
184 priv_candidate_transport_to_string (NiceCandidateTransport transport)
185 {
186   switch (transport) {
187     case NICE_CANDIDATE_TRANSPORT_UDP:
188       return "udp";
189     case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
190       return "tcp-act";
191     case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
192       return "tcp-pass";
193     case NICE_CANDIDATE_TRANSPORT_TCP_SO:
194       return "tcp-so";
195     default:
196       g_assert_not_reached ();
197   }
198 }
199
200 static const gchar *
201 priv_socket_type_to_string (NiceSocketType type)
202 {
203   switch (type) {
204     case NICE_SOCKET_TYPE_UDP_BSD:
205       return "udp";
206     case NICE_SOCKET_TYPE_TCP_BSD:
207       return "tcp";
208     case NICE_SOCKET_TYPE_PSEUDOSSL:
209       return "ssl";
210     case NICE_SOCKET_TYPE_HTTP:
211       return "http";
212     case NICE_SOCKET_TYPE_SOCKS5:
213       return "socks";
214     case NICE_SOCKET_TYPE_UDP_TURN:
215       return "udp-turn";
216     case NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP:
217       return "tcp-turn";
218     case NICE_SOCKET_TYPE_TCP_ACTIVE:
219       return "tcp-act";
220     case NICE_SOCKET_TYPE_TCP_PASSIVE:
221       return "tcp-pass";
222     case NICE_SOCKET_TYPE_TCP_SO:
223       return "tcp-so";
224     default:
225       g_assert_not_reached ();
226   }
227 }
228
229 /*
230  * Dump the component list of incoming checks
231  */
232 static void
233 print_component_incoming_checks (NiceAgent *agent, NiceStream *stream,
234   NiceComponent *component)
235 {
236   GList *i;
237
238   for (i = component->incoming_checks.head; i; i = i->next) {
239     IncomingCheck *icheck = i->data;
240     gchar tmpbuf1[INET6_ADDRSTRLEN] = {0};
241     gchar tmpbuf2[INET6_ADDRSTRLEN] = {0};
242
243     nice_address_to_string (&icheck->local_socket->addr, tmpbuf1);
244     nice_address_to_string (&icheck->from, tmpbuf2);
245     nice_debug ("Agent %p : *** sc=%d/%d : icheck %p : "
246       "sock %s [%s]:%u > [%s]:%u",
247       agent, stream->id, component->id, icheck,
248       priv_socket_type_to_string (icheck->local_socket->type),
249       tmpbuf1, nice_address_get_port (&icheck->local_socket->addr),
250       tmpbuf2, nice_address_get_port (&icheck->from));
251   }
252 }
253
254 /*
255  * Dump the conncheck lists of the agent
256  */
257 static void
258 priv_print_conn_check_lists (NiceAgent *agent, const gchar *where, const gchar *detail)
259 {
260   GSList *i, *k, *l;
261   guint j, m;
262   gint64 now;
263
264   if (!nice_debug_is_verbose ())
265     return;
266
267   now = g_get_monotonic_time ();
268
269 #define PRIORITY_LEN 32
270
271   nice_debug ("Agent %p : *** conncheck list DUMP (called from %s%s)",
272       agent, where, detail ? detail : "");
273   nice_debug ("Agent %p : *** agent nomination mode %s, %s",
274       agent, agent->nomination_mode == NICE_NOMINATION_MODE_AGGRESSIVE ?
275       "aggressive" : "regular",
276       agent->controlling_mode ? "controlling" : "controlled");
277   for (i = agent->streams; i ; i = i->next) {
278     NiceStream *stream = i->data;
279     for (j = 1; j <= stream->n_components; j++) {
280       NiceComponent *component;
281       for (k = stream->conncheck_list; k ; k = k->next) {
282         CandidateCheckPair *pair = k->data;
283         if (pair->component_id == j) {
284           gchar local_addr[INET6_ADDRSTRLEN];
285           gchar remote_addr[INET6_ADDRSTRLEN];
286           gchar priority[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
287
288           nice_address_to_string (&pair->local->addr, local_addr);
289           nice_address_to_string (&pair->remote->addr, remote_addr);
290           nice_candidate_pair_priority_to_string (pair->priority, priority);
291
292           nice_debug ("Agent %p : *** sc=%d/%d : pair %p : "
293               "f=%s t=%s:%s sock=%s "
294               "%s:[%s]:%u > %s:[%s]:%u prio=%s/%08x state=%c%s%s%s%s",
295               agent, pair->stream_id, pair->component_id, pair,
296               pair->foundation,
297               priv_candidate_type_to_string (pair->local->type),
298               priv_candidate_type_to_string (pair->remote->type),
299               priv_socket_type_to_string (pair->sockptr->type),
300               priv_candidate_transport_to_string (pair->local->transport),
301               local_addr, nice_address_get_port (&pair->local->addr),
302               priv_candidate_transport_to_string (pair->remote->transport),
303               remote_addr, nice_address_get_port (&pair->remote->addr),
304               priority, pair->stun_priority,
305               priv_state_to_gchar (pair->state),
306               pair->valid ? "V" : "",
307               pair->nominated ? "N" : "",
308               pair->use_candidate_on_next_check ? "C" : "",
309               g_slist_find (agent->triggered_check_queue, pair) ? "T" : "");
310
311           for (l = pair->stun_transactions, m = 0; l; l = l->next, m++) {
312             StunTransaction *stun = l->data;
313             nice_debug ("Agent %p : *** sc=%d/%d : pair %p :   "
314                 "stun#=%d timer=%d/%d %" G_GINT64_FORMAT "/%dms buf=%p %s",
315                 agent, pair->stream_id, pair->component_id, pair, m,
316                 stun->timer.retransmissions, stun->timer.max_retransmissions,
317                 stun->timer.delay - priv_timer_remainder (stun->next_tick, now),
318                 stun->timer.delay,
319                 stun->message.buffer,
320                 (m == 0 && pair->retransmit) ? "(R)" : "");
321           }
322         }
323       }
324       if (agent_find_component (agent, stream->id, j, NULL, &component))
325         print_component_incoming_checks (agent, stream, component);
326     }
327   }
328 }
329
330 /* Add the pair to the triggered checks list, if not already present
331  */
332 static void
333 priv_add_pair_to_triggered_check_queue (NiceAgent *agent, CandidateCheckPair *pair)
334 {
335   g_assert (pair);
336
337   SET_PAIR_STATE (agent, pair, NICE_CHECK_IN_PROGRESS);
338   if (agent->triggered_check_queue == NULL ||
339       g_slist_find (agent->triggered_check_queue, pair) == NULL)
340     agent->triggered_check_queue = g_slist_append (agent->triggered_check_queue, pair);
341 }
342
343 /* Remove the pair from the triggered checks list
344  */
345 static void
346 priv_remove_pair_from_triggered_check_queue (NiceAgent *agent, CandidateCheckPair *pair)
347 {
348   g_assert (pair);
349   agent->triggered_check_queue = g_slist_remove (agent->triggered_check_queue, pair);
350 }
351
352 /* Get the pair from the triggered checks list
353  */
354 static CandidateCheckPair *
355 priv_get_pair_from_triggered_check_queue (NiceAgent *agent)
356 {
357   CandidateCheckPair *pair = NULL;
358
359   if (agent->triggered_check_queue) {
360     pair = (CandidateCheckPair *)agent->triggered_check_queue->data;
361     priv_remove_pair_from_triggered_check_queue (agent, pair);
362   }
363   return pair;
364 }
365
366 /*
367  * Check if the conncheck list if Active according to
368  * ICE spec, 5.7.4 (Computing States)
369  *
370  * note: the ICE spec in unclear about that, but the check list should
371  * be considered active when there is at least a pair in Waiting state
372  * OR a pair in In-Progress state.
373  */
374 static gboolean
375 priv_is_checklist_active (NiceStream *stream)
376 {
377   GSList *i;
378
379   for (i = stream->conncheck_list; i ; i = i->next) {
380     CandidateCheckPair *p = i->data;
381     if (p->state == NICE_CHECK_WAITING || p->state == NICE_CHECK_IN_PROGRESS)
382       return TRUE;
383   }
384   return FALSE;
385 }
386
387 /*
388  * Check if the conncheck list if Frozen according to
389  * ICE spec, 5.7.4 (Computing States)
390  */
391 static gboolean
392 priv_is_checklist_frozen (NiceStream *stream)
393 {
394   GSList *i;
395
396   if (stream->conncheck_list == NULL)
397     return FALSE;
398
399   for (i = stream->conncheck_list; i ; i = i->next) {
400     CandidateCheckPair *p = i->data;
401     if (p->state != NICE_CHECK_FROZEN)
402       return FALSE;
403   }
404   return TRUE;
405 }
406
407 /*
408  * Check if all components of the stream have
409  * a valid pair (used for ICE spec, 7.1.3.2.3, point 2.)
410  */
411 static gboolean
412 priv_all_components_have_valid_pair (NiceStream *stream)
413 {
414   guint i;
415   GSList *j;
416
417   for (i = 1; i <= stream->n_components; i++) {
418     for (j = stream->conncheck_list; j ; j = j->next) {
419       CandidateCheckPair *p = j->data;
420       if (p->component_id == i && p->valid)
421         break;
422     }
423     if (j == NULL)
424       return FALSE;
425   }
426   return TRUE;
427 }
428
429 /*
430  * Check if the foundation in parameter matches the foundation
431  * of a valid pair in the conncheck list [of stream] (used for ICE spec,
432  * 7.1.3.2.3, point 2.)
433  */
434 static gboolean
435 priv_foundation_matches_a_valid_pair (const gchar *foundation, NiceStream *stream)
436 {
437   GSList *i;
438
439   for (i = stream->conncheck_list; i ; i = i->next) {
440     CandidateCheckPair *p = i->data;
441     if (p->valid &&
442         strncmp (p->foundation, foundation,
443             NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0)
444       return TRUE;
445   }
446   return FALSE;
447 }
448
449 /*
450  * Finds the next connectivity check in WAITING state.
451  */
452 static CandidateCheckPair *priv_conn_check_find_next_waiting (GSList *conn_check_list)
453 {
454   GSList *i;
455
456   /* note: list is sorted in priority order to first waiting check has
457    *       the highest priority */
458   for (i = conn_check_list; i ; i = i->next) {
459     CandidateCheckPair *p = i->data;
460     if (p->state == NICE_CHECK_WAITING)
461       return p;
462   }
463
464   return NULL;
465 }
466
467 /*
468  * Finds the next connectivity check in FROZEN state.
469  */
470 static CandidateCheckPair *
471 priv_conn_check_find_next_frozen (GSList *conn_check_list)
472 {
473   GSList *i;
474
475   /* note: list is sorted in priority order to first frozen check has
476    *       the highest priority */
477   for (i = conn_check_list; i ; i = i->next) {
478     CandidateCheckPair *p = i->data;
479     if (p->state == NICE_CHECK_FROZEN)
480       return p;
481   }
482
483   return NULL;
484 }
485
486 /*
487  * Returns the number of active check lists of the agent
488  */
489 static guint
490 priv_number_of_active_check_lists (NiceAgent *agent)
491 {
492   guint n = 0;
493   GSList *i;
494
495   for (i = agent->streams; i ; i = i->next)
496     if (priv_is_checklist_active (i->data))
497       n++;
498   return n;
499 }
500
501 /*
502  * Returns the first stream of the agent having a Frozen
503  * connection check list
504  */
505 static NiceStream *
506 priv_find_first_frozen_check_list (NiceAgent *agent)
507 {
508   GSList *i;
509
510   for (i = agent->streams; i ; i = i->next) {
511     NiceStream *stream = i->data;
512     if (priv_is_checklist_frozen (stream))
513       return stream;
514   }
515   return NULL;
516 }
517
518 /*
519  * Initiates a new connectivity check for a ICE candidate pair.
520  *
521  * @return TRUE on success, FALSE on error
522  */
523 static gboolean priv_conn_check_initiate (NiceAgent *agent, CandidateCheckPair *pair)
524 {
525   SET_PAIR_STATE (agent, pair, NICE_CHECK_IN_PROGRESS);
526   if (conn_check_send (agent, pair)) {
527     SET_PAIR_STATE (agent, pair, NICE_CHECK_FAILED);
528     return FALSE;
529   }
530   return TRUE;
531 }
532
533 /*
534  * Unfreezes the next connectivity check in the list. Follows the
535  * algorithm (2.) defined in 5.7.4 (Computing States) of the ICE spec
536  * (RFC5245)
537  *
538  * See also sect 7.1.2.2.3 (Updating Pair States), and
539  * priv_conn_check_unfreeze_related().
540  * 
541  * @return TRUE on success, and FALSE if no frozen candidates were found.
542  */
543 static gboolean priv_conn_check_unfreeze_next (NiceAgent *agent, NiceStream *stream)
544 {
545   GSList *i, *j;
546   GSList *found_list = NULL;
547   gboolean result = FALSE;
548
549   priv_print_conn_check_lists (agent, G_STRFUNC, NULL);
550
551   for (i = stream->conncheck_list; i ; i = i->next) {
552     CandidateCheckPair *p1 = i->data;
553     CandidateCheckPair *pair = NULL;
554     guint lowest_component_id = stream->n_components + 1;
555     guint64 highest_priority = 0;
556
557     if (g_slist_find_custom (found_list, p1->foundation, (GCompareFunc)strcmp))
558       continue;
559     found_list = g_slist_prepend (found_list, p1->foundation);
560
561     for (j = stream->conncheck_list; j ; j = j->next) {
562       CandidateCheckPair *p2 = i->data;
563       if (strncmp (p2->foundation, p1->foundation,
564               NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0) {
565         if (p2->component_id < lowest_component_id ||
566             (p2->component_id == lowest_component_id &&
567              p2->priority > highest_priority)) {
568           pair = p2;
569           lowest_component_id = p2->component_id;
570           highest_priority = p2->priority;
571         }
572       }
573     }
574
575     if (pair) {
576       nice_debug ("Agent %p : Pair %p with s/c-id %u/%u (%s) unfrozen.",
577           agent, pair, pair->stream_id, pair->component_id, pair->foundation);
578       SET_PAIR_STATE (agent, pair, NICE_CHECK_WAITING);
579       result = TRUE;
580     }
581   }
582   g_slist_free (found_list);
583   return result;
584 }
585
586 /*
587  * Unfreezes the next next connectivity check in the list after
588  * check 'success_check' has successfully completed.
589  *
590  * See sect 7.1.2.2.3 (Updating Pair States) of ICE spec (ID-19).
591  * 
592  * @param agent context
593  * @param ok_check a connectivity check that has just completed
594  *
595  * @return TRUE on success, and FALSE if no frozen candidates were found.
596  */
597 static void priv_conn_check_unfreeze_related (NiceAgent *agent, NiceStream *stream, CandidateCheckPair *ok_check)
598 {
599   GSList *i, *j;
600
601   g_assert (ok_check);
602   g_assert_cmpint (ok_check->state, ==, NICE_CHECK_SUCCEEDED);
603   g_assert (stream);
604   g_assert_cmpuint (stream->id, ==, ok_check->stream_id);
605
606   priv_print_conn_check_lists (agent, G_STRFUNC, NULL);
607
608   /* step: perform the step (1) of 'Updating Pair States' */
609   for (i = stream->conncheck_list; i ; i = i->next) {
610     CandidateCheckPair *p = i->data;
611    
612     if (p->stream_id == ok_check->stream_id) {
613       if (p->state == NICE_CHECK_FROZEN &&
614           strncmp (p->foundation, ok_check->foundation,
615               NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0) {
616         nice_debug ("Agent %p : Unfreezing check %p (after successful check %p).", agent, p, ok_check);
617         SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
618       }
619     }
620   }
621
622   /* step: perform the step (2) of 'Updating Pair States' */
623   stream = agent_find_stream (agent, ok_check->stream_id);
624   if (priv_all_components_have_valid_pair (stream)) {
625     for (i = agent->streams; i ; i = i->next) {
626       /* the agent examines the check list for each other
627        * media stream in turn
628        */
629       NiceStream *s = i->data;
630       if (s->id == ok_check->stream_id)
631         continue;
632       if (priv_is_checklist_active (s)) {
633         /* checklist is Active
634          */
635         for (j = s->conncheck_list; j ; j = j->next) {
636           CandidateCheckPair *p = j->data;
637           if (p->state == NICE_CHECK_FROZEN &&
638               priv_foundation_matches_a_valid_pair (p->foundation, stream)) {
639             nice_debug ("Agent %p : Unfreezing check %p from stream %u (after successful check %p).", agent, p, s->id, ok_check);
640             SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
641           }
642         }
643       } else if (priv_is_checklist_frozen (s)) {
644         /* checklist is Frozen
645          */
646         gboolean match_found = FALSE;
647         /* check if there is one pair in the check list whose
648          * foundation matches a pair in the valid list under
649          * consideration
650          */
651         for (j = s->conncheck_list; j ; j = j->next) {
652           CandidateCheckPair *p = j->data;
653           if (priv_foundation_matches_a_valid_pair (p->foundation, stream)) {
654             match_found = TRUE;
655             nice_debug ("Agent %p : Unfreezing check %p from stream %u (after successful check %p).", agent, p, s->id, ok_check);
656             SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
657           }
658         }
659
660         if (!match_found) {
661           /* set the pair with the lowest component ID
662            * and highest priority to Waiting
663            */
664           priv_conn_check_unfreeze_next (agent, s);
665         }
666       }
667     }
668   }    
669 }
670
671 /*
672  * Create a new STUN transaction and add it to the list
673  * of ongoing stun transactions of a pair.
674  *
675  * @pair the pair the new stun transaction should be added to.
676  * @return the created stun transaction.
677  */
678 static StunTransaction *
679 priv_add_stun_transaction (CandidateCheckPair *pair)
680 {
681   StunTransaction *stun = g_slice_new0 (StunTransaction);
682   pair->stun_transactions = g_slist_prepend (pair->stun_transactions, stun);
683   pair->retransmit = TRUE;
684   return stun;
685 }
686
687 /*
688  * Forget a STUN transaction.
689  *
690  * @data the stun transaction to be forgotten.
691  * @user_data the component contained the concerned stun agent.
692  */
693 static void
694 priv_forget_stun_transaction (gpointer data, gpointer user_data)
695 {
696   StunTransaction *stun = data;
697   NiceComponent *component = user_data;
698   StunTransactionId id;
699
700   if (stun->message.buffer != NULL) {
701     stun_message_id (&stun->message, id);
702     stun_agent_forget_transaction (&component->stun_agent, id);
703   }
704 }
705
706 static void
707 priv_free_stun_transaction (gpointer data)
708 {
709   g_slice_free (StunTransaction, data);
710 }
711
712 /*
713  * Remove a STUN transaction from a pair, and forget it
714  * from the related component stun agent.
715  *
716  * @pair the pair the stun transaction should be removed from.
717  * @stun the stun transaction to be removed.
718  * @component the component containing the stun agent used to
719  * forget the stun transaction.
720  */
721 static void
722 priv_remove_stun_transaction (CandidateCheckPair *pair,
723   StunTransaction *stun, NiceComponent *component)
724 {
725   priv_forget_stun_transaction (stun, component);
726   pair->stun_transactions = g_slist_remove (pair->stun_transactions, stun);
727   priv_free_stun_transaction (stun);
728 }
729
730 /*
731  * Remove all STUN transactions from a pair, and forget them
732  * from the related component stun agent.
733  *
734  * @pair the pair the stun list should be cleared.
735  * @component the component containing the stun agent used to
736  * forget the stun transactions.
737  */
738 static void
739 priv_free_all_stun_transactions (CandidateCheckPair *pair,
740   NiceComponent *component)
741 {
742   if (component)
743     g_slist_foreach (pair->stun_transactions, priv_forget_stun_transaction, component);
744   g_slist_free_full (pair->stun_transactions, priv_free_stun_transaction);
745   pair->stun_transactions = NULL;
746 }
747
748 static void
749 candidate_check_pair_fail (NiceStream *stream, NiceAgent *agent, CandidateCheckPair *p)
750 {
751   NiceComponent *component;
752
753   component = nice_stream_find_component_by_id (stream, p->component_id);
754   SET_PAIR_STATE (agent, p, NICE_CHECK_FAILED);
755   priv_free_all_stun_transactions (p, component);
756 }
757
758 /*
759  * Helper function for connectivity check timer callback that
760  * runs through the stream specific part of the state machine. 
761  *
762  * @param schedule if TRUE, schedule a new check
763  *
764  * @return will return FALSE when no more pending timers.
765  */
766 static gboolean priv_conn_check_tick_stream (NiceStream *stream, NiceAgent *agent)
767 {
768   gboolean keep_timer_going = FALSE;
769   GSList *i, *j;
770   CandidateCheckPair *pair;
771   unsigned int timeout;
772   gint64 now;
773
774   now = g_get_monotonic_time ();
775
776   /* step: process ongoing STUN transactions */
777   for (i = stream->conncheck_list; i ; i = i->next) {
778     CandidateCheckPair *p = i->data;
779     gchar tmpbuf1[INET6_ADDRSTRLEN], tmpbuf2[INET6_ADDRSTRLEN];
780     NiceComponent *component;
781     guint index = 0, remaining = 0;
782
783     if (p->stun_transactions == NULL)
784       continue;
785
786     if (p->state != NICE_CHECK_IN_PROGRESS)
787       continue;
788
789     if (!agent_find_component (agent, p->stream_id, p->component_id,
790         NULL, &component))
791       continue;
792
793     j = p->stun_transactions;
794     while (j) {
795       StunTransaction *stun = j->data;
796       GSList *next = j->next;
797
798       if (now < stun->next_tick)
799         remaining++;
800       else
801         switch (stun_timer_refresh (&stun->timer)) {
802           case STUN_USAGE_TIMER_RETURN_TIMEOUT:
803 timer_return_timeout:
804             priv_remove_stun_transaction (p, stun, component);
805             break;
806           case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
807             /* case: retransmission stopped, due to the nomination of
808              * a pair with a higher priority than this in-progress pair,
809              * ICE spec, sect 8.1.2 "Updating States", item 2.2
810              */
811             if (!p->retransmit || index > 0)
812               goto timer_return_timeout;
813
814             /* case: not ready, so schedule a new timeout */
815             timeout = stun_timer_remainder (&stun->timer);
816
817             nice_debug ("Agent %p :STUN transaction retransmitted on pair %p "
818                 "(timer=%d/%d %d/%dms).",
819                 agent, p,
820                 stun->timer.retransmissions, stun->timer.max_retransmissions,
821                 stun->timer.delay - timeout, stun->timer.delay);
822
823             agent_socket_send (p->sockptr, &p->remote->addr,
824                 stun_message_length (&stun->message),
825                 (gchar *)stun->buffer);
826
827             /* note: convert from milli to microseconds for g_time_val_add() */
828             stun->next_tick = now + timeout * 1000;
829
830             return TRUE;
831           case STUN_USAGE_TIMER_RETURN_SUCCESS:
832             timeout = stun_timer_remainder (&stun->timer);
833             /* note: convert from milli to microseconds for g_time_val_add() */
834             stun->next_tick = now + timeout * 1000;
835             remaining++;
836             break;
837           default:
838             g_assert_not_reached();
839             break;
840         }
841       j = next;
842       index++;
843     }
844
845     if (remaining > 0)
846       keep_timer_going = TRUE;
847     else {
848       nice_address_to_string (&p->local->addr, tmpbuf1);
849       nice_address_to_string (&p->remote->addr, tmpbuf2);
850       nice_debug ("Agent %p : Retransmissions failed, giving up on pair %p",
851           agent, p);
852       nice_debug ("Agent %p : Failed pair is [%s]:%u --> [%s]:%u", agent,
853           tmpbuf1, nice_address_get_port (&p->local->addr),
854           tmpbuf2, nice_address_get_port (&p->remote->addr));
855       candidate_check_pair_fail (stream, agent, p);
856       priv_print_conn_check_lists (agent, G_STRFUNC,
857           ", retransmission failed");
858
859       /* perform a check if a transition state from connected to
860        * ready can be performed. This may happen here, when the last
861        * in-progress pair has expired its retransmission count
862        * in priv_conn_check_tick_stream(), which is a condition to
863        * make the transition connected to ready.
864        */
865       conn_check_update_check_list_state_for_ready (agent, stream, component);
866     }
867   }
868
869   /* step: perform an ordinary check, ICE spec, 5.8 "Scheduling Checks"
870    * note: This code is executed when the triggered checks list is
871    * empty, and when no STUN message has been sent (pacing constraint)
872    */
873   pair = priv_conn_check_find_next_waiting (stream->conncheck_list);
874   if (pair) {
875     priv_print_conn_check_lists (agent, G_STRFUNC,
876         ", got a pair in Waiting state");
877     priv_conn_check_initiate (agent, pair);
878     return TRUE;
879   }
880
881   /* note: this is unclear in the ICE spec, but a check list in Frozen
882    * state (where all pairs are in Frozen state) is not supposed to
883    * change its state by an ordinary check, but only by the success of
884    * checks in other check lists, in priv_conn_check_unfreeze_related().
885    * The underlying idea is to concentrate the checks on a single check
886    * list initially.
887    */
888   if (priv_is_checklist_frozen (stream))
889     return keep_timer_going;
890
891   /* step: ordinary check continued, if there's no pair in the waiting
892    * state, pick a pair in the frozen state
893    */
894   pair = priv_conn_check_find_next_frozen (stream->conncheck_list);
895   if (pair) {
896     priv_print_conn_check_lists (agent, G_STRFUNC,
897         ", got a pair in Frozen state");
898     SET_PAIR_STATE (agent, pair, NICE_CHECK_WAITING);
899     priv_conn_check_initiate (agent, pair);
900     return TRUE;
901   }
902   return keep_timer_going;
903 }
904
905 static gboolean
906 priv_conn_check_tick_stream_nominate (NiceStream *stream, NiceAgent *agent)
907 {
908   gboolean keep_timer_going = FALSE;
909   /* s_xxx counters are stream-wide */
910   guint s_inprogress = 0;
911   guint s_succeeded = 0;
912   guint s_discovered = 0;
913   guint s_nominated = 0;
914   guint s_waiting_for_nomination = 0;
915   guint s_valid = 0;
916   guint s_frozen = 0;
917   guint s_waiting = 0;
918   CandidateCheckPair *other_stream_pair = NULL;
919   GSList *i, *j;
920
921   /* Search for a nominated pair (or selected to be nominated pair)
922    * from another stream.
923    */
924   for (i = agent->streams; i ; i = i->next) {
925     NiceStream *s = i->data;
926     if (s->id == stream->id)
927       continue;
928     for (j = s->conncheck_list; j ; j = j->next) {
929       CandidateCheckPair *p = j->data;
930       if (p->nominated || (p->use_candidate_on_next_check &&
931           p->state != NICE_CHECK_FAILED)) {
932         other_stream_pair = p;
933         break;
934       }
935     }
936     if (other_stream_pair)
937       break;
938   }
939
940   /* we compute some stream-wide counter values */
941   for (i = stream->conncheck_list; i ; i = i->next) {
942     CandidateCheckPair *p = i->data;
943     if (p->state == NICE_CHECK_FROZEN)
944       s_frozen++;
945     else if (p->state == NICE_CHECK_IN_PROGRESS)
946       s_inprogress++;
947     else if (p->state == NICE_CHECK_WAITING)
948       s_waiting++;
949     else if (p->state == NICE_CHECK_SUCCEEDED)
950       s_succeeded++;
951     else if (p->state == NICE_CHECK_DISCOVERED)
952       s_discovered++;
953     if (p->valid)
954       s_valid++;
955
956     if ((p->state == NICE_CHECK_SUCCEEDED || p->state == NICE_CHECK_DISCOVERED)
957         && p->nominated)
958       s_nominated++;
959     else if ((p->state == NICE_CHECK_SUCCEEDED ||
960             p->state == NICE_CHECK_DISCOVERED) && !p->nominated)
961       s_waiting_for_nomination++;
962   }
963
964   /* note: keep the timer going as long as there is work to be done */
965   if (s_inprogress)
966     keep_timer_going = TRUE;
967   
968   if (s_nominated < stream->n_components &&
969       s_waiting_for_nomination) {
970     if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
971       if (agent->nomination_mode == NICE_NOMINATION_MODE_REGULAR &&
972           agent->controlling_mode) {
973 #define NICE_MIN_NUMBER_OF_VALID_PAIRS 2
974         /* ICE 8.1.1.1 Regular nomination
975          * we choose to nominate the valid pair of a component if
976          * - there is no pair left frozen, waiting or in-progress, or
977          * - if there are at least two valid pairs, or
978          * - if there is at least one valid pair of type HOST-HOST
979          *
980          * This is the "stopping criterion" described in 8.1.1.1, and is
981          * a "local optimization" between accumulating more valid pairs,
982          * and limiting the time spent waiting for in-progress connections
983          * checks until they finally fail.
984          */
985         for (i = stream->components; i; i = i->next) {
986           NiceComponent *component = i->data;
987           CandidateCheckPair *other_component_pair = NULL;
988           CandidateCheckPair *this_component_pair = NULL;
989           NiceCandidate *lcand1 = NULL;
990           NiceCandidate *rcand1 = NULL;
991           NiceCandidate *lcand2, *rcand2;
992           gboolean already_done = FALSE;
993           gboolean found_other_component_pair = FALSE;
994           gboolean found_other_stream_pair = FALSE;
995           gboolean first_nomination = FALSE;
996           gboolean stopping_criterion;
997           /* p_xxx counters are component-wide */
998           guint p_valid = 0;
999           guint p_frozen = 0;
1000           guint p_waiting = 0;
1001           guint p_inprogress = 0;
1002           guint p_host_host_valid = 0;
1003
1004           /* we compute some component-wide counter values */
1005           for (j = stream->conncheck_list; j ; j = j->next) {
1006             CandidateCheckPair *p = j->data;
1007             if (p->component_id == component->id) {
1008               /* verify that the choice of the pair to be nominated
1009                * has not already been done
1010                */
1011               if (p->use_candidate_on_next_check)
1012                 already_done = TRUE;
1013               if (p->state == NICE_CHECK_FROZEN)
1014                 p_frozen++;
1015               else if (p->state == NICE_CHECK_WAITING)
1016                 p_waiting++;
1017               else if (p->state == NICE_CHECK_IN_PROGRESS)
1018                 p_inprogress++;
1019               if (p->valid)
1020                 p_valid++;
1021               if (p->valid &&
1022                   p->local->type == NICE_CANDIDATE_TYPE_HOST &&
1023                   p->remote->type == NICE_CANDIDATE_TYPE_HOST)
1024                 p_host_host_valid++;
1025             }
1026           }
1027
1028           if (already_done)
1029             continue;
1030
1031           /* Search for a nominated pair (or selected to be nominated pair)
1032            * from another component of this stream.
1033            */
1034           for (j = stream->conncheck_list; j ; j = j->next) {
1035             CandidateCheckPair *p = j->data;
1036             if (p->component_id == component->id)
1037               continue;
1038             if (p->nominated || (p->use_candidate_on_next_check &&
1039                 p->state != NICE_CHECK_FAILED)) {
1040               other_component_pair = p;
1041               break;
1042             }
1043           }
1044
1045           if (other_stream_pair == NULL && other_component_pair == NULL)
1046             first_nomination = TRUE;
1047
1048           /* We choose a pair to be nominated in the list of valid
1049            * pairs.
1050            *
1051            * this pair will be the one with the highest priority,
1052            * when we don't have other nominated pairs in other
1053            * components and in other streams
1054            *
1055            * this pair will be a pair compatible with another nominated
1056            * pair from another component if we found one.
1057            *
1058            * else this pair will be a pair compatible with another
1059            * nominated pair from another stream if we found one.
1060            *
1061            */
1062           for (j = stream->conncheck_list; j ; j = j->next) {
1063             CandidateCheckPair *p = j->data;
1064             /* note: highest priority item selected (list always sorted) */
1065             if (p->component_id == component->id &&
1066                 !p->nominated &&
1067                 !p->use_candidate_on_next_check &&
1068                 p->valid) {
1069               /* According a ICE spec, sect 8.1.1.1.  "Regular
1070                * Nomination", we enqueue the check that produced this
1071                * valid pair. When this pair has been discovered, we want
1072                * to test its parent pair instead.
1073                */
1074               if (p->succeeded_pair != NULL) {
1075                 g_assert_cmpint (p->state, ==, NICE_CHECK_DISCOVERED);
1076                 p = p->succeeded_pair;
1077               }
1078               g_assert_cmpint (p->state, ==, NICE_CHECK_SUCCEEDED);
1079
1080               if (this_component_pair == NULL)
1081                 /* highest priority pair */
1082                 this_component_pair = p;
1083
1084               lcand1 = p->local;
1085               rcand1 = p->remote;
1086
1087               if (first_nomination)
1088                 /* use the highest priority pair */
1089                 break;
1090
1091               if (other_component_pair) {
1092                 lcand2 = other_component_pair->local;
1093                 rcand2 = other_component_pair->remote;
1094               }
1095               if (other_component_pair &&
1096                   lcand1->transport == lcand2->transport &&
1097                   nice_address_equal_no_port (&lcand1->addr, &lcand2->addr) &&
1098                   nice_address_equal_no_port (&rcand1->addr, &rcand2->addr)) {
1099                 /* else continue the research with lower priority
1100                  * pairs, compatible with a nominated pair of
1101                  * another component
1102                  */
1103                 this_component_pair = p;
1104                 found_other_component_pair = TRUE;
1105                 break;
1106               }
1107
1108               if (other_stream_pair) {
1109                 lcand2 = other_stream_pair->local;
1110                 rcand2 = other_stream_pair->remote;
1111               }
1112               if (other_stream_pair &&
1113                   other_component_pair == NULL &&
1114                   lcand1->transport == lcand2->transport &&
1115                   nice_address_equal_no_port (&lcand1->addr, &lcand2->addr) &&
1116                   nice_address_equal_no_port (&rcand1->addr, &rcand2->addr)) {
1117                 /* else continue the research with lower priority
1118                  * pairs, compatible with a nominated pair of
1119                  * another stream
1120                  */
1121                 this_component_pair = p;
1122                 found_other_stream_pair = TRUE;
1123                 break;
1124               }
1125             }
1126           }
1127
1128           /* No valid pair for this component */
1129           if (this_component_pair == NULL)
1130             continue;
1131
1132           /* The stopping criterion tries to select a set of pairs of
1133            * the same kind (transport/type) for all components of a
1134            * stream, and for all streams, when possible (see last
1135            * paragraph).
1136            *
1137            * When no stream has nominated a pair yet, we apply the
1138            * following criterion :
1139            *   - stop if we have a valid host-host pair
1140            *   - or stop if we have at least "some* (2 in the current
1141            *     implementation) valid pairs, and select the best one
1142            *   - or stop if the conncheck cannot evolve more
1143            *
1144            * Else when the stream has a nominated pair in another
1145            * component we apply this criterion:
1146            *   - stop if we have a valid pair of the same kind than this
1147            *     other nominated pair.
1148            *   - or stop if the conncheck cannot evolve more
1149            *
1150            * Else when another stream has a nominated pair we apply the
1151            * following criterion:
1152            *   - stop if we have a valid pair of the same kind than the
1153            *     other nominated pair.
1154            *   - or stop if the conncheck cannot evolve more
1155            *
1156            * When no further evolution of the conncheck is possible, we
1157            * prefer to select the best valid pair we have, *even* if it
1158            * is not compatible with the transport of another stream of
1159            * component. We think it's still a better choice than marking
1160            * this component 'failed'.
1161            */
1162           stopping_criterion = FALSE;
1163           if (first_nomination && p_host_host_valid > 0) {
1164             stopping_criterion = TRUE;
1165             nice_debug ("Agent %p : stopping criterion: "
1166                 "valid host-host pair", agent);
1167           } else if (first_nomination &&
1168               p_valid >= NICE_MIN_NUMBER_OF_VALID_PAIRS) {
1169             stopping_criterion = TRUE;
1170             nice_debug ("Agent %p : stopping criterion: "
1171                 "*some* valid pairs", agent);
1172           } else if (found_other_component_pair) {
1173             stopping_criterion = TRUE;
1174             nice_debug ("Agent %p : stopping criterion: "
1175                 "matching pair in another component", agent);
1176           } else if (found_other_stream_pair) {
1177             stopping_criterion = TRUE;
1178             nice_debug ("Agent %p : stopping criterion: "
1179                 "matching pair in another stream", agent);
1180           } else if (p_waiting == 0 && p_inprogress == 0 && p_frozen == 0) {
1181             stopping_criterion = TRUE;
1182             nice_debug ("Agent %p : stopping criterion: "
1183                 "no more pairs to check", agent);
1184           }
1185
1186           if (!stopping_criterion)
1187             continue;
1188
1189           /* when the stopping criterion is reached, we add the
1190            * selected pair for this component to the triggered checks
1191            * list
1192            */
1193           nice_debug ("Agent %p : restarting check of %s:%s pair %p with "
1194               "USE-CANDIDATE attrib (regular nomination) for "
1195               "stream %d component %d", agent,
1196               priv_candidate_transport_to_string (
1197                   this_component_pair->local->transport),
1198               priv_candidate_transport_to_string (
1199                   this_component_pair->remote->transport),
1200               this_component_pair, stream->id, component->id);
1201           this_component_pair->use_candidate_on_next_check = TRUE;
1202           priv_add_pair_to_triggered_check_queue (agent, this_component_pair);
1203           keep_timer_going = TRUE;
1204         }
1205       }
1206     } else if (agent->controlling_mode) {
1207       for (i = stream->components; i; i = i->next) {
1208         NiceComponent *component = i->data;
1209
1210         for (j = stream->conncheck_list; j ; j = j->next) {
1211           CandidateCheckPair *p = j->data;
1212           /* note: highest priority item selected (list always sorted) */
1213           if (p->component_id == component->id &&
1214               (p->state == NICE_CHECK_SUCCEEDED ||
1215                p->state == NICE_CHECK_DISCOVERED)) {
1216             nice_debug ("Agent %p : restarting check of pair %p as the "
1217                 "nominated pair.", agent, p);
1218             p->nominated = TRUE;
1219             conn_check_update_selected_pair (agent, component, p);
1220             priv_add_pair_to_triggered_check_queue (agent, p);
1221             keep_timer_going = TRUE;
1222             break; /* move to the next component */
1223           }
1224         }
1225       }
1226     }
1227   }
1228   if (stream->tick_counter++ % 50 == 0)
1229     nice_debug ("Agent %p : stream %u: timer tick #%u: %u frozen, "
1230         "%u in-progress, %u waiting, %u succeeded, %u discovered, "
1231         "%u nominated, %u waiting-for-nom, %u valid",
1232         agent, stream->id, stream->tick_counter,
1233         s_frozen, s_inprogress, s_waiting, s_succeeded, s_discovered,
1234         s_nominated, s_waiting_for_nomination, s_valid);
1235
1236   return keep_timer_going;
1237
1238 }
1239
1240 static void
1241 conn_check_stop (NiceAgent *agent)
1242 {
1243   if (agent->conncheck_timer_source == NULL)
1244     return;
1245
1246   g_source_destroy (agent->conncheck_timer_source);
1247   g_source_unref (agent->conncheck_timer_source);
1248   agent->conncheck_timer_source = NULL;
1249   agent->conncheck_ongoing_idle_delay = 0;
1250 }
1251
1252
1253 /*
1254  * Timer callback that handles initiating and managing connectivity
1255  * checks (paced by the Ta timer).
1256  *
1257  * This function is designed for the g_timeout_add() interface.
1258  *
1259  * @return will return FALSE when no more pending timers.
1260  */
1261 static gboolean priv_conn_check_tick_agent_locked (NiceAgent *agent,
1262     gpointer user_data)
1263 {
1264   CandidateCheckPair *pair = NULL;
1265   gboolean keep_timer_going = FALSE;
1266   GSList *i, *j;
1267
1268   /* configure the initial state of the check lists of the agent
1269    * as described in ICE spec, 5.7.4
1270    *
1271    * if all pairs in all check lists are in frozen state, then
1272    * we are in the initial state (5.7.4, point 1.)
1273    */
1274   if (priv_number_of_active_check_lists (agent) == 0) {
1275     /* set some pairs of the first stream in the waiting state
1276      * ICE spec, 5.7.4, point 2.
1277      *
1278      * note: we adapt the ICE spec here, by selecting the first
1279      * frozen check list, which is not necessarily the check
1280      * list of the first stream (the first stream may be completed)
1281      */
1282     NiceStream *stream = priv_find_first_frozen_check_list (agent);
1283     if (stream)
1284       priv_conn_check_unfreeze_next (agent, stream);
1285   }
1286
1287   /* step: perform a test from the triggered checks list,
1288    * ICE spec, 5.8 "Scheduling Checks"
1289    */
1290   pair = priv_get_pair_from_triggered_check_queue (agent);
1291
1292   if (pair) {
1293     priv_print_conn_check_lists (agent, G_STRFUNC,
1294         ", got a pair from triggered check list");
1295     if (conn_check_send (agent, pair)) {
1296       SET_PAIR_STATE (agent, pair, NICE_CHECK_FAILED);
1297       return FALSE;
1298     }
1299     return TRUE;
1300   }
1301
1302   /* step: process ongoing STUN transactions and
1303    * perform an ordinary check, ICE spec, 5.8, "Scheduling Checks"
1304    */
1305   for (i = agent->streams; i ; i = i->next) {
1306     NiceStream *stream = i->data;
1307     if (priv_conn_check_tick_stream (stream, agent))
1308       keep_timer_going = TRUE;
1309     if (priv_conn_check_tick_stream_nominate (stream, agent))
1310       keep_timer_going = TRUE;
1311   }
1312
1313   /* step: if no work left and a conncheck list of a stream is still
1314    * frozen, set the pairs to waiting, according to ICE SPEC, sect
1315    * 7.1.3.3.  "Check List and Timer State Updates"
1316    */
1317   if (!keep_timer_going) {
1318     for (i = agent->streams; i ; i = i->next) {
1319       NiceStream *stream = i->data;
1320       if (priv_is_checklist_frozen (stream)) {
1321         nice_debug ("Agent %p : stream %d conncheck list is still "
1322             "frozen, while other lists are completed. Unfreeze it.",
1323             agent, stream->id);
1324         keep_timer_going = priv_conn_check_unfreeze_next (agent, stream);
1325       }
1326       if (!keep_timer_going && !stream->peer_gathering_done) {
1327         keep_timer_going = TRUE;
1328       }
1329     }
1330   }
1331
1332   /* note: we provide a grace period before declaring a component as
1333    * failed. Components marked connected, and then ready follow another
1334    * code path, and are not concerned by this grace period.
1335    */
1336   if (!keep_timer_going && agent->conncheck_ongoing_idle_delay == 0)
1337     nice_debug ("Agent %p : waiting %d msecs before checking "
1338         "for failed components.", agent, agent->idle_timeout);
1339
1340   if (keep_timer_going)
1341     agent->conncheck_ongoing_idle_delay = 0;
1342   else
1343     agent->conncheck_ongoing_idle_delay += agent->timer_ta;
1344
1345   /* step: stop timer if no work left */
1346   if (!keep_timer_going &&
1347       agent->conncheck_ongoing_idle_delay >= agent->idle_timeout) {
1348     nice_debug ("Agent %p : checking for failed components now.", agent);
1349     for (i = agent->streams; i; i = i->next) {
1350       NiceStream *stream = i->data;
1351       priv_update_check_list_failed_components (agent, stream);
1352       for (j = stream->components; j; j = j->next) {
1353         NiceComponent *component = j->data;
1354         conn_check_update_check_list_state_for_ready (agent, stream, component);
1355       }
1356     }
1357
1358     nice_debug ("Agent %p : %s: stopping conncheck timer", agent, G_STRFUNC);
1359     priv_print_conn_check_lists (agent, G_STRFUNC,
1360         ", conncheck timer stopped");
1361
1362     /* Stopping the timer so destroy the source.. this will allow
1363        the timer to be reset if we get a set_remote_candidates after this
1364        point */
1365     conn_check_stop (agent);
1366
1367     /* XXX: what to signal, is all processing now really done? */
1368     nice_debug ("Agent %p : changing conncheck state to COMPLETED.", agent);
1369     return FALSE;
1370   }
1371
1372   return TRUE;
1373 }
1374
1375 static gboolean priv_conn_keepalive_retransmissions_tick_agent_locked (
1376     NiceAgent *agent, gpointer pointer)
1377 {
1378   CandidatePair *pair = (CandidatePair *) pointer;
1379
1380   g_source_destroy (pair->keepalive.tick_source);
1381   g_source_unref (pair->keepalive.tick_source);
1382   pair->keepalive.tick_source = NULL;
1383
1384   switch (stun_timer_refresh (&pair->keepalive.timer)) {
1385     case STUN_USAGE_TIMER_RETURN_TIMEOUT:
1386       {
1387         /* Time out */
1388         StunTransactionId id;
1389         NiceComponent *component;
1390
1391         if (!agent_find_component (agent,
1392                 pair->keepalive.stream_id, pair->keepalive.component_id,
1393                 NULL, &component)) {
1394           nice_debug ("Could not find stream or component in"
1395               " priv_conn_keepalive_retransmissions_tick");
1396           return FALSE;
1397         }
1398
1399         stun_message_id (&pair->keepalive.stun_message, id);
1400         stun_agent_forget_transaction (&component->stun_agent, id);
1401         pair->keepalive.stun_message.buffer = NULL;
1402
1403         if (agent->media_after_tick) {
1404           nice_debug ("Agent %p : Keepalive conncheck timed out!! "
1405               "but media was received. Suspecting keepalive lost because of "
1406               "network bottleneck", agent);
1407         } else {
1408           nice_debug ("Agent %p : Keepalive conncheck timed out!! "
1409               "peer probably lost connection", agent);
1410           agent_signal_component_state_change (agent,
1411               pair->keepalive.stream_id, pair->keepalive.component_id,
1412               NICE_COMPONENT_STATE_FAILED);
1413         }
1414         break;
1415       }
1416     case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
1417       /* Retransmit */
1418       agent_socket_send (pair->local->sockptr, &pair->remote->addr,
1419           stun_message_length (&pair->keepalive.stun_message),
1420           (gchar *)pair->keepalive.stun_buffer);
1421
1422       nice_debug ("Agent %p : Retransmitting keepalive conncheck",
1423           agent);
1424
1425       G_GNUC_FALLTHROUGH;
1426     case STUN_USAGE_TIMER_RETURN_SUCCESS:
1427       agent_timeout_add_with_context (agent,
1428           &pair->keepalive.tick_source,
1429           "Pair keepalive", stun_timer_remainder (&pair->keepalive.timer),
1430           priv_conn_keepalive_retransmissions_tick_agent_locked, pair);
1431       break;
1432     default:
1433       g_assert_not_reached();
1434       break;
1435   }
1436
1437   return FALSE;
1438 }
1439
1440 static guint32 peer_reflexive_candidate_priority (NiceAgent *agent,
1441     NiceCandidate *local_candidate)
1442 {
1443   NiceCandidate *candidate_priority =
1444       nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE);
1445   guint32 priority;
1446
1447   candidate_priority->transport = local_candidate->transport;
1448   candidate_priority->component_id = local_candidate->component_id;
1449   candidate_priority->base_addr = local_candidate->addr;
1450   if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
1451     priority = nice_candidate_jingle_priority (candidate_priority);
1452   } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
1453              agent->compatibility == NICE_COMPATIBILITY_OC2007) {
1454     priority = nice_candidate_msn_priority (candidate_priority);
1455   } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
1456     priority = nice_candidate_ms_ice_priority (candidate_priority,
1457         agent->reliable, FALSE);
1458   } else {
1459     priority = nice_candidate_ice_priority (candidate_priority,
1460         agent->reliable, FALSE);
1461   }
1462   nice_candidate_free (candidate_priority);
1463
1464   return priority;
1465 }
1466
1467 /* Returns the priority of a local candidate of type peer-reflexive that
1468  * would be learned as a consequence of a check from this local
1469  * candidate. See RFC 5245, section 7.1.2.1. "PRIORITY and USE-CANDIDATE".
1470  * RFC 5245 is more explanatory than RFC 8445 on this detail.
1471  *
1472  * Apply to local candidates of type host only, because candidates of type
1473  * relay are supposed to have a public IP address, that wont generate
1474  * a peer-reflexive address. Server-reflexive candidates are not
1475  * concerned too, because no STUN request is sent with a local candidate
1476  * of this type.
1477  */
1478 static guint32 stun_request_priority (NiceAgent *agent,
1479     NiceCandidate *local_candidate)
1480 {
1481   if (local_candidate->type == NICE_CANDIDATE_TYPE_HOST)
1482     return peer_reflexive_candidate_priority (agent, local_candidate);
1483   else
1484     return local_candidate->priority;
1485 }
1486
1487 static void ms_ice2_legacy_conncheck_send(StunMessage *msg, NiceSocket *sock,
1488     const NiceAddress *remote_addr)
1489 {
1490   uint32_t *fingerprint_attr;
1491   uint32_t fingerprint_orig;
1492   uint16_t fingerprint_len;
1493   size_t buffer_len;
1494
1495   if (msg->agent->ms_ice2_send_legacy_connchecks == FALSE) {
1496     return;
1497   }
1498
1499   fingerprint_attr = (uint32_t *)stun_message_find (msg,
1500       STUN_ATTRIBUTE_FINGERPRINT, &fingerprint_len);
1501
1502   if (fingerprint_attr == NULL) {
1503     nice_debug ("FINGERPRINT not found.");
1504     return;
1505   }
1506
1507   if (fingerprint_len != sizeof (fingerprint_orig)) {
1508     nice_debug ("Unexpected FINGERPRINT length %u.", fingerprint_len);
1509     return;
1510   }
1511
1512   memcpy (&fingerprint_orig, fingerprint_attr, sizeof (fingerprint_orig));
1513
1514   buffer_len = stun_message_length (msg);
1515
1516   *fingerprint_attr = stun_fingerprint (msg->buffer, buffer_len, TRUE);
1517
1518   agent_socket_send (sock, remote_addr, buffer_len, (gchar *)msg->buffer);
1519
1520   memcpy (fingerprint_attr, &fingerprint_orig, sizeof (fingerprint_orig));
1521 }
1522
1523 /*
1524  * Timer callback that handles initiating and managing connectivity
1525  * checks (paced by the Ta timer).
1526  *
1527  * This function is designed for the g_timeout_add() interface.
1528  *
1529  * @return will return FALSE when no more pending timers.
1530  */
1531 static gboolean priv_conn_keepalive_tick_unlocked (NiceAgent *agent)
1532 {
1533   GSList *i, *j, *k;
1534   int errors = 0;
1535   size_t buf_len = 0;
1536   guint64 now;
1537   guint64 min_next_tick;
1538   guint64 next_timer_tick;
1539
1540   now = g_get_monotonic_time ();
1541   min_next_tick = now + 1000 * NICE_AGENT_TIMER_TR_DEFAULT;
1542
1543   /* case 1: session established and media flowing
1544    *         (ref ICE sect 11 "Keepalives" RFC-8445)
1545    * TODO: keepalives should be send only when no packet has been sent
1546    * on that pair in the last Tr seconds, and not unconditionally.
1547    */
1548   for (i = agent->streams; i; i = i->next) {
1549
1550     NiceStream *stream = i->data;
1551     for (j = stream->components; j; j = j->next) {
1552       NiceComponent *component = j->data;
1553       if (component->selected_pair.local != NULL) {
1554         CandidatePair *p = &component->selected_pair;
1555
1556         /* Disable keepalive checks on TCP candidates unless explicitly enabled */
1557         if (p->local->transport != NICE_CANDIDATE_TRANSPORT_UDP &&
1558             !agent->keepalive_conncheck)
1559           continue;
1560
1561         if (p->keepalive.next_tick) {
1562           if (p->keepalive.next_tick < min_next_tick)
1563             min_next_tick = p->keepalive.next_tick;
1564           if (now < p->keepalive.next_tick)
1565             continue;
1566         }
1567
1568         if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
1569             agent->keepalive_conncheck) {
1570           uint8_t uname[NICE_STREAM_MAX_UNAME];
1571           size_t uname_len =
1572               priv_create_username (agent, agent_find_stream (agent, stream->id),
1573                   component->id, p->remote, p->local, uname, sizeof (uname),
1574                   FALSE);
1575           uint8_t *password = NULL;
1576           size_t password_len = priv_get_password (agent,
1577               agent_find_stream (agent, stream->id), p->remote, &password);
1578
1579           if (p->keepalive.stun_message.buffer != NULL) {
1580             nice_debug ("Agent %p: Keepalive for s%u:c%u still"
1581                 " retransmitting, not restarting", agent, stream->id,
1582                 component->id);
1583             continue;
1584           }
1585
1586           if (nice_debug_is_enabled ()) {
1587             gchar tmpbuf[INET6_ADDRSTRLEN];
1588             nice_address_to_string (&p->remote->addr, tmpbuf);
1589             nice_debug ("Agent %p : Keepalive STUN-CC REQ to '%s:%u', "
1590                 "(c-id:%u), username='%.*s' (%" G_GSIZE_FORMAT "), "
1591                 "password='%.*s' (%" G_GSIZE_FORMAT "), priority=%08x.",
1592                 agent, tmpbuf, nice_address_get_port (&p->remote->addr),
1593                 component->id, (int) uname_len, uname, uname_len,
1594                 (int) password_len, password, password_len,
1595                 p->stun_priority);
1596           }
1597           if (uname_len > 0) {
1598             buf_len = stun_usage_ice_conncheck_create (&component->stun_agent,
1599                 &p->keepalive.stun_message, p->keepalive.stun_buffer,
1600                 sizeof(p->keepalive.stun_buffer),
1601                 uname, uname_len, password, password_len,
1602                 agent->controlling_mode, agent->controlling_mode,
1603                 p->stun_priority,
1604                 agent->tie_breaker,
1605                 NULL,
1606                 agent_to_ice_compatibility (agent));
1607
1608             nice_debug ("Agent %p: conncheck created %zd - %p",
1609                 agent, buf_len, p->keepalive.stun_message.buffer);
1610
1611             if (buf_len > 0) {
1612               stun_timer_start (&p->keepalive.timer,
1613                   agent->stun_initial_timeout,
1614                   agent->stun_max_retransmissions);
1615
1616               agent->media_after_tick = FALSE;
1617
1618               /* send the conncheck */
1619               agent_socket_send (p->local->sockptr, &p->remote->addr,
1620                   buf_len, (gchar *)p->keepalive.stun_buffer);
1621
1622               p->keepalive.stream_id = stream->id;
1623               p->keepalive.component_id = component->id;
1624               p->keepalive.next_tick = now + 1000 * NICE_AGENT_TIMER_TR_DEFAULT;
1625
1626               agent_timeout_add_with_context (agent,
1627                   &p->keepalive.tick_source, "Pair keepalive",
1628                   stun_timer_remainder (&p->keepalive.timer),
1629                   priv_conn_keepalive_retransmissions_tick_agent_locked, p);
1630
1631               next_timer_tick = now + agent->timer_ta * 1000;
1632               goto done;
1633             } else {
1634               ++errors;
1635             }
1636           }
1637         } else {
1638           buf_len = stun_usage_bind_keepalive (&component->stun_agent,
1639               &p->keepalive.stun_message, p->keepalive.stun_buffer,
1640               sizeof(p->keepalive.stun_buffer));
1641
1642           if (buf_len > 0) {
1643             agent_socket_send (p->local->sockptr, &p->remote->addr, buf_len,
1644                 (gchar *)p->keepalive.stun_buffer);
1645
1646             p->keepalive.next_tick = now + 1000 * NICE_AGENT_TIMER_TR_DEFAULT;
1647
1648             if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
1649               ms_ice2_legacy_conncheck_send (&p->keepalive.stun_message,
1650                   p->local->sockptr, &p->remote->addr);
1651             }
1652
1653             if (nice_debug_is_enabled ()) {
1654               gchar tmpbuf[INET6_ADDRSTRLEN];
1655               nice_address_to_string (&p->local->base_addr, tmpbuf);
1656               nice_debug ("Agent %p : resending STUN to keep the "
1657                   "selected base address %s:%u alive in s%d/c%d.", agent,
1658                   tmpbuf, nice_address_get_port (&p->local->base_addr),
1659                   stream->id, component->id);
1660             }
1661
1662             next_timer_tick = now + agent->timer_ta * 1000;
1663             goto done;
1664           } else {
1665             ++errors;
1666           }
1667         }
1668       }
1669     }
1670   }
1671
1672   /* case 2: connectivity establishment ongoing
1673    *         (ref ICE sect 5.1.1.4 "Keeping Candidates Alive" RFC-8445)
1674    */
1675   for (i = agent->streams; i; i = i->next) {
1676     NiceStream *stream = i->data;
1677     for (j = stream->components; j; j = j->next) {
1678       NiceComponent *component = j->data;
1679       if (component->state < NICE_COMPONENT_STATE_CONNECTED &&
1680           agent->stun_server_ip) {
1681         NiceAddress stun_server;
1682         if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
1683           StunAgent stun_agent;
1684           uint8_t stun_buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
1685           StunMessage stun_message;
1686           size_t buffer_len = 0;
1687
1688           nice_address_set_port (&stun_server, agent->stun_server_port);
1689
1690           nice_agent_init_stun_agent (agent, &stun_agent);
1691
1692           buffer_len = stun_usage_bind_create (&stun_agent,
1693               &stun_message, stun_buffer, sizeof(stun_buffer));
1694
1695           for (k = component->local_candidates; k; k = k->next) {
1696             NiceCandidate *candidate = (NiceCandidate *) k->data;
1697             if (candidate->type == NICE_CANDIDATE_TYPE_HOST &&
1698                 candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP &&
1699                 nice_address_ip_version (&candidate->addr) ==
1700                 nice_address_ip_version (&stun_server)) {
1701
1702               if (candidate->keepalive_next_tick) {
1703                 if (candidate->keepalive_next_tick < min_next_tick)
1704                   min_next_tick = candidate->keepalive_next_tick;
1705                 if (now < candidate->keepalive_next_tick)
1706                 continue;
1707               }
1708
1709               /* send the conncheck */
1710               if (nice_debug_is_enabled ()) {
1711                 gchar tmpbuf[INET6_ADDRSTRLEN];
1712                 nice_address_to_string (&candidate->addr, tmpbuf);
1713                 nice_debug ("Agent %p : resending STUN to keep the local "
1714                     "candidate %s:%u alive in s%d/c%d.", agent,
1715                     tmpbuf, nice_address_get_port (&candidate->addr),
1716                     stream->id, component->id);
1717               }
1718               agent_socket_send (candidate->sockptr, &stun_server,
1719                   buffer_len, (gchar *)stun_buffer);
1720               candidate->keepalive_next_tick = now +
1721                   1000 * NICE_AGENT_TIMER_TR_DEFAULT;
1722               next_timer_tick = now + agent->timer_ta * 1000;
1723               goto done;
1724             }
1725           }
1726         }
1727       }
1728     }
1729   }
1730
1731   next_timer_tick = min_next_tick;
1732
1733   done:
1734   if (errors) {
1735     nice_debug ("Agent %p : %s: stopping keepalive timer", agent, G_STRFUNC);
1736     return FALSE;
1737   }
1738
1739   if (agent->keepalive_timer_source) {
1740     g_source_destroy (agent->keepalive_timer_source);
1741     g_source_unref (agent->keepalive_timer_source);
1742     agent->keepalive_timer_source = NULL;
1743   }
1744   agent_timeout_add_with_context (agent, &agent->keepalive_timer_source,
1745       "Connectivity keepalive timeout", (next_timer_tick - now)/ 1000,
1746       priv_conn_keepalive_tick_agent_locked, NULL);
1747   return TRUE;
1748 }
1749
1750 static gboolean priv_conn_keepalive_tick_agent_locked (NiceAgent *agent,
1751     gpointer pointer)
1752 {
1753   gboolean ret;
1754
1755   ret = priv_conn_keepalive_tick_unlocked (agent);
1756   if (ret == FALSE) {
1757     if (agent->keepalive_timer_source) {
1758       g_source_destroy (agent->keepalive_timer_source);
1759       g_source_unref (agent->keepalive_timer_source);
1760       agent->keepalive_timer_source = NULL;
1761     }
1762   }
1763
1764   return ret;
1765 }
1766
1767
1768 static gboolean priv_turn_allocate_refresh_retransmissions_tick_agent_locked (
1769     NiceAgent *agent, gpointer pointer)
1770 {
1771   CandidateRefresh *cand = (CandidateRefresh *) pointer;
1772
1773   g_source_destroy (cand->tick_source);
1774   g_source_unref (cand->tick_source);
1775   cand->tick_source = NULL;
1776
1777   switch (stun_timer_refresh (&cand->timer)) {
1778     case STUN_USAGE_TIMER_RETURN_TIMEOUT:
1779       {
1780         /* Time out */
1781         StunTransactionId id;
1782
1783         stun_message_id (&cand->stun_message, id);
1784         stun_agent_forget_transaction (&cand->stun_agent, id);
1785
1786         refresh_free (agent, cand);
1787         break;
1788       }
1789     case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
1790       /* Retransmit */
1791       agent_socket_send (cand->nicesock, &cand->server,
1792           stun_message_length (&cand->stun_message), (gchar *)cand->stun_buffer);
1793
1794       G_GNUC_FALLTHROUGH;
1795     case STUN_USAGE_TIMER_RETURN_SUCCESS:
1796       agent_timeout_add_with_context (agent, &cand->tick_source,
1797           "Candidate TURN refresh", stun_timer_remainder (&cand->timer),
1798           priv_turn_allocate_refresh_retransmissions_tick_agent_locked, cand);
1799       break;
1800     default:
1801       /* Nothing to do. */
1802       break;
1803   }
1804
1805   return G_SOURCE_REMOVE;
1806 }
1807
1808 static void priv_turn_allocate_refresh_tick_unlocked (NiceAgent *agent,
1809     CandidateRefresh *cand)
1810 {
1811   uint8_t *username;
1812   gsize username_len;
1813   uint8_t *password;
1814   gsize password_len;
1815   size_t buffer_len = 0;
1816   StunUsageTurnCompatibility turn_compat =
1817       agent_to_turn_compatibility (agent);
1818
1819   username = (uint8_t *)cand->candidate->turn->username;
1820   username_len = (size_t) strlen (cand->candidate->turn->username);
1821   password = (uint8_t *)cand->candidate->turn->password;
1822   password_len = (size_t) strlen (cand->candidate->turn->password);
1823
1824   if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
1825       turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
1826     username = cand->candidate->turn->decoded_username;
1827     password = cand->candidate->turn->decoded_password;
1828     username_len = cand->candidate->turn->decoded_username_len;
1829     password_len = cand->candidate->turn->decoded_password_len;
1830   }
1831
1832   buffer_len = stun_usage_turn_create_refresh (&cand->stun_agent,
1833       &cand->stun_message,  cand->stun_buffer, sizeof(cand->stun_buffer),
1834       cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg, -1,
1835       username, username_len,
1836       password, password_len,
1837       turn_compat);
1838
1839   nice_debug ("Agent %p : Sending allocate Refresh %zd", agent,
1840       buffer_len);
1841
1842   if (cand->tick_source != NULL) {
1843     g_source_destroy (cand->tick_source);
1844     g_source_unref (cand->tick_source);
1845     cand->tick_source = NULL;
1846   }
1847
1848   if (buffer_len > 0) {
1849     stun_timer_start (&cand->timer,
1850         agent->stun_initial_timeout,
1851         agent->stun_max_retransmissions);
1852
1853     /* send the refresh */
1854     agent_socket_send (cand->nicesock, &cand->server,
1855         buffer_len, (gchar *)cand->stun_buffer);
1856
1857     agent_timeout_add_with_context (agent, &cand->tick_source,
1858         "Candidate TURN refresh", stun_timer_remainder (&cand->timer),
1859         priv_turn_allocate_refresh_retransmissions_tick_agent_locked, cand);
1860   }
1861
1862 }
1863
1864
1865 /*
1866  * Timer callback that handles refreshing TURN allocations
1867  *
1868  * This function is designed for the g_timeout_add() interface.
1869  *
1870  * @return will return FALSE when no more pending timers.
1871  */
1872 static gboolean priv_turn_allocate_refresh_tick_agent_locked (NiceAgent *agent,
1873     gpointer pointer)
1874 {
1875   CandidateRefresh *cand = (CandidateRefresh *) pointer;
1876
1877   priv_turn_allocate_refresh_tick_unlocked (agent, cand);
1878
1879   return G_SOURCE_REMOVE;
1880 }
1881
1882
1883 /*
1884  * Initiates the next pending connectivity check.
1885  */
1886 void conn_check_schedule_next (NiceAgent *agent)
1887 {
1888   if (agent->discovery_unsched_items > 0)
1889     nice_debug ("Agent %p : WARN: starting conn checks before local candidate gathering is finished.", agent);
1890
1891   /* step: schedule timer if not running yet */
1892   if (agent->conncheck_timer_source == NULL) {
1893     agent_timeout_add_with_context (agent, &agent->conncheck_timer_source,
1894         "Connectivity check schedule", agent->timer_ta,
1895         priv_conn_check_tick_agent_locked, NULL);
1896   }
1897
1898   /* step: also start the keepalive timer */
1899   if (agent->keepalive_timer_source == NULL) {
1900     agent_timeout_add_with_context (agent, &agent->keepalive_timer_source,
1901         "Connectivity keepalive timeout", agent->timer_ta,
1902         priv_conn_keepalive_tick_agent_locked, NULL);
1903   }
1904 }
1905
1906 /*
1907  * Compares two connectivity check items. Checkpairs are sorted
1908  * in descending priority order, with highest priority item at
1909  * the start of the list.
1910  */
1911 gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b)
1912 {
1913   if (a->priority > b->priority)
1914     return -1;
1915   else if (a->priority < b->priority)
1916     return 1;
1917   return 0;
1918 }
1919
1920 /* Find a transport compatible with a given socket.
1921  *
1922  * Returns TRUE when a matching transport can be guessed from
1923  * the type of the socket in an unambiguous way.
1924  */
1925 static gboolean
1926 nice_socket_has_compatible_transport (NiceSocket *socket,
1927     NiceCandidateTransport *transport)
1928 {
1929   gboolean found = TRUE;
1930
1931   g_assert (socket);
1932   g_assert (transport);
1933
1934   switch (socket->type) {
1935     case NICE_SOCKET_TYPE_TCP_BSD:
1936       if (nice_tcp_bsd_socket_get_passive_parent (socket))
1937         *transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
1938       else
1939         *transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
1940       break;
1941     case NICE_SOCKET_TYPE_TCP_PASSIVE:
1942       *transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
1943       break;
1944     case NICE_SOCKET_TYPE_TCP_ACTIVE:
1945       *transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
1946       break;
1947     case NICE_SOCKET_TYPE_UDP_BSD:
1948       *transport = NICE_CANDIDATE_TRANSPORT_UDP;
1949       break;
1950     default:
1951       found = FALSE;
1952   }
1953
1954   return found;
1955 }
1956
1957 /* Test if a local socket and a local candidate are compatible. This
1958  * function does supplementary tests when the address and port are not
1959  * sufficient to give a unique candidate. We try to avoid comparing
1960  * directly the sockptr value, when possible, to rely on objective
1961  * properties of the candidate and the socket instead, and we also
1962  * choose to ignore the conncheck list for the same reason.
1963  */
1964 static gboolean
1965 local_candidate_and_socket_compatible (NiceAgent *agent,
1966     NiceCandidate *lcand, NiceSocket *socket)
1967 {
1968   gboolean ret = TRUE;
1969   NiceCandidateTransport transport;
1970
1971   g_assert (socket);
1972   g_assert (lcand);
1973
1974   if (nice_socket_has_compatible_transport (socket, &transport)) {
1975     ret = (lcand->transport == transport);
1976     /* tcp-active discovered peer-reflexive local candidate, where
1977      * socket is the tcp connect related socket */
1978     if (ret && transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE &&
1979         nice_address_get_port (&lcand->addr) > 0)
1980       ret = (lcand->sockptr == socket);
1981   } else if (socket->type == NICE_SOCKET_TYPE_UDP_TURN)
1982     /* Socket of type udp-turn will match a unique local candidate
1983      * by its sockptr value. An an udp-turn socket doesn't carry enough
1984      * information when base socket is udp-turn-over-tcp to disambiguate
1985      * between a tcp-act and a tcp-pass local candidate.
1986      */
1987     ret = (lcand->sockptr == socket);
1988
1989   return ret;
1990 }
1991
1992 /* Test if a local socket and a remote candidate are compatible.
1993  * This function is very close to its local candidate counterpart,
1994  * the difference is that we also use information from the local
1995  * candidate we may have identified previously. This is needed
1996  * to disambiguate the transport of the candidate with a socket
1997  * of type udp-turn.
1998  *
1999  */
2000 static gboolean
2001 remote_candidate_and_socket_compatible (NiceAgent *agent,
2002     NiceCandidate *lcand, NiceCandidate *rcand, NiceSocket *socket)
2003 {
2004   gboolean ret = TRUE;
2005   NiceCandidateTransport transport;
2006
2007   g_assert (socket);
2008   g_assert (rcand);
2009
2010   if (nice_socket_has_compatible_transport (socket, &transport))
2011     ret = (conn_check_match_transport (rcand->transport) == transport);
2012
2013   /* This supplementary test with the local candidate is needed with
2014    * socket of type udp-turn, the type doesn't allow to disambiguate
2015    * between a tcp-pass and a tcp-act remote candidate
2016    */
2017   if (lcand && ret)
2018     ret = (conn_check_match_transport (lcand->transport) == rcand->transport);
2019
2020   return ret;
2021 }
2022
2023 void
2024 conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream,
2025     NiceComponent *component)
2026 {
2027   GList *i;
2028   GSList *j;
2029   NiceCandidate *lcand = NULL, *rcand = NULL;
2030
2031   nice_debug ("Agent %p : conn_check_remote_candidates_set %u %u",
2032     agent, stream->id, component->id);
2033
2034   if (stream->remote_ufrag[0] == 0)
2035     return;
2036
2037   if (component->incoming_checks.head)
2038     nice_debug ("Agent %p : credentials have been set, "
2039       "we can process incoming checks", agent);
2040
2041   for (i = component->incoming_checks.head; i;) {
2042     IncomingCheck *icheck = i->data;
2043     GList *i_next = i->next;
2044
2045     nice_debug ("Agent %p : replaying icheck=%p (sock=%p)",
2046         agent, icheck, icheck->local_socket);
2047
2048     /* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to
2049      * be handled separately */
2050     for (j = component->local_candidates; j; j = j->next) {
2051       NiceCandidate *cand = j->data;
2052       NiceAddress *addr;
2053
2054       if (cand->type == NICE_CANDIDATE_TYPE_RELAYED)
2055         addr = &cand->addr;
2056       else
2057         addr = &cand->base_addr;
2058
2059       if (nice_address_equal (&icheck->local_socket->addr, addr) &&
2060           local_candidate_and_socket_compatible (agent, cand,
2061           icheck->local_socket)) {
2062         lcand = cand;
2063         break;
2064       }
2065     }
2066
2067     g_assert (lcand != NULL);
2068
2069     for (j = component->remote_candidates; j; j = j->next) {
2070       NiceCandidate *cand = j->data;
2071       if (nice_address_equal (&cand->addr, &icheck->from) &&
2072           remote_candidate_and_socket_compatible (agent, lcand, cand,
2073           icheck->local_socket)) {
2074         rcand = cand;
2075         break;
2076       }
2077     }
2078
2079     if (lcand->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
2080       CandidateCheckPair *pair = NULL;
2081
2082       for (j = stream->conncheck_list; j; j = j->next) {
2083         CandidateCheckPair *p = j->data;
2084         if (lcand == p->local && rcand == p->remote) {
2085           pair = p;
2086           break;
2087         }
2088       }
2089       if (pair == NULL) {
2090         pair = priv_conn_check_add_for_candidate_pair_matched (agent,
2091             stream->id, component, lcand, rcand, NICE_CHECK_SUCCEEDED);
2092         if (pair)
2093           pair->valid = TRUE;
2094       }
2095     }
2096
2097     priv_schedule_triggered_check (agent, stream, component,
2098         icheck->local_socket, rcand);
2099     if (icheck->use_candidate)
2100       priv_mark_pair_nominated (agent, stream, component, lcand, rcand);
2101
2102     if (icheck->username)
2103       g_free (icheck->username);
2104     g_slice_free (IncomingCheck, icheck);
2105     g_queue_delete_link (&component->incoming_checks, i);
2106     i = i_next;
2107   }
2108 }
2109
2110 /*
2111  * Handle any processing steps for connectivity checks after
2112  * remote credentials have been set. This function handles
2113  * the special case where answerer has sent us connectivity
2114  * checks before the answer (containing credentials information),
2115  * reaches us. The special case is documented in RFC 5245 sect 7.2.
2116  * ).
2117  */
2118 void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream)
2119 {
2120   GSList *j;
2121
2122   for (j = stream->components; j ; j = j->next) {
2123     NiceComponent *component = j->data;
2124
2125     conn_check_remote_candidates_set(agent, stream, component);
2126   }
2127 }
2128
2129 /*
2130  * Enforces the upper limit for connectivity checks by dropping
2131  * lower-priority pairs as described RFC 8445 section 6.1.2.5. See also
2132  * conn_check_add_for_candidate().
2133  * Returns TRUE if the pair in argument is one of the deleted pairs.
2134  */
2135 static gboolean priv_limit_conn_check_list_size (NiceAgent *agent,
2136     NiceStream *stream, CandidateCheckPair *pair)
2137 {
2138   guint valid = 0;
2139   guint cancelled = 0;
2140   gboolean deleted = FALSE;
2141   GSList *item = stream->conncheck_list;
2142
2143   while (item) {
2144     CandidateCheckPair *p = item->data;
2145     GSList *next = item->next;
2146
2147     valid++;
2148     /* We remove lower-priority pairs, but only the ones that can be
2149      * safely discarded without breaking an ongoing conncheck process.
2150      * This only includes pairs that are in the frozen state (those
2151      * initially added when remote candidates are received) or in failed
2152      * state. Pairs in any other state play a role in the conncheck, and
2153      * there removal may lead to a failing conncheck that would succeed
2154      * otherwise.
2155      *
2156      * We also remove failed pairs from the list unconditionally.
2157      */
2158     if ((valid > agent->max_conn_checks && p->state == NICE_CHECK_FROZEN) ||
2159         p->state == NICE_CHECK_FAILED) {
2160       if (p == pair)
2161         deleted = TRUE;
2162       nice_debug ("Agent %p : pair %p removed.", agent, p);
2163       candidate_check_pair_free (agent, p);
2164       stream->conncheck_list = g_slist_delete_link (stream->conncheck_list,
2165           item);
2166       cancelled++;
2167     }
2168     item = next;
2169   }
2170
2171   if (cancelled > 0)
2172     nice_debug ("Agent %p : Pruned %d pairs. "
2173         "Conncheck list has %d elements left. "
2174         "Maximum connchecks allowed : %d", agent, cancelled,
2175         valid - cancelled, agent->max_conn_checks);
2176
2177   return deleted;
2178 }
2179
2180 /*
2181  * Changes the selected pair for the component if 'pair'
2182  * has higher priority than the currently selected pair. See
2183  * RFC 8445 sect 8.1.1. "Nominating Pairs"
2184  */
2185 void
2186 conn_check_update_selected_pair (NiceAgent *agent, NiceComponent *component,
2187     CandidateCheckPair *pair)
2188 {
2189   CandidatePair cpair = { 0, };
2190
2191   g_assert (component);
2192   g_assert (pair);
2193   /* pair is expected to have the nominated flag */
2194   g_assert (pair->nominated);
2195   if (pair->priority > component->selected_pair.priority) {
2196     gchar priority[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
2197     nice_candidate_pair_priority_to_string (pair->priority, priority);
2198     nice_debug ("Agent %p : changing SELECTED PAIR for component %u: %s:%s "
2199         "(prio:%s).", agent, component->id,
2200         pair->local->foundation, pair->remote->foundation, priority);
2201
2202     cpair.local = pair->local;
2203     cpair.remote = pair->remote;
2204     cpair.priority = pair->priority;
2205     cpair.stun_priority = pair->stun_priority;
2206
2207     nice_component_update_selected_pair (agent, component, &cpair);
2208
2209     priv_conn_keepalive_tick_unlocked (agent);
2210
2211     agent_signal_new_selected_pair (agent, pair->stream_id, component->id,
2212         pair->local, pair->remote);
2213   }
2214 }
2215
2216 /*
2217  * Updates the check list state.
2218  *
2219  * Implements parts of the algorithm described in 
2220  * ICE sect 8.1.2. "Updating States" (RFC 5245): if for any
2221  * component, all checks have been completed and have
2222  * failed to produce a nominated pair, mark that component's
2223  * state to NICE_CHECK_FAILED.
2224  *
2225  * Sends a component state changesignal via 'agent'.
2226  */
2227 static void priv_update_check_list_failed_components (NiceAgent *agent, NiceStream *stream)
2228 {
2229   GSList *i;
2230   gboolean completed;
2231   guint nominated;
2232   /* note: emitting a signal might cause the client 
2233    *       to remove the stream, thus the component count
2234    *       must be fetched before entering the loop*/
2235   guint c, components = stream->n_components;
2236
2237   if (stream->conncheck_list == NULL)
2238     return;
2239
2240   for (i = agent->discovery_list; i; i = i->next) {
2241     CandidateDiscovery *d = i->data;
2242
2243     /* There is still discovery ogoing for this stream,
2244      * so don't fail any of it's candidates.
2245      */
2246     if (d->stream_id == stream->id && !d->done)
2247       return;
2248   }
2249   if (agent->discovery_list != NULL)
2250     return;
2251
2252   /* note: iterate the conncheck list for each component separately */
2253   for (c = 0; c < components; c++) {
2254     NiceComponent *component = NULL;
2255     if (!agent_find_component (agent, stream->id, c+1, NULL, &component))
2256       continue;
2257
2258     nominated = 0;
2259     completed = TRUE;
2260     for (i = stream->conncheck_list; i; i = i->next) {
2261       CandidateCheckPair *p = i->data;
2262
2263       g_assert_cmpuint (p->stream_id, ==, stream->id);
2264
2265       if (p->component_id == (c + 1)) {
2266         if (p->nominated)
2267           ++nominated;
2268         if (p->state != NICE_CHECK_FAILED &&
2269             p->state != NICE_CHECK_SUCCEEDED &&
2270             p->state != NICE_CHECK_DISCOVERED)
2271           completed = FALSE;
2272       }
2273     }
2274  
2275     /* note: all pairs are either failed or succeeded, and the component
2276      * has not produced a nominated pair.
2277      * Set the component to FAILED only if it actually had remote candidates
2278      * that failed.. */
2279     if (completed && nominated == 0 &&
2280         component != NULL && component->remote_candidates != NULL)
2281       agent_signal_component_state_change (agent,
2282                                            stream->id,
2283                                            (c + 1), /* component-id */
2284                                            NICE_COMPONENT_STATE_FAILED);
2285   }
2286 }
2287
2288 /*
2289  * Updates the check list state for a stream component.
2290  *
2291  * Implements the algorithm described in ICE sect 8.1.2 
2292  * "Updating States" (ID-19) as it applies to checks of 
2293  * a certain component. If there are any nominated pairs, 
2294  * ICE processing may be concluded, and component state is 
2295  * changed to READY.
2296  *
2297  * Sends a component state changesignal via 'agent'.
2298  */
2299 void conn_check_update_check_list_state_for_ready (NiceAgent *agent,
2300     NiceStream *stream, NiceComponent *component)
2301 {
2302   GSList *i;
2303   guint valid = 0, nominated = 0;
2304
2305   g_assert (component);
2306
2307   /* step: search for at least one nominated pair */
2308   for (i = stream->conncheck_list; i; i = i->next) {
2309     CandidateCheckPair *p = i->data;
2310     if (p->component_id == component->id) {
2311       if (p->valid) {
2312         ++valid;
2313         if (p->nominated == TRUE) {
2314           ++nominated;
2315         }
2316       }
2317     }
2318   }
2319
2320   if (nominated > 0) {
2321     /* Only go to READY if no checks are left in progress. If there are
2322      * any that are kept, then this function will be called again when the
2323      * conncheck tick timer finishes them all */
2324     if (priv_prune_pending_checks (agent, stream, component) == 0) {
2325       /* Continue through the states to give client code a nice
2326        * logical progression. See http://phabricator.freedesktop.org/D218 for
2327        * discussion. */
2328       if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
2329           component->state == NICE_COMPONENT_STATE_FAILED)
2330         agent_signal_component_state_change (agent, stream->id, component->id,
2331             NICE_COMPONENT_STATE_CONNECTING);
2332       if (component->state < NICE_COMPONENT_STATE_CONNECTED)
2333         agent_signal_component_state_change (agent, stream->id, component->id,
2334             NICE_COMPONENT_STATE_CONNECTED);
2335       agent_signal_component_state_change (agent, stream->id,
2336           component->id, NICE_COMPONENT_STATE_READY);
2337     }
2338   }
2339   nice_debug ("Agent %p : conn.check list status: %u nominated, %u valid, c-id %u.", agent, nominated, valid, component->id);
2340 }
2341
2342 /*
2343  * The remote party has signalled that the candidate pair
2344  * described by 'component' and 'remotecand' is nominated
2345  * for use.
2346  */
2347 static void priv_mark_pair_nominated (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceCandidate *localcand, NiceCandidate *remotecand)
2348 {
2349   GSList *i;
2350
2351   g_assert (component);
2352
2353   if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
2354       agent->controlling_mode)
2355     return;
2356
2357   /* step: search for at least one nominated pair */
2358   for (i = stream->conncheck_list; i; i = i->next) {
2359     CandidateCheckPair *pair = i->data;
2360     if (pair->local == localcand && pair->remote == remotecand) {
2361       /* ICE, 7.2.1.5. Updating the Nominated Flag */
2362       /* note: TCP candidates typically produce peer reflexive
2363        * candidate, generating a "discovered" pair that can be
2364        * nominated.
2365        */
2366       if (pair->state == NICE_CHECK_SUCCEEDED &&
2367           pair->discovered_pair != NULL) {
2368         pair = pair->discovered_pair;
2369         g_assert_cmpint (pair->state, ==, NICE_CHECK_DISCOVERED);
2370       }
2371
2372       /* If the state of this pair is In-Progress, [...] the resulting
2373        * valid pair has its nominated flag set when the response
2374        * arrives.
2375        */
2376       if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
2377           pair->state == NICE_CHECK_IN_PROGRESS) {
2378         pair->mark_nominated_on_response_arrival = TRUE;
2379         nice_debug ("Agent %p : pair %p (%s) is in-progress, "
2380             "will be nominated on response receipt.",
2381             agent, pair, pair->foundation);
2382       }
2383
2384       if (pair->valid ||
2385           !NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
2386         nice_debug ("Agent %p : marking pair %p (%s) as nominated",
2387             agent, pair, pair->foundation);
2388         pair->nominated = TRUE;
2389       }
2390
2391       if (pair->valid) {
2392         /* Do not step down to CONNECTED if we're already at state READY*/
2393         if (component->state == NICE_COMPONENT_STATE_FAILED)
2394           agent_signal_component_state_change (agent,
2395               stream->id, component->id, NICE_COMPONENT_STATE_CONNECTING);
2396         conn_check_update_selected_pair (agent, component, pair);
2397         if (component->state == NICE_COMPONENT_STATE_CONNECTING)
2398           /* step: notify the client of a new component state (must be done
2399            *       before the possible check list state update step */
2400           agent_signal_component_state_change (agent,
2401               stream->id, component->id, NICE_COMPONENT_STATE_CONNECTED);
2402       }
2403
2404       if (pair->nominated)
2405         conn_check_update_check_list_state_for_ready (agent, stream, component);
2406     }
2407   }
2408 }
2409
2410 /*
2411  * Creates a new connectivity check pair and adds it to
2412  * the agent's list of checks.
2413  */
2414 static CandidateCheckPair *priv_add_new_check_pair (NiceAgent *agent,
2415     guint stream_id, NiceComponent *component, NiceCandidate *local,
2416     NiceCandidate *remote, NiceCheckState initial_state)
2417 {
2418   NiceStream *stream;
2419   CandidateCheckPair *pair;
2420   guint64 priority;
2421
2422   g_assert (local != NULL);
2423   g_assert (remote != NULL);
2424
2425   priority = agent_candidate_pair_priority (agent, local, remote);
2426
2427   if (component->selected_pair.priority &&
2428       priority < component->selected_pair.priority) {
2429     gchar prio1[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
2430     gchar prio2[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
2431
2432     nice_candidate_pair_priority_to_string (priority, prio1);
2433     nice_candidate_pair_priority_to_string (component->selected_pair.priority,
2434         prio2);
2435     nice_debug ("Agent %p : do not create a pair that would have a priority "
2436         "%s lower than selected pair priority %s.", agent, prio1, prio2);
2437     return NULL;
2438   }
2439
2440   stream = agent_find_stream (agent, stream_id);
2441   pair = g_slice_new0 (CandidateCheckPair);
2442
2443   pair->stream_id = stream_id;
2444   pair->component_id = component->id;;
2445   pair->local = local;
2446   pair->remote = remote;
2447   /* note: we use the remote sockptr only in the case
2448    * of TCP transport
2449    */
2450   if (local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
2451       remote->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
2452     pair->sockptr = (NiceSocket *) remote->sockptr;
2453   else
2454     pair->sockptr = (NiceSocket *) local->sockptr;
2455   g_snprintf (pair->foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s", local->foundation, remote->foundation);
2456
2457   pair->priority = agent_candidate_pair_priority (agent, local, remote);
2458   nice_debug ("Agent %p : creating a new pair", agent);
2459   SET_PAIR_STATE (agent, pair, initial_state);
2460   {
2461       gchar tmpbuf1[INET6_ADDRSTRLEN];
2462       gchar tmpbuf2[INET6_ADDRSTRLEN];
2463       nice_address_to_string (&pair->local->addr, tmpbuf1);
2464       nice_address_to_string (&pair->remote->addr, tmpbuf2);
2465       nice_debug ("Agent %p : new pair %p : [%s]:%u --> [%s]:%u", agent, pair,
2466           tmpbuf1, nice_address_get_port (&pair->local->addr),
2467           tmpbuf2, nice_address_get_port (&pair->remote->addr));
2468   }
2469   pair->stun_priority = stun_request_priority (agent, local);
2470
2471   stream->conncheck_list = g_slist_insert_sorted (stream->conncheck_list, pair,
2472       (GCompareFunc)conn_check_compare);
2473
2474   nice_debug ("Agent %p : added a new pair %p with foundation '%s' and "
2475       "transport %s:%s to stream %u component %u",
2476       agent, pair, pair->foundation,
2477       priv_candidate_transport_to_string (pair->local->transport),
2478       priv_candidate_transport_to_string (pair->remote->transport),
2479       stream_id, component->id);
2480
2481   /* If this is the first pair added into the check list and the first stream's
2482    * components already have valid pairs, unfreeze the pair as it would happen
2483    * in priv_conn_check_unfreeze_related() were the list not empty. */
2484   if (stream != agent->streams->data &&
2485       g_slist_length (stream->conncheck_list) == 1 &&
2486       priv_all_components_have_valid_pair (agent->streams->data)) {
2487     nice_debug ("Agent %p : %p is the first pair in this stream's check list "
2488         "and the first stream already has valid pairs. Unfreezing immediately.",
2489         agent, pair);
2490     priv_conn_check_unfreeze_next (agent, stream);
2491   }
2492
2493   /* implement the hard upper limit for number of
2494      checks (see sect 5.7.3 ICE ID-19): */
2495   if (agent->compatibility == NICE_COMPATIBILITY_RFC5245) {
2496     if (priv_limit_conn_check_list_size (agent, stream, pair))
2497       return NULL;
2498   }
2499
2500   return pair;
2501 }
2502
2503 NiceCandidateTransport
2504 conn_check_match_transport (NiceCandidateTransport transport)
2505 {
2506   switch (transport) {
2507     case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
2508       return NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
2509       break;
2510     case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
2511       return NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
2512       break;
2513     case NICE_CANDIDATE_TRANSPORT_TCP_SO:
2514     case NICE_CANDIDATE_TRANSPORT_UDP:
2515     default:
2516       return transport;
2517       break;
2518   }
2519 }
2520
2521 static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched (
2522     NiceAgent *agent, guint stream_id, NiceComponent *component,
2523      NiceCandidate *local, NiceCandidate *remote, NiceCheckState initial_state)
2524 {
2525   CandidateCheckPair *pair;
2526
2527   pair = priv_add_new_check_pair (agent, stream_id, component, local, remote,
2528       initial_state);
2529   if (component->state == NICE_COMPONENT_STATE_CONNECTED ||
2530       component->state == NICE_COMPONENT_STATE_READY) {
2531     agent_signal_component_state_change (agent,
2532         stream_id,
2533         component->id,
2534         NICE_COMPONENT_STATE_CONNECTED);
2535   } else {
2536     agent_signal_component_state_change (agent,
2537         stream_id,
2538         component->id,
2539         NICE_COMPONENT_STATE_CONNECTING);
2540   }
2541
2542   return pair;
2543 }
2544
2545 gboolean conn_check_add_for_candidate_pair (NiceAgent *agent,
2546     guint stream_id, NiceComponent *component, NiceCandidate *local,
2547     NiceCandidate *remote)
2548 {
2549   gboolean ret = FALSE;
2550
2551   g_assert (local != NULL);
2552   g_assert (remote != NULL);
2553
2554   /* note: do not create pairs where the local candidate is a srv-reflexive
2555    * or peer-reflexive (ICE 6.1.2.4. "Pruning the pairs" RFC 8445)
2556    */
2557   if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
2558       agent->compatibility == NICE_COMPATIBILITY_WLM2009 ||
2559       agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
2560       (local->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
2561       local->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)) {
2562     return FALSE;
2563   }
2564
2565   /* note: do not create pairs where local candidate has TCP passive transport
2566    *       (ice-tcp-13 6.2. "Forming the Check Lists") */
2567   if (local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
2568     return FALSE;
2569   }
2570
2571   /* note: match pairs only if transport and address family are the same */
2572   if (local->transport == conn_check_match_transport (remote->transport) &&
2573      local->addr.s.addr.sa_family == remote->addr.s.addr.sa_family) {
2574     priv_conn_check_add_for_candidate_pair_matched (agent, stream_id, component,
2575         local, remote, NICE_CHECK_FROZEN);
2576     ret = TRUE;
2577   }
2578
2579   return ret;
2580 }
2581
2582 /*
2583  * Forms new candidate pairs by matching the new remote candidate
2584  * 'remote_cand' with all existing local candidates of 'component'.
2585  * Implements the logic described in ICE sect 5.7.1. "Forming Candidate
2586  * Pairs" (ID-19).
2587  *
2588  * @param agent context
2589  * @param component pointer to the component
2590  * @param remote remote candidate to match with
2591  *
2592  * @return number of checks added, negative on fatal errors
2593  */
2594 int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *remote)
2595 {
2596   GSList *i;
2597   int added = 0;
2598   int ret = 0;
2599
2600   g_assert (remote != NULL);
2601
2602   /* note: according to 7.2.1.3, "Learning Peer Reflexive Candidates",
2603    * the agent does not pair this candidate with any local candidates.
2604    */
2605   if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
2606       remote->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
2607   {
2608     return added;
2609   }
2610
2611   for (i = component->local_candidates; i ; i = i->next) {
2612     NiceCandidate *local = i->data;
2613
2614     if (agent->force_relay && local->type != NICE_CANDIDATE_TYPE_RELAYED)
2615         continue;
2616
2617     ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote);
2618
2619     if (ret) {
2620       ++added;
2621     }
2622   }
2623
2624   return added;
2625 }
2626
2627 /*
2628  * Forms new candidate pairs by matching the new local candidate
2629  * 'local_cand' with all existing remote candidates of 'component'.
2630  *
2631  * @param agent context
2632  * @param component pointer to the component
2633  * @param local local candidate to match with
2634  *
2635  * @return number of checks added, negative on fatal errors
2636  */
2637 int conn_check_add_for_local_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local)
2638 {
2639   GSList *i;
2640   int added = 0;
2641   int ret = 0;
2642
2643   g_assert (local != NULL);
2644
2645   /*
2646    * note: according to 7.1.3.2.1 "Discovering Peer Reflexive
2647    * Candidates", the peer reflexive candidate is not paired
2648    * with other remote candidates
2649    */
2650
2651   if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
2652       local->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
2653   {
2654     return added;
2655   }
2656
2657   for (i = component->remote_candidates; i ; i = i->next) {
2658
2659     NiceCandidate *remote = i->data;
2660     ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote);
2661
2662     if (ret) {
2663       ++added;
2664     }
2665   }
2666
2667   return added;
2668 }
2669
2670 /*
2671  * Frees the CandidateCheckPair structure pointer to 
2672  * by 'user data'. Compatible with GDestroyNotify.
2673  */
2674 static void candidate_check_pair_free (NiceAgent *agent,
2675     CandidateCheckPair *pair)
2676 {
2677   priv_remove_pair_from_triggered_check_queue (agent, pair);
2678   priv_free_all_stun_transactions (pair, NULL);
2679   g_slice_free (CandidateCheckPair, pair);
2680 }
2681
2682 /*
2683  * Frees all resources of all connectivity checks.
2684  */
2685 void conn_check_free (NiceAgent *agent)
2686 {
2687   GSList *i;
2688   for (i = agent->streams; i; i = i->next) {
2689     NiceStream *stream = i->data;
2690
2691     if (stream->conncheck_list) {
2692       GSList *item;
2693
2694       nice_debug ("Agent %p, freeing conncheck_list of stream %p", agent,
2695           stream);
2696       for (item = stream->conncheck_list; item; item = item->next)
2697         candidate_check_pair_free (agent, item->data);
2698       g_slist_free (stream->conncheck_list);
2699       stream->conncheck_list = NULL;
2700     }
2701   }
2702
2703   conn_check_stop (agent);
2704 }
2705
2706 /*
2707  * Prunes the list of connectivity checks for items related
2708  * to stream 'stream_id'. 
2709  *
2710  * @return TRUE on success, FALSE on a fatal error
2711  */
2712 void conn_check_prune_stream (NiceAgent *agent, NiceStream *stream)
2713 {
2714   GSList *i;
2715   gboolean keep_going = FALSE;
2716
2717   if (stream->conncheck_list) {
2718     GSList *item;
2719
2720     nice_debug ("Agent %p, freeing conncheck_list of stream %p", agent, stream);
2721
2722     for (item = stream->conncheck_list; item; item = item->next)
2723       candidate_check_pair_free (agent, item->data);
2724     g_slist_free (stream->conncheck_list);
2725     stream->conncheck_list = NULL;
2726   }
2727
2728   for (i = agent->streams; i; i = i->next) {
2729     NiceStream *s = i->data;
2730     if (s->conncheck_list) {
2731       keep_going = TRUE;
2732       break;
2733     }
2734   }
2735
2736   if (!keep_going)
2737     conn_check_stop (agent);
2738 }
2739
2740 /*
2741  * Fills 'dest' with a username string for use in an outbound connectivity
2742  * checks. No more than 'dest_len' characters (including terminating
2743  * NULL) is ever written to the 'dest'.
2744  */
2745 static
2746 size_t priv_gen_username (NiceAgent *agent, guint component_id,
2747     gchar *remote, gchar *local, uint8_t *dest, guint dest_len)
2748 {
2749   guint len = 0;
2750   gsize remote_len = strlen (remote);
2751   gsize local_len = strlen (local);
2752
2753   if (remote_len > 0 && local_len > 0) {
2754     if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
2755         dest_len >= remote_len + local_len + 1) {
2756       memcpy (dest, remote, remote_len);
2757       len += remote_len;
2758       memcpy (dest + len, ":", 1);
2759       len++;
2760       memcpy (dest + len, local, local_len);
2761       len += local_len;
2762     } else if ((agent->compatibility == NICE_COMPATIBILITY_WLM2009 ||
2763         agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
2764         dest_len >= remote_len + local_len + 4 ) {
2765       memcpy (dest, remote, remote_len);
2766       len += remote_len;
2767       memcpy (dest + len, ":", 1);
2768       len++;
2769       memcpy (dest + len, local, local_len);
2770       len += local_len;
2771       if (len % 4 != 0) {
2772         memset (dest + len, 0, 4 - (len % 4));
2773         len += 4 - (len % 4);
2774       }
2775     } else if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE &&
2776         dest_len >= remote_len + local_len) {
2777       memcpy (dest, remote, remote_len);
2778       len += remote_len;
2779       memcpy (dest + len, local, local_len);
2780       len += local_len;
2781     } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
2782                agent->compatibility == NICE_COMPATIBILITY_OC2007) {
2783       gchar component_str[10];
2784       guchar *local_decoded = NULL;
2785       guchar *remote_decoded = NULL;
2786       gsize local_decoded_len;
2787       gsize remote_decoded_len;
2788       gsize total_len;
2789       int padding;
2790
2791       g_snprintf (component_str, sizeof(component_str), "%d", component_id);
2792       local_decoded = g_base64_decode (local, &local_decoded_len);
2793       remote_decoded = g_base64_decode (remote, &remote_decoded_len);
2794
2795       total_len = remote_decoded_len + local_decoded_len + 3 + 2*strlen (component_str);
2796       padding = 4 - (total_len % 4);
2797
2798       if (dest_len >= total_len + padding) {
2799         guchar pad_char[1] = {0};
2800         int i;
2801
2802         memcpy (dest, remote_decoded, remote_decoded_len);
2803         len += remote_decoded_len;
2804         memcpy (dest + len, ":", 1);
2805         len++;
2806         memcpy (dest + len, component_str, strlen (component_str));
2807         len += strlen (component_str);
2808
2809         memcpy (dest + len, ":", 1);
2810         len++;
2811
2812         memcpy (dest + len, local_decoded, local_decoded_len);
2813         len += local_decoded_len;
2814         memcpy (dest + len, ":", 1);
2815         len++;
2816         memcpy (dest + len, component_str, strlen (component_str));;
2817         len += strlen (component_str);
2818
2819         for (i = 0; i < padding; i++) {
2820           memcpy (dest + len, pad_char, 1);
2821           len++;
2822         }
2823
2824       }
2825
2826       g_free (local_decoded);
2827       g_free (remote_decoded);
2828     }
2829   }
2830
2831   return len;
2832 }
2833
2834 /*
2835  * Fills 'dest' with a username string for use in an outbound connectivity
2836  * checks. No more than 'dest_len' characters (including terminating
2837  * NULL) is ever written to the 'dest'.
2838  */
2839 static
2840 size_t priv_create_username (NiceAgent *agent, NiceStream *stream,
2841     guint component_id, NiceCandidate *remote, NiceCandidate *local,
2842     uint8_t *dest, guint dest_len, gboolean inbound)
2843 {
2844   gchar *local_username = NULL;
2845   gchar *remote_username = NULL;
2846
2847
2848   if (remote && remote->username) {
2849     remote_username = remote->username;
2850   }
2851
2852   if (local && local->username) {
2853     local_username = local->username;
2854   }
2855
2856   if (stream) {
2857     if (remote_username == NULL) {
2858       remote_username = stream->remote_ufrag;
2859     }
2860     if (local_username == NULL) {
2861       local_username = stream->local_ufrag;
2862     }
2863   }
2864
2865   if (local_username && remote_username) {
2866     if (inbound) {
2867       return priv_gen_username (agent, component_id,
2868           local_username, remote_username, dest, dest_len);
2869     } else {
2870       return priv_gen_username (agent, component_id,
2871           remote_username, local_username, dest, dest_len);
2872     }
2873   }
2874
2875   return 0;
2876 }
2877
2878 /*
2879  * Returns a password string for use in an outbound connectivity
2880  * check.
2881  */
2882 static
2883 size_t priv_get_password (NiceAgent *agent, NiceStream *stream,
2884     NiceCandidate *remote, uint8_t **password)
2885 {
2886   if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
2887     return 0;
2888
2889   if (remote && remote->password) {
2890     *password = (uint8_t *)remote->password;
2891     return strlen (remote->password);
2892   }
2893
2894   if (stream) {
2895     *password = (uint8_t *)stream->remote_password;
2896     return strlen (stream->remote_password);
2897   }
2898
2899   return 0;
2900 }
2901
2902 /* Implement the computation specific in RFC 5245 section 16 */
2903
2904 static unsigned int priv_compute_conncheck_timer (NiceAgent *agent, NiceStream *stream)
2905 {
2906   GSList *i;
2907   guint waiting_and_in_progress = 0;
2908   guint n = 0;
2909   unsigned int rto = 0;
2910
2911   for (i = stream->conncheck_list; i ; i = i->next) {
2912     CandidateCheckPair *p = i->data;
2913     if (p->state == NICE_CHECK_IN_PROGRESS ||
2914         p->state == NICE_CHECK_WAITING)
2915       waiting_and_in_progress++;
2916   }
2917
2918   n = priv_number_of_active_check_lists (agent);
2919   rto = agent->timer_ta  * n * waiting_and_in_progress;
2920
2921   /* We assume non-reliable streams are RTP, so we use 100 as the max */
2922   nice_debug ("Agent %p : timer set to %dms, "
2923     "waiting+in_progress=%d, nb_active=%d",
2924     agent, agent->reliable ? MAX (rto, 500) : MAX (rto, 100),
2925     waiting_and_in_progress, n);
2926   if (agent->reliable)
2927     return MAX (rto, 500);
2928   else
2929     return MAX (rto, 100);
2930 }
2931
2932 /*
2933  * Sends a connectivity check over candidate pair 'pair'.
2934  *
2935  * @return zero on success, non-zero on error
2936  */
2937 int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair)
2938 {
2939
2940   /* note: following information is supplied:
2941    *  - username (for USERNAME attribute)
2942    *  - password (for MESSAGE-INTEGRITY)
2943    *  - priority (for PRIORITY)
2944    *  - ICE-CONTROLLED/ICE-CONTROLLING (for role conflicts)
2945    *  - USE-CANDIDATE (if sent by the controlling agent)
2946    */
2947
2948   uint8_t uname[NICE_STREAM_MAX_UNAME];
2949   NiceStream *stream;
2950   NiceComponent *component;
2951   gsize uname_len;
2952   uint8_t *password = NULL;
2953   gsize password_len;
2954   bool controlling = agent->controlling_mode;
2955  /* XXX: add API to support different nomination modes: */
2956   bool cand_use = controlling;
2957   size_t buffer_len;
2958   unsigned int timeout;
2959   StunTransaction *stun;
2960
2961   if (!agent_find_component (agent, pair->stream_id, pair->component_id,
2962           &stream, &component))
2963     return -1;
2964
2965   uname_len = priv_create_username (agent, stream, pair->component_id,
2966       pair->remote, pair->local, uname, sizeof (uname), FALSE);
2967   password_len = priv_get_password (agent, stream, pair->remote, &password);
2968
2969   if (password != NULL &&
2970       (agent->compatibility == NICE_COMPATIBILITY_MSN ||
2971        agent->compatibility == NICE_COMPATIBILITY_OC2007)) {
2972     password = g_base64_decode ((gchar *) password, &password_len);
2973   }
2974
2975   if (nice_debug_is_enabled ()) {
2976     gchar tmpbuf1[INET6_ADDRSTRLEN];
2977     gchar tmpbuf2[INET6_ADDRSTRLEN];
2978     nice_address_to_string (&pair->local->addr, tmpbuf1);
2979     nice_address_to_string (&pair->remote->addr, tmpbuf2);
2980     nice_debug ("Agent %p : STUN-CC REQ [%s]:%u --> [%s]:%u, socket=%u, "
2981         "pair=%p (c-id:%u), tie=%llu, username='%.*s' (%" G_GSIZE_FORMAT "), "
2982         "password='%.*s' (%" G_GSIZE_FORMAT "), prio=%08x, %s.", agent,
2983              tmpbuf1, nice_address_get_port (&pair->local->addr),
2984              tmpbuf2, nice_address_get_port (&pair->remote->addr),
2985              pair->sockptr->fileno ? g_socket_get_fd(pair->sockptr->fileno) : -1,
2986              pair, pair->component_id,
2987              (unsigned long long)agent->tie_breaker,
2988         (int) uname_len, uname, uname_len,
2989         (int) password_len, password, password_len,
2990         pair->stun_priority,
2991         controlling ? "controlling" : "controlled");
2992   }
2993
2994   if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
2995     switch (agent->nomination_mode) {
2996       case NICE_NOMINATION_MODE_REGULAR:
2997         /* We are doing regular nomination, so we set the use-candidate
2998          * attrib, when the controlling agent decided which valid pair to
2999          * resend with this flag in priv_conn_check_tick_stream()
3000          */
3001         cand_use = pair->use_candidate_on_next_check;
3002         nice_debug ("Agent %p : %s: set cand_use=%d "
3003             "(regular nomination).", agent, G_STRFUNC, cand_use);
3004         break;
3005       case NICE_NOMINATION_MODE_AGGRESSIVE:
3006         /* We are doing aggressive nomination, we set the use-candidate
3007          * attrib in every check we send, when we are the controlling
3008          * agent, RFC 5245, 8.1.1.2
3009          */
3010         cand_use = controlling;
3011         nice_debug ("Agent %p : %s: set cand_use=%d "
3012             "(aggressive nomination).", agent, G_STRFUNC, cand_use);
3013         break;
3014       default:
3015         /* Nothing to do. */
3016         break;
3017     }
3018   } else if (cand_use)
3019     pair->nominated = controlling;
3020
3021   if (uname_len == 0) {
3022     nice_debug ("Agent %p: no credentials found, cancelling conncheck", agent);
3023     return -1;
3024   }
3025
3026   stun = priv_add_stun_transaction (pair);
3027
3028   buffer_len = stun_usage_ice_conncheck_create (&component->stun_agent,
3029       &stun->message, stun->buffer, sizeof(stun->buffer),
3030       uname, uname_len, password, password_len,
3031       cand_use, controlling, pair->stun_priority,
3032       agent->tie_breaker,
3033       pair->local->foundation,
3034       agent_to_ice_compatibility (agent));
3035
3036   nice_debug ("Agent %p: conncheck created %zd - %p", agent, buffer_len,
3037       stun->message.buffer);
3038
3039   if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
3040       agent->compatibility == NICE_COMPATIBILITY_OC2007) {
3041     g_free (password);
3042   }
3043
3044   if (buffer_len == 0) {
3045     nice_debug ("Agent %p: buffer is empty, cancelling conncheck", agent);
3046     priv_remove_stun_transaction (pair, stun, component);
3047     return -1;
3048   }
3049
3050   if (nice_socket_is_reliable(pair->sockptr)) {
3051     timeout = agent->stun_reliable_timeout;
3052     stun_timer_start_reliable(&stun->timer, timeout);
3053   } else {
3054     timeout = priv_compute_conncheck_timer (agent, stream);
3055     stun_timer_start (&stun->timer, timeout, agent->stun_max_retransmissions);
3056   }
3057
3058   stun->next_tick = g_get_monotonic_time () + timeout * 1000;
3059
3060   /* TCP-ACTIVE candidate must create a new socket before sending
3061    * by connecting to the peer. The new socket is stored in the candidate
3062    * check pair, until we discover a new local peer reflexive */
3063   if (pair->sockptr->fileno == NULL &&
3064       pair->sockptr->type != NICE_SOCKET_TYPE_UDP_TURN &&
3065       pair->local->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) {
3066     NiceStream *stream2 = NULL;
3067     NiceComponent *component2 = NULL;
3068     NiceSocket *new_socket;
3069
3070     if (agent_find_component (agent, pair->stream_id, pair->component_id,
3071             &stream2, &component2)) {
3072       new_socket = nice_tcp_active_socket_connect (pair->sockptr,
3073           &pair->remote->addr);
3074       if (new_socket) {
3075         nice_debug ("Agent %p: add to tcp-act socket %p a new "
3076             "tcp connect socket %p on pair %p in s/c %d/%d",
3077             agent, pair->sockptr, new_socket, pair, stream->id, component->id);
3078         pair->sockptr = new_socket;
3079         _priv_set_socket_tos (agent, pair->sockptr, stream2->tos);
3080
3081         nice_socket_set_writable_callback (pair->sockptr, _tcp_sock_is_writable,
3082             component2);
3083
3084         nice_component_attach_socket (component2, new_socket);
3085       }
3086     }
3087   }
3088   /* send the conncheck */
3089   agent_socket_send (pair->sockptr, &pair->remote->addr,
3090       buffer_len, (gchar *)stun->buffer);
3091
3092   if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2)
3093     ms_ice2_legacy_conncheck_send (&stun->message, pair->sockptr,
3094         &pair->remote->addr);
3095
3096   return 0;
3097 }
3098
3099 /*
3100  * Implemented the pruning steps described in ICE sect 8.1.2
3101  * "Updating States" (ID-19) after a pair has been nominated.
3102  *
3103  * @see conn_check_update_check_list_state_failed_components()
3104  */
3105 static guint priv_prune_pending_checks (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
3106 {
3107   GSList *i;
3108   guint64 priority;
3109   guint in_progress = 0;
3110   gchar prio[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
3111
3112   nice_debug ("Agent %p: Pruning pending checks for s%d/c%d",
3113       agent, stream->id, component->id);
3114
3115   /* Called when we have at least one selected pair */
3116   priority = component->selected_pair.priority;
3117   g_assert (priority > 0);
3118
3119   nice_candidate_pair_priority_to_string (priority, prio);
3120   nice_debug ("Agent %p : selected pair priority is %s", agent, prio);
3121
3122   i = stream->conncheck_list;
3123   while (i) {
3124     CandidateCheckPair *p = i->data;
3125     GSList *next = i->next;
3126
3127     if (p->component_id != component->id) {
3128       i = next;
3129       continue;
3130     }
3131
3132     /* step: cancel all FROZEN and WAITING pairs for the component */
3133     if (p->state == NICE_CHECK_FROZEN || p->state == NICE_CHECK_WAITING) {
3134       nice_debug ("Agent %p : pair %p removed.", agent, p);
3135       candidate_check_pair_free (agent, p);
3136       stream->conncheck_list = g_slist_delete_link(stream->conncheck_list, i);
3137     }
3138
3139     /* note: a SHOULD level req. in ICE 8.1.2. "Updating States" (ID-19) */
3140     else if (p->state == NICE_CHECK_IN_PROGRESS) {
3141       if (p->priority < priority) {
3142         priv_remove_pair_from_triggered_check_queue (agent, p);
3143         if (p->retransmit && p->stun_transactions) {
3144           p->retransmit  = FALSE;
3145           nice_debug ("Agent %p : pair %p will not be retransmitted.",
3146               agent, p);
3147         } else if (p->retransmit) {
3148           /* Pair in-progress, but stun request not yet sent */
3149           nice_debug ("Agent %p : pair %p removed.", agent, p);
3150           candidate_check_pair_free (agent, p);
3151           stream->conncheck_list = g_slist_delete_link(stream->conncheck_list,
3152               i);
3153         }
3154       } else {
3155         /* We must keep the higher priority pairs running because if a udp
3156          * packet was lost, we might end up using a bad candidate */
3157         nice_candidate_pair_priority_to_string (p->priority, prio);
3158         nice_debug ("Agent %p : pair %p kept IN_PROGRESS because priority "
3159             "%s is higher than priority of best nominated pair.", agent, p, prio);
3160         /* We may also have to enable the retransmit flag of pairs with
3161          * a higher priority than the first nominated pair
3162          */
3163         if (!p->retransmit && p->stun_transactions) {
3164           p->retransmit = TRUE;
3165           nice_debug ("Agent %p : pair %p will be retransmitted.", agent, p);
3166         }
3167         in_progress++;
3168       }
3169     }
3170     /* A triggered check on a failed pair will depend on the retransmit
3171      * flag, so on the relative priority of this pair and the nominated
3172      * pair.
3173      */
3174     else if (p->state == NICE_CHECK_FAILED)
3175       p->retransmit = (p->priority > priority ? TRUE : FALSE);
3176     i = next;
3177   }
3178
3179   return in_progress;
3180 }
3181
3182 /*
3183  * Schedules a triggered check after a successfully inbound 
3184  * connectivity check. Implements ICE sect 7.2.1.4 "Triggered Checks" (ID-19).
3185  * 
3186  * @param agent self pointer
3187  * @param component the check is related to
3188  * @param local_socket socket from which the inbound check was received
3189  * @param remote_cand remote candidate from which the inbound check was sent
3190  */
3191 static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *local_socket, NiceCandidate *remote_cand)
3192 {
3193   GSList *i;
3194   NiceCandidate *local = NULL;
3195   CandidateCheckPair *p;
3196
3197   g_assert (remote_cand != NULL);
3198
3199   nice_debug ("Agent %p : scheduling triggered check with socket=%p "
3200       "and remote cand=%p.", agent, local_socket, remote_cand);
3201
3202   for (i = stream->conncheck_list; i ; i = i->next) {
3203       p = i->data;
3204       if (p->component_id == component->id &&
3205           p->remote == remote_cand &&
3206           ((p->local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
3207               p->sockptr == local_socket) ||
3208               (p->local->transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
3209                   p->local->sockptr == local_socket))) {
3210         /* We don't check for p->sockptr because in the case of
3211          * tcp-active we don't want to retrigger a check on a pair that
3212          * was FAILED when a peer-reflexive pair was created */
3213
3214         if (p->succeeded_pair != NULL) {
3215           g_assert_cmpint (p->state, ==, NICE_CHECK_DISCOVERED);
3216           p = p->succeeded_pair;
3217         }
3218
3219         nice_debug ("Agent %p : Found a matching pair %p (%s) (%s) ...",
3220             agent, p, p->foundation, priv_state_to_string (p->state));
3221         
3222         switch (p->state) {
3223           case NICE_CHECK_WAITING:
3224           case NICE_CHECK_FROZEN:
3225             nice_debug ("Agent %p : pair %p added for a triggered check.",
3226                 agent, p);
3227             priv_add_pair_to_triggered_check_queue (agent, p);
3228             break;
3229           case NICE_CHECK_IN_PROGRESS:
3230             /* note: according to ICE SPEC sect 7.2.1.4 "Triggered Checks"
3231              * we cancel the in-progress transaction, and after the
3232              * retransmission timeout, we create a new connectivity check
3233              * for that pair.  The controlling role of this new check may
3234              * be different from the role of this cancelled check.
3235              *
3236              * note: the flag retransmit unset means that
3237              * another pair, with a higher priority is already nominated,
3238              * so there's no reason to recheck this pair, since it can in
3239              * no way replace the nominated one.
3240              */
3241             if (!nice_socket_is_reliable (p->sockptr) && p->retransmit) {
3242               nice_debug ("Agent %p : pair %p added for a triggered check.",
3243                   agent, p);
3244               priv_add_pair_to_triggered_check_queue (agent, p);
3245             }
3246             break;
3247           case NICE_CHECK_FAILED:
3248             if (p->retransmit) {
3249                 nice_debug ("Agent %p : pair %p added for a triggered check.",
3250                     agent, p);
3251                 priv_add_pair_to_triggered_check_queue (agent, p);
3252                 /* If the component for this pair is in failed state, move it
3253                  * back to connecting, and reinitiate the timers
3254                  */
3255                 if (component->state == NICE_COMPONENT_STATE_FAILED) {
3256                   agent_signal_component_state_change (agent, stream->id,
3257                       component->id, NICE_COMPONENT_STATE_CONNECTING);
3258                   conn_check_schedule_next (agent);
3259                 }
3260             }
3261             break;
3262           case NICE_CHECK_SUCCEEDED:
3263             nice_debug ("Agent %p : nothing to do for pair %p.", agent, p);
3264             /* note: this is a bit unsure corner-case -- let's do the
3265                same state update as for processing responses to our own checks */
3266             /* note: this update is required by the trickle test, to
3267              * ensure the transition ready -> connected -> ready, because
3268              * an incoming stun request generates a discovered peer reflexive,
3269              * that causes the ready -> connected transition.
3270              */
3271             conn_check_update_check_list_state_for_ready (agent, stream,
3272                 component);
3273             break;
3274           default:
3275             break;
3276         }
3277
3278         /* note: the spec says the we SHOULD retransmit in-progress
3279          *       checks immediately, but we won't do that now */
3280
3281         return TRUE;
3282       }
3283   }
3284
3285   for (i = component->local_candidates; i ; i = i->next) {
3286     local = i->data;
3287     if (local->sockptr == local_socket)
3288       break;
3289   }
3290
3291   if (i) {
3292     nice_debug ("Agent %p : Adding a triggered check to conn.check list (local=%p).", agent, local);
3293     p = priv_conn_check_add_for_candidate_pair_matched (agent, stream->id,
3294         component, local, remote_cand, NICE_CHECK_WAITING);
3295     if (p)
3296       priv_add_pair_to_triggered_check_queue (agent, p);
3297     return TRUE;
3298   }
3299   else {
3300     nice_debug ("Agent %p : Didn't find a matching pair for triggered check (remote-cand=%p).", agent, remote_cand);
3301     return FALSE;
3302   }
3303 }
3304
3305
3306 /*
3307  * Sends a reply to an successfully received STUN connectivity 
3308  * check request. Implements parts of the ICE spec section 7.2 (STUN
3309  * Server Procedures).
3310  *
3311  * @param agent context pointer
3312  * @param stream which stream (of the agent)
3313  * @param component which component (of the stream)
3314  * @param rcand remote candidate from which the request came, if NULL,
3315  *        the response is sent immediately but no other processing is done
3316  * @param toaddr address to which reply is sent
3317  * @param socket the socket over which the request came
3318  * @param rbuf_len length of STUN message to send
3319  * @param msg the STUN message to send
3320  * @param use_candidate whether the request had USE_CANDIDATE attribute
3321  * 
3322  * @pre (rcand == NULL || nice_address_equal(rcand->addr, toaddr) == TRUE)
3323  */
3324 static void priv_reply_to_conn_check (NiceAgent *agent, NiceStream *stream,
3325     NiceComponent *component, NiceCandidate *lcand, NiceCandidate *rcand,
3326     const NiceAddress *toaddr, NiceSocket *sockptr, size_t rbuf_len,
3327     StunMessage *msg, gboolean use_candidate)
3328 {
3329   g_assert (rcand == NULL || nice_address_equal(&rcand->addr, toaddr) == TRUE);
3330
3331   if (nice_debug_is_enabled ()) {
3332     gchar tmpbuf[INET6_ADDRSTRLEN];
3333     nice_address_to_string (toaddr, tmpbuf);
3334     nice_debug ("Agent %p : STUN-CC RESP to '%s:%u', socket=%u, len=%u, cand=%p (c-id:%u), use-cand=%d.", agent,
3335              tmpbuf,
3336              nice_address_get_port (toaddr),
3337              sockptr->fileno ? g_socket_get_fd(sockptr->fileno) : -1,
3338              (unsigned)rbuf_len,
3339              rcand, component->id,
3340              (int)use_candidate);
3341   }
3342
3343   agent_socket_send (sockptr, toaddr, rbuf_len, (const gchar*)msg->buffer);
3344   if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
3345     ms_ice2_legacy_conncheck_send(msg, sockptr, toaddr);
3346   }
3347
3348   /* We react to this stun request when we have the remote credentials.
3349    * When credentials are not yet known, this request is stored
3350    * in incoming_checks for later processing when returning from this
3351    * function.
3352    */
3353   if (rcand && stream->remote_ufrag[0]) {
3354     priv_schedule_triggered_check (agent, stream, component, sockptr, rcand);
3355     if (use_candidate)
3356       priv_mark_pair_nominated (agent, stream, component, lcand, rcand);
3357   }
3358 }
3359
3360 /*
3361  * Stores information of an incoming STUN connectivity check
3362  * for later use. This is only needed when a check is received
3363  * before we get information about the remote candidates (via
3364  * SDP or other signaling means).
3365  *
3366  * @return non-zero on error, zero on success
3367  */
3368 static int priv_store_pending_check (NiceAgent *agent, NiceComponent *component,
3369     const NiceAddress *from, NiceSocket *sockptr, uint8_t *username,
3370     uint16_t username_len, uint32_t priority, gboolean use_candidate)
3371 {
3372   IncomingCheck *icheck;
3373   nice_debug ("Agent %p : Storing pending check.", agent);
3374
3375   if (g_queue_get_length (&component->incoming_checks) >=
3376       NICE_AGENT_MAX_REMOTE_CANDIDATES) {
3377     nice_debug ("Agent %p : WARN: unable to store information for early incoming check.", agent);
3378     return -1;
3379   }
3380
3381   icheck = g_slice_new0 (IncomingCheck);
3382   g_queue_push_tail (&component->incoming_checks, icheck);
3383   icheck->from = *from;
3384   icheck->local_socket = sockptr;
3385   icheck->priority = priority;
3386   icheck->use_candidate = use_candidate;
3387   icheck->username_len = username_len;
3388   icheck->username = NULL;
3389   if (username_len > 0)
3390     icheck->username = g_memdup (username, username_len);
3391
3392   return 0;
3393 }
3394
3395 /*
3396  * Adds a new pair, discovered from an incoming STUN response, to 
3397  * the connectivity check list.
3398  *
3399  * @return created pair, or NULL on fatal (memory allocation) errors
3400  */
3401 static CandidateCheckPair *priv_add_peer_reflexive_pair (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local_cand, CandidateCheckPair *parent_pair)
3402 {
3403   CandidateCheckPair *pair = g_slice_new0 (CandidateCheckPair);
3404   NiceStream *stream = agent_find_stream (agent, stream_id);
3405
3406   pair->stream_id = stream_id;
3407   pair->component_id = component->id;;
3408   pair->local = local_cand;
3409   pair->remote = parent_pair->remote;
3410   pair->sockptr = local_cand->sockptr;
3411   parent_pair->discovered_pair = pair;
3412   pair->succeeded_pair = parent_pair;
3413   nice_debug ("Agent %p : creating a new pair", agent);
3414   SET_PAIR_STATE (agent, pair, NICE_CHECK_DISCOVERED);
3415   {
3416       gchar tmpbuf1[INET6_ADDRSTRLEN];
3417       gchar tmpbuf2[INET6_ADDRSTRLEN];
3418       nice_address_to_string (&pair->local->addr, tmpbuf1);
3419       nice_address_to_string (&pair->remote->addr, tmpbuf2);
3420       nice_debug ("Agent %p : new pair %p : [%s]:%u --> [%s]:%u", agent, pair,
3421           tmpbuf1, nice_address_get_port (&pair->local->addr),
3422           tmpbuf2, nice_address_get_port (&pair->remote->addr));
3423   }
3424   g_snprintf (pair->foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s",
3425       local_cand->foundation, parent_pair->remote->foundation);
3426
3427   if (agent->controlling_mode == TRUE)
3428     pair->priority = nice_candidate_pair_priority (pair->local->priority,
3429         pair->remote->priority);
3430   else
3431     pair->priority = nice_candidate_pair_priority (pair->remote->priority,
3432         pair->local->priority);
3433   pair->nominated = parent_pair->nominated;
3434   /* the peer-reflexive priority used in stun request is copied from
3435    * the parent succeeded pair. This value is not required for discovered
3436    * pair, that won't emit stun requests themselves, but may be used when
3437    * such pair becomes the selected pair, and when keepalive stun are emitted,
3438    * using the sockptr and stun_priority values from the succeeded pair.
3439    */
3440   pair->stun_priority = parent_pair->stun_priority;
3441   nice_debug ("Agent %p : added a new peer-discovered pair %p with "
3442       "foundation '%s' and transport %s:%s to stream %u component %u",
3443       agent, pair, pair->foundation,
3444       priv_candidate_transport_to_string (pair->local->transport),
3445       priv_candidate_transport_to_string (pair->remote->transport),
3446       stream_id, component->id);
3447
3448   stream->conncheck_list = g_slist_insert_sorted (stream->conncheck_list, pair,
3449       (GCompareFunc)conn_check_compare);
3450
3451   return pair;
3452 }
3453
3454 /*
3455  * Recalculates priorities of all candidate pairs. This
3456  * is required after a conflict in ICE roles.
3457  */
3458 void recalculate_pair_priorities (NiceAgent *agent)
3459 {
3460   GSList *i, *j;
3461
3462   for (i = agent->streams; i; i = i->next) {
3463     NiceStream *stream = i->data;
3464     for (j = stream->conncheck_list; j; j = j->next) {
3465       CandidateCheckPair *p = j->data;
3466       p->priority = agent_candidate_pair_priority (agent, p->local, p->remote);
3467     }
3468     stream->conncheck_list = g_slist_sort (stream->conncheck_list,
3469         (GCompareFunc)conn_check_compare);
3470   }
3471 }
3472
3473 /*
3474  * Change the agent role if different from 'control'. Can be
3475  * initiated both by handling of incoming connectivity checks,
3476  * and by processing the responses to checks sent by us.
3477  */
3478 static void priv_check_for_role_conflict (NiceAgent *agent, gboolean control)
3479 {
3480   /* role conflict, change mode; wait for a new conn. check */
3481   if (control != agent->controlling_mode) {
3482     nice_debug ("Agent %p : Role conflict, changing agent role to \"%s\".",
3483         agent, control ? "controlling" : "controlled");
3484     agent->controlling_mode = control;
3485     /* the pair priorities depend on the roles, so recalculation
3486      * is needed */
3487     recalculate_pair_priorities (agent);
3488   }
3489   else 
3490     nice_debug ("Agent %p : Role conflict, staying with role \"%s\".",
3491         agent, control ? "controlling" : "controlled");
3492 }
3493
3494 /*
3495  * Checks whether the mapped address in connectivity check response 
3496  * matches any of the known local candidates. If not, apply the
3497  * mechanism for "Discovering Peer Reflexive Candidates" ICE ID-19)
3498  *
3499  * @param agent context pointer
3500  * @param stream which stream (of the agent)
3501  * @param component which component (of the stream)
3502  * @param p the connectivity check pair for which we got a response
3503  * @param socketptr socket used to send the reply
3504  * @param mapped_sockaddr mapped address in the response
3505  *
3506  * @return pointer to a candidate pair, found in conncheck list or newly created
3507  */
3508 static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent *agent, NiceStream *stream, NiceComponent *component, CandidateCheckPair *p, NiceSocket *sockptr, struct sockaddr *mapped_sockaddr, NiceCandidate *local_candidate, NiceCandidate *remote_candidate)
3509 {
3510   CandidateCheckPair *new_pair = NULL;
3511   NiceAddress mapped;
3512   GSList *i;
3513   NiceCandidate *local_cand = NULL;
3514
3515   nice_address_set_from_sockaddr (&mapped, mapped_sockaddr);
3516
3517   for (i = component->local_candidates; i; i = i->next) {
3518     NiceCandidate *cand = i->data;
3519
3520     if (nice_address_equal (&mapped, &cand->addr) &&
3521         local_candidate_and_socket_compatible (agent, cand, sockptr)) {
3522       local_cand = cand;
3523       break;
3524     }
3525   }
3526
3527   /* The mapped address allows to look for a previously discovered
3528    * peer reflexive local candidate, and its related pair. This
3529    * new_pair will be marked 'Valid', while the pair 'p' of the
3530    * initial stun request will be marked 'Succeeded'
3531    *
3532    * In the case of a tcp-act/tcp-pass pair 'p', where the local
3533    * candidate is of type tcp-act, and its port number is zero, a
3534    * conncheck on this pair *always* leads to the creation of a
3535    * discovered peer-reflexive tcp-act local candidate.
3536    */
3537   for (i = stream->conncheck_list; i; i = i->next) {
3538     CandidateCheckPair *pair = i->data;
3539     if (local_cand == pair->local && remote_candidate == pair->remote) {
3540       new_pair = pair;
3541       break;
3542     }
3543   }
3544
3545   if (new_pair) {
3546     /* note: when new_pair is distinct from p, it means new_pair is a
3547      * previously discovered peer-reflexive candidate pair, so we don't
3548      * set the valid flag on p in this case, because the valid flag is
3549      * already set on the discovered pair.
3550      */
3551     if (new_pair == p)
3552       p->valid = TRUE;
3553     SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
3554     priv_remove_pair_from_triggered_check_queue (agent, p);
3555     priv_free_all_stun_transactions (p, component);
3556     nice_component_add_valid_candidate (agent, component, remote_candidate);
3557   }
3558   else {
3559     if (local_cand == NULL && !agent->force_relay) {
3560       /* step: find a new local candidate, see RFC 5245 7.1.3.2.1.
3561        * "Discovering Peer Reflexive Candidates"
3562        *
3563        * The priority equal to the value of the PRIORITY attribute
3564        * in the Binding request is taken from the "parent" pair p
3565        */
3566       local_cand = discovery_add_peer_reflexive_candidate (agent,
3567                                                            stream->id,
3568                                                            component->id,
3569                                                            p->stun_priority,
3570                                                           &mapped,
3571                                                            sockptr,
3572                                                            local_candidate,
3573                                                            remote_candidate);
3574       nice_debug ("Agent %p : added a new peer-reflexive local candidate %p "
3575           "with transport %s", agent, local_cand,
3576           priv_candidate_transport_to_string (local_cand->transport));
3577     }
3578
3579     /* step: add a new discovered pair (see RFC 5245 7.1.3.2.2
3580                "Constructing a Valid Pair") */
3581     if (local_cand)
3582       new_pair = priv_add_peer_reflexive_pair (agent, stream->id, component,
3583           local_cand, p);
3584     /* note: this is same as "adding to VALID LIST" in the spec
3585        text */
3586     if (new_pair)
3587       new_pair->valid = TRUE;
3588     /* step: The agent sets the state of the pair that *generated* the check to
3589      * Succeeded, RFC 5245, 7.1.3.2.3, "Updating Pair States"
3590      */
3591     SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
3592     priv_remove_pair_from_triggered_check_queue (agent, p);
3593     priv_free_all_stun_transactions (p, component);
3594   }
3595
3596   if (new_pair && new_pair->valid)
3597     nice_component_add_valid_candidate (agent, component, remote_candidate);
3598
3599
3600   return new_pair;
3601 }
3602
3603 /*
3604  * Tries to match STUN reply in 'buf' to an existing STUN connectivity
3605  * check transaction. If found, the reply is processed. Implements
3606  * section 7.1.2 "Processing the Response" of ICE spec (ID-19).
3607  *
3608  * @return TRUE if a matching transaction is found
3609  */
3610 static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *sockptr, const NiceAddress *from, NiceCandidate *local_candidate, NiceCandidate *remote_candidate, StunMessage *resp)
3611 {
3612   union {
3613     struct sockaddr_storage storage;
3614     struct sockaddr addr;
3615   } sockaddr;
3616   socklen_t socklen = sizeof (sockaddr);
3617   GSList *i, *j;
3618   guint k;
3619   StunUsageIceReturn res;
3620   StunTransactionId discovery_id;
3621   StunTransactionId response_id;
3622   stun_message_id (resp, response_id);
3623
3624   for (i = stream->conncheck_list; i; i = i->next) {
3625     CandidateCheckPair *p = i->data;
3626
3627     for (j = p->stun_transactions, k = 0; j; j = j->next, k++) {
3628       StunTransaction *stun = j->data;
3629
3630       stun_message_id (&stun->message, discovery_id);
3631
3632       if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)))
3633         continue;
3634
3635       res = stun_usage_ice_conncheck_process (resp,
3636           &sockaddr.storage, &socklen,
3637           agent_to_ice_compatibility (agent));
3638       nice_debug ("Agent %p : stun_bind_process/conncheck for %p: "
3639           "%s,res=%s,stun#=%d.",
3640           agent, p,
3641           agent->controlling_mode ? "controlling" : "controlled",
3642           priv_ice_return_to_string (res), k);
3643
3644       if (res == STUN_USAGE_ICE_RETURN_SUCCESS ||
3645           res == STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS) {
3646         /* case: found a matching connectivity check request */
3647
3648         CandidateCheckPair *ok_pair = NULL;
3649
3650         nice_debug ("Agent %p : pair %p MATCHED.", agent, p);
3651         priv_remove_stun_transaction (p, stun, component);
3652
3653         /* step: verify that response came from the same IP address we
3654          *       sent the original request to (see 7.1.2.1. "Failure
3655          *       Cases") */
3656         if (nice_address_equal (from, &p->remote->addr) == FALSE) {
3657           candidate_check_pair_fail (stream, agent, p);
3658           if (nice_debug_is_enabled ()) {
3659             gchar tmpbuf[INET6_ADDRSTRLEN];
3660             gchar tmpbuf2[INET6_ADDRSTRLEN];
3661             nice_debug ("Agent %p : pair %p FAILED"
3662                 " (mismatch of source address).", agent, p);
3663             nice_address_to_string (&p->remote->addr, tmpbuf);
3664             nice_address_to_string (from, tmpbuf2);
3665             nice_debug ("Agent %p : '%s:%u' != '%s:%u'", agent,
3666                 tmpbuf, nice_address_get_port (&p->remote->addr),
3667                 tmpbuf2, nice_address_get_port (from));
3668           }
3669           return TRUE;
3670         }
3671
3672         if (remote_candidate == NULL) {
3673           candidate_check_pair_fail (stream, agent, p);
3674           if (nice_debug_is_enabled ()) {
3675             nice_debug ("Agent %p : pair %p FAILED "
3676                 "(got a matching pair without a known remote candidate).", agent, p);
3677           }
3678           return TRUE;
3679         }
3680
3681         /* note: CONNECTED but not yet READY, see docs */
3682
3683         /* step: handle the possible case of a peer-reflexive
3684          *       candidate where the mapped-address in response does
3685          *       not match any local candidate, see 7.1.2.2.1
3686          *       "Discovering Peer Reflexive Candidates" ICE ID-19) */
3687
3688         if (res == STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS) {
3689           nice_debug ("Agent %p : Mapped address not found", agent);
3690           SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
3691           p->valid = TRUE;
3692           nice_component_add_valid_candidate (agent, component, p->remote);
3693         } else
3694           ok_pair = priv_process_response_check_for_reflexive (agent,
3695               stream, component, p, sockptr, &sockaddr.addr,
3696               local_candidate, remote_candidate);
3697
3698         /* note: The success of this check might also
3699          * cause the state of other checks to change as well, ICE
3700          * spec 7.1.3.2.3
3701          */
3702         priv_conn_check_unfreeze_related (agent, stream, p);
3703
3704         /* Note: this assignment helps to reduce the numbers of cases
3705          * to be tested. If ok_pair and p refer to distinct pairs, it
3706          * means that ok_pair is a discovered peer reflexive one,
3707          * caused by the check made on pair p.  In that case, the
3708          * flags to be tested are on p, but the nominated flag will be
3709          * set on ok_pair. When there's no discovered pair, p and
3710          * ok_pair refer to the same pair.
3711          * To summarize : p is a SUCCEEDED pair, ok_pair is a
3712          * DISCOVERED, VALID, and eventually NOMINATED pair. 
3713          */
3714         if (!ok_pair)
3715           ok_pair = p;
3716
3717         /* step: updating nominated flag (ICE 7.1.2.2.4 "Updating the
3718            Nominated Flag" (ID-19) */
3719         if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
3720           nice_debug ("Agent %p : Updating nominated flag (%s): "
3721               "ok_pair=%p (%d/%d) p=%p (%d/%d) (ucnc/mnora)",
3722               agent, p->local->transport == NICE_CANDIDATE_TRANSPORT_UDP ?
3723                 "UDP" : "TCP",
3724               ok_pair, ok_pair->use_candidate_on_next_check,
3725               ok_pair->mark_nominated_on_response_arrival,
3726               p, p->use_candidate_on_next_check,
3727               p->mark_nominated_on_response_arrival);
3728
3729           if (agent->controlling_mode) {
3730             switch (agent->nomination_mode) {
3731               case NICE_NOMINATION_MODE_REGULAR:
3732                 if (p->use_candidate_on_next_check) {
3733                   nice_debug ("Agent %p : marking pair %p (%s) as nominated "
3734                       "(regular nomination, controlling, "
3735                       "use_cand_on_next_check=1).",
3736                       agent, ok_pair, ok_pair->foundation);
3737                   ok_pair->nominated = TRUE;
3738                 }
3739                 break;
3740               case NICE_NOMINATION_MODE_AGGRESSIVE:
3741                 if (!p->nominated) {
3742                   nice_debug ("Agent %p : marking pair %p (%s) as nominated "
3743                       "(aggressive nomination, controlling).",
3744                       agent, ok_pair, ok_pair->foundation);
3745                   ok_pair->nominated = TRUE;
3746                 }
3747                 break;
3748               default:
3749                 /* Nothing to do */
3750                 break;
3751             }
3752           } else {
3753             if (p->mark_nominated_on_response_arrival) {
3754               nice_debug ("Agent %p : marking pair %p (%s) as nominated "
3755                   "(%s nomination, controlled, mark_on_response=1).",
3756                   agent, ok_pair, ok_pair->foundation,
3757                   agent->nomination_mode == NICE_NOMINATION_MODE_AGGRESSIVE ?
3758                     "aggressive" : "regular");
3759               ok_pair->nominated = TRUE;
3760             }
3761           }
3762         }
3763
3764         if (ok_pair->nominated == TRUE) {
3765           conn_check_update_selected_pair (agent, component, ok_pair);
3766           priv_print_conn_check_lists (agent, G_STRFUNC,
3767               ", got a nominated pair");
3768
3769           /* Do not step down to CONNECTED if we're already at state READY*/
3770           if (component->state != NICE_COMPONENT_STATE_READY)
3771             /* step: notify the client of a new component state (must be done
3772              *       before the possible check list state update step */
3773             agent_signal_component_state_change (agent,
3774                 stream->id, component->id, NICE_COMPONENT_STATE_CONNECTED);
3775         }
3776
3777         /* step: update pair states (ICE 7.1.2.2.3 "Updating pair
3778            states" and 8.1.2 "Updating States", ID-19) */
3779         conn_check_update_check_list_state_for_ready (agent, stream, component);
3780       } else if (res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT) {
3781         uint64_t tie;
3782         gboolean controlled_mode;
3783
3784         if (!p->retransmit) {
3785           nice_debug ("Agent %p : Role conflict with pair %p, not restarting",
3786               agent, p);
3787           return TRUE;
3788         }
3789
3790         /* case: role conflict error, need to restart with new role */
3791         nice_debug ("Agent %p : Role conflict with pair %p, restarting",
3792             agent, p);
3793
3794         /* note: this res value indicates that the role of the peer
3795          * agent has not changed after the tie-breaker comparison, so
3796          * this is our role that must change. see ICE sect. 7.1.3.1
3797          * "Failure Cases". Our role might already have changed due to
3798          * an earlier incoming request, but if not, change role now.
3799          *
3800          * Sect. 7.1.3.1 is not clear on this point, but we choose to
3801          * put the candidate pair in the triggered check list even
3802          * when the agent did not switch its role. The reason for this
3803          * interpretation is that the reception of the stun reply, even
3804          * an error reply, is a good sign that this pair will be
3805          * valid, if we retry the check after the role of both peers
3806          * has been fixed.
3807          */
3808         controlled_mode = (stun_message_find64 (&stun->message,
3809             STUN_ATTRIBUTE_ICE_CONTROLLED, &tie) ==
3810             STUN_MESSAGE_RETURN_SUCCESS);
3811
3812         priv_check_for_role_conflict (agent, controlled_mode);
3813         priv_remove_stun_transaction (p, stun, component);
3814         priv_add_pair_to_triggered_check_queue (agent, p);
3815       } else {
3816         /* case: STUN error, the check STUN context was freed */
3817         candidate_check_pair_fail (stream, agent, p);
3818       }
3819       return TRUE;
3820     }
3821   }
3822
3823   return FALSE;
3824 }
3825
3826 /*
3827  * Tries to match STUN reply in 'buf' to an existing STUN discovery
3828  * transaction. If found, a reply is sent.
3829  *
3830  * @return TRUE if a matching transaction is found
3831  */
3832 static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessage *resp)
3833 {
3834   union {
3835     struct sockaddr_storage storage;
3836     struct sockaddr addr;
3837   } sockaddr;
3838   socklen_t socklen = sizeof (sockaddr);
3839
3840   union {
3841     struct sockaddr_storage storage;
3842     struct sockaddr addr;
3843   } alternate;
3844   socklen_t alternatelen = sizeof (sockaddr);
3845
3846   GSList *i;
3847   StunUsageBindReturn res;
3848   gboolean trans_found = FALSE;
3849   StunTransactionId discovery_id;
3850   StunTransactionId response_id;
3851   stun_message_id (resp, response_id);
3852
3853   for (i = agent->discovery_list; i && trans_found != TRUE; i = i->next) {
3854     CandidateDiscovery *d = i->data;
3855
3856     if (d->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE &&
3857         d->stun_message.buffer) {
3858       stun_message_id (&d->stun_message, discovery_id);
3859
3860       if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
3861         res = stun_usage_bind_process (resp, &sockaddr.addr,
3862             &socklen, &alternate.addr, &alternatelen);
3863         nice_debug ("Agent %p : stun_bind_process/disc for %p res %d.",
3864             agent, d, (int)res);
3865
3866         if (res == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
3867           /* handle alternate server */
3868           NiceAddress niceaddr;
3869           nice_address_set_from_sockaddr (&niceaddr, &alternate.addr);
3870           d->server = niceaddr;
3871
3872           d->pending = FALSE;
3873           agent->discovery_unsched_items++;
3874         } else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) {
3875           /* case: successful binding discovery, create a new local candidate */
3876
3877           if (!agent->force_relay) {
3878             NiceAddress niceaddr;
3879
3880             nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
3881             discovery_add_server_reflexive_candidate (
3882                 agent,
3883                 d->stream_id,
3884                 d->component_id,
3885                 &niceaddr,
3886                 NICE_CANDIDATE_TRANSPORT_UDP,
3887                 d->nicesock,
3888                 FALSE);
3889             if (agent->use_ice_tcp)
3890               discovery_discover_tcp_server_reflexive_candidates (
3891                   agent,
3892                   d->stream_id,
3893                   d->component_id,
3894                   &niceaddr,
3895                   d->nicesock);
3896           }
3897           d->stun_message.buffer = NULL;
3898           d->stun_message.buffer_len = 0;
3899           d->done = TRUE;
3900           trans_found = TRUE;
3901         } else if (res == STUN_USAGE_BIND_RETURN_ERROR) {
3902           /* case: STUN error, the check STUN context was freed */
3903           d->stun_message.buffer = NULL;
3904           d->stun_message.buffer_len = 0;
3905           d->done = TRUE;
3906           trans_found = TRUE;
3907         }
3908       }
3909     }
3910   }
3911
3912   return trans_found;
3913 }
3914
3915 static guint
3916 priv_calc_turn_timeout (guint lifetime)
3917 {
3918   if (lifetime > 120)
3919     return lifetime - 60;
3920   else
3921     return lifetime / 2;
3922 }
3923
3924 static CandidateRefresh *
3925 priv_add_new_turn_refresh (NiceAgent *agent, CandidateDiscovery *cdisco,
3926     NiceCandidate *relay_cand, guint lifetime)
3927 {
3928   CandidateRefresh *cand;
3929
3930   cand = g_slice_new0 (CandidateRefresh);
3931   agent->refresh_list = g_slist_append (agent->refresh_list, cand);
3932
3933   cand->candidate = relay_cand;
3934   cand->nicesock = cdisco->nicesock;
3935   cand->server = cdisco->server;
3936   cand->stream_id = cdisco->stream_id;
3937   cand->component_id = cdisco->component_id;
3938   memcpy (&cand->stun_agent, &cdisco->stun_agent, sizeof(StunAgent));
3939
3940   /* Use previous stun response for authentication credentials */
3941   if (cdisco->stun_resp_msg.buffer != NULL) {
3942     memcpy(cand->stun_resp_buffer, cdisco->stun_resp_buffer,
3943         sizeof(cand->stun_resp_buffer));
3944     memcpy(&cand->stun_resp_msg, &cdisco->stun_resp_msg, sizeof(StunMessage));
3945     cand->stun_resp_msg.buffer = cand->stun_resp_buffer;
3946     cand->stun_resp_msg.agent = NULL;
3947     cand->stun_resp_msg.key = NULL;
3948   }
3949
3950   nice_debug ("Agent %p : Adding new refresh candidate %p with timeout %d",
3951       agent, cand, priv_calc_turn_timeout (lifetime));
3952   /* step: also start the refresh timer */
3953   /* refresh should be sent 1 minute before it expires */
3954   agent_timeout_add_seconds_with_context (agent, &cand->timer_source,
3955       "Candidate TURN refresh",
3956       priv_calc_turn_timeout (lifetime),
3957       priv_turn_allocate_refresh_tick_agent_locked, cand);
3958
3959   nice_debug ("timer source is : %p", cand->timer_source);
3960
3961   return cand;
3962 }
3963
3964 static void priv_handle_turn_alternate_server (NiceAgent *agent,
3965     CandidateDiscovery *disco, NiceAddress server, NiceAddress alternate)
3966 {
3967   /* We need to cancel and reset all candidate discovery turn for the same
3968      stream and type if there is an alternate server. Otherwise, we might end up
3969      with two relay components on different servers, creating candidates with
3970      unique foundations that only contain one component.
3971   */
3972   GSList *i;
3973
3974   for (i = agent->discovery_list; i; i = i->next) {
3975     CandidateDiscovery *d = i->data;
3976
3977     if (!d->done &&
3978         d->type == disco->type &&
3979         d->stream_id == disco->stream_id &&
3980         d->turn->type == disco->turn->type &&
3981         nice_address_equal (&d->server, &server)) {
3982       gchar ip[INET6_ADDRSTRLEN];
3983       // Cancel the pending request to avoid a race condition with another
3984       // component responding with another altenrate-server
3985       d->stun_message.buffer = NULL;
3986       d->stun_message.buffer_len = 0;
3987
3988       nice_address_to_string (&server, ip);
3989       nice_debug ("Agent %p : Cancelling and setting alternate server %s for "
3990           "CandidateDiscovery %p", agent, ip, d);
3991       d->server = alternate;
3992       d->turn->server = alternate;
3993       d->pending = FALSE;
3994       agent->discovery_unsched_items++;
3995     }
3996   }
3997 }
3998
3999 /*
4000  * Tries to match STUN reply in 'buf' to an existing STUN discovery
4001  * transaction. If found, a reply is sent.
4002  * 
4003  * @return TRUE if a matching transaction is found
4004  */
4005 static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *resp)
4006 {
4007   union {
4008     struct sockaddr_storage storage;
4009     struct sockaddr addr;
4010   } sockaddr;
4011   socklen_t socklen = sizeof (sockaddr);
4012
4013   union {
4014     struct sockaddr_storage storage;
4015     struct sockaddr addr;
4016   } alternate;
4017   socklen_t alternatelen = sizeof (alternate);
4018
4019   union {
4020     struct sockaddr_storage storage;
4021     struct sockaddr addr;
4022   } relayaddr;
4023   socklen_t relayaddrlen = sizeof (relayaddr);
4024
4025   uint32_t lifetime;
4026   uint32_t bandwidth;
4027   GSList *i;
4028   StunUsageTurnReturn res;
4029   gboolean trans_found = FALSE;
4030   StunTransactionId discovery_id;
4031   StunTransactionId response_id;
4032   stun_message_id (resp, response_id);
4033
4034   for (i = agent->discovery_list; i && trans_found != TRUE; i = i->next) {
4035     CandidateDiscovery *d = i->data;
4036
4037     if (d->type == NICE_CANDIDATE_TYPE_RELAYED &&
4038         d->stun_message.buffer) {
4039       stun_message_id (&d->stun_message, discovery_id);
4040
4041       if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
4042         res = stun_usage_turn_process (resp,
4043             &relayaddr.storage, &relayaddrlen,
4044             &sockaddr.storage, &socklen,
4045             &alternate.storage, &alternatelen,
4046             &bandwidth, &lifetime, agent_to_turn_compatibility (agent));
4047         nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.",
4048             agent, d, (int)res);
4049
4050         if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) {
4051           NiceAddress addr;
4052
4053           /* handle alternate server */
4054           nice_address_set_from_sockaddr (&addr, &alternate.addr);
4055           priv_handle_turn_alternate_server (agent, d, d->server, addr);
4056           trans_found = TRUE;
4057         } else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS ||
4058                    res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS) {
4059           /* case: successful allocate, create a new local candidate */
4060           NiceAddress niceaddr;
4061           NiceCandidate *relay_cand;
4062
4063           nice_address_set_from_sockaddr (&niceaddr, &relayaddr.addr);
4064
4065           if (res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS) {
4066             NiceAddress mappedniceaddr;
4067
4068             /* We also received our mapped address */
4069             nice_address_set_from_sockaddr (&mappedniceaddr, &sockaddr.addr);
4070
4071             /* TCP or TLS TURNS means the server-reflexive address was
4072              * on a TCP connection, which cannot be used for server-reflexive
4073              * discovery of candidates.
4074              */
4075             if (d->turn->type == NICE_RELAY_TYPE_TURN_UDP &&
4076                 !agent->force_relay) {
4077               discovery_add_server_reflexive_candidate (
4078                   agent,
4079                   d->stream_id,
4080                   d->component_id,
4081                   &mappedniceaddr,
4082                   NICE_CANDIDATE_TRANSPORT_UDP,
4083                   d->nicesock,
4084                   FALSE);
4085             }
4086             if (agent->use_ice_tcp) {
4087               if ((agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
4088                    agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
4089                   !nice_address_equal_no_port (&niceaddr, &d->turn->server)) {
4090                   nice_debug("TURN port got allocated on an alternate server, "
4091                              "ignoring bogus srflx address");
4092               } else {
4093                 discovery_discover_tcp_server_reflexive_candidates (
4094                     agent,
4095                     d->stream_id,
4096                     d->component_id,
4097                     &mappedniceaddr,
4098                     d->nicesock);
4099               }
4100             }
4101           }
4102
4103           if (nice_socket_is_reliable (d->nicesock)) {
4104             relay_cand = discovery_add_relay_candidate (
4105                 agent,
4106                 d->stream_id,
4107                 d->component_id,
4108                 &niceaddr,
4109                 NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE,
4110                 d->nicesock,
4111                 d->turn);
4112
4113             if (relay_cand) {
4114               if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
4115                   agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
4116                 nice_udp_turn_socket_set_ms_realm(relay_cand->sockptr,
4117                     &d->stun_message);
4118                 nice_udp_turn_socket_set_ms_connection_id(relay_cand->sockptr,
4119                     resp);
4120               } else {
4121                 priv_add_new_turn_refresh (agent, d, relay_cand, lifetime);
4122               }
4123             }
4124
4125             relay_cand = discovery_add_relay_candidate (
4126                 agent,
4127                 d->stream_id,
4128                 d->component_id,
4129                 &niceaddr,
4130                 NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE,
4131                 d->nicesock,
4132                 d->turn);
4133           } else {
4134             relay_cand = discovery_add_relay_candidate (
4135                 agent,
4136                 d->stream_id,
4137                 d->component_id,
4138                 &niceaddr,
4139                 NICE_CANDIDATE_TRANSPORT_UDP,
4140                 d->nicesock,
4141                 d->turn);
4142           }
4143
4144           if (relay_cand) {
4145             if (d->stun_resp_msg.buffer)
4146               nice_udp_turn_socket_cache_realm_nonce (relay_cand->sockptr,
4147                   &d->stun_resp_msg);
4148             if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
4149                 agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
4150               /* These data are needed on TURN socket when sending requests,
4151                * but never reach nice_turn_socket_parse_recv() where it could
4152                * be read directly, as the socket does not exist when allocate
4153                * response arrives to _nice_agent_recv(). We must set them right
4154                * after socket gets created in discovery_add_relay_candidate(),
4155                * so we are doing it here. */
4156               nice_udp_turn_socket_set_ms_realm(relay_cand->sockptr,
4157                   &d->stun_message);
4158               nice_udp_turn_socket_set_ms_connection_id(relay_cand->sockptr,
4159                   resp);
4160             } else {
4161               priv_add_new_turn_refresh (agent, d, relay_cand, lifetime);
4162             }
4163
4164             /* In case a new candidate has been added */
4165             conn_check_schedule_next (agent);
4166           }
4167
4168           d->stun_message.buffer = NULL;
4169           d->stun_message.buffer_len = 0;
4170           d->done = TRUE;
4171           trans_found = TRUE;
4172         } else if (res == STUN_USAGE_TURN_RETURN_ERROR) {
4173           int code = -1;
4174           uint8_t *sent_realm = NULL;
4175           uint8_t *recv_realm = NULL;
4176           uint16_t sent_realm_len = 0;
4177           uint16_t recv_realm_len = 0;
4178
4179           sent_realm = (uint8_t *) stun_message_find (&d->stun_message,
4180               STUN_ATTRIBUTE_REALM, &sent_realm_len);
4181           recv_realm = (uint8_t *) stun_message_find (resp,
4182               STUN_ATTRIBUTE_REALM, &recv_realm_len);
4183
4184           if ((agent->compatibility == NICE_COMPATIBILITY_OC2007  ||
4185               agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
4186               alternatelen != sizeof(alternate)) {
4187             NiceAddress addr;
4188
4189             nice_address_set_from_sockaddr (&addr, &alternate.addr);
4190
4191             if (!nice_address_equal (&addr, &d->server)) {
4192               priv_handle_turn_alternate_server (agent, d, d->server, addr);
4193             }
4194           }
4195           /* check for unauthorized error response */
4196           if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
4197                agent->compatibility == NICE_COMPATIBILITY_OC2007  ||
4198                agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
4199               stun_message_get_class (resp) == STUN_ERROR &&
4200               stun_message_find_error (resp, &code) ==
4201               STUN_MESSAGE_RETURN_SUCCESS &&
4202               recv_realm != NULL && recv_realm_len > 0) {
4203
4204             if (code == STUN_ERROR_STALE_NONCE ||
4205                 (code == STUN_ERROR_UNAUTHORIZED &&
4206                     !(recv_realm_len == sent_realm_len &&
4207                         sent_realm != NULL &&
4208                         memcmp (sent_realm, recv_realm, sent_realm_len) == 0))) {
4209               d->stun_resp_msg = *resp;
4210               memcpy (d->stun_resp_buffer, resp->buffer,
4211                   stun_message_length (resp));
4212               d->stun_resp_msg.buffer = d->stun_resp_buffer;
4213               d->stun_resp_msg.buffer_len = sizeof(d->stun_resp_buffer);
4214               d->pending = FALSE;
4215               agent->discovery_unsched_items++;
4216             } else {
4217               /* case: a real unauthorized error */
4218               d->stun_message.buffer = NULL;
4219               d->stun_message.buffer_len = 0;
4220               d->done = TRUE;
4221             }
4222           } else {
4223             /* case: STUN error, the check STUN context was freed */
4224             d->stun_message.buffer = NULL;
4225             d->stun_message.buffer_len = 0;
4226             d->done = TRUE;
4227           }
4228           trans_found = TRUE;
4229         }
4230       }
4231     }
4232   }
4233
4234   return trans_found;
4235 }
4236
4237
4238 /*
4239  * Tries to match STUN reply in 'buf' to an existing STUN discovery
4240  * transaction. If found, a reply is sent.
4241  * 
4242  * @return TRUE if a matching transaction is found
4243  */
4244 static gboolean priv_map_reply_to_relay_refresh (NiceAgent *agent, StunMessage *resp)
4245 {
4246   uint32_t lifetime;
4247   GSList *i;
4248   StunUsageTurnReturn res;
4249   gboolean trans_found = FALSE;
4250   StunTransactionId refresh_id;
4251   StunTransactionId response_id;
4252   stun_message_id (resp, response_id);
4253
4254   for (i = agent->refresh_list; i && trans_found != TRUE;) {
4255     CandidateRefresh *cand = i->data;
4256     GSList *next = i->next;
4257
4258     if (!cand->disposing && cand->stun_message.buffer) {
4259       stun_message_id (&cand->stun_message, refresh_id);
4260
4261       if (memcmp (refresh_id, response_id, sizeof(StunTransactionId)) == 0) {
4262         res = stun_usage_turn_refresh_process (resp,
4263             &lifetime, agent_to_turn_compatibility (agent));
4264         nice_debug ("Agent %p : stun_turn_refresh_process for %p res %d with lifetime %u.",
4265             agent, cand, (int)res, lifetime);
4266         if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS) {
4267           /* refresh should be sent 1 minute before it expires */
4268           agent_timeout_add_seconds_with_context (agent,
4269               &cand->timer_source,
4270               "Candidate TURN refresh", priv_calc_turn_timeout (lifetime),
4271               priv_turn_allocate_refresh_tick_agent_locked, cand);
4272
4273           g_source_destroy (cand->tick_source);
4274           g_source_unref (cand->tick_source);
4275           cand->tick_source = NULL;
4276           trans_found = TRUE;
4277         } else if (res == STUN_USAGE_TURN_RETURN_ERROR) {
4278           int code = -1;
4279           uint8_t *sent_realm = NULL;
4280           uint8_t *recv_realm = NULL;
4281           uint16_t sent_realm_len = 0;
4282           uint16_t recv_realm_len = 0;
4283
4284           sent_realm = (uint8_t *) stun_message_find (&cand->stun_message,
4285               STUN_ATTRIBUTE_REALM, &sent_realm_len);
4286           recv_realm = (uint8_t *) stun_message_find (resp,
4287               STUN_ATTRIBUTE_REALM, &recv_realm_len);
4288
4289           /* check for unauthorized error response */
4290           if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
4291               stun_message_get_class (resp) == STUN_ERROR &&
4292               stun_message_find_error (resp, &code) ==
4293               STUN_MESSAGE_RETURN_SUCCESS &&
4294               recv_realm != NULL && recv_realm_len > 0) {
4295
4296             if (code == STUN_ERROR_STALE_NONCE ||
4297                 (code == STUN_ERROR_UNAUTHORIZED &&
4298                     !(recv_realm_len == sent_realm_len &&
4299                         sent_realm != NULL &&
4300                         memcmp (sent_realm, recv_realm, sent_realm_len) == 0))) {
4301               cand->stun_resp_msg = *resp;
4302               memcpy (cand->stun_resp_buffer, resp->buffer,
4303                   stun_message_length (resp));
4304               cand->stun_resp_msg.buffer = cand->stun_resp_buffer;
4305               cand->stun_resp_msg.buffer_len = sizeof(cand->stun_resp_buffer);
4306               priv_turn_allocate_refresh_tick_unlocked (agent, cand);
4307             } else {
4308               /* case: a real unauthorized error */
4309               refresh_free (agent, cand);
4310             }
4311           } else {
4312             /* case: STUN error, the check STUN context was freed */
4313             refresh_free (agent, cand);
4314           }
4315           trans_found = TRUE;
4316         }
4317       }
4318     }
4319     i = next;
4320   }
4321
4322   return trans_found;
4323 }
4324
4325 static gboolean priv_map_reply_to_relay_remove (NiceAgent *agent,
4326     StunMessage *resp)
4327 {
4328   StunTransactionId response_id;
4329   GSList *i;
4330
4331   stun_message_id (resp, response_id);
4332
4333   for (i = agent->refresh_list; i; i = i->next) {
4334     CandidateRefresh *cand = i->data;
4335     StunTransactionId request_id;
4336     StunUsageTurnReturn res;
4337     uint32_t lifetime;
4338
4339     if (!cand->disposing || !cand->stun_message.buffer) {
4340       continue;
4341     }
4342
4343     stun_message_id (&cand->stun_message, request_id);
4344
4345     if (memcmp (request_id, response_id, sizeof(StunTransactionId)) == 0) {
4346       res = stun_usage_turn_refresh_process (resp, &lifetime,
4347           agent_to_turn_compatibility (agent));
4348
4349       nice_debug ("Agent %p : priv_map_reply_to_relay_remove for %p res %d "
4350           "with lifetime %u.", agent, cand, res, lifetime);
4351
4352       if (res != STUN_USAGE_TURN_RETURN_INVALID) {
4353         refresh_free (agent, cand);
4354         return TRUE;
4355       }
4356     }
4357   }
4358
4359   return FALSE;
4360 }
4361
4362 static gboolean priv_map_reply_to_keepalive_conncheck (NiceAgent *agent,
4363     NiceComponent *component, StunMessage *resp)
4364 {
4365   StunTransactionId conncheck_id;
4366   StunTransactionId response_id;
4367   stun_message_id (resp, response_id);
4368
4369   if (component->selected_pair.keepalive.stun_message.buffer) {
4370       stun_message_id (&component->selected_pair.keepalive.stun_message,
4371           conncheck_id);
4372       if (memcmp (conncheck_id, response_id, sizeof(StunTransactionId)) == 0) {
4373         nice_debug ("Agent %p : Keepalive for selected pair received.",
4374             agent);
4375         if (component->selected_pair.keepalive.tick_source) {
4376           g_source_destroy (component->selected_pair.keepalive.tick_source);
4377           g_source_unref (component->selected_pair.keepalive.tick_source);
4378           component->selected_pair.keepalive.tick_source = NULL;
4379         }
4380         component->selected_pair.keepalive.stun_message.buffer = NULL;
4381         return TRUE;
4382       }
4383   }
4384
4385   return FALSE;
4386 }
4387
4388
4389 typedef struct {
4390   NiceAgent *agent;
4391   NiceStream *stream;
4392   NiceComponent *component;
4393   uint8_t *password;
4394 } conncheck_validater_data;
4395
4396 static bool conncheck_stun_validater (StunAgent *agent,
4397     StunMessage *message, uint8_t *username, uint16_t username_len,
4398     uint8_t **password, size_t *password_len, void *user_data)
4399 {
4400   conncheck_validater_data *data = (conncheck_validater_data*) user_data;
4401   GSList *i;
4402   gchar *ufrag = NULL;
4403   gsize ufrag_len;
4404
4405   gboolean msn_msoc_nice_compatibility =
4406       data->agent->compatibility == NICE_COMPATIBILITY_MSN ||
4407       data->agent->compatibility == NICE_COMPATIBILITY_OC2007;
4408
4409   if (data->agent->compatibility == NICE_COMPATIBILITY_OC2007 &&
4410       stun_message_get_class (message) == STUN_RESPONSE)
4411     i = data->component->remote_candidates;
4412   else
4413     i = data->component->local_candidates;
4414
4415   for (; i; i = i->next) {
4416     NiceCandidate *cand = i->data;
4417
4418     ufrag = NULL;
4419     if (cand->username)
4420       ufrag = cand->username;
4421     else
4422       ufrag = data->stream->local_ufrag;
4423     ufrag_len = ufrag? strlen (ufrag) : 0;
4424
4425     if (ufrag && msn_msoc_nice_compatibility)
4426       ufrag = (gchar *)g_base64_decode (ufrag, &ufrag_len);
4427
4428     if (ufrag == NULL)
4429       continue;
4430
4431     stun_debug ("Comparing username/ufrag of len %d and %" G_GSIZE_FORMAT ", equal=%d",
4432         username_len, ufrag_len, username_len >= ufrag_len ?
4433         memcmp (username, ufrag, ufrag_len) : 0);
4434     stun_debug_bytes ("  username: ", username, username_len);
4435     stun_debug_bytes ("  ufrag:    ", ufrag, ufrag_len);
4436     if (ufrag_len > 0 && username_len >= ufrag_len &&
4437         memcmp (username, ufrag, ufrag_len) == 0) {
4438       gchar *pass = NULL;
4439
4440       if (cand->password)
4441         pass = cand->password;
4442       else if (data->stream && data->stream->local_password[0])
4443         pass = data->stream->local_password;
4444
4445       if (pass) {
4446         *password = (uint8_t *) pass;
4447         *password_len = strlen (pass);
4448
4449         if (msn_msoc_nice_compatibility) {
4450           gsize pass_len;
4451
4452           data->password = g_base64_decode (pass, &pass_len);
4453           *password = data->password;
4454           *password_len = pass_len;
4455         }
4456       }
4457
4458       if (msn_msoc_nice_compatibility)
4459         g_free (ufrag);
4460
4461       stun_debug ("Found valid username, returning password: '%s'", *password);
4462       return TRUE;
4463     }
4464
4465     if (msn_msoc_nice_compatibility)
4466       g_free (ufrag);
4467   }
4468
4469   return FALSE;
4470 }
4471
4472 /*
4473  * handle RENOMINATION stun attribute
4474  * @return TRUE if nomination changed. FALSE otherwise
4475  */
4476 static gboolean conn_check_handle_renomination (NiceAgent *agent, NiceStream *stream,
4477     NiceComponent *component, StunMessage *req,
4478     NiceCandidate *remote_candidate, NiceCandidate *local_candidate)
4479 {
4480   GSList *lst;
4481   if (!agent->controlling_mode && NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
4482       agent->support_renomination && remote_candidate && local_candidate)
4483   {
4484     uint32_t nom_value = 0;
4485     uint16_t nom_len = 0;
4486     const void *value = stun_message_find (req, STUN_ATTRIBUTE_NOMINATION, &nom_len);
4487     if (nom_len == 0) {
4488       return FALSE;
4489     }
4490     if (nom_len == 4) {
4491       memcpy (&nom_value, value, 4);
4492       nom_value = ntohl (nom_value);
4493     } else {
4494       nice_debug ("Agent %p : received NOMINATION attr with incorrect octet length %u, expected 4 bytes",
4495           agent, nom_len);
4496       return FALSE;
4497     }
4498
4499     if (nice_debug_is_enabled ()) {
4500       gchar remote_str[INET6_ADDRSTRLEN];
4501       nice_address_to_string(&remote_candidate->addr, remote_str);
4502       nice_debug ("Agent %p : received NOMINATION attr for remote candidate [%s]:%u, value is %u",
4503           agent, remote_str, nice_address_get_port (&remote_candidate->addr), nom_value);
4504     }
4505
4506     /*
4507      * If another pair is SELECTED, change this pair's priority to be greater than
4508      * selected pair's priority so this pair gets SELECTED!
4509      */
4510     if (component->selected_pair.priority &&
4511         component->selected_pair.remote && component->selected_pair.remote != remote_candidate &&
4512         component->selected_pair.local && component->selected_pair.local != local_candidate) {
4513       for (lst = stream->conncheck_list; lst; lst = lst->next) {
4514         CandidateCheckPair *pair = lst->data;
4515         if (pair->local == local_candidate && pair->remote == remote_candidate) {
4516           if (pair->valid) {
4517             pair->priority = component->selected_pair.priority + 1;
4518           }
4519           break;
4520         }
4521       }
4522     }
4523     priv_mark_pair_nominated (agent, stream, component, local_candidate, remote_candidate);
4524     return TRUE;
4525   }
4526   return FALSE;
4527 }
4528
4529 /*
4530  * Processing an incoming STUN message.
4531  *
4532  * @param agent self pointer
4533  * @param stream stream the packet is related to
4534  * @param component component the packet is related to
4535  * @param nicesock socket from which the packet was received
4536  * @param from address of the sender
4537  * @param buf message contents
4538  * @param buf message length
4539  *
4540  * @pre contents of 'buf' is a STUN message
4541  *
4542  * @return XXX (what FALSE means exactly?)
4543  */
4544 gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
4545     NiceComponent *component, NiceSocket *nicesock, const NiceAddress *from,
4546     gchar *buf, guint len)
4547 {
4548   union {
4549     struct sockaddr_storage storage;
4550     struct sockaddr addr;
4551   } sockaddr;
4552   uint8_t rbuf[MAX_STUN_DATAGRAM_PAYLOAD];
4553   ssize_t res;
4554   size_t rbuf_len = sizeof (rbuf);
4555   bool control = agent->controlling_mode;
4556   uint8_t uname[NICE_STREAM_MAX_UNAME];
4557   guint uname_len;
4558   uint8_t *username;
4559   uint16_t username_len;
4560   StunMessage req;
4561   StunMessage msg;
4562   StunValidationStatus valid;
4563   conncheck_validater_data validater_data = {agent, stream, component, NULL};
4564   GSList *i, *j;
4565   NiceCandidate *remote_candidate = NULL;
4566   NiceCandidate *remote_candidate2 = NULL;
4567   NiceCandidate *local_candidate = NULL;
4568   gboolean discovery_msg = FALSE;
4569
4570   nice_address_copy_to_sockaddr (from, &sockaddr.addr);
4571
4572   /* note: contents of 'buf' already validated, so it is
4573    *       a valid and fully received STUN message */
4574
4575   if (nice_debug_is_enabled ()) {
4576     gchar tmpbuf[INET6_ADDRSTRLEN];
4577     nice_address_to_string (from, tmpbuf);
4578     nice_debug ("Agent %p: inbound STUN packet for %u/%u (stream/component) from [%s]:%u (%u octets) :",
4579         agent, stream->id, component->id, tmpbuf, nice_address_get_port (from), len);
4580   }
4581
4582   /* note: ICE  7.2. "STUN Server Procedures" (ID-19) */
4583
4584   valid = stun_agent_validate (&component->stun_agent, &req,
4585       (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
4586
4587   /* Check for discovery candidates stun agents */
4588   if (valid == STUN_VALIDATION_BAD_REQUEST ||
4589       valid == STUN_VALIDATION_UNMATCHED_RESPONSE) {
4590     for (i = agent->discovery_list; i; i = i->next) {
4591       CandidateDiscovery *d = i->data;
4592       if (d->stream_id == stream->id && d->component_id == component->id &&
4593           d->nicesock == nicesock) {
4594         valid = stun_agent_validate (&d->stun_agent, &req,
4595             (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
4596
4597         if (valid == STUN_VALIDATION_UNMATCHED_RESPONSE)
4598           continue;
4599
4600         discovery_msg = TRUE;
4601         break;
4602       }
4603     }
4604   }
4605   /* Check for relay refresh stun agents */
4606   if (valid == STUN_VALIDATION_BAD_REQUEST ||
4607       valid == STUN_VALIDATION_UNMATCHED_RESPONSE) {
4608     for (i = agent->refresh_list; i; i = i->next) {
4609       CandidateRefresh *r = i->data;
4610
4611       nice_debug_verbose ("Comparing r.sid=%u to sid=%u, r.cid=%u to cid=%u and %p and %p to %p",
4612           r->stream_id, stream->id, r->component_id, component->id, r->nicesock,
4613           r->candidate->sockptr, nicesock);
4614
4615       if (r->stream_id == stream->id && r->component_id == component->id &&
4616           (r->nicesock == nicesock || r->candidate->sockptr == nicesock)) {
4617         valid = stun_agent_validate (&r->stun_agent, &req,
4618             (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
4619         nice_debug ("Validating gave %d", valid);
4620         if (valid == STUN_VALIDATION_UNMATCHED_RESPONSE)
4621           continue;
4622         discovery_msg = TRUE;
4623         break;
4624       }
4625     }
4626   }
4627
4628   g_free (validater_data.password);
4629
4630   if (valid == STUN_VALIDATION_NOT_STUN ||
4631       valid == STUN_VALIDATION_INCOMPLETE_STUN ||
4632       valid == STUN_VALIDATION_BAD_REQUEST)
4633   {
4634     nice_debug ("Agent %p : Incorrectly multiplexed STUN message ignored.",
4635         agent);
4636     return FALSE;
4637   }
4638
4639   if (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) {
4640     nice_debug ("Agent %p : Unknown mandatory attributes in message.", agent);
4641
4642     if (agent->compatibility != NICE_COMPATIBILITY_MSN &&
4643         agent->compatibility != NICE_COMPATIBILITY_OC2007) {
4644       rbuf_len = stun_agent_build_unknown_attributes_error (&component->stun_agent,
4645           &msg, rbuf, rbuf_len, &req);
4646       if (rbuf_len != 0)
4647         agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
4648     }
4649     return TRUE;
4650   }
4651
4652   if (valid == STUN_VALIDATION_UNAUTHORIZED) {
4653     nice_debug ("Agent %p : Integrity check failed.", agent);
4654
4655     if (stun_agent_init_error (&component->stun_agent, &msg, rbuf, rbuf_len,
4656             &req, STUN_ERROR_UNAUTHORIZED)) {
4657       rbuf_len = stun_agent_finish_message (&component->stun_agent, &msg, NULL, 0);
4658       if (rbuf_len > 0 && agent->compatibility != NICE_COMPATIBILITY_MSN &&
4659           agent->compatibility != NICE_COMPATIBILITY_OC2007)
4660         agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
4661     }
4662     return TRUE;
4663   }
4664   if (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST) {
4665     nice_debug ("Agent %p : Integrity check failed - bad request.", agent);
4666     if (stun_agent_init_error (&component->stun_agent, &msg, rbuf, rbuf_len,
4667             &req, STUN_ERROR_BAD_REQUEST)) {
4668       rbuf_len = stun_agent_finish_message (&component->stun_agent, &msg, NULL, 0);
4669       if (rbuf_len > 0 && agent->compatibility != NICE_COMPATIBILITY_MSN &&
4670           agent->compatibility != NICE_COMPATIBILITY_OC2007)
4671         agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
4672     }
4673     return TRUE;
4674   }
4675
4676   username = (uint8_t *) stun_message_find (&req, STUN_ATTRIBUTE_USERNAME,
4677                                             &username_len);
4678
4679   for (i = component->local_candidates; i; i = i->next) {
4680     NiceCandidate *cand = i->data;
4681     NiceAddress *addr;
4682
4683     if (cand->type == NICE_CANDIDATE_TYPE_RELAYED)
4684       addr = &cand->addr;
4685     else
4686       addr = &cand->base_addr;
4687
4688     if (nice_address_equal (&nicesock->addr, addr) &&
4689         local_candidate_and_socket_compatible (agent, cand, nicesock)) {
4690       local_candidate = cand;
4691       break;
4692     }
4693   }
4694
4695   for (i = component->remote_candidates; i; i = i->next) {
4696     NiceCandidate *cand = i->data;
4697     if (nice_address_equal (from, &cand->addr) &&
4698         remote_candidate_and_socket_compatible (agent, local_candidate,
4699         cand, nicesock)) {
4700       remote_candidate = cand;
4701       break;
4702     }
4703   }
4704
4705   if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
4706       agent->compatibility == NICE_COMPATIBILITY_MSN ||
4707       agent->compatibility == NICE_COMPATIBILITY_OC2007) {
4708     /* We need to find which local candidate was used */
4709     for (i = component->remote_candidates;
4710          i != NULL && remote_candidate2 == NULL; i = i->next) {
4711       for (j = component->local_candidates; j; j = j->next) {
4712         gboolean inbound = TRUE;
4713         NiceCandidate *rcand = i->data;
4714         NiceCandidate *lcand = j->data;
4715
4716         /* If we receive a response, then the username is local:remote */
4717         if (agent->compatibility != NICE_COMPATIBILITY_MSN) {
4718           if (stun_message_get_class (&req) == STUN_REQUEST ||
4719               stun_message_get_class (&req) == STUN_INDICATION) {
4720             inbound = TRUE;
4721           } else {
4722             inbound = FALSE;
4723           }
4724         }
4725
4726         uname_len = priv_create_username (agent, stream,
4727             component->id,  rcand, lcand,
4728             uname, sizeof (uname), inbound);
4729
4730
4731
4732         stun_debug ("Comparing usernames of size %d and %d: %d",
4733             username_len, uname_len, username && uname_len == username_len &&
4734             memcmp (username, uname, uname_len) == 0);
4735         stun_debug_bytes ("  First username: ", username,
4736             username ? username_len : 0);
4737         stun_debug_bytes ("  Second uname:   ", uname, uname_len);
4738
4739         if (username &&
4740             uname_len == username_len &&
4741             memcmp (uname, username, username_len) == 0) {
4742           local_candidate = lcand;
4743           remote_candidate2 = rcand;
4744           break;
4745         }
4746       }
4747     }
4748   }
4749
4750   if (component->remote_candidates &&
4751       agent->compatibility == NICE_COMPATIBILITY_GOOGLE &&
4752       local_candidate == NULL &&
4753       discovery_msg == FALSE) {
4754     /* if we couldn't match the username and the stun agent has
4755        IGNORE_CREDENTIALS then we have an integrity check failing.
4756        This could happen with the race condition of receiving connchecks
4757        before the remote candidates are added. Just drop the message, and let
4758        the retransmissions make it work. */
4759     nice_debug ("Agent %p : Username check failed.", agent);
4760     return TRUE;
4761   }
4762
4763   /* This is most likely caused by a second response to a request which
4764    * already has received a valid reply.
4765    */
4766   if (valid == STUN_VALIDATION_UNMATCHED_RESPONSE) {
4767     nice_debug ("Agent %p : Valid STUN response for which we don't have a request, ignoring", agent);
4768     return TRUE;
4769   }
4770
4771   if (valid != STUN_VALIDATION_SUCCESS) {
4772     nice_debug ("Agent %p : STUN message is unsuccessful %d, ignoring", agent, valid);
4773     return FALSE;
4774   }
4775
4776
4777   if (stun_message_get_class (&req) == STUN_REQUEST) {
4778     if (   agent->compatibility == NICE_COMPATIBILITY_MSN
4779         || agent->compatibility == NICE_COMPATIBILITY_OC2007) {
4780       if (local_candidate && remote_candidate2) {
4781         gsize key_len;
4782
4783         if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
4784           username = (uint8_t *) stun_message_find (&req,
4785           STUN_ATTRIBUTE_USERNAME, &username_len);
4786           uname_len = priv_create_username (agent, stream,
4787               component->id,  remote_candidate2, local_candidate,
4788               uname, sizeof (uname), FALSE);
4789           memcpy (username, uname, MIN (uname_len, username_len));
4790
4791           req.key = g_base64_decode ((gchar *) remote_candidate2->password,
4792               &key_len);
4793           req.key_len = key_len;
4794         } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007) {
4795           req.key = g_base64_decode ((gchar *) local_candidate->password,
4796               &key_len);
4797           req.key_len = key_len;
4798         }
4799       } else {
4800         nice_debug ("Agent %p : received MSN incoming check from unknown remote candidate. "
4801             "Ignoring request", agent);
4802         return TRUE;
4803       }
4804     }
4805
4806     rbuf_len = sizeof (rbuf);
4807     res = stun_usage_ice_conncheck_create_reply (&component->stun_agent, &req,
4808         &msg, rbuf, &rbuf_len, &sockaddr.storage, sizeof (sockaddr),
4809         &control, agent->tie_breaker,
4810         agent_to_ice_compatibility (agent));
4811
4812     if (   agent->compatibility == NICE_COMPATIBILITY_MSN
4813         || agent->compatibility == NICE_COMPATIBILITY_OC2007) {
4814       g_free (req.key);
4815     }
4816
4817     if (res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT)
4818       priv_check_for_role_conflict (agent, control);
4819
4820     if (res == STUN_USAGE_ICE_RETURN_SUCCESS ||
4821         res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT) {
4822       /* case 1: valid incoming request, send a reply/error */
4823       bool use_candidate =
4824           stun_usage_ice_conncheck_use_candidate (&req);
4825       uint32_t priority = stun_usage_ice_conncheck_priority (&req);
4826
4827       if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
4828           agent->compatibility == NICE_COMPATIBILITY_MSN ||
4829           agent->compatibility == NICE_COMPATIBILITY_OC2007)
4830         use_candidate = TRUE;
4831
4832       if (stream->initial_binding_request_received != TRUE)
4833         agent_signal_initial_binding_request_received (agent, stream);
4834
4835       if (remote_candidate == NULL) {
4836         nice_debug ("Agent %p : No matching remote candidate for incoming "
4837             "check -> peer-reflexive candidate.", agent);
4838         remote_candidate = discovery_learn_remote_peer_reflexive_candidate (
4839             agent, stream, component, priority, from, nicesock,
4840             local_candidate,
4841             remote_candidate2 ? remote_candidate2 : remote_candidate);
4842         if(remote_candidate && stream->remote_ufrag[0]) {
4843           if (local_candidate &&
4844               local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
4845             CandidateCheckPair *pair;
4846
4847             pair = priv_conn_check_add_for_candidate_pair_matched (agent,
4848                 stream->id, component, local_candidate, remote_candidate,
4849                 NICE_CHECK_SUCCEEDED);
4850             if (pair) {
4851               pair->valid = TRUE;
4852             }
4853           } else
4854             conn_check_add_for_candidate (agent, stream->id, component, remote_candidate);
4855         }
4856       }
4857
4858       nice_component_add_valid_candidate (agent, component, remote_candidate);
4859
4860       priv_reply_to_conn_check (agent, stream, component, local_candidate,
4861           remote_candidate, from, nicesock, rbuf_len, &msg, use_candidate);
4862
4863       if (stream->remote_ufrag[0] == 0) {
4864         /* case: We've got a valid binding request to a local candidate
4865          *       but we do not yet know remote credentials.
4866          *       As per sect 7.2 of ICE (ID-19), we send a reply
4867          *       immediately but postpone all other processing until
4868          *       we get information about the remote candidates */
4869
4870         /* step: send a reply immediately but postpone other processing */
4871         priv_store_pending_check (agent, component, from, nicesock,
4872             username, username_len, priority, use_candidate);
4873         priv_print_conn_check_lists (agent, G_STRFUNC, ", icheck stored");
4874       }
4875     } else {
4876       nice_debug ("Agent %p : Invalid STUN packet, ignoring... %s",
4877           agent, strerror(errno));
4878       return FALSE;
4879     }
4880   } else {
4881       /* case 2: not a new request, might be a reply...  */
4882       gboolean trans_found = FALSE;
4883
4884       /* note: ICE sect 7.1.2. "Processing the Response" (ID-19) */
4885
4886       /* step: let's try to match the response to an existing check context */
4887       if (trans_found != TRUE)
4888         trans_found = priv_map_reply_to_conn_check_request (agent, stream,
4889             component, nicesock, from, local_candidate, remote_candidate, &req);
4890
4891       /* step: let's try to match the response to an existing discovery */
4892       if (trans_found != TRUE)
4893         trans_found = priv_map_reply_to_discovery_request (agent, &req);
4894
4895       /* step: let's try to match the response to an existing turn allocate */
4896       if (trans_found != TRUE)
4897         trans_found = priv_map_reply_to_relay_request (agent, &req);
4898
4899       /* step: let's try to match the response to an existing turn refresh */
4900       if (trans_found != TRUE)
4901         trans_found = priv_map_reply_to_relay_refresh (agent, &req);
4902
4903       if (trans_found != TRUE)
4904         trans_found = priv_map_reply_to_relay_remove (agent, &req);
4905
4906       /* step: let's try to match the response to an existing keepalive conncheck */
4907       if (trans_found != TRUE)
4908         trans_found = priv_map_reply_to_keepalive_conncheck (agent, component,
4909             &req);
4910
4911       if (trans_found != TRUE)
4912         nice_debug ("Agent %p : Unable to match to an existing transaction, "
4913             "probably a keepalive.", agent);
4914   }
4915
4916   /* RENOMINATION attribute support */
4917   conn_check_handle_renomination(agent, stream, component, &req, remote_candidate, local_candidate);
4918
4919   return TRUE;
4920 }
4921
4922 /* Remove all pointers to the given @sock from the connection checking process.
4923  * These are entirely NiceCandidates pointed to from various places. */
4924 void
4925 conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *component,
4926     NiceSocket *sock)
4927 {
4928   GSList *l;
4929
4930   if (component->selected_pair.local &&
4931       component->selected_pair.local->sockptr == sock &&
4932       component->state == NICE_COMPONENT_STATE_READY) {
4933     nice_debug ("Agent %p: Selected pair socket %p has been destroyed, "
4934         "declaring failed", agent, sock);
4935     agent_signal_component_state_change (agent,
4936         stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
4937   }
4938
4939   /* Prune from the candidate check pairs. */
4940   for (l = stream->conncheck_list; l != NULL;) {
4941     CandidateCheckPair *p = l->data;
4942     GSList *next = l->next;
4943
4944     if ((p->local != NULL && p->local->sockptr == sock) ||
4945         (p->remote != NULL && p->remote->sockptr == sock) ||
4946         (p->sockptr == sock)) {
4947       nice_debug ("Agent %p : Retransmissions failed, giving up on pair %p",
4948           agent, p);
4949       candidate_check_pair_fail (stream, agent, p);
4950       candidate_check_pair_free (agent, p);
4951       stream->conncheck_list = g_slist_delete_link (stream->conncheck_list, l);
4952     }
4953
4954     l = next;
4955   }
4956 }