Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjnath / src / pjnath-test / server.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 "server.h"
21 #include "test.h"
22
23 #define THIS_FILE       "server.c"
24 #define MAX_STUN_PKT    1500
25 #define TURN_NONCE      "thenonce"
26
27 static pj_bool_t stun_on_data_recvfrom(pj_activesock_t *asock,
28                                        void *data,
29                                        pj_size_t size,
30                                        const pj_sockaddr_t *src_addr,
31                                        int addr_len,
32                                        pj_status_t status);
33 static pj_bool_t turn_on_data_recvfrom(pj_activesock_t *asock,
34                                        void *data,
35                                        pj_size_t size,
36                                        const pj_sockaddr_t *src_addr,
37                                        int addr_len,
38                                        pj_status_t status);
39 static pj_bool_t alloc_on_data_recvfrom(pj_activesock_t *asock,
40                                        void *data,
41                                        pj_size_t size,
42                                        const pj_sockaddr_t *src_addr,
43                                        int addr_len,
44                                        pj_status_t status);
45
46 pj_status_t create_test_server(pj_stun_config *stun_cfg,
47                                pj_uint32_t flags,
48                                const char *domain,
49                                test_server **p_test_srv)
50 {
51     pj_pool_t *pool;
52     test_server *test_srv;
53     pj_sockaddr hostip;
54     char strbuf[100];
55     pj_status_t status;
56
57     PJ_ASSERT_RETURN(stun_cfg && domain && p_test_srv, PJ_EINVAL);
58
59     status = pj_gethostip(pj_AF_INET(), &hostip);
60     if (status != PJ_SUCCESS)
61         return status;
62
63     pool = pj_pool_create(mem, THIS_FILE, 512, 512, NULL);
64     test_srv = (test_server*) PJ_POOL_ZALLOC_T(pool, test_server);
65     test_srv->pool = pool;
66     test_srv->flags = flags;
67     test_srv->stun_cfg = stun_cfg;
68
69     pj_strdup2(pool, &test_srv->domain, domain);
70     test_srv->username = pj_str(TURN_USERNAME);
71     test_srv->passwd = pj_str(TURN_PASSWD);
72
73     pj_ioqueue_op_key_init(&test_srv->send_key, sizeof(test_srv->send_key));
74
75     if (flags & CREATE_DNS_SERVER) {
76         status = pj_dns_server_create(mem, test_srv->stun_cfg->ioqueue,
77                                       pj_AF_INET(), DNS_SERVER_PORT,
78                                       0, &test_srv->dns_server);
79         if (status != PJ_SUCCESS) {
80             destroy_test_server(test_srv);
81             return status;
82         }
83
84         /* Add DNS A record for the domain, for fallback */
85         if (flags & CREATE_A_RECORD_FOR_DOMAIN) {
86             pj_dns_parsed_rr rr;
87             pj_str_t res_name;
88             pj_in_addr ip_addr;
89
90             pj_strdup2(pool, &res_name, domain);
91             ip_addr = hostip.ipv4.sin_addr;
92             pj_dns_init_a_rr(&rr, &res_name, PJ_DNS_CLASS_IN, 60, &ip_addr);
93             pj_dns_server_add_rec(test_srv->dns_server, 1, &rr);
94         }
95
96     }
97
98     if (flags & CREATE_STUN_SERVER) {
99         pj_activesock_cb stun_sock_cb;
100         pj_sockaddr bound_addr;
101
102         pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
103         stun_sock_cb.on_data_recvfrom = &stun_on_data_recvfrom;
104
105         pj_sockaddr_in_init(&bound_addr.ipv4, NULL, STUN_SERVER_PORT);
106
107         status = pj_activesock_create_udp(pool, &bound_addr, NULL, 
108                                           test_srv->stun_cfg->ioqueue,
109                                           &stun_sock_cb, test_srv, 
110                                           &test_srv->stun_sock, NULL);
111         if (status != PJ_SUCCESS) {
112             destroy_test_server(test_srv);
113             return status;
114         }
115
116         status = pj_activesock_start_recvfrom(test_srv->stun_sock, pool,
117                                               MAX_STUN_PKT, 0);
118         if (status != PJ_SUCCESS) {
119             destroy_test_server(test_srv);
120             return status;
121         }
122
123         if (test_srv->dns_server && (flags & CREATE_STUN_SERVER_DNS_SRV)) {
124             pj_str_t res_name, target;
125             pj_dns_parsed_rr rr;
126             pj_in_addr ip_addr;
127
128             /* Add DNS entries:
129              *  _stun._udp.domain 60 IN SRV 0 0 PORT stun.domain.
130              *  stun.domain IN A 127.0.0.1
131              */
132             pj_ansi_snprintf(strbuf, sizeof(strbuf),
133                              "_stun._udp.%s", domain);
134             pj_strdup2(pool, &res_name, strbuf);
135             pj_ansi_snprintf(strbuf, sizeof(strbuf),
136                              "stun.%s", domain);
137             pj_strdup2(pool, &target, strbuf);
138             pj_dns_init_srv_rr(&rr, &res_name, PJ_DNS_CLASS_IN, 60, 0, 0, 
139                                STUN_SERVER_PORT, &target);
140             pj_dns_server_add_rec(test_srv->dns_server, 1, &rr);
141
142             res_name = target;
143             ip_addr = hostip.ipv4.sin_addr;
144             pj_dns_init_a_rr(&rr, &res_name, PJ_DNS_CLASS_IN, 60, &ip_addr);
145             pj_dns_server_add_rec(test_srv->dns_server, 1, &rr);
146         }
147
148     }
149
150     if (flags & CREATE_TURN_SERVER) {
151         pj_activesock_cb turn_sock_cb;
152         pj_sockaddr bound_addr;
153
154         pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb));
155         turn_sock_cb.on_data_recvfrom = &turn_on_data_recvfrom;
156
157         pj_sockaddr_in_init(&bound_addr.ipv4, NULL, TURN_SERVER_PORT);
158
159         status = pj_activesock_create_udp(pool, &bound_addr, NULL, 
160                                           test_srv->stun_cfg->ioqueue,
161                                           &turn_sock_cb, test_srv,
162                                           &test_srv->turn_sock, NULL);
163         if (status != PJ_SUCCESS) {
164             destroy_test_server(test_srv);
165             return status;
166         }
167
168         status = pj_activesock_start_recvfrom(test_srv->turn_sock, pool,
169                                               MAX_STUN_PKT, 0);
170         if (status != PJ_SUCCESS) {
171             destroy_test_server(test_srv);
172             return status;
173         }
174
175         if (test_srv->dns_server && (flags & CREATE_TURN_SERVER_DNS_SRV)) {
176             pj_str_t res_name, target;
177             pj_dns_parsed_rr rr;
178             pj_in_addr ip_addr;
179
180             /* Add DNS entries:
181              *  _turn._udp.domain 60 IN SRV 0 0 PORT turn.domain.
182              *  turn.domain IN A 127.0.0.1
183              */
184             pj_ansi_snprintf(strbuf, sizeof(strbuf),
185                              "_turn._udp.%s", domain);
186             pj_strdup2(pool, &res_name, strbuf);
187             pj_ansi_snprintf(strbuf, sizeof(strbuf),
188                              "turn.%s", domain);
189             pj_strdup2(pool, &target, strbuf);
190             pj_dns_init_srv_rr(&rr, &res_name, PJ_DNS_CLASS_IN, 60, 0, 0, 
191                                TURN_SERVER_PORT, &target);
192             pj_dns_server_add_rec(test_srv->dns_server, 1, &rr);
193
194             res_name = target;
195             ip_addr = hostip.ipv4.sin_addr;
196             pj_dns_init_a_rr(&rr, &res_name, PJ_DNS_CLASS_IN, 60, &ip_addr);
197             pj_dns_server_add_rec(test_srv->dns_server, 1, &rr);
198         }
199     }
200
201     *p_test_srv = test_srv;
202     return PJ_SUCCESS;
203 }
204
205 void destroy_test_server(test_server *test_srv)
206 {
207     unsigned i;
208
209     PJ_ASSERT_ON_FAIL(test_srv, return);
210
211     for (i=0; i<test_srv->turn_alloc_cnt; ++i) {
212         pj_activesock_close(test_srv->turn_alloc[i].sock);
213         pj_pool_release(test_srv->turn_alloc[i].pool);
214     }
215     test_srv->turn_alloc_cnt = 0;
216
217     if (test_srv->turn_sock) {
218         pj_activesock_close(test_srv->turn_sock);
219         test_srv->turn_sock = NULL;
220     }
221
222     if (test_srv->stun_sock) {
223         pj_activesock_close(test_srv->stun_sock);
224         test_srv->stun_sock = NULL;
225     }
226
227     if (test_srv->dns_server) {
228         pj_dns_server_destroy(test_srv->dns_server);
229         test_srv->dns_server = NULL;
230     }
231
232     if (test_srv->pool) {
233         pj_pool_t *pool = test_srv->pool;
234         test_srv->pool = NULL;
235         pj_pool_release(pool);
236     }
237 }
238
239 static pj_bool_t stun_on_data_recvfrom(pj_activesock_t *asock,
240                                        void *data,
241                                        pj_size_t size,
242                                        const pj_sockaddr_t *src_addr,
243                                        int addr_len,
244                                        pj_status_t status)
245 {
246     test_server *test_srv;
247     pj_stun_msg *req, *resp = NULL;
248     pj_pool_t *pool;
249     pj_ssize_t len;
250
251     if (status != PJ_SUCCESS)
252         return PJ_TRUE;
253
254     test_srv = (test_server*) pj_activesock_get_user_data(asock);
255     pool = pj_pool_create(test_srv->stun_cfg->pf, NULL, 512, 512, NULL);
256
257     status = pj_stun_msg_decode(pool, (pj_uint8_t*)data, size, 
258                                 PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, 
259                                 &req, NULL, NULL);
260     if (status != PJ_SUCCESS)
261         goto on_return;
262
263     if (req->hdr.type != PJ_STUN_BINDING_REQUEST) {
264         pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, 
265                                     NULL, &resp);
266         goto send_pkt;
267     }
268
269     status = pj_stun_msg_create_response(pool, req, 0, NULL, &resp);
270     if (status != PJ_SUCCESS)
271         goto on_return;
272
273     pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_MAPPED_ADDR,
274                                   PJ_TRUE, src_addr, addr_len);
275
276 send_pkt:
277     status = pj_stun_msg_encode(resp, (pj_uint8_t*)data, MAX_STUN_PKT, 
278                                 0, NULL, &size);
279     if (status != PJ_SUCCESS)
280         goto on_return;
281
282     len = size;
283     status = pj_activesock_sendto(asock, &test_srv->send_key, data, &len,
284                                   0, src_addr, addr_len);
285
286 on_return:
287     pj_pool_release(pool);
288     return PJ_TRUE;
289 }
290
291
292 static pj_stun_msg* create_success_response(test_server *test_srv,
293                                             turn_allocation *alloc,
294                                             pj_stun_msg *req,
295                                             pj_pool_t *pool,
296                                             unsigned lifetime,
297                                             pj_str_t *auth_key)
298 {
299     pj_stun_msg *resp;
300     pj_str_t tmp;
301     pj_status_t status;
302
303     /* Create response */
304     status = pj_stun_msg_create_response(pool, req, 0, NULL, &resp);
305     if (status != PJ_SUCCESS) {
306         return NULL;
307     }
308     /* Add TURN_NONCE */
309     pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE));
310     /* Add LIFETIME */
311     pj_stun_msg_add_uint_attr(pool, resp, PJ_STUN_ATTR_LIFETIME, lifetime);
312     if (lifetime != 0) {
313         /* Add XOR-RELAYED-ADDRESS */
314         pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr,
315                                       pj_sockaddr_get_len(&alloc->alloc_addr));
316         /* Add XOR-MAPPED-ADDRESS */
317         pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, &alloc->client_addr,
318                                       pj_sockaddr_get_len(&alloc->client_addr));
319     }
320
321     /* Add blank MESSAGE-INTEGRITY */
322     pj_stun_msg_add_msgint_attr(pool, resp);
323
324     /* Set auth key */
325     pj_stun_create_key(pool, auth_key, &test_srv->domain, &test_srv->username,
326                        PJ_STUN_PASSWD_PLAIN, &test_srv->passwd);
327
328     return resp;
329 }
330
331
332 static pj_bool_t turn_on_data_recvfrom(pj_activesock_t *asock,
333                                        void *data,
334                                        pj_size_t size,
335                                        const pj_sockaddr_t *src_addr,
336                                        int addr_len,
337                                        pj_status_t status)
338 {
339     test_server *test_srv;
340     pj_pool_t *pool;
341     turn_allocation *alloc;
342     pj_stun_msg *req, *resp = NULL;
343     pj_str_t auth_key = { NULL, 0 };
344     char client_info[PJ_INET6_ADDRSTRLEN+10];
345     unsigned i;
346     pj_ssize_t len;
347
348     if (status != PJ_SUCCESS)
349         return PJ_TRUE;
350
351     pj_sockaddr_print(src_addr, client_info, sizeof(client_info), 3);
352
353     test_srv = (test_server*) pj_activesock_get_user_data(asock);
354     pool = pj_pool_create(test_srv->stun_cfg->pf, NULL, 512, 512, NULL);
355
356     /* Find the client */
357     for (i=0; i<test_srv->turn_alloc_cnt; i++) {
358         if (pj_sockaddr_cmp(&test_srv->turn_alloc[i].client_addr, src_addr)==0)
359             break;
360     }
361
362
363     if (pj_stun_msg_check((pj_uint8_t*)data, size, PJ_STUN_NO_FINGERPRINT_CHECK)!=PJ_SUCCESS)  {
364         /* Not STUN message, this probably is a ChannelData */
365         pj_turn_channel_data cd;
366         const pj_turn_channel_data *pcd = (const pj_turn_channel_data*)data;
367         pj_ssize_t sent;
368
369         if (i==test_srv->turn_alloc_cnt) {
370             /* Invalid data */
371             PJ_LOG(1,(THIS_FILE, 
372                       "TURN Server received strayed data"));
373             goto on_return;
374         }
375
376         alloc = &test_srv->turn_alloc[i];
377
378         cd.ch_number = pj_ntohs(pcd->ch_number);
379         cd.length = pj_ntohs(pcd->length);
380
381         /* For UDP check the packet length */
382         if (size < cd.length+sizeof(cd)) {
383             PJ_LOG(1,(THIS_FILE, 
384                       "TURN Server: ChannelData discarded: UDP size error"));
385             goto on_return;
386         }
387
388         /* Lookup peer */
389         for (i=0; i<alloc->perm_cnt; ++i) {
390             if (alloc->chnum[i] == cd.ch_number)
391                 break;
392         }
393
394         if (i==alloc->perm_cnt) {
395             PJ_LOG(1,(THIS_FILE, 
396                       "TURN Server: ChannelData discarded: invalid channel number"));
397             goto on_return;
398         }
399
400         /* Relay the data to peer */
401         sent = cd.length;
402         pj_activesock_sendto(alloc->sock, &alloc->send_key,
403                              pcd+1, &sent, 0,
404                              &alloc->perm[i],
405                              pj_sockaddr_get_len(&alloc->perm[i]));
406
407         /* Done */
408         goto on_return;
409     }
410
411     status = pj_stun_msg_decode(pool, (pj_uint8_t*)data, size, 
412                                 PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET |
413                                     PJ_STUN_NO_FINGERPRINT_CHECK, 
414                                 &req, NULL, NULL);
415     if (status != PJ_SUCCESS) {
416         char errmsg[PJ_ERR_MSG_SIZE];
417         pj_strerror(status, errmsg, sizeof(errmsg));
418         PJ_LOG(1,("", "STUN message decode error from client %s: %s", client_info, errmsg));
419         goto on_return;
420     }
421
422     if (i==test_srv->turn_alloc_cnt) {
423         /* New client */
424         //pj_str_t ip_addr;
425         pj_stun_username_attr *uname;
426         pj_activesock_cb alloc_sock_cb;
427         turn_allocation *alloc;
428
429         /* Must be Allocate request */
430         if (req->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
431             PJ_LOG(1,(THIS_FILE, "Invalid %s %s from client %s",
432                       pj_stun_get_method_name(req->hdr.type),
433                       pj_stun_get_class_name(req->hdr.type),
434                       client_info));
435
436             if (PJ_STUN_IS_REQUEST(req->hdr.type))
437                 pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp);
438             goto send_pkt;
439         }
440
441         test_srv->turn_stat.rx_allocate_cnt++;
442
443         /* Skip if we're not responding to Allocate request */
444         if (!test_srv->turn_respond_allocate)
445             return PJ_TRUE;
446
447         /* Check if we have too many clients */
448         if (test_srv->turn_alloc_cnt == MAX_TURN_ALLOC) {
449             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp);
450             goto send_pkt;
451         }
452
453         /* Get USERNAME attribute */
454         uname = (pj_stun_username_attr*)
455                 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0);
456
457         /* Reject if it doesn't have MESSAGE-INTEGRITY or USERNAME attributes or
458          * the user is incorrect
459          */
460         if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0) == NULL ||
461             uname==NULL || pj_stricmp2(&uname->value, TURN_USERNAME) != 0) 
462         {
463             pj_str_t tmp;
464
465             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_UNAUTHORIZED, NULL, &resp);
466             pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_REALM, &test_srv->domain);
467             pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE));
468             goto send_pkt;
469         }
470
471         pj_bzero(&alloc_sock_cb, sizeof(alloc_sock_cb));
472         alloc_sock_cb.on_data_recvfrom = &alloc_on_data_recvfrom;
473
474         /* Create allocation */
475         alloc = &test_srv->turn_alloc[test_srv->turn_alloc_cnt];
476         alloc->perm_cnt = 0;
477         alloc->test_srv = test_srv;
478         pj_memcpy(&alloc->client_addr, src_addr, addr_len);
479         pj_ioqueue_op_key_init(&alloc->send_key, sizeof(alloc->send_key));
480
481         alloc->pool = pj_pool_create(test_srv->stun_cfg->pf, "alloc", 512, 512, NULL);
482
483         /* Create relay socket */
484         pj_sockaddr_in_init(&alloc->alloc_addr.ipv4, NULL, 0);
485         pj_gethostip(pj_AF_INET(), &alloc->alloc_addr);
486
487         status = pj_activesock_create_udp(alloc->pool, &alloc->alloc_addr, NULL, 
488                                           test_srv->stun_cfg->ioqueue,
489                                           &alloc_sock_cb, alloc, 
490                                           &alloc->sock, &alloc->alloc_addr);
491         if (status != PJ_SUCCESS) {
492             pj_pool_release(alloc->pool);
493             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
494             goto send_pkt;
495         }
496         //pj_sockaddr_set_str_addr(pj_AF_INET(), &alloc->alloc_addr, &ip_addr);
497
498         pj_activesock_set_user_data(alloc->sock, alloc);
499
500         status = pj_activesock_start_recvfrom(alloc->sock, alloc->pool, 1500, 0);
501         if (status != PJ_SUCCESS) {
502             pj_activesock_close(alloc->sock);
503             pj_pool_release(alloc->pool);
504             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
505             goto send_pkt;
506         }
507
508         /* Create Data indication */
509         status = pj_stun_msg_create(alloc->pool, PJ_STUN_DATA_INDICATION,
510                                     PJ_STUN_MAGIC, NULL, &alloc->data_ind);
511         if (status != PJ_SUCCESS) {
512             pj_activesock_close(alloc->sock);
513             pj_pool_release(alloc->pool);
514             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
515             goto send_pkt;
516         }
517         pj_stun_msg_add_sockaddr_attr(alloc->pool, alloc->data_ind, 
518                                       PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE,
519                                       &alloc->alloc_addr,
520                                       pj_sockaddr_get_len(&alloc->alloc_addr));
521         pj_stun_msg_add_binary_attr(alloc->pool, alloc->data_ind,
522                                     PJ_STUN_ATTR_DATA, (pj_uint8_t*)"", 1);
523
524         /* Create response */
525         resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key);
526         if (resp == NULL) {
527             pj_activesock_close(alloc->sock);
528             pj_pool_release(alloc->pool);
529             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
530             goto send_pkt;
531         }
532
533         ++test_srv->turn_alloc_cnt;
534
535     } else {
536         alloc = &test_srv->turn_alloc[i];
537
538         if (req->hdr.type == PJ_STUN_ALLOCATE_REQUEST) {
539
540             test_srv->turn_stat.rx_allocate_cnt++;
541
542             /* Skip if we're not responding to Allocate request */
543             if (!test_srv->turn_respond_allocate)
544                 return PJ_TRUE;
545
546             resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
547
548         } else if (req->hdr.type == PJ_STUN_REFRESH_REQUEST) {
549             pj_stun_lifetime_attr *lf_attr;
550
551             test_srv->turn_stat.rx_refresh_cnt++;
552
553             /* Skip if we're not responding to Refresh request */
554             if (!test_srv->turn_respond_refresh)
555                 return PJ_TRUE;
556
557             lf_attr = (pj_stun_lifetime_attr*)
558                       pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0);
559             if (lf_attr && lf_attr->value != 0) {
560                 resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key);
561                 pj_array_erase(test_srv->turn_alloc, sizeof(test_srv->turn_alloc[0]),
562                                test_srv->turn_alloc_cnt, i);
563                 --test_srv->turn_alloc_cnt;
564             } else
565                 resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
566         } else if (req->hdr.type == PJ_STUN_CREATE_PERM_REQUEST) {
567             for (i=0; i<req->attr_count; ++i) {
568                 if (req->attr[i]->type == PJ_STUN_ATTR_XOR_PEER_ADDR) {
569                     pj_stun_xor_peer_addr_attr *pa = (pj_stun_xor_peer_addr_attr*)req->attr[i];
570                     unsigned j;
571
572                     for (j=0; j<alloc->perm_cnt; ++j) {
573                         if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
574                             break;
575                     }
576
577                     if (j==alloc->perm_cnt && alloc->perm_cnt < MAX_TURN_PERM) {
578                         char peer_info[PJ_INET6_ADDRSTRLEN];
579                         pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3);
580
581                         pj_sockaddr_cp(&alloc->perm[alloc->perm_cnt], &pa->sockaddr);
582                         ++alloc->perm_cnt;
583
584                         PJ_LOG(5,("", "Permission %s added to client %s, perm_cnt=%d", 
585                                       peer_info, client_info, alloc->perm_cnt));
586                     }
587
588                 }
589             }
590             resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
591         } else if (req->hdr.type == PJ_STUN_SEND_INDICATION) {
592             pj_stun_xor_peer_addr_attr *pa;
593             pj_stun_data_attr *da;
594
595             test_srv->turn_stat.rx_send_ind_cnt++;
596
597             pa = (pj_stun_xor_peer_addr_attr*)
598                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
599             da = (pj_stun_data_attr*)
600                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_DATA, 0);
601             if (pa && da) {
602                 unsigned j;
603                 char peer_info[PJ_INET6_ADDRSTRLEN];
604                 pj_ssize_t sent;
605
606                 pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3);
607
608                 for (j=0; j<alloc->perm_cnt; ++j) {
609                     if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
610                         break;
611                 }
612
613                 if (j==alloc->perm_cnt) {
614                     PJ_LOG(5,("", "SendIndication to %s is rejected (no permission)", 
615                                   peer_info, client_info, alloc->perm_cnt));
616                 } else {
617                     PJ_LOG(5,(THIS_FILE, "Relaying %d bytes data from client %s to peer %s, "
618                                          "perm_cnt=%d", 
619                               da->length, client_info, peer_info, alloc->perm_cnt));
620
621                     sent = da->length;
622                     pj_activesock_sendto(alloc->sock, &alloc->send_key,
623                                          da->data, &sent, 0,
624                                          &pa->sockaddr,
625                                          pj_sockaddr_get_len(&pa->sockaddr));
626                 }
627             } else {
628                 PJ_LOG(1,(THIS_FILE, "Invalid Send Indication from %s", client_info));
629             }
630         } else if (req->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) {
631             pj_stun_xor_peer_addr_attr *pa;
632             pj_stun_channel_number_attr *cna;
633             unsigned j, cn;
634
635             pa = (pj_stun_xor_peer_addr_attr*)
636                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
637             cna = (pj_stun_channel_number_attr*)
638                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_CHANNEL_NUMBER, 0);
639             cn = PJ_STUN_GET_CH_NB(cna->value);
640
641             resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
642
643             for (j=0; j<alloc->perm_cnt; ++j) {
644                 if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
645                     break;
646             }
647
648             if (i==alloc->perm_cnt) {
649                 if (alloc->perm_cnt==MAX_TURN_PERM) {
650                     pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp);
651                     goto send_pkt;
652                 }
653                 pj_sockaddr_cp(&alloc->perm[i], &pa->sockaddr);
654                 ++alloc->perm_cnt;
655             }
656             alloc->chnum[i] = cn;
657
658             resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
659
660         } else if (PJ_STUN_IS_REQUEST(req->hdr.type)) {
661             pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp);
662         }
663     }
664
665
666 send_pkt:
667     if (resp) {
668         status = pj_stun_msg_encode(resp, (pj_uint8_t*)data, MAX_STUN_PKT, 
669                                     0, &auth_key, &size);
670         if (status != PJ_SUCCESS)
671             goto on_return;
672
673         len = size;
674         status = pj_activesock_sendto(asock, &test_srv->send_key, data, &len,
675                                       0, src_addr, addr_len);
676     }
677
678 on_return:
679     pj_pool_release(pool);
680     return PJ_TRUE;
681 }
682
683 /* On received data from peer */
684 static pj_bool_t alloc_on_data_recvfrom(pj_activesock_t *asock,
685                                        void *data,
686                                        pj_size_t size,
687                                        const pj_sockaddr_t *src_addr,
688                                        int addr_len,
689                                        pj_status_t status)
690 {
691     turn_allocation *alloc;
692     pj_stun_xor_peer_addr_attr *pa;
693     pj_stun_data_attr *da;
694     char peer_info[PJ_INET6_ADDRSTRLEN+10];
695     char client_info[PJ_INET6_ADDRSTRLEN+10];
696     pj_uint8_t buffer[1500];
697     pj_ssize_t sent;
698     unsigned i;
699
700     if (status != PJ_SUCCESS)
701         return PJ_TRUE;
702
703     alloc = (turn_allocation*) pj_activesock_get_user_data(asock);
704
705     pj_sockaddr_print(&alloc->client_addr, client_info, sizeof(client_info), 3);
706     pj_sockaddr_print(src_addr, peer_info, sizeof(peer_info), 3);
707
708     /* Check that this peer has a permission */
709     for (i=0; i<alloc->perm_cnt; ++i) {
710         if (pj_sockaddr_get_len(&alloc->perm[i]) == (unsigned)addr_len &&
711             pj_memcmp(pj_sockaddr_get_addr(&alloc->perm[i]),
712                       pj_sockaddr_get_addr(src_addr),
713                       addr_len) == 0)
714         {
715             break;
716         }
717     }
718     if (i==alloc->perm_cnt) {
719         PJ_LOG(5,("", "Client %s received %d bytes unauthorized data from peer %s", 
720                       client_info, size, peer_info));
721         if (alloc->perm_cnt == 0)
722             PJ_LOG(5,("", "Client %s has no permission", client_info));
723         return PJ_TRUE;
724     }
725
726     /* Format a Data indication */
727     pa = (pj_stun_xor_peer_addr_attr*)
728          pj_stun_msg_find_attr(alloc->data_ind, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
729     da = (pj_stun_data_attr*)
730          pj_stun_msg_find_attr(alloc->data_ind, PJ_STUN_ATTR_DATA, 0);
731     pj_assert(pa && da);
732
733     pj_sockaddr_cp(&pa->sockaddr, src_addr);
734     da->data = (pj_uint8_t*)data;
735     da->length = size;
736
737     /* Encode Data indication */
738     status = pj_stun_msg_encode(alloc->data_ind, buffer, sizeof(buffer), 0,
739                                 NULL, &size);
740     if (status != PJ_SUCCESS)
741         return PJ_TRUE;
742
743     /* Send */
744     sent = size;
745     PJ_LOG(5,("", "Forwarding %d bytes data from peer %s to client %s", 
746                    sent, peer_info, client_info));
747
748     pj_activesock_sendto(alloc->test_srv->turn_sock, &alloc->send_key, buffer,
749                          &sent, 0, &alloc->client_addr,
750                          pj_sockaddr_get_len(&alloc->client_addr));
751
752     return PJ_TRUE;
753 }
754