Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions pjsip/include/pjsip/sip_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,19 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
# define PJSIP_TSX_1XX_RETRANS_DELAY 60
#endif

/**
* Setting to determine if certain SIP UAS transaction, such as
* INVITE UAS tsx that hasn't been confirmed, is allowed to continue
* upon transport error. If disabled, the transaction will always be
* terminated, which is the default behavior prior to the introduction
* of this setting.
*
* Default: 1 (transaction will continue)
*/
#ifndef PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR
# define PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR 1
#endif

#define PJSIP_MAX_TSX_KEY_LEN (PJSIP_MAX_URL_SIZE*2)

/* User agent. */
Expand Down
35 changes: 32 additions & 3 deletions pjsip/src/pjsip/sip_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ static pj_time_val timeout_timer_val = { (64*PJSIP_T1_TIMEOUT)/1000,
#define RETRANSMIT_TIMER 1
#define TIMEOUT_TIMER 2
#define TRANSPORT_ERR_TIMER 3
#define TRANSPORT_DISC_TIMER 4

/* Flags for tsx_set_state() */
enum
Expand Down Expand Up @@ -1124,8 +1125,11 @@ static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry)
return;
}

if (entry->id == TRANSPORT_ERR_TIMER) {
/* Posted transport error event */
if (entry->id == TRANSPORT_ERR_TIMER || entry->id == TRANSPORT_DISC_TIMER)
{
/* Posted transport error/disconnection event */
pj_bool_t tp_disc = (entry->id == TRANSPORT_DISC_TIMER);

entry->id = 0;
if (tsx->state < PJSIP_TSX_STATE_TERMINATED) {
pjsip_tsx_state_e prev_state;
Expand All @@ -1137,6 +1141,31 @@ static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry)
/* Release transport as it's no longer working. */
tsx_update_transport(tsx, NULL);

#if PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR
if (tp_disc && tsx->method.id == PJSIP_INVITE_METHOD &&
tsx->role == PJSIP_ROLE_UAS && tsx->status_code < 200 &&
!(tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) &&
!(tsx->transport_flag & TSX_HAS_PENDING_DESTROY))
#else
PJ_UNUSED_ARG(tp_disc);
if (0)
#endif
{
/* Upon transport disconnection event, if we receive
* incoming INVITE and haven't responded with a final answer,
* just return here and don't terminate the transaction,
* in case that the library can switch to another working
* transport.
*/
tsx->transport_flag = 0;
tsx->addr_len = 0;
tsx->res_addr.transport = NULL;
tsx->res_addr.addr_len = 0;

pj_grp_lock_release(tsx->grp_lock);
return;
}

if (tsx->status_code < 200) {
pj_str_t err;
char errmsg[PJ_ERR_MSG_SIZE];
Expand Down Expand Up @@ -2132,7 +2161,7 @@ static void tsx_tp_state_callback( pjsip_transport *tp,
if (tsx->state < PJSIP_TSX_STATE_COMPLETED) {
tsx_cancel_timer(tsx, &tsx->timeout_timer);
tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay,
TRANSPORT_ERR_TIMER);
TRANSPORT_DISC_TIMER);
}
unlock_timer(tsx);
}
Expand Down