~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjnath/src/pjturn-srv/server.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: server.c 4728 2014-02-04 10:13:56Z bennylp $ */
 
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
#define MAX_CLIENTS             32
 
24
#define MAX_PEERS_PER_CLIENT    8
 
25
//#define MAX_HANDLES           (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS)
 
26
#define MAX_HANDLES             PJ_IOQUEUE_MAX_HANDLES
 
27
#define MAX_TIMER               (MAX_HANDLES * 2)
 
28
#define MIN_PORT                49152
 
29
#define MAX_PORT                65535
 
30
#define MAX_LISTENERS           16
 
31
#define MAX_THREADS             2
 
32
#define MAX_NET_EVENTS          1000
 
33
 
 
34
/* Prototypes */
 
35
static int server_thread_proc(void *arg);
 
36
static pj_status_t on_tx_stun_msg( pj_stun_session *sess,
 
37
                                   void *token,
 
38
                                   const void *pkt,
 
39
                                   pj_size_t pkt_size,
 
40
                                   const pj_sockaddr_t *dst_addr,
 
41
                                   unsigned addr_len);
 
42
static pj_status_t on_rx_stun_request(pj_stun_session *sess,
 
43
                                      const pj_uint8_t *pkt,
 
44
                                      unsigned pkt_len,
 
45
                                      const pj_stun_rx_data *rdata,
 
46
                                      void *user_data,
 
47
                                      const pj_sockaddr_t *src_addr,
 
48
                                      unsigned src_addr_len);
 
49
 
 
50
struct saved_cred
 
51
{
 
52
    pj_str_t realm;
 
53
    pj_str_t username;
 
54
    pj_str_t nonce;
 
55
    int      data_type;
 
56
    pj_str_t data;
 
57
};
 
58
 
 
59
 
 
60
/*
 
61
 * Get transport type name, normally for logging purpose only.
 
62
 */
 
63
PJ_DEF(const char*) pj_turn_tp_type_name(int tp_type)
 
64
{
 
65
    /* Must be 3 characters long! */
 
66
    if (tp_type == PJ_TURN_TP_UDP) {
 
67
        return "UDP";
 
68
    } else if (tp_type == PJ_TURN_TP_TCP) {
 
69
        return "TCP";
 
70
    } else {
 
71
        pj_assert(!"Unsupported transport");
 
72
        return "???";
 
73
    }
 
74
}
 
75
 
 
76
/*
 
77
 * Create server.
 
78
 */
 
79
PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf,
 
80
                                       pj_turn_srv **p_srv)
 
81
{
 
82
    pj_pool_t *pool;
 
83
    pj_stun_session_cb sess_cb;
 
84
    pj_turn_srv *srv;
 
85
    unsigned i;
 
86
    pj_status_t status;
 
87
 
 
88
    PJ_ASSERT_RETURN(pf && p_srv, PJ_EINVAL);
 
89
 
 
90
    /* Create server and init core settings */
 
91
    pool = pj_pool_create(pf, "srv%p", 1000, 1000, NULL);
 
92
    srv = PJ_POOL_ZALLOC_T(pool, pj_turn_srv);
 
93
    srv->obj_name = pool->obj_name;
 
94
    srv->core.pf = pf;
 
95
    srv->core.pool = pool;
 
96
    srv->core.tls_key = srv->core.tls_data = -1;
 
97
 
 
98
    /* Create ioqueue */
 
99
    status = pj_ioqueue_create(pool, MAX_HANDLES, &srv->core.ioqueue);
 
100
    if (status != PJ_SUCCESS)
 
101
        goto on_error;
 
102
 
 
103
    /* Server mutex */
 
104
    status = pj_lock_create_recursive_mutex(pool, srv->obj_name,
 
105
                                            &srv->core.lock);
 
106
    if (status != PJ_SUCCESS)
 
107
        goto on_error;
 
108
 
 
109
    /* Allocate TLS */
 
110
    status = pj_thread_local_alloc(&srv->core.tls_key);
 
111
    if (status != PJ_SUCCESS)
 
112
        goto on_error;
 
113
 
 
114
    status = pj_thread_local_alloc(&srv->core.tls_data);
 
115
    if (status != PJ_SUCCESS)
 
116
        goto on_error;
 
117
 
 
118
    /* Create timer heap */
 
119
    status = pj_timer_heap_create(pool, MAX_TIMER, &srv->core.timer_heap);
 
120
    if (status != PJ_SUCCESS)
 
121
        goto on_error;
 
122
 
 
123
    /* Configure lock for the timer heap */
 
124
    pj_timer_heap_set_lock(srv->core.timer_heap, srv->core.lock, PJ_FALSE);
 
125
 
 
126
    /* Array of listeners */
 
127
    srv->core.listener = (pj_turn_listener**)
 
128
                         pj_pool_calloc(pool, MAX_LISTENERS,
 
129
                                        sizeof(srv->core.listener[0]));
 
130
 
 
131
    /* Create hash tables */
 
132
    srv->tables.alloc = pj_hash_create(pool, MAX_CLIENTS);
 
133
    srv->tables.res = pj_hash_create(pool, MAX_CLIENTS);
 
134
 
 
135
    /* Init ports settings */
 
136
    srv->ports.min_udp = srv->ports.next_udp = MIN_PORT;
 
137
    srv->ports.max_udp = MAX_PORT;
 
138
    srv->ports.min_tcp = srv->ports.next_tcp = MIN_PORT;
 
139
    srv->ports.max_tcp = MAX_PORT;
 
140
 
 
141
    /* Init STUN config */
 
142
    pj_stun_config_init(&srv->core.stun_cfg, pf, 0, srv->core.ioqueue,
 
143
                        srv->core.timer_heap);
 
144
 
 
145
    /* Init STUN credential */
 
146
    srv->core.cred.type = PJ_STUN_AUTH_CRED_DYNAMIC;
 
147
    srv->core.cred.data.dyn_cred.user_data = srv;
 
148
    srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth;
 
149
    srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password;
 
150
    srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce;
 
151
 
 
152
    /* Create STUN session to handle new allocation */
 
153
    pj_bzero(&sess_cb, sizeof(sess_cb));
 
154
    sess_cb.on_rx_request = &on_rx_stun_request;
 
155
    sess_cb.on_send_msg = &on_tx_stun_msg;
 
156
 
 
157
    status = pj_stun_session_create(&srv->core.stun_cfg, srv->obj_name,
 
158
                                    &sess_cb, PJ_FALSE, NULL,
 
159
                                    &srv->core.stun_sess);
 
160
    if (status != PJ_SUCCESS) {
 
161
        goto on_error;
 
162
    }
 
163
 
 
164
    pj_stun_session_set_user_data(srv->core.stun_sess, srv);
 
165
    pj_stun_session_set_credential(srv->core.stun_sess, PJ_STUN_AUTH_LONG_TERM,
 
166
                                   &srv->core.cred);
 
167
 
 
168
 
 
169
    /* Array of worker threads */
 
170
    srv->core.thread_cnt = MAX_THREADS;
 
171
    srv->core.thread = (pj_thread_t**)
 
172
                       pj_pool_calloc(pool, srv->core.thread_cnt,
 
173
                                      sizeof(pj_thread_t*));
 
174
 
 
175
    /* Start the worker threads */
 
176
    for (i=0; i<srv->core.thread_cnt; ++i) {
 
177
        status = pj_thread_create(pool, srv->obj_name, &server_thread_proc,
 
178
                                  srv, 0, 0, &srv->core.thread[i]);
 
179
        if (status != PJ_SUCCESS)
 
180
            goto on_error;
 
181
    }
 
182
 
 
183
    /* We're done. Application should add listeners now */
 
184
    PJ_LOG(4,(srv->obj_name, "TURN server v%s is running",
 
185
              pj_get_version()));
 
186
 
 
187
    *p_srv = srv;
 
188
    return PJ_SUCCESS;
 
189
 
 
190
on_error:
 
191
    pj_turn_srv_destroy(srv);
 
192
    return status;
 
193
}
 
194
 
 
195
 
 
196
/*
 
197
 * Handle timer and network events
 
198
 */
 
199
static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout)
 
200
{
 
201
    /* timeout is 'out' var. This just to make compiler happy. */
 
202
    pj_time_val timeout = { 0, 0};
 
203
    unsigned net_event_count = 0;
 
204
    int c;
 
205
 
 
206
    /* Poll the timer. The timer heap has its own mutex for better
 
207
     * granularity, so we don't need to lock the server.
 
208
     */
 
209
    timeout.sec = timeout.msec = 0;
 
210
    c = pj_timer_heap_poll( srv->core.timer_heap, &timeout );
 
211
 
 
212
    /* timer_heap_poll should never ever returns negative value, or otherwise
 
213
     * ioqueue_poll() will block forever!
 
214
     */
 
215
    pj_assert(timeout.sec >= 0 && timeout.msec >= 0);
 
216
    if (timeout.msec >= 1000) timeout.msec = 999;
 
217
 
 
218
    /* If caller specifies maximum time to wait, then compare the value with
 
219
     * the timeout to wait from timer, and use the minimum value.
 
220
     */
 
221
    if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) {
 
222
        timeout = *max_timeout;
 
223
    }
 
224
 
 
225
    /* Poll ioqueue.
 
226
     * Repeat polling the ioqueue while we have immediate events, because
 
227
     * timer heap may process more than one events, so if we only process
 
228
     * one network events at a time (such as when IOCP backend is used),
 
229
     * the ioqueue may have trouble keeping up with the request rate.
 
230
     *
 
231
     * For example, for each send() request, one network event will be
 
232
     *   reported by ioqueue for the send() completion. If we don't poll
 
233
     *   the ioqueue often enough, the send() completion will not be
 
234
     *   reported in timely manner.
 
235
     */
 
236
    do {
 
237
        c = pj_ioqueue_poll( srv->core.ioqueue, &timeout);
 
238
        if (c < 0) {
 
239
            pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
 
240
            return;
 
241
        } else if (c == 0) {
 
242
            break;
 
243
        } else {
 
244
            net_event_count += c;
 
245
            timeout.sec = timeout.msec = 0;
 
246
        }
 
247
    } while (c > 0 && net_event_count < MAX_NET_EVENTS);
 
248
 
 
249
}
 
250
 
 
251
/*
 
252
 * Server worker thread proc.
 
253
 */
 
254
static int server_thread_proc(void *arg)
 
255
{
 
256
    pj_turn_srv *srv = (pj_turn_srv*)arg;
 
257
 
 
258
    while (!srv->core.quit) {
 
259
        pj_time_val timeout_max = {0, 100};
 
260
        srv_handle_events(srv, &timeout_max);
 
261
    }
 
262
 
 
263
    return 0;
 
264
}
 
265
 
 
266
/*
 
267
 * Destroy the server.
 
268
 */
 
269
PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv)
 
270
{
 
271
    pj_hash_iterator_t itbuf, *it;
 
272
    unsigned i;
 
273
 
 
274
    /* Stop all worker threads */
 
275
    srv->core.quit = PJ_TRUE;
 
276
    for (i=0; i<srv->core.thread_cnt; ++i) {
 
277
        if (srv->core.thread[i]) {
 
278
            pj_thread_join(srv->core.thread[i]);
 
279
            pj_thread_destroy(srv->core.thread[i]);
 
280
            srv->core.thread[i] = NULL;
 
281
        }
 
282
    }
 
283
 
 
284
    /* Destroy all allocations FIRST */
 
285
    if (srv->tables.alloc) {
 
286
        it = pj_hash_first(srv->tables.alloc, &itbuf);
 
287
        while (it != NULL) {
 
288
            pj_turn_allocation *alloc = (pj_turn_allocation*)
 
289
                                        pj_hash_this(srv->tables.alloc, it);
 
290
            pj_hash_iterator_t *next = pj_hash_next(srv->tables.alloc, it);
 
291
            pj_turn_allocation_destroy(alloc);
 
292
            it = next;
 
293
        }
 
294
    }
 
295
 
 
296
    /* Destroy all listeners. */
 
297
    for (i=0; i<srv->core.lis_cnt; ++i) {
 
298
        if (srv->core.listener[i]) {
 
299
            pj_turn_listener_destroy(srv->core.listener[i]);
 
300
            srv->core.listener[i] = NULL;
 
301
        }
 
302
    }
 
303
 
 
304
    /* Destroy STUN session */
 
305
    if (srv->core.stun_sess) {
 
306
        pj_stun_session_destroy(srv->core.stun_sess);
 
307
        srv->core.stun_sess = NULL;
 
308
    }
 
309
 
 
310
    /* Destroy hash tables (well, sort of) */
 
311
    if (srv->tables.alloc) {
 
312
        srv->tables.alloc = NULL;
 
313
        srv->tables.res = NULL;
 
314
    }
 
315
 
 
316
    /* Destroy timer heap */
 
317
    if (srv->core.timer_heap) {
 
318
        pj_timer_heap_destroy(srv->core.timer_heap);
 
319
        srv->core.timer_heap = NULL;
 
320
    }
 
321
 
 
322
    /* Destroy ioqueue */
 
323
    if (srv->core.ioqueue) {
 
324
        pj_ioqueue_destroy(srv->core.ioqueue);
 
325
        srv->core.ioqueue = NULL;
 
326
    }
 
327
 
 
328
    /* Destroy thread local IDs */
 
329
    if (srv->core.tls_key != -1) {
 
330
        pj_thread_local_free(srv->core.tls_key);
 
331
        srv->core.tls_key = -1;
 
332
    }
 
333
    if (srv->core.tls_data != -1) {
 
334
        pj_thread_local_free(srv->core.tls_data);
 
335
        srv->core.tls_data = -1;
 
336
    }
 
337
 
 
338
    /* Destroy server lock */
 
339
    if (srv->core.lock) {
 
340
        pj_lock_destroy(srv->core.lock);
 
341
        srv->core.lock = NULL;
 
342
    }
 
343
 
 
344
    /* Release pool */
 
345
    if (srv->core.pool) {
 
346
        pj_pool_t *pool = srv->core.pool;
 
347
        srv->core.pool = NULL;
 
348
        pj_pool_release(pool);
 
349
    }
 
350
 
 
351
    /* Done */
 
352
    return PJ_SUCCESS;
 
353
}
 
354
 
 
355
 
 
356
/*
 
357
 * Add listener.
 
358
 */
 
359
PJ_DEF(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv,
 
360
                                             pj_turn_listener *lis)
 
361
{
 
362
    unsigned index;
 
363
 
 
364
    PJ_ASSERT_RETURN(srv && lis, PJ_EINVAL);
 
365
    PJ_ASSERT_RETURN(srv->core.lis_cnt < MAX_LISTENERS, PJ_ETOOMANY);
 
366
 
 
367
    /* Add to array */
 
368
    index = srv->core.lis_cnt;
 
369
    srv->core.listener[index] = lis;
 
370
    lis->server = srv;
 
371
    lis->id = index;
 
372
    srv->core.lis_cnt++;
 
373
 
 
374
    PJ_LOG(4,(srv->obj_name, "Listener %s/%s added at index %d",
 
375
              lis->obj_name, lis->info, lis->id));
 
376
 
 
377
    return PJ_SUCCESS;
 
378
}
 
379
 
 
380
 
 
381
/*
 
382
 * Destroy listener.
 
383
 */
 
384
PJ_DEF(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener)
 
385
{
 
386
    pj_turn_srv *srv = listener->server;
 
387
    unsigned i;
 
388
 
 
389
    /* Remove from our listener list */
 
390
    pj_lock_acquire(srv->core.lock);
 
391
    for (i=0; i<srv->core.lis_cnt; ++i) {
 
392
        if (srv->core.listener[i] == listener) {
 
393
            srv->core.listener[i] = NULL;
 
394
            srv->core.lis_cnt--;
 
395
            listener->id = PJ_TURN_INVALID_LIS_ID;
 
396
            break;
 
397
        }
 
398
    }
 
399
    pj_lock_release(srv->core.lock);
 
400
 
 
401
    /* Destroy */
 
402
    return listener->destroy(listener);
 
403
}
 
404
 
 
405
 
 
406
/**
 
407
 * Add a reference to a transport.
 
408
 */
 
409
PJ_DEF(void) pj_turn_transport_add_ref( pj_turn_transport *transport,
 
410
                                        pj_turn_allocation *alloc)
 
411
{
 
412
    transport->add_ref(transport, alloc);
 
413
}
 
414
 
 
415
 
 
416
/**
 
417
 * Decrement transport reference counter.
 
418
 */
 
419
PJ_DEF(void) pj_turn_transport_dec_ref( pj_turn_transport *transport,
 
420
                                        pj_turn_allocation *alloc)
 
421
{
 
422
    transport->dec_ref(transport, alloc);
 
423
}
 
424
 
 
425
 
 
426
/*
 
427
 * Register an allocation to the hash tables.
 
428
 */
 
429
PJ_DEF(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv,
 
430
                                                    pj_turn_allocation *alloc)
 
431
{
 
432
    /* Add to hash tables */
 
433
    pj_lock_acquire(srv->core.lock);
 
434
    pj_hash_set(alloc->pool, srv->tables.alloc,
 
435
                &alloc->hkey, sizeof(alloc->hkey), 0, alloc);
 
436
    pj_hash_set(alloc->pool, srv->tables.res,
 
437
                &alloc->relay.hkey, sizeof(alloc->relay.hkey), 0,
 
438
                &alloc->relay);
 
439
    pj_lock_release(srv->core.lock);
 
440
 
 
441
    return PJ_SUCCESS;
 
442
}
 
443
 
 
444
 
 
445
/*
 
446
 * Unregister an allocation from the hash tables.
 
447
 */
 
448
PJ_DEF(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv,
 
449
                                                     pj_turn_allocation *alloc)
 
450
{
 
451
    /* Unregister from hash tables */
 
452
    pj_lock_acquire(srv->core.lock);
 
453
    pj_hash_set(alloc->pool, srv->tables.alloc,
 
454
                &alloc->hkey, sizeof(alloc->hkey), 0, NULL);
 
455
    pj_hash_set(alloc->pool, srv->tables.res,
 
456
                &alloc->relay.hkey, sizeof(alloc->relay.hkey), 0, NULL);
 
457
    pj_lock_release(srv->core.lock);
 
458
 
 
459
    return PJ_SUCCESS;
 
460
}
 
461
 
 
462
 
 
463
/* Callback from our own STUN session whenever it needs to send
 
464
 * outgoing STUN packet.
 
465
 */
 
466
static pj_status_t on_tx_stun_msg( pj_stun_session *sess,
 
467
                                   void *token,
 
468
                                   const void *pdu,
 
469
                                   pj_size_t pdu_size,
 
470
                                   const pj_sockaddr_t *dst_addr,
 
471
                                   unsigned addr_len)
 
472
{
 
473
    pj_turn_transport *transport = (pj_turn_transport*) token;
 
474
 
 
475
    PJ_ASSERT_RETURN(transport!=NULL, PJ_EINVALIDOP);
 
476
 
 
477
    PJ_UNUSED_ARG(sess);
 
478
 
 
479
    return transport->sendto(transport, pdu, pdu_size, 0,
 
480
                             dst_addr, addr_len);
 
481
}
 
482
 
 
483
 
 
484
/* Respond to STUN request */
 
485
static pj_status_t stun_respond(pj_stun_session *sess,
 
486
                                pj_turn_transport *transport,
 
487
                                const pj_stun_rx_data *rdata,
 
488
                                unsigned code,
 
489
                                const char *errmsg,
 
490
                                pj_bool_t cache,
 
491
                                const pj_sockaddr_t *dst_addr,
 
492
                                unsigned addr_len)
 
493
{
 
494
    pj_status_t status;
 
495
    pj_str_t reason;
 
496
    pj_stun_tx_data *tdata;
 
497
 
 
498
    /* Create response */
 
499
    status = pj_stun_session_create_res(sess, rdata, code,
 
500
                                        (errmsg?pj_cstr(&reason,errmsg):NULL),
 
501
                                        &tdata);
 
502
    if (status != PJ_SUCCESS)
 
503
        return status;
 
504
 
 
505
    /* Send the response */
 
506
    return pj_stun_session_send_msg(sess, transport, cache, PJ_FALSE,
 
507
                                    dst_addr,  addr_len, tdata);
 
508
}
 
509
 
 
510
 
 
511
/* Callback from our own STUN session when incoming request arrives.
 
512
 * This function is triggered by pj_stun_session_on_rx_pkt() call in
 
513
 * pj_turn_srv_on_rx_pkt() function below.
 
514
 */
 
515
static pj_status_t on_rx_stun_request(pj_stun_session *sess,
 
516
                                      const pj_uint8_t *pdu,
 
517
                                      unsigned pdu_len,
 
518
                                      const pj_stun_rx_data *rdata,
 
519
                                      void *token,
 
520
                                      const pj_sockaddr_t *src_addr,
 
521
                                      unsigned src_addr_len)
 
522
{
 
523
    pj_turn_transport *transport;
 
524
    const pj_stun_msg *msg = rdata->msg;
 
525
    pj_turn_allocation *alloc;
 
526
    pj_status_t status;
 
527
 
 
528
    PJ_UNUSED_ARG(pdu);
 
529
    PJ_UNUSED_ARG(pdu_len);
 
530
 
 
531
    transport = (pj_turn_transport*) token;
 
532
 
 
533
    /* Respond any requests other than ALLOCATE with 437 response */
 
534
    if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
 
535
        stun_respond(sess, transport, rdata, PJ_STUN_SC_ALLOCATION_MISMATCH,
 
536
                     NULL, PJ_FALSE, src_addr, src_addr_len);
 
537
        return PJ_SUCCESS;
 
538
    }
 
539
 
 
540
    /* Create new allocation. The relay resource will be allocated
 
541
     * in this function.
 
542
     */
 
543
    status = pj_turn_allocation_create(transport, src_addr, src_addr_len,
 
544
                                       rdata, sess, &alloc);
 
545
    if (status != PJ_SUCCESS) {
 
546
        /* STUN response has been sent, no need to reply here */
 
547
        return PJ_SUCCESS;
 
548
    }
 
549
 
 
550
    /* Done. */
 
551
    return PJ_SUCCESS;
 
552
}
 
553
 
 
554
/* Handle STUN Binding request */
 
555
static void handle_binding_request(pj_turn_pkt *pkt,
 
556
                                   unsigned options)
 
557
{
 
558
    pj_stun_msg *request, *response;
 
559
    pj_uint8_t pdu[200];
 
560
    pj_size_t len;
 
561
    pj_status_t status;
 
562
 
 
563
    /* Decode request */
 
564
    status = pj_stun_msg_decode(pkt->pool, pkt->pkt, pkt->len, options,
 
565
                                &request, NULL, NULL);
 
566
    if (status != PJ_SUCCESS)
 
567
        return;
 
568
 
 
569
    /* Create response */
 
570
    status = pj_stun_msg_create_response(pkt->pool, request, 0, NULL,
 
571
                                         &response);
 
572
    if (status != PJ_SUCCESS)
 
573
        return;
 
574
 
 
575
    /* Add XOR-MAPPED-ADDRESS */
 
576
    pj_stun_msg_add_sockaddr_attr(pkt->pool, response,
 
577
                                  PJ_STUN_ATTR_XOR_MAPPED_ADDR,
 
578
                                  PJ_TRUE,
 
579
                                  &pkt->src.clt_addr,
 
580
                                  pkt->src_addr_len);
 
581
 
 
582
    /* Encode */
 
583
    status = pj_stun_msg_encode(response, pdu, sizeof(pdu), 0, NULL, &len);
 
584
    if (status != PJ_SUCCESS)
 
585
        return;
 
586
 
 
587
    /* Send response */
 
588
    pkt->transport->sendto(pkt->transport, pdu, len, 0,
 
589
                           &pkt->src.clt_addr, pkt->src_addr_len);
 
590
}
 
591
 
 
592
/*
 
593
 * This callback is called by UDP listener on incoming packet. This is
 
594
 * the first entry for incoming packet (from client) to the server. From
 
595
 * here, the packet may be handed over to an allocation if an allocation
 
596
 * is found for the client address, or handed over to owned STUN session
 
597
 * if an allocation is not found.
 
598
 */
 
599
PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv,
 
600
                                   pj_turn_pkt *pkt)
 
601
{
 
602
    pj_turn_allocation *alloc;
 
603
 
 
604
    /* Get TURN allocation from the source address */
 
605
    pj_lock_acquire(srv->core.lock);
 
606
    alloc = (pj_turn_allocation*)
 
607
            pj_hash_get(srv->tables.alloc, &pkt->src, sizeof(pkt->src), NULL);
 
608
    pj_lock_release(srv->core.lock);
 
609
 
 
610
    /* If allocation is found, just hand over the packet to the
 
611
     * allocation.
 
612
     */
 
613
    if (alloc) {
 
614
        pj_turn_allocation_on_rx_client_pkt(alloc, pkt);
 
615
    } else {
 
616
        /* Otherwise this is a new client */
 
617
        unsigned options;
 
618
        pj_size_t parsed_len;
 
619
        pj_status_t status;
 
620
 
 
621
        /* Check that this is a STUN message */
 
622
        options = PJ_STUN_CHECK_PACKET | PJ_STUN_NO_FINGERPRINT_CHECK;
 
623
        if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP)
 
624
            options |= PJ_STUN_IS_DATAGRAM;
 
625
 
 
626
        status = pj_stun_msg_check(pkt->pkt, pkt->len, options);
 
627
        if (status != PJ_SUCCESS) {
 
628
            /* If the first byte are not STUN, drop the packet. First byte
 
629
             * of STUN message is always 0x00 or 0x01. Otherwise wait for
 
630
             * more data as the data might have come from TCP.
 
631
             *
 
632
             * Also drop packet if it's unreasonably too big, as this might
 
633
             * indicate invalid data that's building up in the buffer.
 
634
             *
 
635
             * Or if packet is a datagram.
 
636
             */
 
637
            if ((*pkt->pkt != 0x00 && *pkt->pkt != 0x01) ||
 
638
                pkt->len > 1600 ||
 
639
                (options & PJ_STUN_IS_DATAGRAM))
 
640
            {
 
641
                char errmsg[PJ_ERR_MSG_SIZE];
 
642
                char ip[PJ_INET6_ADDRSTRLEN+10];
 
643
 
 
644
                pkt->len = 0;
 
645
 
 
646
                pj_strerror(status, errmsg, sizeof(errmsg));
 
647
                PJ_LOG(5,(srv->obj_name,
 
648
                          "Non-STUN packet from %s is dropped: %s",
 
649
                          pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3),
 
650
                          errmsg));
 
651
            }
 
652
            return;
 
653
        }
 
654
 
 
655
        /* Special handling for Binding Request. We won't give it to the
 
656
         * STUN session since this request is not authenticated.
 
657
         */
 
658
        if (pkt->pkt[1] == 1) {
 
659
            handle_binding_request(pkt, options);
 
660
            return;
 
661
        }
 
662
 
 
663
        /* Hand over processing to STUN session. This will trigger
 
664
         * on_rx_stun_request() callback to be called if the STUN
 
665
         * message is a request.
 
666
         */
 
667
        options &= ~PJ_STUN_CHECK_PACKET;
 
668
        parsed_len = 0;
 
669
        status = pj_stun_session_on_rx_pkt(srv->core.stun_sess, pkt->pkt,
 
670
                                           pkt->len, options, pkt->transport,
 
671
                                           &parsed_len, &pkt->src.clt_addr,
 
672
                                           pkt->src_addr_len);
 
673
        if (status != PJ_SUCCESS) {
 
674
            char errmsg[PJ_ERR_MSG_SIZE];
 
675
            char ip[PJ_INET6_ADDRSTRLEN+10];
 
676
 
 
677
            pj_strerror(status, errmsg, sizeof(errmsg));
 
678
            PJ_LOG(5,(srv->obj_name,
 
679
                      "Error processing STUN packet from %s: %s",
 
680
                      pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3),
 
681
                      errmsg));
 
682
        }
 
683
 
 
684
        if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP) {
 
685
            pkt->len = 0;
 
686
        } else if (parsed_len > 0) {
 
687
            if (parsed_len == pkt->len) {
 
688
                pkt->len = 0;
 
689
            } else {
 
690
                pj_memmove(pkt->pkt, pkt->pkt+parsed_len,
 
691
                           pkt->len - parsed_len);
 
692
                pkt->len -= parsed_len;
 
693
            }
 
694
        }
 
695
    }
 
696
}
 
697
 
 
698