blob: 38bb6d022f985020d2dfa30aaaf32c73179a680f [file] [log] [blame]
Benny Prijonofb9d9872007-03-21 22:05:58 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include "test.h"
20
Benny Prijono7e0d52c2007-03-26 13:25:07 +000021#define THIS_FILE "ice_test.c"
Benny Prijonofb9d9872007-03-21 22:05:58 +000022
23
24struct ice_data
25{
Benny Prijono2532b9d2007-03-22 01:16:37 +000026 const char *obj_name;
Benny Prijonofb9d9872007-03-21 22:05:58 +000027 pj_bool_t complete;
28 pj_status_t err_code;
29 unsigned rx_rtp_cnt;
30 unsigned rx_rtcp_cnt;
Benny Prijono2532b9d2007-03-22 01:16:37 +000031
Benny Prijonofd7f1472007-03-22 11:59:03 +000032 unsigned rx_rtp_count;
33 char last_rx_rtp_data[32];
34 unsigned rx_rtcp_count;
35 char last_rx_rtcp_data[32];
Benny Prijonofb9d9872007-03-21 22:05:58 +000036};
37
38static pj_stun_config stun_cfg;
39
Benny Prijonoa6bd7582007-03-28 15:49:48 +000040static void on_ice_complete(pj_ice_strans *icest,
Benny Prijonofb9d9872007-03-21 22:05:58 +000041 pj_status_t status)
42{
Benny Prijonoff49ab72007-03-22 21:00:53 +000043 struct ice_data *id = (struct ice_data*) icest->user_data;
Benny Prijonofb9d9872007-03-21 22:05:58 +000044 id->complete = PJ_TRUE;
45 id->err_code = status;
Benny Prijono7e0d52c2007-03-26 13:25:07 +000046 PJ_LOG(3,(THIS_FILE, " ICE %s complete %s", id->obj_name,
Benny Prijono2532b9d2007-03-22 01:16:37 +000047 (status==PJ_SUCCESS ? "successfully" : "with failure")));
Benny Prijonofb9d9872007-03-21 22:05:58 +000048}
49
50
Benny Prijonoa6bd7582007-03-28 15:49:48 +000051static void on_rx_data(pj_ice_strans *icest, unsigned comp_id,
Benny Prijonofb9d9872007-03-21 22:05:58 +000052 void *pkt, pj_size_t size,
53 const pj_sockaddr_t *src_addr,
54 unsigned src_addr_len)
55{
Benny Prijonoff49ab72007-03-22 21:00:53 +000056 struct ice_data *id = (struct ice_data*) icest->user_data;
Benny Prijono2532b9d2007-03-22 01:16:37 +000057
Benny Prijonoff49ab72007-03-22 21:00:53 +000058 if (comp_id == 1) {
59 id->rx_rtp_cnt++;
60 pj_memcpy(id->last_rx_rtp_data, pkt, size);
61 id->last_rx_rtp_data[size] = '\0';
62 } else if (comp_id == 2) {
63 id->rx_rtcp_cnt++;
64 pj_memcpy(id->last_rx_rtcp_data, pkt, size);
65 id->last_rx_rtcp_data[size] = '\0';
66 } else {
67 pj_assert(!"Invalid component ID");
68 }
Benny Prijono2532b9d2007-03-22 01:16:37 +000069
70 PJ_UNUSED_ARG(src_addr);
71 PJ_UNUSED_ARG(src_addr_len);
Benny Prijonofb9d9872007-03-21 22:05:58 +000072}
73
74
75static void handle_events(unsigned msec_timeout)
76{
77 pj_time_val delay;
78
79 pj_timer_heap_poll(stun_cfg.timer_heap, NULL);
80
81 delay.sec = 0;
82 delay.msec = msec_timeout;
83 pj_time_val_normalize(&delay);
84
85 pj_ioqueue_poll(stun_cfg.ioqueue, &delay);
86}
87
88
89/* Basic create and destroy test */
90static int ice_basic_create_destroy_test()
91{
Benny Prijonoa6bd7582007-03-28 15:49:48 +000092 pj_ice_strans *im;
93 pj_ice_strans_cb icest_cb;
Benny Prijonofb9d9872007-03-21 22:05:58 +000094 pj_status_t status;
95
96 PJ_LOG(3,(THIS_FILE, "...basic create/destroy"));
97
Benny Prijonoff49ab72007-03-22 21:00:53 +000098 pj_bzero(&icest_cb, sizeof(icest_cb));
99 icest_cb.on_ice_complete = &on_ice_complete;
100 icest_cb.on_rx_data = &on_rx_data;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000101
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000102 status = pj_ice_strans_create(&stun_cfg, "icetest", 2, NULL, &icest_cb, &im);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000103 if (status != PJ_SUCCESS)
104 return -10;
105
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000106 pj_ice_strans_destroy(im);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000107
108 return 0;
109}
110
111
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000112static pj_status_t start_ice(pj_ice_strans *ist, pj_ice_strans *remote)
Benny Prijonofb9d9872007-03-21 22:05:58 +0000113{
Benny Prijonoff49ab72007-03-22 21:00:53 +0000114 unsigned count;
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000115 pj_ice_sess_cand cand[PJ_ICE_MAX_CAND];
Benny Prijonofb9d9872007-03-21 22:05:58 +0000116 pj_status_t status;
117
Benny Prijonoff49ab72007-03-22 21:00:53 +0000118 count = PJ_ARRAY_SIZE(cand);
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000119 status = pj_ice_strans_enum_cands(remote, &count, cand);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000120 if (status != PJ_SUCCESS)
121 return status;
122
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000123 return pj_ice_strans_start_ice(ist, &remote->ice->rx_ufrag, &remote->ice->rx_pass,
Benny Prijonoff49ab72007-03-22 21:00:53 +0000124 count, cand);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000125}
126
127
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000128struct dummy_cand
129{
130 unsigned comp_id;
131 pj_ice_cand_type type;
132 const char *addr;
133 unsigned port;
134};
135
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000136static int init_ice_st(pj_ice_strans *ice_st,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000137 pj_bool_t add_valid_comp,
138 unsigned dummy_cnt,
139 struct dummy_cand cand[])
140{
141 pj_str_t a;
142 pj_status_t status;
143 unsigned i;
144
145 /* Create components */
146 for (i=0; i<ice_st->comp_cnt; ++i) {
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000147 status = pj_ice_strans_create_comp(ice_st, i+1, PJ_ICE_ST_OPT_DONT_ADD_CAND, NULL);
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000148 if (status != PJ_SUCCESS)
149 return -21;
150 }
151
152 /* Add dummy candidates */
153 for (i=0; i<dummy_cnt; ++i) {
154 pj_sockaddr_in addr;
155
156 pj_sockaddr_in_init(&addr, pj_cstr(&a, cand[i].addr), (pj_uint16_t)cand[i].port);
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000157 status = pj_ice_strans_add_cand(ice_st, cand[i].comp_id, cand[i].type,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000158 65535, &addr, PJ_FALSE);
159 if (status != PJ_SUCCESS)
160 return -22;
161 }
162
163 /* Add the real candidate */
164 if (add_valid_comp) {
165 for (i=0; i<ice_st->comp_cnt; ++i) {
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000166 status = pj_ice_strans_add_cand(ice_st, i+1, PJ_ICE_CAND_TYPE_HOST, 65535,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000167 &ice_st->comp[i]->local_addr.ipv4, PJ_TRUE);
168 if (status != PJ_SUCCESS)
169 return -23;
170 }
171 }
172
173 return 0;
174}
175
176
177/* When ICE completes, both agents should agree on the same candidate pair.
178 * Check that the remote address selected by agent1 is equal to the
179 * local address of selected by agent 2.
180 */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000181static int verify_address(pj_ice_strans *agent1, pj_ice_strans *agent2,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000182 unsigned comp_id)
183{
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000184 pj_ice_sess_cand *rcand, *lcand;
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000185 int lcand_id;
186
187 if (agent1->ice->comp[comp_id-1].valid_check == NULL) {
188 PJ_LOG(3,(THIS_FILE, "....error: valid_check not set for comp_id %d", comp_id));
189 return -60;
190 }
191
192 /* Get default remote candidate of agent 1 */
193 rcand = agent1->ice->comp[comp_id-1].valid_check->rcand;
194
195 /* Get default local candidate of agent 2 */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000196 pj_ice_sess_find_default_cand(agent2->ice, comp_id, &lcand_id);
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000197 if (lcand_id < 0)
198 return -62;
199
200 lcand = &agent2->ice->lcand[lcand_id];
201
202 if (pj_memcmp(&rcand->addr, &lcand->addr, sizeof(pj_sockaddr_in))!=0) {
203 PJ_LOG(3,(THIS_FILE, "....error: the selected addresses are incorrect for comp_id %d", comp_id));
204 return -64;
205 }
206
207 return 0;
208}
209
Benny Prijonoff49ab72007-03-22 21:00:53 +0000210
Benny Prijono2532b9d2007-03-22 01:16:37 +0000211/* Perform ICE test with the following parameters:
212 *
213 * - title: The title of the test
214 * - ocand_cnt,
215 * ocand Additional candidates to be added to offerer
216 * - acand_cnt,
217 * acand Additional candidates to be added to answerer
218 *
Benny Prijonofd7f1472007-03-22 11:59:03 +0000219 * The additional candidates are normally invalid candidates, meaning
220 * they won't be reachable by the agents. They are used to "confuse"
Benny Prijono2532b9d2007-03-22 01:16:37 +0000221 * ICE processing.
222 */
223static int perform_ice_test(const char *title,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000224 pj_bool_t expected_success,
225 unsigned comp_cnt,
226 pj_bool_t add_valid_comp,
Benny Prijonofd7f1472007-03-22 11:59:03 +0000227 unsigned wait_before_send,
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000228 unsigned max_total_time,
229 unsigned ocand_cnt,
230 struct dummy_cand ocand[],
231 unsigned acand_cnt,
232 struct dummy_cand acand[])
Benny Prijonofb9d9872007-03-21 22:05:58 +0000233{
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000234 pj_ice_strans *im1, *im2;
235 pj_ice_strans_cb icest_cb;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000236 struct ice_data *id1, *id2;
Benny Prijono2532b9d2007-03-22 01:16:37 +0000237 pj_timestamp t_start, t_end;
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000238 unsigned i;
Benny Prijonofd7f1472007-03-22 11:59:03 +0000239 pj_str_t data_from_offerer, data_from_answerer;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000240 pj_status_t status;
241
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000242#define CHECK_COMPLETE() if (id1->complete && id2->complete) { \
243 if (t_end.u32.lo==0) pj_get_timestamp(&t_end); \
244 } else {}
245
Benny Prijono2532b9d2007-03-22 01:16:37 +0000246 PJ_LOG(3,(THIS_FILE, "...%s", title));
Benny Prijonofb9d9872007-03-21 22:05:58 +0000247
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000248 pj_bzero(&t_end, sizeof(t_end));
249
Benny Prijonoff49ab72007-03-22 21:00:53 +0000250 pj_bzero(&icest_cb, sizeof(icest_cb));
251 icest_cb.on_ice_complete = &on_ice_complete;
252 icest_cb.on_rx_data = &on_rx_data;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000253
254 /* Create first ICE */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000255 status = pj_ice_strans_create(&stun_cfg, "offerer", comp_cnt, NULL, &icest_cb, &im1);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000256 if (status != PJ_SUCCESS)
257 return -20;
258
259 id1 = PJ_POOL_ZALLOC_T(im1->pool, struct ice_data);
Benny Prijono2532b9d2007-03-22 01:16:37 +0000260 id1->obj_name = "offerer";
Benny Prijonofb9d9872007-03-21 22:05:58 +0000261 im1->user_data = id1;
262
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000263 /* Init components */
264 status = init_ice_st(im1, add_valid_comp, ocand_cnt, ocand);
265 if (status != 0)
266 return status;
Benny Prijono2532b9d2007-03-22 01:16:37 +0000267
Benny Prijonofb9d9872007-03-21 22:05:58 +0000268 /* Create second ICE */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000269 status = pj_ice_strans_create(&stun_cfg, "answerer", comp_cnt, NULL, &icest_cb, &im2);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000270 if (status != PJ_SUCCESS)
271 return -25;
272
273 id2 = PJ_POOL_ZALLOC_T(im2->pool, struct ice_data);
Benny Prijono2532b9d2007-03-22 01:16:37 +0000274 id2->obj_name = "answerer";
Benny Prijonofb9d9872007-03-21 22:05:58 +0000275 im2->user_data = id2;
276
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000277 /* Init components */
278 status = init_ice_st(im2, add_valid_comp, acand_cnt, acand);
279 if (status != 0)
280 return status;
Benny Prijono2532b9d2007-03-22 01:16:37 +0000281
Benny Prijonofb9d9872007-03-21 22:05:58 +0000282
Benny Prijonoff49ab72007-03-22 21:00:53 +0000283 /* Init ICE on im1 */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000284 status = pj_ice_strans_init_ice(im1, PJ_ICE_SESS_ROLE_CONTROLLING, NULL, NULL);
Benny Prijonoff49ab72007-03-22 21:00:53 +0000285 if (status != PJ_SUCCESS)
286 return -29;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000287
Benny Prijonoff49ab72007-03-22 21:00:53 +0000288 /* Init ICE on im2 */
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000289 status = pj_ice_strans_init_ice(im2, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
Benny Prijonoff49ab72007-03-22 21:00:53 +0000290 if (status != PJ_SUCCESS)
291 return -29;
292
293 /* Start ICE on im2 */
294 status = start_ice(im2, im1);
Benny Prijono1c064e62007-05-22 21:11:10 +0000295 if (status != PJ_SUCCESS) {
296 app_perror(" error starting ICE", status);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000297 return -30;
Benny Prijono1c064e62007-05-22 21:11:10 +0000298 }
Benny Prijonofb9d9872007-03-21 22:05:58 +0000299
Benny Prijonoff49ab72007-03-22 21:00:53 +0000300 /* Start ICE on im1 */
301 status = start_ice(im1, im2);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000302 if (status != PJ_SUCCESS)
303 return -35;
304
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000305 /* Apply delay to let other checks commence */
306 pj_thread_sleep(40);
307
Benny Prijono2532b9d2007-03-22 01:16:37 +0000308 /* Mark start time */
309 pj_get_timestamp(&t_start);
310
Benny Prijonofd7f1472007-03-22 11:59:03 +0000311 /* Poll for wait_before_send msecs before we send the first data */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000312 if (expected_success) {
313 for (;;) {
314 pj_timestamp t_now;
Benny Prijonofd7f1472007-03-22 11:59:03 +0000315
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000316 handle_events(1);
Benny Prijonofd7f1472007-03-22 11:59:03 +0000317
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000318 CHECK_COMPLETE();
319
320 pj_get_timestamp(&t_now);
321 if (pj_elapsed_msec(&t_start, &t_now) >= wait_before_send)
322 break;
323 }
324
325 /* Send data. It must be successful! */
326 data_from_offerer = pj_str("from offerer");
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000327 status = pj_ice_sess_send_data(im1->ice, 1, data_from_offerer.ptr, data_from_offerer.slen);
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000328 if (status != PJ_SUCCESS)
329 return -47;
330
331 data_from_answerer = pj_str("from answerer");
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000332 status = pj_ice_sess_send_data(im2->ice, 1, data_from_answerer.ptr, data_from_answerer.slen);
Benny Prijono1c064e62007-05-22 21:11:10 +0000333 if (status != PJ_SUCCESS) {
334 app_perror(" error sending packet", status);
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000335 return -48;
Benny Prijono1c064e62007-05-22 21:11:10 +0000336 }
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000337
338 /* Poll to allow data to be received */
339 for (;;) {
340 pj_timestamp t_now;
341 handle_events(1);
342 CHECK_COMPLETE();
343 pj_get_timestamp(&t_now);
344 if (pj_elapsed_msec(&t_start, &t_now) >= (wait_before_send + 200))
345 break;
346 }
Benny Prijonofd7f1472007-03-22 11:59:03 +0000347 }
348
Benny Prijonofb9d9872007-03-21 22:05:58 +0000349 /* Just wait until both completes, or timed out */
Benny Prijono2532b9d2007-03-22 01:16:37 +0000350 while (!id1->complete || !id2->complete) {
351 pj_timestamp t_now;
352
Benny Prijonofb9d9872007-03-21 22:05:58 +0000353 handle_events(1);
354
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000355 CHECK_COMPLETE();
Benny Prijono2532b9d2007-03-22 01:16:37 +0000356 pj_get_timestamp(&t_now);
Benny Prijonofd7f1472007-03-22 11:59:03 +0000357 if (pj_elapsed_msec(&t_start, &t_now) >= max_total_time) {
Benny Prijono2532b9d2007-03-22 01:16:37 +0000358 PJ_LOG(3,(THIS_FILE, "....error: timed-out"));
359 return -50;
360 }
361 }
Benny Prijonofb9d9872007-03-21 22:05:58 +0000362
Benny Prijono2532b9d2007-03-22 01:16:37 +0000363 /* Mark end-time */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000364 CHECK_COMPLETE();
365
366 /* If expected to fail, then just check that both fail */
367 if (!expected_success) {
368 /* Check status */
369 if (id1->err_code == PJ_SUCCESS)
370 return -51;
371 if (id2->err_code == PJ_SUCCESS)
372 return -52;
373 goto on_return;
374 }
Benny Prijono2532b9d2007-03-22 01:16:37 +0000375
376 /* Check status */
377 if (id1->err_code != PJ_SUCCESS)
378 return -53;
379 if (id2->err_code != PJ_SUCCESS)
380 return -56;
381
382 /* Verify that offerer gets answerer's transport address */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000383 for (i=0; i<comp_cnt; ++i) {
384 status = verify_address(im1, im2, i+1);
385 if (status != 0)
386 return status;
Benny Prijono2532b9d2007-03-22 01:16:37 +0000387 }
388
389 /* And the other way around */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000390 for (i=0; i<comp_cnt; ++i) {
391 status = verify_address(im2, im1, i+1);
392 if (status != 0)
393 return status;
Benny Prijono2532b9d2007-03-22 01:16:37 +0000394 }
395
Benny Prijonofd7f1472007-03-22 11:59:03 +0000396 /* Check that data is received in offerer */
397 if (id1->rx_rtp_cnt != 1) {
398 PJ_LOG(3,(THIS_FILE, "....error: data not received in offerer"));
399 return -80;
400 }
401 if (pj_strcmp2(&data_from_answerer, id1->last_rx_rtp_data) != 0) {
402 PJ_LOG(3,(THIS_FILE, "....error: data mismatch in offerer"));
403 return -82;
404 }
405
406 /* And the same in answerer */
407 if (id2->rx_rtp_cnt != 1) {
408 PJ_LOG(3,(THIS_FILE, "....error: data not received in answerer"));
409 return -84;
410 }
411 if (pj_strcmp2(&data_from_offerer, id2->last_rx_rtp_data) != 0) {
412 PJ_LOG(3,(THIS_FILE, "....error: data mismatch in answerer"));
413 return -82;
414 }
415
416
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000417on_return:
418
Benny Prijono2532b9d2007-03-22 01:16:37 +0000419 /* Done */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000420 PJ_LOG(3,(THIS_FILE, "....success: ICE completed in %d msec, waiting..",
Benny Prijono2532b9d2007-03-22 01:16:37 +0000421 pj_elapsed_msec(&t_start, &t_end)));
422
423 /* Wait for some more time */
Benny Prijono2532b9d2007-03-22 01:16:37 +0000424 for (;;) {
425 pj_timestamp t_now;
426
427 pj_get_timestamp(&t_now);
Benny Prijonofd7f1472007-03-22 11:59:03 +0000428 if (pj_elapsed_msec(&t_start, &t_now) > max_total_time)
Benny Prijono2532b9d2007-03-22 01:16:37 +0000429 break;
430
431 handle_events(1);
432 }
433
434
Benny Prijonoa6bd7582007-03-28 15:49:48 +0000435 pj_ice_strans_destroy(im1);
436 pj_ice_strans_destroy(im2);
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000437 handle_events(100);
Benny Prijono2532b9d2007-03-22 01:16:37 +0000438 return 0;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000439}
440
441
442int ice_test(void)
443{
444 int rc = 0;
445 pj_pool_t *pool;
446 pj_ioqueue_t *ioqueue;
447 pj_timer_heap_t *timer_heap;
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000448 enum { D1=500, D2=5000, D3=15000 };
449 struct dummy_cand ocand[] =
450 {
451 {1, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65534 },
452 {2, PJ_ICE_CAND_TYPE_SRFLX, "127.1.1.1", 65535 },
453 };
454 struct dummy_cand acand[] =
455 {
456 {1, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65534 },
457 {2, PJ_ICE_CAND_TYPE_SRFLX, "127.2.2.2", 65535 },
458 };
Benny Prijono2532b9d2007-03-22 01:16:37 +0000459
Benny Prijonofb9d9872007-03-21 22:05:58 +0000460 pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
461 pj_ioqueue_create(pool, 12, &ioqueue);
462 pj_timer_heap_create(pool, 100, &timer_heap);
463
464 pj_stun_config_init(&stun_cfg, mem, 0, ioqueue, timer_heap);
465
Benny Prijono0cb7bf12007-04-02 18:00:45 +0000466#if 0
Benny Prijonofd70c9b2007-03-27 11:00:38 +0000467 pj_log_set_level(5);
468#endif
469
Benny Prijono0cb7bf12007-04-02 18:00:45 +0000470 //goto test;
Benny Prijonofb9d9872007-03-21 22:05:58 +0000471
Benny Prijono2532b9d2007-03-22 01:16:37 +0000472 /* Basic create/destroy */
Benny Prijonofb9d9872007-03-21 22:05:58 +0000473 rc = ice_basic_create_destroy_test();
474 if (rc != 0)
475 goto on_return;
476
Benny Prijono2532b9d2007-03-22 01:16:37 +0000477 /* Direct communication */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000478 rc = perform_ice_test("Simple test (1 component)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 0, NULL, 0, NULL);
479 if (rc != 0)
480 goto on_return;
481
482 /* Failure case (all checks fail) */
Benny Prijono1c064e62007-05-22 21:11:10 +0000483#if 0
484 /* Cannot just add an SRFLX candidate; it needs a base */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000485 rc = perform_ice_test("Failure case (all checks fail)", PJ_FALSE, 1, PJ_FALSE, D3, D3, 1, ocand, 1, acand);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000486 if (rc != 0)
487 goto on_return;
Benny Prijono1c064e62007-05-22 21:11:10 +0000488#endif
Benny Prijonofb9d9872007-03-21 22:05:58 +0000489
Benny Prijono2532b9d2007-03-22 01:16:37 +0000490 /* Direct communication with invalid address */
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000491 rc = perform_ice_test("With 1 unreachable address", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 0, NULL);
492 if (rc != 0)
493 goto on_return;
494
495 /* Direct communication with invalid address */
496 rc = perform_ice_test("With 2 unreachable addresses (one each)", PJ_TRUE, 1, PJ_TRUE, D1, D2, 1, ocand, 1, acand);
Benny Prijono2532b9d2007-03-22 01:16:37 +0000497 if (rc != 0)
498 goto on_return;
499
Benny Prijonofd7f1472007-03-22 11:59:03 +0000500 /* Direct communication with two components */
Benny Prijono0cb7bf12007-04-02 18:00:45 +0000501//test:
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000502 rc = perform_ice_test("With two components (RTP and RTCP)", PJ_TRUE, 2, PJ_TRUE, D1, D2, 0, NULL, 0, NULL);
503 if (rc != 0)
504 goto on_return;
505
Benny Prijonofd70c9b2007-03-27 11:00:38 +0000506 goto on_return;
507
Benny Prijono7e0d52c2007-03-26 13:25:07 +0000508 /* Direct communication with mismatch number of components */
509
510 /* Direct communication with 2 components and 2 invalid address */
511 rc = perform_ice_test("With 2 two components and 2 unreachable address", PJ_TRUE, 2, PJ_TRUE, D1, D2, 1, ocand, 1, acand);
Benny Prijonofd7f1472007-03-22 11:59:03 +0000512 if (rc != 0)
513 goto on_return;
514
515
Benny Prijono2532b9d2007-03-22 01:16:37 +0000516
Benny Prijonofb9d9872007-03-21 22:05:58 +0000517on_return:
Benny Prijonofd70c9b2007-03-27 11:00:38 +0000518 pj_log_set_level(3);
Benny Prijonofb9d9872007-03-21 22:05:58 +0000519 pj_ioqueue_destroy(stun_cfg.ioqueue);
520 pj_pool_release(pool);
521 return rc;
522}
523