blob: 182269cd2c805e60ad47edd53cff8b0f130c95c7 [file] [log] [blame]
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 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
20#include "test.h"
21#include <pjsip_core.h>
22#include <pjlib.h>
23
Benny Prijono85598d92006-01-07 18:44:25 +000024#define THIS_FILE "tsx_uac_test.c"
25
26
Benny Prijonofa73e3e2006-01-05 23:35:46 +000027/*****************************************************************************
28 **
Benny Prijono85598d92006-01-07 18:44:25 +000029 ** UAC tests.
Benny Prijonofa73e3e2006-01-05 23:35:46 +000030 **
Benny Prijono85598d92006-01-07 18:44:25 +000031 ** This file performs various tests for UAC transactions. Each test will have
32 ** a different Via branch param so that message receiver module and
33 ** transaction user module can identify which test is being carried out.
Benny Prijonofa73e3e2006-01-05 23:35:46 +000034 **
Benny Prijono85598d92006-01-07 18:44:25 +000035 ** TEST1_BRANCH_ID
36 ** Perform basic retransmission and timeout test. Message receiver will
37 ** verify that retransmission is received at correct time.
38 ** This test verifies the following requirements:
39 ** - retransmit timer doubles for INVITE
40 ** - retransmit timer doubles and caps off for non-INVITE
41 ** - retransmit timer timer is precise
42 ** - correct timeout and retransmission count
43 ** Requirements not tested:
44 ** - retransmit timer only starts after resolving has completed.
45 **
46 ** TEST2_BRANCH_ID
47 ** Test scenario where resolver is unable to resolve destination host.
48 **
49 ** TEST3_BRANCH_ID
50 ** Test scenario where transaction is terminated while resolver is still
51 ** running.
52 **
53 ** TEST4_BRANCH_ID
54 ** Test scenario where transport failed after several retransmissions.
55 **
56 ** TEST5_BRANCH_ID
57 ** Test scenario where transaction is terminated by user after several
58 ** retransmissions.
59 **
60 ** TEST6_BRANCH_ID
61 ** Test successfull non-INVITE transaction.
62 ** It tests the following requirements:
63 ** - transaction correctly moves to COMPLETED state.
64 ** - retransmission must cease.
65 ** - tx_data must be maintained until state is terminated.
66 **
67 ** TEST7_BRANCH_ID
68 ** Test successfull non-INVITE transaction, with provisional response.
69 **
70 ** TEST8_BRANCH_ID
71 ** Test failed INVITE transaction (e.g. ACK must be received)
72 **
73 ** TEST9_BRANCH_ID
74 ** Test failed INVITE transaction with provisional response.
75 **
76 **
Benny Prijonofa73e3e2006-01-05 23:35:46 +000077 *****************************************************************************
78 */
79
Benny Prijonodbe337a2006-01-08 23:57:52 +000080static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test1";
81static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test2";
82static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test3";
83static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test4";
84static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test5";
85static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test6";
86static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test7";
87static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test8";
88static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test9";
Benny Prijono85598d92006-01-07 18:44:25 +000089
90#define TEST1_ALLOWED_DIFF (150)
91#define TEST4_RETRANSMIT_CNT 3
92#define TEST5_RETRANSMIT_CNT 3
93
94
Benny Prijonofa73e3e2006-01-05 23:35:46 +000095static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
96static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata);
97
98/* UAC transaction user module. */
99static pjsip_module tsx_user =
100{
101 NULL, NULL, /* prev and next */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000102 { "Tsx-UAC-User", 12}, /* Name. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000103 -1, /* Id */
104 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
105 NULL, /* User data. */
106 0, /* Number of methods supported (=0). */
107 { 0 }, /* Array of methods (none) */
108 NULL, /* load() */
109 NULL, /* start() */
110 NULL, /* stop() */
111 NULL, /* unload() */
112 NULL, /* on_rx_request() */
113 NULL, /* on_rx_response() */
Benny Prijono85598d92006-01-07 18:44:25 +0000114 NULL, /* on_tx_request() */
115 NULL, /* on_tx_response() */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000116 &tsx_user_on_tsx_state, /* on_tsx_state() */
117};
118
119/* Module to receive the loop-backed request. */
120static pjsip_module msg_receiver =
121{
122 NULL, NULL, /* prev and next */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000123 { "Msg-Receiver", 12}, /* Name. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000124 -1, /* Id */
125 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
126 NULL, /* User data. */
127 0, /* Number of methods supported (=0). */
128 { 0 }, /* Array of methods (none) */
129 NULL, /* load() */
130 NULL, /* start() */
131 NULL, /* stop() */
132 NULL, /* unload() */
133 &msg_receiver_on_rx_request, /* on_rx_request() */
134 NULL, /* on_rx_response() */
Benny Prijono85598d92006-01-07 18:44:25 +0000135 NULL, /* on_tx_request() */
136 NULL, /* on_tx_response() */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000137 NULL, /* on_tsx_state() */
138};
139
Benny Prijono85598d92006-01-07 18:44:25 +0000140/* Static vars, which will be reset on each test. */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000141static int recv_count;
142static pj_time_val recv_last;
143static pj_bool_t test_complete;
144
Benny Prijono85598d92006-01-07 18:44:25 +0000145/* Loop transport instance. */
146static pjsip_transport *loop;
147
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000148/* General timer entry to be used by tests. */
149static pj_timer_entry timer;
150
Benny Prijono85598d92006-01-07 18:44:25 +0000151/*
152 * This is the handler to receive state changed notification from the
153 * transaction. It is used to verify that the transaction behaves according
154 * to the test scenario.
155 */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000156static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
157{
Benny Prijono85598d92006-01-07 18:44:25 +0000158 if (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0) {
159 /*
160 * Transaction with TEST1_BRANCH_ID should terminate with transaction
161 * timeout status.
162 */
163 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
164
165 if (test_complete == 0)
166 test_complete = 1;
167
168 /* Test the status code. */
169 if (tsx->status_code != PJSIP_SC_TSX_TIMEOUT) {
170 PJ_LOG(3,(THIS_FILE,
171 " error: status code is %d instead of %d",
172 tsx->status_code, PJSIP_SC_TSX_TIMEOUT));
173 test_complete = -710;
174 }
175 }
176
177 } else if (pj_strcmp2(&tsx->branch, TEST2_BRANCH_ID)==0) {
178 /*
179 * Transaction with TEST2_BRANCH_ID should terminate with transport error.
180 */
181 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
182
183 /* Test the status code. */
184 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
185 PJ_LOG(3,(THIS_FILE,
186 " error: status code is %d instead of %d",
187 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR));
188 test_complete = -720;
189 }
190
191 if (test_complete == 0)
192 test_complete = 1;
193 }
194
195 } else if (pj_strcmp2(&tsx->branch, TEST3_BRANCH_ID)==0) {
196 /*
197 * This test terminates the transaction while resolver is still
198 * running.
199 */
200 if (tsx->state == PJSIP_TSX_STATE_CALLING) {
201
202 /* Terminate the transaction. */
203 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
204
205 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
206
207 /* Check if status code is correct. */
208 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
209 PJ_LOG(3,(THIS_FILE,
210 " error: status code is %d instead of %d",
211 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
212 test_complete = -730;
213 }
214
215 if (test_complete == 0)
216 test_complete = 1;
217
218 }
219
220 } else if (pj_strcmp2(&tsx->branch, TEST4_BRANCH_ID)==0) {
221 /*
222 * This test simulates transport failure after several
223 * retransmissions.
224 */
225 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
226
227 /* Status code must be transport error. */
228 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
229 PJ_LOG(3,(THIS_FILE,
230 " error: status code is %d instead of %d",
231 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR));
232 test_complete = -730;
233 }
234
235 /* Must have correct retransmission count. */
236 if (tsx->retransmit_count != TEST4_RETRANSMIT_CNT) {
237 PJ_LOG(3,(THIS_FILE,
238 " error: retransmit cnt is %d instead of %d",
239 tsx->retransmit_count, TEST4_RETRANSMIT_CNT));
240 test_complete = -731;
241 }
242
243 if (test_complete == 0)
244 test_complete = 1;
245 }
246
247
248 } else if (pj_strcmp2(&tsx->branch, TEST5_BRANCH_ID)==0) {
249 /*
250 * This test simulates transport failure after several
251 * retransmissions.
252 */
253 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
254
255 /* Status code must be PJSIP_SC_REQUEST_TERMINATED. */
256 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
257 PJ_LOG(3,(THIS_FILE,
258 " error: status code is %d instead of %d",
259 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
260 test_complete = -733;
261 }
262
263 /* Must have correct retransmission count. */
264 if (tsx->retransmit_count != TEST5_RETRANSMIT_CNT) {
265 PJ_LOG(3,(THIS_FILE,
266 " error: retransmit cnt is %d instead of %d",
267 tsx->retransmit_count, TEST5_RETRANSMIT_CNT));
268 test_complete = -734;
269 }
270
271 if (test_complete == 0)
272 test_complete = 1;
273 }
274
275
276 } else if (pj_strcmp2(&tsx->branch, TEST6_BRANCH_ID)==0) {
277 /*
278 * Successfull non-INVITE transaction.
279 */
280 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
281
282 /* Status code must be 202. */
283 if (tsx->status_code != 202) {
284 PJ_LOG(3,(THIS_FILE,
285 " error: status code is %d instead of %d",
286 tsx->status_code, 202));
287 test_complete = -736;
288 }
289
290 /* Must have correct retransmission count. */
291 if (tsx->retransmit_count != 0) {
292 PJ_LOG(3,(THIS_FILE,
293 " error: retransmit cnt is %d instead of %d",
294 tsx->retransmit_count, 0));
295 test_complete = -737;
296 }
297
298 /* Must still keep last_tx */
299 if (tsx->last_tx == NULL) {
300 PJ_LOG(3,(THIS_FILE,
301 " error: transaction lost last_tx"));
302 test_complete = -738;
303 }
304
305 if (test_complete == 0) {
306 test_complete = 1;
307 pjsip_tsx_terminate(tsx, 202);
308 }
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000309
310 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
311
312 /* Previous state must be COMPLETED. */
313 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
314 test_complete = -7381;
315 }
316
Benny Prijono85598d92006-01-07 18:44:25 +0000317 }
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000318
319 } else if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID)==0) {
320 /*
321 * Successfull non-INVITE transaction.
322 */
323 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
324
325 /* Check prev state. */
326 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
327 PJ_LOG(3,(THIS_FILE,
328 " error: prev state is %s instead of %s",
329 pjsip_tsx_state_str(e->body.tsx_state.prev_state),
330 pjsip_tsx_state_str(PJSIP_TSX_STATE_PROCEEDING)));
331 test_complete = -739;
332 }
333
334 /* Status code must be 202. */
335 if (tsx->status_code != 202) {
336 PJ_LOG(3,(THIS_FILE,
337 " error: status code is %d instead of %d",
338 tsx->status_code, 202));
339 test_complete = -740;
340 }
341
342 /* Must have correct retransmission count. */
343 if (tsx->retransmit_count != 0) {
344 PJ_LOG(3,(THIS_FILE,
345 " error: retransmit cnt is %d instead of %d",
346 tsx->retransmit_count, 0));
347 test_complete = -741;
348 }
349
350 /* Must still keep last_tx */
351 if (tsx->last_tx == NULL) {
352 PJ_LOG(3,(THIS_FILE,
353 " error: transaction lost last_tx"));
354 test_complete = -741;
355 }
356
357 if (test_complete == 0) {
358 test_complete = 1;
359 pjsip_tsx_terminate(tsx, 202);
360 }
361
362 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
363
364 /* Previous state must be COMPLETED. */
365 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
366 test_complete = -742;
367 }
368
369 }
370
371
372 } else if (pj_strcmp2(&tsx->branch, TEST8_BRANCH_ID)==0) {
373 /*
374 * Failed INVITE transaction.
375 */
376 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
377
378 /* Status code must be 301. */
379 if (tsx->status_code != 301) {
380 PJ_LOG(3,(THIS_FILE,
381 " error: status code is %d instead of %d",
382 tsx->status_code, 301));
383 test_complete = -745;
384 }
385
386 /* Must have correct retransmission count. */
387 if (tsx->retransmit_count != 0) {
388 PJ_LOG(3,(THIS_FILE,
389 " error: retransmit cnt is %d instead of %d",
390 tsx->retransmit_count, 0));
391 test_complete = -746;
392 }
393
394 /* Must still keep last_tx */
395 if (tsx->last_tx == NULL) {
396 PJ_LOG(3,(THIS_FILE,
397 " error: transaction lost last_tx"));
398 test_complete = -747;
399 }
400
401 /* last_tx is ACK in this case. */
402 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
403 PJSIP_ACK_METHOD)
404 {
405 PJ_LOG(3,(THIS_FILE,
406 " error: last_tx is not ACK"));
407 test_complete = -748;
408 }
409 }
410 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
411
412 test_complete = 1;
413
414 /* Previous state must be COMPLETED. */
415 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
416 test_complete = -750;
417 }
418
419 /* Status code must be 301. */
420 if (tsx->status_code != 301) {
421 PJ_LOG(3,(THIS_FILE,
422 " error: status code is %d instead of %d",
423 tsx->status_code, 301));
424 test_complete = -751;
425 }
426
427 }
428
429
430 } else if (pj_strcmp2(&tsx->branch, TEST9_BRANCH_ID)==0) {
431 /*
432 * Failed INVITE transaction with provisional response.
433 */
434 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
435
436 /* Previous state must be PJSIP_TSX_STATE_PROCEEDING. */
437 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
438 test_complete = -760;
439 }
440
441 /* Status code must be 302. */
442 if (tsx->status_code != 302) {
443 PJ_LOG(3,(THIS_FILE,
444 " error: status code is %d instead of %d",
445 tsx->status_code, 302));
446 test_complete = -761;
447 }
448
449 /* Must have correct retransmission count. */
450 if (tsx->retransmit_count != 0) {
451 PJ_LOG(3,(THIS_FILE,
452 " error: retransmit cnt is %d instead of %d",
453 tsx->retransmit_count, 0));
454 test_complete = -762;
455 }
456
457 /* Must still keep last_tx */
458 if (tsx->last_tx == NULL) {
459 PJ_LOG(3,(THIS_FILE,
460 " error: transaction lost last_tx"));
461 test_complete = -763;
462 }
463
464 /* last_tx is ACK in this case. */
465 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
466 PJSIP_ACK_METHOD)
467 {
468 PJ_LOG(3,(THIS_FILE,
469 " error: last_tx is not ACK"));
470 test_complete = -764;
471 }
472
473 }
474 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
475
476 test_complete = 1;
477
478 /* Previous state must be COMPLETED. */
479 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
480 test_complete = -767;
481 }
482
483 /* Status code must be 302. */
484 if (tsx->status_code != 302) {
485 PJ_LOG(3,(THIS_FILE,
486 " error: status code is %d instead of %d",
487 tsx->status_code, 302));
488 test_complete = -768;
489 }
490
491 }
492
Benny Prijono85598d92006-01-07 18:44:25 +0000493 }
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000494}
495
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000496/*
497 * This timer callback is called to send delayed response.
498 */
499struct response
500{
501 pjsip_response_addr res_addr;
502 pjsip_tx_data *tdata;
503};
504
505static void send_response_callback( pj_timer_heap_t *timer_heap,
506 struct pj_timer_entry *entry)
507{
508 struct response *r = entry->user_data;
509 pjsip_transport *tp = r->res_addr.transport;
510
511 pjsip_endpt_send_response(endpt, &r->res_addr, r->tdata, NULL, NULL);
512 if (tp)
513 pjsip_transport_dec_ref(tp);
514}
515
516/* Timer callback to terminate a transaction. */
517static void terminate_tsx_callback( pj_timer_heap_t *timer_heap,
518 struct pj_timer_entry *entry)
519{
520 pjsip_transaction *tsx = entry->user_data;
521 int status_code = entry->id;
522
523 if (tsx) {
524 pjsip_tsx_terminate(tsx, status_code);
525 }
526}
527
528
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000529#define DIFF(a,b) ((a<b) ? (b-a) : (a-b))
530
Benny Prijono85598d92006-01-07 18:44:25 +0000531/*
532 * This is the handler to receive message for this test. It is used to
533 * control and verify the behavior of the message transmitted by the
534 * transaction.
535 */
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000536static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata)
537{
Benny Prijono85598d92006-01-07 18:44:25 +0000538 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST1_BRANCH_ID) == 0) {
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000539 /*
Benny Prijono85598d92006-01-07 18:44:25 +0000540 * The TEST1_BRANCH_ID test performs the verifications for transaction
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000541 * retransmission mechanism. It will not answer the incoming request
542 * with any response.
543 */
544 pjsip_msg *msg = rdata->msg_info.msg;
545
Benny Prijono85598d92006-01-07 18:44:25 +0000546 PJ_LOG(4,(THIS_FILE, " received request"));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000547
548 /* Only wants to take INVITE or OPTIONS method. */
549 if (msg->line.req.method.id != PJSIP_INVITE_METHOD &&
550 msg->line.req.method.id != PJSIP_OPTIONS_METHOD)
551 {
Benny Prijono85598d92006-01-07 18:44:25 +0000552 PJ_LOG(3,(THIS_FILE, " error: received unexpected method %.*s",
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000553 msg->line.req.method.name.slen,
554 msg->line.req.method.name.ptr));
555 test_complete = -600;
556 return PJ_TRUE;
557 }
558
559 if (recv_count == 0) {
560 recv_count++;
Benny Prijono85598d92006-01-07 18:44:25 +0000561 //pj_gettimeofday(&recv_last);
562 recv_last = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000563 } else {
564 pj_time_val now;
565 unsigned msec_expected, msec_elapsed;
Benny Prijono85598d92006-01-07 18:44:25 +0000566 int max_received;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000567
Benny Prijono85598d92006-01-07 18:44:25 +0000568 //pj_gettimeofday(&now);
569 now = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000570 PJ_TIME_VAL_SUB(now, recv_last);
571 msec_elapsed = now.sec*1000 + now.msec;
572
573 ++recv_count;
574 msec_expected = (1<<(recv_count-2))*PJSIP_T1_TIMEOUT;
575
576 if (msg->line.req.method.id != PJSIP_INVITE_METHOD) {
577 if (msec_expected > PJSIP_T2_TIMEOUT)
578 msec_expected = PJSIP_T2_TIMEOUT;
Benny Prijono85598d92006-01-07 18:44:25 +0000579 max_received = 11;
580 } else {
581 max_received = 7;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000582 }
583
Benny Prijono85598d92006-01-07 18:44:25 +0000584 if (DIFF(msec_expected, msec_elapsed) > TEST1_ALLOWED_DIFF) {
585 PJ_LOG(3,(THIS_FILE,
586 " error: expecting retransmission no. %d in %d "
587 "ms, received in %d ms",
588 recv_count-1, msec_expected, msec_elapsed));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000589 test_complete = -610;
590 }
591
Benny Prijono85598d92006-01-07 18:44:25 +0000592
593 if (recv_count > max_received) {
594 PJ_LOG(3,(THIS_FILE,
595 " error: too many messages (%d) received",
596 recv_count));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000597 test_complete = -620;
598 }
599
Benny Prijono85598d92006-01-07 18:44:25 +0000600 //pj_gettimeofday(&recv_last);
601 recv_last = rdata->pkt_info.timestamp;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000602 }
603 return PJ_TRUE;
Benny Prijono85598d92006-01-07 18:44:25 +0000604
605 } else
606 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST4_BRANCH_ID) == 0) {
607 /*
608 * The TEST4_BRANCH_ID test simulates transport failure after several
609 * retransmissions.
610 */
611 recv_count++;
612
613 if (recv_count == TEST4_RETRANSMIT_CNT) {
614 /* Simulate transport failure. */
615 pjsip_loop_set_failure(loop, 2, NULL);
616
617 } else if (recv_count > TEST4_RETRANSMIT_CNT) {
618 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
619 recv_count));
620 test_complete = -631;
621 }
622
623 return PJ_TRUE;
624
625
626 } else
627 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST5_BRANCH_ID) == 0) {
628 /*
629 * The TEST5_BRANCH_ID test simulates user terminating the transaction
630 * after several retransmissions.
631 */
632 recv_count++;
633
634 if (recv_count == TEST5_RETRANSMIT_CNT+1) {
635 pj_str_t key;
636 pjsip_transaction *tsx;
637
638 pjsip_tsx_create_key( rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,
639 &rdata->msg_info.msg->line.req.method, rdata);
640 tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
641 if (tsx) {
642 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
643 pj_mutex_unlock(tsx->mutex);
644 } else {
645 PJ_LOG(3,(THIS_FILE, " error: uac transaction not found!"));
646 test_complete = -633;
647 }
648
649 } else if (recv_count > TEST5_RETRANSMIT_CNT+1) {
650 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
651 recv_count));
652 test_complete = -634;
653 }
654
655 return PJ_TRUE;
656
657 } else
658 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) {
659 /*
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000660 * The TEST6_BRANCH_ID test successfull non-INVITE transaction.
Benny Prijono85598d92006-01-07 18:44:25 +0000661 */
Benny Prijono85598d92006-01-07 18:44:25 +0000662 pj_status_t status;
663
664 recv_count++;
665
666 if (recv_count > 1) {
667 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
668 recv_count));
669 test_complete = -635;
670 }
671
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000672 status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL,
673 NULL, NULL);
Benny Prijono85598d92006-01-07 18:44:25 +0000674 if (status != PJ_SUCCESS) {
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000675 app_perror(" error: unable to send response", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000676 test_complete = -636;
677 }
678
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000679 return PJ_TRUE;
680
681
682 } else
683 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) {
684 /*
685 * The TEST7_BRANCH_ID test successfull non-INVITE transaction
686 * with provisional response.
687 */
688 pj_status_t status;
689 pjsip_response_addr res_addr;
690 struct response *r;
691 pjsip_tx_data *tdata;
692 pj_time_val delay = { 2, 0 };
693
694 recv_count++;
695
696 if (recv_count > 1) {
697 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
698 recv_count));
699 test_complete = -640;
700 return PJ_TRUE;
Benny Prijono85598d92006-01-07 18:44:25 +0000701 }
702
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000703 /* Respond with provisional response */
704 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata);
705 pj_assert(status == PJ_SUCCESS);
706
707 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
708 pj_assert(status == PJ_SUCCESS);
709
710 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
711 NULL, NULL);
712 pj_assert(status == PJ_SUCCESS);
713
714 /* Create the final response. */
715 status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata);
716 pj_assert(status == PJ_SUCCESS);
717
718 /* Schedule sending final response in couple of of secs. */
719 r = pj_pool_alloc(tdata->pool, sizeof(*r));
720 r->res_addr = res_addr;
721 r->tdata = tdata;
722 if (r->res_addr.transport)
723 pjsip_transport_add_ref(r->res_addr.transport);
724
725 timer.cb = &send_response_callback;
726 timer.user_data = r;
727 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
728
729 return PJ_TRUE;
730
731
732 } else
733 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) {
734 /*
735 * The TEST8_BRANCH_ID test failed INVITE transaction.
736 */
737 pjsip_method *method;
738 pj_status_t status;
739
740 method = &rdata->msg_info.msg->line.req.method;
741
742 recv_count++;
743
744 if (method->id == PJSIP_INVITE_METHOD) {
745
746 if (recv_count > 1) {
747 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
748 recv_count));
749 test_complete = -635;
750 }
751
752 status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL,
753 NULL, NULL);
754 if (status != PJ_SUCCESS) {
755 app_perror(" error: unable to send response", status);
756 test_complete = -636;
757 }
758
759 } else if (method->id == PJSIP_ACK_METHOD) {
760
761 if (recv_count == 2) {
762 pj_str_t key;
763 pj_time_val delay = { 5, 0 };
764
765 /* Schedule timer to destroy transaction after 5 seconds.
766 * This is to make sure that transaction does not
767 * retransmit ACK.
768 */
769 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
770 PJSIP_ROLE_UAC, &pjsip_invite_method,
771 rdata);
772
773 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);
774 timer.id = 301;
775 timer.cb = &terminate_tsx_callback;
776
777 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
778 }
779
780 if (recv_count > 2) {
781 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
782 recv_count));
783 test_complete = -638;
784 }
785
786
787 } else {
788 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
789 pjsip_rx_data_get_info(rdata)));
790 test_complete = -639;
791
792 }
793
794
795 } else
796 if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) {
797 /*
798 * The TEST9_BRANCH_ID test failed INVITE transaction with
799 * provisional response.
800 */
801 pjsip_method *method;
802 pj_status_t status;
803
804 method = &rdata->msg_info.msg->line.req.method;
805
806 recv_count++;
807
808 if (method->id == PJSIP_INVITE_METHOD) {
809
810 pjsip_response_addr res_addr;
811 struct response *r;
812 pjsip_tx_data *tdata;
813 pj_time_val delay = { 2, 0 };
814
815 if (recv_count > 1) {
816 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
817 recv_count));
818 test_complete = -650;
819 return PJ_TRUE;
820 }
821
822 /* Respond with provisional response */
823 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL,
824 &tdata);
825 pj_assert(status == PJ_SUCCESS);
826
827 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
828 pj_assert(status == PJ_SUCCESS);
829
830 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
831 NULL, NULL);
832 pj_assert(status == PJ_SUCCESS);
833
834 /* Create the final response. */
835 status = pjsip_endpt_create_response(endpt, rdata, 302, NULL,
836 &tdata);
837 pj_assert(status == PJ_SUCCESS);
838
839 /* Schedule sending final response in couple of of secs. */
840 r = pj_pool_alloc(tdata->pool, sizeof(*r));
841 r->res_addr = res_addr;
842 r->tdata = tdata;
843 if (r->res_addr.transport)
844 pjsip_transport_add_ref(r->res_addr.transport);
845
846 timer.cb = &send_response_callback;
847 timer.user_data = r;
848 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
849
850 } else if (method->id == PJSIP_ACK_METHOD) {
851
852 if (recv_count == 2) {
853 pj_str_t key;
854 pj_time_val delay = { 5, 0 };
855
856 /* Schedule timer to destroy transaction after 5 seconds.
857 * This is to make sure that transaction does not
858 * retransmit ACK.
859 */
860 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
861 PJSIP_ROLE_UAC, &pjsip_invite_method,
862 rdata);
863
864 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);
865 timer.id = 302;
866 timer.cb = &terminate_tsx_callback;
867
868 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
869 }
870
871 if (recv_count > 2) {
872 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
873 recv_count));
874 test_complete = -638;
875 }
876
877
878 } else {
879 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
880 pjsip_rx_data_get_info(rdata)));
881 test_complete = -639;
882
Benny Prijono85598d92006-01-07 18:44:25 +0000883 }
884
885 return PJ_TRUE;
Benny Prijono9c1d9f52006-01-07 23:01:56 +0000886
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000887 }
Benny Prijono85598d92006-01-07 18:44:25 +0000888
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000889 return PJ_FALSE;
890}
891
Benny Prijono85598d92006-01-07 18:44:25 +0000892/*
893 * The generic test framework, used by most of the tests.
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000894 */
Benny Prijono85598d92006-01-07 18:44:25 +0000895static int perform_tsx_test(int dummy, char *target_uri, char *from_uri,
896 char *branch_param, int test_time,
897 const pjsip_method *method)
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000898{
899 pjsip_tx_data *tdata;
900 pjsip_transaction *tsx;
Benny Prijono85598d92006-01-07 18:44:25 +0000901 pj_str_t target, from, tsx_key;
902 pjsip_via_hdr *via;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000903 pj_time_val timeout;
904 pj_status_t status;
905
Benny Prijono85598d92006-01-07 18:44:25 +0000906 PJ_LOG(3,(THIS_FILE,
907 " please standby, this will take at most %d seconds..",
908 test_time));
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000909
Benny Prijono85598d92006-01-07 18:44:25 +0000910 /* Reset test. */
911 recv_count = 0;
912 test_complete = 0;
913
914 /* Init headers. */
915 target = pj_str(target_uri);
916 from = pj_str(from_uri);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000917
918 /* Create request. */
919 status = pjsip_endpt_create_request( endpt, method, &target,
Benny Prijono85598d92006-01-07 18:44:25 +0000920 &from, &target, NULL, NULL, -1,
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000921 NULL, &tdata);
922 if (status != PJ_SUCCESS) {
923 app_perror(" Error: unable to create request", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000924 return -100;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000925 }
926
Benny Prijono85598d92006-01-07 18:44:25 +0000927 /* Set the branch param for test 1. */
928 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
929 via->branch_param = pj_str(branch_param);
930
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000931 /* Add additional reference to tdata to prevent transaction from
932 * deleting it.
933 */
934 pjsip_tx_data_add_ref(tdata);
935
936 /* Create transaction. */
937 status = pjsip_tsx_create_uac( &tsx_user, tdata, &tsx);
938 if (status != PJ_SUCCESS) {
939 app_perror(" Error: unable to create UAC transaction", status);
Benny Prijono85598d92006-01-07 18:44:25 +0000940 pjsip_tx_data_dec_ref(tdata);
941 return -110;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000942 }
943
944 /* Get transaction key. */
945 pj_strdup(tdata->pool, &tsx_key, &tsx->transaction_key);
946
947 /* Send the message. */
948 status = pjsip_tsx_send_msg(tsx, NULL);
Benny Prijono85598d92006-01-07 18:44:25 +0000949 // Ignore send result. Some tests do deliberately triggers error
950 // when sending message.
951 //if (status != PJ_SUCCESS) {
952 // app_perror(" Error: unable to send request", status);
953 // pjsip_tx_data_dec_ref(tdata);
954 // return -120;
955 //}
956
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000957
958 /* Set test completion time. */
959 pj_gettimeofday(&timeout);
Benny Prijono85598d92006-01-07 18:44:25 +0000960 timeout.sec += test_time;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000961
962 /* Wait until test complete. */
963 while (!test_complete) {
Benny Prijono85598d92006-01-07 18:44:25 +0000964 pj_time_val now, poll_delay = {0, 10};
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000965
Benny Prijono85598d92006-01-07 18:44:25 +0000966 pjsip_endpt_handle_events(endpt, &poll_delay);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000967
968 pj_gettimeofday(&now);
969 if (now.sec > timeout.sec) {
Benny Prijono85598d92006-01-07 18:44:25 +0000970 PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
971 pjsip_tx_data_dec_ref(tdata);
972 return -130;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000973 }
974 }
975
Benny Prijono85598d92006-01-07 18:44:25 +0000976 if (test_complete < 0) {
977 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
978 if (tsx) {
979 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
980 pj_mutex_unlock(tsx->mutex);
981 flush_events(1000);
982 }
983 pjsip_tx_data_dec_ref(tdata);
984 return test_complete;
985 }
986
987 /* Allow transaction to destroy itself */
988 flush_events(500);
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000989
990 /* Make sure transaction has been destroyed. */
991 if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
Benny Prijono85598d92006-01-07 18:44:25 +0000992 PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
993 pjsip_tx_data_dec_ref(tdata);
994 return -140;
Benny Prijonofa73e3e2006-01-05 23:35:46 +0000995 }
996
997 /* Check tdata reference counter. */
998 if (pj_atomic_get(tdata->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000999 PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001000 pj_atomic_get(tdata->ref_cnt)));
Benny Prijono85598d92006-01-07 18:44:25 +00001001 pjsip_tx_data_dec_ref(tdata);
1002 return -150;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001003 }
1004
1005 /* Destroy txdata */
1006 pjsip_tx_data_dec_ref(tdata);
1007
1008 return PJ_SUCCESS;
1009}
1010
1011/*****************************************************************************
1012 **
Benny Prijono85598d92006-01-07 18:44:25 +00001013 ** TEST1_BRANCH_ID: UAC basic retransmission and timeout test.
1014 **
1015 ** This will test the retransmission of the UAC transaction. Remote will not
1016 ** answer the transaction, so the transaction should fail. The Via branch prm
1017 ** TEST1_BRANCH_ID will be used for this test.
1018 **
1019 *****************************************************************************
1020 */
1021static int tsx_uac_retransmit_test(void)
1022{
1023 int status, enabled;
1024 int i;
1025 struct {
1026 const pjsip_method *method;
1027 unsigned delay;
1028 } sub_test[] =
1029 {
1030 { &pjsip_invite_method, 0},
1031 { &pjsip_invite_method, TEST1_ALLOWED_DIFF*2},
1032 { &pjsip_options_method, 0},
1033 { &pjsip_options_method, TEST1_ALLOWED_DIFF*2}
1034 };
1035
1036 PJ_LOG(3,(THIS_FILE, " test1: basic uac retransmit and timeout test"));
1037
1038
1039 /* For this test. message printing shound be disabled because it makes
1040 * incorrect timing.
1041 */
1042 enabled = msg_logger_set_enabled(0);
1043
1044 for (i=0; i<PJ_ARRAY_SIZE(sub_test); ++i) {
1045
1046 PJ_LOG(3,(THIS_FILE,
1047 " variant %c: %s with %d ms network delay",
1048 ('a' + i),
1049 sub_test[i].method->name.ptr,
1050 sub_test[i].delay));
1051
1052 /* Configure transport */
1053 pjsip_loop_set_failure(loop, 0, NULL);
1054 pjsip_loop_set_recv_delay(loop, sub_test[i].delay, NULL);
1055
1056 /* Do the test. */
1057 status = perform_tsx_test(-500, "sip:bob@127.0.0.1;transport=loop-dgram",
1058 "sip:alice@127.0.0.1;transport=loop-dgram",
1059 TEST1_BRANCH_ID,
1060 35, sub_test[i].method);
1061 if (status != 0)
1062 break;
1063 }
1064
1065 /* Restore transport. */
1066 pjsip_loop_set_recv_delay(loop, 0, NULL);
1067
1068 /* Restore msg logger. */
1069 msg_logger_set_enabled(enabled);
1070
1071 /* Done. */
1072 return status;
1073}
1074
1075/*****************************************************************************
1076 **
1077 ** TEST2_BRANCH_ID: UAC resolve error test.
1078 **
1079 ** Test the scenario where destination host is unresolvable. There are
1080 ** two variants:
1081 ** (a) resolver returns immediate error
1082 ** (b) resolver returns error via the callback.
1083 **
1084 *****************************************************************************
1085 */
1086static int tsx_resolve_error_test(void)
1087{
1088 int status;
1089
1090 PJ_LOG(3,(THIS_FILE, " test2: resolve error test"));
1091
1092 /*
1093 * Variant (a): immediate resolve error.
1094 */
1095 PJ_LOG(3,(THIS_FILE, " variant a: immediate resolving error"));
1096
1097 status = perform_tsx_test(-800,
1098 "sip:bob@unresolved-host;transport=loop-dgram",
1099 "sip:alice@127.0.0.1;transport=loop-dgram",
1100 TEST2_BRANCH_ID, 10,
1101 &pjsip_options_method);
1102 if (status != 0)
1103 return status;
1104
1105 /*
1106 * Variant (b): error via callback.
1107 */
1108 PJ_LOG(3,(THIS_FILE, " variant b: error via callback"));
1109
1110 /* Set loop transport to return delayed error. */
1111 pjsip_loop_set_failure(loop, 2, NULL);
1112 pjsip_loop_set_send_callback_delay(loop, 10, NULL);
1113
1114 status = perform_tsx_test(-800, "sip:bob@127.0.0.1;transport=loop-dgram",
1115 "sip:alice@127.0.0.1;transport=loop-dgram",
1116 TEST2_BRANCH_ID, 2,
1117 &pjsip_options_method);
1118 if (status != 0)
1119 return status;
1120
1121 /* Restore loop transport settings. */
1122 pjsip_loop_set_failure(loop, 0, NULL);
1123 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1124
1125 return status;
1126}
1127
1128
1129/*****************************************************************************
1130 **
1131 ** TEST3_BRANCH_ID: UAC terminate while resolving test.
1132 **
1133 ** Terminate the transaction while resolver is still running.
1134 **
1135 *****************************************************************************
1136 */
1137static int tsx_terminate_resolving_test(void)
1138{
1139 unsigned prev_delay;
1140 pj_status_t status;
1141
1142 PJ_LOG(3,(THIS_FILE, " test3: terminate while resolving test"));
1143
1144 /* Configure transport delay. */
1145 pjsip_loop_set_send_callback_delay(loop, 100, &prev_delay);
1146
1147 /* Start the test. */
1148 status = perform_tsx_test(-900, "sip:127.0.0.1;transport=loop-dgram",
1149 "sip:127.0.0.1;transport=loop-dgram",
1150 TEST3_BRANCH_ID, 2, &pjsip_options_method);
1151
1152 /* Restore delay. */
1153 pjsip_loop_set_send_callback_delay(loop, prev_delay, NULL);
1154
1155 return status;
1156}
1157
1158
1159/*****************************************************************************
1160 **
1161 ** TEST4_BRANCH_ID: Transport failed after several retransmissions
1162 **
1163 ** There are two variants of this test: (a) failure occurs immediately when
1164 ** transaction calls pjsip_transport_send() or (b) failure is reported via
1165 ** transport callback.
1166 **
1167 *****************************************************************************
1168 */
1169static int tsx_retransmit_fail_test(void)
1170{
1171 int i;
1172 unsigned delay[] = {0, 10};
1173 pj_status_t status;
1174
1175 PJ_LOG(3,(THIS_FILE,
1176 " test4: transport fails after several retransmissions test"));
1177
1178
1179 for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
1180
1181 PJ_LOG(3,(THIS_FILE,
1182 " variant %c: transport delay %d ms", ('a'+i), delay[i]));
1183
1184 /* Configure transport delay. */
1185 pjsip_loop_set_send_callback_delay(loop, delay[i], NULL);
1186
1187 /* Restore transport failure mode. */
1188 pjsip_loop_set_failure(loop, 0, 0);
1189
1190 /* Start the test. */
1191 status = perform_tsx_test(-1000, "sip:127.0.0.1;transport=loop-dgram",
1192 "sip:127.0.0.1;transport=loop-dgram",
1193 TEST4_BRANCH_ID, 6, &pjsip_options_method);
1194
1195 if (status != 0)
1196 break;
1197
1198 }
1199
1200 /* Restore delay. */
1201 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1202
1203 /* Restore transport failure mode. */
1204 pjsip_loop_set_failure(loop, 0, 0);
1205
1206 return status;
1207}
1208
1209
1210/*****************************************************************************
1211 **
1212 ** TEST5_BRANCH_ID: Terminate transaction after several retransmissions
1213 **
1214 *****************************************************************************
1215 */
1216static int tsx_terminate_after_retransmit_test(void)
1217{
1218 int status;
1219
1220 PJ_LOG(3,(THIS_FILE, " test5: terminate after retransmissions"));
1221
1222 /* Do the test. */
1223 status = perform_tsx_test(-1100, "sip:bob@127.0.0.1;transport=loop-dgram",
1224 "sip:alice@127.0.0.1;transport=loop-dgram",
1225 TEST5_BRANCH_ID,
1226 6, &pjsip_options_method);
1227
1228 /* Done. */
1229 return status;
1230}
1231
1232
1233/*****************************************************************************
1234 **
1235 ** TEST6_BRANCH_ID: Successfull non-invite transaction
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001236 ** TEST7_BRANCH_ID: Successfull non-invite transaction with provisional
1237 ** TEST8_BRANCH_ID: Failed invite transaction
1238 ** TEST9_BRANCH_ID: Failed invite transaction with provisional
Benny Prijono85598d92006-01-07 18:44:25 +00001239 **
1240 *****************************************************************************
1241 */
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001242static int perform_generic_test( const char *title,
1243 char *branch_id,
1244 const pjsip_method *method)
Benny Prijono85598d92006-01-07 18:44:25 +00001245{
1246 int i, status;
1247 unsigned delay[] = { 1, 200 };
1248
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001249 PJ_LOG(3,(THIS_FILE, " %s", title));
Benny Prijono85598d92006-01-07 18:44:25 +00001250
1251 /* Do the test. */
1252 for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
1253
1254 PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay",
1255 ('a'+i), delay[i]));
1256
1257 pjsip_loop_set_delay(loop, delay[i]);
1258
1259 status = perform_tsx_test(-1200,
1260 "sip:bob@127.0.0.1;transport=loop-dgram",
1261 "sip:alice@127.0.0.1;transport=loop-dgram",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001262 branch_id,
1263 10, method);
Benny Prijono85598d92006-01-07 18:44:25 +00001264 if (status != 0)
1265 return status;
1266 }
1267
1268 pjsip_loop_set_delay(loop, 0);
1269
1270 /* Done. */
1271 return status;
1272}
1273
1274
1275/*****************************************************************************
1276 **
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001277 ** UAC Transaction Test.
1278 **
1279 *****************************************************************************
1280 */
1281int tsx_uac_test(void)
1282{
1283 pj_sockaddr_in addr;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001284 pj_status_t status;
1285
Benny Prijono85598d92006-01-07 18:44:25 +00001286 /* Check if loop transport is configured. */
1287 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
1288 &addr, sizeof(addr), &loop);
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001289 if (status != PJ_SUCCESS) {
Benny Prijono85598d92006-01-07 18:44:25 +00001290 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
1291 return -10;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001292 }
1293
1294 /* Register modules. */
1295 status = pjsip_endpt_register_module(endpt, &tsx_user);
1296 if (status != PJ_SUCCESS) {
1297 app_perror(" Error: unable to register module", status);
1298 return -30;
1299 }
1300 status = pjsip_endpt_register_module(endpt, &msg_receiver);
1301 if (status != PJ_SUCCESS) {
1302 app_perror(" Error: unable to register module", status);
Benny Prijono85598d92006-01-07 18:44:25 +00001303 return -40;
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001304 }
1305
Benny Prijono85598d92006-01-07 18:44:25 +00001306 /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */
1307 status = tsx_uac_retransmit_test();
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001308 if (status != 0)
1309 return status;
1310
Benny Prijono85598d92006-01-07 18:44:25 +00001311 /* TEST2_BRANCH_ID: Resolve error test. */
1312 status = tsx_resolve_error_test();
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001313 if (status != 0)
1314 return status;
1315
Benny Prijono85598d92006-01-07 18:44:25 +00001316 /* TEST3_BRANCH_ID: UAC terminate while resolving test. */
1317 status = tsx_terminate_resolving_test();
1318 if (status != 0)
1319 return status;
1320
1321 /* TEST4_BRANCH_ID: Transport failed after several retransmissions */
1322 status = tsx_retransmit_fail_test();
1323 if (status != 0)
1324 return status;
1325
1326 /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions */
1327 status = tsx_terminate_after_retransmit_test();
1328 if (status != 0)
1329 return status;
Benny Prijono85598d92006-01-07 18:44:25 +00001330
1331 /* TEST6_BRANCH_ID: Successfull non-invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001332 status = perform_generic_test("test6: successfull non-invite transaction",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001333 TEST6_BRANCH_ID, &pjsip_options_method);
1334 if (status != 0)
1335 return status;
1336
1337 /* TEST7_BRANCH_ID: Successfull non-invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001338 status = perform_generic_test("test7: successfull non-invite transaction "
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001339 "with provisional response",
1340 TEST7_BRANCH_ID, &pjsip_options_method);
1341 if (status != 0)
1342 return status;
1343
1344 /* TEST8_BRANCH_ID: Failed invite transaction */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001345 status = perform_generic_test("test8: failed invite transaction",
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001346 TEST8_BRANCH_ID, &pjsip_invite_method);
1347 if (status != 0)
1348 return status;
1349
1350 /* TEST9_BRANCH_ID: Failed invite transaction with provisional response */
Benny Prijonoe8a2ff52006-01-07 23:36:57 +00001351 status = perform_generic_test("test9: failed invite transaction with "
Benny Prijono9c1d9f52006-01-07 23:01:56 +00001352 "provisional response",
1353 TEST9_BRANCH_ID, &pjsip_invite_method);
Benny Prijono85598d92006-01-07 18:44:25 +00001354 if (status != 0)
1355 return status;
1356
1357
1358 pjsip_transport_dec_ref(loop);
Benny Prijonofa73e3e2006-01-05 23:35:46 +00001359 return 0;
1360}
Benny Prijono85598d92006-01-07 18:44:25 +00001361