Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjnath / src / pjnath / turn_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/turn_session.h>
21 #include <pjnath/errno.h>
22 #include <pjlib-util/srv_resolver.h>
23 #include <pj/addr_resolv.h>
24 #include <pj/assert.h>
25 #include <pj/errno.h>
26 #include <pj/hash.h>
27 #include <pj/lock.h>
28 #include <pj/log.h>
29 #include <pj/os.h>
30 #include <pj/pool.h>
31 #include <pj/rand.h>
32 #include <pj/sock.h>
33
34 #define PJ_TURN_CHANNEL_MIN         0x4000
35 #define PJ_TURN_CHANNEL_MAX         0x7FFF  /* inclusive */
36 #define PJ_TURN_CHANNEL_HTABLE_SIZE 8
37 #define PJ_TURN_PERM_HTABLE_SIZE    8
38
39 static const char *state_names[] = 
40 {
41     "Null",
42     "Resolving",
43     "Resolved",
44     "Allocating",
45     "Ready",
46     "Deallocating",
47     "Deallocated",
48     "Destroying"
49 };
50
51 enum timer_id_t
52 {
53     TIMER_NONE,
54     TIMER_KEEP_ALIVE,
55     TIMER_DESTROY
56 };
57
58 /* This structure describes a channel binding. A channel binding is index by
59  * the channel number or IP address and port number of the peer.
60  */
61 struct ch_t
62 {
63     /* The channel number */
64     pj_uint16_t     num;
65
66     /* PJ_TRUE if we've received successful response to ChannelBind request
67      * for this channel.
68      */
69     pj_bool_t       bound;
70
71     /* The peer IP address and port */
72     pj_sockaddr     addr;
73
74     /* The channel binding expiration */
75     pj_time_val     expiry;
76 };
77
78
79 /* This structure describes a permission. A permission is identified by the
80  * IP address only.
81  */
82 struct perm_t
83 {
84     /* Cache of hash value to speed-up lookup */
85     pj_uint32_t     hval;
86
87     /* The permission IP address. The port number MUST be zero */
88     pj_sockaddr     addr;
89
90     /* Number of peers that uses this permission. */
91     unsigned        peer_cnt;
92
93     /* Automatically renew this permission once it expires? */
94     pj_bool_t       renew;
95
96     /* The permission expiration */
97     pj_time_val     expiry;
98
99     /* Arbitrary/random pointer value (token) to map this perm with the 
100      * request to create it. It is used to invalidate this perm when the 
101      * request fails.
102      */
103     void           *req_token;
104 };
105
106
107 /* The TURN client session structure */
108 struct pj_turn_session
109 {
110     pj_pool_t           *pool;
111     const char          *obj_name;
112     pj_turn_session_cb   cb;
113     void                *user_data;
114     pj_stun_config       stun_cfg;
115
116     pj_lock_t           *lock;
117     int                  busy;
118
119     pj_turn_state_t      state;
120     pj_status_t          last_status;
121     pj_bool_t            pending_destroy;
122     pj_bool_t            destroy_notified;
123
124     pj_stun_session     *stun;
125
126     unsigned             lifetime;
127     int                  ka_interval;
128     pj_time_val          expiry;
129
130     pj_timer_heap_t     *timer_heap;
131     pj_timer_entry       timer;
132
133     pj_dns_srv_async_query *dns_async;
134     pj_uint16_t          default_port;
135
136     pj_uint16_t          af;
137     pj_turn_tp_type      conn_type;
138     pj_uint16_t          srv_addr_cnt;
139     pj_sockaddr         *srv_addr_list;
140     pj_sockaddr         *srv_addr;
141
142     pj_bool_t            pending_alloc;
143     pj_turn_alloc_param  alloc_param;
144
145     pj_sockaddr          mapped_addr;
146     pj_sockaddr          relay_addr;
147
148     pj_hash_table_t     *ch_table;
149     pj_hash_table_t     *perm_table;
150
151     pj_uint32_t          send_ind_tsx_id[3];
152     /* tx_pkt must be 16bit aligned */
153     pj_uint8_t           tx_pkt[PJ_TURN_MAX_PKT_LEN];
154
155     pj_uint16_t          next_ch;
156 };
157
158
159 /*
160  * Prototypes.
161  */
162 static void sess_shutdown(pj_turn_session *sess,
163                           pj_status_t status);
164 static void do_destroy(pj_turn_session *sess);
165 static void send_refresh(pj_turn_session *sess, int lifetime);
166 static pj_status_t stun_on_send_msg(pj_stun_session *sess,
167                                     void *token,
168                                     const void *pkt,
169                                     pj_size_t pkt_size,
170                                     const pj_sockaddr_t *dst_addr,
171                                     unsigned addr_len);
172 static void stun_on_request_complete(pj_stun_session *sess,
173                                      pj_status_t status,
174                                      void *token,
175                                      pj_stun_tx_data *tdata,
176                                      const pj_stun_msg *response,
177                                      const pj_sockaddr_t *src_addr,
178                                      unsigned src_addr_len);
179 static pj_status_t stun_on_rx_indication(pj_stun_session *sess,
180                                          const pj_uint8_t *pkt,
181                                          unsigned pkt_len,
182                                          const pj_stun_msg *msg,
183                                          void *token,
184                                          const pj_sockaddr_t *src_addr,
185                                          unsigned src_addr_len);
186 static void dns_srv_resolver_cb(void *user_data,
187                                 pj_status_t status,
188                                 const pj_dns_srv_record *rec);
189 static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess,
190                                       const pj_sockaddr_t *addr,
191                                       unsigned addr_len,
192                                       pj_bool_t update,
193                                       pj_bool_t bind_channel);
194 static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess,
195                                        pj_uint16_t chnum);
196 static struct perm_t *lookup_perm(pj_turn_session *sess,
197                                   const pj_sockaddr_t *addr,
198                                   unsigned addr_len,
199                                   pj_bool_t update);
200 static void invalidate_perm(pj_turn_session *sess,
201                             struct perm_t *perm);
202 static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e);
203
204
205 /*
206  * Create default pj_turn_alloc_param.
207  */
208 PJ_DEF(void) pj_turn_alloc_param_default(pj_turn_alloc_param *prm)
209 {
210     pj_bzero(prm, sizeof(*prm));
211 }
212
213 /*
214  * Duplicate pj_turn_alloc_param.
215  */
216 PJ_DEF(void) pj_turn_alloc_param_copy( pj_pool_t *pool, 
217                                        pj_turn_alloc_param *dst,
218                                        const pj_turn_alloc_param *src)
219 {
220     PJ_UNUSED_ARG(pool);
221     pj_memcpy(dst, src, sizeof(*dst));
222 }
223
224 /*
225  * Get TURN state name.
226  */
227 PJ_DEF(const char*) pj_turn_state_name(pj_turn_state_t state)
228 {
229     return state_names[state];
230 }
231
232 /*
233  * Create TURN client session.
234  */
235 PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg,
236                                             const char *name,
237                                             int af,
238                                             pj_turn_tp_type conn_type,
239                                             const pj_turn_session_cb *cb,
240                                             unsigned options,
241                                             void *user_data,
242                                             pj_turn_session **p_sess)
243 {
244     pj_pool_t *pool;
245     pj_turn_session *sess;
246     pj_stun_session_cb stun_cb;
247     pj_lock_t *null_lock;
248     pj_status_t status;
249
250     PJ_ASSERT_RETURN(cfg && cfg->pf && cb && p_sess, PJ_EINVAL);
251     PJ_ASSERT_RETURN(cb->on_send_pkt, PJ_EINVAL);
252
253     PJ_UNUSED_ARG(options);
254
255     if (name == NULL)
256         name = "turn%p";
257
258     /* Allocate and create TURN session */
259     pool = pj_pool_create(cfg->pf, name, PJNATH_POOL_LEN_TURN_SESS,
260                           PJNATH_POOL_INC_TURN_SESS, NULL);
261     sess = PJ_POOL_ZALLOC_T(pool, pj_turn_session);
262     sess->pool = pool;
263     sess->obj_name = pool->obj_name;
264     sess->timer_heap = cfg->timer_heap;
265     sess->af = (pj_uint16_t)af;
266     sess->conn_type = conn_type;
267     sess->ka_interval = PJ_TURN_KEEP_ALIVE_SEC;
268     sess->user_data = user_data;
269     sess->next_ch = PJ_TURN_CHANNEL_MIN;
270
271     /* Copy STUN session */
272     pj_memcpy(&sess->stun_cfg, cfg, sizeof(pj_stun_config));
273
274     /* Copy callback */
275     pj_memcpy(&sess->cb, cb, sizeof(*cb));
276
277     /* Peer hash table */
278     sess->ch_table = pj_hash_create(pool, PJ_TURN_CHANNEL_HTABLE_SIZE);
279
280     /* Permission hash table */
281     sess->perm_table = pj_hash_create(pool, PJ_TURN_PERM_HTABLE_SIZE);
282
283     /* Session lock */
284     status = pj_lock_create_recursive_mutex(pool, sess->obj_name, 
285                                             &sess->lock);
286     if (status != PJ_SUCCESS) {
287         do_destroy(sess);
288         return status;
289     }
290
291     /* Timer */
292     pj_timer_entry_init(&sess->timer, TIMER_NONE, sess, &on_timer_event);
293
294     /* Create STUN session */
295     pj_bzero(&stun_cb, sizeof(stun_cb));
296     stun_cb.on_send_msg = &stun_on_send_msg;
297     stun_cb.on_request_complete = &stun_on_request_complete;
298     stun_cb.on_rx_indication = &stun_on_rx_indication;
299     status = pj_stun_session_create(&sess->stun_cfg, sess->obj_name, &stun_cb,
300                                     PJ_FALSE, &sess->stun);
301     if (status != PJ_SUCCESS) {
302         do_destroy(sess);
303         return status;
304     }
305
306     /* Attach ourself to STUN session */
307     pj_stun_session_set_user_data(sess->stun, sess);
308
309     /* Replace mutex in STUN session with a NULL mutex, since access to
310      * STUN session is serialized.
311      */
312     status = pj_lock_create_null_mutex(pool, name, &null_lock);
313     if (status != PJ_SUCCESS) {
314         do_destroy(sess);
315         return status;
316     }
317     pj_stun_session_set_lock(sess->stun, null_lock, PJ_TRUE);
318
319     /* Done */
320
321     PJ_LOG(4,(sess->obj_name, "TURN client session created"));
322
323     *p_sess = sess;
324     return PJ_SUCCESS;
325 }
326
327
328 /* Destroy */
329 static void do_destroy(pj_turn_session *sess)
330 {
331     /* Lock session */
332     if (sess->lock) {
333         pj_lock_acquire(sess->lock);
334     }
335
336     /* Cancel pending timer, if any */
337     if (sess->timer.id != TIMER_NONE) {
338         pj_timer_heap_cancel(sess->timer_heap, &sess->timer);
339         sess->timer.id = TIMER_NONE;
340     }
341
342     /* Destroy STUN session */
343     if (sess->stun) {
344         pj_stun_session_destroy(sess->stun);
345         sess->stun = NULL;
346     }
347
348     /* Destroy lock */
349     if (sess->lock) {
350         pj_lock_release(sess->lock);
351         pj_lock_destroy(sess->lock);
352         sess->lock = NULL;
353     }
354
355     /* Destroy pool */
356     if (sess->pool) {
357         pj_pool_t *pool = sess->pool;
358
359         PJ_LOG(4,(sess->obj_name, "TURN client session destroyed"));
360
361         sess->pool = NULL;
362         pj_pool_release(pool);
363     }
364 }
365
366
367 /* Set session state */
368 static void set_state(pj_turn_session *sess, enum pj_turn_state_t state)
369 {
370     pj_turn_state_t old_state = sess->state;
371
372     if (state==sess->state)
373         return;
374
375     PJ_LOG(4,(sess->obj_name, "State changed %s --> %s",
376               state_names[old_state], state_names[state]));
377     sess->state = state;
378
379     if (sess->cb.on_state) {
380         (*sess->cb.on_state)(sess, old_state, state);
381     }
382 }
383
384 /*
385  * Notify application and shutdown the TURN session.
386  */
387 static void sess_shutdown(pj_turn_session *sess,
388                           pj_status_t status)
389 {
390     pj_bool_t can_destroy = PJ_TRUE;
391
392     PJ_LOG(4,(sess->obj_name, "Request to shutdown in state %s, cause:%d",
393               state_names[sess->state], status));
394
395     if (sess->last_status == PJ_SUCCESS && status != PJ_SUCCESS)
396         sess->last_status = status;
397
398     switch (sess->state) {
399     case PJ_TURN_STATE_NULL:
400         break;
401     case PJ_TURN_STATE_RESOLVING:
402         if (sess->dns_async != NULL) {
403             pj_dns_srv_cancel_query(sess->dns_async, PJ_FALSE);
404             sess->dns_async = NULL;
405         }
406         break;
407     case PJ_TURN_STATE_RESOLVED:
408         break;
409     case PJ_TURN_STATE_ALLOCATING:
410         /* We need to wait until allocation complete */
411         sess->pending_destroy = PJ_TRUE;
412         can_destroy = PJ_FALSE;
413         break;
414     case PJ_TURN_STATE_READY:
415         /* Send REFRESH with LIFETIME=0 */
416         can_destroy = PJ_FALSE;
417         send_refresh(sess, 0);
418         break;
419     case PJ_TURN_STATE_DEALLOCATING:
420         can_destroy = PJ_FALSE;
421         /* This may recursively call this function again with
422          * state==PJ_TURN_STATE_DEALLOCATED.
423          */
424         send_refresh(sess, 0);
425         break;
426     case PJ_TURN_STATE_DEALLOCATED:
427     case PJ_TURN_STATE_DESTROYING:
428         break;
429     }
430
431     if (can_destroy) {
432         /* Schedule destroy */
433         pj_time_val delay = {0, 0};
434
435         set_state(sess, PJ_TURN_STATE_DESTROYING);
436
437         if (sess->timer.id != TIMER_NONE) {
438             pj_timer_heap_cancel(sess->timer_heap, &sess->timer);
439             sess->timer.id = TIMER_NONE;
440         }
441
442         sess->timer.id = TIMER_DESTROY;
443         pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &delay);
444     }
445 }
446
447
448 /*
449  * Public API to destroy TURN client session.
450  */
451 PJ_DEF(pj_status_t) pj_turn_session_shutdown(pj_turn_session *sess)
452 {
453     PJ_ASSERT_RETURN(sess, PJ_EINVAL);
454
455     pj_lock_acquire(sess->lock);
456
457     sess_shutdown(sess, PJ_SUCCESS);
458
459     pj_lock_release(sess->lock);
460
461     return PJ_SUCCESS;
462 }
463
464
465 /**
466  * Forcefully destroy the TURN session.
467  */
468 PJ_DEF(pj_status_t) pj_turn_session_destroy( pj_turn_session *sess,
469                                              pj_status_t last_err)
470 {
471     PJ_ASSERT_RETURN(sess, PJ_EINVAL);
472
473     if (last_err != PJ_SUCCESS && sess->last_status == PJ_SUCCESS)
474         sess->last_status = last_err;
475     set_state(sess, PJ_TURN_STATE_DEALLOCATED);
476     sess_shutdown(sess, PJ_SUCCESS);
477     return PJ_SUCCESS;
478 }
479
480
481 /*
482  * Get TURN session info.
483  */
484 PJ_DEF(pj_status_t) pj_turn_session_get_info( pj_turn_session *sess,
485                                               pj_turn_session_info *info)
486 {
487     pj_time_val now;
488
489     PJ_ASSERT_RETURN(sess && info, PJ_EINVAL);
490
491     pj_gettimeofday(&now);
492
493     info->state = sess->state;
494     info->conn_type = sess->conn_type;
495     info->lifetime = sess->expiry.sec - now.sec;
496     info->last_status = sess->last_status;
497
498     if (sess->srv_addr)
499         pj_memcpy(&info->server, sess->srv_addr, sizeof(info->server));
500     else
501         pj_bzero(&info->server, sizeof(info->server));
502
503     pj_memcpy(&info->mapped_addr, &sess->mapped_addr, 
504               sizeof(sess->mapped_addr));
505     pj_memcpy(&info->relay_addr, &sess->relay_addr, 
506               sizeof(sess->relay_addr));
507
508     return PJ_SUCCESS;
509 }
510
511
512 /*
513  * Re-assign user data.
514  */
515 PJ_DEF(pj_status_t) pj_turn_session_set_user_data( pj_turn_session *sess,
516                                                    void *user_data)
517 {
518     sess->user_data = user_data;
519     return PJ_SUCCESS;
520 }
521
522
523 /**
524  * Retrieve user data.
525  */
526 PJ_DEF(void*) pj_turn_session_get_user_data(pj_turn_session *sess)
527 {
528     return sess->user_data;
529 }
530
531
532 /*
533  * Configure message logging. By default all flags are enabled.
534  *
535  * @param sess          The TURN client session.
536  * @param flags         Bitmask combination of #pj_stun_sess_msg_log_flag
537  */
538 PJ_DEF(void) pj_turn_session_set_log( pj_turn_session *sess,
539                                       unsigned flags)
540 {
541     pj_stun_session_set_log(sess->stun, flags);
542 }
543
544
545 /*
546  * Set software name
547  */
548 PJ_DEF(pj_status_t) pj_turn_session_set_software_name( pj_turn_session *sess,
549                                                        const pj_str_t *sw)
550 {
551     pj_status_t status;
552
553     pj_lock_acquire(sess->lock);
554     status = pj_stun_session_set_software_name(sess->stun, sw);
555     pj_lock_release(sess->lock);
556
557     return status;
558 }
559
560
561 /**
562  * Set the server or domain name of the server.
563  */
564 PJ_DEF(pj_status_t) pj_turn_session_set_server( pj_turn_session *sess,
565                                                 const pj_str_t *domain,
566                                                 int default_port,
567                                                 pj_dns_resolver *resolver)
568 {
569     pj_sockaddr tmp_addr;
570     pj_bool_t is_ip_addr;
571     pj_status_t status;
572
573     PJ_ASSERT_RETURN(sess && domain, PJ_EINVAL);
574     PJ_ASSERT_RETURN(sess->state == PJ_TURN_STATE_NULL, PJ_EINVALIDOP);
575
576     pj_lock_acquire(sess->lock);
577
578     /* See if "domain" contains just IP address */
579     tmp_addr.addr.sa_family = sess->af;
580     status = pj_inet_pton(sess->af, domain, 
581                           pj_sockaddr_get_addr(&tmp_addr));
582     is_ip_addr = (status == PJ_SUCCESS);
583
584     if (!is_ip_addr && resolver) {
585         /* Resolve with DNS SRV resolution, and fallback to DNS A resolution
586          * if default_port is specified.
587          */
588         unsigned opt = 0;
589         pj_str_t res_name;
590
591         switch (sess->conn_type) {
592         case PJ_TURN_TP_UDP:
593             res_name = pj_str("_turn._udp.");
594             break;
595         case PJ_TURN_TP_TCP:
596             res_name = pj_str("_turn._tcp.");
597             break;
598         case PJ_TURN_TP_TLS:
599             res_name = pj_str("_turns._tcp.");
600             break;
601         default:
602             status = PJNATH_ETURNINTP;
603             goto on_return;
604         }
605
606         /* Fallback to DNS A only if default port is specified */
607         if (default_port>0 && default_port<65536) {
608             opt = PJ_DNS_SRV_FALLBACK_A;
609             sess->default_port = (pj_uint16_t)default_port;
610         }
611
612         PJ_LOG(5,(sess->obj_name, "Resolving %.*s%.*s with DNS SRV",
613                   (int)res_name.slen, res_name.ptr,
614                   (int)domain->slen, domain->ptr));
615         set_state(sess, PJ_TURN_STATE_RESOLVING);
616
617         /* User may have destroyed us in the callback */
618         if (sess->state != PJ_TURN_STATE_RESOLVING) {
619             status = PJ_ECANCELLED;
620             goto on_return;
621         }
622
623         status = pj_dns_srv_resolve(domain, &res_name, default_port, 
624                                     sess->pool, resolver, opt, sess, 
625                                     &dns_srv_resolver_cb, &sess->dns_async);
626         if (status != PJ_SUCCESS) {
627             set_state(sess, PJ_TURN_STATE_NULL);
628             goto on_return;
629         }
630
631     } else {
632         /* Resolver is not specified, resolve with standard gethostbyname().
633          * The default_port MUST be specified in this case.
634          */
635         pj_addrinfo *ai;
636         unsigned i, cnt;
637
638         /* Default port must be specified */
639         PJ_ASSERT_RETURN(default_port>0 && default_port<65536, PJ_EINVAL);
640         sess->default_port = (pj_uint16_t)default_port;
641
642         cnt = PJ_TURN_MAX_DNS_SRV_CNT;
643         ai = (pj_addrinfo*)
644              pj_pool_calloc(sess->pool, cnt, sizeof(pj_addrinfo));
645
646         PJ_LOG(5,(sess->obj_name, "Resolving %.*s with DNS A",
647                   (int)domain->slen, domain->ptr));
648         set_state(sess, PJ_TURN_STATE_RESOLVING);
649
650         /* User may have destroyed us in the callback */
651         if (sess->state != PJ_TURN_STATE_RESOLVING) {
652             status = PJ_ECANCELLED;
653             goto on_return;
654         }
655
656         status = pj_getaddrinfo(sess->af, domain, &cnt, ai);
657         if (status != PJ_SUCCESS)
658             goto on_return;
659
660         sess->srv_addr_cnt = (pj_uint16_t)cnt;
661         sess->srv_addr_list = (pj_sockaddr*)
662                               pj_pool_calloc(sess->pool, cnt, 
663                                              sizeof(pj_sockaddr));
664         for (i=0; i<cnt; ++i) {
665             pj_sockaddr *addr = &sess->srv_addr_list[i];
666             pj_memcpy(addr, &ai[i].ai_addr, sizeof(pj_sockaddr));
667             addr->addr.sa_family = sess->af;
668             addr->ipv4.sin_port = pj_htons(sess->default_port);
669         }
670
671         sess->srv_addr = &sess->srv_addr_list[0];
672         set_state(sess, PJ_TURN_STATE_RESOLVED);
673     }
674
675 on_return:
676     pj_lock_release(sess->lock);
677     return status;
678 }
679
680
681 /**
682  * Set credential to be used by the session.
683  */
684 PJ_DEF(pj_status_t) pj_turn_session_set_credential(pj_turn_session *sess,
685                                              const pj_stun_auth_cred *cred)
686 {
687     PJ_ASSERT_RETURN(sess && cred, PJ_EINVAL);
688     PJ_ASSERT_RETURN(sess->stun, PJ_EINVALIDOP);
689
690     pj_lock_acquire(sess->lock);
691
692     pj_stun_session_set_credential(sess->stun, PJ_STUN_AUTH_LONG_TERM, cred);
693
694     pj_lock_release(sess->lock);
695
696     return PJ_SUCCESS;
697 }
698
699
700 /**
701  * Create TURN allocation.
702  */
703 PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess,
704                                           const pj_turn_alloc_param *param)
705 {
706     pj_stun_tx_data *tdata;
707     pj_bool_t retransmit;
708     pj_status_t status;
709
710     PJ_ASSERT_RETURN(sess, PJ_EINVAL);
711     PJ_ASSERT_RETURN(sess->state>PJ_TURN_STATE_NULL && 
712                      sess->state<=PJ_TURN_STATE_RESOLVED, 
713                      PJ_EINVALIDOP);
714
715     pj_lock_acquire(sess->lock);
716
717     if (param && param != &sess->alloc_param) 
718         pj_turn_alloc_param_copy(sess->pool, &sess->alloc_param, param);
719
720     if (sess->state < PJ_TURN_STATE_RESOLVED) {
721         sess->pending_alloc = PJ_TRUE;
722
723         PJ_LOG(4,(sess->obj_name, "Pending ALLOCATE in state %s",
724                   state_names[sess->state]));
725
726         pj_lock_release(sess->lock);
727         return PJ_SUCCESS;
728
729     }
730
731     /* Ready to allocate */
732     pj_assert(sess->state == PJ_TURN_STATE_RESOLVED);
733     
734     /* Create a bare request */
735     status = pj_stun_session_create_req(sess->stun, PJ_STUN_ALLOCATE_REQUEST,
736                                         PJ_STUN_MAGIC, NULL, &tdata);
737     if (status != PJ_SUCCESS) {
738         pj_lock_release(sess->lock);
739         return status;
740     }
741
742     /* MUST include REQUESTED-TRANSPORT attribute */
743     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
744                               PJ_STUN_ATTR_REQ_TRANSPORT, 
745                               PJ_STUN_SET_RT_PROTO(PJ_TURN_TP_UDP));
746
747     /* Include BANDWIDTH if requested */
748     if (sess->alloc_param.bandwidth > 0) {
749         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
750                                   PJ_STUN_ATTR_BANDWIDTH,
751                                   sess->alloc_param.bandwidth);
752     }
753
754     /* Include LIFETIME if requested */
755     if (sess->alloc_param.lifetime > 0) {
756         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
757                                   PJ_STUN_ATTR_LIFETIME,
758                                   sess->alloc_param.lifetime);
759     }
760
761     /* Server address must be set */
762     pj_assert(sess->srv_addr != NULL);
763
764     /* Send request */
765     set_state(sess, PJ_TURN_STATE_ALLOCATING);
766     retransmit = (sess->conn_type == PJ_TURN_TP_UDP);
767     status = pj_stun_session_send_msg(sess->stun, NULL, PJ_FALSE, 
768                                       retransmit, sess->srv_addr,
769                                       pj_sockaddr_get_len(sess->srv_addr), 
770                                       tdata);
771     if (status != PJ_SUCCESS) {
772         /* Set state back to RESOLVED. We don't want to destroy session now,
773          * let the application do it if it wants to.
774          */
775         set_state(sess, PJ_TURN_STATE_RESOLVED);
776     }
777
778     pj_lock_release(sess->lock);
779     return status;
780 }
781
782
783 /*
784  * Install or renew permissions
785  */
786 PJ_DEF(pj_status_t) pj_turn_session_set_perm( pj_turn_session *sess,
787                                               unsigned addr_cnt,
788                                               const pj_sockaddr addr[],
789                                               unsigned options)
790 {
791     pj_stun_tx_data *tdata;
792     pj_hash_iterator_t it_buf, *it;
793     void *req_token;
794     unsigned i, attr_added=0;
795     pj_status_t status;
796
797     PJ_ASSERT_RETURN(sess && addr_cnt && addr, PJ_EINVAL);
798
799     pj_lock_acquire(sess->lock);
800
801     /* Create a bare CreatePermission request */
802     status = pj_stun_session_create_req(sess->stun, 
803                                         PJ_STUN_CREATE_PERM_REQUEST,
804                                         PJ_STUN_MAGIC, NULL, &tdata);
805     if (status != PJ_SUCCESS) {
806         pj_lock_release(sess->lock);
807         return status;
808     }
809
810     /* Create request token to map the request to the perm structures
811      * which the request belongs.
812      */
813     req_token = (void*)(long)pj_rand();
814
815     /* Process the addresses */
816     for (i=0; i<addr_cnt; ++i) {
817         struct perm_t *perm;
818
819         /* Lookup the perm structure and create if it doesn't exist */
820         perm = lookup_perm(sess, &addr[i], pj_sockaddr_get_len(&addr[i]),
821                            PJ_TRUE);
822         perm->renew = (options & 0x01);
823
824         /* Only add to the request if the request doesn't contain this
825          * address yet.
826          */
827         if (perm->req_token != req_token) {
828             perm->req_token = req_token;
829
830             /* Add XOR-PEER-ADDRESS */
831             status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
832                                                    PJ_STUN_ATTR_XOR_PEER_ADDR,
833                                                    PJ_TRUE,
834                                                    &addr[i],
835                                                    sizeof(addr[i]));
836             if (status != PJ_SUCCESS)
837                 goto on_error;
838
839             ++attr_added;
840         }
841     }
842
843     pj_assert(attr_added != 0);
844
845     /* Send the request */
846     status = pj_stun_session_send_msg(sess->stun, req_token, PJ_FALSE, 
847                                       (sess->conn_type==PJ_TURN_TP_UDP),
848                                       sess->srv_addr,
849                                       pj_sockaddr_get_len(sess->srv_addr), 
850                                       tdata);
851     if (status != PJ_SUCCESS) {
852         /* tdata is already destroyed */
853         tdata = NULL;
854         goto on_error;
855     }
856
857     pj_lock_release(sess->lock);
858     return PJ_SUCCESS;
859
860 on_error:
861     /* destroy tdata */
862     if (tdata) {
863         pj_stun_msg_destroy_tdata(sess->stun, tdata);
864     }
865     /* invalidate perm structures associated with this request */
866     it = pj_hash_first(sess->perm_table, &it_buf);
867     while (it) {
868         struct perm_t *perm = (struct perm_t*)
869                               pj_hash_this(sess->perm_table, it);
870         it = pj_hash_next(sess->perm_table, it);
871         if (perm->req_token == req_token)
872             invalidate_perm(sess, perm);
873     }
874     pj_lock_release(sess->lock);
875     return status;
876 }
877
878 /*
879  * Send REFRESH
880  */
881 static void send_refresh(pj_turn_session *sess, int lifetime)
882 {
883     pj_stun_tx_data *tdata;
884     pj_status_t status;
885
886     PJ_ASSERT_ON_FAIL(sess->state==PJ_TURN_STATE_READY, return);
887
888     /* Create a bare REFRESH request */
889     status = pj_stun_session_create_req(sess->stun, PJ_STUN_REFRESH_REQUEST,
890                                         PJ_STUN_MAGIC, NULL, &tdata);
891     if (status != PJ_SUCCESS)
892         goto on_error;
893
894     /* Add LIFETIME */
895     if (lifetime >= 0) {
896         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
897                                   PJ_STUN_ATTR_LIFETIME, lifetime);
898     }
899
900     /* Send request */
901     if (lifetime == 0) {
902         set_state(sess, PJ_TURN_STATE_DEALLOCATING);
903     }
904
905     status = pj_stun_session_send_msg(sess->stun, NULL, PJ_FALSE, 
906                                       (sess->conn_type==PJ_TURN_TP_UDP),
907                                       sess->srv_addr,
908                                       pj_sockaddr_get_len(sess->srv_addr), 
909                                       tdata);
910     if (status != PJ_SUCCESS)
911         goto on_error;
912
913     return;
914
915 on_error:
916     if (lifetime == 0) {
917         set_state(sess, PJ_TURN_STATE_DEALLOCATED);
918         sess_shutdown(sess, status);
919     }
920 }
921
922
923 /**
924  * Relay data to the specified peer through the session.
925  */
926 PJ_DEF(pj_status_t) pj_turn_session_sendto( pj_turn_session *sess,
927                                             const pj_uint8_t *pkt,
928                                             unsigned pkt_len,
929                                             const pj_sockaddr_t *addr,
930                                             unsigned addr_len)
931 {
932     struct ch_t *ch;
933     struct perm_t *perm;
934     pj_status_t status;
935
936     PJ_ASSERT_RETURN(sess && pkt && pkt_len && addr && addr_len, 
937                      PJ_EINVAL);
938
939     /* Return error if we're not ready */
940     if (sess->state != PJ_TURN_STATE_READY) {
941         return PJ_EIGNORED;
942     }
943
944     /* Lock session now */
945     pj_lock_acquire(sess->lock);
946
947     /* Lookup permission first */
948     perm = lookup_perm(sess, addr, pj_sockaddr_get_len(addr), PJ_FALSE);
949     if (perm == NULL) {
950         /* Permission doesn't exist, install it first */
951         char ipstr[PJ_INET6_ADDRSTRLEN+2];
952
953         PJ_LOG(4,(sess->obj_name, 
954                   "sendto(): IP %s has no permission, requesting it first..",
955                   pj_sockaddr_print(addr, ipstr, sizeof(ipstr), 2)));
956
957         status = pj_turn_session_set_perm(sess, 1, (const pj_sockaddr*)addr, 
958                                           0);
959         if (status != PJ_SUCCESS) {
960             pj_lock_release(sess->lock);
961             return status;
962         }
963     }
964
965     /* See if the peer is bound to a channel number */
966     ch = lookup_ch_by_addr(sess, addr, pj_sockaddr_get_len(addr), 
967                            PJ_FALSE, PJ_FALSE);
968     if (ch && ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound) {
969         unsigned total_len;
970
971         /* Peer is assigned a channel number, we can use ChannelData */
972         pj_turn_channel_data *cd = (pj_turn_channel_data*)sess->tx_pkt;
973         
974         pj_assert(sizeof(*cd)==4);
975
976         /* Calculate total length, including paddings */
977         total_len = (pkt_len + sizeof(*cd) + 3) & (~3);
978         if (total_len > sizeof(sess->tx_pkt)) {
979             status = PJ_ETOOBIG;
980             goto on_return;
981         }
982
983         cd->ch_number = pj_htons((pj_uint16_t)ch->num);
984         cd->length = pj_htons((pj_uint16_t)pkt_len);
985         pj_memcpy(cd+1, pkt, pkt_len);
986
987         pj_assert(sess->srv_addr != NULL);
988
989         status = sess->cb.on_send_pkt(sess, sess->tx_pkt, total_len,
990                                       sess->srv_addr,
991                                       pj_sockaddr_get_len(sess->srv_addr));
992
993     } else {
994         /* Use Send Indication. */
995         pj_stun_sockaddr_attr peer_attr;
996         pj_stun_binary_attr data_attr;
997         pj_stun_msg send_ind;
998         pj_size_t send_ind_len;
999
1000         /* Increment counter */
1001         ++sess->send_ind_tsx_id[2];
1002
1003         /* Create blank SEND-INDICATION */
1004         status = pj_stun_msg_init(&send_ind, PJ_STUN_SEND_INDICATION,
1005                                   PJ_STUN_MAGIC, 
1006                                   (const pj_uint8_t*)sess->send_ind_tsx_id);
1007         if (status != PJ_SUCCESS)
1008             goto on_return;
1009
1010         /* Add XOR-PEER-ADDRESS */
1011         pj_stun_sockaddr_attr_init(&peer_attr, PJ_STUN_ATTR_XOR_PEER_ADDR,
1012                                    PJ_TRUE, addr, addr_len);
1013         pj_stun_msg_add_attr(&send_ind, (pj_stun_attr_hdr*)&peer_attr);
1014
1015         /* Add DATA attribute */
1016         pj_stun_binary_attr_init(&data_attr, NULL, PJ_STUN_ATTR_DATA, NULL, 0);
1017         data_attr.data = (pj_uint8_t*)pkt;
1018         data_attr.length = pkt_len;
1019         pj_stun_msg_add_attr(&send_ind, (pj_stun_attr_hdr*)&data_attr);
1020
1021         /* Encode the message */
1022         status = pj_stun_msg_encode(&send_ind, sess->tx_pkt, 
1023                                     sizeof(sess->tx_pkt), 0,
1024                                     NULL, &send_ind_len);
1025         if (status != PJ_SUCCESS)
1026             goto on_return;
1027
1028         /* Send the Send Indication */
1029         status = sess->cb.on_send_pkt(sess, sess->tx_pkt, send_ind_len,
1030                                       sess->srv_addr,
1031                                       pj_sockaddr_get_len(sess->srv_addr));
1032     }
1033
1034 on_return:
1035     pj_lock_release(sess->lock);
1036     return status;
1037 }
1038
1039
1040 /**
1041  * Bind a peer address to a channel number.
1042  */
1043 PJ_DEF(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess,
1044                                                  const pj_sockaddr_t *peer_adr,
1045                                                  unsigned addr_len)
1046 {
1047     struct ch_t *ch;
1048     pj_stun_tx_data *tdata;
1049     pj_uint16_t ch_num;
1050     pj_status_t status;
1051
1052     PJ_ASSERT_RETURN(sess && peer_adr && addr_len, PJ_EINVAL);
1053     PJ_ASSERT_RETURN(sess->state == PJ_TURN_STATE_READY, PJ_EINVALIDOP);
1054
1055     pj_lock_acquire(sess->lock);
1056
1057     /* Create blank ChannelBind request */
1058     status = pj_stun_session_create_req(sess->stun, 
1059                                         PJ_STUN_CHANNEL_BIND_REQUEST,
1060                                         PJ_STUN_MAGIC, NULL, &tdata);
1061     if (status != PJ_SUCCESS)
1062         goto on_return;
1063
1064     /* Lookup if this peer has already been assigned a number */
1065     ch = lookup_ch_by_addr(sess, peer_adr, pj_sockaddr_get_len(peer_adr),
1066                            PJ_TRUE, PJ_FALSE);
1067     pj_assert(ch);
1068
1069     if (ch->num != PJ_TURN_INVALID_CHANNEL) {
1070         /* Channel is already bound. This is a refresh request. */
1071         ch_num = ch->num;
1072     } else {
1073         PJ_ASSERT_ON_FAIL(sess->next_ch <= PJ_TURN_CHANNEL_MAX, 
1074                             {status=PJ_ETOOMANY; goto on_return;});
1075         ch->num = ch_num = sess->next_ch++;
1076     }
1077
1078     /* Add CHANNEL-NUMBER attribute */
1079     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
1080                               PJ_STUN_ATTR_CHANNEL_NUMBER,
1081                               PJ_STUN_SET_CH_NB(ch_num));
1082
1083     /* Add XOR-PEER-ADDRESS attribute */
1084     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
1085                                   PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE,
1086                                   peer_adr, addr_len);
1087
1088     /* Send the request, associate peer data structure with tdata 
1089      * for future reference when we receive the ChannelBind response.
1090      */
1091     status = pj_stun_session_send_msg(sess->stun, ch, PJ_FALSE, 
1092                                       (sess->conn_type==PJ_TURN_TP_UDP),
1093                                       sess->srv_addr,
1094                                       pj_sockaddr_get_len(sess->srv_addr),
1095                                       tdata);
1096
1097 on_return:
1098     pj_lock_release(sess->lock);
1099     return status;
1100 }
1101
1102
1103 /**
1104  * Notify TURN client session upon receiving a packet from server.
1105  * The packet maybe a STUN packet or ChannelData packet.
1106  */
1107 PJ_DEF(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess,
1108                                               void *pkt,
1109                                               pj_size_t pkt_len,
1110                                               pj_size_t *parsed_len)
1111 {
1112     pj_bool_t is_stun;
1113     pj_status_t status;
1114     pj_bool_t is_datagram;
1115
1116     /* Packet could be ChannelData or STUN message (response or
1117      * indication).
1118      */
1119
1120     /* Start locking the session */
1121     pj_lock_acquire(sess->lock);
1122
1123     is_datagram = (sess->conn_type==PJ_TURN_TP_UDP);
1124
1125     /* Quickly check if this is STUN message */
1126     is_stun = ((((pj_uint8_t*)pkt)[0] & 0xC0) == 0);
1127
1128     if (is_stun) {
1129         /* This looks like STUN, give it to the STUN session */
1130         unsigned options;
1131
1132         options = PJ_STUN_CHECK_PACKET | PJ_STUN_NO_FINGERPRINT_CHECK;
1133         if (is_datagram)
1134             options |= PJ_STUN_IS_DATAGRAM;
1135         status=pj_stun_session_on_rx_pkt(sess->stun, pkt, pkt_len,
1136                                          options, NULL, parsed_len,
1137                                          sess->srv_addr,
1138                                          pj_sockaddr_get_len(sess->srv_addr));
1139
1140     } else {
1141         /* This must be ChannelData. */
1142         pj_turn_channel_data cd;
1143         struct ch_t *ch;
1144
1145         if (pkt_len < 4) {
1146             if (parsed_len) *parsed_len = 0;
1147             return PJ_ETOOSMALL;
1148         }
1149
1150         /* Decode ChannelData packet */
1151         pj_memcpy(&cd, pkt, sizeof(pj_turn_channel_data));
1152         cd.ch_number = pj_ntohs(cd.ch_number);
1153         cd.length = pj_ntohs(cd.length);
1154
1155         /* Check that size is sane */
1156         if (pkt_len < cd.length+sizeof(cd)) {
1157             if (parsed_len) {
1158                 if (is_datagram) {
1159                     /* Discard the datagram */
1160                     *parsed_len = pkt_len;
1161                 } else {
1162                     /* Insufficient fragment */
1163                     *parsed_len = 0;
1164                 }
1165             }
1166             status = PJ_ETOOSMALL;
1167             goto on_return;
1168         } else {
1169             if (parsed_len) {
1170                 /* Apply padding too */
1171                 *parsed_len = ((cd.length + 3) & (~3)) + sizeof(cd);
1172             }
1173         }
1174
1175         /* Lookup channel */
1176         ch = lookup_ch_by_chnum(sess, cd.ch_number);
1177         if (!ch || !ch->bound) {
1178             status = PJ_ENOTFOUND;
1179             goto on_return;
1180         }
1181
1182         /* Notify application */
1183         if (sess->cb.on_rx_data) {
1184             (*sess->cb.on_rx_data)(sess, ((pj_uint8_t*)pkt)+sizeof(cd), 
1185                                    cd.length, &ch->addr,
1186                                    pj_sockaddr_get_len(&ch->addr));
1187         }
1188
1189         status = PJ_SUCCESS;
1190     }
1191
1192 on_return:
1193     pj_lock_release(sess->lock);
1194     return status;
1195 }
1196
1197
1198 /*
1199  * This is a callback from STUN session to send outgoing packet.
1200  */
1201 static pj_status_t stun_on_send_msg(pj_stun_session *stun,
1202                                     void *token,
1203                                     const void *pkt,
1204                                     pj_size_t pkt_size,
1205                                     const pj_sockaddr_t *dst_addr,
1206                                     unsigned addr_len)
1207 {
1208     pj_turn_session *sess;
1209
1210     PJ_UNUSED_ARG(token);
1211
1212     sess = (pj_turn_session*) pj_stun_session_get_user_data(stun);
1213     return (*sess->cb.on_send_pkt)(sess, (const pj_uint8_t*)pkt, pkt_size, 
1214                                    dst_addr, addr_len);
1215 }
1216
1217
1218 /*
1219  * Handle failed ALLOCATE or REFRESH request. This may switch to alternate
1220  * server if we have one.
1221  */
1222 static void on_session_fail( pj_turn_session *sess, 
1223                              enum pj_stun_method_e method,
1224                              pj_status_t status,
1225                              const pj_str_t *reason)
1226 {
1227     sess->last_status = status;
1228
1229     do {
1230         pj_str_t reason1;
1231         char err_msg[PJ_ERR_MSG_SIZE];
1232
1233         if (reason == NULL) {
1234             pj_strerror(status, err_msg, sizeof(err_msg));
1235             reason1 = pj_str(err_msg);
1236             reason = &reason1;
1237         }
1238
1239         PJ_LOG(4,(sess->obj_name, "%s error: %.*s",
1240                   pj_stun_get_method_name(method),
1241                   (int)reason->slen, reason->ptr));
1242
1243         /* If this is ALLOCATE response and we don't have more server 
1244          * addresses to try, notify application and destroy the TURN
1245          * session.
1246          */
1247         if (method==PJ_STUN_ALLOCATE_METHOD &&
1248             sess->srv_addr == &sess->srv_addr_list[sess->srv_addr_cnt-1]) 
1249         {
1250
1251             set_state(sess, PJ_TURN_STATE_DEALLOCATED);
1252             sess_shutdown(sess, status);
1253             return;
1254         }
1255
1256         /* Otherwise if this is not ALLOCATE response, notify application
1257          * that session has been TERMINATED.
1258          */
1259         if (method!=PJ_STUN_ALLOCATE_METHOD) {
1260             set_state(sess, PJ_TURN_STATE_DEALLOCATED);
1261             sess_shutdown(sess, status);
1262             return;
1263         }
1264
1265         /* Try next server */
1266         ++sess->srv_addr;
1267         reason = NULL;
1268
1269         PJ_LOG(4,(sess->obj_name, "Trying next server"));
1270         set_state(sess, PJ_TURN_STATE_RESOLVED);
1271
1272     } while (0);
1273 }
1274
1275
1276 /*
1277  * Handle successful response to ALLOCATE or REFRESH request.
1278  */
1279 static void on_allocate_success(pj_turn_session *sess, 
1280                                 enum pj_stun_method_e method,
1281                                 const pj_stun_msg *msg)
1282 {
1283     const pj_stun_lifetime_attr *lf_attr;
1284     const pj_stun_xor_relayed_addr_attr *raddr_attr;
1285     const pj_stun_sockaddr_attr *mapped_attr;
1286     pj_str_t s;
1287     pj_time_val timeout;
1288
1289     /* Must have LIFETIME attribute */
1290     lf_attr = (const pj_stun_lifetime_attr*)
1291               pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0);
1292     if (lf_attr == NULL) {
1293         on_session_fail(sess, method, PJNATH_EINSTUNMSG,
1294                         pj_cstr(&s, "Error: Missing LIFETIME attribute"));
1295         return;
1296     }
1297
1298     /* If LIFETIME is zero, this is a deallocation */
1299     if (lf_attr->value == 0) {
1300         set_state(sess, PJ_TURN_STATE_DEALLOCATED);
1301         sess_shutdown(sess, PJ_SUCCESS);
1302         return;
1303     }
1304
1305     /* Update lifetime and keep-alive interval */
1306     sess->lifetime = lf_attr->value;
1307     pj_gettimeofday(&sess->expiry);
1308
1309     if (sess->lifetime < PJ_TURN_KEEP_ALIVE_SEC) {
1310         if (sess->lifetime <= 2) {
1311             on_session_fail(sess, method, PJ_ETOOSMALL,
1312                              pj_cstr(&s, "Error: LIFETIME too small"));
1313             return;
1314         }
1315         sess->ka_interval = sess->lifetime - 2;
1316         sess->expiry.sec += (sess->ka_interval-1);
1317     } else {
1318         int timeout;
1319
1320         sess->ka_interval = PJ_TURN_KEEP_ALIVE_SEC;
1321
1322         timeout = sess->lifetime - PJ_TURN_REFRESH_SEC_BEFORE;
1323         if (timeout < sess->ka_interval)
1324             timeout = sess->ka_interval - 1;
1325
1326         sess->expiry.sec += timeout;
1327     }
1328
1329     /* Check that relayed transport address contains correct
1330      * address family.
1331      */
1332     raddr_attr = (const pj_stun_xor_relayed_addr_attr*)
1333                  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_RELAYED_ADDR, 0);
1334     if (raddr_attr == NULL && method==PJ_STUN_ALLOCATE_METHOD) {
1335         on_session_fail(sess, method, PJNATH_EINSTUNMSG,
1336                         pj_cstr(&s, "Error: Received ALLOCATE without "
1337                                     "RELAY-ADDRESS attribute"));
1338         return;
1339     }
1340     if (raddr_attr && raddr_attr->sockaddr.addr.sa_family != sess->af) {
1341         on_session_fail(sess, method, PJNATH_EINSTUNMSG,
1342                         pj_cstr(&s, "Error: RELAY-ADDRESS with non IPv4"
1343                                     " address family is not supported "
1344                                     "for now"));
1345         return;
1346     }
1347     if (raddr_attr && !pj_sockaddr_has_addr(&raddr_attr->sockaddr)) {
1348         on_session_fail(sess, method, PJNATH_EINSTUNMSG,
1349                         pj_cstr(&s, "Error: Invalid IP address in "
1350                                     "RELAY-ADDRESS attribute"));
1351         return;
1352     }
1353     
1354     /* Save relayed address */
1355     if (raddr_attr) {
1356         /* If we already have relay address, check if the relay address 
1357          * in the response matches our relay address.
1358          */
1359         if (pj_sockaddr_has_addr(&sess->relay_addr)) {
1360             if (pj_sockaddr_cmp(&sess->relay_addr, &raddr_attr->sockaddr)) {
1361                 on_session_fail(sess, method, PJNATH_EINSTUNMSG,
1362                                 pj_cstr(&s, "Error: different RELAY-ADDRESS is"
1363                                             "returned by server"));
1364                 return;
1365             }
1366         } else {
1367             /* Otherwise save the relayed address */
1368             pj_memcpy(&sess->relay_addr, &raddr_attr->sockaddr, 
1369                       sizeof(pj_sockaddr));
1370         }
1371     }
1372
1373     /* Get mapped address */
1374     mapped_attr = (const pj_stun_sockaddr_attr*)
1375                   pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_MAPPED_ADDR, 0);
1376     if (mapped_attr) {
1377         pj_memcpy(&sess->mapped_addr, &mapped_attr->sockaddr,
1378                   sizeof(mapped_attr->sockaddr));
1379     }
1380
1381     /* Success */
1382
1383     /* Cancel existing keep-alive timer, if any */
1384     pj_assert(sess->timer.id != TIMER_DESTROY);
1385
1386     if (sess->timer.id != TIMER_NONE) {
1387         pj_timer_heap_cancel(sess->timer_heap, &sess->timer);
1388         sess->timer.id = TIMER_NONE;
1389     }
1390
1391     /* Start keep-alive timer once allocation succeeds */
1392     timeout.sec = sess->ka_interval;
1393     timeout.msec = 0;
1394
1395     sess->timer.id = TIMER_KEEP_ALIVE;
1396     pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &timeout);
1397
1398     set_state(sess, PJ_TURN_STATE_READY);
1399 }
1400
1401 /*
1402  * Notification from STUN session on request completion.
1403  */
1404 static void stun_on_request_complete(pj_stun_session *stun,
1405                                      pj_status_t status,
1406                                      void *token,
1407                                      pj_stun_tx_data *tdata,
1408                                      const pj_stun_msg *response,
1409                                      const pj_sockaddr_t *src_addr,
1410                                      unsigned src_addr_len)
1411 {
1412     pj_turn_session *sess;
1413     enum pj_stun_method_e method = (enum pj_stun_method_e) 
1414                                    PJ_STUN_GET_METHOD(tdata->msg->hdr.type);
1415
1416     PJ_UNUSED_ARG(src_addr);
1417     PJ_UNUSED_ARG(src_addr_len);
1418
1419     sess = (pj_turn_session*)pj_stun_session_get_user_data(stun);
1420
1421     if (method == PJ_STUN_ALLOCATE_METHOD) {
1422
1423         /* Destroy if we have pending destroy request */
1424         if (sess->pending_destroy) {
1425             if (status == PJ_SUCCESS)
1426                 sess->state = PJ_TURN_STATE_READY;
1427             else
1428                 sess->state = PJ_TURN_STATE_DEALLOCATED;
1429             sess_shutdown(sess, PJ_SUCCESS);
1430             return;
1431         }
1432
1433         /* Handle ALLOCATE response */
1434         if (status==PJ_SUCCESS && 
1435             PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type)) 
1436         {
1437
1438             /* Successful Allocate response */
1439             on_allocate_success(sess, method, response);
1440
1441         } else {
1442             /* Failed Allocate request */
1443             const pj_str_t *err_msg = NULL;
1444
1445             if (status == PJ_SUCCESS) {
1446                 const pj_stun_errcode_attr *err_attr;
1447                 err_attr = (const pj_stun_errcode_attr*)
1448                            pj_stun_msg_find_attr(response,
1449                                                  PJ_STUN_ATTR_ERROR_CODE, 0);
1450                 if (err_attr) {
1451                     status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_code);
1452                     err_msg = &err_attr->reason;
1453                 } else {
1454                     status = PJNATH_EINSTUNMSG;
1455                 }
1456             }
1457
1458             on_session_fail(sess, method, status, err_msg);
1459         }
1460
1461     } else if (method == PJ_STUN_REFRESH_METHOD) {
1462         /* Handle Refresh response */
1463         if (status==PJ_SUCCESS && 
1464             PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type)) 
1465         {
1466             /* Success, schedule next refresh. */
1467             on_allocate_success(sess, method, response);
1468
1469         } else {
1470             /* Failed Refresh request */
1471             const pj_str_t *err_msg = NULL;
1472
1473             pj_assert(status != PJ_SUCCESS);
1474
1475             if (response) {
1476                 const pj_stun_errcode_attr *err_attr;
1477                 err_attr = (const pj_stun_errcode_attr*)
1478                            pj_stun_msg_find_attr(response,
1479                                                  PJ_STUN_ATTR_ERROR_CODE, 0);
1480                 if (err_attr) {
1481                     status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_code);
1482                     err_msg = &err_attr->reason;
1483                 }
1484             }
1485
1486             /* Notify and destroy */
1487             on_session_fail(sess, method, status, err_msg);
1488         }
1489
1490     } else if (method == PJ_STUN_CHANNEL_BIND_METHOD) {
1491         /* Handle ChannelBind response */
1492         if (status==PJ_SUCCESS && 
1493             PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type)) 
1494         {
1495             /* Successful ChannelBind response */
1496             struct ch_t *ch = (struct ch_t*)token;
1497
1498             pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL);
1499             ch->bound = PJ_TRUE;
1500
1501             /* Update hash table */
1502             lookup_ch_by_addr(sess, &ch->addr,
1503                               pj_sockaddr_get_len(&ch->addr),
1504                               PJ_TRUE, PJ_TRUE);
1505
1506         } else {
1507             /* Failed ChannelBind response */
1508             pj_str_t reason = {"", 0};
1509             int err_code = 0;
1510             char errbuf[PJ_ERR_MSG_SIZE];
1511
1512             pj_assert(status != PJ_SUCCESS);
1513
1514             if (response) {
1515                 const pj_stun_errcode_attr *err_attr;
1516                 err_attr = (const pj_stun_errcode_attr*)
1517                            pj_stun_msg_find_attr(response,
1518                                                  PJ_STUN_ATTR_ERROR_CODE, 0);
1519                 if (err_attr) {
1520                     err_code = err_attr->err_code;
1521                     status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_code);
1522                     reason = err_attr->reason;
1523                 }
1524             } else {
1525                 err_code = status;
1526                 reason = pj_strerror(status, errbuf, sizeof(errbuf));
1527             }
1528
1529             PJ_LOG(1,(sess->obj_name, "ChannelBind failed: %d/%.*s",
1530                       err_code, (int)reason.slen, reason.ptr));
1531
1532             if (err_code == PJ_STUN_SC_ALLOCATION_MISMATCH) {
1533                 /* Allocation mismatch means allocation no longer exists */
1534                 on_session_fail(sess, PJ_STUN_CHANNEL_BIND_METHOD,
1535                                 status, &reason);
1536                 return;
1537             }
1538         }
1539
1540     } else if (method == PJ_STUN_CREATE_PERM_METHOD) {
1541         /* Handle CreatePermission response */
1542         if (status==PJ_SUCCESS && 
1543             PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type)) 
1544         {
1545             /* No special handling when the request is successful. */
1546         } else {
1547             /* Iterate the permission table and invalidate all permissions
1548              * that are related to this request.
1549              */
1550             pj_hash_iterator_t it_buf, *it;
1551             char ipstr[PJ_INET6_ADDRSTRLEN+10];
1552             int err_code;
1553             char errbuf[PJ_ERR_MSG_SIZE];
1554             pj_str_t reason;
1555
1556             pj_assert(status != PJ_SUCCESS);
1557
1558             if (response) {
1559                 const pj_stun_errcode_attr *eattr;
1560
1561                 eattr = (const pj_stun_errcode_attr*)
1562                         pj_stun_msg_find_attr(response, 
1563                                               PJ_STUN_ATTR_ERROR_CODE, 0);
1564                 if (eattr) {
1565                     err_code = eattr->err_code;
1566                     reason = eattr->reason;
1567                 } else {
1568                     err_code = -1;
1569                     reason = pj_str("?");
1570                 }
1571             } else {
1572                 err_code = status;
1573                 reason = pj_strerror(status, errbuf, sizeof(errbuf));
1574             }
1575
1576             it = pj_hash_first(sess->perm_table, &it_buf);
1577             while (it) {
1578                 struct perm_t *perm = (struct perm_t*)
1579                                       pj_hash_this(sess->perm_table, it);
1580                 it = pj_hash_next(sess->perm_table, it);
1581
1582                 if (perm->req_token == token) {
1583                     PJ_LOG(1,(sess->obj_name, 
1584                               "CreatePermission failed for IP %s: %d/%.*s",
1585                               pj_sockaddr_print(&perm->addr, ipstr, 
1586                                                 sizeof(ipstr), 2),
1587                               err_code, (int)reason.slen, reason.ptr));
1588
1589                     invalidate_perm(sess, perm);
1590                 }
1591             }
1592
1593             if (err_code == PJ_STUN_SC_ALLOCATION_MISMATCH) {
1594                 /* Allocation mismatch means allocation no longer exists */
1595                 on_session_fail(sess, PJ_STUN_CREATE_PERM_METHOD,
1596                                 status, &reason);
1597                 return;
1598             }
1599         }
1600
1601     } else {
1602         PJ_LOG(4,(sess->obj_name, "Unexpected STUN %s response",
1603                   pj_stun_get_method_name(response->hdr.type)));
1604     }
1605 }
1606
1607
1608 /*
1609  * Notification from STUN session on incoming STUN Indication
1610  * message.
1611  */
1612 static pj_status_t stun_on_rx_indication(pj_stun_session *stun,
1613                                          const pj_uint8_t *pkt,
1614                                          unsigned pkt_len,
1615                                          const pj_stun_msg *msg,
1616                                          void *token,
1617                                          const pj_sockaddr_t *src_addr,
1618                                          unsigned src_addr_len)
1619 {
1620     pj_turn_session *sess;
1621     pj_stun_xor_peer_addr_attr *peer_attr;
1622     pj_stun_icmp_attr *icmp;
1623     pj_stun_data_attr *data_attr;
1624
1625     PJ_UNUSED_ARG(token);
1626     PJ_UNUSED_ARG(pkt);
1627     PJ_UNUSED_ARG(pkt_len);
1628     PJ_UNUSED_ARG(src_addr);
1629     PJ_UNUSED_ARG(src_addr_len);
1630
1631     sess = (pj_turn_session*)pj_stun_session_get_user_data(stun);
1632
1633     /* Expecting Data Indication only */
1634     if (msg->hdr.type != PJ_STUN_DATA_INDICATION) {
1635         PJ_LOG(4,(sess->obj_name, "Unexpected STUN %s indication",
1636                   pj_stun_get_method_name(msg->hdr.type)));
1637         return PJ_EINVALIDOP;
1638     }
1639
1640     /* Check if there is ICMP attribute in the message */
1641     icmp = (pj_stun_icmp_attr*)
1642            pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICMP, 0);
1643     if (icmp != NULL) {
1644         /* This is a forwarded ICMP packet. Ignore it for now */
1645         return PJ_SUCCESS;
1646     }
1647
1648     /* Get XOR-PEER-ADDRESS attribute */
1649     peer_attr = (pj_stun_xor_peer_addr_attr*)
1650                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
1651
1652     /* Get DATA attribute */
1653     data_attr = (pj_stun_data_attr*)
1654                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0);
1655
1656     /* Must have both XOR-PEER-ADDRESS and DATA attributes */
1657     if (!peer_attr || !data_attr) {
1658         PJ_LOG(4,(sess->obj_name, 
1659                   "Received Data indication with missing attributes"));
1660         return PJ_EINVALIDOP;
1661     }
1662
1663     /* Notify application */
1664     if (sess->cb.on_rx_data) {
1665         (*sess->cb.on_rx_data)(sess, data_attr->data, data_attr->length, 
1666                                &peer_attr->sockaddr,
1667                                pj_sockaddr_get_len(&peer_attr->sockaddr));
1668     }
1669
1670     return PJ_SUCCESS;
1671 }
1672
1673
1674 /*
1675  * Notification on completion of DNS SRV resolution.
1676  */
1677 static void dns_srv_resolver_cb(void *user_data,
1678                                 pj_status_t status,
1679                                 const pj_dns_srv_record *rec)
1680 {
1681     pj_turn_session *sess = (pj_turn_session*) user_data;
1682     unsigned i, cnt, tot_cnt;
1683
1684     /* Clear async resolver */
1685     sess->dns_async = NULL;
1686
1687     /* Check failure */
1688     if (status != PJ_SUCCESS) {
1689         sess_shutdown(sess, status);
1690         return;
1691     }
1692
1693     /* Calculate total number of server entries in the response */
1694     tot_cnt = 0;
1695     for (i=0; i<rec->count; ++i) {
1696         tot_cnt += rec->entry[i].server.addr_count;
1697     }
1698
1699     if (tot_cnt > PJ_TURN_MAX_DNS_SRV_CNT)
1700         tot_cnt = PJ_TURN_MAX_DNS_SRV_CNT;
1701
1702     /* Allocate server entries */
1703     sess->srv_addr_list = (pj_sockaddr*)
1704                            pj_pool_calloc(sess->pool, tot_cnt, 
1705                                           sizeof(pj_sockaddr));
1706
1707     /* Copy results to server entries */
1708     for (i=0, cnt=0; i<rec->count && cnt<PJ_TURN_MAX_DNS_SRV_CNT; ++i) {
1709         unsigned j;
1710
1711         for (j=0; j<rec->entry[i].server.addr_count && 
1712                   cnt<PJ_TURN_MAX_DNS_SRV_CNT; ++j) 
1713         {
1714             pj_sockaddr_in *addr = &sess->srv_addr_list[cnt].ipv4;
1715
1716             addr->sin_family = sess->af;
1717             addr->sin_port = pj_htons(rec->entry[i].port);
1718             addr->sin_addr.s_addr = rec->entry[i].server.addr[j].s_addr;
1719
1720             ++cnt;
1721         }
1722     }
1723     sess->srv_addr_cnt = (pj_uint16_t)cnt;
1724
1725     /* Set current server */
1726     sess->srv_addr = &sess->srv_addr_list[0];
1727
1728     /* Set state to PJ_TURN_STATE_RESOLVED */
1729     set_state(sess, PJ_TURN_STATE_RESOLVED);
1730
1731     /* Run pending allocation */
1732     if (sess->pending_alloc) {
1733         pj_turn_session_alloc(sess, NULL);
1734     }
1735 }
1736
1737
1738 /*
1739  * Lookup peer descriptor from its address.
1740  */
1741 static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess,
1742                                       const pj_sockaddr_t *addr,
1743                                       unsigned addr_len,
1744                                       pj_bool_t update,
1745                                       pj_bool_t bind_channel)
1746 {
1747     pj_uint32_t hval = 0;
1748     struct ch_t *ch;
1749
1750     ch = (struct ch_t*) 
1751          pj_hash_get(sess->ch_table, addr, addr_len, &hval);
1752     if (ch == NULL && update) {
1753         ch = PJ_POOL_ZALLOC_T(sess->pool, struct ch_t);
1754         ch->num = PJ_TURN_INVALID_CHANNEL;
1755         pj_memcpy(&ch->addr, addr, addr_len);
1756
1757         /* Register by peer address */
1758         pj_hash_set(sess->pool, sess->ch_table, &ch->addr, addr_len,
1759                     hval, ch);
1760     }
1761
1762     if (ch && update) {
1763         pj_gettimeofday(&ch->expiry);
1764         ch->expiry.sec += PJ_TURN_PERM_TIMEOUT - sess->ka_interval - 1;
1765
1766         if (bind_channel) {
1767             pj_uint32_t hval = 0;
1768             /* Register by channel number */
1769             pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound);
1770
1771             if (pj_hash_get(sess->ch_table, &ch->num, 
1772                             sizeof(ch->num), &hval)==0) {
1773                 pj_hash_set(sess->pool, sess->ch_table, &ch->num,
1774                             sizeof(ch->num), hval, ch);
1775             }
1776         }
1777     }
1778
1779     /* Also create/update permission for this destination. Ideally we
1780      * should update this when we receive the successful response,
1781      * but that would cause duplicate CreatePermission to be sent
1782      * during refreshing.
1783      */
1784     if (ch && update) {
1785         lookup_perm(sess, &ch->addr, pj_sockaddr_get_len(&ch->addr), PJ_TRUE);
1786     }
1787
1788     return ch;
1789 }
1790
1791
1792 /*
1793  * Lookup channel descriptor from its channel number.
1794  */
1795 static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess,
1796                                          pj_uint16_t chnum)
1797 {
1798     return (struct ch_t*) pj_hash_get(sess->ch_table, &chnum, 
1799                                       sizeof(chnum), NULL);
1800 }
1801
1802
1803 /*
1804  * Lookup permission and optionally create if it doesn't exist.
1805  */
1806 static struct perm_t *lookup_perm(pj_turn_session *sess,
1807                                   const pj_sockaddr_t *addr,
1808                                   unsigned addr_len,
1809                                   pj_bool_t update)
1810 {
1811     pj_uint32_t hval = 0;
1812     pj_sockaddr perm_addr;
1813     struct perm_t *perm;
1814
1815     /* make sure port number if zero */
1816     if (pj_sockaddr_get_port(addr) != 0) {
1817         pj_memcpy(&perm_addr, addr, addr_len);
1818         pj_sockaddr_set_port(&perm_addr, 0);
1819         addr = &perm_addr;
1820     }
1821
1822     /* lookup and create if it doesn't exist and wanted */
1823     perm = (struct perm_t*) 
1824            pj_hash_get(sess->perm_table, addr, addr_len, &hval);
1825     if (perm == NULL && update) {
1826         perm = PJ_POOL_ZALLOC_T(sess->pool, struct perm_t);
1827         pj_memcpy(&perm->addr, addr, addr_len);
1828         perm->hval = hval;
1829
1830         pj_hash_set(sess->pool, sess->perm_table, &perm->addr, addr_len,
1831                     perm->hval, perm);
1832     }
1833
1834     if (perm && update) {
1835         pj_gettimeofday(&perm->expiry);
1836         perm->expiry.sec += PJ_TURN_PERM_TIMEOUT - sess->ka_interval - 1;
1837
1838     }
1839
1840     return perm;
1841 }
1842
1843 /*
1844  * Delete permission
1845  */
1846 static void invalidate_perm(pj_turn_session *sess,
1847                             struct perm_t *perm)
1848 {
1849     pj_hash_set(NULL, sess->perm_table, &perm->addr,
1850                 pj_sockaddr_get_len(&perm->addr), perm->hval, NULL);
1851 }
1852
1853 /*
1854  * Scan permission's hash table to refresh the permission.
1855  */
1856 static unsigned refresh_permissions(pj_turn_session *sess, 
1857                                     const pj_time_val *now)
1858 {
1859     pj_stun_tx_data *tdata = NULL;
1860     unsigned count = 0;
1861     void *req_token = NULL;
1862     pj_hash_iterator_t *it, itbuf;
1863     pj_status_t status;
1864
1865     it = pj_hash_first(sess->perm_table, &itbuf);
1866     while (it) {
1867         struct perm_t *perm = (struct perm_t*)
1868                               pj_hash_this(sess->perm_table, it);
1869
1870         it = pj_hash_next(sess->perm_table, it);
1871
1872         if (perm->expiry.sec-1 <= now->sec) {
1873             if (perm->renew) {
1874                 /* Renew this permission */
1875                 if (tdata == NULL) {
1876                     /* Create a bare CreatePermission request */
1877                     status = pj_stun_session_create_req(
1878                                         sess->stun, 
1879                                         PJ_STUN_CREATE_PERM_REQUEST,
1880                                         PJ_STUN_MAGIC, NULL, &tdata);
1881                     if (status != PJ_SUCCESS) {
1882                         PJ_LOG(1,(sess->obj_name, 
1883                                  "Error creating CreatePermission request: %d",
1884                                  status));
1885                         return 0;
1886                     }
1887
1888                     /* Create request token to map the request to the perm
1889                      * structures which the request belongs.
1890                      */
1891                     req_token = (void*)(long)pj_rand();
1892                 }
1893
1894                 status = pj_stun_msg_add_sockaddr_attr(
1895                                         tdata->pool, 
1896                                         tdata->msg,
1897                                         PJ_STUN_ATTR_XOR_PEER_ADDR,
1898                                         PJ_TRUE,
1899                                         &perm->addr,
1900                                         sizeof(perm->addr));
1901                 if (status != PJ_SUCCESS) {
1902                     pj_stun_msg_destroy_tdata(sess->stun, tdata);
1903                     return 0;
1904                 }
1905
1906                 perm->expiry = *now;
1907                 perm->expiry.sec += PJ_TURN_PERM_TIMEOUT-sess->ka_interval-1;
1908                 perm->req_token = req_token;
1909                 ++count;
1910
1911             } else {
1912                 /* This permission has expired and app doesn't want
1913                  * us to renew, so delete it from the hash table.
1914                  */
1915                 invalidate_perm(sess, perm);
1916             }
1917         }
1918     }
1919
1920     if (tdata) {
1921         status = pj_stun_session_send_msg(sess->stun, req_token, PJ_FALSE, 
1922                                           (sess->conn_type==PJ_TURN_TP_UDP),
1923                                           sess->srv_addr,
1924                                           pj_sockaddr_get_len(sess->srv_addr), 
1925                                           tdata);
1926         if (status != PJ_SUCCESS) {
1927             PJ_LOG(1,(sess->obj_name, 
1928                       "Error sending CreatePermission request: %d",
1929                       status));
1930             count = 0;
1931         }
1932
1933     }
1934
1935     return count;
1936 }
1937
1938 /*
1939  * Timer event.
1940  */
1941 static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e)
1942 {
1943     pj_turn_session *sess = (pj_turn_session*)e->user_data;
1944     enum timer_id_t eid;
1945
1946     PJ_UNUSED_ARG(th);
1947
1948     pj_lock_acquire(sess->lock);
1949
1950     eid = (enum timer_id_t) e->id;
1951     e->id = TIMER_NONE;
1952     
1953     if (eid == TIMER_KEEP_ALIVE) {
1954         pj_time_val now;
1955         pj_hash_iterator_t itbuf, *it;
1956         pj_bool_t resched = PJ_TRUE;
1957         pj_bool_t pkt_sent = PJ_FALSE;
1958
1959         pj_gettimeofday(&now);
1960
1961         /* Refresh allocation if it's time to do so */
1962         if (PJ_TIME_VAL_LTE(sess->expiry, now)) {
1963             int lifetime = sess->alloc_param.lifetime;
1964
1965             if (lifetime == 0)
1966                 lifetime = -1;
1967
1968             send_refresh(sess, lifetime);
1969             resched = PJ_FALSE;
1970             pkt_sent = PJ_TRUE;
1971         }
1972
1973         /* Scan hash table to refresh bound channels */
1974         it = pj_hash_first(sess->ch_table, &itbuf);
1975         while (it) {
1976             struct ch_t *ch = (struct ch_t*) 
1977                               pj_hash_this(sess->ch_table, it);
1978             if (ch->bound && PJ_TIME_VAL_LTE(ch->expiry, now)) {
1979
1980                 /* Send ChannelBind to refresh channel binding and 
1981                  * permission.
1982                  */
1983                 pj_turn_session_bind_channel(sess, &ch->addr,
1984                                              pj_sockaddr_get_len(&ch->addr));
1985                 pkt_sent = PJ_TRUE;
1986             }
1987
1988             it = pj_hash_next(sess->ch_table, it);
1989         }
1990
1991         /* Scan permission table to refresh permissions */
1992         if (refresh_permissions(sess, &now))
1993             pkt_sent = PJ_TRUE;
1994
1995         /* If no packet is sent, send a blank Send indication to
1996          * refresh local NAT.
1997          */
1998         if (!pkt_sent && sess->alloc_param.ka_interval > 0) {
1999             pj_stun_tx_data *tdata;
2000             pj_status_t rc;
2001
2002             /* Create blank SEND-INDICATION */
2003             rc = pj_stun_session_create_ind(sess->stun, 
2004                                             PJ_STUN_SEND_INDICATION, &tdata);
2005             if (rc == PJ_SUCCESS) {
2006                 /* Add DATA attribute with zero length */
2007                 pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg,
2008                                             PJ_STUN_ATTR_DATA, NULL, 0);
2009
2010                 /* Send the indication */
2011                 pj_stun_session_send_msg(sess->stun, NULL, PJ_FALSE, 
2012                                          PJ_FALSE, sess->srv_addr,
2013                                          pj_sockaddr_get_len(sess->srv_addr),
2014                                          tdata);
2015             }
2016         }
2017
2018         /* Reshcedule timer */
2019         if (resched) {
2020             pj_time_val delay;
2021
2022             delay.sec = sess->ka_interval;
2023             delay.msec = 0;
2024
2025             sess->timer.id = TIMER_KEEP_ALIVE;
2026             pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &delay);
2027         }
2028
2029         pj_lock_release(sess->lock);
2030
2031     } else if (eid == TIMER_DESTROY) {
2032         /* Time to destroy */
2033         pj_lock_release(sess->lock);
2034         do_destroy(sess);
2035     } else {
2036         pj_assert(!"Unknown timer event");
2037         pj_lock_release(sess->lock);
2038     }
2039 }
2040