blob: 0b07180d080e83dcdb60b8ba2e17ba4ff3c8290e [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $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
27static 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);
33static 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);
39static 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
46pj_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
205void 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
239static 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
276send_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
286on_return:
287 pj_pool_release(pool);
288 return PJ_TRUE;
289}
290
291
292static 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
332static 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
666send_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
678on_return:
679 pj_pool_release(pool);
680 return PJ_TRUE;
681}
682
683/* On received data from peer */
684static 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 = (unsigned)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