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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjnath/src/pjnath-test/turn_sock_test.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: turn_sock_test.c 3553 2011-05-05 06:14:19Z nanang $ */
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 "test.h"
21
 
#include "server.h"
22
 
 
23
 
#define SRV_DOMAIN      "pjsip.lab.domain"
24
 
#define KA_INTERVAL     50
25
 
 
26
 
struct test_result
27
 
{
28
 
    unsigned    state_called;
29
 
    unsigned    rx_data_cnt;
30
 
};
31
 
 
32
 
struct test_session
33
 
{
34
 
    pj_pool_t           *pool;
35
 
    pj_stun_config      *stun_cfg;
36
 
    pj_turn_sock        *turn_sock;
37
 
    pj_dns_resolver     *resolver;
38
 
    test_server         *test_srv;
39
 
 
40
 
    pj_bool_t            destroy_called;
41
 
    int                  destroy_on_state;
42
 
    struct test_result   result;
43
 
};
44
 
 
45
 
struct test_session_cfg
46
 
{
47
 
    struct {
48
 
        pj_bool_t       enable_dns_srv;
49
 
        int             destroy_on_state;
50
 
    } client;
51
 
 
52
 
    struct {
53
 
        pj_uint32_t     flags;
54
 
        pj_bool_t       respond_allocate;
55
 
        pj_bool_t       respond_refresh;
56
 
    } srv;
57
 
};
58
 
 
59
 
static void turn_on_rx_data(pj_turn_sock *turn_sock,
60
 
                            void *pkt,
61
 
                            unsigned pkt_len,
62
 
                            const pj_sockaddr_t *peer_addr,
63
 
                            unsigned addr_len);
64
 
static void turn_on_state(pj_turn_sock *turn_sock, 
65
 
                          pj_turn_state_t old_state,
66
 
                          pj_turn_state_t new_state);
67
 
 
68
 
static void destroy_session(struct test_session *sess)
69
 
{
70
 
    if (sess->resolver) {
71
 
        pj_dns_resolver_destroy(sess->resolver, PJ_TRUE);
72
 
        sess->resolver = NULL;
73
 
    }
74
 
 
75
 
    if (sess->turn_sock) {
76
 
        if (!sess->destroy_called) {
77
 
            sess->destroy_called = PJ_TRUE;
78
 
            pj_turn_sock_destroy(sess->turn_sock);
79
 
        }
80
 
        sess->turn_sock = NULL;
81
 
    }
82
 
 
83
 
    if (sess->test_srv) {
84
 
        destroy_test_server(sess->test_srv);
85
 
        sess->test_srv = NULL;
86
 
    }
87
 
 
88
 
    if (sess->pool) {
89
 
        pj_pool_release(sess->pool);
90
 
    }
91
 
}
92
 
 
93
 
 
94
 
 
95
 
static int create_test_session(pj_stun_config  *stun_cfg,
96
 
                               const struct test_session_cfg *cfg,
97
 
                               struct test_session **p_sess)
98
 
{
99
 
    struct test_session *sess;
100
 
    pj_pool_t *pool;
101
 
    pj_turn_sock_cb turn_sock_cb;
102
 
    pj_turn_alloc_param alloc_param;
103
 
    pj_stun_auth_cred cred;
104
 
    pj_status_t status;
105
 
 
106
 
    /* Create client */
107
 
    pool = pj_pool_create(mem, "turnclient", 512, 512, NULL);
108
 
    sess = PJ_POOL_ZALLOC_T(pool, struct test_session);
109
 
    sess->pool = pool;
110
 
    sess->stun_cfg = stun_cfg;
111
 
    sess->destroy_on_state = cfg->client.destroy_on_state;
112
 
 
113
 
    pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb));
114
 
    turn_sock_cb.on_rx_data = &turn_on_rx_data;
115
 
    turn_sock_cb.on_state = &turn_on_state;
116
 
    status = pj_turn_sock_create(sess->stun_cfg, pj_AF_INET(), PJ_TURN_TP_UDP,
117
 
                                 &turn_sock_cb, 0, sess, &sess->turn_sock);
118
 
    if (status != PJ_SUCCESS) {
119
 
        destroy_session(sess);
120
 
        return -20;
121
 
    }
122
 
 
123
 
    /* Create test server */
124
 
    status = create_test_server(sess->stun_cfg, cfg->srv.flags,
125
 
                                SRV_DOMAIN, &sess->test_srv);
126
 
    if (status != PJ_SUCCESS) {
127
 
        destroy_session(sess);
128
 
        return -30;
129
 
    }
130
 
 
131
 
    sess->test_srv->turn_respond_allocate = cfg->srv.respond_allocate;
132
 
    sess->test_srv->turn_respond_refresh = cfg->srv.respond_refresh;
133
 
 
134
 
    /* Create client resolver */
135
 
    status = pj_dns_resolver_create(mem, "resolver", 0, sess->stun_cfg->timer_heap,
136
 
                                    sess->stun_cfg->ioqueue, &sess->resolver);
137
 
    if (status != PJ_SUCCESS) {
138
 
        destroy_session(sess);
139
 
        return -40;
140
 
 
141
 
    } else {
142
 
        pj_str_t dns_srv = pj_str("127.0.0.1");
143
 
        pj_uint16_t dns_srv_port = (pj_uint16_t) DNS_SERVER_PORT;
144
 
        status = pj_dns_resolver_set_ns(sess->resolver, 1, &dns_srv, &dns_srv_port);
145
 
 
146
 
        if (status != PJ_SUCCESS) {
147
 
            destroy_session(sess);
148
 
            return -50;
149
 
        }
150
 
    }
151
 
 
152
 
    /* Init TURN credential */
153
 
    pj_bzero(&cred, sizeof(cred));
154
 
    cred.type = PJ_STUN_AUTH_CRED_STATIC;
155
 
    cred.data.static_cred.realm = pj_str(SRV_DOMAIN);
156
 
    cred.data.static_cred.username = pj_str(TURN_USERNAME);
157
 
    cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
158
 
    cred.data.static_cred.data = pj_str(TURN_PASSWD);
159
 
 
160
 
    /* Init TURN allocate parameter */
161
 
    pj_turn_alloc_param_default(&alloc_param);
162
 
    alloc_param.ka_interval = KA_INTERVAL;
163
 
 
164
 
    /* Start the client */
165
 
    if (cfg->client.enable_dns_srv) {
166
 
        /* Use DNS SRV to resolve server, may fallback to DNS A */
167
 
        pj_str_t domain = pj_str(SRV_DOMAIN);
168
 
        status = pj_turn_sock_alloc(sess->turn_sock, &domain, TURN_SERVER_PORT,
169
 
                                    sess->resolver, &cred, &alloc_param);
170
 
 
171
 
    } else {
172
 
        /* Explicitly specify server address */
173
 
        pj_str_t host = pj_str("127.0.0.1");
174
 
        status = pj_turn_sock_alloc(sess->turn_sock, &host, TURN_SERVER_PORT,
175
 
                                    NULL, &cred, &alloc_param);
176
 
 
177
 
    }
178
 
 
179
 
    if (status != PJ_SUCCESS) {
180
 
        if (cfg->client.destroy_on_state >= PJ_TURN_STATE_READY) {
181
 
            destroy_session(sess);
182
 
            return -70;
183
 
        }
184
 
    }
185
 
 
186
 
    *p_sess = sess;
187
 
    return 0;
188
 
}
189
 
 
190
 
 
191
 
static void turn_on_rx_data(pj_turn_sock *turn_sock,
192
 
                            void *pkt,
193
 
                            unsigned pkt_len,
194
 
                            const pj_sockaddr_t *peer_addr,
195
 
                            unsigned addr_len)
196
 
{
197
 
    struct test_session *sess;
198
 
 
199
 
    PJ_UNUSED_ARG(pkt);
200
 
    PJ_UNUSED_ARG(pkt_len);
201
 
    PJ_UNUSED_ARG(peer_addr);
202
 
    PJ_UNUSED_ARG(addr_len);
203
 
 
204
 
    sess = (struct test_session*) pj_turn_sock_get_user_data(turn_sock);
205
 
    if (sess == NULL)
206
 
        return;
207
 
 
208
 
    sess->result.rx_data_cnt++;
209
 
}
210
 
 
211
 
 
212
 
static void turn_on_state(pj_turn_sock *turn_sock, 
213
 
                          pj_turn_state_t old_state,
214
 
                          pj_turn_state_t new_state)
215
 
{
216
 
    struct test_session *sess;
217
 
    unsigned i, mask;
218
 
 
219
 
    PJ_UNUSED_ARG(old_state);
220
 
 
221
 
    sess = (struct test_session*) pj_turn_sock_get_user_data(turn_sock);
222
 
    if (sess == NULL)
223
 
        return;
224
 
 
225
 
    /* This state must not be called before */
226
 
    pj_assert((sess->result.state_called & (1<<new_state)) == 0);
227
 
 
228
 
    /* new_state must be greater than old_state */
229
 
    pj_assert(new_state > old_state);
230
 
 
231
 
    /* must not call any greater state before */
232
 
    mask = 0;
233
 
    for (i=new_state+1; i<31; ++i) mask |= (1 << i);
234
 
 
235
 
    pj_assert((sess->result.state_called & mask) == 0);
236
 
 
237
 
    sess->result.state_called |= (1 << new_state);
238
 
 
239
 
    if (new_state >= sess->destroy_on_state && !sess->destroy_called) {
240
 
        sess->destroy_called = PJ_TRUE;
241
 
        pj_turn_sock_destroy(turn_sock);
242
 
    }
243
 
 
244
 
    if (new_state >= PJ_TURN_STATE_DESTROYING) {
245
 
        pj_turn_sock_set_user_data(sess->turn_sock, NULL);
246
 
        sess->turn_sock = NULL;
247
 
    }
248
 
}
249
 
 
250
 
 
251
 
/////////////////////////////////////////////////////////////////////
252
 
 
253
 
static int state_progression_test(pj_stun_config  *stun_cfg)
254
 
{
255
 
    struct test_session_cfg test_cfg = 
256
 
    {
257
 
        {   /* Client cfg */
258
 
            /* DNS SRV */   /* Destroy on state */
259
 
            PJ_TRUE,        0xFFFF
260
 
        },
261
 
        {   /* Server cfg */
262
 
            0xFFFFFFFF,     /* flags */
263
 
            PJ_TRUE,        /* respond to allocate  */
264
 
            PJ_TRUE         /* respond to refresh   */
265
 
        }
266
 
    };
267
 
    struct test_session *sess;
268
 
    unsigned i;
269
 
    int rc;
270
 
 
271
 
    PJ_LOG(3,("", "  state progression tests"));
272
 
 
273
 
    for (i=0; i<=1; ++i) {
274
 
        enum { TIMEOUT = 60 };
275
 
        pjlib_state pjlib_state;
276
 
        pj_turn_session_info info;
277
 
        struct test_result result;
278
 
        pj_time_val tstart;
279
 
 
280
 
        PJ_LOG(3,("", "   %s DNS SRV resolution",
281
 
                      (i==0? "without" : "with")));
282
 
 
283
 
        capture_pjlib_state(stun_cfg, &pjlib_state);
284
 
 
285
 
        test_cfg.client.enable_dns_srv = i;
286
 
 
287
 
        rc = create_test_session(stun_cfg, &test_cfg, &sess);
288
 
        if (rc != 0)
289
 
            return rc;
290
 
 
291
 
        pj_bzero(&info, sizeof(info));
292
 
 
293
 
        /* Wait until state is READY */
294
 
        pj_gettimeofday(&tstart);
295
 
        while (sess->turn_sock) {
296
 
            pj_time_val now;
297
 
 
298
 
            poll_events(stun_cfg, 10, PJ_FALSE);
299
 
            rc = pj_turn_sock_get_info(sess->turn_sock, &info);
300
 
            if (rc!=PJ_SUCCESS)
301
 
                break;
302
 
 
303
 
            if (info.state >= PJ_TURN_STATE_READY)
304
 
                break;
305
 
 
306
 
            pj_gettimeofday(&now);
307
 
            if (now.sec - tstart.sec > TIMEOUT) {
308
 
                PJ_LOG(3,("", "    timed-out"));
309
 
                break;
310
 
            }
311
 
        }
312
 
 
313
 
        if (info.state != PJ_TURN_STATE_READY) {
314
 
            PJ_LOG(3,("", "    error: state is not READY"));
315
 
            destroy_session(sess);
316
 
            return -130;
317
 
        }
318
 
 
319
 
        /* Deallocate */
320
 
        pj_turn_sock_destroy(sess->turn_sock);
321
 
 
322
 
        /* Wait for couple of seconds.
323
 
         * We can't poll the session info since the session may have
324
 
         * been destroyed
325
 
         */
326
 
        poll_events(stun_cfg, 2000, PJ_FALSE);
327
 
        sess->turn_sock = NULL;
328
 
        pj_memcpy(&result, &sess->result, sizeof(result));
329
 
        destroy_session(sess);
330
 
 
331
 
        /* Check the result */
332
 
        if ((result.state_called & (1<<PJ_TURN_STATE_RESOLVING)) == 0) {
333
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_RESOLVING is not called"));
334
 
            return -140;
335
 
        }
336
 
 
337
 
        if ((result.state_called & (1<<PJ_TURN_STATE_RESOLVED)) == 0) {
338
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_RESOLVED is not called"));
339
 
            return -150;
340
 
        }
341
 
 
342
 
        if ((result.state_called & (1<<PJ_TURN_STATE_ALLOCATING)) == 0) {
343
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_ALLOCATING is not called"));
344
 
            return -155;
345
 
        }
346
 
 
347
 
        if ((result.state_called & (1<<PJ_TURN_STATE_READY)) == 0) {
348
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_READY is not called"));
349
 
            return -160;
350
 
        }
351
 
 
352
 
        if ((result.state_called & (1<<PJ_TURN_STATE_DEALLOCATING)) == 0) {
353
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_DEALLOCATING is not called"));
354
 
            return -170;
355
 
        }
356
 
 
357
 
        if ((result.state_called & (1<<PJ_TURN_STATE_DEALLOCATED)) == 0) {
358
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_DEALLOCATED is not called"));
359
 
            return -180;
360
 
        }
361
 
 
362
 
        if ((result.state_called & (1<<PJ_TURN_STATE_DESTROYING)) == 0) {
363
 
            PJ_LOG(3,("", "    error: PJ_TURN_STATE_DESTROYING is not called"));
364
 
            return -190;
365
 
        }
366
 
 
367
 
        poll_events(stun_cfg, 500, PJ_FALSE);
368
 
        rc = check_pjlib_state(stun_cfg, &pjlib_state);
369
 
        if (rc != 0) {
370
 
            PJ_LOG(3,("", "    error: memory/timer-heap leak detected"));
371
 
            return rc;
372
 
        }
373
 
    }
374
 
 
375
 
    return 0;
376
 
}
377
 
 
378
 
 
379
 
/////////////////////////////////////////////////////////////////////
380
 
 
381
 
static int destroy_test(pj_stun_config  *stun_cfg,
382
 
                        pj_bool_t with_dns_srv,
383
 
                        pj_bool_t in_callback)
384
 
{
385
 
    struct test_session_cfg test_cfg = 
386
 
    {
387
 
        {   /* Client cfg */
388
 
            /* DNS SRV */   /* Destroy on state */
389
 
            PJ_TRUE,        0xFFFF
390
 
        },
391
 
        {   /* Server cfg */
392
 
            0xFFFFFFFF,     /* flags */
393
 
            PJ_TRUE,        /* respond to allocate  */
394
 
            PJ_TRUE         /* respond to refresh   */
395
 
        }
396
 
    };
397
 
    struct test_session *sess;
398
 
    int target_state;
399
 
    int rc;
400
 
 
401
 
    PJ_LOG(3,("", "  destroy test %s %s",
402
 
                  (in_callback? "in callback" : ""),
403
 
                  (with_dns_srv? "with DNS srv" : "")
404
 
                  ));
405
 
 
406
 
    test_cfg.client.enable_dns_srv = with_dns_srv;
407
 
 
408
 
    for (target_state=PJ_TURN_STATE_RESOLVING; target_state<=PJ_TURN_STATE_READY; ++target_state) {
409
 
        enum { TIMEOUT = 60 };
410
 
        pjlib_state pjlib_state;
411
 
        pj_turn_session_info info;
412
 
        pj_time_val tstart;
413
 
 
414
 
        capture_pjlib_state(stun_cfg, &pjlib_state);
415
 
 
416
 
        PJ_LOG(3,("", "   %s", pj_turn_state_name((pj_turn_state_t)target_state)));
417
 
 
418
 
        if (in_callback)
419
 
            test_cfg.client.destroy_on_state = target_state;
420
 
 
421
 
        rc = create_test_session(stun_cfg, &test_cfg, &sess);
422
 
        if (rc != 0)
423
 
            return rc;
424
 
 
425
 
        if (in_callback) {
426
 
            pj_gettimeofday(&tstart);
427
 
            rc = 0;
428
 
            while (sess->turn_sock) {
429
 
                pj_time_val now;
430
 
 
431
 
                poll_events(stun_cfg, 100, PJ_FALSE);
432
 
 
433
 
                pj_gettimeofday(&now);
434
 
                if (now.sec - tstart.sec > TIMEOUT) {
435
 
                    rc = -7;
436
 
                    break;
437
 
                }
438
 
            }
439
 
 
440
 
        } else {
441
 
            pj_gettimeofday(&tstart);
442
 
            rc = 0;
443
 
            while (sess->turn_sock) {
444
 
                pj_time_val now;
445
 
 
446
 
                poll_events(stun_cfg, 1, PJ_FALSE);
447
 
 
448
 
                pj_turn_sock_get_info(sess->turn_sock, &info);
449
 
                
450
 
                if (info.state >= target_state) {
451
 
                    pj_turn_sock_destroy(sess->turn_sock);
452
 
                    break;
453
 
                }
454
 
 
455
 
                pj_gettimeofday(&now);
456
 
                if (now.sec - tstart.sec > TIMEOUT) {
457
 
                    rc = -8;
458
 
                    break;
459
 
                }
460
 
            }
461
 
        }
462
 
 
463
 
 
464
 
        if (rc != 0) {
465
 
            PJ_LOG(3,("", "    error: timeout"));
466
 
            return rc;
467
 
        }
468
 
 
469
 
        poll_events(stun_cfg, 1000, PJ_FALSE);
470
 
        destroy_session(sess);
471
 
 
472
 
        rc = check_pjlib_state(stun_cfg, &pjlib_state);
473
 
        if (rc != 0) {
474
 
            PJ_LOG(3,("", "    error: memory/timer-heap leak detected"));
475
 
            return rc;
476
 
        }
477
 
    }
478
 
 
479
 
    return 0;
480
 
}
481
 
 
482
 
 
483
 
/////////////////////////////////////////////////////////////////////
484
 
 
485
 
int turn_sock_test(void)
486
 
{
487
 
    pj_pool_t *pool;
488
 
    pj_stun_config stun_cfg;
489
 
    int i, rc = 0;
490
 
 
491
 
    pool = pj_pool_create(mem, "turntest", 512, 512, NULL);
492
 
    rc = create_stun_config(pool, &stun_cfg);
493
 
    if (rc != PJ_SUCCESS) {
494
 
        pj_pool_release(pool);
495
 
        return -2;
496
 
    }
497
 
 
498
 
    rc = state_progression_test(&stun_cfg);
499
 
    if (rc != 0) 
500
 
        goto on_return;
501
 
 
502
 
    for (i=0; i<=1; ++i) {
503
 
        int j;
504
 
        for (j=0; j<=1; ++j) {
505
 
            rc = destroy_test(&stun_cfg, i, j);
506
 
            if (rc != 0)
507
 
                goto on_return;
508
 
        }
509
 
    }
510
 
 
511
 
on_return:
512
 
    destroy_stun_config(&stun_cfg);
513
 
    pj_pool_release(pool);
514
 
    return rc;
515
 
}
516