1
/* $Id: ice_test.c 4412 2013-03-05 03:12:32Z riza $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
30
#define NODELAY 0xFFFFFFFF
31
#define SRV_DOMAIN "pjsip.lab.domain"
32
#define MAX_THREADS 16
34
#define THIS_FILE "ice_test.c"
48
pj_status_t init_status; /* init successful? */
49
pj_status_t nego_status; /* negotiation successful? */
50
unsigned rx_cnt[4]; /* Number of data received */
53
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
54
/* Test session configuration */
57
pj_ice_sess_role role; /* Role. */
58
unsigned comp_cnt; /* Component count */
59
unsigned enable_host; /* Enable host candidates */
60
unsigned enable_stun; /* Enable srflx candidates */
61
unsigned enable_turn; /* Enable turn candidates */
62
unsigned client_flag; /* Client flags */
64
unsigned answer_delay; /* Delay before sending SDP */
65
unsigned send_delay; /* unused */
66
unsigned destroy_delay; /* unused */
68
struct test_result expected;/* Expected result */
70
pj_bool_t nom_regular; /* Use regular nomination? */
73
/* ICE endpoint state */
76
struct test_cfg cfg; /* Configuratino. */
77
pj_ice_strans *ice; /* ICE stream transport */
78
struct test_result result;/* Test result. */
80
pj_str_t ufrag; /* username fragment. */
81
pj_str_t pass; /* password */
88
unsigned worker_timeout;
89
pj_bool_t worker_quit;
91
pj_bool_t destroy_after_create;
92
pj_bool_t destroy_after_one_done;
95
/* The test session */
99
pj_stun_config *stun_cfg;
100
pj_dns_resolver *resolver;
102
struct sess_param *param;
106
pj_thread_t *worker_threads[MAX_THREADS];
108
unsigned server_flag;
109
struct ice_ept caller;
110
struct ice_ept callee;
114
static void ice_on_rx_data(pj_ice_strans *ice_st,
116
void *pkt, pj_size_t size,
117
const pj_sockaddr_t *src_addr,
118
unsigned src_addr_len);
119
static void ice_on_ice_complete(pj_ice_strans *ice_st,
122
static void destroy_sess(struct test_sess *sess, unsigned wait_msec);
124
/* Create ICE stream transport */
125
static int create_ice_strans(struct test_sess *test_sess,
127
pj_ice_strans **p_ice)
130
pj_ice_strans_cb ice_cb;
131
pj_ice_strans_cfg ice_cfg;
133
char serverip[PJ_INET6_ADDRSTRLEN];
136
status = pj_gethostip(pj_AF_INET(), &hostip);
137
if (status != PJ_SUCCESS)
140
pj_sockaddr_print(&hostip, serverip, sizeof(serverip), 0);
142
/* Init callback structure */
143
pj_bzero(&ice_cb, sizeof(ice_cb));
144
ice_cb.on_rx_data = &ice_on_rx_data;
145
ice_cb.on_ice_complete = &ice_on_ice_complete;
147
/* Init ICE stream transport configuration structure */
148
pj_ice_strans_cfg_default(&ice_cfg);
149
pj_memcpy(&ice_cfg.stun_cfg, test_sess->stun_cfg, sizeof(pj_stun_config));
150
if ((ept->cfg.enable_stun & SRV)==SRV || (ept->cfg.enable_turn & SRV)==SRV)
151
ice_cfg.resolver = test_sess->resolver;
153
if (ept->cfg.enable_stun & YES) {
154
if ((ept->cfg.enable_stun & SRV) == SRV) {
155
ice_cfg.stun.server = pj_str(SRV_DOMAIN);
157
ice_cfg.stun.server = pj_str(serverip);
159
ice_cfg.stun.port = STUN_SERVER_PORT;
162
if (ept->cfg.enable_host == 0) {
163
ice_cfg.stun.max_host_cands = 0;
165
//ice_cfg.stun.no_host_cands = PJ_FALSE;
166
ice_cfg.stun.loop_addr = PJ_TRUE;
170
if (ept->cfg.enable_turn & YES) {
171
if ((ept->cfg.enable_turn & SRV) == SRV) {
172
ice_cfg.turn.server = pj_str(SRV_DOMAIN);
174
ice_cfg.turn.server = pj_str(serverip);
176
ice_cfg.turn.port = TURN_SERVER_PORT;
177
ice_cfg.turn.conn_type = PJ_TURN_TP_UDP;
178
ice_cfg.turn.auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
179
ice_cfg.turn.auth_cred.data.static_cred.realm = pj_str(SRV_DOMAIN);
180
if (ept->cfg.client_flag & WRONG_TURN)
181
ice_cfg.turn.auth_cred.data.static_cred.username = pj_str("xxx");
183
ice_cfg.turn.auth_cred.data.static_cred.username = pj_str(TURN_USERNAME);
184
ice_cfg.turn.auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
185
ice_cfg.turn.auth_cred.data.static_cred.data = pj_str(TURN_PASSWD);
188
/* Create ICE stream transport */
189
status = pj_ice_strans_create(NULL, &ice_cfg, ept->cfg.comp_cnt,
192
if (status != PJ_SUCCESS) {
193
app_perror(INDENT "err: pj_ice_strans_create()", status);
197
pj_create_unique_string(test_sess->pool, &ept->ufrag);
198
pj_create_unique_string(test_sess->pool, &ept->pass);
205
/* Create test session */
206
static int create_sess(pj_stun_config *stun_cfg,
207
unsigned server_flag,
208
struct test_cfg *caller_cfg,
209
struct test_cfg *callee_cfg,
210
struct sess_param *test_param,
211
struct test_sess **p_sess)
214
struct test_sess *sess;
220
/* Create session structure */
221
pool = pj_pool_create(mem, "testsess", 512, 512, NULL);
222
sess = PJ_POOL_ZALLOC_T(pool, struct test_sess);
224
sess->stun_cfg = stun_cfg;
225
sess->param = test_param;
227
pj_memcpy(&sess->caller.cfg, caller_cfg, sizeof(*caller_cfg));
228
sess->caller.result.init_status = sess->caller.result.nego_status = PJ_EPENDING;
230
pj_memcpy(&sess->callee.cfg, callee_cfg, sizeof(*callee_cfg));
231
sess->callee.result.init_status = sess->callee.result.nego_status = PJ_EPENDING;
235
status = create_test_server(stun_cfg, flags, SRV_DOMAIN, &sess->server);
236
if (status != PJ_SUCCESS) {
237
app_perror(INDENT "error: create_test_server()", status);
238
destroy_sess(sess, 500);
241
sess->server->turn_respond_allocate =
242
sess->server->turn_respond_refresh = PJ_TRUE;
244
/* Create resolver */
245
status = pj_dns_resolver_create(mem, NULL, 0, stun_cfg->timer_heap,
246
stun_cfg->ioqueue, &sess->resolver);
247
if (status != PJ_SUCCESS) {
248
app_perror(INDENT "error: pj_dns_resolver_create()", status);
249
destroy_sess(sess, 500);
253
ns_ip = pj_str("127.0.0.1");
254
ns_port = (pj_uint16_t)DNS_SERVER_PORT;
255
status = pj_dns_resolver_set_ns(sess->resolver, 1, &ns_ip, &ns_port);
256
if (status != PJ_SUCCESS) {
257
app_perror( INDENT "error: pj_dns_resolver_set_ns()", status);
258
destroy_sess(sess, 500);
262
/* Create caller ICE stream transport */
263
status = create_ice_strans(sess, &sess->caller, &sess->caller.ice);
264
if (status != PJ_SUCCESS) {
265
destroy_sess(sess, 500);
269
/* Create callee ICE stream transport */
270
status = create_ice_strans(sess, &sess->callee, &sess->callee.ice);
271
if (status != PJ_SUCCESS) {
272
destroy_sess(sess, 500);
280
/* Destroy test session */
281
static void destroy_sess(struct test_sess *sess, unsigned wait_msec)
285
if (sess->caller.ice) {
286
pj_ice_strans_destroy(sess->caller.ice);
287
sess->caller.ice = NULL;
290
if (sess->callee.ice) {
291
pj_ice_strans_destroy(sess->callee.ice);
292
sess->callee.ice = NULL;
295
sess->param->worker_quit = PJ_TRUE;
296
for (i=0; i<sess->param->worker_cnt; ++i) {
297
if (sess->worker_threads[i])
298
pj_thread_join(sess->worker_threads[i]);
301
poll_events(sess->stun_cfg, wait_msec, PJ_FALSE);
303
if (sess->resolver) {
304
pj_dns_resolver_destroy(sess->resolver, PJ_FALSE);
305
sess->resolver = NULL;
309
destroy_test_server(sess->server);
314
pj_pool_t *pool = sess->pool;
316
pj_pool_release(pool);
320
static void ice_on_rx_data(pj_ice_strans *ice_st,
322
void *pkt, pj_size_t size,
323
const pj_sockaddr_t *src_addr,
324
unsigned src_addr_len)
330
PJ_UNUSED_ARG(src_addr);
331
PJ_UNUSED_ARG(src_addr_len);
333
ept = (struct ice_ept*) pj_ice_strans_get_user_data(ice_st);
334
ept->result.rx_cnt[comp_id]++;
338
static void ice_on_ice_complete(pj_ice_strans *ice_st,
344
ept = (struct ice_ept*) pj_ice_strans_get_user_data(ice_st);
346
case PJ_ICE_STRANS_OP_INIT:
347
ept->result.init_status = status;
348
if (status != PJ_SUCCESS && (ept->cfg.client_flag & DEL_ON_ERR)) {
349
pj_ice_strans_destroy(ice_st);
353
case PJ_ICE_STRANS_OP_NEGOTIATION:
354
ept->result.nego_status = status;
356
case PJ_ICE_STRANS_OP_KEEP_ALIVE:
357
/* keep alive failed? */
360
pj_assert(!"Unknown op");
365
/* Start ICE negotiation on the endpoint, based on parameter from
366
* the other endpoint.
368
static pj_status_t start_ice(struct ice_ept *ept, const struct ice_ept *remote)
370
pj_ice_sess_cand rcand[32];
371
unsigned i, rcand_cnt = 0;
374
/* Enum remote candidates */
375
for (i=0; i<remote->cfg.comp_cnt; ++i) {
376
unsigned cnt = PJ_ARRAY_SIZE(rcand) - rcand_cnt;
377
status = pj_ice_strans_enum_cands(remote->ice, i+1, &cnt, rcand+rcand_cnt);
378
if (status != PJ_SUCCESS) {
379
app_perror(INDENT "err: pj_ice_strans_enum_cands()", status);
385
status = pj_ice_strans_start_ice(ept->ice, &remote->ufrag, &remote->pass,
387
if (status != PJ_SUCCESS) {
388
app_perror(INDENT "err: pj_ice_strans_start_ice()", status);
396
/* Check that the pair in both agents are matched */
397
static int check_pair(const struct ice_ept *ept1, const struct ice_ept *ept2,
400
unsigned i, min_cnt, max_cnt;
402
if (ept1->cfg.comp_cnt < ept2->cfg.comp_cnt) {
403
min_cnt = ept1->cfg.comp_cnt;
404
max_cnt = ept2->cfg.comp_cnt;
406
min_cnt = ept2->cfg.comp_cnt;
407
max_cnt = ept1->cfg.comp_cnt;
410
/* Must have valid pair for common components */
411
for (i=0; i<min_cnt; ++i) {
412
const pj_ice_sess_check *c1;
413
const pj_ice_sess_check *c2;
415
c1 = pj_ice_strans_get_valid_pair(ept1->ice, i+1);
417
PJ_LOG(3,(THIS_FILE, INDENT "err: unable to get valid pair for ice1 "
418
"component %d", i+1));
419
return start_err - 2;
422
c2 = pj_ice_strans_get_valid_pair(ept2->ice, i+1);
424
PJ_LOG(3,(THIS_FILE, INDENT "err: unable to get valid pair for ice2 "
425
"component %d", i+1));
426
return start_err - 4;
429
if (pj_sockaddr_cmp(&c1->rcand->addr, &c2->lcand->addr) != 0) {
430
PJ_LOG(3,(THIS_FILE, INDENT "err: candidate pair does not match "
431
"for component %d", i+1));
432
return start_err - 6;
436
/* Extra components must not have valid pair */
437
for (; i<max_cnt; ++i) {
438
if (ept1->cfg.comp_cnt>i &&
439
pj_ice_strans_get_valid_pair(ept1->ice, i+1) != NULL)
441
PJ_LOG(3,(THIS_FILE, INDENT "err: ice1 shouldn't have valid pair "
442
"for component %d", i+1));
443
return start_err - 8;
445
if (ept2->cfg.comp_cnt>i &&
446
pj_ice_strans_get_valid_pair(ept2->ice, i+1) != NULL)
448
PJ_LOG(3,(THIS_FILE, INDENT "err: ice2 shouldn't have valid pair "
449
"for component %d", i+1));
450
return start_err - 9;
458
#define WAIT_UNTIL(timeout,expr, RC) { \
460
pj_gettimeofday(&t0); \
463
poll_events(stun_cfg, 10, PJ_FALSE); \
464
pj_gettimeofday(&t); \
469
PJ_TIME_VAL_SUB(t, t0); \
470
if ((unsigned)PJ_TIME_VAL_MSEC(t) >= (timeout)) \
475
int worker_thread_proc(void *data)
478
struct test_sess *sess = (struct test_sess *) data;
479
pj_stun_config *stun_cfg = sess->stun_cfg;
481
/* Wait until negotiation is complete on both endpoints */
482
#define ALL_DONE (sess->param->worker_quit || \
483
(sess->caller.result.nego_status!=PJ_EPENDING && \
484
sess->callee.result.nego_status!=PJ_EPENDING))
485
WAIT_UNTIL(sess->param->worker_timeout, ALL_DONE, rc);
490
static int perform_test2(const char *title,
491
pj_stun_config *stun_cfg,
492
unsigned server_flag,
493
struct test_cfg *caller_cfg,
494
struct test_cfg *callee_cfg,
495
struct sess_param *test_param)
497
pjlib_state pjlib_state;
498
struct test_sess *sess;
502
PJ_LOG(3,(THIS_FILE, INDENT "%s", title));
504
capture_pjlib_state(stun_cfg, &pjlib_state);
506
rc = create_sess(stun_cfg, server_flag, caller_cfg, callee_cfg, test_param, &sess);
510
#define ALL_READY (sess->caller.result.init_status!=PJ_EPENDING && \
511
sess->callee.result.init_status!=PJ_EPENDING)
513
/* Wait until both ICE transports are initialized */
514
WAIT_UNTIL(30000, ALL_READY, rc);
517
PJ_LOG(3,(THIS_FILE, INDENT "err: init timed-out"));
518
destroy_sess(sess, 500);
522
if (sess->caller.result.init_status != sess->caller.cfg.expected.init_status) {
523
app_perror(INDENT "err: caller init", sess->caller.result.init_status);
524
destroy_sess(sess, 500);
527
if (sess->callee.result.init_status != sess->callee.cfg.expected.init_status) {
528
app_perror(INDENT "err: callee init", sess->callee.result.init_status);
529
destroy_sess(sess, 500);
533
/* Failure condition */
534
if (sess->caller.result.init_status != PJ_SUCCESS ||
535
sess->callee.result.init_status != PJ_SUCCESS)
540
/* Init ICE on caller */
541
rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role,
542
&sess->caller.ufrag, &sess->caller.pass);
543
if (rc != PJ_SUCCESS) {
544
app_perror(INDENT "err: caller pj_ice_strans_init_ice()", rc);
545
destroy_sess(sess, 500);
549
/* Init ICE on callee */
550
rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role,
551
&sess->callee.ufrag, &sess->callee.pass);
552
if (rc != PJ_SUCCESS) {
553
app_perror(INDENT "err: callee pj_ice_strans_init_ice()", rc);
554
destroy_sess(sess, 500);
557
/* Start ICE on callee */
558
rc = start_ice(&sess->callee, &sess->caller);
559
if (rc != PJ_SUCCESS) {
560
destroy_sess(sess, 500);
563
/* Wait for callee's answer_delay */
564
poll_events(stun_cfg, sess->callee.cfg.answer_delay, PJ_FALSE);
565
/* Start ICE on caller */
566
rc = start_ice(&sess->caller, &sess->callee);
567
if (rc != PJ_SUCCESS) {
568
destroy_sess(sess, 500);
572
for (i=0; i<sess->param->worker_cnt; ++i) {
575
status = pj_thread_create(sess->pool, "worker_thread",
576
worker_thread_proc, sess, 0, 0,
577
&sess->worker_threads[i]);
578
if (status != PJ_SUCCESS) {
579
PJ_LOG(3,(THIS_FILE, INDENT "err: create thread"));
580
destroy_sess(sess, 500);
585
if (sess->param->destroy_after_create)
588
if (sess->param->destroy_after_one_done) {
589
while (sess->caller.result.init_status==PJ_EPENDING &&
590
sess->callee.result.init_status==PJ_EPENDING)
592
if (sess->param->worker_cnt)
595
poll_events(stun_cfg, 0, PJ_FALSE);
600
WAIT_UNTIL(30000, ALL_DONE, rc);
602
PJ_LOG(3,(THIS_FILE, INDENT "err: negotiation timed-out"));
603
destroy_sess(sess, 500);
607
if (sess->caller.result.nego_status != sess->caller.cfg.expected.nego_status) {
608
app_perror(INDENT "err: caller negotiation failed", sess->caller.result.nego_status);
609
destroy_sess(sess, 500);
613
if (sess->callee.result.nego_status != sess->callee.cfg.expected.nego_status) {
614
app_perror(INDENT "err: callee negotiation failed", sess->callee.result.nego_status);
615
destroy_sess(sess, 500);
619
/* Verify that both agents have agreed on the same pair */
620
rc = check_pair(&sess->caller, &sess->callee, -170);
622
destroy_sess(sess, 500);
625
rc = check_pair(&sess->callee, &sess->caller, -180);
627
destroy_sess(sess, 500);
631
/* Looks like everything is okay */
634
/* Destroy ICE stream transports first to let it de-allocate
635
* TURN relay (otherwise there'll be timer/memory leak, unless
636
* we wait for long time in the last poll_events() below).
638
if (sess->caller.ice) {
639
pj_ice_strans_destroy(sess->caller.ice);
640
sess->caller.ice = NULL;
643
if (sess->callee.ice) {
644
pj_ice_strans_destroy(sess->callee.ice);
645
sess->callee.ice = NULL;
650
poll_events(stun_cfg, 200, PJ_FALSE);
652
/* Now destroy everything */
653
destroy_sess(sess, 500);
656
poll_events(stun_cfg, 100, PJ_FALSE);
658
rc = check_pjlib_state(stun_cfg, &pjlib_state);
666
static int perform_test(const char *title,
667
pj_stun_config *stun_cfg,
668
unsigned server_flag,
669
struct test_cfg *caller_cfg,
670
struct test_cfg *callee_cfg)
672
struct sess_param test_param;
674
pj_bzero(&test_param, sizeof(test_param));
675
return perform_test2(title, stun_cfg, server_flag, caller_cfg,
676
callee_cfg, &test_param);
679
#define ROLE1 PJ_ICE_SESS_ROLE_CONTROLLED
680
#define ROLE2 PJ_ICE_SESS_ROLE_CONTROLLING
685
pj_stun_config stun_cfg;
690
unsigned server_flag;
695
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
697
"hosts candidates only",
699
{ROLE1, 1, YES, NO, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
700
{ROLE2, 1, YES, NO, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
705
{ROLE1, 1, YES, YES, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
706
{ROLE2, 1, YES, YES, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
711
{ROLE1, 1, YES, NO, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
712
{ROLE2, 1, NO, NO, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
717
{ROLE1, 1, NO, NO, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
718
{ROLE2, 1, YES, NO, NO, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
723
{ROLE1, 1, NO, NO, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
724
{ROLE2, 1, NO, NO, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
729
{ROLE1, 1, YES, YES, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
730
{ROLE2, 1, YES, YES, YES, NO, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
734
pool = pj_pool_create(mem, NULL, 512, 512, NULL);
735
rc = create_stun_config(pool, &stun_cfg);
736
if (rc != PJ_SUCCESS) {
737
pj_pool_release(pool);
741
/* Simple test first with host candidate */
743
struct sess_cfg_t cfg =
745
"Basic with host candidates",
747
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
748
{ROLE1, 1, YES, NO, NO, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
749
{ROLE2, 1, YES, NO, NO, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
752
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
757
cfg.ua1.comp_cnt = 2;
758
cfg.ua2.comp_cnt = 2;
759
rc = perform_test("Basic with host candidates, 2 components",
760
&stun_cfg, cfg.server_flag,
766
/* Simple test first with srflx candidate */
768
struct sess_cfg_t cfg =
770
"Basic with srflx candidates",
772
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
773
{ROLE1, 1, YES, YES, NO, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
774
{ROLE2, 1, YES, YES, NO, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
777
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
782
cfg.ua1.comp_cnt = 2;
783
cfg.ua2.comp_cnt = 2;
785
rc = perform_test("Basic with srflx candidates, 2 components",
786
&stun_cfg, cfg.server_flag,
792
/* Simple test with relay candidate */
794
struct sess_cfg_t cfg =
796
"Basic with relay candidates",
798
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
799
{ROLE1, 1, NO, NO, YES, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
800
{ROLE2, 1, NO, NO, YES, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
803
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
808
cfg.ua1.comp_cnt = 2;
809
cfg.ua2.comp_cnt = 2;
811
rc = perform_test("Basic with relay candidates, 2 components",
812
&stun_cfg, cfg.server_flag,
818
/* Failure test with STUN resolution */
820
struct sess_cfg_t cfg =
822
"STUN resolution failure",
824
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
825
{ROLE1, 2, NO, YES, NO, 0, 0, 0, 0, {PJNATH_ESTUNTIMEDOUT, -1}},
826
{ROLE2, 2, NO, YES, NO, 0, 0, 0, 0, {PJNATH_ESTUNTIMEDOUT, -1}}
829
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
834
cfg.ua1.client_flag |= DEL_ON_ERR;
835
cfg.ua2.client_flag |= DEL_ON_ERR;
837
rc = perform_test("STUN resolution failure with destroy on callback",
838
&stun_cfg, cfg.server_flag,
844
/* Failure test with TURN resolution */
846
struct sess_cfg_t cfg =
848
"TURN allocation failure",
850
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
851
{ROLE1, 2, NO, NO, YES, WRONG_TURN, 0, 0, 0, {PJ_STATUS_FROM_STUN_CODE(401), -1}},
852
{ROLE2, 2, NO, NO, YES, WRONG_TURN, 0, 0, 0, {PJ_STATUS_FROM_STUN_CODE(401), -1}}
855
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
860
cfg.ua1.client_flag |= DEL_ON_ERR;
861
cfg.ua2.client_flag |= DEL_ON_ERR;
863
rc = perform_test("TURN allocation failure with destroy on callback",
864
&stun_cfg, cfg.server_flag,
871
/* STUN failure, testing TURN deallocation */
873
struct sess_cfg_t cfg =
875
"STUN failure, testing TURN deallocation",
876
0xFFFF & (~(CREATE_STUN_SERVER)),
877
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
878
{ROLE1, 1, YES, YES, YES, 0, 0, 0, 0, {PJNATH_ESTUNTIMEDOUT, -1}},
879
{ROLE2, 1, YES, YES, YES, 0, 0, 0, 0, {PJNATH_ESTUNTIMEDOUT, -1}}
882
rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag,
887
cfg.ua1.client_flag |= DEL_ON_ERR;
888
cfg.ua2.client_flag |= DEL_ON_ERR;
890
rc = perform_test("STUN failure, testing TURN deallocation (cb)",
891
&stun_cfg, cfg.server_flag,
898
/* Iterate each test item */
899
for (i=0; i<PJ_ARRAY_SIZE(sess_cfg); ++i) {
900
struct sess_cfg_t *cfg = &sess_cfg[i];
901
unsigned delay[] = { 50, 2000 };
904
PJ_LOG(3,(THIS_FILE, " %s", cfg->title));
906
/* For each test item, test with various answer delay */
907
for (d=0; d<PJ_ARRAY_SIZE(delay); ++d) {
909
pj_ice_sess_role ua1;
910
pj_ice_sess_role ua2;
920
cfg->ua1.answer_delay = delay[d];
921
cfg->ua2.answer_delay = delay[d];
923
/* For each test item, test with role conflict scenarios */
924
for (j=0; j<PJ_ARRAY_SIZE(role); ++j) {
927
cfg->ua1.role = role[j].ua1;
928
cfg->ua2.role = role[j].ua2;
930
/* For each test item, test with different number of components */
931
for (k1=1; k1<=2; ++k1) {
934
cfg->ua1.comp_cnt = k1;
936
for (k2=1; k2<=2; ++k2) {
940
"%s/%s, %dms answer delay, %d vs %d components",
941
pj_ice_sess_role_name(role[j].ua1),
942
pj_ice_sess_role_name(role[j].ua2),
945
cfg->ua2.comp_cnt = k2;
946
rc = perform_test(title, &stun_cfg, cfg->server_flag,
947
&cfg->ua1, &cfg->ua2);
957
destroy_stun_config(&stun_cfg);
958
pj_pool_release(pool);
962
int ice_one_conc_test(pj_stun_config *stun_cfg, int err_quit)
966
unsigned server_flag;
973
/* Role comp# host? stun? turn? flag? ans_del snd_del des_del */
974
{ROLE1, 1, YES, YES, YES, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}},
975
{ROLE2, 1, YES, YES, YES, 0, 0, 0, 0, {PJ_SUCCESS, PJ_SUCCESS}}
977
struct sess_param test_param;
981
/* test a: destroy as soon as nego starts */
982
cfg.title = " ice test a: immediate destroy";
983
pj_bzero(&test_param, sizeof(test_param));
984
test_param.worker_cnt = 4;
985
test_param.worker_timeout = 1000;
986
test_param.destroy_after_create = PJ_TRUE;
988
rc = perform_test2(cfg.title, stun_cfg, cfg.server_flag,
989
&cfg.ua1, &cfg.ua2, &test_param);
990
if (rc != 0 && err_quit)
993
/* test b: destroy as soon as one is done */
994
cfg.title = " ice test b: destroy after 1 success";
995
test_param.destroy_after_create = PJ_FALSE;
996
test_param.destroy_after_one_done = PJ_TRUE;
998
rc = perform_test2(cfg.title, stun_cfg, cfg.server_flag,
999
&cfg.ua1, &cfg.ua2, &test_param);
1000
if (rc != 0 && err_quit)
1003
/* test c: normal */
1004
cfg.title = " ice test c: normal flow";
1005
pj_bzero(&test_param, sizeof(test_param));
1006
test_param.worker_cnt = 4;
1007
test_param.worker_timeout = 1000;
1009
rc = perform_test2(cfg.title, stun_cfg, cfg.server_flag,
1010
&cfg.ua1, &cfg.ua2, &test_param);
1011
if (rc != 0 && err_quit)
1017
int ice_conc_test(void)
1019
const unsigned LOOP = 100;
1021
pj_stun_config stun_cfg;
1025
pool = pj_pool_create(mem, NULL, 512, 512, NULL);
1026
rc = create_stun_config(pool, &stun_cfg);
1027
if (rc != PJ_SUCCESS) {
1028
pj_pool_release(pool);
1032
for (i = 0; i < LOOP; i++) {
1033
PJ_LOG(3,(THIS_FILE, INDENT "Test %d of %d", i+1, LOOP));
1034
rc = ice_one_conc_test(&stun_cfg, PJ_TRUE);
1039
/* Avoid compiler warning */
1043
destroy_stun_config(&stun_cfg);
1044
pj_pool_release(pool);