📄 tsx_uac_test.c
字号:
/* Set the branch param for test 1. */
via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
via->branch_param = pj_str(branch_param);
/* Add additional reference to tdata to prevent transaction from
* deleting it.
*/
pjsip_tx_data_add_ref(tdata);
/* Create transaction. */
status = pjsip_tsx_create_uac( &tsx_user, tdata, &tsx);
if (status != PJ_SUCCESS) {
app_perror(" Error: unable to create UAC transaction", status);
pjsip_tx_data_dec_ref(tdata);
return -110;
}
/* Get transaction key. */
pj_strdup(tdata->pool, &tsx_key, &tsx->transaction_key);
/* Send the message. */
status = pjsip_tsx_send_msg(tsx, NULL);
// Ignore send result. Some tests do deliberately triggers error
// when sending message.
if (status != PJ_SUCCESS) {
// app_perror(" Error: unable to send request", status);
pjsip_tx_data_dec_ref(tdata);
// return -120;
}
/* Set test completion time. */
pj_gettimeofday(&timeout);
timeout.sec += test_time;
/* Wait until test complete. */
while (!test_complete) {
pj_time_val now, poll_delay = {0, 10};
pjsip_endpt_handle_events(endpt, &poll_delay);
pj_gettimeofday(&now);
if (now.sec > timeout.sec) {
PJ_LOG(3,(THIS_FILE, " Error: test has timed out"));
pjsip_tx_data_dec_ref(tdata);
return -130;
}
}
if (test_complete < 0) {
tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
if (tsx) {
pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
pj_mutex_unlock(tsx->mutex);
flush_events(1000);
}
pjsip_tx_data_dec_ref(tdata);
return test_complete;
} else {
pj_time_val now;
/* Allow transaction to destroy itself */
flush_events(500);
/* Wait until test completes */
pj_gettimeofday(&now);
if (PJ_TIME_VAL_LT(now, timeout)) {
pj_time_val interval;
interval = timeout;
PJ_TIME_VAL_SUB(interval, now);
flush_events(PJ_TIME_VAL_MSEC(interval));
}
}
/* Make sure transaction has been destroyed. */
if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) {
PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed"));
pjsip_tx_data_dec_ref(tdata);
return -140;
}
/* Check tdata reference counter. */
if (pj_atomic_get(tdata->ref_cnt) != 1) {
PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d",
pj_atomic_get(tdata->ref_cnt)));
pjsip_tx_data_dec_ref(tdata);
return -150;
}
/* Destroy txdata */
pjsip_tx_data_dec_ref(tdata);
return PJ_SUCCESS;
}
/*****************************************************************************
**
** TEST1_BRANCH_ID: UAC basic retransmission and timeout test.
**
** This will test the retransmission of the UAC transaction. Remote will not
** answer the transaction, so the transaction should fail. The Via branch prm
** TEST1_BRANCH_ID will be used for this test.
**
*****************************************************************************
*/
static int tsx_uac_retransmit_test(void)
{
int status, enabled;
int i;
struct {
const pjsip_method *method;
unsigned delay;
} sub_test[] =
{
{ &pjsip_invite_method, 0},
{ &pjsip_invite_method, TEST1_ALLOWED_DIFF*2},
{ &pjsip_options_method, 0},
{ &pjsip_options_method, TEST1_ALLOWED_DIFF*2}
};
PJ_LOG(3,(THIS_FILE, " test1: basic uac retransmit and timeout test"));
/* For this test. message printing shound be disabled because it makes
* incorrect timing.
*/
enabled = msg_logger_set_enabled(0);
for (i=0; i<PJ_ARRAY_SIZE(sub_test); ++i) {
PJ_LOG(3,(THIS_FILE,
" variant %c: %s with %d ms network delay",
('a' + i),
sub_test[i].method->name.ptr,
sub_test[i].delay));
/* Configure transport */
pjsip_loop_set_failure(loop, 0, NULL);
pjsip_loop_set_recv_delay(loop, sub_test[i].delay, NULL);
/* Do the test. */
status = perform_tsx_test(-500, TARGET_URI, FROM_URI,
TEST1_BRANCH_ID,
35, sub_test[i].method);
if (status != 0)
break;
}
/* Restore transport. */
pjsip_loop_set_recv_delay(loop, 0, NULL);
/* Restore msg logger. */
msg_logger_set_enabled(enabled);
/* Done. */
return status;
}
/*****************************************************************************
**
** TEST2_BRANCH_ID: UAC resolve error test.
**
** Test the scenario where destination host is unresolvable. There are
** two variants:
** (a) resolver returns immediate error
** (b) resolver returns error via the callback.
**
*****************************************************************************
*/
static int tsx_resolve_error_test(void)
{
int status;
PJ_LOG(3,(THIS_FILE, " test2: resolve error test"));
/*
* Variant (a): immediate resolve error.
*/
PJ_LOG(3,(THIS_FILE, " variant a: immediate resolving error"));
status = perform_tsx_test(-800,
"sip:bob@unresolved-host",
FROM_URI, TEST2_BRANCH_ID, 10,
&pjsip_options_method);
if (status != 0)
return status;
/*
* Variant (b): error via callback.
*/
PJ_LOG(3,(THIS_FILE, " variant b: error via callback"));
/* This only applies to "loop-dgram" transport */
if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
/* Set loop transport to return delayed error. */
pjsip_loop_set_failure(loop, 2, NULL);
pjsip_loop_set_send_callback_delay(loop, 10, NULL);
status = perform_tsx_test(-800, TARGET_URI, FROM_URI,
TEST2_BRANCH_ID, 2,
&pjsip_options_method);
if (status != 0)
return status;
/* Restore loop transport settings. */
pjsip_loop_set_failure(loop, 0, NULL);
pjsip_loop_set_send_callback_delay(loop, 0, NULL);
}
return status;
}
/*****************************************************************************
**
** TEST3_BRANCH_ID: UAC terminate while resolving test.
**
** Terminate the transaction while resolver is still running.
**
*****************************************************************************
*/
static int tsx_terminate_resolving_test(void)
{
unsigned prev_delay;
pj_status_t status;
PJ_LOG(3,(THIS_FILE, " test3: terminate while resolving test"));
/* Configure transport delay. */
pjsip_loop_set_send_callback_delay(loop, 100, &prev_delay);
/* Start the test. */
status = perform_tsx_test(-900, TARGET_URI, FROM_URI,
TEST3_BRANCH_ID, 2, &pjsip_options_method);
/* Restore delay. */
pjsip_loop_set_send_callback_delay(loop, prev_delay, NULL);
return status;
}
/*****************************************************************************
**
** TEST4_BRANCH_ID: Transport failed after several retransmissions
**
** There are two variants of this test: (a) failure occurs immediately when
** transaction calls pjsip_transport_send() or (b) failure is reported via
** transport callback.
**
*****************************************************************************
*/
static int tsx_retransmit_fail_test(void)
{
int i;
unsigned delay[] = {0, 10};
pj_status_t status;
PJ_LOG(3,(THIS_FILE,
" test4: transport fails after several retransmissions test"));
for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
PJ_LOG(3,(THIS_FILE,
" variant %c: transport delay %d ms", ('a'+i), delay[i]));
/* Configure transport delay. */
pjsip_loop_set_send_callback_delay(loop, delay[i], NULL);
/* Restore transport failure mode. */
pjsip_loop_set_failure(loop, 0, 0);
/* Start the test. */
status = perform_tsx_test(-1000, TARGET_URI, FROM_URI,
TEST4_BRANCH_ID, 6, &pjsip_options_method);
if (status != 0)
break;
}
/* Restore delay. */
pjsip_loop_set_send_callback_delay(loop, 0, NULL);
/* Restore transport failure mode. */
pjsip_loop_set_failure(loop, 0, 0);
return status;
}
/*****************************************************************************
**
** TEST5_BRANCH_ID: Terminate transaction after several retransmissions
**
*****************************************************************************
*/
static int tsx_terminate_after_retransmit_test(void)
{
int status;
PJ_LOG(3,(THIS_FILE, " test5: terminate after retransmissions"));
/* Do the test. */
status = perform_tsx_test(-1100, TARGET_URI, FROM_URI,
TEST5_BRANCH_ID,
6, &pjsip_options_method);
/* Done. */
return status;
}
/*****************************************************************************
**
** TEST6_BRANCH_ID: Successfull non-invite transaction
** TEST7_BRANCH_ID: Successfull non-invite transaction with provisional
** TEST8_BRANCH_ID: Failed invite transaction
** TEST9_BRANCH_ID: Failed invite transaction with provisional
**
*****************************************************************************
*/
static int perform_generic_test( const char *title,
char *branch_id,
const pjsip_method *method)
{
int i, status;
unsigned delay[] = { 1, 200 };
PJ_LOG(3,(THIS_FILE, " %s", title));
/* Do the test. */
for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) {
if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay",
('a'+i), delay[i]));
pjsip_loop_set_delay(loop, delay[i]);
}
status = perform_tsx_test(-1200, TARGET_URI, FROM_URI,
branch_id, 10, method);
if (status != 0)
return status;
if (test_param->type != PJSIP_TRANSPORT_LOOP_DGRAM)
break;
}
pjsip_loop_set_delay(loop, 0);
/* Done. */
return status;
}
/*****************************************************************************
**
** UAC Transaction Test.
**
*****************************************************************************
*/
int tsx_uac_test(struct tsx_test_param *param)
{
pj_sockaddr_in addr;
pj_status_t status;
timer.tsx_key.ptr = timer.key_buf;
test_param = param;
/* Get transport flag */
tp_flag = pjsip_transport_get_flag_from_type(test_param->type);
pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s",
param->port, param->tp_type);
pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s",
param->port, param->tp_type);
/* Check if loop transport is configured. */
status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
&addr, sizeof(addr), NULL, &loop);
if (status != PJ_SUCCESS) {
PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!"));
return -10;
}
/* Register modules. */
status = pjsip_endpt_register_module(endpt, &tsx_user);
if (status != PJ_SUCCESS) {
app_perror(" Error: unable to register module", status);
return -30;
}
status = pjsip_endpt_register_module(endpt, &msg_receiver);
if (status != PJ_SUCCESS) {
app_perror(" Error: unable to register module", status);
return -40;
}
/* TEST1_BRANCH_ID: Basic retransmit and timeout test. */
status = tsx_uac_retransmit_test();
if (status != 0)
return status;
/* TEST2_BRANCH_ID: Resolve error test. */
status = tsx_resolve_error_test();
if (status != 0)
return status;
/* TEST3_BRANCH_ID: UAC terminate while resolving test. */
status = tsx_terminate_resolving_test();
if (status != 0)
return status;
/* TEST4_BRANCH_ID: Transport failed after several retransmissions.
* Only applies to loop transport.
*/
if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
status = tsx_retransmit_fail_test();
if (status != 0)
return status;
}
/* TEST5_BRANCH_ID: Terminate transaction after several retransmissions
* Only applicable to non-reliable transports.
*/
if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
status = tsx_terminate_after_retransmit_test();
if (status != 0)
return status;
}
/* TEST6_BRANCH_ID: Successfull non-invite transaction */
status = perform_generic_test("test6: successfull non-invite transaction",
TEST6_BRANCH_ID, &pjsip_options_method);
if (status != 0)
return status;
/* TEST7_BRANCH_ID: Successfull non-invite transaction */
status = perform_generic_test("test7: successfull non-invite transaction "
"with provisional response",
TEST7_BRANCH_ID, &pjsip_options_method);
if (status != 0)
return status;
/* TEST8_BRANCH_ID: Failed invite transaction */
status = perform_generic_test("test8: failed invite transaction",
TEST8_BRANCH_ID, &pjsip_invite_method);
if (status != 0)
return status;
/* TEST9_BRANCH_ID: Failed invite transaction with provisional response */
status = perform_generic_test("test9: failed invite transaction with "
"provisional response",
TEST9_BRANCH_ID, &pjsip_invite_method);
if (status != 0)
return status;
pjsip_transport_dec_ref(loop);
flush_events(500);
/* Unregister modules. */
status = pjsip_endpt_unregister_module(endpt, &tsx_user);
if (status != PJ_SUCCESS) {
app_perror(" Error: unable to unregister module", status);
return -31;
}
status = pjsip_endpt_unregister_module(endpt, &msg_receiver);
if (status != PJ_SUCCESS) {
app_perror(" Error: unable to unregister module", status);
return -41;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -