From e36eebf36b72819b1b23c39469d60206f5df2bcf Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 20 Jun 2016 22:39:08 +0200 Subject: [PATCH] tm: detect blind uac branch to avoid generating cancel for it --- modules/tm/h_table.h | 9 +++++---- modules/tm/t_cancel.h | 9 +++++++-- modules/tm/t_fwd.c | 17 +++++++++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h index 3cef44474e5..c6b334b0320 100644 --- a/modules/tm/h_table.h +++ b/modules/tm/h_table.h @@ -183,9 +183,10 @@ typedef struct ua_server /* User Agent Client content */ /* UAC internal flags */ -#define TM_UAC_FLAG_RR 1 /* Record-Route applied */ -#define TM_UAC_FLAG_R2 2 /* 2nd Record-Route applied */ -#define TM_UAC_FLAG_FB 4 /* Mark first entry in new branch set */ +#define TM_UAC_FLAG_RR (1) /* Record-Route applied */ +#define TM_UAC_FLAG_R2 (1<<1) /* 2nd Record-Route applied */ +#define TM_UAC_FLAG_FB (1<<2) /* Mark first entry in new branch set */ +#define TM_UAC_FLAG_BLIND (1<<3) /* A blind uac */ typedef struct ua_client { @@ -194,7 +195,7 @@ typedef struct ua_client char *end_reply; /* pointer to end of sip_msg so we know the shm blocked used in clone...(used in async replies) */ struct retr_buf request; /* we maintain a separate copy of cancel rather than - reuse the structure for original request; the + reuse the structure for original request; the original request is no longer needed but its delayed timer may fire and interfere with whoever tries to rewrite it diff --git a/modules/tm/t_cancel.h b/modules/tm/t_cancel.h index f8fe1189dd6..d3289388f0f 100644 --- a/modules/tm/t_cancel.h +++ b/modules/tm/t_cancel.h @@ -103,9 +103,14 @@ inline short static prepare_cancel_branch( struct cell *t, int b, int noreply ) int last_received; unsigned long old; + /* blind uac branch (e.g., suspend) without outgoing request */ + if((t->uac[b].flags & TM_UAC_FLAG_BLIND) + && t->uac[b].request.buffer==NULL) + return 0; + last_received=t->uac[b].last_received; - /* if noreply=1 cancel even if no reply received (in this case - * cancel_branch() won't actually send the cancel but it will do the + /* if noreply=1 cancel even if no reply received (in this case + * cancel_branch() won't actually send the cancel but it will do the * cleanup) */ if (last_received<200 && (noreply || last_received>=100)){ old=atomic_cmpxchg_long((void*)&t->uac[b].local_cancel.buffer, 0, diff --git a/modules/tm/t_fwd.c b/modules/tm/t_fwd.c index 7f6faa0cb0c..7bb9ce60178 100644 --- a/modules/tm/t_fwd.c +++ b/modules/tm/t_fwd.c @@ -711,6 +711,8 @@ int add_blind_uac( /*struct cell *t*/ ) t->flags |= T_NOISY_CTIMER_FLAG; membar_write(); /* to allow lockless prepare_to_cancel() we want to be sure all the writes finished before updating branch number*/ + + t->uac[branch].flags |= TM_UAC_FLAG_BLIND; t->nr_of_outgoings=(branch+1); t->async_backup.blind_uac = branch; /* whenever we create a blind UAC, lets save the current branch * this is used in async tm processing specifically to be able to route replies @@ -1280,9 +1282,19 @@ void e2e_cancel( struct sip_msg *cancel_msg, t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE ); return; } - + /* determine which branches to cancel ... */ prepare_to_cancel(t_invite, &cancel_bm, 0); + + /* no branches to cancel (e.g., a suspended transaction with blind uac) */ + if (cancel_bm==0){ + /* no outgoing branches yet => force a reply to the invite */ + t_reply( t_invite, t_invite->uas.request, 487, CANCELED ); + DBG("DEBUG: e2e_cancel: e2e cancel -- no active branches\n"); + t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE ); + return; + } + #ifdef E2E_CANCEL_HOP_BY_HOP /* we don't need to set t_cancel label to be the same as t_invite if * we do hop by hop cancel. The cancel transaction will have a different @@ -1311,7 +1323,7 @@ void e2e_cancel( struct sip_msg *cancel_msg, } } #endif /* CANCEL_REASON_SUPPORT */ - for (i=0; inr_of_outgoings; i++) + for (i=0; inr_of_outgoings; i++) { if (cancel_bm & (1< free it */