Skip to content

Commit

Permalink
Terminate client transaction upon transport error (pjsip#3806)
Browse files Browse the repository at this point in the history
  • Loading branch information
trengginas authored and dshamaev-intermedia committed Mar 22, 2024
1 parent 52c5cc6 commit 8c2a0b9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 30 deletions.
26 changes: 22 additions & 4 deletions pjsip/src/pjsip/sip_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -2146,7 +2146,13 @@ static void send_msg_callback( pjsip_send_state *send_state,

/* Terminate transaction, if it's not already terminated. */
tsx_set_status_code(tsx, sc, &err);
if (tsx->state != PJSIP_TSX_STATE_TERMINATED &&
/* For UAC tsx, we directly terminate the transaction.
* For UAS tsx, we terminate the transaction for 502 error,
* and will retry for 503.
* See #3805 and #3806.
*/
if ((tsx->role == PJSIP_ROLE_UAC || sc == PJSIP_SC_BAD_GATEWAY) &&
tsx->state != PJSIP_TSX_STATE_TERMINATED &&
tsx->state != PJSIP_TSX_STATE_DESTROYED)
{
/* Set tsx state to TERMINATED, but release the lock
Expand Down Expand Up @@ -2218,7 +2224,16 @@ static void transport_callback(void *token, pjsip_tx_data *tdata,
pj_grp_lock_acquire(tsx->grp_lock);
tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT);

if (sent > 0) {
if (sent > 0 || tsx->role == PJSIP_ROLE_UAS) {
if (sent < 0) {
/* For UAS transactions, we just print error log
* and continue as per normal.
*/
PJ_PERROR(2,(tsx->obj_name, (pj_status_t)-sent,
"Transport failed to send %s!",
pjsip_tx_data_get_info(tdata)));
}

/* Pending destroy? */
if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) {
tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED,
Expand Down Expand Up @@ -2251,7 +2266,7 @@ static void transport_callback(void *token, pjsip_tx_data *tdata,
}
pj_grp_lock_release(tsx->grp_lock);

if (sent < 0) {
if (sent < 0 && tsx->role == PJSIP_ROLE_UAC) {
pj_time_val delay = {0, 0};

PJ_PERROR(2,(tsx->obj_name, (pj_status_t)-sent,
Expand Down Expand Up @@ -2386,8 +2401,11 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx,

/* If we have resolved the server, we treat the error as permanent error.
* Terminate transaction with transport error failure.
* Only applicable for UAC transactions.
*/
if (tsx->transport_flag & TSX_HAS_RESOLVED_SERVER) {
if (tsx->role == PJSIP_ROLE_UAC &&
(tsx->transport_flag & TSX_HAS_RESOLVED_SERVER))
{

char errmsg[PJ_ERR_MSG_SIZE];
pj_str_t err;
Expand Down
2 changes: 1 addition & 1 deletion pjsip/src/test/tsx_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ static int uas_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed)
rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL);
rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL);
rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CALL_ID, NULL);
rdata.msg_info.via = via;

pj_sockaddr_in_init(&remote, 0, 0);
Expand Down
56 changes: 31 additions & 25 deletions pjsip/src/test/tsx_uas_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,11 @@ static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
if (!test_complete)
test_complete = 1;

if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) {
if (tsx->status_code != PJSIP_SC_REQUEST_TIMEOUT) {
PJ_LOG(3,(THIS_FILE," error: incorrect status code"
" (expecting %d, got %d)",
PJSIP_SC_TSX_TRANSPORT_ERROR,
PJSIP_SC_REQUEST_TIMEOUT,
// PJSIP_SC_TSX_TRANSPORT_ERROR,
tsx->status_code));
test_complete = -170;
}
Expand All @@ -726,12 +727,13 @@ static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
if (!test_complete)
test_complete = 1;

if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR &&
if (tsx->status_code != PJSIP_SC_REQUEST_TIMEOUT &&
tsx->status_code != PJSIP_SC_OK)
{
PJ_LOG(3,(THIS_FILE," error: incorrect status code"
" (expecting %d, got %d)",
PJSIP_SC_TSX_TRANSPORT_ERROR,
PJSIP_SC_REQUEST_TIMEOUT,
// PJSIP_SC_TSX_TRANSPORT_ERROR,
tsx->status_code));
test_complete = -170;
}
Expand Down Expand Up @@ -1199,9 +1201,11 @@ static int perform_test( char *target_uri, char *from_uri,
int sent_cnt;
pj_status_t status;

PJ_LOG(3,(THIS_FILE,
" please standby, this will take at most %d seconds..",
test_time));
if (test_time > 0) {
PJ_LOG(3,(THIS_FILE,
" please standby, this will take at most %d seconds..",
test_time));
}

/* Reset test. */
recv_count = 0;
Expand Down Expand Up @@ -1481,24 +1485,29 @@ int tsx_transport_failure_test(void)
{
struct test_desc
{
int result;
int transport_delay;
int fail_delay;
char *branch_id;
char *title;
} tests[] =
{
{ 0, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (no delay)" },
{ 50, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (50 ms delay)" },
{ 0, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (no delay)" },
// After ticket #2076, transport error will be ignored if tsx is in COMPLETED state, note that
// tsx state will be shifted to COMPLETED state once 200 response is sent due to transport delay.
//{ 50, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (50 ms delay)" },
{ 0, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (no delay)" },
//Not applicable (maybe)
//This test may expect transport failure notification in COMPLETED state. This may not be
//possible because the loop transport can only notify failure when it has something to send,
//while in this case, there is nothing to send because UAS already sends 200/OK
//{ 50, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (50 ms delay)" },
// After #3805 and #3806, transport error will be ignored and
// the tests will time out.
// All tests are valid, but it will take too long to complete,
// so we disable some of the similar ones.
{ 0, 0, 10, TEST10_BRANCH_ID,
"test10: failed transport in TRYING state (no delay)" },
//{ 0, 50, 10, TEST10_BRANCH_ID,
// "test10: failed transport in TRYING state (50 ms delay)" },
//{ 1, 0, 1500, TEST11_BRANCH_ID,
// "test11: failed transport in PROCEEDING state (no delay)" },
{ 1, 50, 1500, TEST11_BRANCH_ID,
"test11: failed transport in PROCEEDING state (50 ms delay)" },
{ 1, 0, 2500, TEST12_BRANCH_ID,
"test12: failed transport in COMPLETED state (no delay)" },
//{ 1, 50, 2500, TEST12_BRANCH_ID,
// "test12: failed transport in COMPLETED state (50 ms delay)" },
};
int i, status;

Expand Down Expand Up @@ -1532,21 +1541,18 @@ int tsx_transport_failure_test(void)
PJ_LOG(5,(THIS_FILE, " transport loop fail mode set"));

end_test = now;
end_test.sec += 5;
end_test.sec += 33;

do {
pj_time_val interval = { 0, 1 };
pj_gettimeofday(&now);
pjsip_endpt_handle_events(endpt, &interval);
} while (!test_complete && PJ_TIME_VAL_LT(now, end_test));

if (test_complete == 0) {
PJ_LOG(3,(THIS_FILE, " error: test has timed out"));
if (test_complete != tests[i].result) {
PJ_LOG(3,(THIS_FILE, " error: expecting timeout"));
return -41;
}

if (test_complete != 1)
return test_complete;
}

return 0;
Expand Down

0 comments on commit 8c2a0b9

Please sign in to comment.