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