Skip to content

Commit

Permalink
tm: detect blind uac branch to avoid generating cancel for it
Browse files Browse the repository at this point in the history
(cherry picked from commit e36eebf)
  • Loading branch information
miconda committed Jun 27, 2016
1 parent f087e62 commit 8814e5f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
9 changes: 5 additions & 4 deletions modules/tm/h_table.h
Expand Up @@ -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
{
Expand All @@ -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
Expand Down
9 changes: 7 additions & 2 deletions modules/tm/t_cancel.h
Expand Up @@ -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,
Expand Down
17 changes: 15 additions & 2 deletions modules/tm/t_fwd.c
Expand Up @@ -697,6 +697,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
Expand Down Expand Up @@ -1266,9 +1268,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
Expand Down Expand Up @@ -1297,7 +1309,7 @@ void e2e_cancel( struct sip_msg *cancel_msg,
}
}
#endif /* CANCEL_REASON_SUPPORT */
for (i=0; i<t_invite->nr_of_outgoings; i++)
for (i=0; i<t_invite->nr_of_outgoings; i++) {
if (cancel_bm & (1<<i)) {
/* it's safe to get the reply lock since e2e_cancel is
* called with the cancel as the "current" transaction so
Expand All @@ -1316,6 +1328,7 @@ void e2e_cancel( struct sip_msg *cancel_msg,
if (ret<0) cancel_bm &= ~(1<<i);
if (ret<lowest_error) lowest_error=ret;
}
}
#ifdef CANCEL_REASON_SUPPORT
if (unlikely(free_reason)) {
/* reason was not set as the global reason => free it */
Expand Down

0 comments on commit 8814e5f

Please sign in to comment.