blob: bed6fd0858b3209336b955e2b429b79ca4fe2aa9 [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"
21#include <pjsip_core.h>
22#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.
38 **
39 ** TEST2_BRANCH_ID
40 ** As above, for non-2xx final response.
41 **
42 ** TEST3_BRANCH_ID
43 ** Transaction correctly progressing to PROCEEDING state when provisional
44 ** response is sent.
45 **
46 ** TEST4_BRANCH_ID
47 ** Transaction retransmits last response (if any) without notifying
Benny Prijono0c2bc612006-01-10 13:31:40 +000048 ** transaction user upon receiving request retransmissions on TRYING
49 ** state
Benny Prijonodbe337a2006-01-08 23:57:52 +000050 **
51 ** TEST5_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000052 ** As above, in PROCEEDING state.
Benny Prijonodbe337a2006-01-08 23:57:52 +000053 **
54 ** TEST6_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000055 ** As above, in COMPLETED state, with first sending provisional response.
Benny Prijonodbe337a2006-01-08 23:57:52 +000056 **
57 ** TEST7_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000058 ** INVITE transaction MUST retransmit non-2xx final response.
Benny Prijonodbe337a2006-01-08 23:57:52 +000059 **
60 ** TEST8_BRANCH_ID
Benny Prijono0c2bc612006-01-10 13:31:40 +000061 ** As above, for INVITE's 2xx final response (this is PJSIP specific).
62 **
63 ** TEST9_BRANCH_ID
64 ** INVITE transaction MUST cease retransmission of final response when
65 ** ACK is received. (Note: PJSIP also retransmit 2xx final response
66 ** until it's terminated by user).
67 ** Transaction also MUST terminate in T4 seconds.
68 **
69 ** TEST10_BRANCH_ID
70 ** Test where INVITE UAS transaction never receives ACK
71 **
72 ** TEST11_BRANCH_ID
Benny Prijonodbe337a2006-01-08 23:57:52 +000073 ** When UAS failed to deliver the response with the selected transport,
74 ** it should try contacting the client with other transport or begin
75 ** RFC 3263 server resolution procedure.
76 ** This should be tested on:
77 ** a. TRYING state (when delivering first response).
78 ** b. PROCEEDING state (when failed to retransmit last response
79 ** upon receiving request retransmission).
80 ** c. COMPLETED state.
81 **
Benny Prijono0c2bc612006-01-10 13:31:40 +000082 ** TEST12_BRANCH_ID
Benny Prijonodbe337a2006-01-08 23:57:52 +000083 ** Variant of previous test, where transaction fails to deliver the
84 ** response using any kind of transports. Transaction should report
85 ** transport error to its transaction user.
86 **
87 **/
88
89static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test1";
90static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test2";
91static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test3";
92static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test4";
93static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test5";
94static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test6";
95static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test7";
Benny Prijono0c2bc612006-01-10 13:31:40 +000096static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test8";
97static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test9";
98static char *TEST10_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test10";
99static char *TEST11_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test11";
100static char *TEST12_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test12";
Benny Prijonodbe337a2006-01-08 23:57:52 +0000101
102#define TEST1_STATUS_CODE 200
103#define TEST2_STATUS_CODE 301
104#define TEST3_PROVISIONAL_CODE PJSIP_SC_QUEUED
105#define TEST3_STATUS_CODE 202
Benny Prijono0c2bc612006-01-10 13:31:40 +0000106#define TEST4_STATUS_CODE 200
107#define TEST4_REQUEST_COUNT 2
108#define TEST5_PROVISIONAL_CODE 100
109#define TEST5_STATUS_CODE 200
110#define TEST5_REQUEST_COUNT 2
111#define TEST5_RESPONSE_COUNT 2
112#define TEST6_PROVISIONAL_CODE 100
113#define TEST6_STATUS_CODE 200 /* Must be final */
114#define TEST6_REQUEST_COUNT 2
115#define TEST6_RESPONSE_COUNT 3
116#define TEST7_STATUS_CODE 301
117#define TEST8_STATUS_CODE 302
Benny Prijonodbe337a2006-01-08 23:57:52 +0000118
119
Benny Prijono0c2bc612006-01-10 13:31:40 +0000120#define TEST4_TITLE "test4: absorbing request retransmission"
121#define TEST5_TITLE "test5: retransmit last response in PROCEEDING state"
122#define TEST6_TITLE "test6: retransmit last response in COMPLETED state"
123
124
125#define TEST_TIMEOUT_ERROR -30
126#define MAX_ALLOWED_DIFF 150
127
Benny Prijonodbe337a2006-01-08 23:57:52 +0000128static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
129static pj_bool_t on_rx_message(pjsip_rx_data *rdata);
130
131/* UAC transaction user module. */
132static pjsip_module tsx_user =
133{
134 NULL, NULL, /* prev and next */
135 { "Tsx-UAS-User", 12}, /* Name. */
136 -1, /* Id */
137 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
138 NULL, /* User data. */
139 0, /* Number of methods supported (=0). */
140 { 0 }, /* Array of methods (none) */
141 NULL, /* load() */
142 NULL, /* start() */
143 NULL, /* stop() */
144 NULL, /* unload() */
145 NULL, /* on_rx_request() */
146 NULL, /* on_rx_response() */
147 NULL, /* on_tx_request() */
148 NULL, /* on_tx_response() */
149 &tsx_user_on_tsx_state, /* on_tsx_state() */
150};
151
152/* Module to send request. */
153static pjsip_module msg_sender =
154{
155 NULL, NULL, /* prev and next */
156 { "Msg-Sender", 10}, /* Name. */
157 -1, /* Id */
158 PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */
159 NULL, /* User data. */
160 0, /* Number of methods supported (=0). */
161 { 0 }, /* Array of methods (none) */
162 NULL, /* load() */
163 NULL, /* start() */
164 NULL, /* stop() */
165 NULL, /* unload() */
166 &on_rx_message, /* on_rx_request() */
167 &on_rx_message, /* on_rx_response() */
168 NULL, /* on_tx_request() */
169 NULL, /* on_tx_response() */
170 NULL, /* on_tsx_state() */
171};
172
173/* Static vars, which will be reset on each test. */
174static int recv_count;
175static pj_time_val recv_last;
176static pj_bool_t test_complete;
177
178/* Loop transport instance. */
179static pjsip_transport *loop;
180
181/* UAS transaction key. */
182static char key_buf[64];
183static pj_str_t tsx_key = { key_buf, 0 };
184
185
186/* General timer entry to be used by tests. */
187static pj_timer_entry timer;
188
189/* Timer to send response via transaction. */
190struct response
191{
192 pj_str_t tsx_key;
193 pjsip_tx_data *tdata;
194};
195
Benny Prijono0c2bc612006-01-10 13:31:40 +0000196/* Timer callback to send response. */
Benny Prijonodbe337a2006-01-08 23:57:52 +0000197static void send_response_timer( pj_timer_heap_t *timer_heap,
198 struct pj_timer_entry *entry)
199{
200 pjsip_transaction *tsx;
201 struct response *r = entry->user_data;
202 pj_status_t status;
203
204 tsx = pjsip_tsx_layer_find_tsx(&r->tsx_key, PJ_TRUE);
205 if (!tsx) {
206 PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction"));
207 pjsip_tx_data_dec_ref(r->tdata);
208 return;
209 }
210
211 status = pjsip_tsx_send_msg(tsx, r->tdata);
212 if (status != PJ_SUCCESS) {
213 PJ_LOG(3,(THIS_FILE," error: timer unable to send response"));
214 pjsip_tx_data_dec_ref(r->tdata);
215 return;
216 }
217}
218
Benny Prijono0c2bc612006-01-10 13:31:40 +0000219/* Utility to send response. */
220static void send_response( pjsip_rx_data *rdata,
221 pjsip_transaction *tsx,
222 int status_code )
223{
224 pj_status_t status;
225 pjsip_tx_data *tdata;
226
227 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL,
228 &tdata);
229 if (status != PJ_SUCCESS) {
230 app_perror(" error: unable to create response", status);
231 test_complete = -196;
232 return;
233 }
234
235 status = pjsip_tsx_send_msg(tsx, tdata);
236 if (status != PJ_SUCCESS) {
237 app_perror(" error: unable to send response", status);
238 pjsip_tx_data_dec_ref(tdata);
239 test_complete = -197;
240 return;
241 }
242}
243
Benny Prijonodbe337a2006-01-08 23:57:52 +0000244/* Schedule timer to send response for the specified UAS transaction */
245static void schedule_send_response( pjsip_rx_data *rdata,
246 const pj_str_t *tsx_key,
247 int status_code,
248 int msec_delay )
249{
250 pj_status_t status;
251 pjsip_tx_data *tdata;
252 struct response *r;
253 pj_time_val delay;
254
255 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL,
256 &tdata);
257 if (status != PJ_SUCCESS) {
258 app_perror(" error: unable to create response", status);
259 test_complete = -198;
260 return;
261 }
262
263 r = pj_pool_alloc(tdata->pool, sizeof(*r));
264 pj_strdup(tdata->pool, &r->tsx_key, tsx_key);
265 r->tdata = tdata;
266
267 delay.sec = 0;
268 delay.msec = msec_delay;
269 pj_time_val_normalize(&delay);
270
271 timer.user_data = r;
272 timer.cb = &send_response_timer;
273
274 status = pjsip_endpt_schedule_timer(endpt, &timer, &delay);
275 if (status != PJ_SUCCESS) {
276 app_perror(" error: unable to schedule timer", status);
277 test_complete = -199;
278 pjsip_tx_data_dec_ref(tdata);
279 return;
280 }
281}
282
Benny Prijono0c2bc612006-01-10 13:31:40 +0000283
284/* Find and terminate tsx with the specified key. */
285static void terminate_our_tsx(int status_code)
286{
287 pjsip_transaction *tsx;
288
289 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
290 if (!tsx) {
291 PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction"));
292 return;
293 }
294
295 pjsip_tsx_terminate(tsx, status_code);
296 pj_mutex_unlock(tsx->mutex);
297}
298
299/* Timer callback to terminate transaction. */
300static void terminate_tsx_timer( pj_timer_heap_t *timer_heap,
301 struct pj_timer_entry *entry)
302{
303 terminate_our_tsx(entry->id);
304}
305
306
307/* Schedule timer to terminate transaction. */
308static void schedule_terminate_tsx( pjsip_transaction *tsx,
309 int status_code,
310 int msec_delay )
311{
312 pj_time_val delay;
313
314 delay.sec = 0;
315 delay.msec = msec_delay;
316 pj_time_val_normalize(&delay);
317
318 pj_assert(pj_strcmp(&tsx->transaction_key, &tsx_key)==0);
319 timer.user_data = NULL;
320 timer.id = status_code;
321 timer.cb = &terminate_tsx_timer;
322 pjsip_endpt_schedule_timer(endpt, &timer, &delay);
323}
324
325
Benny Prijonodbe337a2006-01-08 23:57:52 +0000326/*
327 * This is the handler to receive state changed notification from the
328 * transaction. It is used to verify that the transaction behaves according
329 * to the test scenario.
330 */
331static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
332{
333 if (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0 ||
334 pj_strcmp2(&tsx->branch, TEST2_BRANCH_ID)==0)
335 {
336 /*
337 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits final
338 * response using correct transport and terminates transaction after
339 * T4 (PJSIP_T4_TIMEOUT, 5 seconds).
340 *
341 * TEST2_BRANCH_ID does similar test for non-2xx final response.
342 */
343 int status_code = (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0) ?
344 TEST1_STATUS_CODE : TEST2_STATUS_CODE;
345
346 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
347
348 test_complete = 1;
349
350 /* Check that status code is status_code. */
351 if (tsx->status_code != status_code) {
352 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
353 test_complete = -100;
354 }
355
356 /* Previous state must be completed. */
357 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
358 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
359 test_complete = -101;
360 }
361
362 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
363
364 /* Previous state must be TRYING. */
365 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
366 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
367 test_complete = -102;
368 }
369 }
370
371 }
372 else
373 if (pj_strcmp2(&tsx->branch, TEST3_BRANCH_ID)==0) {
374 /*
375 * TEST3_BRANCH_ID tests sending provisional response.
376 */
377 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
378
379 test_complete = 1;
380
381 /* Check that status code is status_code. */
382 if (tsx->status_code != TEST3_STATUS_CODE) {
383 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
384 test_complete = -110;
385 }
386
387 /* Previous state must be completed. */
388 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
389 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
390 test_complete = -111;
391 }
392
393 } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
394
395 /* Previous state must be TRYING. */
396 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
397 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
398 test_complete = -112;
399 }
400
401 /* Check that status code is status_code. */
402 if (tsx->status_code != TEST3_PROVISIONAL_CODE) {
403 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
404 test_complete = -113;
405 }
406
407 /* Check that event must be TX_MSG */
408 if (e->body.tsx_state.type != PJSIP_EVENT_TX_MSG) {
409 PJ_LOG(3,(THIS_FILE, " error: incorrect event"));
410 test_complete = -114;
411 }
412
413 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
414
415 /* Previous state must be PROCEEDING. */
416 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
417 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
418 test_complete = -115;
419 }
420
421 /* Check that status code is status_code. */
422 if (tsx->status_code != TEST3_STATUS_CODE) {
423 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
424 test_complete = -116;
425 }
426
427 /* Check that event must be TX_MSG */
428 if (e->body.tsx_state.type != PJSIP_EVENT_TX_MSG) {
429 PJ_LOG(3,(THIS_FILE, " error: incorrect event"));
430 test_complete = -117;
431 }
432
433 }
434
Benny Prijono0c2bc612006-01-10 13:31:40 +0000435 } else
436 if (pj_strcmp2(&tsx->branch, TEST4_BRANCH_ID)==0) {
437 /*
438 * TEST4_BRANCH_ID tests receiving retransmissions in TRYING state.
439 */
440 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
441
442 /* Check that status code is status_code. */
443 if (tsx->status_code != TEST4_STATUS_CODE) {
444 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
445 test_complete = -120;
446 }
447
448 /* Previous state. */
449 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
450 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
451 test_complete = -121;
452 }
453
454 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED)
455 {
456 PJ_LOG(3,(THIS_FILE, " error: unexpected state"));
457 test_complete = -122;
458
459 }
460
461
462 } else
463 if (pj_strcmp2(&tsx->branch, TEST5_BRANCH_ID)==0) {
464 /*
465 * TEST5_BRANCH_ID tests receiving retransmissions in PROCEEDING state
466 */
467 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
468
469 /* Check that status code is status_code. */
470 if (tsx->status_code != TEST5_STATUS_CODE) {
471 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
472 test_complete = -130;
473 }
474
475 /* Previous state. */
476 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) {
477 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
478 test_complete = -131;
479 }
480
481 } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
482
483 /* Check status code. */
484 if (tsx->status_code != TEST5_PROVISIONAL_CODE) {
485 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
486 test_complete = -132;
487 }
488
489 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) {
490 PJ_LOG(3,(THIS_FILE, " error: unexpected state"));
491 test_complete = -133;
492
493 }
494
495 } else
496 if (pj_strcmp2(&tsx->branch, TEST6_BRANCH_ID)==0) {
497 /*
498 * TEST6_BRANCH_ID tests receiving retransmissions in COMPLETED state
499 */
500 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
501
502 /* Check that status code is status_code. */
503 if (tsx->status_code != TEST6_STATUS_CODE) {
504 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
505 test_complete = -140;
506 }
507
508 /* Previous state. */
509 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
510 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
511 test_complete = -141;
512 }
513
514 } else if (tsx->state != PJSIP_TSX_STATE_PROCEEDING &&
515 tsx->state != PJSIP_TSX_STATE_COMPLETED &&
516 tsx->state != PJSIP_TSX_STATE_DESTROYED)
517 {
518 PJ_LOG(3,(THIS_FILE, " error: unexpected state"));
519 test_complete = -142;
520
521 }
522
523
524 } else
525 if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID)==0 ||
526 pj_strcmp2(&tsx->branch, TEST8_BRANCH_ID)==0)
527 {
528 /*
529 * TEST7_BRANCH_ID and TEST8_BRANCH_ID test retransmission of
530 * INVITE final response
531 */
532 int code;
533
534 if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID) == 0)
535 code = TEST7_STATUS_CODE;
536 else
537 code = TEST8_STATUS_CODE;
538
539 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
540
541 if (test_complete == 0)
542 test_complete = 1;
543
544 /* Check status code. */
545 if (tsx->status_code != PJSIP_SC_TSX_TIMEOUT) {
546 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
547 test_complete = -150;
548 }
549
550 /* Previous state. */
551 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) {
552 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
553 test_complete = -151;
554 }
555
556 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
557
558 /* Check that status code is status_code. */
559 if (tsx->status_code != code) {
560 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
561 test_complete = -152;
562 }
563
564 /* Previous state. */
565 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) {
566 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state"));
567 test_complete = -153;
568 }
569
570 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) {
571
572 PJ_LOG(3,(THIS_FILE, " error: unexpected state"));
573 test_complete = -154;
574
575 }
576
Benny Prijonodbe337a2006-01-08 23:57:52 +0000577 }
578
579}
580
581/* Save transaction key to global variables. */
582static void save_key(pjsip_transaction *tsx)
583{
584 pj_str_t key;
585
586 pj_strdup(tsx->pool, &key, &tsx->transaction_key);
587 pj_strcpy(&tsx_key, &key);
588}
589
Benny Prijono0c2bc612006-01-10 13:31:40 +0000590#define DIFF(a,b) ((a<b) ? (b-a) : (a-b))
591
Benny Prijonodbe337a2006-01-08 23:57:52 +0000592/*
593 * Message receiver handler.
594 */
595static pj_bool_t on_rx_message(pjsip_rx_data *rdata)
596{
597 pjsip_msg *msg = rdata->msg_info.msg;
598 pj_str_t branch_param = rdata->msg_info.via->branch_param;
599 pj_status_t status;
600
601 if (pj_strcmp2(&branch_param, TEST1_BRANCH_ID) == 0 ||
602 pj_strcmp2(&branch_param, TEST2_BRANCH_ID) == 0)
603 {
604 /*
605 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits 2xx
606 * final response using correct transport and terminates transaction
607 * after 32 seconds.
608 *
609 * TEST2_BRANCH_ID performs similar test for non-2xx final response.
610 */
611 int status_code = (pj_strcmp2(&branch_param, TEST1_BRANCH_ID) == 0) ?
612 TEST1_STATUS_CODE : TEST2_STATUS_CODE;
613
614 if (msg->type == PJSIP_REQUEST_MSG) {
615 /* On received response, create UAS and respond with final
616 * response.
617 */
618 pjsip_transaction *tsx;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000619
620 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
621 if (status != PJ_SUCCESS) {
622 app_perror(" error: unable to create transaction", status);
623 test_complete = -110;
624 return PJ_TRUE;
625 }
626
627 save_key(tsx);
Benny Prijono0c2bc612006-01-10 13:31:40 +0000628 send_response(rdata, tsx, status_code);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000629
630 } else {
631 /* Verify the response received. */
632
633 ++recv_count;
634
635 /* Verify status code. */
636 if (msg->line.status.code != status_code) {
637 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
638 test_complete = -113;
639 }
640
641 /* Verify that no retransmissions is received. */
642 if (recv_count > 1) {
643 PJ_LOG(3,(THIS_FILE, " error: retransmission received"));
644 test_complete = -114;
645 }
646
647 }
648 return PJ_TRUE;
649
650 } else if (pj_strcmp2(&branch_param, TEST3_BRANCH_ID) == 0) {
651
652 /* TEST3_BRANCH_ID tests provisional response. */
653
654 if (msg->type == PJSIP_REQUEST_MSG) {
655 /* On received response, create UAS and respond with provisional
656 * response, then schedule timer to send final response.
657 */
658 pjsip_transaction *tsx;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000659
660 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
661 if (status != PJ_SUCCESS) {
662 app_perror(" error: unable to create transaction", status);
663 test_complete = -120;
664 return PJ_TRUE;
665 }
666
667 save_key(tsx);
668
Benny Prijono0c2bc612006-01-10 13:31:40 +0000669 send_response(rdata, tsx, TEST3_PROVISIONAL_CODE);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000670 schedule_send_response(rdata, &tsx->transaction_key,
671 TEST3_STATUS_CODE, 2000);
672
673 } else {
674 /* Verify the response received. */
675
676 ++recv_count;
677
678 if (recv_count == 1) {
679 /* Verify status code. */
680 if (msg->line.status.code != TEST3_PROVISIONAL_CODE) {
681 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
682 test_complete = -123;
683 }
684 } else if (recv_count == 2) {
685 /* Verify status code. */
686 if (msg->line.status.code != TEST3_STATUS_CODE) {
687 PJ_LOG(3,(THIS_FILE, " error: incorrect status code"));
688 test_complete = -124;
689 }
690 } else {
691 PJ_LOG(3,(THIS_FILE, " error: retransmission received"));
692 test_complete = -125;
693 }
694
695 }
696 return PJ_TRUE;
697
Benny Prijono0c2bc612006-01-10 13:31:40 +0000698 } else if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0 ||
699 pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0 ||
700 pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0)
701 {
702
703 /* TEST4_BRANCH_ID: absorbs retransmissions in TRYING state. */
704 /* TEST5_BRANCH_ID: retransmit last response in PROCEEDING state. */
705 /* TEST6_BRANCH_ID: retransmit last response in COMPLETED state. */
706
707 if (msg->type == PJSIP_REQUEST_MSG) {
708 /* On received response, create UAS. */
709 pjsip_transaction *tsx;
710
711 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
712 if (status != PJ_SUCCESS) {
713 app_perror(" error: unable to create transaction", status);
714 test_complete = -130;
715 return PJ_TRUE;
716 }
717
718 save_key(tsx);
719
720 if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0) {
721
722 } else if (pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0) {
723 send_response(rdata, tsx, TEST5_PROVISIONAL_CODE);
724
725 } else if (pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0) {
726 send_response(rdata, tsx, TEST6_PROVISIONAL_CODE);
727 send_response(rdata, tsx, TEST6_STATUS_CODE);
728 }
729
730 } else {
731 /* Verify the response received. */
732
733 ++recv_count;
734
735 if (pj_strcmp2(&branch_param, TEST4_BRANCH_ID) == 0) {
736 PJ_LOG(3,(THIS_FILE, " error: not expecting response!"));
737 test_complete = -132;
738
739 } else if (pj_strcmp2(&branch_param, TEST5_BRANCH_ID) == 0) {
740
741 if (rdata->msg_info.msg->line.status.code!=TEST5_PROVISIONAL_CODE) {
742 PJ_LOG(3,(THIS_FILE, " error: incorrect status code!"));
743 test_complete = -133;
744
745 }
746 if (recv_count > TEST5_RESPONSE_COUNT) {
747 PJ_LOG(3,(THIS_FILE, " error: not expecting response!"));
748 test_complete = -134;
749 }
750
751 } else if (pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0) {
752
753 int code = rdata->msg_info.msg->line.status.code;
754
755 switch (recv_count) {
756 case 1:
757 if (code != TEST6_PROVISIONAL_CODE) {
758 PJ_LOG(3,(THIS_FILE, " error: invalid code!"));
759 test_complete = -135;
760 }
761 break;
762 case 2:
763 case 3:
764 if (code != TEST6_STATUS_CODE) {
765 PJ_LOG(3,(THIS_FILE, " error: invalid code!"));
766 test_complete = -136;
767 }
768 break;
769 default:
770 PJ_LOG(3,(THIS_FILE, " error: not expecting response"));
771 test_complete = -137;
772 break;
773 }
774 }
775 }
776 return PJ_TRUE;
777
778
779 } else if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0 ||
780 pj_strcmp2(&branch_param, TEST8_BRANCH_ID) == 0)
781 {
782
783 /*
784 * TEST7_BRANCH_ID and TEST8_BRANCH_ID test the retransmission
785 * of INVITE final response
786 */
787 if (msg->type == PJSIP_REQUEST_MSG) {
788
789 /* On received response, create UAS. */
790 pjsip_transaction *tsx;
791
792 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
793 if (status != PJ_SUCCESS) {
794 app_perror(" error: unable to create transaction", status);
795 test_complete = -140;
796 return PJ_TRUE;
797 }
798
799 save_key(tsx);
800
801 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0) {
802
803 send_response(rdata, tsx, TEST7_STATUS_CODE);
804
805 } else {
806
807 send_response(rdata, tsx, TEST8_STATUS_CODE);
808
809 }
810
811 } else {
812 int code;
813
814 ++recv_count;
815
816 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0)
817 code = TEST7_STATUS_CODE;
818 else
819 code = TEST8_STATUS_CODE;
820
821 if (recv_count==1) {
822
823 if (rdata->msg_info.msg->line.status.code != code) {
824 PJ_LOG(3,(THIS_FILE," error: invalid status code"));
825 test_complete = -141;
826 }
827
828 recv_last = rdata->pkt_info.timestamp;
829
830 } else {
831
832 pj_time_val now;
833 unsigned msec, msec_expected;
834
835 now = rdata->pkt_info.timestamp;
836
837 PJ_TIME_VAL_SUB(now, recv_last);
838
839 msec = now.sec*1000 + now.msec;
840 msec_expected = (1 << (recv_count-2)) * PJSIP_T1_TIMEOUT;
841 if (msec_expected > PJSIP_T2_TIMEOUT)
842 msec_expected = PJSIP_T2_TIMEOUT;
843
844 if (DIFF(msec, msec_expected) > MAX_ALLOWED_DIFF) {
845 PJ_LOG(3,(THIS_FILE,
846 " error: incorrect retransmission "
847 "time (%d ms expected, %d ms received",
848 msec_expected, msec));
849 test_complete = -142;
850 }
851
852 if (recv_count > 11) {
853 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)",
854 recv_count));
855 test_complete = -143;
856 }
857
858 recv_last = rdata->pkt_info.timestamp;
859 }
860
861 }
862 return PJ_TRUE;
863
864 } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID)) {
865
866 /*
867 * TEST9_BRANCH_ID tests that the retransmission of INVITE final
868 * response should cease when ACK is received. Transaction also MUST
869 * terminate in T4 seconds.
870 */
871 if (msg->type == PJSIP_REQUEST_MSG) {
872
873 /* On received response, create UAS. */
874 pjsip_transaction *tsx;
875
876 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx);
877 if (status != PJ_SUCCESS) {
878 app_perror(" error: unable to create transaction", status);
879 test_complete = -140;
880 return PJ_TRUE;
881 }
882
883 save_key(tsx);
884
885 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0) {
886
887 send_response(rdata, tsx, TEST7_STATUS_CODE);
888
889 } else {
890
891 send_response(rdata, tsx, TEST8_STATUS_CODE);
892
893 }
894
895 } else {
896 int code;
897
898 ++recv_count;
899
900 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0)
901 code = TEST7_STATUS_CODE;
902 else
903 code = TEST8_STATUS_CODE;
904
905 if (recv_count==1) {
906
907 if (rdata->msg_info.msg->line.status.code != code) {
908 PJ_LOG(3,(THIS_FILE," error: invalid status code"));
909 test_complete = -141;
910 }
911
912 recv_last = rdata->pkt_info.timestamp;
913
914 } else {
915
916 pj_time_val now;
917 unsigned msec, msec_expected;
918
919 now = rdata->pkt_info.timestamp;
920
921 PJ_TIME_VAL_SUB(now, recv_last);
922
923 msec = now.sec*1000 + now.msec;
924 msec_expected = (1 << (recv_count-2)) * PJSIP_T1_TIMEOUT;
925 if (msec_expected > PJSIP_T2_TIMEOUT)
926 msec_expected = PJSIP_T2_TIMEOUT;
927
928 if (DIFF(msec, msec_expected) > MAX_ALLOWED_DIFF) {
929 PJ_LOG(3,(THIS_FILE,
930 " error: incorrect retransmission "
931 "time (%d ms expected, %d ms received",
932 msec_expected, msec));
933 test_complete = -142;
934 }
935
936 if (recv_count > 11) {
937 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)",
938 recv_count));
939 test_complete = -143;
940 }
941
942 recv_last = rdata->pkt_info.timestamp;
943 }
944
945 }
946 return PJ_TRUE;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000947 }
948
949 return PJ_FALSE;
950}
951
952/*
953 * The generic test framework, used by most of the tests.
954 */
955static int perform_test( char *target_uri, char *from_uri,
956 char *branch_param, int test_time,
Benny Prijono0c2bc612006-01-10 13:31:40 +0000957 const pjsip_method *method,
958 int request_cnt, int request_interval_msec,
959 int expecting_timeout)
Benny Prijonodbe337a2006-01-08 23:57:52 +0000960{
961 pjsip_tx_data *tdata;
962 pj_str_t target, from;
963 pjsip_via_hdr *via;
Benny Prijono0c2bc612006-01-10 13:31:40 +0000964 pj_time_val timeout, next_send;
965 int sent_cnt;
Benny Prijonodbe337a2006-01-08 23:57:52 +0000966 pj_status_t status;
967
968 PJ_LOG(3,(THIS_FILE,
969 " please standby, this will take at most %d seconds..",
970 test_time));
971
972 /* Reset test. */
973 recv_count = 0;
974 test_complete = 0;
975 tsx_key.slen = 0;
976
977 /* Init headers. */
978 target = pj_str(target_uri);
979 from = pj_str(from_uri);
980
981 /* Create request. */
982 status = pjsip_endpt_create_request( endpt, method, &target,
983 &from, &target, NULL, NULL, -1,
984 NULL, &tdata);
985 if (status != PJ_SUCCESS) {
986 app_perror(" Error: unable to create request", status);
987 return -10;
988 }
989
990 /* Set the branch param for test 1. */
991 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
992 via->branch_param = pj_str(branch_param);
993
Benny Prijono0c2bc612006-01-10 13:31:40 +0000994 /* Schedule first send. */
995 sent_cnt = 0;
996 pj_gettimeofday(&next_send);
997 pj_time_val_normalize(&next_send);
Benny Prijonodbe337a2006-01-08 23:57:52 +0000998
999 /* Set test completion time. */
1000 pj_gettimeofday(&timeout);
1001 timeout.sec += test_time;
1002
1003 /* Wait until test complete. */
1004 while (!test_complete) {
1005 pj_time_val now, poll_delay = {0, 10};
1006
1007 pjsip_endpt_handle_events(endpt, &poll_delay);
1008
1009 pj_gettimeofday(&now);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001010
1011 if (sent_cnt < request_cnt && PJ_TIME_VAL_GTE(now, next_send)) {
1012 /* Add additional reference to tdata to prevent transaction from
1013 * deleting it.
1014 */
1015 pjsip_tx_data_add_ref(tdata);
1016
1017 /* (Re)Send the request. */
1018 status = pjsip_endpt_send_request_stateless(endpt, tdata, 0, 0);
1019 if (status != PJ_SUCCESS) {
1020 app_perror(" Error: unable to send request", status);
1021 pjsip_tx_data_dec_ref(tdata);
1022 return -20;
1023 }
1024
1025 /* Schedule next send, if any. */
1026 sent_cnt++;
1027 if (sent_cnt < request_cnt) {
1028 pj_gettimeofday(&next_send);
1029 next_send.msec += request_interval_msec;
1030 pj_time_val_normalize(&next_send);
1031 }
1032 }
1033
Benny Prijonodbe337a2006-01-08 23:57:52 +00001034 if (now.sec > timeout.sec) {
Benny Prijono0c2bc612006-01-10 13:31:40 +00001035 if (!expecting_timeout)
1036 PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
Benny Prijonodbe337a2006-01-08 23:57:52 +00001037 pjsip_tx_data_dec_ref(tdata);
Benny Prijono0c2bc612006-01-10 13:31:40 +00001038 return TEST_TIMEOUT_ERROR;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001039 }
1040 }
1041
1042 if (test_complete < 0) {
1043 pjsip_transaction *tsx;
1044
1045 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
1046 if (tsx) {
1047 pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
1048 pj_mutex_unlock(tsx->mutex);
1049 flush_events(1000);
1050 }
1051 pjsip_tx_data_dec_ref(tdata);
1052 return test_complete;
1053 }
1054
1055 /* Allow transaction to destroy itself */
1056 flush_events(500);
1057
1058 /* Make sure transaction has been destroyed. */
1059 if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
1060 PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
1061 pjsip_tx_data_dec_ref(tdata);
1062 return -40;
1063 }
1064
1065 /* Check tdata reference counter. */
1066 if (pj_atomic_get(tdata->ref_cnt) != 1) {
1067 PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
1068 pj_atomic_get(tdata->ref_cnt)));
1069 pjsip_tx_data_dec_ref(tdata);
1070 return -50;
1071 }
1072
1073 /* Destroy txdata */
1074 pjsip_tx_data_dec_ref(tdata);
1075
1076 return PJ_SUCCESS;
1077
1078}
1079
1080
1081/*****************************************************************************
1082 **
1083 ** TEST1_BRANCH_ID: Basic 2xx final response
1084 ** TEST2_BRANCH_ID: Basic non-2xx final response
1085 **
1086 *****************************************************************************
1087 */
1088static int tsx_basic_final_response_test(void)
1089{
1090 int status;
1091
1092 PJ_LOG(3,(THIS_FILE," test1: basic sending 2xx final response"));
1093
1094 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1095 "sip:129.0.0.1;transport=loop-dgram",
1096 TEST1_BRANCH_ID,
1097 33, /* Test duration must be greater than 32 secs */
Benny Prijono0c2bc612006-01-10 13:31:40 +00001098 &pjsip_options_method, 1, 0, 0);
Benny Prijonodbe337a2006-01-08 23:57:52 +00001099 if (status != 0)
1100 return status;
1101
1102 PJ_LOG(3,(THIS_FILE," test2: basic sending non-2xx final response"));
1103
1104 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1105 "sip:129.0.0.1;transport=loop-dgram",
1106 TEST2_BRANCH_ID,
1107 33, /* Test duration must be greater than 32 secs */
Benny Prijono0c2bc612006-01-10 13:31:40 +00001108 &pjsip_options_method, 1, 0, 0);
Benny Prijonodbe337a2006-01-08 23:57:52 +00001109 if (status != 0)
1110 return status;
1111
1112 return 0;
1113}
1114
1115
1116/*****************************************************************************
1117 **
1118 ** TEST3_BRANCH_ID: Sending provisional response
1119 **
1120 *****************************************************************************
1121 */
1122static int tsx_basic_provisional_response_test(void)
1123{
1124 int status;
1125
1126 PJ_LOG(3,(THIS_FILE," test1: basic sending 2xx final response"));
1127
1128 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1129 "sip:129.0.0.1;transport=loop-dgram",
1130 TEST3_BRANCH_ID,
1131 35,
Benny Prijono0c2bc612006-01-10 13:31:40 +00001132 &pjsip_options_method, 1, 0, 0);
1133
Benny Prijonodbe337a2006-01-08 23:57:52 +00001134 return status;
1135}
1136
1137
1138/*****************************************************************************
1139 **
Benny Prijono0c2bc612006-01-10 13:31:40 +00001140 ** TEST4_BRANCH_ID: Absorbs retransmissions in TRYING state
1141 ** TEST5_BRANCH_ID: Absorbs retransmissions in PROCEEDING state
1142 ** TEST6_BRANCH_ID: Absorbs retransmissions in COMPLETED state
1143 **
1144 *****************************************************************************
1145 */
1146static int tsx_retransmit_last_response_test(const char *title,
1147 char *branch_id,
1148 int request_cnt,
1149 int status_code)
1150{
1151 int status;
1152
1153 PJ_LOG(3,(THIS_FILE," %s", title));
1154
1155 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1156 "sip:129.0.0.1;transport=loop-dgram",
1157 branch_id,
1158 5,
1159 &pjsip_options_method,
1160 request_cnt, 1000, 1);
1161 if (status && status != TEST_TIMEOUT_ERROR)
1162 return status;
1163 if (!status) {
1164 PJ_LOG(3,(THIS_FILE, " error: expecting timeout"));
1165 return -31;
1166 }
1167
1168 terminate_our_tsx(status_code);
1169 flush_events(100);
1170
1171 if (test_complete != 1)
1172 return test_complete;
1173
1174 flush_events(100);
1175 return 0;
1176}
1177
1178/*****************************************************************************
1179 **
1180 ** TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test
1181 ** TEST8_BRANCH_ID: INVITE 2xx final response retransmission test
1182 **
1183 *****************************************************************************
1184 */
1185static int tsx_final_response_retransmission_test(void)
1186{
1187 int status;
1188
1189 PJ_LOG(3,(THIS_FILE,
1190 " test7: INVITE non-2xx final response retransmission"));
1191
1192 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1193 "sip:129.0.0.1;transport=loop-dgram",
1194 TEST7_BRANCH_ID,
1195 33, /* Test duration must be greater than 32 secs */
1196 &pjsip_invite_method, 1, 0, 0);
1197 if (status != 0)
1198 return status;
1199
1200 PJ_LOG(3,(THIS_FILE,
1201 " test8: INVITE 2xx final response retransmission"));
1202
1203 status = perform_test("sip:129.0.0.1;transport=loop-dgram",
1204 "sip:129.0.0.1;transport=loop-dgram",
1205 TEST8_BRANCH_ID,
1206 33, /* Test duration must be greater than 32 secs */
1207 &pjsip_invite_method, 1, 0, 0);
1208 if (status != 0)
1209 return status;
1210
1211 return 0;
1212}
1213
1214
1215
1216/*****************************************************************************
1217 **
Benny Prijonodbe337a2006-01-08 23:57:52 +00001218 ** UAS Transaction Test.
1219 **
1220 *****************************************************************************
1221 */
1222int tsx_uas_test(void)
1223{
1224 pj_sockaddr_in addr;
1225 pj_status_t status;
1226
1227 /* Check if loop transport is configured. */
1228 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
1229 &addr, sizeof(addr), &loop);
1230 if (status != PJ_SUCCESS) {
1231 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
1232 return -1;
1233 }
1234
1235 /* Register modules. */
1236 status = pjsip_endpt_register_module(endpt, &tsx_user);
1237 if (status != PJ_SUCCESS) {
1238 app_perror(" Error: unable to register module", status);
1239 return -3;
1240 }
1241 status = pjsip_endpt_register_module(endpt, &msg_sender);
1242 if (status != PJ_SUCCESS) {
1243 app_perror(" Error: unable to register module", status);
1244 return -4;
1245 }
1246
1247#if 0
1248 /* TEST1_BRANCH_ID: Basic 2xx final response.
1249 * TEST2_BRANCH_ID: Basic non-2xx final response.
1250 */
1251 status = tsx_basic_final_response_test();
1252 if (status != 0)
1253 return status;
Benny Prijonodbe337a2006-01-08 23:57:52 +00001254
1255 /* TEST3_BRANCH_ID: with provisional response
1256 */
1257 status = tsx_basic_provisional_response_test();
1258 if (status != 0)
1259 return status;
1260
Benny Prijono0c2bc612006-01-10 13:31:40 +00001261 /* TEST4_BRANCH_ID: absorbs retransmissions in TRYING state
1262 */
1263 status = tsx_retransmit_last_response_test(TEST4_TITLE,
1264 TEST4_BRANCH_ID,
1265 TEST4_REQUEST_COUNT,
1266 TEST4_STATUS_CODE);
1267 if (status != 0)
1268 return status;
1269
1270 /* TEST5_BRANCH_ID: retransmit last response in PROCEEDING state
1271 */
1272 status = tsx_retransmit_last_response_test(TEST5_TITLE,
1273 TEST5_BRANCH_ID,
1274 TEST5_REQUEST_COUNT,
1275 TEST5_STATUS_CODE);
1276 if (status != 0)
1277 return status;
1278
1279 /* TEST6_BRANCH_ID: retransmit last response in PROCEEDING state
1280 */
1281 status = tsx_retransmit_last_response_test(TEST6_TITLE,
1282 TEST6_BRANCH_ID,
1283 TEST6_REQUEST_COUNT,
1284 TEST6_STATUS_CODE);
1285 if (status != 0)
1286 return status;
1287
1288 /* TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test
1289 * TEST8_BRANCH_ID: INVITE 2xx final response retransmission test
1290 */
1291
1292 status = tsx_final_response_retransmission_test();
1293 if (status != 0)
1294 return status;
1295
1296#endif
Benny Prijonodbe337a2006-01-08 23:57:52 +00001297
1298 pjsip_transport_dec_ref(loop);
1299 return 0;
1300
1301}
1302