blob: d978df80b4a1faf88ae575fa9b14fc25f773877b [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
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
21#include "test.h"
22#include <pjsip.h>
23#include <pjlib.h>
24
25#define THIS_FILE "tsx_uac_test.c"
26
27
28/*****************************************************************************
29 **
30 ** UAC tests.
31 **
32 ** This file performs various tests for UAC transactions. Each test will have
33 ** a different Via branch param so that message receiver module and
34 ** transaction user module can identify which test is being carried out.
35 **
36 ** TEST1_BRANCH_ID
37 ** Perform basic retransmission and timeout test. Message receiver will
38 ** verify that retransmission is received at correct time.
39 ** This test verifies the following requirements:
40 ** - retransmit timer doubles for INVITE
41 ** - retransmit timer doubles and caps off for non-INVITE
42 ** - retransmit timer timer is precise
43 ** - correct timeout and retransmission count
44 ** Requirements not tested:
45 ** - retransmit timer only starts after resolving has completed.
46 **
47 ** TEST2_BRANCH_ID
48 ** Test scenario where resolver is unable to resolve destination host.
49 **
50 ** TEST3_BRANCH_ID
51 ** Test scenario where transaction is terminated while resolver is still
52 ** running.
53 **
54 ** TEST4_BRANCH_ID
55 ** Test scenario where transport failed after several retransmissions.
56 **
57 ** TEST5_BRANCH_ID
58 ** Test scenario where transaction is terminated by user after several
59 ** retransmissions.
60 **
61 ** TEST6_BRANCH_ID
62 ** Test successfull non-INVITE transaction.
63 ** It tests the following requirements:
64 ** - transaction correctly moves to COMPLETED state.
65 ** - retransmission must cease.
66 ** - tx_data must be maintained until state is terminated.
67 **
68 ** TEST7_BRANCH_ID
69 ** Test successfull non-INVITE transaction, with provisional response.
70 **
71 ** TEST8_BRANCH_ID
72 ** Test failed INVITE transaction (e.g. ACK must be received)
73 **
74 ** TEST9_BRANCH_ID
75 ** Test failed INVITE transaction with provisional response.
76 **
77 **
78 *****************************************************************************
79 */
80
81static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test1";
82static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test2";
83static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test3";
84static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test4";
85static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test5";
86static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test6";
87static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test7";
88static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test8";
89static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAC-Test9";
90
91#define TEST1_ALLOWED_DIFF (150)
92#define TEST4_RETRANSMIT_CNT 3
93#define TEST5_RETRANSMIT_CNT 3
94
95static char TARGET_URI[128];
96static char FROM_URI[128];
97static unsigned tp_flag;
98static struct tsx_test_param *test_param;
99
100static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
101static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata);
102
103/* UAC transaction user module. */
104static pjsip_module tsx_user =
105{
106 NULL, NULL, /* prev and next */
107 { "Tsx-UAC-User", 12}, /* Name. */
108 -1, /* Id */
109 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
110 NULL, /* load() */
111 NULL, /* start() */
112 NULL, /* stop() */
113 NULL, /* unload() */
114 NULL, /* on_rx_request() */
115 NULL, /* on_rx_response() */
116 NULL, /* on_tx_request() */
117 NULL, /* on_tx_response() */
118 &tsx_user_on_tsx_state, /* on_tsx_state() */
119};
120
121/* Module to receive the loop-backed request. */
122static pjsip_module msg_receiver =
123{
124 NULL, NULL, /* prev and next */
125 { "Msg-Receiver", 12}, /* Name. */
126 -1, /* Id */
127 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
128 NULL, /* load() */
129 NULL, /* start() */
130 NULL, /* stop() */
131 NULL, /* unload() */
132 &msg_receiver_on_rx_request, /* on_rx_request() */
133 NULL, /* on_rx_response() */
134 NULL, /* on_tx_request() */
135 NULL, /* on_tx_response() */
136 NULL, /* on_tsx_state() */
137};
138
139/* Static vars, which will be reset on each test. */
140static int recv_count;
141static pj_time_val recv_last;
142static pj_bool_t test_complete;
143
144/* Loop transport instance. */
145static pjsip_transport *loop;
146
147/* General timer entry to be used by tests. */
148static struct my_timer
149{
150 pj_timer_entry entry;
151 char key_buf[1024];
152 pj_str_t tsx_key;
153} timer;
154
155/*
156 * This is the handler to receive state changed notification from the
157 * transaction. It is used to verify that the transaction behaves according
158 * to the test scenario.
159 */
160static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
161{
162 if (pj_stricmp2(&tsx->branch, TEST1_BRANCH_ID)==0) {
163 /*
164 * Transaction with TEST1_BRANCH_ID should terminate with transaction
165 * timeout status.
166 */
167 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
168
169 if (test_complete == 0)
170 test_complete = 1;
171
172 /* Test the status code. */
173 if (tsx->status_code != PJSIP_SC_TSX_TIMEOUT) {
174 PJ_LOG(3,(THIS_FILE,
175 " error: status code is %d instead of %d",
176 tsx->status_code, PJSIP_SC_TSX_TIMEOUT));
177 test_complete = -710;
178 }
179
180
181 /* If transport is reliable, then there must not be any
182 * retransmissions.
183 */
184 if (tp_flag & PJSIP_TRANSPORT_RELIABLE) {
185 if (recv_count != 1) {
186 PJ_LOG(3,(THIS_FILE,
187 " error: there were %d (re)transmissions",
188 recv_count));
189 test_complete = -715;
190 }
191 } else {
192 /* Check the number of transmissions, which must be
193 * 6 for INVITE and 10 for non-INVITE
194 */
195 if (tsx->method.id==PJSIP_INVITE_METHOD && recv_count != 7) {
196 PJ_LOG(3,(THIS_FILE,
197 " error: there were %d (re)transmissions",
198 recv_count));
199 test_complete = -716;
200 } else
201 if (tsx->method.id==PJSIP_OPTIONS_METHOD && recv_count != 11) {
202 PJ_LOG(3,(THIS_FILE,
203 " error: there were %d (re)transmissions",
204 recv_count));
205 test_complete = -717;
206 } else
207 if (tsx->method.id!=PJSIP_INVITE_METHOD &&
208 tsx->method.id!=PJSIP_OPTIONS_METHOD)
209 {
210 PJ_LOG(3,(THIS_FILE, " error: unexpected method"));
211 test_complete = -718;
212 }
213 }
214 }
215
216 } else if (pj_stricmp2(&tsx->branch, TEST2_BRANCH_ID)==0) {
217 /*
218 * Transaction with TEST2_BRANCH_ID should terminate with transport error.
219 */
220 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
221
222 /* Test the status code. */
223 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR &&
224 tsx->status_code != PJSIP_SC_BAD_GATEWAY)
225 {
226 PJ_LOG(3,(THIS_FILE,
227 " error: status code is %d instead of %d or %d",
228 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR,
229 PJSIP_SC_BAD_GATEWAY));
230 test_complete = -720;
231 }
232
233 if (test_complete == 0)
234 test_complete = 1;
235 }
236
237 } else if (pj_stricmp2(&tsx->branch, TEST3_BRANCH_ID)==0) {
238 /*
239 * This test terminates the transaction while resolver is still
240 * running.
241 */
242 if (tsx->state == PJSIP_TSX_STATE_CALLING) {
243
244 /* Terminate the transaction. */
245 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
246
247 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
248
249 /* Check if status code is correct. */
250 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
251 PJ_LOG(3,(THIS_FILE,
252 " error: status code is %d instead of %d",
253 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
254 test_complete = -730;
255 }
256
257 if (test_complete == 0)
258 test_complete = 1;
259
260 }
261
262 } else if (pj_stricmp2(&tsx->branch, TEST4_BRANCH_ID)==0) {
263 /*
264 * This test simulates transport failure after several
265 * retransmissions.
266 */
267 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
268
269 /* Status code must be transport error. */
270 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
271 PJ_LOG(3,(THIS_FILE,
272 " error: status code is %d instead of %d",
273 tsx->status_code, PJSIP_SC_TSX_TRANSPORT_ERROR));
274 test_complete = -730;
275 }
276
277 /* Must have correct retransmission count. */
278 if (tsx->retransmit_count != TEST4_RETRANSMIT_CNT) {
279 PJ_LOG(3,(THIS_FILE,
280 " error: retransmit cnt is %d instead of %d",
281 tsx->retransmit_count, TEST4_RETRANSMIT_CNT));
282 test_complete = -731;
283 }
284
285 if (test_complete == 0)
286 test_complete = 1;
287 }
288
289
290 } else if (pj_stricmp2(&tsx->branch, TEST5_BRANCH_ID)==0) {
291 /*
292 * This test simulates transport failure after several
293 * retransmissions.
294 */
295 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
296
297 /* Status code must be PJSIP_SC_REQUEST_TERMINATED. */
298 if (tsx->status_code != PJSIP_SC_REQUEST_TERMINATED) {
299 PJ_LOG(3,(THIS_FILE,
300 " error: status code is %d instead of %d",
301 tsx->status_code, PJSIP_SC_REQUEST_TERMINATED));
302 test_complete = -733;
303 }
304
305 /* Must have correct retransmission count. */
306 if (tsx->retransmit_count != TEST5_RETRANSMIT_CNT) {
307 PJ_LOG(3,(THIS_FILE,
308 " error: retransmit cnt is %d instead of %d",
309 tsx->retransmit_count, TEST5_RETRANSMIT_CNT));
310 test_complete = -734;
311 }
312
313 if (test_complete == 0)
314 test_complete = 1;
315 }
316
317
318 } else if (pj_stricmp2(&tsx->branch, TEST6_BRANCH_ID)==0) {
319 /*
320 * Successfull non-INVITE transaction.
321 */
322 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
323
324 /* Status code must be 202. */
325 if (tsx->status_code != 202) {
326 PJ_LOG(3,(THIS_FILE,
327 " error: status code is %d instead of %d",
328 tsx->status_code, 202));
329 test_complete = -736;
330 }
331
332 /* Must have correct retransmission count. */
333 if (tsx->retransmit_count != 0) {
334 PJ_LOG(3,(THIS_FILE,
335 " error: retransmit cnt is %d instead of %d",
336 tsx->retransmit_count, 0));
337 test_complete = -737;
338 }
339
340 /* Must still keep last_tx */
341 if (tsx->last_tx == NULL) {
342 PJ_LOG(3,(THIS_FILE,
343 " error: transaction lost last_tx"));
344 test_complete = -738;
345 }
346
347 if (test_complete == 0) {
348 test_complete = 1;
349 pjsip_tsx_terminate(tsx, 202);
350 }
351
352 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
353
354 /* Previous state must be COMPLETED. */
355 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
356 test_complete = -7381;
357 }
358
359 }
360
361 } else if (pj_stricmp2(&tsx->branch, TEST7_BRANCH_ID)==0) {
362 /*
363 * Successfull non-INVITE transaction.
364 */
365 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
366
367 /* Check prev state. */
368 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
369 PJ_LOG(3,(THIS_FILE,
370 " error: prev state is %s instead of %s",
371 pjsip_tsx_state_str((pjsip_tsx_state_e)e->body.tsx_state.prev_state),
372 pjsip_tsx_state_str(PJSIP_TSX_STATE_PROCEEDING)));
373 test_complete = -739;
374 }
375
376 /* Status code must be 202. */
377 if (tsx->status_code != 202) {
378 PJ_LOG(3,(THIS_FILE,
379 " error: status code is %d instead of %d",
380 tsx->status_code, 202));
381 test_complete = -740;
382 }
383
384 /* Must have correct retransmission count. */
385 if (tsx->retransmit_count != 0) {
386 PJ_LOG(3,(THIS_FILE,
387 " error: retransmit cnt is %d instead of %d",
388 tsx->retransmit_count, 0));
389 test_complete = -741;
390 }
391
392 /* Must still keep last_tx */
393 if (tsx->last_tx == NULL) {
394 PJ_LOG(3,(THIS_FILE,
395 " error: transaction lost last_tx"));
396 test_complete = -741;
397 }
398
399 if (test_complete == 0) {
400 test_complete = 1;
401 pjsip_tsx_terminate(tsx, 202);
402 }
403
404 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
405
406 /* Previous state must be COMPLETED. */
407 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
408 test_complete = -742;
409 }
410
411 }
412
413
414 } else if (pj_stricmp2(&tsx->branch, TEST8_BRANCH_ID)==0) {
415 /*
416 * Failed INVITE transaction.
417 */
418 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
419
420 /* Status code must be 301. */
421 if (tsx->status_code != 301) {
422 PJ_LOG(3,(THIS_FILE,
423 " error: status code is %d instead of %d",
424 tsx->status_code, 301));
425 test_complete = -745;
426 }
427
428 /* Must have correct retransmission count. */
429 if (tsx->retransmit_count != 0) {
430 PJ_LOG(3,(THIS_FILE,
431 " error: retransmit cnt is %d instead of %d",
432 tsx->retransmit_count, 0));
433 test_complete = -746;
434 }
435
436 /* Must still keep last_tx */
437 if (tsx->last_tx == NULL) {
438 PJ_LOG(3,(THIS_FILE,
439 " error: transaction lost last_tx"));
440 test_complete = -747;
441 }
442
443 /* last_tx MUST be the INVITE request
444 * (authorization depends on this behavior)
445 */
446 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
447 PJSIP_INVITE_METHOD)
448 {
449 PJ_LOG(3,(THIS_FILE,
450 " error: last_tx is not INVITE"));
451 test_complete = -748;
452 }
453 }
454 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
455
456 test_complete = 1;
457
458 /* Previous state must be COMPLETED. */
459 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
460 test_complete = -750;
461 }
462
463 /* Status code must be 301. */
464 if (tsx->status_code != 301) {
465 PJ_LOG(3,(THIS_FILE,
466 " error: status code is %d instead of %d",
467 tsx->status_code, 301));
468 test_complete = -751;
469 }
470
471 }
472
473
474 } else if (pj_stricmp2(&tsx->branch, TEST9_BRANCH_ID)==0) {
475 /*
476 * Failed INVITE transaction with provisional response.
477 */
478 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
479
480 /* Previous state must be PJSIP_TSX_STATE_PROCEEDING. */
481 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
482 test_complete = -760;
483 }
484
485 /* Status code must be 302. */
486 if (tsx->status_code != 302) {
487 PJ_LOG(3,(THIS_FILE,
488 " error: status code is %d instead of %d",
489 tsx->status_code, 302));
490 test_complete = -761;
491 }
492
493 /* Must have correct retransmission count. */
494 if (tsx->retransmit_count != 0) {
495 PJ_LOG(3,(THIS_FILE,
496 " error: retransmit cnt is %d instead of %d",
497 tsx->retransmit_count, 0));
498 test_complete = -762;
499 }
500
501 /* Must still keep last_tx */
502 if (tsx->last_tx == NULL) {
503 PJ_LOG(3,(THIS_FILE,
504 " error: transaction lost last_tx"));
505 test_complete = -763;
506 }
507
508 /* last_tx MUST be INVITE.
509 * (authorization depends on this behavior)
510 */
511 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id !=
512 PJSIP_INVITE_METHOD)
513 {
514 PJ_LOG(3,(THIS_FILE,
515 " error: last_tx is not INVITE"));
516 test_complete = -764;
517 }
518
519 }
520 else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
521
522 test_complete = 1;
523
524 /* Previous state must be COMPLETED. */
525 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
526 test_complete = -767;
527 }
528
529 /* Status code must be 302. */
530 if (tsx->status_code != 302) {
531 PJ_LOG(3,(THIS_FILE,
532 " error: status code is %d instead of %d",
533 tsx->status_code, 302));
534 test_complete = -768;
535 }
536
537 }
538
539 }
540}
541
542/*
543 * This timer callback is called to send delayed response.
544 */
545struct response
546{
547 pjsip_response_addr res_addr;
548 pjsip_tx_data *tdata;
549};
550
551static void send_response_callback( pj_timer_heap_t *timer_heap,
552 struct pj_timer_entry *entry)
553{
554 struct response *r = (struct response*) entry->user_data;
555 pjsip_transport *tp = r->res_addr.transport;
556
557 PJ_UNUSED_ARG(timer_heap);
558
559 pjsip_endpt_send_response(endpt, &r->res_addr, r->tdata, NULL, NULL);
560 if (tp)
561 pjsip_transport_dec_ref(tp);
562}
563
564/* Timer callback to terminate a transaction. */
565static void terminate_tsx_callback( pj_timer_heap_t *timer_heap,
566 struct pj_timer_entry *entry)
567{
568 struct my_timer *m = (struct my_timer *)entry;
569 pjsip_transaction *tsx = pjsip_tsx_layer_find_tsx(&m->tsx_key, PJ_FALSE);
570 int status_code = entry->id;
571
572 PJ_UNUSED_ARG(timer_heap);
573
574 if (tsx) {
575 pjsip_tsx_terminate(tsx, status_code);
576 }
577}
578
579
580#define DIFF(a,b) ((a<b) ? (b-a) : (a-b))
581
582/*
583 * This is the handler to receive message for this test. It is used to
584 * control and verify the behavior of the message transmitted by the
585 * transaction.
586 */
587static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata)
588{
589 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST1_BRANCH_ID) == 0) {
590 /*
591 * The TEST1_BRANCH_ID test performs the verifications for transaction
592 * retransmission mechanism. It will not answer the incoming request
593 * with any response.
594 */
595 pjsip_msg *msg = rdata->msg_info.msg;
596
597 PJ_LOG(4,(THIS_FILE, " received request"));
598
599 /* Only wants to take INVITE or OPTIONS method. */
600 if (msg->line.req.method.id != PJSIP_INVITE_METHOD &&
601 msg->line.req.method.id != PJSIP_OPTIONS_METHOD)
602 {
603 PJ_LOG(3,(THIS_FILE, " error: received unexpected method %.*s",
604 msg->line.req.method.name.slen,
605 msg->line.req.method.name.ptr));
606 test_complete = -600;
607 return PJ_TRUE;
608 }
609
610 if (recv_count == 0) {
611 recv_count++;
612 //pj_gettimeofday(&recv_last);
613 recv_last = rdata->pkt_info.timestamp;
614 } else {
615 pj_time_val now;
616 unsigned msec_expected, msec_elapsed;
617 int max_received;
618
619 //pj_gettimeofday(&now);
620 now = rdata->pkt_info.timestamp;
621 PJ_TIME_VAL_SUB(now, recv_last);
622 msec_elapsed = now.sec*1000 + now.msec;
623
624 ++recv_count;
625 msec_expected = (1<<(recv_count-2))*pjsip_cfg()->tsx.t1;
626
627 if (msg->line.req.method.id != PJSIP_INVITE_METHOD) {
628 if (msec_expected > pjsip_cfg()->tsx.t2)
629 msec_expected = pjsip_cfg()->tsx.t2;
630 max_received = 11;
631 } else {
632 max_received = 7;
633 }
634
635 if (DIFF(msec_expected, msec_elapsed) > TEST1_ALLOWED_DIFF) {
636 PJ_LOG(3,(THIS_FILE,
637 " error: expecting retransmission no. %d in %d "
638 "ms, received in %d ms",
639 recv_count-1, msec_expected, msec_elapsed));
640 test_complete = -610;
641 }
642
643
644 if (recv_count > max_received) {
645 PJ_LOG(3,(THIS_FILE,
646 " error: too many messages (%d) received",
647 recv_count));
648 test_complete = -620;
649 }
650
651 //pj_gettimeofday(&recv_last);
652 recv_last = rdata->pkt_info.timestamp;
653 }
654 return PJ_TRUE;
655
656 } else
657 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST4_BRANCH_ID) == 0) {
658 /*
659 * The TEST4_BRANCH_ID test simulates transport failure after several
660 * retransmissions.
661 */
662 recv_count++;
663
664 if (recv_count == TEST4_RETRANSMIT_CNT) {
665 /* Simulate transport failure. */
666 pjsip_loop_set_failure(loop, 2, NULL);
667
668 } else if (recv_count > TEST4_RETRANSMIT_CNT) {
669 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
670 recv_count));
671 test_complete = -631;
672 }
673
674 return PJ_TRUE;
675
676
677 } else
678 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST5_BRANCH_ID) == 0) {
679 /*
680 * The TEST5_BRANCH_ID test simulates user terminating the transaction
681 * after several retransmissions.
682 */
683 recv_count++;
684
685 if (recv_count == TEST5_RETRANSMIT_CNT+1) {
686 pj_str_t key;
687 pjsip_transaction *tsx;
688
689 pjsip_tsx_create_key( rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,
690 &rdata->msg_info.msg->line.req.method, rdata);
691 tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
692 if (tsx) {
693 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
694 pj_grp_lock_release(tsx->grp_lock);
695 } else {
696 PJ_LOG(3,(THIS_FILE, " error: uac transaction not found!"));
697 test_complete = -633;
698 }
699
700 } else if (recv_count > TEST5_RETRANSMIT_CNT+1) {
701 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
702 recv_count));
703 test_complete = -634;
704 }
705
706 return PJ_TRUE;
707
708 } else
709 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) {
710 /*
711 * The TEST6_BRANCH_ID test successfull non-INVITE transaction.
712 */
713 pj_status_t status;
714
715 recv_count++;
716
717 if (recv_count > 1) {
718 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
719 recv_count));
720 test_complete = -635;
721 }
722
723 status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL,
724 NULL, NULL);
725 if (status != PJ_SUCCESS) {
726 app_perror(" error: unable to send response", status);
727 test_complete = -636;
728 }
729
730 return PJ_TRUE;
731
732
733 } else
734 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) {
735 /*
736 * The TEST7_BRANCH_ID test successfull non-INVITE transaction
737 * with provisional response.
738 */
739 pj_status_t status;
740 pjsip_response_addr res_addr;
741 struct response *r;
742 pjsip_tx_data *tdata;
743 pj_time_val delay = { 2, 0 };
744
745 recv_count++;
746
747 if (recv_count > 1) {
748 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
749 recv_count));
750 test_complete = -640;
751 return PJ_TRUE;
752 }
753
754 /* Respond with provisional response */
755 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata);
756 pj_assert(status == PJ_SUCCESS);
757
758 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
759 pj_assert(status == PJ_SUCCESS);
760
761 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
762 NULL, NULL);
763 pj_assert(status == PJ_SUCCESS);
764
765 /* Create the final response. */
766 status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata);
767 pj_assert(status == PJ_SUCCESS);
768
769 /* Schedule sending final response in couple of of secs. */
770 r = PJ_POOL_ALLOC_T(tdata->pool, struct response);
771 r->res_addr = res_addr;
772 r->tdata = tdata;
773 if (r->res_addr.transport)
774 pjsip_transport_add_ref(r->res_addr.transport);
775
776 timer.entry.cb = &send_response_callback;
777 timer.entry.user_data = r;
778 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
779
780 return PJ_TRUE;
781
782
783 } else
784 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) {
785 /*
786 * The TEST8_BRANCH_ID test failed INVITE transaction.
787 */
788 pjsip_method *method;
789 pj_status_t status;
790
791 method = &rdata->msg_info.msg->line.req.method;
792
793 recv_count++;
794
795 if (method->id == PJSIP_INVITE_METHOD) {
796
797 if (recv_count > 1) {
798 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
799 recv_count));
800 test_complete = -635;
801 }
802
803 status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL,
804 NULL, NULL);
805 if (status != PJ_SUCCESS) {
806 app_perror(" error: unable to send response", status);
807 test_complete = -636;
808 }
809
810 } else if (method->id == PJSIP_ACK_METHOD) {
811
812 if (recv_count == 2) {
813 pj_str_t key;
814 pj_time_val delay = { 5, 0 };
815
816 /* Schedule timer to destroy transaction after 5 seconds.
817 * This is to make sure that transaction does not
818 * retransmit ACK.
819 */
820 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
821 PJSIP_ROLE_UAC, &pjsip_invite_method,
822 rdata);
823
824 pj_strcpy(&timer.tsx_key, &key);
825 timer.entry.id = 301;
826 timer.entry.cb = &terminate_tsx_callback;
827
828 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
829 }
830
831 if (recv_count > 2) {
832 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
833 recv_count));
834 test_complete = -638;
835 }
836
837
838 } else {
839 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
840 pjsip_rx_data_get_info(rdata)));
841 test_complete = -639;
842
843 }
844
845
846 } else
847 if (pj_stricmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) {
848 /*
849 * The TEST9_BRANCH_ID test failed INVITE transaction with
850 * provisional response.
851 */
852 pjsip_method *method;
853 pj_status_t status;
854
855 method = &rdata->msg_info.msg->line.req.method;
856
857 recv_count++;
858
859 if (method->id == PJSIP_INVITE_METHOD) {
860
861 pjsip_response_addr res_addr;
862 struct response *r;
863 pjsip_tx_data *tdata;
864 pj_time_val delay = { 2, 0 };
865
866 if (recv_count > 1) {
867 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
868 recv_count));
869 test_complete = -650;
870 return PJ_TRUE;
871 }
872
873 /* Respond with provisional response */
874 status = pjsip_endpt_create_response(endpt, rdata, 100, NULL,
875 &tdata);
876 pj_assert(status == PJ_SUCCESS);
877
878 status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
879 pj_assert(status == PJ_SUCCESS);
880
881 status = pjsip_endpt_send_response(endpt, &res_addr, tdata,
882 NULL, NULL);
883 pj_assert(status == PJ_SUCCESS);
884
885 /* Create the final response. */
886 status = pjsip_endpt_create_response(endpt, rdata, 302, NULL,
887 &tdata);
888 pj_assert(status == PJ_SUCCESS);
889
890 /* Schedule sending final response in couple of of secs. */
891 r = PJ_POOL_ALLOC_T(tdata->pool, struct response);
892 r->res_addr = res_addr;
893 r->tdata = tdata;
894 if (r->res_addr.transport)
895 pjsip_transport_add_ref(r->res_addr.transport);
896
897 timer.entry.cb = &send_response_callback;
898 timer.entry.user_data = r;
899 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
900
901 } else if (method->id == PJSIP_ACK_METHOD) {
902
903 if (recv_count == 2) {
904 pj_str_t key;
905 pj_time_val delay = { 5, 0 };
906
907 /* Schedule timer to destroy transaction after 5 seconds.
908 * This is to make sure that transaction does not
909 * retransmit ACK.
910 */
911 pjsip_tsx_create_key(rdata->tp_info.pool, &key,
912 PJSIP_ROLE_UAC, &pjsip_invite_method,
913 rdata);
914
915 pj_strcpy(&timer.tsx_key, &key);
916 timer.entry.id = 302;
917 timer.entry.cb = &terminate_tsx_callback;
918
919 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
920 }
921
922 if (recv_count > 2) {
923 PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!",
924 recv_count));
925 test_complete = -638;
926 }
927
928
929 } else {
930 PJ_LOG(3,(THIS_FILE," error: not expecting %s",
931 pjsip_rx_data_get_info(rdata)));
932 test_complete = -639;
933
934 }
935
936 return PJ_TRUE;
937
938 }
939
940 return PJ_FALSE;
941}
942
943/*
944 * The generic test framework, used by most of the tests.
945 */
946static int perform_tsx_test(int dummy, char *target_uri, char *from_uri,
947 char *branch_param, int test_time,
948 const pjsip_method *method)
949{
950 pjsip_tx_data *tdata;
951 pjsip_transaction *tsx;
952 pj_str_t target, from, tsx_key;
953 pjsip_via_hdr *via;
954 pj_time_val timeout;
955 pj_status_t status;
956
957 PJ_UNUSED_ARG(dummy);
958
959 PJ_LOG(3,(THIS_FILE,
960 " please standby, this will take at most %d seconds..",
961 test_time));
962
963 /* Reset test. */
964 recv_count = 0;
965 test_complete = 0;
966
967 /* Init headers. */
968 target = pj_str(target_uri);
969 from = pj_str(from_uri);
970
971 /* Create request. */
972 status = pjsip_endpt_create_request( endpt, method, &target,
973 &from, &target, NULL, NULL, -1,
974 NULL, &tdata);
975 if (status != PJ_SUCCESS) {
976 app_perror(" Error: unable to create request", status);
977 return -100;
978 }
979
980 /* Set the branch param for test 1. */
981 via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
982 via->branch_param = pj_str(branch_param);
983
984 /* Add additional reference to tdata to prevent transaction from
985 * deleting it.
986 */
987 pjsip_tx_data_add_ref(tdata);
988
989 /* Create transaction. */
990 status = pjsip_tsx_create_uac( &tsx_user, tdata, &tsx);
991 if (status != PJ_SUCCESS) {
992 app_perror(" Error: unable to create UAC transaction", status);
993 pjsip_tx_data_dec_ref(tdata);
994 return -110;
995 }
996
997 /* Get transaction key. */
998 pj_strdup(tdata->pool, &tsx_key, &tsx->transaction_key);
999
1000 /* Send the message. */
1001 status = pjsip_tsx_send_msg(tsx, NULL);
1002 // Ignore send result. Some tests do deliberately triggers error
1003 // when sending message.
1004 if (status != PJ_SUCCESS) {
1005 // app_perror(" Error: unable to send request", status);
1006 pjsip_tx_data_dec_ref(tdata);
1007 // return -120;
1008 }
1009
1010
1011 /* Set test completion time. */
1012 pj_gettimeofday(&timeout);
1013 timeout.sec += test_time;
1014
1015 /* Wait until test complete. */
1016 while (!test_complete) {
1017 pj_time_val now, poll_delay = {0, 10};
1018
1019 pjsip_endpt_handle_events(endpt, &poll_delay);
1020
1021 pj_gettimeofday(&now);
1022 if (now.sec > timeout.sec) {
1023 PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
1024 pjsip_tx_data_dec_ref(tdata);
1025 return -130;
1026 }
1027 }
1028
1029 if (test_complete < 0) {
1030 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
1031 if (tsx) {
1032 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
1033 pj_grp_lock_release(tsx->grp_lock);
1034 flush_events(1000);
1035 }
1036 pjsip_tx_data_dec_ref(tdata);
1037 return test_complete;
1038
1039 } else {
1040 pj_time_val now;
1041
1042 /* Allow transaction to destroy itself */
1043 flush_events(500);
1044
1045 /* Wait until test completes */
1046 pj_gettimeofday(&now);
1047
1048 if (PJ_TIME_VAL_LT(now, timeout)) {
1049 pj_time_val interval;
1050 interval = timeout;
1051 PJ_TIME_VAL_SUB(interval, now);
1052 flush_events(PJ_TIME_VAL_MSEC(interval));
1053 }
1054 }
1055
1056 /* Make sure transaction has been destroyed. */
1057 if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
1058 PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
1059 pjsip_tx_data_dec_ref(tdata);
1060 return -140;
1061 }
1062
1063 /* Check tdata reference counter. */
1064 if (pj_atomic_get(tdata->ref_cnt) != 1) {
1065 PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
1066 pj_atomic_get(tdata->ref_cnt)));
1067 pjsip_tx_data_dec_ref(tdata);
1068 return -150;
1069 }
1070
1071 /* Destroy txdata */
1072 pjsip_tx_data_dec_ref(tdata);
1073
1074 return PJ_SUCCESS;
1075}
1076
1077/*****************************************************************************
1078 **
1079 ** TEST1_BRANCH_ID: UAC basic retransmission and timeout test.
1080 **
1081 ** This will test the retransmission of the UAC transaction. Remote will not
1082 ** answer the transaction, so the transaction should fail. The Via branch prm
1083 ** TEST1_BRANCH_ID will be used for this test.
1084 **
1085 *****************************************************************************
1086 */
1087static int tsx_uac_retransmit_test(void)
1088{
1089 int status = 0, enabled;
1090 int i;
1091 struct {
1092 const pjsip_method *method;
1093 unsigned delay;
1094 } sub_test[] =
1095 {
1096 { &pjsip_invite_method, 0},
1097 { &pjsip_invite_method, TEST1_ALLOWED_DIFF*2},
1098 { &pjsip_options_method, 0},
1099 { &pjsip_options_method, TEST1_ALLOWED_DIFF*2}
1100 };
1101
1102 PJ_LOG(3,(THIS_FILE, " test1: basic uac retransmit and timeout test"));
1103
1104
1105 /* For this test. message printing shound be disabled because it makes
1106 * incorrect timing.
1107 */
1108 enabled = msg_logger_set_enabled(0);
1109
1110 for (i=0; i<(int)PJ_ARRAY_SIZE(sub_test); ++i) {
1111
1112 PJ_LOG(3,(THIS_FILE,
1113 " variant %c: %s with %d ms network delay",
1114 ('a' + i),
1115 sub_test[i].method->name.ptr,
1116 sub_test[i].delay));
1117
1118 /* Configure transport */
1119 pjsip_loop_set_failure(loop, 0, NULL);
1120 pjsip_loop_set_recv_delay(loop, sub_test[i].delay, NULL);
1121
1122 /* Do the test. */
1123 status = perform_tsx_test(-500, TARGET_URI, FROM_URI,
1124 TEST1_BRANCH_ID,
1125 35, sub_test[i].method);
1126 if (status != 0)
1127 break;
1128 }
1129
1130 /* Restore transport. */
1131 pjsip_loop_set_recv_delay(loop, 0, NULL);
1132
1133 /* Restore msg logger. */
1134 msg_logger_set_enabled(enabled);
1135
1136 /* Done. */
1137 return status;
1138}
1139
1140/*****************************************************************************
1141 **
1142 ** TEST2_BRANCH_ID: UAC resolve error test.
1143 **
1144 ** Test the scenario where destination host is unresolvable. There are
1145 ** two variants:
1146 ** (a) resolver returns immediate error
1147 ** (b) resolver returns error via the callback.
1148 **
1149 *****************************************************************************
1150 */
1151static int tsx_resolve_error_test(void)
1152{
1153 int status = 0;
1154
1155 PJ_LOG(3,(THIS_FILE, " test2: resolve error test"));
1156
1157 /*
1158 * Variant (a): immediate resolve error.
1159 */
1160 PJ_LOG(3,(THIS_FILE, " variant a: immediate resolving error"));
1161
1162 status = perform_tsx_test(-800,
1163 "sip:bob@unresolved-host",
1164 FROM_URI, TEST2_BRANCH_ID, 20,
1165 &pjsip_options_method);
1166 if (status != 0)
1167 return status;
1168
1169 /*
1170 * Variant (b): error via callback.
1171 */
1172 PJ_LOG(3,(THIS_FILE, " variant b: error via callback"));
1173
1174 /* This only applies to "loop-dgram" transport */
1175 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
1176 /* Set loop transport to return delayed error. */
1177 pjsip_loop_set_failure(loop, 2, NULL);
1178 pjsip_loop_set_send_callback_delay(loop, 10, NULL);
1179
1180 status = perform_tsx_test(-800, TARGET_URI, FROM_URI,
1181 TEST2_BRANCH_ID, 2,
1182 &pjsip_options_method);
1183 if (status != 0)
1184 return status;
1185
1186 /* Restore loop transport settings. */
1187 pjsip_loop_set_failure(loop, 0, NULL);
1188 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1189 }
1190
1191 return status;
1192}
1193
1194
1195/*****************************************************************************
1196 **
1197 ** TEST3_BRANCH_ID: UAC terminate while resolving test.
1198 **
1199 ** Terminate the transaction while resolver is still running.
1200 **
1201 *****************************************************************************
1202 */
1203static int tsx_terminate_resolving_test(void)
1204{
1205 unsigned prev_delay;
1206 pj_status_t status;
1207
1208 PJ_LOG(3,(THIS_FILE, " test3: terminate while resolving test"));
1209
1210 /* Configure transport delay. */
1211 pjsip_loop_set_send_callback_delay(loop, 100, &prev_delay);
1212
1213 /* Start the test. */
1214 status = perform_tsx_test(-900, TARGET_URI, FROM_URI,
1215 TEST3_BRANCH_ID, 2, &pjsip_options_method);
1216
1217 /* Restore delay. */
1218 pjsip_loop_set_send_callback_delay(loop, prev_delay, NULL);
1219
1220 return status;
1221}
1222
1223
1224/*****************************************************************************
1225 **
1226 ** TEST4_BRANCH_ID: Transport failed after several retransmissions
1227 **
1228 ** There are two variants of this test: (a) failure occurs immediately when
1229 ** transaction calls pjsip_transport_send() or (b) failure is reported via
1230 ** transport callback.
1231 **
1232 *****************************************************************************
1233 */
1234static int tsx_retransmit_fail_test(void)
1235{
1236 int i;
1237 unsigned delay[] = {0, 10};
1238 pj_status_t status = PJ_SUCCESS;
1239
1240 PJ_LOG(3,(THIS_FILE,
1241 " test4: transport fails after several retransmissions test"));
1242
1243
1244 for (i=0; i<(int)PJ_ARRAY_SIZE(delay); ++i) {
1245
1246 PJ_LOG(3,(THIS_FILE,
1247 " variant %c: transport delay %d ms", ('a'+i), delay[i]));
1248
1249 /* Configure transport delay. */
1250 pjsip_loop_set_send_callback_delay(loop, delay[i], NULL);
1251
1252 /* Restore transport failure mode. */
1253 pjsip_loop_set_failure(loop, 0, 0);
1254
1255 /* Start the test. */
1256 status = perform_tsx_test(-1000, TARGET_URI, FROM_URI,
1257 TEST4_BRANCH_ID, 6, &pjsip_options_method);
1258
1259 if (status != 0)
1260 break;
1261
1262 }
1263
1264 /* Restore delay. */
1265 pjsip_loop_set_send_callback_delay(loop, 0, NULL);
1266
1267 /* Restore transport failure mode. */
1268 pjsip_loop_set_failure(loop, 0, 0);
1269
1270 return status;
1271}
1272
1273
1274/*****************************************************************************
1275 **
1276 ** TEST5_BRANCH_ID: Terminate transaction after several retransmissions
1277 **
1278 *****************************************************************************
1279 */
1280static int tsx_terminate_after_retransmit_test(void)
1281{
1282 int status;
1283
1284 PJ_LOG(3,(THIS_FILE, " test5: terminate after retransmissions"));
1285
1286 /* Do the test. */
1287 status = perform_tsx_test(-1100, TARGET_URI, FROM_URI,
1288 TEST5_BRANCH_ID,
1289 6, &pjsip_options_method);
1290
1291 /* Done. */
1292 return status;
1293}
1294
1295
1296/*****************************************************************************
1297 **
1298 ** TEST6_BRANCH_ID: Successfull non-invite transaction
1299 ** TEST7_BRANCH_ID: Successfull non-invite transaction with provisional
1300 ** TEST8_BRANCH_ID: Failed invite transaction
1301 ** TEST9_BRANCH_ID: Failed invite transaction with provisional
1302 **
1303 *****************************************************************************
1304 */
1305static int perform_generic_test( const char *title,
1306 char *branch_id,
1307 const pjsip_method *method)
1308{
1309 int i, status = 0;
1310 unsigned delay[] = { 1, 200 };
1311
1312 PJ_LOG(3,(THIS_FILE, " %s", title));
1313
1314 /* Do the test. */
1315 for (i=0; i<(int)PJ_ARRAY_SIZE(delay); ++i) {
1316
1317 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
1318 PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay",
1319 ('a'+i), delay[i]));
1320
1321 pjsip_loop_set_delay(loop, delay[i]);
1322 }
1323
1324 status = perform_tsx_test(-1200, TARGET_URI, FROM_URI,
1325 branch_id, 10, method);
1326 if (status != 0)
1327 return status;
1328
1329 if (test_param->type != PJSIP_TRANSPORT_LOOP_DGRAM)
1330 break;
1331 }
1332
1333 pjsip_loop_set_delay(loop, 0);
1334
1335 /* Done. */
1336 return status;
1337}
1338
1339
1340/*****************************************************************************
1341 **
1342 ** UAC Transaction Test.
1343 **
1344 *****************************************************************************
1345 */
1346int tsx_uac_test(struct tsx_test_param *param)
1347{
1348 pj_sockaddr_in addr;
1349 pj_status_t status;
1350
1351 timer.tsx_key.ptr = timer.key_buf;
1352
1353 test_param = param;
1354
1355 /* Get transport flag */
1356 tp_flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)test_param->type);
1357
1358 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s",
1359 param->port, param->tp_type);
1360 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s",
1361 param->port, param->tp_type);
1362
1363 /* Check if loop transport is configured. */
1364 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
1365 &addr, sizeof(addr), NULL, &loop);
1366 if (status != PJ_SUCCESS) {
1367 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
1368 return -10;
1369 }
1370
1371 /* Register modules. */
1372 status = pjsip_endpt_register_module(endpt, &tsx_user);
1373 if (status != PJ_SUCCESS) {
1374 app_perror(" Error: unable to register module", status);
1375 return -30;
1376 }
1377 status = pjsip_endpt_register_module(endpt, &msg_receiver);
1378 if (status != PJ_SUCCESS) {
1379 app_perror(" Error: unable to register module", status);
1380 return -40;
1381 }
1382
1383 /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */
1384 status = tsx_uac_retransmit_test();
1385 if (status != 0)
1386 return status;
1387
1388 /* TEST2_BRANCH_ID: Resolve error test. */
1389 status = tsx_resolve_error_test();
1390 if (status != 0)
1391 return status;
1392
1393 /* TEST3_BRANCH_ID: UAC terminate while resolving test. */
1394 status = tsx_terminate_resolving_test();
1395 if (status != 0)
1396 return status;
1397
1398 /* TEST4_BRANCH_ID: Transport failed after several retransmissions.
1399 * Only applies to loop transport.
1400 */
1401 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
1402 status = tsx_retransmit_fail_test();
1403 if (status != 0)
1404 return status;
1405 }
1406
1407 /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions
1408 * Only applicable to non-reliable transports.
1409 */
1410 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
1411 status = tsx_terminate_after_retransmit_test();
1412 if (status != 0)
1413 return status;
1414 }
1415
1416 /* TEST6_BRANCH_ID: Successfull non-invite transaction */
1417 status = perform_generic_test("test6: successfull non-invite transaction",
1418 TEST6_BRANCH_ID, &pjsip_options_method);
1419 if (status != 0)
1420 return status;
1421
1422 /* TEST7_BRANCH_ID: Successfull non-invite transaction */
1423 status = perform_generic_test("test7: successfull non-invite transaction "
1424 "with provisional response",
1425 TEST7_BRANCH_ID, &pjsip_options_method);
1426 if (status != 0)
1427 return status;
1428
1429 /* TEST8_BRANCH_ID: Failed invite transaction */
1430 status = perform_generic_test("test8: failed invite transaction",
1431 TEST8_BRANCH_ID, &pjsip_invite_method);
1432 if (status != 0)
1433 return status;
1434
1435 /* TEST9_BRANCH_ID: Failed invite transaction with provisional response */
1436 status = perform_generic_test("test9: failed invite transaction with "
1437 "provisional response",
1438 TEST9_BRANCH_ID, &pjsip_invite_method);
1439 if (status != 0)
1440 return status;
1441
1442 pjsip_transport_dec_ref(loop);
1443 flush_events(500);
1444
1445 /* Unregister modules. */
1446 status = pjsip_endpt_unregister_module(endpt, &tsx_user);
1447 if (status != PJ_SUCCESS) {
1448 app_perror(" Error: unable to unregister module", status);
1449 return -31;
1450 }
1451 status = pjsip_endpt_unregister_module(endpt, &msg_receiver);
1452 if (status != PJ_SUCCESS) {
1453 app_perror(" Error: unable to unregister module", status);
1454 return -41;
1455 }
1456
1457 return 0;
1458}
1459