Prechádzať zdrojové kódy

tm: detect blind uac branch to avoid generating cancel for it

Daniel-Constantin Mierla 9 rokov pred
rodič
commit
e36eebf36b
3 zmenil súbory, kde vykonal 27 pridanie a 8 odobranie
  1. 5 4
      modules/tm/h_table.h
  2. 7 2
      modules/tm/t_cancel.h
  3. 15 2
      modules/tm/t_fwd.c

+ 5 - 4
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

+ 7 - 2
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,

+ 15 - 2
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; 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
@@ -1330,6 +1342,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 */