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