Переглянути джерело

- stop creating new branches (forking)if a 6xx or a CANCEL was received
- cancel branch fix: if a branch was canceled stop possible dns failover
forking on it
- stop retransmission timer fix for cancel for non-invites

Andrei Pelinescu-Onciul 19 роки тому
батько
коміт
81f72c6ca1
4 змінених файлів з 31 додано та 7 видалено
  1. 1 1
      Makefile.defs
  2. 9 1
      modules/tm/h_table.h
  3. 4 2
      modules/tm/t_cancel.c
  4. 17 3
      modules/tm/t_fwd.c

+ 1 - 1
Makefile.defs

@@ -67,7 +67,7 @@ MAIN_NAME=ser
 VERSION = 0
 VERSION = 0
 PATCHLEVEL = 10
 PATCHLEVEL = 10
 SUBLEVEL =   99
 SUBLEVEL =   99
-EXTRAVERSION = -dev50-dns_cache
+EXTRAVERSION = -dev51-tm_fixes
 
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 			$(SUBLEVEL) )
 			$(SUBLEVEL) )

+ 9 - 1
modules/tm/h_table.h

@@ -111,6 +111,10 @@ enum kill_reason { REQ_FWDED=1, REQ_RPLD=2, REQ_RLSD=4, REQ_EXIST=8 };
 #define F_RB_REPLIED	0x20 /* reply received */
 #define F_RB_REPLIED	0x20 /* reply received */
 
 
 
 
+/* if canceled or intended to be canceled, return true */
+#define uac_dont_fork(uac)	((uac)->local_cancel.buffer)
+
+
 typedef struct retr_buf
 typedef struct retr_buf
 {
 {
 	short activ_type;
 	short activ_type;
@@ -191,11 +195,15 @@ struct totag_elem {
 /* transaction canceled */
 /* transaction canceled */
 #define T_CANCELED           (1<<3)
 #define T_CANCELED           (1<<3)
 /* 6xx received => stop forking */
 /* 6xx received => stop forking */
-#define T_6xx                (1<<4) 
+#define T_6xx            (1<<4) 
 
 
 #define T_IN_AGONY (1<<5) /* set if waiting to die (delete timer)
 #define T_IN_AGONY (1<<5) /* set if waiting to die (delete timer)
                              TODO: replace it with del on unref */
                              TODO: replace it with del on unref */
 
 
+#define T_DONT_FORK   (T_CANCELED|T_6xx)
+
+
+
 /* transaction context */
 /* transaction context */
 
 
 typedef struct cell
 typedef struct cell

+ 4 - 2
modules/tm/t_cancel.c

@@ -75,7 +75,9 @@ void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
  *          cancel_bm - bitmap with the branches that are supposed to be 
  *          cancel_bm - bitmap with the branches that are supposed to be 
  *                       canceled 
  *                       canceled 
  *          flags     - how_to_cancel flags, see cancel_branch()
  *          flags     - how_to_cancel flags, see cancel_branch()
- * returns: bitmap with the still active branches (on fr timer) */
+ * returns: bitmap with the still active branches (on fr timer)
+ * WARNING: always fill cancel_bm using which_cancel(), supplying values
+ *          in any other way is a bug*/
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
 {
 {
 	int i;
 	int i;
@@ -242,7 +244,7 @@ void rpc_cancel(rpc_t* rpc, void* c)
 	i=cancel_uacs(trans, cancel_bm, 0); /* don't fake 487s, 
 	i=cancel_uacs(trans, cancel_bm, 0); /* don't fake 487s, 
 										 just wait for timeout */
 										 just wait for timeout */
 	
 	
-	     /* t_lookup_callid REF`d the transaction for us, we must UNREF here! */
+	/* t_lookup_callid REF`d the transaction for us, we must UNREF here! */
 	UNREF(trans);
 	UNREF(trans);
 	j=0;
 	j=0;
 	while(i){
 	while(i){

+ 17 - 3
modules/tm/t_fwd.c

@@ -58,6 +58,9 @@
  *               failure_route and replying to a cancel (andrei)
  *               failure_route and replying to a cancel (andrei)
  *  2006-10-10  e2e_cancel update for the new/modified 
  *  2006-10-10  e2e_cancel update for the new/modified 
  *               which_cancel()/should_cancel() (andrei)
  *               which_cancel()/should_cancel() (andrei)
+ *  2006-10-11  don't fork a new branch if the transaction or branch was
+ *               canceled, or a 6xx was received
+ *              stop retr. timers fix on cancel for non-invites     (andrei)
  */
  */
 
 
 #include "defs.h"
 #include "defs.h"
@@ -361,11 +364,20 @@ int add_uac_dns_fallback( struct cell *t, struct sip_msg* msg,
 	int ret;
 	int ret;
 	
 	
 	ret=-1;
 	ret=-1;
-	if (use_dns_failover && dns_srv_handle_next(&old_uac->dns_h, 0)){
+	if (use_dns_failover && 
+			!((t->flags & T_DONT_FORK) || uac_dont_fork(old_uac)) &&
+			dns_srv_handle_next(&old_uac->dns_h, 0)){
 			if (lock_replies){
 			if (lock_replies){
 				/* use reply lock to guarantee nobody is adding a branch
 				/* use reply lock to guarantee nobody is adding a branch
 				 * in the same time */
 				 * in the same time */
 				LOCK_REPLIES(t);
 				LOCK_REPLIES(t);
+				/* check again that we can fork */
+				if ((t->flags & T_DONT_FORK) || uac_dont_fork(old_uac)){
+					UNLOCK_REPLIES(t);
+					DBG("add_uac_dns_fallback: no forking on => no new"
+							" branches\n");
+					return ret;
+				}
 			}
 			}
 			if (t->nr_of_outgoings >= MAX_BRANCHES){
 			if (t->nr_of_outgoings >= MAX_BRANCHES){
 				LOG(L_ERR, "ERROR: add_uac_dns_fallback: maximum number of "
 				LOG(L_ERR, "ERROR: add_uac_dns_fallback: maximum number of "
@@ -493,8 +505,10 @@ void e2e_cancel( struct sip_msg *cancel_msg,
 		if (cancel_bm & (1 << i)) {
 		if (cancel_bm & (1 << i)) {
 			if (t_invite->uac[i].last_received>=100){
 			if (t_invite->uac[i].last_received>=100){
 				/* Provisional reply received on this branch, send CANCEL */
 				/* Provisional reply received on this branch, send CANCEL */
-				/* No need to stop timers as they have already been stopped 
-				 * by the reply */
+				/* we do need to stop the retr. timers if the request is not 
+				 * an invite and since the stop_rb_retr() cost is lower then
+				 * the invite check we do it always --andrei */
+				stop_rb_retr(&t_invite->uac[i].request);
 				if (SEND_BUFFER(&t_cancel->uac[i].request) == -1) {
 				if (SEND_BUFFER(&t_cancel->uac[i].request) == -1) {
 					LOG(L_ERR, "ERROR: e2e_cancel: send failed\n");
 					LOG(L_ERR, "ERROR: e2e_cancel: send failed\n");
 				}
 				}