Skip to content

Commit

Permalink
dialog: prevent BYEs on dialog expiration when replication tag is backup
Browse files Browse the repository at this point in the history
  • Loading branch information
rvlad-patrascu committed Mar 27, 2018
1 parent 5fdbce4 commit c9e68f9
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 30 deletions.
39 changes: 23 additions & 16 deletions modules/dialog/dlg_handlers.c
Expand Up @@ -1907,7 +1907,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
/* When done, this function also has the job to unref the dialog as removed
* from timer list. This must be done in all cases!!
*/
void dlg_ontimeout( struct dlg_tl *tl)
void dlg_ontimeout(struct dlg_tl *tl)
{
struct sip_msg *fake_msg;
context_p old_ctx;
Expand All @@ -1916,28 +1916,35 @@ void dlg_ontimeout( struct dlg_tl *tl)
int new_state;
int old_state;
int unref;
int do_expire_actions = 1;

dlg = get_dlg_tl_payload(tl);

LM_DBG("byeontimeout ? %d , state = %d\n",dlg->flags,dlg->state);
LM_DBG("byeontimeout ? flags = %d , state = %d\n",dlg->flags,dlg->state);

if ( (dlg->flags&DLG_FLAG_BYEONTIMEOUT) &&
(dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED)) {
if (dialog_repl_cluster)
/* if dialog replication is used, send BYEs only if the current node
* is "in charge" of the dialog (or if unable to fetch this info) */
do_expire_actions = get_repltag_state(dlg) != REPLTAG_STATE_BACKUP;

init_dlg_term_reason(dlg,"Lifetime Timeout",sizeof("Lifetime Timeout")-1);
if ((dlg->flags&DLG_FLAG_BYEONTIMEOUT) &&
(dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED)) {

if (do_expire_actions)
init_dlg_term_reason(dlg,"Lifetime Timeout",sizeof("Lifetime Timeout")-1);
/* we just send the BYEs in both directions */
dlg_end_dlg( dlg, NULL);
/* dialog is no longer refed by timer; from now one it is refed
dlg_end_dlg(dlg, NULL, do_expire_actions);
/* dialog is no longer refed by timer; from now on it is refed
by the send_bye functions */
unref_dlg( dlg, 1);
unref_dlg(dlg, 1);
/* is not 100% sure, but do it */
if_update_stat( dlg_enable_stats, expired_dlgs, 1);
return ;
if_update_stat(dlg_enable_stats, expired_dlgs, 1);

return;
}

/* act like as if we've received a BYE from caller */
next_state_dlg( dlg, DLG_EVENT_REQBYE, DLG_DIR_DOWNSTREAM, &old_state,
next_state_dlg(dlg, DLG_EVENT_REQBYE, DLG_DIR_DOWNSTREAM, &old_state,
&new_state, &unref, dlg->legs_no[DLG_LEG_200OK], 0);

if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
Expand All @@ -1955,8 +1962,8 @@ void dlg_ontimeout( struct dlg_tl *tl)
dlg_unlock_dlg(dlg);

/* dialog timeout */
if (push_new_processing_context( dlg, &old_ctx, &new_ctx, &fake_msg)==0) {
run_dlg_callbacks( DLGCB_EXPIRED, dlg, fake_msg,
if (push_new_processing_context(dlg, &old_ctx, &new_ctx, &fake_msg)==0) {
run_dlg_callbacks(DLGCB_EXPIRED, dlg, fake_msg,
DLG_DIR_NONE, NULL, 0);

if (current_processing_ctx == NULL)
Expand All @@ -1974,8 +1981,8 @@ void dlg_ontimeout( struct dlg_tl *tl)

unref_dlg(dlg, unref + 1 /*timer list*/);

if_update_stat( dlg_enable_stats, expired_dlgs, 1);
if_update_stat( dlg_enable_stats, active_dlgs, -1);
if_update_stat(dlg_enable_stats, expired_dlgs, 1);
if_update_stat(dlg_enable_stats, active_dlgs, -1);
} else {
unref_dlg(dlg, 1 /*just timer list*/);
}
Expand Down Expand Up @@ -2363,7 +2370,7 @@ int terminate_dlg(unsigned int h_entry, unsigned int h_id,str *reason)

init_dlg_term_reason(dlg,reason->s,reason->len);

if ( dlg_end_dlg( dlg, 0) ) {
if (dlg_end_dlg(dlg, 0, 1) ) {
LM_ERR("Failed to end dialog");
ret = -1;
}
Expand Down
2 changes: 1 addition & 1 deletion modules/dialog/dlg_profile.c
Expand Up @@ -1425,7 +1425,7 @@ struct mi_root * mi_profile_terminate(struct mi_root *cmd_tree, void *param ) {
init_dlg_term_reason(delete_entry->dlg, "MI Termination",
sizeof("MI Termination") - 1);

if ( dlg_end_dlg( delete_entry->dlg, NULL) ) {
if (dlg_end_dlg( delete_entry->dlg, NULL, 1) ) {
while(delete_entry){
deleted = delete_entry;
delete_entry = delete_entry->next;
Expand Down
27 changes: 17 additions & 10 deletions modules/dialog/dlg_req_within.c
Expand Up @@ -316,7 +316,7 @@ void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps)
/* mark the transaction as belonging to this dialog */
t->dialog_ctx = *(ps->param);

dual_bye_event( (struct dlg_cell *)(*(ps->param)), ps->req, 1);
dual_bye_event((struct dlg_cell *)(*(ps->param)), ps->req, 1);
}


Expand Down Expand Up @@ -421,15 +421,16 @@ static inline int send_leg_bye(struct dlg_cell *cell, int dst_leg, int src_leg,
/* sends BYE in both directions
* returns 0 if both BYEs were successful
*/
int dlg_end_dlg(struct dlg_cell *dlg, str *extra_hdrs)
int dlg_end_dlg(struct dlg_cell *dlg, str *extra_hdrs, int send_byes)
{
str str_hdr = {NULL,0};
struct cell* t;
int i,res = 0;
int callee;

/* lookup_dlg has incremented the reference count !! */
if (dlg->state == DLG_STATE_UNCONFIRMED || dlg->state == DLG_STATE_EARLY) {
if (send_byes &&
(dlg->state == DLG_STATE_UNCONFIRMED || dlg->state == DLG_STATE_EARLY)) {
/* locate initial transaction */
LM_DBG("trying to find transaction with hash_index = %u and label = %u\n",
dlg->initial_t_hash_index,dlg->initial_t_label);
Expand All @@ -449,23 +450,29 @@ int dlg_end_dlg(struct dlg_cell *dlg, str *extra_hdrs)
return 0;
}

if ((build_extra_hdr(dlg, extra_hdrs, &str_hdr)) != 0){
if (send_byes && (build_extra_hdr(dlg, extra_hdrs, &str_hdr)) != 0){
LM_ERR("failed to create extra headers\n");
return -1;
}

callee = callee_idx(dlg);
if ( send_leg_bye( dlg, DLG_CALLER_LEG, callee, &str_hdr)!=0) {
if (send_byes && send_leg_bye(dlg, DLG_CALLER_LEG, callee, &str_hdr)!=0) {
res--;
}
if (send_leg_bye( dlg, callee, DLG_CALLER_LEG, &str_hdr)!=0 ) {
if (send_byes && send_leg_bye(dlg, callee, DLG_CALLER_LEG, &str_hdr)!=0 ) {
res--;
}

for( i=res ; i<0 ; i++)
dual_bye_event( dlg, NULL, 0);
if (!send_byes) {
dual_bye_event(dlg, NULL, 0);
dual_bye_event(dlg, NULL, 0);
} else
for(i=res ; i<0 ; i++)
dual_bye_event(dlg, NULL, 0);

if (str_hdr.s)
pkg_free(str_hdr.s);

pkg_free(str_hdr.s);
return res;
}

Expand Down Expand Up @@ -546,7 +553,7 @@ struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param ){
/* lookup_dlg has incremented the reference count !! */
init_dlg_term_reason(dlg,"MI Termination",sizeof("MI Termination")-1);

if ( dlg_end_dlg( dlg, mi_extra_hdrs) ) {
if (dlg_end_dlg(dlg, mi_extra_hdrs, 1) ) {
status = 500;
msg = MI_DLG_OPERATION_ERR;
msg_len = MI_DLG_OPERATION_ERR_LEN;
Expand Down
2 changes: 1 addition & 1 deletion modules/dialog/dlg_req_within.h
Expand Up @@ -117,7 +117,7 @@ static inline int push_new_processing_context( struct dlg_cell *dlg,
}


int dlg_end_dlg(struct dlg_cell *dlg, str *extra_hdrs);
int dlg_end_dlg(struct dlg_cell *dlg, str *extra_hdrs, int send_byes);

struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param );

Expand Down
4 changes: 2 additions & 2 deletions modules/dialog/dlg_timer.c
Expand Up @@ -910,7 +910,7 @@ void dlg_options_routine(unsigned int ticks , void * attr)
init_dlg_term_reason(dlg,"Ping Timeout",sizeof("Ping Timeout")-1);
/* FIXME - maybe better not to send BYE both ways as we know for
* sure one end in down . */
dlg_end_dlg(dlg,0);
dlg_end_dlg(dlg,0,1);

/* no longer reffed in list */
unref_dlg(dlg,1);
Expand Down Expand Up @@ -1008,7 +1008,7 @@ void dlg_reinvite_routine(unsigned int ticks , void * attr)
init_dlg_term_reason(dlg,"ReINVITE Ping Timeout",sizeof("ReINVITE Ping Timeout")-1);
/* FIXME - maybe better not to send BYE both ways as we know for
* sure one end in down . */
dlg_end_dlg(dlg,0);
dlg_end_dlg(dlg,0,1);

/* no longer reffed in list */
unref_dlg(dlg,1);
Expand Down

0 comments on commit c9e68f9

Please sign in to comment.