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