blob: 42cb075fc220ad5bd02a638bcd83c2e13c0886cd [file] [log] [blame]
Benny Prijonodbe337a2006-01-08 23:57:52 +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"
Benny Prijono40f2f642006-01-30 18:40:05 +000021#include <pjsip.h>
Benny Prijonodbe337a2006-01-08 23:57:52 +000022#include <pjlib.h>
23
24#define THIS_FILE "tsx_uas_test.c"
25
26
27/*****************************************************************************
28 **
29 ** UAS tests.
30 **
31 ** 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.
34 **
35 ** TEST1_BRANCH_ID
36 ** Test that non-INVITE transaction returns 2xx response to the correct
37 ** transport and correctly terminates the transaction.
Benny Prijonoe93e2872006-06-28 16:46:49 +000038 ** This also checks that transaction is destroyed immediately after
39 ** it sends final response when reliable transport is used.
Benny Prijonodbe337a2006-01-08 23:57:52 +000040 **
41 ** TEST2_BRANCH_ID
42 ** As above, for non-2xx final response.
43 **
44 ** TEST3_BRANCH_ID
45 ** Transaction correctly progressing to PROCEEDING state when provisional
46 ** response is sent.
47 **
48 ** TEST4_BRANCH_ID
49 ** Transaction retransmits last response (if any) without notifying
Benny Prijono0c2bc612006-01-10 13:31:40 +000050 ** transaction user upon receiving request retransmissions on TRYING
51 ** state
Benny Prijonodbe337a2006-01-08 23:57:52 +000052 **
53 ** TEST5_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000054 ** As above, in PROCEEDING state.
Benny Prijonodbe337a2006-01-08 23:57:52 +000055 **
56 ** TEST6_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000057 ** As above, in COMPLETED state, with first sending provisional response.
Benny Prijonoe93e2872006-06-28 16:46:49 +000058 ** (Only applicable for non-reliable transports).
Benny Prijonodbe337a2006-01-08 23:57:52 +000059 **
60 ** TEST7_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000061 ** INVITE transaction MUST retransmit non-2xx final response.
Benny Prijonodbe337a2006-01-08 23:57:52 +000062 **
63 ** TEST8_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000064 ** As above, for INVITE's 2xx final response (this is PJSIP specific).
65 **
66 ** TEST9_BRANCH_ID
67 ** INVITE transaction MUST cease retransmission of final response when
68 ** ACK is received. (Note: PJSIP also retransmit 2xx final response
69 ** until it's terminated by user).
70 ** Transaction also MUST terminate in T4 seconds.
Benny Prijonoe93e2872006-06-28 16:46:49 +000071 ** (Only applicable for non-reliable transports).
Benny Prijono0c2bc612006-01-10 13:31:40 +000072 **
Benny Prijono0c2bc612006-01-10 13:31:40 +000073 ** TEST11_BRANCH_ID
Benny Prijono728a9052006-01-18 23:34:15 +000074 ** Test scenario where transport fails before response is sent (i.e.
75 ** in TRYING state).
76 **
77 ** TEST12_BRANCH_ID
78 ** As above, after provisional response is sent but before final
79 ** response is sent (i.e. in PROCEEDING state).
80 **
81 ** TEST13_BRANCH_ID
82 ** As above, for INVITE, after final response has been sent but before
83 ** ACK is received (i.e. in CONNECTED state).
84 **
85 ** TEST14_BRANCH_ID
Benny Prijonodbe337a2006-01-08 23:57:52 +000086 ** When UAS failed to deliver the response with the selected transport,
87 ** it should try contacting the client with other transport or begin
88 ** RFC 3263 server resolution procedure.
89 ** This should be tested on:
90 ** a. TRYING state (when delivering first response).
91 ** b. PROCEEDING state (when failed to retransmit last response
92 ** upon receiving request retransmission).
93 ** c. COMPLETED state.
94 **
Benny Prijonodbe337a2006-01-08 23:57:52 +000095 **/
96
97static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test1";
98static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test2";
99static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test3";
100static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test4";
101static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test5";
102static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test6";
103static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test7";
Benny Prijono0c2bc612006-01-10 13:31:40 +0000104static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test8";
105static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test9";
106static char *TEST10_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test10";
107static char *TEST11_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test11";
108static char *TEST12_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test12";
Benny Prijono728a9052006-01-18 23:34:15 +0000109static char *TEST13_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test13";
Benny Prijonodbe337a2006-01-08 23:57:52 +0000110
111#define TEST1_STATUS_CODE 200
112#define TEST2_STATUS_CODE 301
113#define TEST3_PROVISIONAL_CODE PJSIP_SC_QUEUED
114#define TEST3_STATUS_CODE 202
Benny Prijono0c2bc612006-01-10 13:31:40 +0000115#define TEST4_STATUS_CODE 200
116#define TEST4_REQUEST_COUNT 2
117#define TEST5_PROVISIONAL_CODE 100
118#define TEST5_STATUS_CODE 200
119#define TEST5_REQUEST_COUNT 2
120#define TEST5_RESPONSE_COUNT 2
121#define TEST6_PROVISIONAL_CODE 100
122#define TEST6_STATUS_CODE 200 /* Must be final */
123#define TEST6_REQUEST_COUNT 2
124#define TEST6_RESPONSE_COUNT 3
125#define TEST7_STATUS_CODE 301
126#define TEST8_STATUS_CODE 302
Benny Prijono728a9052006-01-18 23:34:15 +0000127#define TEST9_STATUS_CODE 301
Benny Prijonodbe337a2006-01-08 23:57:52 +0000128
129
Benny Prijono0c2bc612006-01-10 13:31:40 +0000130#define TEST4_TITLE "test4: absorbing request retransmission"
131#define TEST5_TITLE "test5: retransmit last response in PROCEEDING state"
132#define TEST6_TITLE "test6: retransmit last response in COMPLETED state"
133
134
Benny Prijonoe93e2872006-06-28 16:46:49 +0000135static char TARGET_URI[128];
136static char FROM_URI[128];
137static struct tsx_test_param *test_param;
138static unsigned tp_flag;
139
140
Benny Prijono0c2bc612006-01-10 13:31:40 +0000141#define TEST_TIMEOUT_ERROR -30
142#define MAX_ALLOWED_DIFF 150
143
Benny Prijonodbe337a2006-01-08 23:57:52 +0000144static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
145static pj_bool_t on_rx_message(pjsip_rx_data *rdata);
146
147/* UAC transaction user module. */
148static pjsip_module tsx_user =
149{
150 NULL, NULL, /* prev and next */
151 { "Tsx-UAS-User", 12}, /* Name. */
152 -1, /* Id */
153 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000154 NULL, /* load() */
155 NULL, /* start() */
156 NULL, /* stop() */
157 NULL, /* unload() */
158 NULL, /* on_rx_request() */
159 NULL, /* on_rx_response() */
160 NULL, /* on_tx_request() */
161 NULL, /* on_tx_response() */
162 &tsx_user_on_tsx_state, /* on_tsx_state() */
163};
164
165/* Module to send request. */
166static pjsip_module msg_sender =
167{
168 NULL, NULL, /* prev and next */
169 { "Msg-Sender", 10}, /* Name. */
170 -1, /* Id */
171 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000172 NULL, /* load() */
173 NULL, /* start() */
174 NULL, /* stop() */
175 NULL, /* unload() */
176 &on_rx_message, /* on_rx_request() */
177 &on_rx_message, /* on_rx_response() */
178 NULL, /* on_tx_request() */
179 NULL, /* on_tx_response() */
180 NULL, /* on_tsx_state() */
181};
182
183/* Static vars, which will be reset on each test. */
184static int recv_count;
185static pj_time_val recv_last;
186static pj_bool_t test_complete;
187
188/* Loop transport instance. */
189static pjsip_transport *loop;
190
191/* UAS transaction key. */
192static char key_buf[64];
193static pj_str_t tsx_key = { key_buf, 0 };
194
195
196/* General timer entry to be used by tests. */
197static pj_timer_entry timer;
198
199/* Timer to send response via transaction. */
200struct response
201{
202 pj_str_t tsx_key;
203 pjsip_tx_data *tdata;
204};
205
Benny Prijono0c2bc612006-01-10 13:31:40 +0000206/* Timer callback to send response. */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000207static void send_response_timer( pj_timer_heap_t *timer_heap,
208 struct pj_timer_entry *entry)
209{
210 pjsip_transaction *tsx;
211 struct response *r = entry->user_data;
212 pj_status_t status;
213
214 tsx = pjsip_tsx_layer_find_tsx(&r->tsx_key, PJ_TRUE);
215 if (!tsx) {
216 PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction"));
217 pjsip_tx_data_dec_ref(r->tdata);
218 return;
219 }
220
221 status = pjsip_tsx_send_msg(tsx, r->tdata);
222 if (status != PJ_SUCCESS) {
Benny Prijono728a9052006-01-18 23:34:15 +0000223 // Some tests do expect failure!
224 //PJ_LOG(3,(THIS_FILE," error: timer unable to send response"));
225 pj_mutex_unlock(tsx->mutex);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000226 pjsip_tx_data_dec_ref(r->tdata);
227 return;
228 }
Benny Prijono728a9052006-01-18 23:34:15 +0000229
230 pj_mutex_unlock(tsx->mutex);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000231}
232
Benny Prijono0c2bc612006-01-10 13:31:40 +0000233/* Utility to send response. */
234static void send_response( pjsip_rx_data *rdata,
235 pjsip_transaction *tsx,
236 int status_code )
237{
238 pj_status_t status;
239 pjsip_tx_data *tdata;
240
241 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL,
242 &tdata);
243 if (status != PJ_SUCCESS) {
244 app_perror(" error: unable to create response", status);
245 test_complete = -196;
246 return;
247 }
248
249 status = pjsip_tsx_send_msg(tsx, tdata);
250 if (status != PJ_SUCCESS) {
Benny Prijono0c2bc612006-01-10 13:31:40 +0000251 pjsip_tx_data_dec_ref(tdata);
Benny Prijono728a9052006-01-18 23:34:15 +0000252 // Some tests do expect failure!
253 //app_perror(" error: unable to send response", status);
254 //test_complete = -197;
Benny Prijono0c2bc612006-01-10 13:31:40 +0000255 return;
256 }
257}
258
Benny Prijonodbe337a2006-01-08 23:57:52 +0000259/* Schedule timer to send response for the specified UAS transaction */
260static void schedule_send_response( pjsip_rx_data *rdata,
261 const pj_str_t *tsx_key,
262 int status_code,
263 int msec_delay )
264{
265 pj_status_t status;
266 pjsip_tx_data *tdata;
Benny Prijono728a9052006-01-18 23:34:15 +0000267 pj_timer_entry *t;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000268 struct response *r;
269 pj_time_val delay;
270
271 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL,
272 &tdata);
273 if (status != PJ_SUCCESS) {
274 app_perror(" error: unable to create response", status);
275 test_complete = -198;
276 return;
277 }
278
279 r = pj_pool_alloc(tdata->pool, sizeof(*r));
280 pj_strdup(tdata->pool, &r->tsx_key, tsx_key);
281 r->tdata = tdata;
282
283 delay.sec = 0;
284 delay.msec = msec_delay;
285 pj_time_val_normalize(&delay);
286
Benny Prijono728a9052006-01-18 23:34:15 +0000287 t = pj_pool_zalloc(tdata->pool, sizeof(*t));
288 t->user_data = r;
289 t->cb = &send_response_timer;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000290
Benny Prijono728a9052006-01-18 23:34:15 +0000291 status = pjsip_endpt_schedule_timer(endpt, t, &delay);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000292 if (status != PJ_SUCCESS) {
Benny Prijono728a9052006-01-18 23:34:15 +0000293 pjsip_tx_data_dec_ref(tdata);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000294 app_perror(" error: unable to schedule timer", status);
295 test_complete = -199;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000296 return;
297 }
298}
299
Benny Prijono0c2bc612006-01-10 13:31:40 +0000300
301/* Find and terminate tsx with the specified key. */
302static void terminate_our_tsx(int status_code)
303{
304 pjsip_transaction *tsx;
305
306 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
307 if (!tsx) {
308 PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction"));
309 return;
310 }
311
312 pjsip_tsx_terminate(tsx, status_code);
313 pj_mutex_unlock(tsx->mutex);
314}
315
316/* Timer callback to terminate transaction. */
317static void terminate_tsx_timer( pj_timer_heap_t *timer_heap,
318 struct pj_timer_entry *entry)
319{
320 terminate_our_tsx(entry->id);
321}
322
323
324/* Schedule timer to terminate transaction. */
325static void schedule_terminate_tsx( pjsip_transaction *tsx,
326 int status_code,
327 int msec_delay )
328{
329 pj_time_val delay;
330
331 delay.sec = 0;
332 delay.msec = msec_delay;
333 pj_time_val_normalize(&delay);
334
335 pj_assert(pj_strcmp(&tsx->transaction_key, &tsx_key)==0);
336 timer.user_data = NULL;
337 timer.id = status_code;
338 timer.cb = &terminate_tsx_timer;
339 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
340}
341
342
Benny Prijonodbe337a2006-01-08 23:57:52 +0000343/*
344 * This is the handler to receive state changed notification from the
345 * transaction. It is used to verify that the transaction behaves according
346 * to the test scenario.
347 */
348static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
349{
350 if (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0 ||
351 pj_strcmp2(&tsx->branch, TEST2_BRANCH_ID)==0)
352 {
353 /*
354 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits final
355 * response using correct transport and terminates transaction after
356 * T4 (PJSIP_T4_TIMEOUT, 5 seconds).
357 *
358 * TEST2_BRANCH_ID does similar test for non-2xx final response.
359 */
360 int status_code = (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0) ?
361 TEST1_STATUS_CODE : TEST2_STATUS_CODE;
362
363 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
364
365 test_complete = 1;
366
367 /* Check that status code is status_code. */
368 if (tsx->status_code != status_code) {
369 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
370 test_complete = -100;
371 }
372
373 /* Previous state must be completed. */
374 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
375 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
376 test_complete = -101;
377 }
378
379 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
380
381 /* Previous state must be TRYING. */
382 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
383 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
384 test_complete = -102;
385 }
386 }
387
388 }
389 else
390 if (pj_strcmp2(&tsx->branch, TEST3_BRANCH_ID)==0) {
391 /*
392 * TEST3_BRANCH_ID tests sending provisional response.
393 */
394 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
395
396 test_complete = 1;
397
398 /* Check that status code is status_code. */
399 if (tsx->status_code != TEST3_STATUS_CODE) {
400 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
401 test_complete = -110;
402 }
403
404 /* Previous state must be completed. */
405 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
406 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
407 test_complete = -111;
408 }
409
410 } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
411
412 /* Previous state must be TRYING. */
413 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
414 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
415 test_complete = -112;
416 }
417
418 /* Check that status code is status_code. */
419 if (tsx->status_code != TEST3_PROVISIONAL_CODE) {
420 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
421 test_complete = -113;
422 }
423
424 /* Check that event must be TX_MSG */
425 if (e->body.tsx_state.type != PJSIP_EVENT_TX_MSG) {
426 PJ_LOG(3,(THIS_FILE, " error: incorrect event"));
427 test_complete = -114;
428 }
429
430 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
431
432 /* Previous state must be PROCEEDING. */
433 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
434 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
435 test_complete = -115;
436 }
437
438 /* Check that status code is status_code. */
439 if (tsx->status_code != TEST3_STATUS_CODE) {
440 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
441 test_complete = -116;
442 }
443
444 /* Check that event must be TX_MSG */
445 if (e->body.tsx_state.type != PJSIP_EVENT_TX_MSG) {
446 PJ_LOG(3,(THIS_FILE, " error: incorrect event"));
447 test_complete = -117;
448 }
449
450 }
451
Benny Prijono0c2bc612006-01-10 13:31:40 +0000452 } else
453 if (pj_strcmp2(&tsx->branch, TEST4_BRANCH_ID)==0) {
454 /*
455 * TEST4_BRANCH_ID tests receiving retransmissions in TRYING state.
456 */
Benny Prijono02b8fd82006-06-26 15:12:55 +0000457 if (tsx->state == PJSIP_TSX_STATE_TRYING) {
458 /* Request is received. */
459 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
Benny Prijono0c2bc612006-01-10 13:31:40 +0000460
461 /* Check that status code is status_code. */
462 if (tsx->status_code != TEST4_STATUS_CODE) {
Benny Prijono02b8fd82006-06-26 15:12:55 +0000463 PJ_LOG(3,(THIS_FILE,
464 " error: incorrect status code %d "
465 "(expecting %d)", tsx->status_code,
466 TEST4_STATUS_CODE));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000467 test_complete = -120;
468 }
469
470 /* Previous state. */
471 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
472 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
473 test_complete = -121;
474 }
475
476 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED)
477 {
Benny Prijono02b8fd82006-06-26 15:12:55 +0000478 PJ_LOG(3,(THIS_FILE, " error: unexpected state %s (122)",
479 pjsip_tsx_state_str(tsx->state)));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000480 test_complete = -122;
481
482 }
483
484
485 } else
486 if (pj_strcmp2(&tsx->branch, TEST5_BRANCH_ID)==0) {
487 /*
488 * TEST5_BRANCH_ID tests receiving retransmissions in PROCEEDING state
489 */
Benny Prijono02b8fd82006-06-26 15:12:55 +0000490 if (tsx->state == PJSIP_TSX_STATE_TRYING) {
491 /* Request is received. */
492
493 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
Benny Prijono0c2bc612006-01-10 13:31:40 +0000494
495 /* Check that status code is status_code. */
496 if (tsx->status_code != TEST5_STATUS_CODE) {
497 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
498 test_complete = -130;
499 }
500
501 /* Previous state. */
502 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
503 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
504 test_complete = -131;
505 }
506
507 } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
508
509 /* Check status code. */
510 if (tsx->status_code != TEST5_PROVISIONAL_CODE) {
511 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
512 test_complete = -132;
513 }
514
515 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) {
Benny Prijono02b8fd82006-06-26 15:12:55 +0000516 PJ_LOG(3,(THIS_FILE, " error: unexpected state %s (133)",
517 pjsip_tsx_state_str(tsx->state)));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000518 test_complete = -133;
519
520 }
521
522 } else
523 if (pj_strcmp2(&tsx->branch, TEST6_BRANCH_ID)==0) {
524 /*
525 * TEST6_BRANCH_ID tests receiving retransmissions in COMPLETED state
526 */
Benny Prijono02b8fd82006-06-26 15:12:55 +0000527 if (tsx->state == PJSIP_TSX_STATE_TRYING) {
528 /* Request is received. */
529
530 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
Benny Prijono0c2bc612006-01-10 13:31:40 +0000531
532 /* Check that status code is status_code. */
533 if (tsx->status_code != TEST6_STATUS_CODE) {
Benny Prijonoe93e2872006-06-28 16:46:49 +0000534 PJ_LOG(3,(THIS_FILE, " error: incorrect status code %d "
535 "(expecting %d)", tsx->status_code,
536 TEST6_STATUS_CODE));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000537 test_complete = -140;
538 }
539
540 /* Previous state. */
541 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
542 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
543 test_complete = -141;
544 }
545
546 } else if (tsx->state != PJSIP_TSX_STATE_PROCEEDING &&
547 tsx->state != PJSIP_TSX_STATE_COMPLETED &&
548 tsx->state != PJSIP_TSX_STATE_DESTROYED)
549 {
Benny Prijono02b8fd82006-06-26 15:12:55 +0000550 PJ_LOG(3,(THIS_FILE, " error: unexpected state %s (142)",
551 pjsip_tsx_state_str(tsx->state)));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000552 test_complete = -142;
553
554 }
555
556
557 } else
558 if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID)==0 ||
559 pj_strcmp2(&tsx->branch, TEST8_BRANCH_ID)==0)
560 {
561 /*
562 * TEST7_BRANCH_ID and TEST8_BRANCH_ID test retransmission of
563 * INVITE final response
564 */
565 int code;
566
567 if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID) == 0)
568 code = TEST7_STATUS_CODE;
569 else
570 code = TEST8_STATUS_CODE;
571
Benny Prijono02b8fd82006-06-26 15:12:55 +0000572 if (tsx->state == PJSIP_TSX_STATE_TRYING) {
573 /* Request is received. */
574
575 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
Benny Prijono0c2bc612006-01-10 13:31:40 +0000576
577 if (test_complete == 0)
578 test_complete = 1;
579
580 /* Check status code. */
581 if (tsx->status_code != PJSIP_SC_TSX_TIMEOUT) {
582 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
583 test_complete = -150;
584 }
585
586 /* Previous state. */
587 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
588 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
589 test_complete = -151;
590 }
591
Benny Prijonoe93e2872006-06-28 16:46:49 +0000592 /* Check the number of retransmissions */
593 if (tp_flag & PJSIP_TRANSPORT_RELIABLE) {
594
595 if (tsx->retransmit_count != 0) {
596 PJ_LOG(3,(THIS_FILE, " error: should not retransmit"));
597 test_complete = -1510;
598 }
599
600 } else {
601
602 if (tsx->retransmit_count != 10) {
603 PJ_LOG(3,(THIS_FILE,
604 " error: incorrect retransmit count %d "
605 "(expecting 10)",
606 tsx->retransmit_count));
607 test_complete = -1510;
608 }
609
610 }
611
Benny Prijono0c2bc612006-01-10 13:31:40 +0000612 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
613
614 /* Check that status code is status_code. */
615 if (tsx->status_code != code) {
616 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
617 test_complete = -152;
618 }
619
620 /* Previous state. */
621 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
622 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
623 test_complete = -153;
624 }
625
626 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) {
627
Benny Prijono02b8fd82006-06-26 15:12:55 +0000628 PJ_LOG(3,(THIS_FILE, " error: unexpected state (154)"));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000629 test_complete = -154;
630
631 }
632
Benny Prijono728a9052006-01-18 23:34:15 +0000633
634 } else
635 if (pj_strcmp2(&tsx->branch, TEST9_BRANCH_ID)==0) {
636 /*
637 * TEST9_BRANCH_ID tests that retransmission of INVITE final response
638 * must cease when ACK is received.
639 */
640
Benny Prijono02b8fd82006-06-26 15:12:55 +0000641 if (tsx->state == PJSIP_TSX_STATE_TRYING) {
642 /* Request is received. */
643
644 } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
Benny Prijono728a9052006-01-18 23:34:15 +0000645
646 if (test_complete == 0)
647 test_complete = 1;
648
649 /* Check status code. */
650 if (tsx->status_code != TEST9_STATUS_CODE) {
651 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
652 test_complete = -160;
653 }
654
655 /* Previous state. */
656 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_CONFIRMED) {
657 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
658 test_complete = -161;
659 }
660
661 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
662
663 /* Check that status code is status_code. */
664 if (tsx->status_code != TEST9_STATUS_CODE) {
665 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
666 test_complete = -162;
667 }
668
669 /* Previous state. */
670 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
671 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
672 test_complete = -163;
673 }
674
675
676 } else if (tsx->state == PJSIP_TSX_STATE_CONFIRMED) {
677
678 /* Check that status code is status_code. */
679 if (tsx->status_code != TEST9_STATUS_CODE) {
680 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
681 test_complete = -164;
682 }
683
684 /* Previous state. */
685 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
686 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
687 test_complete = -165;
688 }
689
690 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) {
691
Benny Prijono02b8fd82006-06-26 15:12:55 +0000692 PJ_LOG(3,(THIS_FILE, " error: unexpected state (166)"));
Benny Prijono728a9052006-01-18 23:34:15 +0000693 test_complete = -166;
694
695 }
696
697
698 } else
699 if (pj_strcmp2(&tsx->branch, TEST10_BRANCH_ID)==0 ||
700 pj_strcmp2(&tsx->branch, TEST11_BRANCH_ID)==0 ||
701 pj_strcmp2(&tsx->branch, TEST12_BRANCH_ID)==0)
702 {
703 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
704
705 if (!test_complete)
706 test_complete = 1;
707
708 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
709 PJ_LOG(3,(THIS_FILE," error: incorrect status code"));
710 test_complete = -170;
711 }
712 }
Benny Prijonodbe337a2006-01-08 23:57:52 +0000713 }
714
715}
716
717/* Save transaction key to global variables. */
718static void save_key(pjsip_transaction *tsx)
719{
720 pj_str_t key;
721
722 pj_strdup(tsx->pool, &key, &tsx->transaction_key);
723 pj_strcpy(&tsx_key, &key);
724}
725
Benny Prijono0c2bc612006-01-10 13:31:40 +0000726#define DIFF(a,b) ((a<b) ? (b-a) : (a-b))
727
Benny Prijonodbe337a2006-01-08 23:57:52 +0000728/*
729 * Message receiver handler.
730 */
731static pj_bool_t on_rx_message(pjsip_rx_data *rdata)
732{
733 pjsip_msg *msg = rdata->msg_info.msg;
734 pj_str_t branch_param = rdata->msg_info.via->branch_param;
735 pj_status_t status;
736
737 if (pj_strcmp2(&branch_param, TEST1_BRANCH_ID) == 0 ||
738 pj_strcmp2(&branch_param, TEST2_BRANCH_ID) == 0)
739 {
740 /*
741 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits 2xx
742 * final response using correct transport and terminates transaction
743 * after 32 seconds.
744 *
745 * TEST2_BRANCH_ID performs similar test for non-2xx final response.
746 */
747 int status_code = (pj_strcmp2(&branch_param, TEST1_BRANCH_ID) == 0) ?
748 TEST1_STATUS_CODE : TEST2_STATUS_CODE;
749
750 if (msg->type == PJSIP_REQUEST_MSG) {
Benny Prijono728a9052006-01-18 23:34:15 +0000751 /* On received request, create UAS and respond with final
Benny Prijonodbe337a2006-01-08 23:57:52 +0000752 * response.
753 */
754 pjsip_transaction *tsx;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000755
756 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
757 if (status != PJ_SUCCESS) {
758 app_perror(" error: unable to create transaction", status);
759 test_complete = -110;
760 return PJ_TRUE;
761 }
Benny Prijono38998232006-02-08 22:44:25 +0000762 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000763
764 save_key(tsx);
Benny Prijono0c2bc612006-01-10 13:31:40 +0000765 send_response(rdata, tsx, status_code);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000766
767 } else {
768 /* Verify the response received. */
769
770 ++recv_count;
771
772 /* Verify status code. */
773 if (msg->line.status.code != status_code) {
774 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
775 test_complete = -113;
776 }
777
778 /* Verify that no retransmissions is received. */
779 if (recv_count > 1) {
780 PJ_LOG(3,(THIS_FILE, " error: retransmission received"));
781 test_complete = -114;
782 }
783
784 }
785 return PJ_TRUE;
786
787 } else if (pj_strcmp2(&branch_param, TEST3_BRANCH_ID) == 0) {
788
789 /* TEST3_BRANCH_ID tests provisional response. */
790
791 if (msg->type == PJSIP_REQUEST_MSG) {
Benny Prijono728a9052006-01-18 23:34:15 +0000792 /* On received request, create UAS and respond with provisional
Benny Prijonodbe337a2006-01-08 23:57:52 +0000793 * response, then schedule timer to send final response.
794 */
795 pjsip_transaction *tsx;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000796
797 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
798 if (status != PJ_SUCCESS) {
799 app_perror(" error: unable to create transaction", status);
Benny Prijono02b8fd82006-06-26 15:12:55 +0000800 test_complete = -116;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000801 return PJ_TRUE;
802 }
Benny Prijono38998232006-02-08 22:44:25 +0000803 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000804
805 save_key(tsx);
806
Benny Prijono0c2bc612006-01-10 13:31:40 +0000807 send_response(rdata, tsx, TEST3_PROVISIONAL_CODE);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000808 schedule_send_response(rdata, &tsx->transaction_key,
809 TEST3_STATUS_CODE, 2000);
810
811 } else {
812 /* Verify the response received. */
813
814 ++recv_count;
815
816 if (recv_count == 1) {
817 /* Verify status code. */
818 if (msg->line.status.code != TEST3_PROVISIONAL_CODE) {
819 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
820 test_complete = -123;
821 }
822 } else if (recv_count == 2) {
823 /* Verify status code. */
824 if (msg->line.status.code != TEST3_STATUS_CODE) {
825 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
826 test_complete = -124;
827 }
828 } else {
829 PJ_LOG(3,(THIS_FILE, " error: retransmission received"));
830 test_complete = -125;
831 }
832
833 }
834 return PJ_TRUE;
835
Benny Prijono0c2bc612006-01-10 13:31:40 +0000836 } else if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0 ||
837 pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0 ||
838 pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0)
839 {
840
841 /* TEST4_BRANCH_ID: absorbs retransmissions in TRYING state. */
842 /* TEST5_BRANCH_ID: retransmit last response in PROCEEDING state. */
843 /* TEST6_BRANCH_ID: retransmit last response in COMPLETED state. */
844
845 if (msg->type == PJSIP_REQUEST_MSG) {
Benny Prijono728a9052006-01-18 23:34:15 +0000846 /* On received request, create UAS. */
Benny Prijono0c2bc612006-01-10 13:31:40 +0000847 pjsip_transaction *tsx;
848
Benny Prijonoe93e2872006-06-28 16:46:49 +0000849 PJ_LOG(4,(THIS_FILE, " received request (probably retransmission)"));
850
Benny Prijono0c2bc612006-01-10 13:31:40 +0000851 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
852 if (status != PJ_SUCCESS) {
853 app_perror(" error: unable to create transaction", status);
854 test_complete = -130;
855 return PJ_TRUE;
856 }
857
Benny Prijono38998232006-02-08 22:44:25 +0000858 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijono0c2bc612006-01-10 13:31:40 +0000859 save_key(tsx);
860
861 if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0) {
862
863 } else if (pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0) {
864 send_response(rdata, tsx, TEST5_PROVISIONAL_CODE);
865
866 } else if (pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0) {
Benny Prijonoe93e2872006-06-28 16:46:49 +0000867 PJ_LOG(4,(THIS_FILE, " sending provisional response"));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000868 send_response(rdata, tsx, TEST6_PROVISIONAL_CODE);
Benny Prijonoe93e2872006-06-28 16:46:49 +0000869 PJ_LOG(4,(THIS_FILE, " sending final response"));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000870 send_response(rdata, tsx, TEST6_STATUS_CODE);
871 }
872
873 } else {
874 /* Verify the response received. */
875
Benny Prijonoe93e2872006-06-28 16:46:49 +0000876 PJ_LOG(4,(THIS_FILE, " received response number %d", recv_count));
877
Benny Prijono0c2bc612006-01-10 13:31:40 +0000878 ++recv_count;
879
880 if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0) {
881 PJ_LOG(3,(THIS_FILE, " error: not expecting response!"));
882 test_complete = -132;
883
884 } else if (pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0) {
885
886 if (rdata->msg_info.msg->line.status.code!=TEST5_PROVISIONAL_CODE) {
887 PJ_LOG(3,(THIS_FILE, " error: incorrect status code!"));
888 test_complete = -133;
889
890 }
891 if (recv_count > TEST5_RESPONSE_COUNT) {
892 PJ_LOG(3,(THIS_FILE, " error: not expecting response!"));
893 test_complete = -134;
894 }
895
896 } else if (pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0) {
897
898 int code = rdata->msg_info.msg->line.status.code;
899
900 switch (recv_count) {
901 case 1:
902 if (code != TEST6_PROVISIONAL_CODE) {
903 PJ_LOG(3,(THIS_FILE, " error: invalid code!"));
904 test_complete = -135;
905 }
906 break;
907 case 2:
908 case 3:
909 if (code != TEST6_STATUS_CODE) {
Benny Prijonoe93e2872006-06-28 16:46:49 +0000910 PJ_LOG(3,(THIS_FILE, " error: invalid code %d "
911 "(expecting %d)", code, TEST6_STATUS_CODE));
Benny Prijono0c2bc612006-01-10 13:31:40 +0000912 test_complete = -136;
913 }
914 break;
915 default:
916 PJ_LOG(3,(THIS_FILE, " error: not expecting response"));
917 test_complete = -137;
918 break;
919 }
920 }
921 }
922 return PJ_TRUE;
923
924
925 } else if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0 ||
926 pj_strcmp2(&branch_param, TEST8_BRANCH_ID) == 0)
927 {
928
929 /*
930 * TEST7_BRANCH_ID and TEST8_BRANCH_ID test the retransmission
931 * of INVITE final response
932 */
933 if (msg->type == PJSIP_REQUEST_MSG) {
934
Benny Prijono728a9052006-01-18 23:34:15 +0000935 /* On received request, create UAS. */
Benny Prijono0c2bc612006-01-10 13:31:40 +0000936 pjsip_transaction *tsx;
937
938 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
939 if (status != PJ_SUCCESS) {
940 app_perror(" error: unable to create transaction", status);
941 test_complete = -140;
942 return PJ_TRUE;
943 }
944
Benny Prijono38998232006-02-08 22:44:25 +0000945 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijono0c2bc612006-01-10 13:31:40 +0000946 save_key(tsx);
947
948 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0) {
949
950 send_response(rdata, tsx, TEST7_STATUS_CODE);
951
952 } else {
953
954 send_response(rdata, tsx, TEST8_STATUS_CODE);
955
956 }
957
958 } else {
959 int code;
960
961 ++recv_count;
962
963 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0)
964 code = TEST7_STATUS_CODE;
965 else
966 code = TEST8_STATUS_CODE;
967
968 if (recv_count==1) {
969
970 if (rdata->msg_info.msg->line.status.code != code) {
971 PJ_LOG(3,(THIS_FILE," error: invalid status code"));
972 test_complete = -141;
973 }
974
975 recv_last = rdata->pkt_info.timestamp;
976
977 } else {
978
979 pj_time_val now;
980 unsigned msec, msec_expected;
981
982 now = rdata->pkt_info.timestamp;
983
984 PJ_TIME_VAL_SUB(now, recv_last);
985
986 msec = now.sec*1000 + now.msec;
987 msec_expected = (1 << (recv_count-2)) * PJSIP_T1_TIMEOUT;
988 if (msec_expected > PJSIP_T2_TIMEOUT)
989 msec_expected = PJSIP_T2_TIMEOUT;
990
991 if (DIFF(msec, msec_expected) > MAX_ALLOWED_DIFF) {
992 PJ_LOG(3,(THIS_FILE,
993 " error: incorrect retransmission "
994 "time (%d ms expected, %d ms received",
995 msec_expected, msec));
996 test_complete = -142;
997 }
998
999 if (recv_count > 11) {
1000 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)",
1001 recv_count));
1002 test_complete = -143;
1003 }
1004
1005 recv_last = rdata->pkt_info.timestamp;
1006 }
1007
1008 }
1009 return PJ_TRUE;
1010
Benny Prijono728a9052006-01-18 23:34:15 +00001011 } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID) == 0) {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001012
1013 /*
1014 * TEST9_BRANCH_ID tests that the retransmission of INVITE final
1015 * response should cease when ACK is received. Transaction also MUST
1016 * terminate in T4 seconds.
1017 */
1018 if (msg->type == PJSIP_REQUEST_MSG) {
1019
Benny Prijono728a9052006-01-18 23:34:15 +00001020 /* On received request, create UAS. */
Benny Prijono0c2bc612006-01-10 13:31:40 +00001021 pjsip_transaction *tsx;
1022
1023 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
1024 if (status != PJ_SUCCESS) {
1025 app_perror(" error: unable to create transaction", status);
Benny Prijono728a9052006-01-18 23:34:15 +00001026 test_complete = -150;
Benny Prijono0c2bc612006-01-10 13:31:40 +00001027 return PJ_TRUE;
1028 }
1029
Benny Prijono38998232006-02-08 22:44:25 +00001030 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001031 save_key(tsx);
Benny Prijono728a9052006-01-18 23:34:15 +00001032 send_response(rdata, tsx, TEST9_STATUS_CODE);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001033
Benny Prijono0c2bc612006-01-10 13:31:40 +00001034
1035 } else {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001036
1037 ++recv_count;
1038
Benny Prijono728a9052006-01-18 23:34:15 +00001039 if (rdata->msg_info.msg->line.status.code != TEST9_STATUS_CODE) {
1040 PJ_LOG(3,(THIS_FILE," error: invalid status code"));
1041 test_complete = -151;
1042 }
Benny Prijono0c2bc612006-01-10 13:31:40 +00001043
1044 if (recv_count==1) {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001045
1046 recv_last = rdata->pkt_info.timestamp;
1047
Benny Prijono728a9052006-01-18 23:34:15 +00001048 } else if (recv_count < 5) {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001049
Benny Prijono728a9052006-01-18 23:34:15 +00001050 /* Let UAS retransmit some messages before we send ACK. */
Benny Prijono0c2bc612006-01-10 13:31:40 +00001051 pj_time_val now;
1052 unsigned msec, msec_expected;
1053
1054 now = rdata->pkt_info.timestamp;
1055
1056 PJ_TIME_VAL_SUB(now, recv_last);
1057
1058 msec = now.sec*1000 + now.msec;
1059 msec_expected = (1 << (recv_count-2)) * PJSIP_T1_TIMEOUT;
1060 if (msec_expected > PJSIP_T2_TIMEOUT)
1061 msec_expected = PJSIP_T2_TIMEOUT;
1062
1063 if (DIFF(msec, msec_expected) > MAX_ALLOWED_DIFF) {
1064 PJ_LOG(3,(THIS_FILE,
1065 " error: incorrect retransmission "
1066 "time (%d ms expected, %d ms received",
1067 msec_expected, msec));
Benny Prijono728a9052006-01-18 23:34:15 +00001068 test_complete = -152;
Benny Prijono0c2bc612006-01-10 13:31:40 +00001069 }
1070
1071 recv_last = rdata->pkt_info.timestamp;
Benny Prijono728a9052006-01-18 23:34:15 +00001072
1073 } else if (recv_count == 5) {
1074 pjsip_tx_data *tdata;
1075 pjsip_sip_uri *uri;
1076 pjsip_via_hdr *via;
1077
1078 status = pjsip_endpt_create_request_from_hdr(
1079 endpt, &pjsip_ack_method,
1080 rdata->msg_info.to->uri,
1081 rdata->msg_info.from,
1082 rdata->msg_info.to,
1083 NULL,
1084 rdata->msg_info.cid,
1085 rdata->msg_info.cseq->cseq,
1086 NULL,
1087 &tdata);
1088 if (status != PJ_SUCCESS) {
1089 app_perror(" error: unable to create ACK", status);
1090 test_complete = -153;
1091 return PJ_TRUE;
1092 }
1093
1094 uri=(pjsip_sip_uri*)pjsip_uri_get_uri(tdata->msg->line.req.uri);
1095 uri->transport_param = pj_str("loop-dgram");
1096
1097 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1098 via->branch_param = pj_str(TEST9_BRANCH_ID);
1099
1100 status = pjsip_endpt_send_request_stateless(endpt, tdata,
1101 NULL, NULL);
1102 if (status != PJ_SUCCESS) {
1103 app_perror(" error: unable to send ACK", status);
1104 test_complete = -154;
1105 }
1106
1107 } else {
1108 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)",
1109 recv_count));
1110 test_complete = -155;
Benny Prijono0c2bc612006-01-10 13:31:40 +00001111 }
1112
1113 }
1114 return PJ_TRUE;
Benny Prijono728a9052006-01-18 23:34:15 +00001115
1116 } else if (pj_strcmp2(&branch_param, TEST10_BRANCH_ID) == 0 ||
1117 pj_strcmp2(&branch_param, TEST11_BRANCH_ID) == 0 ||
1118 pj_strcmp2(&branch_param, TEST12_BRANCH_ID) == 0)
1119 {
1120 int test_num, code1, code2;
1121
1122 if (pj_strcmp2(&branch_param, TEST10_BRANCH_ID) == 0)
1123 test_num=10, code1 = 100, code2 = 0;
1124 else if (pj_strcmp2(&branch_param, TEST11_BRANCH_ID) == 0)
1125 test_num=11, code1 = 100, code2 = 200;
1126 else
1127 test_num=12, code1 = 200, code2 = 0;
1128
1129 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
1130
1131 /* On received response, create UAS. */
1132 pjsip_transaction *tsx;
1133
1134 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
1135 if (status != PJ_SUCCESS) {
1136 app_perror(" error: unable to create transaction", status);
1137 test_complete = -150;
1138 return PJ_TRUE;
1139 }
1140
Benny Prijono38998232006-02-08 22:44:25 +00001141 pjsip_tsx_recv_msg(tsx, rdata);
Benny Prijono728a9052006-01-18 23:34:15 +00001142 save_key(tsx);
1143
1144 schedule_send_response(rdata, &tsx_key, code1, 1000);
1145
1146 if (code2)
1147 schedule_send_response(rdata, &tsx_key, code2, 2000);
1148
1149 } else {
1150
1151 }
1152
1153 return PJ_TRUE;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001154 }
1155
1156 return PJ_FALSE;
1157}
1158
1159/*
1160 * The generic test framework, used by most of the tests.
1161 */
1162static int perform_test( char *target_uri, char *from_uri,
1163 char *branch_param, int test_time,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001164 const pjsip_method *method,
1165 int request_cnt, int request_interval_msec,
1166 int expecting_timeout)
Benny Prijonodbe337a2006-01-08 23:57:52 +00001167{
1168 pjsip_tx_data *tdata;
1169 pj_str_t target, from;
1170 pjsip_via_hdr *via;
Benny Prijono0c2bc612006-01-10 13:31:40 +00001171 pj_time_val timeout, next_send;
1172 int sent_cnt;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001173 pj_status_t status;
1174
1175 PJ_LOG(3,(THIS_FILE,
1176 " please standby, this will take at most %d seconds..",
1177 test_time));
1178
1179 /* Reset test. */
1180 recv_count = 0;
1181 test_complete = 0;
1182 tsx_key.slen = 0;
1183
1184 /* Init headers. */
1185 target = pj_str(target_uri);
1186 from = pj_str(from_uri);
1187
1188 /* Create request. */
1189 status = pjsip_endpt_create_request( endpt, method, &target,
1190 &from, &target, NULL, NULL, -1,
1191 NULL, &tdata);
1192 if (status != PJ_SUCCESS) {
1193 app_perror(" Error: unable to create request", status);
1194 return -10;
1195 }
1196
1197 /* Set the branch param for test 1. */
1198 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1199 via->branch_param = pj_str(branch_param);
1200
Benny Prijono0c2bc612006-01-10 13:31:40 +00001201 /* Schedule first send. */
1202 sent_cnt = 0;
1203 pj_gettimeofday(&next_send);
1204 pj_time_val_normalize(&next_send);
Benny Prijonodbe337a2006-01-08 23:57:52 +00001205
1206 /* Set test completion time. */
1207 pj_gettimeofday(&timeout);
1208 timeout.sec += test_time;
1209
1210 /* Wait until test complete. */
1211 while (!test_complete) {
1212 pj_time_val now, poll_delay = {0, 10};
1213
1214 pjsip_endpt_handle_events(endpt, &poll_delay);
1215
1216 pj_gettimeofday(&now);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001217
1218 if (sent_cnt < request_cnt && PJ_TIME_VAL_GTE(now, next_send)) {
1219 /* Add additional reference to tdata to prevent transaction from
1220 * deleting it.
1221 */
1222 pjsip_tx_data_add_ref(tdata);
1223
1224 /* (Re)Send the request. */
Benny Prijonoe93e2872006-06-28 16:46:49 +00001225 PJ_LOG(4,(THIS_FILE, " (re)sending request %d", sent_cnt));
1226
Benny Prijono0c2bc612006-01-10 13:31:40 +00001227 status = pjsip_endpt_send_request_stateless(endpt, tdata, 0, 0);
1228 if (status != PJ_SUCCESS) {
1229 app_perror(" Error: unable to send request", status);
1230 pjsip_tx_data_dec_ref(tdata);
1231 return -20;
1232 }
1233
1234 /* Schedule next send, if any. */
1235 sent_cnt++;
1236 if (sent_cnt < request_cnt) {
1237 pj_gettimeofday(&next_send);
1238 next_send.msec += request_interval_msec;
1239 pj_time_val_normalize(&next_send);
1240 }
1241 }
1242
Benny Prijonodbe337a2006-01-08 23:57:52 +00001243 if (now.sec > timeout.sec) {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001244 if (!expecting_timeout)
1245 PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
Benny Prijonodbe337a2006-01-08 23:57:52 +00001246 pjsip_tx_data_dec_ref(tdata);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001247 return TEST_TIMEOUT_ERROR;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001248 }
1249 }
1250
1251 if (test_complete < 0) {
1252 pjsip_transaction *tsx;
1253
1254 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
1255 if (tsx) {
1256 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
1257 pj_mutex_unlock(tsx->mutex);
1258 flush_events(1000);
1259 }
1260 pjsip_tx_data_dec_ref(tdata);
1261 return test_complete;
1262 }
1263
1264 /* Allow transaction to destroy itself */
1265 flush_events(500);
1266
1267 /* Make sure transaction has been destroyed. */
1268 if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
1269 PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
1270 pjsip_tx_data_dec_ref(tdata);
1271 return -40;
1272 }
1273
1274 /* Check tdata reference counter. */
1275 if (pj_atomic_get(tdata->ref_cnt) != 1) {
1276 PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
1277 pj_atomic_get(tdata->ref_cnt)));
1278 pjsip_tx_data_dec_ref(tdata);
1279 return -50;
1280 }
1281
1282 /* Destroy txdata */
1283 pjsip_tx_data_dec_ref(tdata);
1284
1285 return PJ_SUCCESS;
1286
1287}
1288
1289
1290/*****************************************************************************
1291 **
1292 ** TEST1_BRANCH_ID: Basic 2xx final response
1293 ** TEST2_BRANCH_ID: Basic non-2xx final response
1294 **
1295 *****************************************************************************
1296 */
1297static int tsx_basic_final_response_test(void)
1298{
Benny Prijonoe93e2872006-06-28 16:46:49 +00001299 unsigned duration;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001300 int status;
1301
1302 PJ_LOG(3,(THIS_FILE," test1: basic sending 2xx final response"));
1303
Benny Prijonoe93e2872006-06-28 16:46:49 +00001304 /* Test duration must be greater than 32 secs if unreliable transport
1305 * is used.
1306 */
1307 duration = (tp_flag & PJSIP_TRANSPORT_RELIABLE) ? 1 : 33;
1308
1309 status = perform_test(TARGET_URI, FROM_URI, TEST1_BRANCH_ID,
1310 duration, &pjsip_options_method, 1, 0, 0);
Benny Prijonodbe337a2006-01-08 23:57:52 +00001311 if (status != 0)
1312 return status;
1313
1314 PJ_LOG(3,(THIS_FILE," test2: basic sending non-2xx final response"));
1315
Benny Prijonoe93e2872006-06-28 16:46:49 +00001316 status = perform_test(TARGET_URI, FROM_URI, TEST2_BRANCH_ID,
1317 duration, &pjsip_options_method, 1, 0, 0);
Benny Prijonodbe337a2006-01-08 23:57:52 +00001318 if (status != 0)
1319 return status;
1320
1321 return 0;
1322}
1323
1324
1325/*****************************************************************************
1326 **
1327 ** TEST3_BRANCH_ID: Sending provisional response
1328 **
1329 *****************************************************************************
1330 */
1331static int tsx_basic_provisional_response_test(void)
1332{
Benny Prijonoe93e2872006-06-28 16:46:49 +00001333 unsigned duration;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001334 int status;
1335
Benny Prijono02b8fd82006-06-26 15:12:55 +00001336 PJ_LOG(3,(THIS_FILE," test3: basic sending 2xx final response"));
Benny Prijonodbe337a2006-01-08 23:57:52 +00001337
Benny Prijonoe93e2872006-06-28 16:46:49 +00001338 duration = (tp_flag & PJSIP_TRANSPORT_RELIABLE) ? 1 : 33;
1339 duration += 2;
1340
1341 status = perform_test(TARGET_URI, FROM_URI, TEST3_BRANCH_ID, duration,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001342 &pjsip_options_method, 1, 0, 0);
1343
Benny Prijonodbe337a2006-01-08 23:57:52 +00001344 return status;
1345}
1346
1347
1348/*****************************************************************************
1349 **
Benny Prijono0c2bc612006-01-10 13:31:40 +00001350 ** TEST4_BRANCH_ID: Absorbs retransmissions in TRYING state
1351 ** TEST5_BRANCH_ID: Absorbs retransmissions in PROCEEDING state
1352 ** TEST6_BRANCH_ID: Absorbs retransmissions in COMPLETED state
1353 **
1354 *****************************************************************************
1355 */
1356static int tsx_retransmit_last_response_test(const char *title,
1357 char *branch_id,
1358 int request_cnt,
1359 int status_code)
1360{
1361 int status;
1362
1363 PJ_LOG(3,(THIS_FILE," %s", title));
1364
Benny Prijonoe93e2872006-06-28 16:46:49 +00001365 status = perform_test(TARGET_URI, FROM_URI, branch_id, 5,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001366 &pjsip_options_method,
1367 request_cnt, 1000, 1);
1368 if (status && status != TEST_TIMEOUT_ERROR)
1369 return status;
1370 if (!status) {
1371 PJ_LOG(3,(THIS_FILE, " error: expecting timeout"));
1372 return -31;
1373 }
1374
1375 terminate_our_tsx(status_code);
1376 flush_events(100);
1377
1378 if (test_complete != 1)
1379 return test_complete;
1380
1381 flush_events(100);
1382 return 0;
1383}
1384
1385/*****************************************************************************
1386 **
1387 ** TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test
1388 ** TEST8_BRANCH_ID: INVITE 2xx final response retransmission test
1389 **
1390 *****************************************************************************
1391 */
1392static int tsx_final_response_retransmission_test(void)
1393{
1394 int status;
1395
1396 PJ_LOG(3,(THIS_FILE,
1397 " test7: INVITE non-2xx final response retransmission"));
1398
Benny Prijonoe93e2872006-06-28 16:46:49 +00001399 status = perform_test(TARGET_URI, FROM_URI, TEST7_BRANCH_ID,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001400 33, /* Test duration must be greater than 32 secs */
1401 &pjsip_invite_method, 1, 0, 0);
1402 if (status != 0)
1403 return status;
1404
1405 PJ_LOG(3,(THIS_FILE,
1406 " test8: INVITE 2xx final response retransmission"));
1407
Benny Prijonoe93e2872006-06-28 16:46:49 +00001408 status = perform_test(TARGET_URI, FROM_URI, TEST8_BRANCH_ID,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001409 33, /* Test duration must be greater than 32 secs */
1410 &pjsip_invite_method, 1, 0, 0);
1411 if (status != 0)
1412 return status;
1413
1414 return 0;
1415}
1416
1417
Benny Prijono728a9052006-01-18 23:34:15 +00001418/*****************************************************************************
1419 **
1420 ** TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must
1421 ** cease when ACK is received
1422 **
1423 *****************************************************************************
1424 */
1425static int tsx_ack_test(void)
1426{
1427 int status;
1428
1429 PJ_LOG(3,(THIS_FILE,
1430 " test9: receiving ACK for non-2xx final response"));
1431
Benny Prijonoe93e2872006-06-28 16:46:49 +00001432 status = perform_test(TARGET_URI, FROM_URI, TEST9_BRANCH_ID,
Benny Prijono728a9052006-01-18 23:34:15 +00001433 20, /* allow 5 retransmissions */
1434 &pjsip_invite_method, 1, 0, 0);
1435 if (status != 0)
1436 return status;
1437
1438
1439 return 0;
1440}
1441
1442
1443
1444/*****************************************************************************
1445 **
1446 ** TEST10_BRANCH_ID: test transport failure in TRYING state.
1447 ** TEST11_BRANCH_ID: test transport failure in PROCEEDING state.
1448 ** TEST12_BRANCH_ID: test transport failure in CONNECTED state.
1449 ** TEST13_BRANCH_ID: test transport failure in CONFIRMED state.
1450 **
1451 *****************************************************************************
1452 */
1453static int tsx_transport_failure_test(void)
1454{
1455 struct test_desc
1456 {
1457 int transport_delay;
1458 int fail_delay;
1459 char *branch_id;
1460 char *title;
1461 } tests[] =
1462 {
1463 { 0, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (no delay)" },
1464 { 50, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (50 ms delay)" },
1465 { 0, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (no delay)" },
1466 { 50, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (50 ms delay)" },
1467 { 0, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (no delay)" },
1468 { 50, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (50 ms delay)" },
1469 };
1470 int i, status;
1471
1472 for (i=0; i<PJ_ARRAY_SIZE(tests); ++i) {
1473 pj_time_val fail_time, end_test, now;
1474
1475 PJ_LOG(3,(THIS_FILE, " %s", tests[i].title));
1476 pjsip_loop_set_failure(loop, 0, NULL);
1477 pjsip_loop_set_delay(loop, tests[i].transport_delay);
1478
Benny Prijonoe93e2872006-06-28 16:46:49 +00001479 status = perform_test(TARGET_URI, FROM_URI, tests[i].branch_id,
1480 0, &pjsip_invite_method, 1, 0, 1);
Benny Prijono728a9052006-01-18 23:34:15 +00001481 if (status && status != TEST_TIMEOUT_ERROR)
1482 return status;
1483 if (!status) {
1484 PJ_LOG(3,(THIS_FILE, " error: expecting timeout"));
1485 return -40;
1486 }
1487
1488 pj_gettimeofday(&fail_time);
1489 fail_time.msec += tests[i].fail_delay;
1490 pj_time_val_normalize(&fail_time);
1491
1492 do {
1493 pj_time_val interval = { 0, 1 };
1494 pj_gettimeofday(&now);
1495 pjsip_endpt_handle_events(endpt, &interval);
1496 } while (PJ_TIME_VAL_LT(now, fail_time));
1497
1498 pjsip_loop_set_failure(loop, 1, NULL);
1499
1500 end_test = now;
1501 end_test.sec += 5;
1502
1503 do {
1504 pj_time_val interval = { 0, 1 };
1505 pj_gettimeofday(&now);
1506 pjsip_endpt_handle_events(endpt, &interval);
1507 } while (!test_complete && PJ_TIME_VAL_LT(now, end_test));
1508
1509 if (test_complete == 0) {
1510 PJ_LOG(3,(THIS_FILE, " error: test has timed out"));
1511 return -41;
1512 }
1513
1514 if (test_complete != 1)
1515 return test_complete;
1516 }
1517
1518 return 0;
1519}
Benny Prijono0c2bc612006-01-10 13:31:40 +00001520
1521/*****************************************************************************
1522 **
Benny Prijonodbe337a2006-01-08 23:57:52 +00001523 ** UAS Transaction Test.
1524 **
1525 *****************************************************************************
1526 */
Benny Prijonoe93e2872006-06-28 16:46:49 +00001527int tsx_uas_test(struct tsx_test_param *param)
Benny Prijonodbe337a2006-01-08 23:57:52 +00001528{
1529 pj_sockaddr_in addr;
1530 pj_status_t status;
1531
Benny Prijonoe93e2872006-06-28 16:46:49 +00001532 test_param = param;
1533 tp_flag = pjsip_transport_get_flag_from_type(param->type);
1534
1535 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s",
1536 param->port, param->tp_type);
1537 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s",
1538 param->port, param->tp_type);
1539
Benny Prijonodbe337a2006-01-08 23:57:52 +00001540 /* Check if loop transport is configured. */
1541 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
1542 &addr, sizeof(addr), &loop);
1543 if (status != PJ_SUCCESS) {
1544 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
Benny Prijonoe93e2872006-06-28 16:46:49 +00001545 return -10;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001546 }
Benny Prijonodbe337a2006-01-08 23:57:52 +00001547 /* Register modules. */
1548 status = pjsip_endpt_register_module(endpt, &tsx_user);
1549 if (status != PJ_SUCCESS) {
1550 app_perror(" Error: unable to register module", status);
1551 return -3;
1552 }
1553 status = pjsip_endpt_register_module(endpt, &msg_sender);
1554 if (status != PJ_SUCCESS) {
1555 app_perror(" Error: unable to register module", status);
1556 return -4;
1557 }
1558
Benny Prijonodbe337a2006-01-08 23:57:52 +00001559 /* TEST1_BRANCH_ID: Basic 2xx final response.
1560 * TEST2_BRANCH_ID: Basic non-2xx final response.
1561 */
1562 status = tsx_basic_final_response_test();
1563 if (status != 0)
1564 return status;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001565
1566 /* TEST3_BRANCH_ID: with provisional response
1567 */
1568 status = tsx_basic_provisional_response_test();
1569 if (status != 0)
1570 return status;
1571
Benny Prijono0c2bc612006-01-10 13:31:40 +00001572 /* TEST4_BRANCH_ID: absorbs retransmissions in TRYING state
1573 */
1574 status = tsx_retransmit_last_response_test(TEST4_TITLE,
1575 TEST4_BRANCH_ID,
1576 TEST4_REQUEST_COUNT,
1577 TEST4_STATUS_CODE);
1578 if (status != 0)
1579 return status;
1580
1581 /* TEST5_BRANCH_ID: retransmit last response in PROCEEDING state
1582 */
1583 status = tsx_retransmit_last_response_test(TEST5_TITLE,
1584 TEST5_BRANCH_ID,
1585 TEST5_REQUEST_COUNT,
1586 TEST5_STATUS_CODE);
1587 if (status != 0)
1588 return status;
1589
Benny Prijonoe93e2872006-06-28 16:46:49 +00001590 /* TEST6_BRANCH_ID: retransmit last response in COMPLETED state
1591 * This only applies to non-reliable transports,
1592 * since UAS transaction is destroyed as soon
1593 * as final response is sent for reliable transports.
Benny Prijono0c2bc612006-01-10 13:31:40 +00001594 */
Benny Prijonoe93e2872006-06-28 16:46:49 +00001595 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
1596 status = tsx_retransmit_last_response_test(TEST6_TITLE,
1597 TEST6_BRANCH_ID,
1598 TEST6_REQUEST_COUNT,
1599 TEST6_STATUS_CODE);
1600 if (status != 0)
1601 return status;
1602 }
Benny Prijono0c2bc612006-01-10 13:31:40 +00001603
1604 /* TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test
1605 * TEST8_BRANCH_ID: INVITE 2xx final response retransmission test
1606 */
Benny Prijono0c2bc612006-01-10 13:31:40 +00001607 status = tsx_final_response_retransmission_test();
1608 if (status != 0)
1609 return status;
1610
Benny Prijono728a9052006-01-18 23:34:15 +00001611 /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must
1612 * cease when ACK is received
Benny Prijonoe93e2872006-06-28 16:46:49 +00001613 * Only applicable for non-reliable transports.
Benny Prijono728a9052006-01-18 23:34:15 +00001614 */
Benny Prijonoe93e2872006-06-28 16:46:49 +00001615 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
1616 status = tsx_ack_test();
1617 if (status != 0)
1618 return status;
1619 }
1620
Benny Prijono728a9052006-01-18 23:34:15 +00001621
1622 /* TEST10_BRANCH_ID: test transport failure in TRYING state.
1623 * TEST11_BRANCH_ID: test transport failure in PROCEEDING state.
1624 * TEST12_BRANCH_ID: test transport failure in CONNECTED state.
1625 * TEST13_BRANCH_ID: test transport failure in CONFIRMED state.
1626 */
Benny Prijonoe93e2872006-06-28 16:46:49 +00001627 /* Only valid for loop-dgram */
1628 if (param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
1629 status = tsx_transport_failure_test();
1630 if (status != 0)
1631 return status;
1632 }
Benny Prijono728a9052006-01-18 23:34:15 +00001633
Benny Prijonodbe337a2006-01-08 23:57:52 +00001634
Benny Prijonoe93e2872006-06-28 16:46:49 +00001635 /* Register modules. */
1636 status = pjsip_endpt_unregister_module(endpt, &tsx_user);
1637 if (status != PJ_SUCCESS) {
1638 app_perror(" Error: unable to unregister module", status);
1639 return -8;
1640 }
1641 status = pjsip_endpt_unregister_module(endpt, &msg_sender);
1642 if (status != PJ_SUCCESS) {
1643 app_perror(" Error: unable to unregister module", status);
1644 return -9;
1645 }
1646
1647
1648 if (loop)
1649 pjsip_transport_dec_ref(loop);
1650
Benny Prijonodbe337a2006-01-08 23:57:52 +00001651 return 0;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001652}
1653