Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjnath / src / pjturn-srv / allocation.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 "turn.h"
21 #include "auth.h"
22
23
24 #define THIS_FILE   "allocation.c"
25
26
27 enum {
28     TIMER_ID_NONE,
29     TIMER_ID_TIMEOUT,
30     TIMER_ID_DESTROY
31 };
32
33 #define DESTROY_DELAY       {0, 500}
34 #define PEER_TABLE_SIZE     32
35
36 #define MAX_CLIENT_BANDWIDTH    128  /* In Kbps */
37 #define DEFA_CLIENT_BANDWIDTH   64
38
39 #define MIN_LIFETIME            30
40 #define MAX_LIFETIME            600
41 #define DEF_LIFETIME            300
42
43
44 /* Parsed Allocation request. */
45 typedef struct alloc_request
46 {
47     unsigned            tp_type;                    /* Requested transport  */
48     char                addr[PJ_INET6_ADDRSTRLEN];  /* Requested IP         */
49     unsigned            bandwidth;                  /* Requested bandwidth  */
50     unsigned            lifetime;                   /* Lifetime.            */
51     unsigned            rpp_bits;                   /* A bits               */
52     unsigned            rpp_port;                   /* Requested port       */
53 } alloc_request;
54
55
56
57 /* Prototypes */
58 static void destroy_allocation(pj_turn_allocation *alloc);
59 static pj_status_t create_relay(pj_turn_srv *srv,
60                                 pj_turn_allocation *alloc,
61                                 const pj_stun_msg *msg,
62                                 const alloc_request *req,
63                                 pj_turn_relay_res *relay);
64 static void destroy_relay(pj_turn_relay_res *relay);
65 static void on_rx_from_peer(pj_ioqueue_key_t *key, 
66                             pj_ioqueue_op_key_t *op_key, 
67                             pj_ssize_t bytes_read);
68 static pj_status_t stun_on_send_msg(pj_stun_session *sess,
69                                     void *token,
70                                     const void *pkt,
71                                     pj_size_t pkt_size,
72                                     const pj_sockaddr_t *dst_addr,
73                                     unsigned addr_len);
74 static pj_status_t stun_on_rx_request(pj_stun_session *sess,
75                                       const pj_uint8_t *pkt,
76                                       unsigned pkt_len,
77                                       const pj_stun_rx_data *rdata,
78                                       void *token,
79                                       const pj_sockaddr_t *src_addr,
80                                       unsigned src_addr_len);
81 static pj_status_t stun_on_rx_indication(pj_stun_session *sess,
82                                          const pj_uint8_t *pkt,
83                                          unsigned pkt_len,
84                                          const pj_stun_msg *msg,
85                                          void *token,
86                                          const pj_sockaddr_t *src_addr,
87                                          unsigned src_addr_len);
88
89 /* Log allocation error */
90 static void alloc_err(pj_turn_allocation *alloc, const char *title,
91                       pj_status_t status)
92 {
93     char errmsg[PJ_ERR_MSG_SIZE];
94
95     pj_strerror(status, errmsg, sizeof(errmsg));
96     PJ_LOG(4,(alloc->obj_name, "%s for client %s: %s",
97               title, alloc->info, errmsg));
98 }
99
100
101 /* Parse ALLOCATE request */
102 static pj_status_t parse_allocate_req(alloc_request *cfg,
103                                       pj_stun_session *sess,
104                                       const pj_stun_rx_data *rdata,
105                                       const pj_sockaddr_t *src_addr,
106                                       unsigned src_addr_len)
107 {
108     const pj_stun_msg *req = rdata->msg;
109     pj_stun_bandwidth_attr *attr_bw;
110     pj_stun_req_transport_attr *attr_req_tp;
111     pj_stun_res_token_attr *attr_res_token;
112     pj_stun_lifetime_attr *attr_lifetime;
113
114     pj_bzero(cfg, sizeof(*cfg));
115
116     /* Get BANDWIDTH attribute, if any. */
117     attr_bw = (pj_stun_uint_attr*)
118               pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0);
119     if (attr_bw) {
120         cfg->bandwidth = attr_bw->value;
121     } else {
122         cfg->bandwidth = DEFA_CLIENT_BANDWIDTH;
123     }
124
125     /* Check if we can satisfy the bandwidth */
126     if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) {
127         pj_stun_session_respond(sess, rdata, 
128                                 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED,
129                                 "Invalid bandwidth", NULL, PJ_TRUE,
130                                 src_addr, src_addr_len);
131         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ALLOCATION_QUOTA_REACHED);
132     }
133
134     /* MUST have REQUESTED-TRANSPORT attribute */
135     attr_req_tp = (pj_stun_uint_attr*)
136                   pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0);
137     if (attr_req_tp == NULL) {
138         pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST,
139                                 "Missing REQUESTED-TRANSPORT attribute", 
140                                 NULL, PJ_TRUE, src_addr, src_addr_len);
141         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST);
142     }
143
144     cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value);
145
146     /* Can only support UDP for now */
147     if (cfg->tp_type != PJ_TURN_TP_UDP) {
148         pj_stun_session_respond(sess, rdata, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,
149                                 NULL, NULL, PJ_TRUE, src_addr, src_addr_len);
150         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO);
151     }
152
153     /* Get RESERVATION-TOKEN attribute, if any */
154     attr_res_token = (pj_stun_res_token_attr*)
155                      pj_stun_msg_find_attr(req, PJ_STUN_ATTR_RESERVATION_TOKEN,
156                                            0);
157     if (attr_res_token) {
158         /* We don't support RESERVATION-TOKEN for now */
159         pj_stun_session_respond(sess, rdata, 
160                                 PJ_STUN_SC_BAD_REQUEST,
161                                 "RESERVATION-TOKEN is not supported", NULL, 
162                                 PJ_TRUE, src_addr, src_addr_len);
163         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST);
164     }
165
166     /* Get LIFETIME attribute */
167     attr_lifetime = (pj_stun_uint_attr*)
168                     pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0);
169     if (attr_lifetime) {
170         cfg->lifetime = attr_lifetime->value;
171         if (cfg->lifetime < MIN_LIFETIME) {
172             pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST,
173                                     "LIFETIME too short", NULL, 
174                                     PJ_TRUE, src_addr, src_addr_len);
175             return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST);
176         }
177         if (cfg->lifetime > MAX_LIFETIME)
178             cfg->lifetime = MAX_LIFETIME;
179     } else {
180         cfg->lifetime = DEF_LIFETIME;
181     }
182
183     return PJ_SUCCESS;
184 }
185
186
187 /* Respond to ALLOCATE request */
188 static pj_status_t send_allocate_response(pj_turn_allocation *alloc,
189                                           pj_stun_session *srv_sess,
190                                           pj_turn_transport *transport,
191                                           const pj_stun_rx_data *rdata)
192 {
193     pj_stun_tx_data *tdata;
194     pj_status_t status;
195
196     /* Respond the original ALLOCATE request */
197     status = pj_stun_session_create_res(srv_sess, rdata, 0, NULL, &tdata);
198     if (status != PJ_SUCCESS)
199         return status;
200
201     /* Add XOR-RELAYED-ADDRESS attribute */
202     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
203                                   PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE,
204                                   &alloc->relay.hkey.addr,
205                                   pj_sockaddr_get_len(&alloc->relay.hkey.addr));
206
207     /* Add LIFETIME. */
208     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
209                               PJ_STUN_ATTR_LIFETIME, 
210                               (unsigned)alloc->relay.lifetime);
211
212     /* Add BANDWIDTH */
213     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
214                               PJ_STUN_ATTR_BANDWIDTH,
215                               alloc->bandwidth);
216
217     /* Add RESERVATION-TOKEN */
218     PJ_TODO(ADD_RESERVATION_TOKEN);
219
220     /* Add XOR-MAPPED-ADDRESS */
221     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
222                                   PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE,
223                                   &alloc->hkey.clt_addr,
224                                   pj_sockaddr_get_len(&alloc->hkey.clt_addr));
225     
226     /* Send the response */
227     return pj_stun_session_send_msg(srv_sess, transport, PJ_TRUE,
228                                     PJ_FALSE, &alloc->hkey.clt_addr, 
229                                     pj_sockaddr_get_len(&alloc->hkey.clt_addr),
230                                     tdata);
231 }
232
233
234 /*
235  * Init credential for the allocation. We use static credential, meaning that
236  * the user's password must not change during allocation.
237  */
238 static pj_status_t init_cred(pj_turn_allocation *alloc, const pj_stun_msg *req)
239 {
240     const pj_stun_username_attr *user;
241     const pj_stun_realm_attr *realm;
242     const pj_stun_nonce_attr *nonce;
243     pj_status_t status;
244
245     realm = (const pj_stun_realm_attr*)
246             pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0);
247     PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG);
248
249     user = (const pj_stun_username_attr*)
250            pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0);
251     PJ_ASSERT_RETURN(user != NULL, PJ_EBUG);
252
253     nonce = (const pj_stun_nonce_attr*)
254             pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0);
255     PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG);
256
257     /* Lookup the password */
258     status = pj_turn_get_password(NULL, NULL, &realm->value, 
259                                   &user->value, alloc->pool, 
260                                   &alloc->cred.data.static_cred.data_type, 
261                                   &alloc->cred.data.static_cred.data);
262     if (status != PJ_SUCCESS)
263         return status;
264
265     /* Save credential */
266     alloc->cred.type = PJ_STUN_AUTH_CRED_STATIC;
267     pj_strdup(alloc->pool, &alloc->cred.data.static_cred.realm, &realm->value);
268     pj_strdup(alloc->pool, &alloc->cred.data.static_cred.username, &user->value);
269     pj_strdup(alloc->pool, &alloc->cred.data.static_cred.nonce, &nonce->value);
270
271     return PJ_SUCCESS;
272 }
273
274
275 /*
276  * Create new allocation.
277  */
278 PJ_DEF(pj_status_t) pj_turn_allocation_create(pj_turn_transport *transport,
279                                               const pj_sockaddr_t *src_addr,
280                                               unsigned src_addr_len,
281                                               const pj_stun_rx_data *rdata,
282                                               pj_stun_session *srv_sess,
283                                               pj_turn_allocation **p_alloc)
284 {
285     pj_turn_srv *srv = transport->listener->server;
286     const pj_stun_msg *msg = rdata->msg;
287     pj_pool_t *pool;
288     alloc_request req;
289     pj_turn_allocation *alloc;
290     pj_stun_session_cb sess_cb;
291     char str_tmp[80];
292     pj_status_t status;
293
294     /* Parse ALLOCATE request */
295     status = parse_allocate_req(&req, srv_sess, rdata, src_addr, src_addr_len);
296     if (status != PJ_SUCCESS)
297         return status;
298
299     pool = pj_pool_create(srv->core.pf, "alloc%p", 1000, 1000, NULL);
300
301     /* Init allocation structure */
302     alloc = PJ_POOL_ZALLOC_T(pool, pj_turn_allocation);
303     alloc->pool = pool;
304     alloc->obj_name = pool->obj_name;
305     alloc->relay.tp.sock = PJ_INVALID_SOCKET;
306     alloc->server = transport->listener->server;
307
308     alloc->bandwidth = req.bandwidth;
309
310     /* Set transport */
311     alloc->transport = transport;
312     pj_turn_transport_add_ref(transport, alloc);
313
314     alloc->hkey.tp_type = transport->listener->tp_type;
315     pj_memcpy(&alloc->hkey.clt_addr, src_addr, src_addr_len);
316
317     status = pj_lock_create_recursive_mutex(pool, alloc->obj_name, 
318                                             &alloc->lock);
319     if (status != PJ_SUCCESS) {
320         goto on_error;
321     }
322
323     /* Create peer hash table */
324     alloc->peer_table = pj_hash_create(pool, PEER_TABLE_SIZE);
325
326     /* Create channel hash table */
327     alloc->ch_table = pj_hash_create(pool, PEER_TABLE_SIZE);
328
329     /* Print info */
330     pj_ansi_strcpy(alloc->info, 
331                    pj_turn_tp_type_name(transport->listener->tp_type));
332     alloc->info[3] = ':';
333     pj_sockaddr_print(src_addr, alloc->info+4, sizeof(alloc->info)-4, 3);
334
335     /* Create STUN session to handle STUN communication with client */
336     pj_bzero(&sess_cb, sizeof(sess_cb));
337     sess_cb.on_send_msg = &stun_on_send_msg;
338     sess_cb.on_rx_request = &stun_on_rx_request;
339     sess_cb.on_rx_indication = &stun_on_rx_indication;
340     status = pj_stun_session_create(&srv->core.stun_cfg, alloc->obj_name,
341                                     &sess_cb, PJ_FALSE, &alloc->sess);
342     if (status != PJ_SUCCESS) {
343         goto on_error;
344     }
345
346     /* Attach to STUN session */
347     pj_stun_session_set_user_data(alloc->sess, alloc);
348
349     /* Init authentication credential */
350     status = init_cred(alloc, msg);
351     if (status != PJ_SUCCESS) {
352         goto on_error;
353     }
354
355     /* Attach authentication credential to STUN session */
356     pj_stun_session_set_credential(alloc->sess, PJ_STUN_AUTH_LONG_TERM,
357                                    &alloc->cred);
358
359     /* Create the relay resource */
360     status = create_relay(srv, alloc, msg, &req, &alloc->relay);
361     if (status != PJ_SUCCESS) {
362         goto on_error;
363     }
364
365     /* Register this allocation */
366     pj_turn_srv_register_allocation(srv, alloc);
367
368     /* Respond to ALLOCATE request */
369     status = send_allocate_response(alloc, srv_sess, transport, rdata);
370     if (status != PJ_SUCCESS)
371         goto on_error;
372
373     /* Done */
374     pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 
375                       sizeof(str_tmp), 3);
376     PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 
377               alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp));
378
379     /* Success */
380     *p_alloc = alloc;
381     return PJ_SUCCESS;
382
383 on_error:
384     /* Send reply to the ALLOCATE request */
385     pj_strerror(status, str_tmp, sizeof(str_tmp));
386     pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 
387                             transport, PJ_TRUE, src_addr, src_addr_len);
388
389     /* Cleanup */
390     destroy_allocation(alloc);
391     return status;
392 }
393
394
395 /* Destroy relay resource */
396 static void destroy_relay(pj_turn_relay_res *relay)
397 {
398     if (relay->timer.id) {
399         pj_timer_heap_cancel(relay->allocation->server->core.timer_heap, 
400                              &relay->timer);
401         relay->timer.id = PJ_FALSE;
402     }
403
404     if (relay->tp.key) {
405         pj_ioqueue_unregister(relay->tp.key);
406         relay->tp.key = NULL;
407         relay->tp.sock = PJ_INVALID_SOCKET;
408     } else if (relay->tp.sock != PJ_INVALID_SOCKET) {
409         pj_sock_close(relay->tp.sock);
410         relay->tp.sock = PJ_INVALID_SOCKET;
411     }
412
413     /* Mark as shutdown */
414     relay->lifetime = 0;
415 }
416
417
418 /*
419  * Really destroy allocation.
420  */
421 static void destroy_allocation(pj_turn_allocation *alloc)
422 {
423     pj_pool_t *pool;
424
425     /* Unregister this allocation */
426     pj_turn_srv_unregister_allocation(alloc->server, alloc);
427
428     /* Destroy relay */
429     destroy_relay(&alloc->relay);
430
431     /* Must lock only after destroying relay otherwise deadlock */
432     if (alloc->lock) {
433         pj_lock_acquire(alloc->lock);
434     }
435
436     /* Unreference transport */
437     if (alloc->transport) {
438         pj_turn_transport_dec_ref(alloc->transport, alloc);
439         alloc->transport = NULL;
440     }
441
442     /* Destroy STUN session */
443     if (alloc->sess) {
444         pj_stun_session_destroy(alloc->sess);
445         alloc->sess = NULL;
446     }
447
448     /* Destroy lock */
449     if (alloc->lock) {
450         pj_lock_release(alloc->lock);
451         pj_lock_destroy(alloc->lock);
452         alloc->lock = NULL;
453     }
454
455     /* Destroy pool */
456     pool = alloc->pool;
457     if (pool) {
458         alloc->pool = NULL;
459         pj_pool_release(pool);
460     }
461 }
462
463
464 PJ_DECL(void) pj_turn_allocation_destroy(pj_turn_allocation *alloc)
465 {
466     destroy_allocation(alloc);
467 }
468
469
470 /*
471  * Handle transport closure.
472  */
473 PJ_DEF(void) pj_turn_allocation_on_transport_closed( pj_turn_allocation *alloc,
474                                                      pj_turn_transport *tp)
475 {
476     PJ_LOG(5,(alloc->obj_name, "Transport %s unexpectedly closed, destroying "
477               "allocation %s", tp->info, alloc->info));
478     pj_turn_transport_dec_ref(tp, alloc);
479     alloc->transport = NULL;
480     destroy_allocation(alloc);
481 }
482
483
484 /* Initiate shutdown sequence for this allocation and start destroy timer.
485  * Once allocation is marked as shutting down, any packets will be 
486  * rejected/discarded 
487  */
488 static void alloc_shutdown(pj_turn_allocation *alloc)
489 {
490     pj_time_val destroy_delay = DESTROY_DELAY;
491
492     /* Work with existing schedule */
493     if (alloc->relay.timer.id == TIMER_ID_TIMEOUT) {
494         /* Cancel existing shutdown timer */
495         pj_timer_heap_cancel(alloc->server->core.timer_heap,
496                              &alloc->relay.timer);
497         alloc->relay.timer.id = TIMER_ID_NONE;
498
499     } else if (alloc->relay.timer.id == TIMER_ID_DESTROY) {
500         /* We've been scheduled to be destroyed, ignore this
501          * shutdown request.
502          */
503         return;
504     } 
505
506     pj_assert(alloc->relay.timer.id == TIMER_ID_NONE);
507
508     /* Shutdown relay socket */
509     destroy_relay(&alloc->relay);
510
511     /* Don't unregister from hash table because we still need to
512      * handle REFRESH retransmission.
513      */
514
515     /* Schedule destroy timer */
516     alloc->relay.timer.id = TIMER_ID_DESTROY;
517     pj_timer_heap_schedule(alloc->server->core.timer_heap,
518                            &alloc->relay.timer, &destroy_delay);
519 }
520
521
522 /* Reschedule timeout using current lifetime setting */
523 static pj_status_t resched_timeout(pj_turn_allocation *alloc)
524 {
525     pj_time_val delay;
526     pj_status_t status;
527
528     pj_gettimeofday(&alloc->relay.expiry);
529     alloc->relay.expiry.sec += alloc->relay.lifetime;
530
531     pj_assert(alloc->relay.timer.id != TIMER_ID_DESTROY);
532     if (alloc->relay.timer.id != 0) {
533         pj_timer_heap_cancel(alloc->server->core.timer_heap, 
534                              &alloc->relay.timer);
535         alloc->relay.timer.id = TIMER_ID_NONE;
536     }
537
538     delay.sec = alloc->relay.lifetime;
539     delay.msec = 0;
540
541     alloc->relay.timer.id = TIMER_ID_TIMEOUT;
542     status = pj_timer_heap_schedule(alloc->server->core.timer_heap, 
543                                     &alloc->relay.timer, &delay);
544     if (status != PJ_SUCCESS) {
545         alloc->relay.timer.id = TIMER_ID_NONE;
546         return status;
547     }
548
549     return PJ_SUCCESS;
550 }
551
552
553 /* Timer timeout callback */
554 static void relay_timeout_cb(pj_timer_heap_t *heap, pj_timer_entry *e)
555 {
556     pj_turn_relay_res *rel;
557     pj_turn_allocation *alloc;
558
559     PJ_UNUSED_ARG(heap);
560
561     rel = (pj_turn_relay_res*) e->user_data;
562     alloc = rel->allocation;
563
564     if (e->id == TIMER_ID_TIMEOUT) {
565
566         e->id = TIMER_ID_NONE;
567
568         PJ_LOG(4,(alloc->obj_name, 
569                   "Client %s refresh timed-out, shutting down..", 
570                   alloc->info));
571
572         alloc_shutdown(alloc);
573
574     } else if (e->id == TIMER_ID_DESTROY) {
575         e->id = TIMER_ID_NONE;
576
577         PJ_LOG(4,(alloc->obj_name, "Client %s destroying..", 
578                   alloc->info));
579
580         destroy_allocation(alloc);
581     }
582 }
583
584
585 /*
586  * Create relay.
587  */
588 static pj_status_t create_relay(pj_turn_srv *srv,
589                                 pj_turn_allocation *alloc,
590                                 const pj_stun_msg *msg,
591                                 const alloc_request *req,
592                                 pj_turn_relay_res *relay)
593 {
594     enum { RETRY = 40 };
595     pj_pool_t *pool = alloc->pool;
596     int retry, retry_max, sock_type;
597     pj_ioqueue_callback icb;
598     int af, namelen;
599     pj_stun_string_attr *sa;
600     pj_status_t status;
601
602     pj_bzero(relay, sizeof(*relay));
603     
604     relay->allocation = alloc;
605     relay->tp.sock = PJ_INVALID_SOCKET;
606     
607     /* TODO: get the requested address family from somewhere */
608     af = alloc->transport->listener->addr.addr.sa_family;
609
610     /* Save realm */
611     sa = (pj_stun_string_attr*)
612          pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0);
613     PJ_ASSERT_RETURN(sa, PJ_EINVALIDOP);
614     pj_strdup(pool, &relay->realm, &sa->value);
615
616     /* Save username */
617     sa = (pj_stun_string_attr*)
618          pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0);
619     PJ_ASSERT_RETURN(sa, PJ_EINVALIDOP);
620     pj_strdup(pool, &relay->user, &sa->value);
621
622     /* Lifetime and timeout */
623     relay->lifetime = req->lifetime;
624     pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay, 
625                         &relay_timeout_cb);
626     resched_timeout(alloc);
627     
628     /* Transport type */
629     relay->hkey.tp_type = req->tp_type;
630
631     /* Create the socket */
632     if (req->tp_type == PJ_TURN_TP_UDP) {
633         sock_type = pj_SOCK_DGRAM();
634     } else if (req->tp_type == PJ_TURN_TP_TCP) {
635         sock_type = pj_SOCK_STREAM();
636     } else {
637         pj_assert(!"Unknown transport");
638         return PJ_EINVALIDOP;
639     }
640
641     status = pj_sock_socket(af, sock_type, 0, &relay->tp.sock);
642     if (status != PJ_SUCCESS) {
643         pj_bzero(relay, sizeof(*relay));
644         return status;
645     }
646
647     /* Find suitable port for this allocation */
648     if (req->rpp_port) {
649         retry_max = 1;
650     } else {
651         retry_max = RETRY;
652     }
653
654     for (retry=0; retry<retry_max; ++retry) {
655         pj_uint16_t port;
656         pj_sockaddr bound_addr;
657
658         pj_lock_acquire(srv->core.lock);
659
660         if (req->rpp_port) {
661             port = (pj_uint16_t) req->rpp_port;
662         } else if (req->tp_type == PJ_TURN_TP_UDP) {
663             port = (pj_uint16_t) srv->ports.next_udp++;
664             if (srv->ports.next_udp > srv->ports.max_udp)
665                 srv->ports.next_udp = srv->ports.min_udp;
666         } else if (req->tp_type == PJ_TURN_TP_TCP) {
667             port = (pj_uint16_t) srv->ports.next_tcp++;
668             if (srv->ports.next_tcp > srv->ports.max_tcp)
669                 srv->ports.next_tcp = srv->ports.min_tcp;
670         } else {
671             pj_assert(!"Invalid transport");
672             port = 0;
673         }
674
675         pj_lock_release(srv->core.lock);
676
677         pj_sockaddr_init(af, &bound_addr, NULL, port);
678
679         status = pj_sock_bind(relay->tp.sock, &bound_addr, 
680                               pj_sockaddr_get_len(&bound_addr));
681         if (status == PJ_SUCCESS)
682             break;
683     }
684
685     if (status != PJ_SUCCESS) {
686         /* Unable to allocate port */
687         PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", 
688                   status));
689         pj_sock_close(relay->tp.sock);
690         relay->tp.sock = PJ_INVALID_SOCKET;
691         return status;
692     }
693
694     /* Init relay key */
695     namelen = sizeof(relay->hkey.addr);
696     status = pj_sock_getsockname(relay->tp.sock, &relay->hkey.addr, &namelen);
697     if (status != PJ_SUCCESS) {
698         PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d", 
699                   status));
700         pj_sock_close(relay->tp.sock);
701         relay->tp.sock = PJ_INVALID_SOCKET;
702         return status;
703     }
704     if (!pj_sockaddr_has_addr(&relay->hkey.addr)) {
705         pj_sockaddr_copy_addr(&relay->hkey.addr, 
706                               &alloc->transport->listener->addr);
707     }
708     if (!pj_sockaddr_has_addr(&relay->hkey.addr)) {
709         pj_sockaddr tmp_addr;
710         pj_gethostip(af, &tmp_addr);
711         pj_sockaddr_copy_addr(&relay->hkey.addr, &tmp_addr);
712     }
713
714     /* Init ioqueue */
715     pj_bzero(&icb, sizeof(icb));
716     icb.on_read_complete = &on_rx_from_peer;
717
718     status = pj_ioqueue_register_sock(pool, srv->core.ioqueue, relay->tp.sock,
719                                       relay, &icb, &relay->tp.key);
720     if (status != PJ_SUCCESS) {
721         PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d", 
722                   status));
723         pj_sock_close(relay->tp.sock);
724         relay->tp.sock = PJ_INVALID_SOCKET;
725         return status;
726     }
727
728     /* Kick off pending read operation */
729     pj_ioqueue_op_key_init(&relay->tp.read_key, sizeof(relay->tp.read_key));
730     on_rx_from_peer(relay->tp.key, &relay->tp.read_key, 0);
731
732     /* Done */
733     return PJ_SUCCESS;
734 }
735
736 /* Create and send error response */
737 static void send_reply_err(pj_turn_allocation *alloc,
738                            const pj_stun_rx_data *rdata,
739                            pj_bool_t cache, 
740                            int code, const char *errmsg)
741 {
742     pj_status_t status;
743
744     status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, NULL, 
745                                      cache, &alloc->hkey.clt_addr,
746                                      pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr));
747     if (status != PJ_SUCCESS) {
748         alloc_err(alloc, "Error sending STUN error response", status);
749         return;
750     }
751 }
752
753 /* Create and send successful response */
754 static void send_reply_ok(pj_turn_allocation *alloc,
755                           const pj_stun_rx_data *rdata)
756 {
757     pj_status_t status;
758     unsigned interval;
759     pj_stun_tx_data *tdata;
760
761     status = pj_stun_session_create_res(alloc->sess, rdata, 0, NULL, &tdata);
762     if (status != PJ_SUCCESS) {
763         alloc_err(alloc, "Error creating STUN success response", status);
764         return;
765     }
766
767     /* Calculate time to expiration */
768     if (alloc->relay.lifetime != 0) {
769         pj_time_val now;
770         pj_gettimeofday(&now);
771         interval = alloc->relay.expiry.sec - now.sec;
772     } else {
773         interval = 0;
774     }
775
776     /* Add LIFETIME if this is not ChannelBind. */
777     if (PJ_STUN_GET_METHOD(tdata->msg->hdr.type)!=PJ_STUN_CHANNEL_BIND_METHOD){
778         pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
779                                   PJ_STUN_ATTR_LIFETIME, interval);
780
781         /* Add BANDWIDTH if lifetime is not zero */
782         if (interval != 0) {
783             pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg,
784                                       PJ_STUN_ATTR_BANDWIDTH,
785                                       alloc->bandwidth);
786         }
787     }
788
789     status = pj_stun_session_send_msg(alloc->sess, NULL, PJ_TRUE, 
790                                       PJ_FALSE, &alloc->hkey.clt_addr,  
791                                       pj_sockaddr_get_len(&alloc->hkey.clt_addr), 
792                                       tdata);
793     if (status != PJ_SUCCESS) {
794         alloc_err(alloc, "Error sending STUN success response", status);
795         return;
796     }
797 }
798
799
800 /* Create new permission */
801 static pj_turn_permission *create_permission(pj_turn_allocation *alloc,
802                                              const pj_sockaddr_t *peer_addr,
803                                              unsigned addr_len)
804 {
805     pj_turn_permission *perm;
806
807     perm = PJ_POOL_ZALLOC_T(alloc->pool, pj_turn_permission);
808     pj_memcpy(&perm->hkey.peer_addr, peer_addr, addr_len);
809     
810     perm->allocation = alloc;
811     perm->channel = PJ_TURN_INVALID_CHANNEL;
812
813     pj_gettimeofday(&perm->expiry);
814     perm->expiry.sec += PJ_TURN_PERM_TIMEOUT;
815
816     /* Register to hash table (only the address part!) */
817     pj_hash_set(alloc->pool, alloc->peer_table, 
818                 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 
819                 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, perm);
820
821     return perm;
822 }
823
824 /* Check if a permission isn't expired. Return NULL if expired. */
825 static pj_turn_permission *check_permission_expiry(pj_turn_permission *perm)
826 {
827     pj_turn_allocation *alloc = perm->allocation;
828     pj_time_val now;
829
830     pj_gettimeofday(&now);
831     if (PJ_TIME_VAL_GT(perm->expiry, now)) {
832         /* Permission has not expired */
833         return perm;
834     }
835
836     /* Remove from permission hash table */
837     pj_hash_set(NULL, alloc->peer_table, 
838                 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 
839                 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, NULL);
840
841     /* Remove from channel hash table, if assigned a channel number */
842     if (perm->channel != PJ_TURN_INVALID_CHANNEL) {
843         pj_hash_set(NULL, alloc->ch_table, &perm->channel, 
844                     sizeof(perm->channel), 0, NULL);
845     }
846
847     return NULL;
848 }
849
850 /* Lookup permission in hash table by the peer address */
851 static pj_turn_permission*
852 lookup_permission_by_addr(pj_turn_allocation *alloc,
853                           const pj_sockaddr_t *peer_addr,
854                           unsigned addr_len)
855 {
856     pj_turn_permission *perm;
857
858     PJ_UNUSED_ARG(addr_len);
859
860     /* Lookup in peer hash table */
861     perm = (pj_turn_permission*) 
862            pj_hash_get(alloc->peer_table, 
863                        pj_sockaddr_get_addr(peer_addr),
864                        pj_sockaddr_get_addr_len(peer_addr), 
865                        NULL);
866     return perm ? check_permission_expiry(perm) : NULL;
867 }
868
869 /* Lookup permission in hash table by the channel number */
870 static pj_turn_permission*
871 lookup_permission_by_chnum(pj_turn_allocation *alloc,
872                            unsigned chnum)
873 {
874     pj_uint16_t chnum16 = (pj_uint16_t)chnum;
875     pj_turn_permission *perm;
876
877     /* Lookup in peer hash table */
878     perm = (pj_turn_permission*) pj_hash_get(alloc->ch_table, &chnum16,
879                                             sizeof(chnum16), NULL);
880     return perm ? check_permission_expiry(perm) : NULL;
881 }
882
883 /* Update permission because of data from client to peer. 
884  * Return PJ_TRUE is permission is found.
885  */
886 static pj_bool_t refresh_permission(pj_turn_permission *perm)
887 {
888     pj_gettimeofday(&perm->expiry);
889     if (perm->channel == PJ_TURN_INVALID_CHANNEL)
890         perm->expiry.sec += PJ_TURN_PERM_TIMEOUT;
891     else
892         perm->expiry.sec += PJ_TURN_CHANNEL_TIMEOUT;
893     return PJ_TRUE;
894 }
895
896 /*
897  * Handle incoming packet from client. This would have been called by
898  * server upon receiving packet from a listener.
899  */
900 PJ_DEF(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc,
901                                                  pj_turn_pkt *pkt)
902 {
903     pj_bool_t is_stun;
904     pj_status_t status;
905
906     /* Lock this allocation */
907     pj_lock_acquire(alloc->lock);
908
909     /* Quickly check if this is STUN message */
910     is_stun = ((*((pj_uint8_t*)pkt->pkt) & 0xC0) == 0);
911
912     if (is_stun) {
913         /*
914          * This could be an incoming STUN requests or indications.
915          * Pass this through to the STUN session, which will call
916          * our stun_on_rx_request() or stun_on_rx_indication()
917          * callbacks.
918          *
919          * Note: currently it is necessary to specify the 
920          * PJ_STUN_NO_FINGERPRINT_CHECK otherwise the FINGERPRINT
921          * attribute inside STUN Send Indication message will mess up
922          * with fingerprint checking.
923          */
924         unsigned options = PJ_STUN_CHECK_PACKET | PJ_STUN_NO_FINGERPRINT_CHECK;
925         pj_size_t parsed_len = 0;
926
927         if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP)
928             options |= PJ_STUN_IS_DATAGRAM;
929
930         status = pj_stun_session_on_rx_pkt(alloc->sess, pkt->pkt, pkt->len,
931                                            options, NULL, &parsed_len,
932                                            &pkt->src.clt_addr, 
933                                            pkt->src_addr_len);
934
935         if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP) {
936             pkt->len = 0;
937         } else if (parsed_len > 0) {
938             if (parsed_len == pkt->len) {
939                 pkt->len = 0;
940             } else {
941                 pj_memmove(pkt->pkt, pkt->pkt+parsed_len,
942                            pkt->len - parsed_len);
943                 pkt->len -= parsed_len;
944             }
945         }
946
947         if (status != PJ_SUCCESS) {
948             alloc_err(alloc, "Error handling STUN packet", status);
949             goto on_return;
950         }
951
952     } else {
953         /*
954          * This is not a STUN packet, must be ChannelData packet.
955          */
956         pj_turn_channel_data *cd = (pj_turn_channel_data*)pkt->pkt;
957         pj_turn_permission *perm;
958         pj_ssize_t len;
959
960         pj_assert(sizeof(*cd)==4);
961
962         /* For UDP check the packet length */
963         if (alloc->transport->listener->tp_type == PJ_TURN_TP_UDP) {
964             if (pkt->len < pj_ntohs(cd->length)+sizeof(*cd)) {
965                 PJ_LOG(4,(alloc->obj_name, 
966                           "ChannelData from %s discarded: UDP size error",
967                           alloc->info));
968                 goto on_return;
969             }
970         } else {
971             pj_assert(!"Unsupported transport");
972             goto on_return;
973         }
974
975         perm = lookup_permission_by_chnum(alloc, pj_ntohs(cd->ch_number));
976         if (!perm) {
977             /* Discard */
978             PJ_LOG(4,(alloc->obj_name, 
979                       "ChannelData from %s discarded: ch#0x%x not found",
980                       alloc->info, pj_ntohs(cd->ch_number)));
981             goto on_return;
982         }
983
984         /* Relay the data */
985         len = pj_ntohs(cd->length);
986         pj_sock_sendto(alloc->relay.tp.sock, cd+1, &len, 0,
987                        &perm->hkey.peer_addr,
988                        pj_sockaddr_get_len(&perm->hkey.peer_addr));
989
990         /* Refresh permission */
991         refresh_permission(perm);
992     }
993
994 on_return:
995     /* Release lock */
996     pj_lock_release(alloc->lock);
997 }
998
999
1000 /*
1001  * Handle incoming packet from peer. This function is called by 
1002  * on_rx_from_peer().
1003  */
1004 static void handle_peer_pkt(pj_turn_allocation *alloc,
1005                             pj_turn_relay_res *rel,
1006                             char *pkt, pj_size_t len,
1007                             const pj_sockaddr *src_addr)
1008 {
1009     pj_turn_permission *perm;
1010
1011     /* Lookup permission */
1012     perm = lookup_permission_by_addr(alloc, src_addr, 
1013                                      pj_sockaddr_get_len(src_addr));
1014     if (perm == NULL) {
1015         /* No permission, discard data */
1016         return;
1017     }
1018
1019     /* Send Data Indication or ChannelData, depends on whether
1020      * this permission is attached to a channel number.
1021      */
1022     if (perm->channel != PJ_TURN_INVALID_CHANNEL) {
1023         /* Send ChannelData */
1024         pj_turn_channel_data *cd = (pj_turn_channel_data*)rel->tp.tx_pkt;
1025
1026         if (len > PJ_TURN_MAX_PKT_LEN) {
1027             char peer_addr[80];
1028             pj_sockaddr_print(src_addr, peer_addr, sizeof(peer_addr), 3);
1029             PJ_LOG(4,(alloc->obj_name, "Client %s: discarded data from %s "
1030                       "because it's too long (%d bytes)",
1031                       alloc->info, peer_addr, len));
1032             return;
1033         }
1034
1035         /* Init header */
1036         cd->ch_number = pj_htons(perm->channel);
1037         cd->length = pj_htons((pj_uint16_t)len);
1038
1039         /* Copy data */
1040         pj_memcpy(rel->tp.tx_pkt+sizeof(pj_turn_channel_data), pkt, len);
1041
1042         /* Send to client */
1043         alloc->transport->sendto(alloc->transport, rel->tp.tx_pkt,
1044                                  len+sizeof(pj_turn_channel_data), 0,
1045                                  &alloc->hkey.clt_addr,
1046                                  pj_sockaddr_get_len(&alloc->hkey.clt_addr));
1047     } else {
1048         /* Send Data Indication */
1049         pj_stun_tx_data *tdata;
1050         pj_status_t status;
1051
1052         status = pj_stun_session_create_ind(alloc->sess, 
1053                                             PJ_STUN_DATA_INDICATION, &tdata);
1054         if (status != PJ_SUCCESS) {
1055             alloc_err(alloc, "Error creating Data indication", status);
1056             return;
1057         }
1058
1059         pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
1060                                       PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE,
1061                                       src_addr, pj_sockaddr_get_len(src_addr));
1062         pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg,
1063                                     PJ_STUN_ATTR_DATA, 
1064                                     (const pj_uint8_t*)pkt, len);
1065
1066         pj_stun_session_send_msg(alloc->sess, NULL, PJ_FALSE, 
1067                                  PJ_FALSE, &alloc->hkey.clt_addr, 
1068                                  pj_sockaddr_get_len(&alloc->hkey.clt_addr), 
1069                                  tdata);
1070     }
1071 }
1072
1073 /*
1074  * ioqueue notification on RX packets from the relay socket.
1075  */
1076 static void on_rx_from_peer(pj_ioqueue_key_t *key, 
1077                             pj_ioqueue_op_key_t *op_key, 
1078                             pj_ssize_t bytes_read)
1079 {
1080     pj_turn_relay_res *rel;
1081     pj_status_t status;
1082
1083     rel = (pj_turn_relay_res*) pj_ioqueue_get_user_data(key);
1084
1085     /* Lock the allocation */
1086     pj_lock_acquire(rel->allocation->lock);
1087
1088     do {
1089         if (bytes_read > 0) {
1090             handle_peer_pkt(rel->allocation, rel, rel->tp.rx_pkt,
1091                             bytes_read, &rel->tp.src_addr);
1092         }
1093
1094         /* Read next packet */
1095         bytes_read = sizeof(rel->tp.rx_pkt);
1096         rel->tp.src_addr_len = sizeof(rel->tp.src_addr);
1097         status = pj_ioqueue_recvfrom(key, op_key,
1098                                      rel->tp.rx_pkt, &bytes_read, 0,
1099                                      &rel->tp.src_addr, 
1100                                      &rel->tp.src_addr_len);
1101
1102         if (status != PJ_EPENDING && status != PJ_SUCCESS)
1103             bytes_read = -status;
1104
1105     } while (status != PJ_EPENDING && status != PJ_ECANCELLED);
1106
1107     /* Release allocation lock */
1108     pj_lock_release(rel->allocation->lock);
1109 }
1110
1111 /*
1112  * Callback notification from STUN session when it wants to send
1113  * a STUN message towards the client.
1114  */
1115 static pj_status_t stun_on_send_msg(pj_stun_session *sess,
1116                                     void *token,
1117                                     const void *pkt,
1118                                     pj_size_t pkt_size,
1119                                     const pj_sockaddr_t *dst_addr,
1120                                     unsigned addr_len)
1121 {
1122     pj_turn_allocation *alloc;
1123
1124     PJ_UNUSED_ARG(token);
1125
1126     alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess);
1127
1128     return alloc->transport->sendto(alloc->transport, pkt, pkt_size, 0,
1129                                     dst_addr, addr_len);
1130 }
1131
1132 /*
1133  * Callback notification from STUN session when it receives STUN
1134  * requests. This callback was trigger by STUN incoming message
1135  * processing in pj_turn_allocation_on_rx_client_pkt().
1136  */
1137 static pj_status_t stun_on_rx_request(pj_stun_session *sess,
1138                                       const pj_uint8_t *pkt,
1139                                       unsigned pkt_len,
1140                                       const pj_stun_rx_data *rdata,
1141                                       void *token,
1142                                       const pj_sockaddr_t *src_addr,
1143                                       unsigned src_addr_len)
1144 {
1145     const pj_stun_msg *msg = rdata->msg;
1146     pj_turn_allocation *alloc;
1147
1148     PJ_UNUSED_ARG(pkt);
1149     PJ_UNUSED_ARG(pkt_len);
1150     PJ_UNUSED_ARG(token);
1151     PJ_UNUSED_ARG(src_addr);
1152     PJ_UNUSED_ARG(src_addr_len);
1153
1154     alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess);
1155
1156     /* Refuse to serve any request if we've been shutdown */
1157     if (alloc->relay.lifetime == 0) {
1158         /* Reject with 437 if we're shutting down */
1159         send_reply_err(alloc, rdata, PJ_TRUE, 
1160                        PJ_STUN_SC_ALLOCATION_MISMATCH, NULL);
1161         return PJ_SUCCESS;
1162     }
1163
1164     if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) {
1165         /* 
1166          * Handle REFRESH request 
1167          */
1168         pj_stun_lifetime_attr *lifetime;
1169         pj_stun_bandwidth_attr *bandwidth;
1170
1171         /* Get LIFETIME attribute */
1172         lifetime = (pj_stun_lifetime_attr*)
1173                    pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_LIFETIME, 0);
1174
1175         /* Get BANDWIDTH attribute */
1176         bandwidth = (pj_stun_bandwidth_attr*)
1177                     pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0);
1178
1179         if (lifetime && lifetime->value==0) {
1180             /*
1181              * This is deallocation request.
1182              */
1183             alloc->relay.lifetime = 0;
1184
1185             /* Respond first */
1186             send_reply_ok(alloc, rdata);
1187
1188             /* Shutdown allocation */
1189             PJ_LOG(4,(alloc->obj_name, 
1190                       "Client %s request to dealloc, shutting down",
1191                       alloc->info));
1192
1193             alloc_shutdown(alloc);
1194
1195         } else {
1196             /*
1197              * This is a refresh request.
1198              */
1199             
1200             /* Update lifetime */
1201             if (lifetime) {
1202                 alloc->relay.lifetime = lifetime->value;
1203             }
1204
1205             /* Update bandwidth */
1206             // TODO:
1207
1208             /* Update expiration timer */
1209             resched_timeout(alloc);
1210
1211             /* Send reply */
1212             send_reply_ok(alloc, rdata);
1213         }
1214
1215     } else if (msg->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) {
1216         /*
1217          * ChannelBind request.
1218          */
1219         pj_stun_channel_number_attr *ch_attr;
1220         pj_stun_xor_peer_addr_attr *peer_attr;
1221         pj_turn_permission *p1, *p2;
1222
1223         ch_attr = (pj_stun_channel_number_attr*)
1224                   pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_CHANNEL_NUMBER, 0);
1225         peer_attr = (pj_stun_xor_peer_addr_attr*)
1226                     pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
1227
1228         if (!ch_attr || !peer_attr) {
1229             send_reply_err(alloc, rdata, PJ_TRUE, 
1230                            PJ_STUN_SC_BAD_REQUEST, NULL);
1231             return PJ_SUCCESS;
1232         }
1233
1234         /* Find permission with the channel number */
1235         p1 = lookup_permission_by_chnum(alloc, PJ_STUN_GET_CH_NB(ch_attr->value));
1236
1237         /* If permission is found, this is supposed to be a channel bind 
1238          * refresh. Make sure it's for the same peer.
1239          */
1240         if (p1) {
1241             if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) {
1242                 /* Address mismatch. Send 400 */
1243                 send_reply_err(alloc, rdata, PJ_TRUE, 
1244                                PJ_STUN_SC_BAD_REQUEST, 
1245                                "Peer address mismatch");
1246                 return PJ_SUCCESS;
1247             }
1248
1249             /* Refresh permission */
1250             refresh_permission(p1);
1251
1252             /* Send response */
1253             send_reply_ok(alloc, rdata);
1254
1255             /* Done */
1256             return PJ_SUCCESS;
1257         }
1258
1259         /* If permission is not found, create a new one. Make sure the peer
1260          * has not alreadyy assigned with a channel number.
1261          */
1262         p2 = lookup_permission_by_addr(alloc, &peer_attr->sockaddr,
1263                                        pj_sockaddr_get_len(&peer_attr->sockaddr));
1264         if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) {
1265             send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 
1266                            "Peer address already assigned a channel number");
1267             return PJ_SUCCESS;
1268         }
1269
1270         /* Create permission if it doesn't exist */
1271         if (!p2) {
1272             p2 = create_permission(alloc, &peer_attr->sockaddr,
1273                                    pj_sockaddr_get_len(&peer_attr->sockaddr));
1274             if (!p2)
1275                 return PJ_SUCCESS;
1276         }
1277
1278         /* Assign channel number to permission */
1279         p2->channel = PJ_STUN_GET_CH_NB(ch_attr->value);
1280
1281         /* Register to hash table */
1282         pj_assert(sizeof(p2->channel==2));
1283         pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 
1284                     sizeof(p2->channel), 0, p2);
1285
1286         /* Update */
1287         refresh_permission(p2);
1288
1289         /* Reply */
1290         send_reply_ok(alloc, rdata);
1291
1292         return PJ_SUCCESS;
1293
1294     } else if (msg->hdr.type == PJ_STUN_ALLOCATE_REQUEST) {
1295
1296         /* Respond with 437 (section 6.3 turn-07) */
1297         send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_ALLOCATION_MISMATCH,
1298                        NULL);
1299
1300     } else {
1301
1302         /* Respond with Bad Request? */
1303         send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, NULL);
1304
1305     }
1306
1307     return PJ_SUCCESS;
1308 }
1309
1310 /*
1311  * Callback notification from STUN session when it receives STUN
1312  * indications. This callback was trigger by STUN incoming message
1313  * processing in pj_turn_allocation_on_rx_client_pkt().
1314  */
1315 static pj_status_t stun_on_rx_indication(pj_stun_session *sess,
1316                                          const pj_uint8_t *pkt,
1317                                          unsigned pkt_len,
1318                                          const pj_stun_msg *msg,
1319                                          void *token,
1320                                          const pj_sockaddr_t *src_addr,
1321                                          unsigned src_addr_len)
1322 {
1323     pj_stun_xor_peer_addr_attr *peer_attr;
1324     pj_stun_data_attr *data_attr;
1325     pj_turn_allocation *alloc;
1326     pj_turn_permission *perm;
1327     pj_ssize_t len;
1328
1329     PJ_UNUSED_ARG(pkt);
1330     PJ_UNUSED_ARG(pkt_len);
1331     PJ_UNUSED_ARG(token);
1332     PJ_UNUSED_ARG(src_addr);
1333     PJ_UNUSED_ARG(src_addr_len);
1334
1335     alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess);
1336
1337     /* Only expect Send Indication */
1338     if (msg->hdr.type != PJ_STUN_SEND_INDICATION) {
1339         /* Ignore */
1340         return PJ_SUCCESS;
1341     }
1342
1343     /* Get XOR-PEER-ADDRESS attribute */
1344     peer_attr = (pj_stun_xor_peer_addr_attr*)
1345                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
1346
1347     /* MUST have XOR-PEER-ADDRESS attribute */
1348     if (!peer_attr)
1349         return PJ_SUCCESS;
1350
1351     /* Get DATA attribute */
1352     data_attr = (pj_stun_data_attr*)
1353                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0);
1354
1355     /* Create/update/refresh the permission */
1356     perm = lookup_permission_by_addr(alloc, &peer_attr->sockaddr,
1357                                      pj_sockaddr_get_len(&peer_attr->sockaddr));
1358     if (perm == NULL) {
1359         perm = create_permission(alloc, &peer_attr->sockaddr,
1360                                  pj_sockaddr_get_len(&peer_attr->sockaddr));
1361     }
1362     refresh_permission(perm);
1363
1364     /* Return if we don't have data */
1365     if (data_attr == NULL)
1366         return PJ_SUCCESS;
1367
1368     /* Relay the data to peer */
1369     len = data_attr->length;
1370     pj_sock_sendto(alloc->relay.tp.sock, data_attr->data, 
1371                    &len, 0, &peer_attr->sockaddr,
1372                    pj_sockaddr_get_len(&peer_attr->sockaddr));
1373
1374     return PJ_SUCCESS;
1375 }
1376
1377