Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjnath / src / pjnath / ice_session.c
1 /* $Id$ */
2 /* 
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19  */
20 #include <pjnath/ice_session.h>
21 #include <pj/addr_resolv.h>
22 #include <pj/array.h>
23 #include <pj/assert.h>
24 #include <pj/guid.h>
25 #include <pj/hash.h>
26 #include <pj/log.h>
27 #include <pj/os.h>
28 #include <pj/pool.h>
29 #include <pj/rand.h>
30 #include <pj/string.h>
31
32 /* String names for candidate types */
33 static const char *cand_type_names[] =
34 {
35     "host",
36     "srflx",
37     "prflx",
38     "relay"
39
40 };
41
42 /* String names for pj_ice_sess_check_state */
43 #if PJ_LOG_MAX_LEVEL >= 4
44 static const char *check_state_name[] = 
45 {
46     "Frozen",
47     "Waiting",
48     "In Progress",
49     "Succeeded",
50     "Failed"
51 };
52
53 static const char *clist_state_name[] =
54 {
55     "Idle",
56     "Running",
57     "Completed"
58 };
59 #endif  /* PJ_LOG_MAX_LEVEL >= 4 */
60
61 static const char *role_names[] = 
62 {
63     "Unknown",
64     "Controlled",
65     "Controlling"
66 };
67
68 enum timer_type
69 {
70     TIMER_NONE,                 /**< Timer not active                   */
71     TIMER_COMPLETION_CALLBACK,  /**< Call on_ice_complete() callback    */
72     TIMER_CONTROLLED_WAIT_NOM,  /**< Controlled agent is waiting for 
73                                      controlling agent to send connectivity
74                                      check with nominated flag after it has
75                                      valid check for every components.  */
76     TIMER_START_NOMINATED_CHECK,/**< Controlling agent start connectivity
77                                      checks with USE-CANDIDATE flag.    */
78     TIMER_KEEP_ALIVE            /**< ICE keep-alive timer.              */
79
80 };
81
82 /* Candidate type preference */
83 static pj_uint8_t cand_type_prefs[4] =
84 {
85 #if PJ_ICE_CAND_TYPE_PREF_BITS < 8
86     /* Keep it to 2 bits */
87     3,      /**< PJ_ICE_HOST_PREF       */
88     1,      /**< PJ_ICE_SRFLX_PREF.     */
89     2,      /**< PJ_ICE_PRFLX_PREF      */
90     0       /**< PJ_ICE_RELAYED_PREF    */
91 #else
92     /* Default ICE session preferences, according to draft-ice */
93     126,    /**< PJ_ICE_HOST_PREF       */
94     100,    /**< PJ_ICE_SRFLX_PREF.     */
95     110,    /**< PJ_ICE_PRFLX_PREF      */
96     0       /**< PJ_ICE_RELAYED_PREF    */
97 #endif
98 };
99
100 #define CHECK_NAME_LEN          128
101 #define LOG4(expr)              PJ_LOG(4,expr)
102 #define LOG5(expr)              PJ_LOG(4,expr)
103 #define GET_LCAND_ID(cand)      (cand - ice->lcand)
104 #define GET_CHECK_ID(cl, chk)   (chk - (cl)->checks)
105
106
107 /* The data that will be attached to the STUN session on each
108  * component.
109  */
110 typedef struct stun_data
111 {
112     pj_ice_sess         *ice;
113     unsigned             comp_id;
114     pj_ice_sess_comp    *comp;
115 } stun_data;
116
117
118 /* The data that will be attached to the timer to perform
119  * periodic check.
120  */
121 typedef struct timer_data
122 {
123     pj_ice_sess             *ice;
124     pj_ice_sess_checklist   *clist;
125 } timer_data;
126
127
128 /* This is the data that will be attached as token to outgoing
129  * STUN messages.
130  */
131
132
133 /* Forward declarations */
134 static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te);
135 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status);
136 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now);
137 static void destroy_ice(pj_ice_sess *ice,
138                         pj_status_t reason);
139 static pj_status_t start_periodic_check(pj_timer_heap_t *th, 
140                                         pj_timer_entry *te);
141 static void start_nominated_check(pj_ice_sess *ice);
142 static void periodic_timer(pj_timer_heap_t *th, 
143                           pj_timer_entry *te);
144 static void handle_incoming_check(pj_ice_sess *ice,
145                                   const pj_ice_rx_check *rcheck);
146
147 /* These are the callbacks registered to the STUN sessions */
148 static pj_status_t on_stun_send_msg(pj_stun_session *sess,
149                                     void *token,
150                                     const void *pkt,
151                                     pj_size_t pkt_size,
152                                     const pj_sockaddr_t *dst_addr,
153                                     unsigned addr_len);
154 static pj_status_t on_stun_rx_request(pj_stun_session *sess,
155                                       const pj_uint8_t *pkt,
156                                       unsigned pkt_len,
157                                       const pj_stun_rx_data *rdata,
158                                       void *token,
159                                       const pj_sockaddr_t *src_addr,
160                                       unsigned src_addr_len);
161 static void on_stun_request_complete(pj_stun_session *stun_sess,
162                                      pj_status_t status,
163                                      void *token,
164                                      pj_stun_tx_data *tdata,
165                                      const pj_stun_msg *response,
166                                      const pj_sockaddr_t *src_addr,
167                                      unsigned src_addr_len);
168 static pj_status_t on_stun_rx_indication(pj_stun_session *sess,
169                                          const pj_uint8_t *pkt,
170                                          unsigned pkt_len,
171                                          const pj_stun_msg *msg,
172                                          void *token,
173                                          const pj_sockaddr_t *src_addr,
174                                          unsigned src_addr_len);
175
176 /* These are the callbacks for performing STUN authentication */
177 static pj_status_t stun_auth_get_auth(void *user_data,
178                                       pj_pool_t *pool,
179                                       pj_str_t *realm,
180                                       pj_str_t *nonce);
181 static pj_status_t stun_auth_get_cred(const pj_stun_msg *msg,
182                                       void *user_data,
183                                       pj_pool_t *pool,
184                                       pj_str_t *realm,
185                                       pj_str_t *username,
186                                       pj_str_t *nonce,
187                                       pj_stun_passwd_type *data_type,
188                                       pj_str_t *data);
189 static pj_status_t stun_auth_get_password(const pj_stun_msg *msg,
190                                           void *user_data, 
191                                           const pj_str_t *realm,
192                                           const pj_str_t *username,
193                                           pj_pool_t *pool,
194                                           pj_stun_passwd_type *data_type,
195                                           pj_str_t *data);
196
197
198 PJ_DEF(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type)
199 {
200     PJ_ASSERT_RETURN(type <= PJ_ICE_CAND_TYPE_RELAYED, "???");
201     return cand_type_names[type];
202 }
203
204
205 PJ_DEF(const char*) pj_ice_sess_role_name(pj_ice_sess_role role)
206 {
207     switch (role) {
208     case PJ_ICE_SESS_ROLE_UNKNOWN:
209         return "Unknown";
210     case PJ_ICE_SESS_ROLE_CONTROLLED:
211         return "Controlled";
212     case PJ_ICE_SESS_ROLE_CONTROLLING:
213         return "Controlling";
214     default:
215         return "??";
216     }
217 }
218
219
220 /* Get the prefix for the foundation */
221 static int get_type_prefix(pj_ice_cand_type type)
222 {
223     switch (type) {
224     case PJ_ICE_CAND_TYPE_HOST:     return 'H';
225     case PJ_ICE_CAND_TYPE_SRFLX:    return 'S';
226     case PJ_ICE_CAND_TYPE_PRFLX:    return 'P';
227     case PJ_ICE_CAND_TYPE_RELAYED:  return 'R';
228     default:
229         pj_assert(!"Invalid type");
230         return 'U';
231     }
232 }
233
234 /* Calculate foundation:
235  * Two candidates have the same foundation when they are "similar" - of
236  * the same type and obtained from the same host candidate and STUN
237  * server using the same protocol.  Otherwise, their foundation is
238  * different.
239  */
240 PJ_DEF(void) pj_ice_calc_foundation(pj_pool_t *pool,
241                                     pj_str_t *foundation,
242                                     pj_ice_cand_type type,
243                                     const pj_sockaddr *base_addr)
244 {
245 #if PJNATH_ICE_PRIO_STD
246     char buf[64];
247     pj_uint32_t val;
248
249     if (base_addr->addr.sa_family == pj_AF_INET()) {
250         val = pj_ntohl(base_addr->ipv4.sin_addr.s_addr);
251     } else {
252         val = pj_hash_calc(0, pj_sockaddr_get_addr(base_addr),
253                            pj_sockaddr_get_addr_len(base_addr));
254     }
255     pj_ansi_snprintf(buf, sizeof(buf), "%c%x",
256                      get_type_prefix(type), val);
257     pj_strdup2(pool, foundation, buf);
258 #else
259     /* Much shorter version, valid for candidates added by
260      * pj_ice_strans.
261      */
262     foundation->ptr = (char*) pj_pool_alloc(pool, 1);
263     *foundation->ptr = (char)get_type_prefix(type);
264     foundation->slen = 1;
265
266     PJ_UNUSED_ARG(base_addr);
267 #endif
268 }
269
270
271 /* Init component */
272 static pj_status_t init_comp(pj_ice_sess *ice,
273                              unsigned comp_id,
274                              pj_ice_sess_comp *comp)
275 {
276     pj_stun_session_cb sess_cb;
277     pj_stun_auth_cred auth_cred;
278     stun_data *sd;
279     pj_status_t status;
280
281     /* Init STUN callbacks */
282     pj_bzero(&sess_cb, sizeof(sess_cb));
283     sess_cb.on_request_complete = &on_stun_request_complete;
284     sess_cb.on_rx_indication = &on_stun_rx_indication;
285     sess_cb.on_rx_request = &on_stun_rx_request;
286     sess_cb.on_send_msg = &on_stun_send_msg;
287
288     /* Create STUN session for this candidate */
289     status = pj_stun_session_create(&ice->stun_cfg, NULL, 
290                                     &sess_cb, PJ_TRUE,
291                                     &comp->stun_sess);
292     if (status != PJ_SUCCESS)
293         return status;
294
295     /* Associate data with this STUN session */
296     sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data);
297     sd->ice = ice;
298     sd->comp_id = comp_id;
299     sd->comp = comp;
300     pj_stun_session_set_user_data(comp->stun_sess, sd);
301
302     /* Init STUN authentication credential */
303     pj_bzero(&auth_cred, sizeof(auth_cred));
304     auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC;
305     auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth;
306     auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred;
307     auth_cred.data.dyn_cred.get_password = &stun_auth_get_password;
308     auth_cred.data.dyn_cred.user_data = comp->stun_sess;
309     pj_stun_session_set_credential(comp->stun_sess, PJ_STUN_AUTH_SHORT_TERM,
310                                    &auth_cred);
311
312     return PJ_SUCCESS;
313 }
314
315
316 /* Init options with default values */
317 PJ_DEF(void) pj_ice_sess_options_default(pj_ice_sess_options *opt)
318 {
319     opt->aggressive = PJ_TRUE;
320     opt->nominated_check_delay = PJ_ICE_NOMINATED_CHECK_DELAY;
321     opt->controlled_agent_want_nom_timeout = 
322         ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT;
323 }
324
325 /*
326  * Create ICE session.
327  */
328 PJ_DEF(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg,
329                                        const char *name,
330                                        pj_ice_sess_role role,
331                                        unsigned comp_cnt,
332                                        const pj_ice_sess_cb *cb,
333                                        const pj_str_t *local_ufrag,
334                                        const pj_str_t *local_passwd,
335                                        pj_ice_sess **p_ice)
336 {
337     pj_pool_t *pool;
338     pj_ice_sess *ice;
339     unsigned i;
340     pj_status_t status;
341
342     PJ_ASSERT_RETURN(stun_cfg && cb && p_ice, PJ_EINVAL);
343
344     if (name == NULL)
345         name = "icess%p";
346
347     pool = pj_pool_create(stun_cfg->pf, name, PJNATH_POOL_LEN_ICE_SESS, 
348                           PJNATH_POOL_INC_ICE_SESS, NULL);
349     ice = PJ_POOL_ZALLOC_T(pool, pj_ice_sess);
350     ice->pool = pool;
351     ice->role = role;
352     ice->tie_breaker.u32.hi = pj_rand();
353     ice->tie_breaker.u32.lo = pj_rand();
354     ice->prefs = cand_type_prefs;
355     pj_ice_sess_options_default(&ice->opt);
356
357     pj_timer_entry_init(&ice->timer, TIMER_NONE, (void*)ice, &on_timer);
358
359     pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name),
360                      name, ice);
361
362     status = pj_mutex_create_recursive(pool, ice->obj_name, 
363                                        &ice->mutex);
364     if (status != PJ_SUCCESS) {
365         destroy_ice(ice, status);
366         return status;
367     }
368
369     pj_memcpy(&ice->cb, cb, sizeof(*cb));
370     pj_memcpy(&ice->stun_cfg, stun_cfg, sizeof(*stun_cfg));
371
372     ice->comp_cnt = comp_cnt;
373     for (i=0; i<comp_cnt; ++i) {
374         pj_ice_sess_comp *comp;
375         comp = &ice->comp[i];
376         comp->valid_check = NULL;
377         comp->nominated_check = NULL;
378
379         status = init_comp(ice, i+1, comp);
380         if (status != PJ_SUCCESS) {
381             destroy_ice(ice, status);
382             return status;
383         }
384     }
385
386     /* Initialize transport datas */
387     for (i=0; i<PJ_ARRAY_SIZE(ice->tp_data); ++i) {
388         ice->tp_data[i].transport_id = i;
389         ice->tp_data[i].has_req_data = PJ_FALSE;
390     }
391
392     if (local_ufrag == NULL) {
393         ice->rx_ufrag.ptr = (char*) pj_pool_alloc(ice->pool, PJ_ICE_UFRAG_LEN);
394         pj_create_random_string(ice->rx_ufrag.ptr, PJ_ICE_UFRAG_LEN);
395         ice->rx_ufrag.slen = PJ_ICE_UFRAG_LEN;
396     } else {
397         pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag);
398     }
399
400     if (local_passwd == NULL) {
401         ice->rx_pass.ptr = (char*) pj_pool_alloc(ice->pool, PJ_ICE_UFRAG_LEN);
402         pj_create_random_string(ice->rx_pass.ptr, PJ_ICE_UFRAG_LEN);
403         ice->rx_pass.slen = PJ_ICE_UFRAG_LEN;
404     } else {
405         pj_strdup(ice->pool, &ice->rx_pass, local_passwd);
406     }
407
408     pj_list_init(&ice->early_check);
409
410     /* Done */
411     *p_ice = ice;
412
413     LOG4((ice->obj_name, 
414          "ICE session created, comp_cnt=%d, role is %s agent",
415          comp_cnt, role_names[ice->role]));
416
417     return PJ_SUCCESS;
418 }
419
420
421 /*
422  * Get the value of various options of the ICE session.
423  */
424 PJ_DEF(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice,
425                                             pj_ice_sess_options *opt)
426 {
427     PJ_ASSERT_RETURN(ice, PJ_EINVAL);
428     pj_memcpy(opt, &ice->opt, sizeof(*opt));
429     return PJ_SUCCESS;
430 }
431
432 /*
433  * Specify various options for this ICE session.
434  */
435 PJ_DEF(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice,
436                                             const pj_ice_sess_options *opt)
437 {
438     PJ_ASSERT_RETURN(ice && opt, PJ_EINVAL);
439     pj_memcpy(&ice->opt, opt, sizeof(*opt));
440     LOG5((ice->obj_name, "ICE nomination type set to %s",
441           (ice->opt.aggressive ? "aggressive" : "regular")));
442     return PJ_SUCCESS;
443 }
444
445
446 /*
447  * Destroy
448  */
449 static void destroy_ice(pj_ice_sess *ice,
450                         pj_status_t reason)
451 {
452     unsigned i;
453
454     if (reason == PJ_SUCCESS) {
455         LOG4((ice->obj_name, "Destroying ICE session"));
456     }
457
458     /* Let other callbacks finish */
459     if (ice->mutex) {
460         pj_mutex_lock(ice->mutex);
461         pj_mutex_unlock(ice->mutex);
462     }
463
464     if (ice->timer.id) {
465         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, 
466                              &ice->timer);
467         ice->timer.id = PJ_FALSE;
468     }
469
470     for (i=0; i<ice->comp_cnt; ++i) {
471         if (ice->comp[i].stun_sess) {
472             pj_stun_session_destroy(ice->comp[i].stun_sess);
473             ice->comp[i].stun_sess = NULL;
474         }
475     }
476
477     if (ice->clist.timer.id) {
478         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer);
479         ice->clist.timer.id = PJ_FALSE;
480     }
481
482     if (ice->mutex) {
483         pj_mutex_destroy(ice->mutex);
484         ice->mutex = NULL;
485     }
486
487     if (ice->pool) {
488         pj_pool_t *pool = ice->pool;
489         ice->pool = NULL;
490         pj_pool_release(pool);
491     }
492 }
493
494
495 /*
496  * Destroy
497  */
498 PJ_DEF(pj_status_t) pj_ice_sess_destroy(pj_ice_sess *ice)
499 {
500     PJ_ASSERT_RETURN(ice, PJ_EINVAL);
501     destroy_ice(ice, PJ_SUCCESS);
502     return PJ_SUCCESS;
503 }
504
505
506 /*
507  * Change session role. 
508  */
509 PJ_DEF(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice,
510                                             pj_ice_sess_role new_role)
511 {
512     PJ_ASSERT_RETURN(ice, PJ_EINVAL);
513
514     if (new_role != ice->role) {
515         ice->role = new_role;
516         LOG4((ice->obj_name, "Role changed to %s", role_names[new_role]));
517     }
518
519     return PJ_SUCCESS;
520 }
521
522
523 /*
524  * Change type preference
525  */
526 PJ_DEF(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice,
527                                           const pj_uint8_t prefs[4])
528 {
529     unsigned i;
530     PJ_ASSERT_RETURN(ice && prefs, PJ_EINVAL);
531     ice->prefs = (pj_uint8_t*) pj_pool_calloc(ice->pool, PJ_ARRAY_SIZE(prefs),
532                                               sizeof(pj_uint8_t));
533     for (i=0; i<4; ++i) {
534 #if PJ_ICE_CAND_TYPE_PREF_BITS < 8
535         pj_assert(prefs[i] < (2 << PJ_ICE_CAND_TYPE_PREF_BITS));
536 #endif
537         ice->prefs[i] = prefs[i];
538     }
539     return PJ_SUCCESS;
540 }
541
542
543 /* Find component by ID */
544 static pj_ice_sess_comp *find_comp(const pj_ice_sess *ice, unsigned comp_id)
545 {
546     pj_assert(comp_id > 0 && comp_id <= ice->comp_cnt);
547     return (pj_ice_sess_comp*) &ice->comp[comp_id-1];
548 }
549
550
551 /* Callback by STUN authentication when it needs to send 401 */
552 static pj_status_t stun_auth_get_auth(void *user_data,
553                                       pj_pool_t *pool,
554                                       pj_str_t *realm,
555                                       pj_str_t *nonce)
556 {
557     PJ_UNUSED_ARG(user_data);
558     PJ_UNUSED_ARG(pool);
559
560     realm->slen = 0;
561     nonce->slen = 0;
562
563     return PJ_SUCCESS;
564 }
565
566
567 /* Get credential to be sent with outgoing message */
568 static pj_status_t stun_auth_get_cred(const pj_stun_msg *msg,
569                                       void *user_data,
570                                       pj_pool_t *pool,
571                                       pj_str_t *realm,
572                                       pj_str_t *username,
573                                       pj_str_t *nonce,
574                                       pj_stun_passwd_type *data_type,
575                                       pj_str_t *data)
576 {
577     pj_stun_session *sess = (pj_stun_session *)user_data;
578     stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess);
579     pj_ice_sess *ice = sd->ice;
580
581     PJ_UNUSED_ARG(pool);
582     realm->slen = nonce->slen = 0;
583
584     if (PJ_STUN_IS_RESPONSE(msg->hdr.type)) {
585         /* Outgoing responses need to have the same credential as
586          * incoming requests.
587          */
588         *username = ice->rx_uname;
589         *data_type = PJ_STUN_PASSWD_PLAIN;
590         *data = ice->rx_pass;
591     }
592     else {
593         *username = ice->tx_uname;
594         *data_type = PJ_STUN_PASSWD_PLAIN;
595         *data = ice->tx_pass;
596     }
597
598     return PJ_SUCCESS;
599 }
600
601 /* Get password to be used to authenticate incoming message */
602 static pj_status_t stun_auth_get_password(const pj_stun_msg *msg,
603                                           void *user_data, 
604                                           const pj_str_t *realm,
605                                           const pj_str_t *username,
606                                           pj_pool_t *pool,
607                                           pj_stun_passwd_type *data_type,
608                                           pj_str_t *data)
609 {
610     pj_stun_session *sess = (pj_stun_session *)user_data;
611     stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess);
612     pj_ice_sess *ice = sd->ice;
613
614     PJ_UNUSED_ARG(realm);
615     PJ_UNUSED_ARG(pool);
616
617     if (PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) ||
618         PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))
619     {
620         /* Incoming response is authenticated with TX credential */
621         /* Verify username */
622         if (pj_strcmp(username, &ice->tx_uname) != 0)
623             return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED);
624         *data_type = PJ_STUN_PASSWD_PLAIN;
625         *data = ice->tx_pass;
626
627     } else {
628         /* Incoming request is authenticated with RX credential */
629         /* The agent MUST accept a credential if the username consists
630          * of two values separated by a colon, where the first value is
631          * equal to the username fragment generated by the agent in an offer
632          * or answer for a session in-progress, and the MESSAGE-INTEGRITY 
633          * is the output of a hash of the password and the STUN packet's 
634          * contents.
635          */
636         const char *pos;
637         pj_str_t ufrag;
638
639         pos = (const char*)pj_memchr(username->ptr, ':', username->slen);
640         if (pos == NULL)
641             return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED);
642
643         ufrag.ptr = (char*)username->ptr;
644         ufrag.slen = (pos - username->ptr);
645
646         if (pj_strcmp(&ufrag, &ice->rx_ufrag) != 0)
647             return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNAUTHORIZED);
648
649         *data_type = PJ_STUN_PASSWD_PLAIN;
650         *data = ice->rx_pass;
651
652     }
653
654     return PJ_SUCCESS;
655 }
656
657
658 static pj_uint32_t CALC_CAND_PRIO(pj_ice_sess *ice,
659                                   pj_ice_cand_type type,
660                                   pj_uint32_t local_pref,
661                                   pj_uint32_t comp_id)
662 {
663 #if PJNATH_ICE_PRIO_STD
664     return ((ice->prefs[type] & 0xFF) << 24) + 
665            ((local_pref & 0xFFFF)    << 8) +
666            (((256 - comp_id) & 0xFF) << 0);
667 #else
668     enum {
669         type_mask   = ((2 << PJ_ICE_CAND_TYPE_PREF_BITS) - 1),
670         local_mask  = ((2 << PJ_ICE_LOCAL_PREF_BITS) - 1),
671         comp_mask   = ((2 << PJ_ICE_COMP_BITS) - 1),
672
673         comp_shift  = 0,
674         local_shift = (PJ_ICE_COMP_BITS),
675         type_shift  = (comp_shift + local_shift),
676
677         max_comp    = (2<<PJ_ICE_COMP_BITS),
678     };
679
680     return ((ice->prefs[type] & type_mask) << type_shift) + 
681            ((local_pref & local_mask) << local_shift) +
682            (((max_comp - comp_id) & comp_mask) << comp_shift);
683 #endif
684 }
685
686
687 /*
688  * Add ICE candidate
689  */
690 PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice,
691                                          unsigned comp_id,
692                                          unsigned transport_id,
693                                          pj_ice_cand_type type,
694                                          pj_uint16_t local_pref,
695                                          const pj_str_t *foundation,
696                                          const pj_sockaddr_t *addr,
697                                          const pj_sockaddr_t *base_addr,
698                                          const pj_sockaddr_t *rel_addr,
699                                          int addr_len,
700                                          unsigned *p_cand_id)
701 {
702     pj_ice_sess_cand *lcand;
703     pj_status_t status = PJ_SUCCESS;
704
705     PJ_ASSERT_RETURN(ice && comp_id && 
706                      foundation && addr && base_addr && addr_len,
707                      PJ_EINVAL);
708     PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL);
709
710     pj_mutex_lock(ice->mutex);
711
712     if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) {
713         status = PJ_ETOOMANY;
714         goto on_error;
715     }
716
717     lcand = &ice->lcand[ice->lcand_cnt];
718     lcand->comp_id = (pj_uint8_t)comp_id;
719     lcand->transport_id = (pj_uint8_t)transport_id;
720     lcand->type = type;
721     pj_strdup(ice->pool, &lcand->foundation, foundation);
722     lcand->prio = CALC_CAND_PRIO(ice, type, local_pref, lcand->comp_id);
723     pj_memcpy(&lcand->addr, addr, addr_len);
724     pj_memcpy(&lcand->base_addr, base_addr, addr_len);
725     if (rel_addr == NULL)
726         rel_addr = base_addr;
727     pj_memcpy(&lcand->rel_addr, rel_addr, addr_len);
728
729     pj_ansi_strcpy(ice->tmp.txt, pj_inet_ntoa(lcand->addr.ipv4.sin_addr));
730     LOG4((ice->obj_name, 
731          "Candidate %d added: comp_id=%d, type=%s, foundation=%.*s, "
732          "addr=%s:%d, base=%s:%d, prio=0x%x (%u)",
733          ice->lcand_cnt, 
734          lcand->comp_id, 
735          cand_type_names[lcand->type],
736          (int)lcand->foundation.slen,
737          lcand->foundation.ptr,
738          ice->tmp.txt, 
739          (int)pj_ntohs(lcand->addr.ipv4.sin_port),
740          pj_inet_ntoa(lcand->base_addr.ipv4.sin_addr),
741          (int)pj_htons(lcand->base_addr.ipv4.sin_port),
742          lcand->prio, lcand->prio));
743
744     if (p_cand_id)
745         *p_cand_id = ice->lcand_cnt;
746
747     ++ice->lcand_cnt;
748
749 on_error:
750     pj_mutex_unlock(ice->mutex);
751     return status;
752 }
753
754
755 /* Find default candidate ID for the component */
756 PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice,
757                                                   unsigned comp_id,
758                                                   int *cand_id)
759 {
760     unsigned i;
761
762     PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL);
763     PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL);
764
765     *cand_id = -1;
766
767     pj_mutex_lock(ice->mutex);
768
769     /* First find in valid list if we have nominated pair */
770     for (i=0; i<ice->valid_list.count; ++i) {
771         pj_ice_sess_check *check = &ice->valid_list.checks[i];
772         
773         if (check->lcand->comp_id == comp_id) {
774             *cand_id = GET_LCAND_ID(check->lcand);
775             pj_mutex_unlock(ice->mutex);
776             return PJ_SUCCESS;
777         }
778     }
779
780     /* If there's no nominated pair, find relayed candidate */
781     for (i=0; i<ice->lcand_cnt; ++i) {
782         pj_ice_sess_cand *lcand = &ice->lcand[i];
783         if (lcand->comp_id==comp_id &&
784             lcand->type == PJ_ICE_CAND_TYPE_RELAYED) 
785         {
786             *cand_id = GET_LCAND_ID(lcand);
787             pj_mutex_unlock(ice->mutex);
788             return PJ_SUCCESS;
789         }
790     }
791
792     /* If there's no relayed candidate, find reflexive candidate */
793     for (i=0; i<ice->lcand_cnt; ++i) {
794         pj_ice_sess_cand *lcand = &ice->lcand[i];
795         if (lcand->comp_id==comp_id &&
796             (lcand->type == PJ_ICE_CAND_TYPE_SRFLX ||
797              lcand->type == PJ_ICE_CAND_TYPE_PRFLX)) 
798         {
799             *cand_id = GET_LCAND_ID(lcand);
800             pj_mutex_unlock(ice->mutex);
801             return PJ_SUCCESS;
802         }
803     }
804
805     /* Otherwise return host candidate */
806     for (i=0; i<ice->lcand_cnt; ++i) {
807         pj_ice_sess_cand *lcand = &ice->lcand[i];
808         if (lcand->comp_id==comp_id &&
809             lcand->type == PJ_ICE_CAND_TYPE_HOST) 
810         {
811             *cand_id = GET_LCAND_ID(lcand);
812             pj_mutex_unlock(ice->mutex);
813             return PJ_SUCCESS;
814         }
815     }
816
817     /* Still no candidate is found! :( */
818     pj_mutex_unlock(ice->mutex);
819
820     pj_assert(!"Should have a candidate by now");
821     return PJ_EBUG;
822 }
823
824
825 #ifndef MIN
826 #   define MIN(a,b) (a < b ? a : b)
827 #endif
828
829 #ifndef MAX
830 #   define MAX(a,b) (a > b ? a : b)
831 #endif
832
833 static pj_timestamp CALC_CHECK_PRIO(const pj_ice_sess *ice, 
834                                     const pj_ice_sess_cand *lcand,
835                                     const pj_ice_sess_cand *rcand)
836 {
837     pj_uint32_t O, A;
838     pj_timestamp prio;
839
840     /* Original formula:
841      *   pair priority = 2^32*MIN(O,A) + 2*MAX(O,A) + (O>A?1:0)
842      */
843
844     if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) {
845         O = lcand->prio; 
846         A = rcand->prio;
847     } else {
848         O = rcand->prio;
849         A = lcand->prio;
850     }
851
852     /*
853     return ((pj_uint64_t)1 << 32) * MIN(O, A) +
854            (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0);
855     */
856
857     prio.u32.hi = MIN(O,A);
858     prio.u32.lo = (MAX(O, A) << 1) + (O>A ? 1 : 0);
859
860     return prio;
861 }
862
863
864 PJ_INLINE(int) CMP_CHECK_PRIO(const pj_ice_sess_check *c1,
865                               const pj_ice_sess_check *c2)
866 {
867     return pj_cmp_timestamp(&c1->prio, &c2->prio);
868 }
869
870
871 #if PJ_LOG_MAX_LEVEL >= 4
872 static const char *dump_check(char *buffer, unsigned bufsize,
873                               const pj_ice_sess_checklist *clist,
874                               const pj_ice_sess_check *check)
875 {
876     const pj_ice_sess_cand *lcand = check->lcand;
877     const pj_ice_sess_cand *rcand = check->rcand;
878     char laddr[PJ_INET6_ADDRSTRLEN];
879     int len;
880
881     PJ_CHECK_STACK();
882
883     pj_ansi_strcpy(laddr, pj_inet_ntoa(lcand->addr.ipv4.sin_addr));
884
885     if (lcand->addr.addr.sa_family == pj_AF_INET()) {
886         len = pj_ansi_snprintf(buffer, bufsize,
887                                "%d: [%d] %s:%d-->%s:%d",
888                                (int)GET_CHECK_ID(clist, check),
889                                check->lcand->comp_id,
890                                laddr, (int)pj_ntohs(lcand->addr.ipv4.sin_port),
891                                pj_inet_ntoa(rcand->addr.ipv4.sin_addr),
892                                (int)pj_ntohs(rcand->addr.ipv4.sin_port));
893     } else {
894         len = pj_ansi_snprintf(buffer, bufsize, "IPv6->IPv6");
895     }
896
897
898     if (len < 0)
899         len = 0;
900     else if (len >= (int)bufsize)
901         len = bufsize - 1;
902
903     buffer[len] = '\0';
904     return buffer;
905 }
906
907 static void dump_checklist(const char *title, pj_ice_sess *ice, 
908                            const pj_ice_sess_checklist *clist)
909 {
910     unsigned i;
911
912     LOG4((ice->obj_name, "%s", title));
913     for (i=0; i<clist->count; ++i) {
914         const pj_ice_sess_check *c = &clist->checks[i];
915         LOG4((ice->obj_name, " %s (%s, state=%s)",
916              dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), clist, c),
917              (c->nominated ? "nominated" : "not nominated"), 
918              check_state_name[c->state]));
919     }
920 }
921
922 #else
923 #define dump_checklist(title, ice, clist)
924 #endif
925
926 static void check_set_state(pj_ice_sess *ice, pj_ice_sess_check *check,
927                             pj_ice_sess_check_state st, 
928                             pj_status_t err_code)
929 {
930     pj_assert(check->state < PJ_ICE_SESS_CHECK_STATE_SUCCEEDED);
931
932     LOG5((ice->obj_name, "Check %s: state changed from %s to %s",
933          dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), &ice->clist, check),
934          check_state_name[check->state],
935          check_state_name[st]));
936     check->state = st;
937     check->err_code = err_code;
938 }
939
940 static void clist_set_state(pj_ice_sess *ice, pj_ice_sess_checklist *clist,
941                             pj_ice_sess_checklist_state st)
942 {
943     if (clist->state != st) {
944         LOG5((ice->obj_name, "Checklist: state changed from %s to %s",
945              clist_state_name[clist->state],
946              clist_state_name[st]));
947         clist->state = st;
948     }
949 }
950
951 /* Sort checklist based on priority */
952 static void sort_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist)
953 {
954     unsigned i;
955     pj_ice_sess_check **check_ptr[PJ_ICE_MAX_COMP*2];
956     unsigned check_ptr_cnt = 0;
957
958     for (i=0; i<ice->comp_cnt; ++i) {
959         if (ice->comp[i].valid_check) {
960             check_ptr[check_ptr_cnt++] = &ice->comp[i].valid_check;
961         }
962         if (ice->comp[i].nominated_check) {
963             check_ptr[check_ptr_cnt++] = &ice->comp[i].nominated_check;
964         }
965     }
966
967     for (i=0; i<clist->count-1; ++i) {
968         unsigned j, highest = i;
969
970         for (j=i+1; j<clist->count; ++j) {
971             if (CMP_CHECK_PRIO(&clist->checks[j], &clist->checks[highest]) > 0) {
972                 highest = j;
973             }
974         }
975
976         if (highest != i) {
977             pj_ice_sess_check tmp;
978             unsigned k;
979
980             pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_sess_check));
981             pj_memcpy(&clist->checks[i], &clist->checks[highest], 
982                       sizeof(pj_ice_sess_check));
983             pj_memcpy(&clist->checks[highest], &tmp, 
984                       sizeof(pj_ice_sess_check));
985
986             /* Update valid and nominated check pointers, since we're moving
987              * around checks
988              */
989             for (k=0; k<check_ptr_cnt; ++k) {
990                 if (*check_ptr[k] == &clist->checks[highest])
991                     *check_ptr[k] = &clist->checks[i];
992                 else if (*check_ptr[k] == &clist->checks[i])
993                     *check_ptr[k] = &clist->checks[highest];
994             }
995         }
996     }
997 }
998
999 enum 
1000
1001     SOCKADDR_EQUAL = 0, 
1002     SOCKADDR_NOT_EQUAL = 1 
1003 };
1004
1005 /* Utility: compare sockaddr.
1006  * Returns 0 if equal.
1007  */
1008 static int sockaddr_cmp(const pj_sockaddr *a1, const pj_sockaddr *a2)
1009 {
1010     if (a1->addr.sa_family != a2->addr.sa_family)
1011         return SOCKADDR_NOT_EQUAL;
1012
1013     if (a1->addr.sa_family == pj_AF_INET()) {
1014         return !(a1->ipv4.sin_addr.s_addr == a2->ipv4.sin_addr.s_addr &&
1015                  a1->ipv4.sin_port == a2->ipv4.sin_port);
1016     } else if (a1->addr.sa_family == pj_AF_INET6()) {
1017         return pj_memcmp(&a1->ipv6, &a2->ipv6, sizeof(a1->ipv6));
1018     } else {
1019         pj_assert(!"Invalid address family!");
1020         return SOCKADDR_NOT_EQUAL;
1021     }
1022 }
1023
1024
1025 /* Prune checklist, this must have been done after the checklist
1026  * is sorted.
1027  */
1028 static pj_status_t prune_checklist(pj_ice_sess *ice, 
1029                                    pj_ice_sess_checklist *clist)
1030 {
1031     unsigned i;
1032
1033     /* Since an agent cannot send requests directly from a reflexive
1034      * candidate, but only from its base, the agent next goes through the
1035      * sorted list of candidate pairs.  For each pair where the local
1036      * candidate is server reflexive, the server reflexive candidate MUST be
1037      * replaced by its base.  Once this has been done, the agent MUST prune
1038      * the list.  This is done by removing a pair if its local and remote
1039      * candidates are identical to the local and remote candidates of a pair
1040      * higher up on the priority list.  The result is a sequence of ordered
1041      * candidate pairs, called the check list for that media stream.    
1042      */
1043     /* First replace SRFLX candidates with their base */
1044     for (i=0; i<clist->count; ++i) {
1045         pj_ice_sess_cand *srflx = clist->checks[i].lcand;
1046
1047         if (clist->checks[i].lcand->type == PJ_ICE_CAND_TYPE_SRFLX) {
1048             /* Find the base for this candidate */
1049             unsigned j;
1050             for (j=0; j<ice->lcand_cnt; ++j) {
1051                 pj_ice_sess_cand *host = &ice->lcand[j];
1052
1053                 if (host->type != PJ_ICE_CAND_TYPE_HOST)
1054                     continue;
1055
1056                 if (sockaddr_cmp(&srflx->base_addr, &host->addr) == 0) {
1057                     /* Replace this SRFLX with its BASE */
1058                     clist->checks[i].lcand = host;
1059                     break;
1060                 }
1061             }
1062
1063             if (j==ice->lcand_cnt) {
1064                 /* Host candidate not found this this srflx! */
1065                 LOG4((ice->obj_name, 
1066                       "Base candidate %s:%d not found for srflx candidate %d",
1067                       pj_inet_ntoa(srflx->base_addr.ipv4.sin_addr),
1068                       pj_ntohs(srflx->base_addr.ipv4.sin_port),
1069                       GET_LCAND_ID(clist->checks[i].lcand)));
1070                 return PJNATH_EICENOHOSTCAND;
1071             }
1072         }
1073     }
1074
1075     /* Next remove a pair if its local and remote candidates are identical
1076      * to the local and remote candidates of a pair higher up on the priority
1077      * list
1078      */
1079     /*
1080      * Not in ICE!
1081      * Remove host candidates if their base are the the same!
1082      */
1083     for (i=0; i<clist->count; ++i) {
1084         pj_ice_sess_cand *licand = clist->checks[i].lcand;
1085         pj_ice_sess_cand *ricand = clist->checks[i].rcand;
1086         unsigned j;
1087
1088         for (j=i+1; j<clist->count;) {
1089             pj_ice_sess_cand *ljcand = clist->checks[j].lcand;
1090             pj_ice_sess_cand *rjcand = clist->checks[j].rcand;
1091             const char *reason = NULL;
1092
1093             if ((licand == ljcand) && (ricand == rjcand)) {
1094                 reason = "duplicate found";
1095             } else if ((rjcand == ricand) &&
1096                        (sockaddr_cmp(&ljcand->base_addr, 
1097                                      &licand->base_addr)==0)) 
1098             {
1099                 reason = "equal base";
1100             }
1101
1102             if (reason != NULL) {
1103                 /* Found duplicate, remove it */
1104                 LOG5((ice->obj_name, "Check %s pruned (%s)",
1105                       dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
1106                                  &ice->clist, &clist->checks[j]),
1107                       reason));
1108
1109                 pj_array_erase(clist->checks, sizeof(clist->checks[0]),
1110                                clist->count, j);
1111                 --clist->count;
1112
1113             } else {
1114                 ++j;
1115             }
1116         }
1117     }
1118
1119     return PJ_SUCCESS;
1120 }
1121
1122 /* Timer callback */
1123 static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te)
1124 {
1125     pj_ice_sess *ice = (pj_ice_sess*) te->user_data;
1126     enum timer_type type = (enum timer_type)te->id;
1127     pj_bool_t has_mutex = PJ_TRUE;
1128
1129     PJ_UNUSED_ARG(th);
1130
1131     pj_mutex_lock(ice->mutex);
1132
1133     te->id = TIMER_NONE;
1134
1135     switch (type) {
1136     case TIMER_CONTROLLED_WAIT_NOM:
1137         LOG4((ice->obj_name, 
1138               "Controlled agent timed-out in waiting for the controlling "
1139               "agent to send nominated check. Setting state to fail now.."));
1140         on_ice_complete(ice, PJNATH_EICENOMTIMEOUT);
1141         break;
1142     case TIMER_COMPLETION_CALLBACK:
1143         {
1144             void (*on_ice_complete)(pj_ice_sess *ice, pj_status_t status);
1145             pj_status_t ice_status;
1146
1147             /* Start keep-alive timer but don't send any packets yet.
1148              * Need to do it here just in case app destroy the session
1149              * in the callback.
1150              */
1151             if (ice->ice_status == PJ_SUCCESS)
1152                 ice_keep_alive(ice, PJ_FALSE);
1153
1154             /* Release mutex in case app destroy us in the callback */
1155             ice_status = ice->ice_status;
1156             on_ice_complete = ice->cb.on_ice_complete;
1157             has_mutex = PJ_FALSE;
1158             pj_mutex_unlock(ice->mutex);
1159
1160             /* Notify app about ICE completion*/
1161             if (on_ice_complete)
1162                 (*on_ice_complete)(ice, ice_status);
1163         }
1164         break;
1165     case TIMER_START_NOMINATED_CHECK:
1166         start_nominated_check(ice);
1167         break;
1168     case TIMER_KEEP_ALIVE:
1169         ice_keep_alive(ice, PJ_TRUE);
1170         break;
1171     case TIMER_NONE:
1172         /* Nothing to do, just to get rid of gcc warning */
1173         break;
1174     }
1175
1176     if (has_mutex)
1177         pj_mutex_unlock(ice->mutex);
1178 }
1179
1180 /* Send keep-alive */
1181 static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now)
1182 {
1183     if (send_now) {
1184         /* Send Binding Indication for the component */
1185         pj_ice_sess_comp *comp = &ice->comp[ice->comp_ka];
1186         pj_stun_tx_data *tdata;
1187         pj_ice_sess_check *the_check;
1188         pj_ice_msg_data *msg_data;
1189         int addr_len;
1190         pj_bool_t saved;
1191         pj_status_t status;
1192
1193         /* Must have nominated check by now */
1194         pj_assert(comp->nominated_check != NULL);
1195         the_check = comp->nominated_check;
1196
1197         /* Create the Binding Indication */
1198         status = pj_stun_session_create_ind(comp->stun_sess, 
1199                                             PJ_STUN_BINDING_INDICATION,
1200                                             &tdata);
1201         if (status != PJ_SUCCESS)
1202             goto done;
1203
1204         /* Need the transport_id */
1205         msg_data = PJ_POOL_ZALLOC_T(tdata->pool, pj_ice_msg_data);
1206         msg_data->transport_id = the_check->lcand->transport_id;
1207
1208         /* Temporarily disable FINGERPRINT. The Binding Indication 
1209          * SHOULD NOT contain any attributes.
1210          */
1211         saved = pj_stun_session_use_fingerprint(comp->stun_sess, PJ_FALSE);
1212
1213         /* Send to session */
1214         addr_len = pj_sockaddr_get_len(&the_check->rcand->addr);
1215         status = pj_stun_session_send_msg(comp->stun_sess, msg_data,
1216                                           PJ_FALSE, PJ_FALSE, 
1217                                           &the_check->rcand->addr, 
1218                                           addr_len, tdata);
1219
1220         /* Restore FINGERPRINT usage */
1221         pj_stun_session_use_fingerprint(comp->stun_sess, saved);
1222
1223 done:
1224         ice->comp_ka = (ice->comp_ka + 1) % ice->comp_cnt;
1225     }
1226
1227     if (ice->timer.id == TIMER_NONE) {
1228         pj_time_val delay = { 0, 0 };
1229
1230         delay.msec = (PJ_ICE_SESS_KEEP_ALIVE_MIN + 
1231                       (pj_rand() % PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND)) * 1000 / 
1232                      ice->comp_cnt;
1233         pj_time_val_normalize(&delay);
1234
1235         ice->timer.id = TIMER_KEEP_ALIVE;
1236         pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay);
1237
1238     } else {
1239         pj_assert(!"Not expected any timer active");
1240     }
1241 }
1242
1243 /* This function is called when ICE processing completes */
1244 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status)
1245 {
1246     if (!ice->is_complete) {
1247         ice->is_complete = PJ_TRUE;
1248         ice->ice_status = status;
1249     
1250         if (ice->timer.id != TIMER_NONE) {
1251             pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer);
1252             ice->timer.id = TIMER_NONE;
1253         }
1254
1255         /* Log message */
1256         LOG4((ice->obj_name, "ICE process complete, status=%s", 
1257              pj_strerror(status, ice->tmp.errmsg, 
1258                          sizeof(ice->tmp.errmsg)).ptr));
1259
1260         dump_checklist("Valid list", ice, &ice->valid_list);
1261
1262         /* Call callback */
1263         if (ice->cb.on_ice_complete) {
1264             pj_time_val delay = {0, 0};
1265
1266             ice->timer.id = TIMER_COMPLETION_CALLBACK;
1267             pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 
1268                                    &ice->timer, &delay);
1269         }
1270     }
1271 }
1272
1273 /* Update valid check and nominated check for the candidate */
1274 static void update_comp_check(pj_ice_sess *ice, unsigned comp_id, 
1275                               pj_ice_sess_check *check)
1276 {
1277     pj_ice_sess_comp *comp;
1278
1279     comp = find_comp(ice, comp_id);
1280     if (comp->valid_check == NULL) {
1281         comp->valid_check = check;
1282     } else {
1283         if (CMP_CHECK_PRIO(comp->valid_check, check) < 0)
1284             comp->valid_check = check;
1285     }
1286
1287     if (check->nominated) {
1288         /* Update the nominated check for the component */
1289         if (comp->nominated_check == NULL) {
1290             comp->nominated_check = check;
1291         } else {
1292             if (CMP_CHECK_PRIO(comp->nominated_check, check) < 0)
1293                 comp->nominated_check = check;
1294         }
1295     }
1296 }
1297
1298 /* This function is called when one check completes */
1299 static pj_bool_t on_check_complete(pj_ice_sess *ice,
1300                                    pj_ice_sess_check *check)
1301 {
1302     pj_ice_sess_comp *comp;
1303     unsigned i;
1304
1305     pj_assert(check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED);
1306
1307     comp = find_comp(ice, check->lcand->comp_id);
1308
1309     /* 7.1.2.2.2.  Updating Pair States
1310      * 
1311      * The agent sets the state of the pair that generated the check to
1312      * Succeeded.  The success of this check might also cause the state of
1313      * other checks to change as well.  The agent MUST perform the following
1314      * two steps:
1315      * 
1316      * 1.  The agent changes the states for all other Frozen pairs for the
1317      *     same media stream and same foundation to Waiting.  Typically
1318      *     these other pairs will have different component IDs but not
1319      *     always.
1320      */
1321     if (check->err_code==PJ_SUCCESS) {
1322
1323         for (i=0; i<ice->clist.count; ++i) {
1324             pj_ice_sess_check *c = &ice->clist.checks[i];
1325             if (pj_strcmp(&c->lcand->foundation, &check->lcand->foundation)==0
1326                  && c->state == PJ_ICE_SESS_CHECK_STATE_FROZEN)
1327             {
1328                 check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING, 0);
1329             }
1330         }
1331
1332         LOG5((ice->obj_name, "Check %d is successful%s",
1333              GET_CHECK_ID(&ice->clist, check),
1334              (check->nominated ? "  and nominated" : "")));
1335
1336     }
1337
1338     /* 8.2.  Updating States
1339      * 
1340      * For both controlling and controlled agents, the state of ICE
1341      * processing depends on the presence of nominated candidate pairs in
1342      * the valid list and on the state of the check list:
1343      *
1344      * o  If there are no nominated pairs in the valid list for a media
1345      *    stream and the state of the check list is Running, ICE processing
1346      *    continues.
1347      *
1348      * o  If there is at least one nominated pair in the valid list:
1349      *
1350      *    - The agent MUST remove all Waiting and Frozen pairs in the check
1351      *      list for the same component as the nominated pairs for that
1352      *      media stream
1353      *
1354      *    - If an In-Progress pair in the check list is for the same
1355      *      component as a nominated pair, the agent SHOULD cease
1356      *      retransmissions for its check if its pair priority is lower
1357      *      than the lowest priority nominated pair for that component
1358      */
1359     if (check->err_code==PJ_SUCCESS && check->nominated) {
1360
1361         for (i=0; i<ice->clist.count; ++i) {
1362
1363             pj_ice_sess_check *c = &ice->clist.checks[i];
1364
1365             if (c->lcand->comp_id == check->lcand->comp_id) {
1366
1367                 if (c->state < PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) {
1368
1369                     /* Just fail Frozen/Waiting check */
1370                     LOG5((ice->obj_name, 
1371                          "Check %s to be failed because state is %s",
1372                          dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
1373                                     &ice->clist, c), 
1374                          check_state_name[c->state]));
1375                     check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_FAILED,
1376                                     PJ_ECANCELLED);
1377
1378                 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS
1379                            && (PJ_ICE_CANCEL_ALL ||
1380                                 CMP_CHECK_PRIO(c, check) < 0)) {
1381
1382                     /* State is IN_PROGRESS, cancel transaction */
1383                     if (c->tdata) {
1384                         LOG5((ice->obj_name, 
1385                              "Cancelling check %s (In Progress)",
1386                              dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
1387                                         &ice->clist, c)));
1388                         pj_stun_session_cancel_req(comp->stun_sess, 
1389                                                    c->tdata, PJ_FALSE, 0);
1390                         c->tdata = NULL;
1391                         check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_FAILED,
1392                                         PJ_ECANCELLED);
1393                     }
1394                 }
1395             }
1396         }
1397     }
1398
1399
1400     /* Still in 8.2.  Updating States
1401      * 
1402      * o  Once there is at least one nominated pair in the valid list for
1403      *    every component of at least one media stream and the state of the
1404      *    check list is Running:
1405      *    
1406      *    *  The agent MUST change the state of processing for its check
1407      *       list for that media stream to Completed.
1408      *    
1409      *    *  The agent MUST continue to respond to any checks it may still
1410      *       receive for that media stream, and MUST perform triggered
1411      *       checks if required by the processing of Section 7.2.
1412      *    
1413      *    *  The agent MAY begin transmitting media for this media stream as
1414      *       described in Section 11.1
1415      */
1416
1417     /* See if all components have nominated pair. If they do, then mark
1418      * ICE processing as success, otherwise wait.
1419      */
1420     for (i=0; i<ice->comp_cnt; ++i) {
1421         if (ice->comp[i].nominated_check == NULL)
1422             break;
1423     }
1424     if (i == ice->comp_cnt) {
1425         /* All components have nominated pair */
1426         on_ice_complete(ice, PJ_SUCCESS);
1427         return PJ_TRUE;
1428     }
1429
1430     /* Note: this is the stuffs that we don't do in 7.1.2.2.2, since our
1431      *       ICE session only supports one media stream for now:
1432      * 
1433      * 7.1.2.2.2.  Updating Pair States
1434      *
1435      * 2.  If there is a pair in the valid list for every component of this
1436      *     media stream (where this is the actual number of components being
1437      *     used, in cases where the number of components signaled in the SDP
1438      *     differs from offerer to answerer), the success of this check may
1439      *     unfreeze checks for other media streams. 
1440      */
1441
1442     /* 7.1.2.3.  Check List and Timer State Updates
1443      * Regardless of whether the check was successful or failed, the
1444      * completion of the transaction may require updating of check list and
1445      * timer states.
1446      * 
1447      * If all of the pairs in the check list are now either in the Failed or
1448      * Succeeded state, and there is not a pair in the valid list for each
1449      * component of the media stream, the state of the check list is set to
1450      * Failed.  
1451      */
1452
1453     /* 
1454      * See if all checks in the checklist have completed. If we do,
1455      * then mark ICE processing as failed.
1456      */
1457     for (i=0; i<ice->clist.count; ++i) {
1458         pj_ice_sess_check *c = &ice->clist.checks[i];
1459         if (c->state < PJ_ICE_SESS_CHECK_STATE_SUCCEEDED) {
1460             break;
1461         }
1462     }
1463
1464     if (i == ice->clist.count) {
1465         /* All checks have completed, but we don't have nominated pair.
1466          * If agent's role is controlled, check if all components have
1467          * valid pair. If it does, this means the controlled agent has
1468          * finished the check list and it's waiting for controlling
1469          * agent to send checks with USE-CANDIDATE flag set.
1470          */
1471         if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLED) {
1472             for (i=0; i < ice->comp_cnt; ++i) {
1473                 if (ice->comp[i].valid_check == NULL)
1474                     break;
1475             }
1476
1477             if (i < ice->comp_cnt) {
1478                 /* This component ID doesn't have valid pair.
1479                  * Mark ICE as failed. 
1480                  */
1481                 on_ice_complete(ice, PJNATH_EICEFAILED);
1482                 return PJ_TRUE;
1483             } else {
1484                 /* All components have a valid pair.
1485                  * We should wait until we receive nominated checks.
1486                  */
1487                 if (ice->timer.id == TIMER_NONE &&
1488                     ice->opt.controlled_agent_want_nom_timeout >= 0) 
1489                 {
1490                     pj_time_val delay;
1491
1492                     delay.sec = 0;
1493                     delay.msec = ice->opt.controlled_agent_want_nom_timeout;
1494                     pj_time_val_normalize(&delay);
1495
1496                     ice->timer.id = TIMER_CONTROLLED_WAIT_NOM;
1497                     pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 
1498                                            &ice->timer,
1499                                            &delay);
1500
1501                     LOG5((ice->obj_name, 
1502                           "All checks have completed. Controlled agent now "
1503                           "waits for nomination from controlling agent "
1504                           "(timeout=%d msec)",
1505                           ice->opt.controlled_agent_want_nom_timeout));
1506                 }
1507                 return PJ_FALSE;
1508             }
1509
1510             /* Unreached */
1511
1512         } else if (ice->is_nominating) {
1513             /* We are controlling agent and all checks have completed but
1514              * there's at least one component without nominated pair (or
1515              * more likely we don't have any nominated pairs at all).
1516              */
1517             on_ice_complete(ice, PJNATH_EICEFAILED);
1518             return PJ_TRUE;
1519
1520         } else {
1521             /* We are controlling agent and all checks have completed. If
1522              * we have valid list for every component, then move on to
1523              * sending nominated check, otherwise we have failed.
1524              */
1525             for (i=0; i<ice->comp_cnt; ++i) {
1526                 if (ice->comp[i].valid_check == NULL)
1527                     break;
1528             }
1529
1530             if (i < ice->comp_cnt) {
1531                 /* At least one component doesn't have a valid check. Mark
1532                  * ICE as failed.
1533                  */
1534                 on_ice_complete(ice, PJNATH_EICEFAILED);
1535                 return PJ_TRUE;
1536             }
1537
1538             /* Now it's time to send connectivity check with nomination 
1539              * flag set.
1540              */
1541             LOG4((ice->obj_name, 
1542                   "All checks have completed, starting nominated checks now"));
1543             start_nominated_check(ice);
1544             return PJ_FALSE;
1545         }
1546     }
1547
1548     /* If this connectivity check has been successful, scan all components
1549      * and see if they have a valid pair, if we are controlling and we haven't
1550      * started our nominated check yet.
1551      */
1552     if (check->err_code == PJ_SUCCESS && 
1553         ice->role==PJ_ICE_SESS_ROLE_CONTROLLING &&
1554         !ice->is_nominating &&
1555         ice->timer.id == TIMER_NONE) 
1556     {
1557         pj_time_val delay;
1558
1559         for (i=0; i<ice->comp_cnt; ++i) {
1560             if (ice->comp[i].valid_check == NULL)
1561                 break;
1562         }
1563
1564         if (i < ice->comp_cnt) {
1565             /* Some components still don't have valid pair, continue
1566              * processing.
1567              */
1568             return PJ_FALSE;
1569         }
1570
1571         LOG4((ice->obj_name, 
1572               "Scheduling nominated check in %d ms",
1573               ice->opt.nominated_check_delay));
1574
1575         if (ice->timer.id != TIMER_NONE) {
1576             pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer);
1577             ice->timer.id = TIMER_NONE;
1578         }
1579
1580         /* All components have valid pair. Let connectivity checks run for
1581          * a little bit more time, then start our nominated check.
1582          */
1583         delay.sec = 0;
1584         delay.msec = ice->opt.nominated_check_delay;
1585         pj_time_val_normalize(&delay);
1586
1587         ice->timer.id = TIMER_START_NOMINATED_CHECK;
1588         pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay);
1589         return PJ_FALSE;
1590     }
1591
1592     /* We still have checks to perform */
1593     return PJ_FALSE;
1594 }
1595
1596
1597 /* Create checklist by pairing local candidates with remote candidates */
1598 PJ_DEF(pj_status_t) pj_ice_sess_create_check_list(
1599                               pj_ice_sess *ice,
1600                               const pj_str_t *rem_ufrag,
1601                               const pj_str_t *rem_passwd,
1602                               unsigned rcand_cnt,
1603                               const pj_ice_sess_cand rcand[])
1604 {
1605     pj_ice_sess_checklist *clist;
1606     char buf[128];
1607     pj_str_t username;
1608     timer_data *td;
1609     unsigned i, j;
1610     unsigned highest_comp = 0;
1611     pj_status_t status;
1612
1613     PJ_ASSERT_RETURN(ice && rem_ufrag && rem_passwd && rcand_cnt && rcand,
1614                      PJ_EINVAL);
1615     PJ_ASSERT_RETURN(rcand_cnt + ice->rcand_cnt <= PJ_ICE_MAX_CAND, 
1616                      PJ_ETOOMANY);
1617
1618     pj_mutex_lock(ice->mutex);
1619
1620     /* Save credentials */
1621     username.ptr = buf;
1622
1623     pj_strcpy(&username, rem_ufrag);
1624     pj_strcat2(&username, ":");
1625     pj_strcat(&username, &ice->rx_ufrag);
1626
1627     pj_strdup(ice->pool, &ice->tx_uname, &username);
1628     pj_strdup(ice->pool, &ice->tx_ufrag, rem_ufrag);
1629     pj_strdup(ice->pool, &ice->tx_pass, rem_passwd);
1630
1631     pj_strcpy(&username, &ice->rx_ufrag);
1632     pj_strcat2(&username, ":");
1633     pj_strcat(&username, rem_ufrag);
1634
1635     pj_strdup(ice->pool, &ice->rx_uname, &username);
1636
1637
1638     /* Save remote candidates */
1639     ice->rcand_cnt = 0;
1640     for (i=0; i<rcand_cnt; ++i) {
1641         pj_ice_sess_cand *cn = &ice->rcand[ice->rcand_cnt];
1642
1643         /* Ignore candidate which has no matching component ID */
1644         if (rcand[i].comp_id==0 || rcand[i].comp_id > ice->comp_cnt) {
1645             continue;
1646         }
1647
1648         if (rcand[i].comp_id > highest_comp)
1649             highest_comp = rcand[i].comp_id;
1650
1651         pj_memcpy(cn, &rcand[i], sizeof(pj_ice_sess_cand));
1652         pj_strdup(ice->pool, &cn->foundation, &rcand[i].foundation);
1653         ice->rcand_cnt++;
1654     }
1655
1656     /* Generate checklist */
1657     clist = &ice->clist;
1658     for (i=0; i<ice->lcand_cnt; ++i) {
1659         for (j=0; j<ice->rcand_cnt; ++j) {
1660
1661             pj_ice_sess_cand *lcand = &ice->lcand[i];
1662             pj_ice_sess_cand *rcand = &ice->rcand[j];
1663             pj_ice_sess_check *chk = &clist->checks[clist->count];
1664
1665             if (clist->count >= PJ_ICE_MAX_CHECKS) {
1666                 pj_mutex_unlock(ice->mutex);
1667                 return PJ_ETOOMANY;
1668             } 
1669
1670             /* A local candidate is paired with a remote candidate if
1671              * and only if the two candidates have the same component ID 
1672              * and have the same IP address version. 
1673              */
1674             if ((lcand->comp_id != rcand->comp_id) ||
1675                 (lcand->addr.addr.sa_family != rcand->addr.addr.sa_family))
1676             {
1677                 continue;
1678             }
1679
1680
1681             chk->lcand = lcand;
1682             chk->rcand = rcand;
1683             chk->state = PJ_ICE_SESS_CHECK_STATE_FROZEN;
1684
1685             chk->prio = CALC_CHECK_PRIO(ice, lcand, rcand);
1686
1687             clist->count++;
1688         }
1689     }
1690
1691     /* Sort checklist based on priority */
1692     sort_checklist(ice, clist);
1693
1694     /* Prune the checklist */
1695     status = prune_checklist(ice, clist);
1696     if (status != PJ_SUCCESS) {
1697         pj_mutex_unlock(ice->mutex);
1698         return status;
1699     }
1700
1701     /* Disable our components which don't have matching component */
1702     for (i=highest_comp; i<ice->comp_cnt; ++i) {
1703         if (ice->comp[i].stun_sess) {
1704             pj_stun_session_destroy(ice->comp[i].stun_sess);
1705             pj_bzero(&ice->comp[i], sizeof(ice->comp[i]));
1706         }
1707     }
1708     ice->comp_cnt = highest_comp;
1709
1710     /* Init timer entry in the checklist. Initially the timer ID is FALSE
1711      * because timer is not running.
1712      */
1713     clist->timer.id = PJ_FALSE;
1714     td = PJ_POOL_ZALLOC_T(ice->pool, timer_data);
1715     td->ice = ice;
1716     td->clist = clist;
1717     clist->timer.user_data = (void*)td;
1718     clist->timer.cb = &periodic_timer;
1719
1720
1721     /* Log checklist */
1722     dump_checklist("Checklist created:", ice, clist);
1723
1724     pj_mutex_unlock(ice->mutex);
1725
1726     return PJ_SUCCESS;
1727 }
1728
1729 /* Perform check on the specified candidate pair. */
1730 static pj_status_t perform_check(pj_ice_sess *ice, 
1731                                  pj_ice_sess_checklist *clist,
1732                                  unsigned check_id,
1733                                  pj_bool_t nominate)
1734 {
1735     pj_ice_sess_comp *comp;
1736     pj_ice_msg_data *msg_data;
1737     pj_ice_sess_check *check;
1738     const pj_ice_sess_cand *lcand;
1739     const pj_ice_sess_cand *rcand;
1740     pj_uint32_t prio;
1741     pj_status_t status;
1742
1743     check = &clist->checks[check_id];
1744     lcand = check->lcand;
1745     rcand = check->rcand;
1746     comp = find_comp(ice, lcand->comp_id);
1747
1748     LOG5((ice->obj_name, 
1749          "Sending connectivity check for check %s", 
1750          dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), clist, check)));
1751     pj_log_push_indent();
1752
1753     /* Create request */
1754     status = pj_stun_session_create_req(comp->stun_sess, 
1755                                         PJ_STUN_BINDING_REQUEST, PJ_STUN_MAGIC,
1756                                         NULL, &check->tdata);
1757     if (status != PJ_SUCCESS) {
1758         pjnath_perror(ice->obj_name, "Error creating STUN request", status);
1759         pj_log_pop_indent();
1760         return status;
1761     }
1762
1763     /* Attach data to be retrieved later when STUN request transaction
1764      * completes and on_stun_request_complete() callback is called.
1765      */
1766     msg_data = PJ_POOL_ZALLOC_T(check->tdata->pool, pj_ice_msg_data);
1767     msg_data->transport_id = lcand->transport_id;
1768     msg_data->has_req_data = PJ_TRUE;
1769     msg_data->data.req.ice = ice;
1770     msg_data->data.req.clist = clist;
1771     msg_data->data.req.ckid = check_id;
1772
1773     /* Add PRIORITY */
1774 #if PJNATH_ICE_PRIO_STD
1775     prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 65535, 
1776                           lcand->comp_id);
1777 #else
1778     prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 0, 
1779                           lcand->comp_id);
1780 #endif
1781     pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg, 
1782                               PJ_STUN_ATTR_PRIORITY, prio);
1783
1784     /* Add USE-CANDIDATE and set this check to nominated.
1785      * Also add ICE-CONTROLLING or ICE-CONTROLLED
1786      */
1787     if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) {
1788         if (nominate) {
1789             pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg,
1790                                        PJ_STUN_ATTR_USE_CANDIDATE);
1791             check->nominated = PJ_TRUE;
1792         }
1793
1794         pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg, 
1795                                     PJ_STUN_ATTR_ICE_CONTROLLING,
1796                                     &ice->tie_breaker);
1797
1798     } else {
1799         pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg, 
1800                                     PJ_STUN_ATTR_ICE_CONTROLLED,
1801                                     &ice->tie_breaker);
1802     }
1803
1804
1805     /* Note that USERNAME and MESSAGE-INTEGRITY will be added by the 
1806      * STUN session.
1807      */
1808
1809     /* Initiate STUN transaction to send the request */
1810     status = pj_stun_session_send_msg(comp->stun_sess, msg_data, PJ_FALSE, 
1811                                       PJ_TRUE, &rcand->addr, 
1812                                       sizeof(pj_sockaddr_in), check->tdata);
1813     if (status != PJ_SUCCESS) {
1814         check->tdata = NULL;
1815         pjnath_perror(ice->obj_name, "Error sending STUN request", status);
1816         pj_log_pop_indent();
1817         return status;
1818     }
1819
1820     check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS, 
1821                     PJ_SUCCESS);
1822     pj_log_pop_indent();
1823     return PJ_SUCCESS;
1824 }
1825
1826
1827 /* Start periodic check for the specified checklist.
1828  * This callback is called by timer on every Ta (20msec by default)
1829  */
1830 static pj_status_t start_periodic_check(pj_timer_heap_t *th, 
1831                                         pj_timer_entry *te)
1832 {
1833     timer_data *td;
1834     pj_ice_sess *ice;
1835     pj_ice_sess_checklist *clist;
1836     unsigned i, start_count=0;
1837     pj_status_t status;
1838
1839     td = (struct timer_data*) te->user_data;
1840     ice = td->ice;
1841     clist = td->clist;
1842
1843     pj_mutex_lock(ice->mutex);
1844
1845     /* Set timer ID to FALSE first */
1846     te->id = PJ_FALSE;
1847
1848     /* Set checklist state to Running */
1849     clist_set_state(ice, clist, PJ_ICE_SESS_CHECKLIST_ST_RUNNING);
1850
1851     LOG5((ice->obj_name, "Starting checklist periodic check"));
1852     pj_log_push_indent();
1853
1854     /* Send STUN Binding request for check with highest priority on
1855      * Waiting state.
1856      */
1857     for (i=0; i<clist->count; ++i) {
1858         pj_ice_sess_check *check = &clist->checks[i];
1859
1860         if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) {
1861             status = perform_check(ice, clist, i, ice->is_nominating);
1862             if (status != PJ_SUCCESS) {
1863                 pj_mutex_unlock(ice->mutex);
1864                 pj_log_pop_indent();
1865                 return status;
1866             }
1867
1868             ++start_count;
1869             break;
1870         }
1871     }
1872
1873     /* If we don't have anything in Waiting state, perform check to
1874      * highest priority pair that is in Frozen state.
1875      */
1876     if (start_count==0) {
1877         for (i=0; i<clist->count; ++i) {
1878             pj_ice_sess_check *check = &clist->checks[i];
1879
1880             if (check->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) {
1881                 status = perform_check(ice, clist, i, ice->is_nominating);
1882                 if (status != PJ_SUCCESS) {
1883                     pj_mutex_unlock(ice->mutex);
1884                     pj_log_pop_indent();
1885                     return status;
1886                 }
1887
1888                 ++start_count;
1889                 break;
1890             }
1891         }
1892     }
1893
1894     /* Cannot start check because there's no suitable candidate pair.
1895      */
1896     if (start_count!=0) {
1897         /* Schedule for next timer */
1898         pj_time_val timeout = {0, PJ_ICE_TA_VAL};
1899
1900         te->id = PJ_TRUE;
1901         pj_time_val_normalize(&timeout);
1902         pj_timer_heap_schedule(th, te, &timeout);
1903     }
1904
1905     pj_mutex_unlock(ice->mutex);
1906     pj_log_pop_indent();
1907     return PJ_SUCCESS;
1908 }
1909
1910
1911 /* Start sending connectivity check with USE-CANDIDATE */
1912 static void start_nominated_check(pj_ice_sess *ice)
1913 {
1914     pj_time_val delay;
1915     unsigned i;
1916     pj_status_t status;
1917
1918     LOG4((ice->obj_name, "Starting nominated check.."));
1919     pj_log_push_indent();
1920
1921     pj_assert(ice->is_nominating == PJ_FALSE);
1922
1923     /* Stop our timer if it's active */
1924     if (ice->timer.id == TIMER_START_NOMINATED_CHECK) {
1925         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer);
1926         ice->timer.id = TIMER_NONE;
1927     }
1928
1929     /* For each component, set the check state of valid check with
1930      * highest priority to Waiting (it should have Success state now).
1931      */
1932     for (i=0; i<ice->comp_cnt; ++i) {
1933         unsigned j;
1934         const pj_ice_sess_check *vc = ice->comp[i].valid_check;
1935
1936         pj_assert(ice->comp[i].nominated_check == NULL);
1937         pj_assert(vc->err_code == PJ_SUCCESS);
1938
1939         for (j=0; j<ice->clist.count; ++j) {
1940             pj_ice_sess_check *c = &ice->clist.checks[j];
1941             if (c->lcand->transport_id == vc->lcand->transport_id &&
1942                 c->rcand == vc->rcand)
1943             {
1944                 pj_assert(c->err_code == PJ_SUCCESS);
1945                 c->state = PJ_ICE_SESS_CHECK_STATE_FROZEN;
1946                 check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING, 
1947                                 PJ_SUCCESS);
1948                 break;
1949             }
1950         }
1951     }
1952
1953     /* And (re)start the periodic check */
1954     if (ice->clist.timer.id) {
1955         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer);
1956         ice->clist.timer.id = PJ_FALSE;
1957     }
1958
1959     ice->clist.timer.id = PJ_TRUE;
1960     delay.sec = delay.msec = 0;
1961     status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 
1962                                     &ice->clist.timer, &delay);
1963     if (status != PJ_SUCCESS) {
1964         ice->clist.timer.id = PJ_FALSE;
1965     } else {
1966         LOG5((ice->obj_name, "Periodic timer rescheduled.."));
1967     }
1968
1969     ice->is_nominating = PJ_TRUE;
1970     pj_log_pop_indent();
1971 }
1972
1973 /* Timer callback to perform periodic check */
1974 static void periodic_timer(pj_timer_heap_t *th, 
1975                            pj_timer_entry *te)
1976 {
1977     start_periodic_check(th, te);
1978 }
1979
1980
1981 /* Utility: find string in string array */
1982 const pj_str_t *find_str(const pj_str_t *strlist[], unsigned count,
1983                          const pj_str_t *str)
1984 {
1985     unsigned i;
1986     for (i=0; i<count; ++i) {
1987         if (pj_strcmp(strlist[i], str)==0)
1988             return strlist[i];
1989     }
1990     return NULL;
1991 }
1992
1993
1994 /*
1995  * Start ICE periodic check. This function will return immediately, and
1996  * application will be notified about the connectivity check status in
1997  * #pj_ice_sess_cb callback.
1998  */
1999 PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice)
2000 {
2001     pj_ice_sess_checklist *clist;
2002     const pj_ice_sess_cand *cand0;
2003     const pj_str_t *flist[PJ_ICE_MAX_CAND]; // XXX
2004     pj_ice_rx_check *rcheck;
2005     unsigned i, flist_cnt = 0;
2006     pj_time_val delay;
2007     pj_status_t status;
2008
2009     PJ_ASSERT_RETURN(ice, PJ_EINVAL);
2010
2011     /* Checklist must have been created */
2012     PJ_ASSERT_RETURN(ice->clist.count > 0, PJ_EINVALIDOP);
2013
2014     /* Lock session */
2015     pj_mutex_lock(ice->mutex);
2016
2017     LOG4((ice->obj_name, "Starting ICE check.."));
2018     pj_log_push_indent();
2019
2020     /* If we are using aggressive nomination, set the is_nominating state */
2021     if (ice->opt.aggressive)
2022         ice->is_nominating = PJ_TRUE;
2023
2024     /* The agent examines the check list for the first media stream (a
2025      * media stream is the first media stream when it is described by
2026      * the first m-line in the SDP offer and answer).  For that media
2027      * stream, it:
2028      * 
2029      * -  Groups together all of the pairs with the same foundation,
2030      * 
2031      * -  For each group, sets the state of the pair with the lowest
2032      *    component ID to Waiting.  If there is more than one such pair,
2033      *    the one with the highest priority is used.
2034      */
2035
2036     clist = &ice->clist;
2037
2038     /* Pickup the first pair for component 1. */
2039     for (i=0; i<clist->count; ++i) {
2040         if (clist->checks[i].lcand->comp_id == 1)
2041             break;
2042     }
2043     if (i == clist->count) {
2044         pj_assert(!"Unable to find checklist for component 1");
2045         pj_mutex_unlock(ice->mutex);
2046         pj_log_pop_indent();
2047         return PJNATH_EICEINCOMPID;
2048     }
2049
2050     /* Set this check to WAITING only if state is frozen. It may be possible
2051      * that this check has already been started by a trigger check
2052      */
2053     if (clist->checks[i].state == PJ_ICE_SESS_CHECK_STATE_FROZEN) {
2054         check_set_state(ice, &clist->checks[i], 
2055                         PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS);
2056     }
2057
2058     cand0 = clist->checks[i].lcand;
2059     flist[flist_cnt++] = &clist->checks[i].lcand->foundation;
2060
2061     /* Find all of the other pairs in that check list with the same
2062      * component ID, but different foundations, and sets all of their
2063      * states to Waiting as well.
2064      */
2065     for (++i; i<clist->count; ++i) {
2066         const pj_ice_sess_cand *cand1;
2067
2068         cand1 = clist->checks[i].lcand;
2069
2070         if (cand1->comp_id==cand0->comp_id &&
2071             find_str(flist, flist_cnt, &cand1->foundation)==NULL)
2072         {
2073             if (clist->checks[i].state == PJ_ICE_SESS_CHECK_STATE_FROZEN) {
2074                 check_set_state(ice, &clist->checks[i], 
2075                                 PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS);
2076             }
2077             flist[flist_cnt++] = &cand1->foundation;
2078         }
2079     }
2080
2081     /* First, perform all pending triggered checks, simultaneously. */
2082     rcheck = ice->early_check.next;
2083     while (rcheck != &ice->early_check) {
2084         LOG4((ice->obj_name, 
2085               "Performing delayed triggerred check for component %d",
2086               rcheck->comp_id));
2087         pj_log_push_indent();
2088         handle_incoming_check(ice, rcheck);
2089         rcheck = rcheck->next;
2090         pj_log_pop_indent();
2091     }
2092     pj_list_init(&ice->early_check);
2093
2094     /* Start periodic check */
2095     /* We could start it immediately like below, but lets schedule timer 
2096      * instead to reduce stack usage:
2097      * return start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer);
2098      */
2099     clist->timer.id = PJ_TRUE;
2100     delay.sec = delay.msec = 0;
2101     status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap, 
2102                                     &clist->timer, &delay);
2103     if (status != PJ_SUCCESS) {
2104         clist->timer.id = PJ_FALSE;
2105     }
2106
2107     pj_mutex_unlock(ice->mutex);
2108     pj_log_pop_indent();
2109     return status;
2110 }
2111
2112
2113 //////////////////////////////////////////////////////////////////////////////
2114
2115 /* Callback called by STUN session to send the STUN message.
2116  * STUN session also doesn't have a transport, remember?!
2117  */
2118 static pj_status_t on_stun_send_msg(pj_stun_session *sess,
2119                                     void *token,
2120                                     const void *pkt,
2121                                     pj_size_t pkt_size,
2122                                     const pj_sockaddr_t *dst_addr,
2123                                     unsigned addr_len)
2124 {
2125     stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess);
2126     pj_ice_sess *ice = sd->ice;
2127     pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token;
2128     
2129     return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id,
2130                                 pkt, pkt_size, dst_addr, addr_len);
2131 }
2132
2133
2134 /* This callback is called when outgoing STUN request completed */
2135 static void on_stun_request_complete(pj_stun_session *stun_sess,
2136                                      pj_status_t status,
2137                                      void *token,
2138                                      pj_stun_tx_data *tdata,
2139                                      const pj_stun_msg *response,
2140                                      const pj_sockaddr_t *src_addr,
2141                                      unsigned src_addr_len)
2142 {
2143     pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token;
2144     pj_ice_sess *ice;
2145     pj_ice_sess_check *check, *new_check;
2146     pj_ice_sess_cand *lcand;
2147     pj_ice_sess_checklist *clist;
2148     pj_stun_xor_mapped_addr_attr *xaddr;
2149     unsigned i;
2150
2151     PJ_UNUSED_ARG(stun_sess);
2152     PJ_UNUSED_ARG(src_addr_len);
2153
2154     pj_assert(msg_data->has_req_data);
2155
2156     ice = msg_data->data.req.ice;
2157     clist = msg_data->data.req.clist;
2158     check = &clist->checks[msg_data->data.req.ckid];
2159     
2160
2161     /* Mark STUN transaction as complete */
2162     pj_assert(tdata == check->tdata);
2163     check->tdata = NULL;
2164
2165     pj_mutex_lock(ice->mutex);
2166
2167     /* Init lcand to NULL. lcand will be found from the mapped address
2168      * found in the response.
2169      */
2170     lcand = NULL;
2171
2172     if (status != PJ_SUCCESS) {
2173         char errmsg[PJ_ERR_MSG_SIZE];
2174
2175         if (status==PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ROLE_CONFLICT)) {
2176
2177             /* Role conclict response.
2178              *
2179              * 7.1.2.1.  Failure Cases:
2180              *
2181              * If the request had contained the ICE-CONTROLLED attribute, 
2182              * the agent MUST switch to the controlling role if it has not
2183              * already done so.  If the request had contained the 
2184              * ICE-CONTROLLING attribute, the agent MUST switch to the 
2185              * controlled role if it has not already done so.  Once it has
2186              * switched, the agent MUST immediately retry the request with
2187              * the ICE-CONTROLLING or ICE-CONTROLLED attribute reflecting 
2188              * its new role.
2189              */
2190             pj_ice_sess_role new_role = PJ_ICE_SESS_ROLE_UNKNOWN;
2191             pj_stun_msg *req = tdata->msg;
2192
2193             if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_ICE_CONTROLLING, 0)) {
2194                 new_role = PJ_ICE_SESS_ROLE_CONTROLLED;
2195             } else if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_ICE_CONTROLLED, 
2196                                              0)) {
2197                 new_role = PJ_ICE_SESS_ROLE_CONTROLLING;
2198             } else {
2199                 pj_assert(!"We should have put CONTROLLING/CONTROLLED attr!");
2200                 new_role = PJ_ICE_SESS_ROLE_CONTROLLED;
2201             }
2202
2203             if (new_role != ice->role) {
2204                 LOG4((ice->obj_name, 
2205                       "Changing role because of role conflict response"));
2206                 pj_ice_sess_change_role(ice, new_role);
2207             }
2208
2209             /* Resend request */
2210             LOG4((ice->obj_name, "Resending check because of role conflict"));
2211             pj_log_push_indent();
2212             check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0);
2213             perform_check(ice, clist, msg_data->data.req.ckid, 
2214                           check->nominated || ice->is_nominating);
2215             pj_log_pop_indent();
2216             pj_mutex_unlock(ice->mutex);
2217             return;
2218         }
2219
2220         pj_strerror(status, errmsg, sizeof(errmsg));
2221         LOG4((ice->obj_name, 
2222              "Check %s%s: connectivity check FAILED: %s",
2223              dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
2224                         &ice->clist, check),
2225              (check->nominated ? " (nominated)" : " (not nominated)"),
2226              errmsg));
2227         pj_log_push_indent();
2228         check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status);
2229         on_check_complete(ice, check);
2230         pj_log_pop_indent();
2231         pj_mutex_unlock(ice->mutex);
2232         return;
2233     }
2234
2235
2236     /* 7.1.2.1.  Failure Cases
2237      *
2238      * The agent MUST check that the source IP address and port of the
2239      * response equals the destination IP address and port that the Binding
2240      * Request was sent to, and that the destination IP address and port of
2241      * the response match the source IP address and port that the Binding
2242      * Request was sent from.
2243      */
2244     if (sockaddr_cmp(&check->rcand->addr, (const pj_sockaddr*)src_addr) != 0) {
2245         status = PJNATH_EICEINSRCADDR;
2246         LOG4((ice->obj_name, 
2247              "Check %s%s: connectivity check FAILED: source address mismatch",
2248              dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
2249                         &ice->clist, check),
2250              (check->nominated ? " (nominated)" : " (not nominated)")));
2251         pj_log_push_indent();
2252         check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, status);
2253         on_check_complete(ice, check);
2254         pj_log_pop_indent();
2255         pj_mutex_unlock(ice->mutex);
2256         return;
2257     }
2258
2259     /* 7.1.2.2.  Success Cases
2260      * 
2261      * A check is considered to be a success if all of the following are
2262      * true:
2263      * 
2264      * o  the STUN transaction generated a success response
2265      * 
2266      * o  the source IP address and port of the response equals the
2267      *    destination IP address and port that the Binding Request was sent
2268      *    to
2269      * 
2270      * o  the destination IP address and port of the response match the
2271      *    source IP address and port that the Binding Request was sent from
2272      */
2273
2274
2275     LOG4((ice->obj_name, 
2276          "Check %s%s: connectivity check SUCCESS",
2277          dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
2278                     &ice->clist, check),
2279          (check->nominated ? " (nominated)" : " (not nominated)")));
2280
2281     /* Get the STUN XOR-MAPPED-ADDRESS attribute. */
2282     xaddr = (pj_stun_xor_mapped_addr_attr*)
2283             pj_stun_msg_find_attr(response, PJ_STUN_ATTR_XOR_MAPPED_ADDR,0);
2284     if (!xaddr) {
2285         check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, 
2286                         PJNATH_ESTUNNOMAPPEDADDR);
2287         on_check_complete(ice, check);
2288         pj_mutex_unlock(ice->mutex);
2289         return;
2290     }
2291
2292     /* Find local candidate that matches the XOR-MAPPED-ADDRESS */
2293     pj_assert(lcand == NULL);
2294     for (i=0; i<ice->lcand_cnt; ++i) {
2295         if (sockaddr_cmp(&xaddr->sockaddr, &ice->lcand[i].addr) == 0) {
2296             /* Match */
2297             lcand = &ice->lcand[i];
2298             break;
2299         }
2300     }
2301
2302     /* 7.1.2.2.1.  Discovering Peer Reflexive Candidates
2303      * If the transport address returned in XOR-MAPPED-ADDRESS does not match
2304      * any of the local candidates that the agent knows about, the mapped 
2305      * address represents a new candidate - a peer reflexive candidate.
2306      */
2307     if (lcand == NULL) {
2308         unsigned cand_id;
2309         pj_str_t foundation;
2310
2311         pj_ice_calc_foundation(ice->pool, &foundation, PJ_ICE_CAND_TYPE_PRFLX,
2312                                &check->lcand->base_addr);
2313
2314         /* Still in 7.1.2.2.1.  Discovering Peer Reflexive Candidates
2315          * Its priority is set equal to the value of the PRIORITY attribute
2316          * in the Binding Request.
2317          *
2318          * I think the priority calculated by add_cand() should be the same
2319          * as the one calculated in perform_check(), so there's no need to
2320          * get the priority from the PRIORITY attribute.
2321          */
2322
2323         /* Add new peer reflexive candidate */
2324         status = pj_ice_sess_add_cand(ice, check->lcand->comp_id, 
2325                                       msg_data->transport_id,
2326                                       PJ_ICE_CAND_TYPE_PRFLX,
2327                                       65535, &foundation,
2328                                       &xaddr->sockaddr, 
2329                                       &check->lcand->base_addr, 
2330                                       &check->lcand->base_addr,
2331                                       sizeof(pj_sockaddr_in), &cand_id);
2332         if (status != PJ_SUCCESS) {
2333             check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_FAILED, 
2334                             status);
2335             on_check_complete(ice, check);
2336             pj_mutex_unlock(ice->mutex);
2337             return;
2338         }
2339
2340         /* Update local candidate */
2341         lcand = &ice->lcand[cand_id];
2342
2343     }
2344
2345     /* 7.1.2.2.3.  Constructing a Valid Pair
2346      * Next, the agent constructs a candidate pair whose local candidate
2347      * equals the mapped address of the response, and whose remote candidate
2348      * equals the destination address to which the request was sent.    
2349      */
2350
2351     /* Add pair to valid list, if it's not there, otherwise just update
2352      * nominated flag
2353      */
2354     for (i=0; i<ice->valid_list.count; ++i) {
2355         if (ice->valid_list.checks[i].lcand == lcand &&
2356             ice->valid_list.checks[i].rcand == check->rcand)
2357             break;
2358     }
2359
2360     if (i==ice->valid_list.count) {
2361         pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS);
2362         new_check = &ice->valid_list.checks[ice->valid_list.count++];
2363         new_check->lcand = lcand;
2364         new_check->rcand = check->rcand;
2365         new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand);
2366         new_check->state = PJ_ICE_SESS_CHECK_STATE_SUCCEEDED;
2367         new_check->nominated = check->nominated;
2368         new_check->err_code = PJ_SUCCESS;
2369     } else {
2370         new_check = &ice->valid_list.checks[i];
2371         ice->valid_list.checks[i].nominated = check->nominated;
2372     }
2373
2374     /* Update valid check and nominated check for the component */
2375     update_comp_check(ice, new_check->lcand->comp_id, new_check);
2376
2377     /* Sort valid_list (must do so after update_comp_check(), otherwise
2378      * new_check will point to something else (#953)
2379      */
2380     sort_checklist(ice, &ice->valid_list);
2381
2382     /* 7.1.2.2.2.  Updating Pair States
2383      * 
2384      * The agent sets the state of the pair that generated the check to
2385      * Succeeded.  The success of this check might also cause the state of
2386      * other checks to change as well.
2387      */
2388     check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_SUCCEEDED, 
2389                     PJ_SUCCESS);
2390
2391     /* Perform 7.1.2.2.2.  Updating Pair States.
2392      * This may terminate ICE processing.
2393      */
2394     if (on_check_complete(ice, check)) {
2395         /* ICE complete! */
2396         pj_mutex_unlock(ice->mutex);
2397         return;
2398     }
2399
2400     pj_mutex_unlock(ice->mutex);
2401 }
2402
2403
2404 /* This callback is called by the STUN session associated with a candidate
2405  * when it receives incoming request.
2406  */
2407 static pj_status_t on_stun_rx_request(pj_stun_session *sess,
2408                                       const pj_uint8_t *pkt,
2409                                       unsigned pkt_len,
2410                                       const pj_stun_rx_data *rdata,
2411                                       void *token,
2412                                       const pj_sockaddr_t *src_addr,
2413                                       unsigned src_addr_len)
2414 {
2415     stun_data *sd;
2416     const pj_stun_msg *msg = rdata->msg;
2417     pj_ice_msg_data *msg_data;
2418     pj_ice_sess *ice;
2419     pj_stun_priority_attr *prio_attr;
2420     pj_stun_use_candidate_attr *uc_attr;
2421     pj_stun_uint64_attr *role_attr;
2422     pj_stun_tx_data *tdata;
2423     pj_ice_rx_check *rcheck, tmp_rcheck;
2424     pj_status_t status;
2425
2426     PJ_UNUSED_ARG(pkt);
2427     PJ_UNUSED_ARG(pkt_len);
2428     
2429     /* Reject any requests except Binding request */
2430     if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) {
2431         pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 
2432                                 NULL, token, PJ_TRUE, 
2433                                 src_addr, src_addr_len);
2434         return PJ_SUCCESS;
2435     }
2436
2437
2438     sd = (stun_data*) pj_stun_session_get_user_data(sess);
2439     ice = sd->ice;
2440
2441     pj_mutex_lock(ice->mutex);
2442
2443     /*
2444      * Note:
2445      *  Be aware that when STUN request is received, we might not get
2446      *  SDP answer yet, so we might not have remote candidates and
2447      *  checklist yet. This case will be handled after we send
2448      *  a response.
2449      */
2450
2451     /* Get PRIORITY attribute */
2452     prio_attr = (pj_stun_priority_attr*)
2453                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PRIORITY, 0);
2454     if (prio_attr == NULL) {
2455         LOG5((ice->obj_name, "Received Binding request with no PRIORITY"));
2456         pj_mutex_unlock(ice->mutex);
2457         return PJ_SUCCESS;
2458     }
2459
2460     /* Get USE-CANDIDATE attribute */
2461     uc_attr = (pj_stun_use_candidate_attr*)
2462               pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USE_CANDIDATE, 0);
2463
2464
2465     /* Get ICE-CONTROLLING or ICE-CONTROLLED */
2466     role_attr = (pj_stun_uint64_attr*)
2467                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICE_CONTROLLING, 0);
2468     if (role_attr == NULL) {
2469         role_attr = (pj_stun_uint64_attr*)
2470                     pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICE_CONTROLLED, 0);
2471     }
2472
2473     /* Handle the case when request comes before answer is received.
2474      * We need to put credential in the response, and since we haven't
2475      * got the response, copy the username from the request.
2476      */
2477     if (ice->rcand_cnt == 0) {
2478         pj_stun_string_attr *uname_attr;
2479
2480         uname_attr = (pj_stun_string_attr*)
2481                      pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0);
2482         pj_assert(uname_attr != NULL);
2483         pj_strdup(ice->pool, &ice->rx_uname, &uname_attr->value);
2484     }
2485
2486     /* 7.2.1.1.  Detecting and Repairing Role Conflicts
2487      */
2488     if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING &&
2489         role_attr && role_attr->hdr.type == PJ_STUN_ATTR_ICE_CONTROLLING)
2490     {
2491         if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) {
2492             /* Switch role to controlled */
2493             LOG4((ice->obj_name, 
2494                   "Changing role because of ICE-CONTROLLING attribute"));
2495             pj_ice_sess_change_role(ice, PJ_ICE_SESS_ROLE_CONTROLLED);
2496         } else {
2497             /* Generate 487 response */
2498             pj_stun_session_respond(sess, rdata, PJ_STUN_SC_ROLE_CONFLICT, 
2499                                     NULL, token, PJ_TRUE, 
2500                                     src_addr, src_addr_len);
2501             pj_mutex_unlock(ice->mutex);
2502             return PJ_SUCCESS;
2503         }
2504
2505     } else if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLED &&
2506                role_attr && role_attr->hdr.type == PJ_STUN_ATTR_ICE_CONTROLLED)
2507     {
2508         if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) {
2509             /* Generate 487 response */
2510             pj_stun_session_respond(sess, rdata, PJ_STUN_SC_ROLE_CONFLICT, 
2511                                     NULL, token, PJ_TRUE, 
2512                                     src_addr, src_addr_len);
2513             pj_mutex_unlock(ice->mutex);
2514             return PJ_SUCCESS;
2515         } else {
2516             /* Switch role to controlled */
2517             LOG4((ice->obj_name, 
2518                   "Changing role because of ICE-CONTROLLED attribute"));
2519             pj_ice_sess_change_role(ice, PJ_ICE_SESS_ROLE_CONTROLLING);
2520         }
2521     }
2522
2523     /* 
2524      * First send response to this request 
2525      */
2526     status = pj_stun_session_create_res(sess, rdata, 0, NULL, &tdata);
2527     if (status != PJ_SUCCESS) {
2528         pj_mutex_unlock(ice->mutex);
2529         return status;
2530     }
2531
2532     /* Add XOR-MAPPED-ADDRESS attribute */
2533     status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
2534                                            PJ_STUN_ATTR_XOR_MAPPED_ADDR,
2535                                            PJ_TRUE, src_addr, src_addr_len);
2536
2537     /* Create a msg_data to be associated with this response */
2538     msg_data = PJ_POOL_ZALLOC_T(tdata->pool, pj_ice_msg_data);
2539     msg_data->transport_id = ((pj_ice_msg_data*)token)->transport_id;
2540     msg_data->has_req_data = PJ_FALSE;
2541
2542     /* Send the response */
2543     status = pj_stun_session_send_msg(sess, msg_data, PJ_TRUE, PJ_TRUE,
2544                                       src_addr, src_addr_len, tdata);
2545
2546
2547     /* 
2548      * Handling early check.
2549      *
2550      * It's possible that we receive this request before we receive SDP
2551      * answer. In this case, we can't perform trigger check since we
2552      * don't have checklist yet, so just save this check in a pending
2553      * triggered check array to be acted upon later.
2554      */
2555     if (ice->rcand_cnt == 0) {
2556         rcheck = PJ_POOL_ZALLOC_T(ice->pool, pj_ice_rx_check);
2557     } else {
2558         rcheck = &tmp_rcheck;
2559     }
2560
2561     /* Init rcheck */
2562     rcheck->comp_id = sd->comp_id;
2563     rcheck->transport_id = ((pj_ice_msg_data*)token)->transport_id;
2564     rcheck->src_addr_len = src_addr_len;
2565     pj_memcpy(&rcheck->src_addr, src_addr, src_addr_len);
2566     rcheck->use_candidate = (uc_attr != NULL);
2567     rcheck->priority = prio_attr->value;
2568     rcheck->role_attr = role_attr;
2569
2570     if (ice->rcand_cnt == 0) {
2571         /* We don't have answer yet, so keep this request for later */
2572         LOG4((ice->obj_name, "Received an early check for comp %d",
2573               rcheck->comp_id));
2574         pj_list_push_back(&ice->early_check, rcheck);
2575     } else {
2576         /* Handle this check */
2577         handle_incoming_check(ice, rcheck);
2578     }
2579
2580     pj_mutex_unlock(ice->mutex);
2581     return PJ_SUCCESS;
2582 }
2583
2584
2585 /* Handle incoming Binding request and perform triggered check.
2586  * This function may be called by on_stun_rx_request(), or when
2587  * SDP answer is received and we have received early checks.
2588  */
2589 static void handle_incoming_check(pj_ice_sess *ice,
2590                                   const pj_ice_rx_check *rcheck)
2591 {
2592     pj_ice_sess_comp *comp;
2593     pj_ice_sess_cand *lcand = NULL;
2594     pj_ice_sess_cand *rcand;
2595     unsigned i;
2596
2597     comp = find_comp(ice, rcheck->comp_id);
2598
2599     /* Find remote candidate based on the source transport address of 
2600      * the request.
2601      */
2602     for (i=0; i<ice->rcand_cnt; ++i) {
2603         if (sockaddr_cmp(&rcheck->src_addr, &ice->rcand[i].addr)==0)
2604             break;
2605     }
2606
2607     /* 7.2.1.3.  Learning Peer Reflexive Candidates
2608      * If the source transport address of the request does not match any
2609      * existing remote candidates, it represents a new peer reflexive remote
2610      * candidate.
2611      */
2612     if (i == ice->rcand_cnt) {
2613         if (ice->rcand_cnt >= PJ_ICE_MAX_CAND) {
2614             LOG4((ice->obj_name, 
2615                   "Unable to add new peer reflexive candidate: too many "
2616                   "candidates already (%d)", PJ_ICE_MAX_CAND));
2617             return;
2618         }
2619
2620         rcand = &ice->rcand[ice->rcand_cnt++];
2621         rcand->comp_id = (pj_uint8_t)rcheck->comp_id;
2622         rcand->type = PJ_ICE_CAND_TYPE_PRFLX;
2623         rcand->prio = rcheck->priority;
2624         pj_memcpy(&rcand->addr, &rcheck->src_addr, rcheck->src_addr_len);
2625
2626         /* Foundation is random, unique from other foundation */
2627         rcand->foundation.ptr = (char*) pj_pool_alloc(ice->pool, 36);
2628         rcand->foundation.slen = pj_ansi_snprintf(rcand->foundation.ptr, 36,
2629                                                   "f%p", 
2630                                                   rcand->foundation.ptr);
2631
2632         LOG4((ice->obj_name, 
2633              "Added new remote candidate from the request: %s:%d",
2634              pj_inet_ntoa(rcand->addr.ipv4.sin_addr),
2635              (int)pj_ntohs(rcand->addr.ipv4.sin_port)));
2636
2637     } else {
2638         /* Remote candidate found */
2639         rcand = &ice->rcand[i];
2640     }
2641
2642 #if 0
2643     /* Find again the local candidate by matching the base address
2644      * with the local candidates in the checklist. Checks may have
2645      * been pruned before, so it's possible that if we use the lcand
2646      * as it is, we wouldn't be able to find the check in the checklist
2647      * and we will end up creating a new check unnecessarily.
2648      */
2649     for (i=0; i<ice->clist.count; ++i) {
2650         pj_ice_sess_check *c = &ice->clist.checks[i];
2651         if (/*c->lcand == lcand ||*/
2652             sockaddr_cmp(&c->lcand->base_addr, &lcand->base_addr)==0)
2653         {
2654             lcand = c->lcand;
2655             break;
2656         }
2657     }
2658 #else
2659     /* Just get candidate with the highest priority and same transport ID
2660      * for the specified  component ID in the checklist.
2661      */
2662     for (i=0; i<ice->clist.count; ++i) {
2663         pj_ice_sess_check *c = &ice->clist.checks[i];
2664         if (c->lcand->comp_id == rcheck->comp_id &&
2665             c->lcand->transport_id == rcheck->transport_id) 
2666         {
2667             lcand = c->lcand;
2668             break;
2669         }
2670     }
2671     if (lcand == NULL) {
2672         /* Should not happen, but just in case remote is sending a
2673          * Binding request for a component which it doesn't have.
2674          */
2675         LOG4((ice->obj_name, 
2676              "Received Binding request but no local candidate is found!"));
2677         return;
2678     }
2679 #endif
2680
2681     /* 
2682      * Create candidate pair for this request. 
2683      */
2684
2685     /* 
2686      * 7.2.1.4.  Triggered Checks
2687      *
2688      * Now that we have local and remote candidate, check if we already
2689      * have this pair in our checklist.
2690      */
2691     for (i=0; i<ice->clist.count; ++i) {
2692         pj_ice_sess_check *c = &ice->clist.checks[i];
2693         if (c->lcand == lcand && c->rcand == rcand)
2694             break;
2695     }
2696
2697     /* If the pair is already on the check list:
2698      * - If the state of that pair is Waiting or Frozen, its state is
2699      *   changed to In-Progress and a check for that pair is performed
2700      *   immediately.  This is called a triggered check.
2701      *
2702      * - If the state of that pair is In-Progress, the agent SHOULD
2703      *   generate an immediate retransmit of the Binding Request for the
2704      *   check in progress.  This is to facilitate rapid completion of
2705      *   ICE when both agents are behind NAT.
2706      * 
2707      * - If the state of that pair is Failed or Succeeded, no triggered
2708      *   check is sent.
2709      */
2710     if (i != ice->clist.count) {
2711         pj_ice_sess_check *c = &ice->clist.checks[i];
2712
2713         /* If USE-CANDIDATE is present, set nominated flag 
2714          * Note: DO NOT overwrite nominated flag if one is already set.
2715          */
2716         c->nominated = ((rcheck->use_candidate) || c->nominated);
2717
2718         if (c->state == PJ_ICE_SESS_CHECK_STATE_FROZEN ||
2719             c->state == PJ_ICE_SESS_CHECK_STATE_WAITING)
2720         {
2721             /* See if we shall nominate this check */
2722             pj_bool_t nominate = (c->nominated || ice->is_nominating);
2723
2724             LOG5((ice->obj_name, "Performing triggered check for check %d",i));
2725             pj_log_push_indent();
2726             perform_check(ice, &ice->clist, i, nominate);
2727             pj_log_pop_indent();
2728
2729         } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) {
2730             /* Should retransmit immediately
2731              */
2732             LOG5((ice->obj_name, "Triggered check for check %d not performed "
2733                   "because it's in progress. Retransmitting", i));
2734             pj_log_push_indent();
2735             pj_stun_session_retransmit_req(comp->stun_sess, c->tdata);
2736             pj_log_pop_indent();
2737
2738         } else if (c->state == PJ_ICE_SESS_CHECK_STATE_SUCCEEDED) {
2739             /* Check complete for this component.
2740              * Note this may end ICE process.
2741              */
2742             pj_bool_t complete;
2743             unsigned j;
2744
2745             /* If this check is nominated, scan the valid_list for the
2746              * same check and update the nominated flag. A controlled 
2747              * agent might have finished the check earlier.
2748              */
2749             if (rcheck->use_candidate) {
2750                 for (j=0; j<ice->valid_list.count; ++j) {
2751                     pj_ice_sess_check *vc = &ice->valid_list.checks[j];
2752                     if (vc->lcand->transport_id == c->lcand->transport_id && 
2753                         vc->rcand == c->rcand) 
2754                     {
2755                         /* Set nominated flag */
2756                         vc->nominated = PJ_TRUE;
2757
2758                         /* Update valid check and nominated check for the component */
2759                         update_comp_check(ice, vc->lcand->comp_id, vc);
2760
2761                         LOG5((ice->obj_name, "Valid check %s is nominated", 
2762                               dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), 
2763                                          &ice->valid_list, vc)));
2764                     }
2765                 }
2766             }
2767
2768             LOG5((ice->obj_name, "Triggered check for check %d not performed "
2769                                 "because it's completed", i));
2770             pj_log_push_indent();
2771             complete = on_check_complete(ice, c);
2772             pj_log_pop_indent();
2773             if (complete) {
2774                 return;
2775             }
2776         }
2777
2778     }
2779     /* If the pair is not already on the check list:
2780      * - The pair is inserted into the check list based on its priority.
2781      * - Its state is set to In-Progress
2782      * - A triggered check for that pair is performed immediately.
2783      */
2784     /* Note: only do this if we don't have too many checks in checklist */
2785     else if (ice->clist.count < PJ_ICE_MAX_CHECKS) {
2786
2787         pj_ice_sess_check *c = &ice->clist.checks[ice->clist.count];
2788         pj_bool_t nominate;
2789
2790         c->lcand = lcand;
2791         c->rcand = rcand;
2792         c->prio = CALC_CHECK_PRIO(ice, lcand, rcand);
2793         c->state = PJ_ICE_SESS_CHECK_STATE_WAITING;
2794         c->nominated = rcheck->use_candidate;
2795         c->err_code = PJ_SUCCESS;
2796
2797         nominate = (c->nominated || ice->is_nominating);
2798
2799         LOG4((ice->obj_name, "New triggered check added: %d", 
2800              ice->clist.count));
2801         pj_log_push_indent();
2802         perform_check(ice, &ice->clist, ice->clist.count++, nominate);
2803         pj_log_pop_indent();
2804
2805     } else {
2806         LOG4((ice->obj_name, "Error: unable to perform triggered check: "
2807              "TOO MANY CHECKS IN CHECKLIST!"));
2808     }
2809 }
2810
2811
2812 static pj_status_t on_stun_rx_indication(pj_stun_session *sess,
2813                                          const pj_uint8_t *pkt,
2814                                          unsigned pkt_len,
2815                                          const pj_stun_msg *msg,
2816                                          void *token,
2817                                          const pj_sockaddr_t *src_addr,
2818                                          unsigned src_addr_len)
2819 {
2820     struct stun_data *sd;
2821
2822     PJ_UNUSED_ARG(sess);
2823     PJ_UNUSED_ARG(pkt);
2824     PJ_UNUSED_ARG(pkt_len);
2825     PJ_UNUSED_ARG(msg);
2826     PJ_UNUSED_ARG(token);
2827     PJ_UNUSED_ARG(src_addr);
2828     PJ_UNUSED_ARG(src_addr_len);
2829
2830     sd = (struct stun_data*) pj_stun_session_get_user_data(sess);
2831
2832     pj_log_push_indent();
2833
2834     if (msg->hdr.type == PJ_STUN_BINDING_INDICATION) {
2835         LOG5((sd->ice->obj_name, "Received Binding Indication keep-alive "
2836               "for component %d", sd->comp_id));
2837     } else {
2838         LOG4((sd->ice->obj_name, "Received unexpected %s indication "
2839               "for component %d", pj_stun_get_method_name(msg->hdr.type), 
2840               sd->comp_id));
2841     }
2842
2843     pj_log_pop_indent();
2844
2845     return PJ_SUCCESS;
2846 }
2847
2848
2849 PJ_DEF(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice,
2850                                           unsigned comp_id,
2851                                           const void *data,
2852                                           pj_size_t data_len)
2853 {
2854     pj_status_t status = PJ_SUCCESS;
2855     pj_ice_sess_comp *comp;
2856     pj_ice_sess_cand *cand;
2857     pj_uint8_t transport_id;
2858     pj_sockaddr addr;
2859
2860     PJ_ASSERT_RETURN(ice && comp_id, PJ_EINVAL);
2861     
2862     /* It is possible that comp_cnt is less than comp_id, when remote
2863      * doesn't support all the components that we have.
2864      */
2865     if (comp_id > ice->comp_cnt) {
2866         return PJNATH_EICEINCOMPID;
2867     }
2868
2869     pj_mutex_lock(ice->mutex);
2870
2871     comp = find_comp(ice, comp_id);
2872     if (comp == NULL) {
2873         status = PJNATH_EICEINCOMPID;
2874         pj_mutex_unlock(ice->mutex);
2875         goto on_return;
2876     }
2877
2878     if (comp->valid_check == NULL) {
2879         status = PJNATH_EICEINPROGRESS;
2880         pj_mutex_unlock(ice->mutex);
2881         goto on_return;
2882     }
2883
2884     cand = comp->valid_check->lcand;
2885     transport_id = cand->transport_id;
2886     pj_sockaddr_cp(&addr, &comp->valid_check->rcand->addr);
2887
2888     /* Release the mutex now to avoid deadlock (see ticket #1451). */
2889     pj_mutex_unlock(ice->mutex);
2890
2891     status = (*ice->cb.on_tx_pkt)(ice, comp_id, transport_id, 
2892                                   data, data_len, 
2893                                   &addr, 
2894                                   sizeof(pj_sockaddr_in));
2895
2896 on_return:
2897     return status;
2898 }
2899
2900
2901 PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice,
2902                                           unsigned comp_id,
2903                                           unsigned transport_id,
2904                                           void *pkt,
2905                                           pj_size_t pkt_size,
2906                                           const pj_sockaddr_t *src_addr,
2907                                           int src_addr_len)
2908 {
2909     pj_status_t status = PJ_SUCCESS;
2910     pj_ice_sess_comp *comp;
2911     pj_ice_msg_data *msg_data = NULL;
2912     unsigned i;
2913
2914     PJ_ASSERT_RETURN(ice, PJ_EINVAL);
2915
2916     pj_mutex_lock(ice->mutex);
2917
2918     comp = find_comp(ice, comp_id);
2919     if (comp == NULL) {
2920         pj_mutex_unlock(ice->mutex);
2921         return PJNATH_EICEINCOMPID;
2922     }
2923
2924     /* Find transport */
2925     for (i=0; i<PJ_ARRAY_SIZE(ice->tp_data); ++i) {
2926         if (ice->tp_data[i].transport_id == transport_id) {
2927             msg_data = &ice->tp_data[i];
2928             break;
2929         }
2930     }
2931     if (msg_data == NULL) {
2932         pj_assert(!"Invalid transport ID");
2933         pj_mutex_unlock(ice->mutex);
2934         return PJ_EINVAL;
2935     }
2936
2937     /* Don't check fingerprint. We only need to distinguish STUN and non-STUN
2938      * packets. We don't need to verify the STUN packet too rigorously, that
2939      * will be done by the user.
2940      */
2941     status = pj_stun_msg_check((const pj_uint8_t*)pkt, pkt_size, 
2942                                PJ_STUN_IS_DATAGRAM |
2943                                  PJ_STUN_NO_FINGERPRINT_CHECK);
2944     if (status == PJ_SUCCESS) {
2945         status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size,
2946                                            PJ_STUN_IS_DATAGRAM, msg_data,
2947                                            NULL, src_addr, src_addr_len);
2948         if (status != PJ_SUCCESS) {
2949             pj_strerror(status, ice->tmp.errmsg, sizeof(ice->tmp.errmsg));
2950             LOG4((ice->obj_name, "Error processing incoming message: %s",
2951                   ice->tmp.errmsg));
2952         }
2953         pj_mutex_unlock(ice->mutex);
2954     } else {
2955         /* Not a STUN packet. Call application's callback instead, but release
2956          * the mutex now or otherwise we may get deadlock.
2957          */
2958         pj_mutex_unlock(ice->mutex);
2959
2960         (*ice->cb.on_rx_data)(ice, comp_id, transport_id, pkt, pkt_size, 
2961                               src_addr, src_addr_len);
2962         status = PJ_SUCCESS;
2963     }
2964
2965     return status;
2966 }
2967
2968