Bogdan-Andrei Iancu il y a 23 ans
Parent
commit
549d5e1c96
10 fichiers modifiés avec 302 ajouts et 254 suppressions
  1. 1 1
      Makefile.defs
  2. 8 4
      modules/tm/h_table.c
  3. 9 3
      modules/tm/h_table.h
  4. 109 112
      modules/tm/t_funcs.c
  5. 4 3
      modules/tm/t_funcs.h
  6. 85 75
      modules/tm/t_lookup.c
  7. 73 43
      modules/tm/t_reply.c
  8. 1 1
      modules/tm/timer.c
  9. 11 11
      modules/tm/tm.c
  10. 1 1
      test/th-uri.cfg

+ 1 - 1
Makefile.defs

@@ -80,8 +80,8 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
 	 -DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"'\
 	 -DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"'\
 	 -DDNS_IP_HACK  -DPKG_MALLOC -DSHM_MEM  -DSHM_MMAP \
 	 -DDNS_IP_HACK  -DPKG_MALLOC -DSHM_MEM  -DSHM_MMAP \
 	 -DF_MALLOC  -DUSE_SYNONIM\
 	 -DF_MALLOC  -DUSE_SYNONIM\
+	 -DWAIT -DNEW_HNAME -DNOISY_REPLIES -DSRL\
 	 -DNO_DEBUG \
 	 -DNO_DEBUG \
-	 -DWAIT -DNEW_HNAME -DNOISY_REPLIES -DSRL
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
 	 #-DNOSMP \
 	 #-DNOSMP \
 	 #-DEXTRA_DEBUG 
 	 #-DEXTRA_DEBUG 

+ 8 - 4
modules/tm/h_table.c

@@ -21,7 +21,8 @@ void free_cell( struct cell* dead_cell )
 	shm_lock();
 	shm_lock();
 	if ( dead_cell->inbound_request )
 	if ( dead_cell->inbound_request )
 		sip_msg_free_unsafe( dead_cell->inbound_request );
 		sip_msg_free_unsafe( dead_cell->inbound_request );
-	if (b=dead_cell->outbound_response.retr_buffer) shm_free_unsafe( b );
+	if (b=dead_cell->outbound_response.retr_buffer)
+		shm_free_unsafe( b );
 
 
 	/* UA Clients */
 	/* UA Clients */
 	for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
 	for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
@@ -36,12 +37,15 @@ void free_cell( struct cell* dead_cell )
 		/* outbound ACKs, if any */
 		/* outbound ACKs, if any */
 		if (rb=dead_cell->outbound_ack[i] )
 		if (rb=dead_cell->outbound_ack[i] )
 			shm_free_unsafe( rb );
 			shm_free_unsafe( rb );
-		/* outbound requests*/
+		/* local cancel , if any */
+		if (rb=dead_cell->outbound_cancel[i] )
+			shm_free_unsafe( rb );
+		/* inbound response */
 		if ( dead_cell -> inbound_response[i] )
 		if ( dead_cell -> inbound_response[i] )
-		sip_msg_free_unsafe( dead_cell->inbound_response[i] );
+			sip_msg_free_unsafe( dead_cell->inbound_response[i] );
 	}
 	}
 	/* mutex */
 	/* mutex */
-	/* release_cell_lock( dead_cell ); */
+	/* release_cell_lock( dead_celle ); */
 	/* the cell's body */
 	/* the cell's body */
 	shm_free_unsafe( dead_cell );
 	shm_free_unsafe( dead_cell );
 	shm_unlock();
 	shm_unlock();

+ 9 - 3
modules/tm/h_table.h

@@ -32,7 +32,10 @@ struct timer;
 
 
 
 
 #define NO_CANCEL       ( (struct retrans_buff*) 0 )
 #define NO_CANCEL       ( (struct retrans_buff*) 0 )
-#define EXTERNAL_CANCEL ( (struct retarbs_buff*) -1)
+#define EXTERNAL_CANCEL ( (struct retrans_buff*) -1)
+
+#define STATUS_LOCAL_CANCEL -1
+#define STATUS_REQUEST       0
 
 
 
 
 typedef struct retrans_buff
 typedef struct retrans_buff
@@ -49,10 +52,13 @@ typedef struct retrans_buff
 
 
 	/*the cell that containes this retrans_buff*/
 	/*the cell that containes this retrans_buff*/
 	struct cell* my_T;
 	struct cell* my_T;
+	unsigned int branch;
 
 
 	enum lists retr_list;
 	enum lists retr_list;
-	/* set to status code if the buffer is a reply, 0 if request */
-	int reply;
+
+	/* set to status code if the buffer is a reply, 
+	0 if request or -1 if local CANCEL */
+	int status;
 
 
 }retrans_buff_type;
 }retrans_buff_type;
 
 

+ 109 - 112
modules/tm/t_funcs.c

@@ -134,35 +134,32 @@ int tm_startup()
 
 
 void tm_shutdown()
 void tm_shutdown()
 {
 {
-    struct timer_link  *tl, *end, *tmp;
-    int i;
+	struct timer_link  *tl, *end, *tmp;
+	int i;
 
 
-    DBG("DEBUG: tm_shutdown : start\n");
-    /*remember the DELETE LIST */
-    tl = hash_table->timers[DELETE_LIST].first_tl.next_tl;
+	DBG("DEBUG: tm_shutdown : start\n");
+	/* remember the DELETE LIST */
+	tl = hash_table->timers[DELETE_LIST].first_tl.next_tl;
 	end = & hash_table->timers[DELETE_LIST].last_tl;
 	end = & hash_table->timers[DELETE_LIST].last_tl;
-    /*unlink the lists*/
-    for( i=0; i<NR_OF_TIMER_LISTS ; i++ )
-    {
-       //lock( hash_table->timers[i].mutex );
+	/* unlink the timer lists */
+	for( i=0; i<NR_OF_TIMER_LISTS ; i++ )
 		reset_timer_list( hash_table, i );
 		reset_timer_list( hash_table, i );
-       //unlock( hash_table->timers[i].mutex );
-    }
 
 
-    DBG("DEBUG: tm_shutdown : empting DELETE list\n");
-    /* deletes all cells from DELETE_LIST list (they are no more accessible from enrys) */
+	DBG("DEBUG: tm_shutdown : empting DELETE list\n");
+	/* deletes all cells from DELETE_LIST list
+	(they are no more accessible from enrys) */
 	while (tl!=end) {
 	while (tl!=end) {
 		tmp=tl->next_tl;
 		tmp=tl->next_tl;
 		free_cell((struct cell*)tl->payload);
 		free_cell((struct cell*)tl->payload);
 		 tl=tmp;
 		 tl=tmp;
 	}
 	}
 
 
-    /* destroy the hash table */
-    DBG("DEBUG: tm_shutdown : empting hash table\n");
-    free_hash_table( hash_table );
-    DBG("DEBUG: tm_shutdown : removing semaphores\n");
+	/* destroy the hash table */
+	DBG("DEBUG: tm_shutdown : empting hash table\n");
+	free_hash_table( hash_table );
+	DBG("DEBUG: tm_shutdown : removing semaphores\n");
 	lock_cleanup();
 	lock_cleanup();
-    DBG("DEBUG: tm_shutdown : done\n");
+	DBG("DEBUG: tm_shutdown : done\n");
 }
 }
 
 
 
 
@@ -174,42 +171,34 @@ void tm_shutdown()
  */
  */
 int t_add_transaction( struct sip_msg* p_msg )
 int t_add_transaction( struct sip_msg* p_msg )
 {
 {
-   struct cell*    new_cell;
-
-   DBG("DEBUG: t_add_transaction: adding......\n");
+	struct cell*    new_cell;
 
 
-   /* sanity check: ACKs can never establish a transaction */
-   if ( p_msg->REQ_METHOD==METHOD_ACK )
-   {
-       LOG(L_ERR, "ERROR: add_transaction: ACK can't be used to add transaction\n");
-      return -1;
-   }
+	DBG("DEBUG: t_add_transaction: adding......\n");
 
 
-   /* it's about the same transaction or not?*/
-	/* if (t_check( p_msg , 0 )==-1) return -1; */
+	/* sanity check: ACKs can never establish a transaction */
+	if ( p_msg->REQ_METHOD==METHOD_ACK )
+	{
+		LOG(L_ERR, "ERROR: add_transaction: ACK can't be used to add"
+			" transaction\n");
+		return -1;
+	}
 
 
-   /* if the lookup's result is not 0 means that it's a retransmission */
-   /* if ( T )
-   {
-      LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
-      return -1;
-   } */
-
-   /* creates a new transaction */
-   new_cell = build_cell( p_msg ) ;
-   DBG("DEBUG: t_add_transaction: new transaction created %p\n", new_cell);
-   if  ( !new_cell ){
-	   LOG(L_ERR, "ERROR: add_transaction: out of mem:\n");
-	   sh_status();
-      return -1;
+	/* creates a new transaction */
+	new_cell = build_cell( p_msg ) ;
+	DBG("DEBUG: t_add_transaction: new transaction created %p\n", new_cell);
+	if  ( !new_cell ){
+		LOG(L_ERR, "ERROR: add_transaction: out of mem:\n");
+		sh_status();
+		return -1;
 	}
 	}
-   /*insert the transaction into hash table*/
-   insert_into_hash_table( hash_table , new_cell );
-   DBG("DEBUG: t_add_transaction: new transaction inserted, hash: %d\n", new_cell->hash_index );
+	/*insert the transaction into hash table*/
+	insert_into_hash_table( hash_table , new_cell );
+	DBG("DEBUG: t_add_transaction: new transaction inserted, hash: %d\n",
+		new_cell->hash_index );
 
 
-   T = new_cell;
+	T = new_cell;
 	T_REF(T);
 	T_REF(T);
-   return 1;
+	return 1;
 }
 }
 
 
 
 
@@ -223,28 +212,16 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 {
 {
 	unsigned int  dest_ip     = dest_ip_param;
 	unsigned int  dest_ip     = dest_ip_param;
 	unsigned int  dest_port  = dest_port_param;
 	unsigned int  dest_port  = dest_port_param;
-	int                  branch;
+	int           branch;
 	unsigned int  len;
 	unsigned int  len;
-	char               *buf, *shbuf;
+	char         *buf, *shbuf;
 	struct retrans_buff  *rb;
 	struct retrans_buff  *rb;
-	struct cell      *T_source = T;
+	struct cell  *T_source = T;
 
 
 	buf=NULL;
 	buf=NULL;
 	shbuf = NULL;
 	shbuf = NULL;
 	branch = 0;	/* we don't do any forking right now */
 	branch = 0;	/* we don't do any forking right now */
 
 
-	/* it's about the same transaction or not? */
-	/* if (t_check( p_msg , 0 )==-1) return -1; */
-
-	/*if T hasn't been found after all -> return not found (error) */
-	/*
-	if ( !T )
-	{
-		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
-		return -1;
-	}
-	*/
-
 	/*if it's an ACK and the status is not final or is final, but error the
 	/*if it's an ACK and the status is not final or is final, but error the
 	ACK is not forwarded*/
 	ACK is not forwarded*/
 	if ( p_msg->REQ_METHOD==METHOD_ACK  && (T->status/100)!=2 ) {
 	if ( p_msg->REQ_METHOD==METHOD_ACK  && (T->status/100)!=2 ) {
@@ -252,10 +229,10 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		return 1;
 		return 1;
 	}
 	}
 
 
-	/* if it's forwarded for the first time ; else the request is retransmited
-	 * from the transaction buffer
-	 * when forwarding an ACK, this condition will be all the time false because
-	 * the forwarded INVITE is in the retransmission buffer */
+	/* if it's forwarded for the first time, else the request is retransmited
+	from the transaction buffer when forwarding an ACK, this condition will
+	be all the time false because the forwarded INVITE is in the
+	retransmission buffer */
 	if ( T->outbound_request[branch]==NULL )
 	if ( T->outbound_request[branch]==NULL )
 	{
 	{
 		DBG("DEBUG: t_forward: first time forwarding\n");
 		DBG("DEBUG: t_forward: first time forwarding\n");
@@ -263,6 +240,12 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
 		if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
 		{
 		{
 			DBG("DEBUG: t_forward: it's CANCEL\n");
 			DBG("DEBUG: t_forward: it's CANCEL\n");
+			if (T->outgoing_cancel[branch]!=NO_CANCEL)
+			{
+				DBG("DEBUG: t_forward: CANCEL already send on this branch ->"
+					" dropping current CANCEL!!\n");
+				return 1;
+			}
 			/* find original cancelled transaction; if found, use its
 			/* find original cancelled transaction; if found, use its
 			   next-hops; otherwise use those passed by script */
 			   next-hops; otherwise use those passed by script */
 			if (T->T_canceled==T_UNDEFINED)
 			if (T->T_canceled==T_UNDEFINED)
@@ -304,8 +287,8 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		/* allocates a new retrans_buff for the outbound request */
 		/* allocates a new retrans_buff for the outbound request */
 		DBG("DEBUG: t_forward: building outbound request\n");
 		DBG("DEBUG: t_forward: building outbound request\n");
 		shm_lock();
 		shm_lock();
-		T->outbound_request[branch] = rb =
-			(struct retrans_buff*)shm_malloc_unsafe( sizeof(struct retrans_buff)  );
+		T->outbound_request[branch] = rb = (struct retrans_buff*)
+			shm_malloc_unsafe(sizeof(struct retrans_buff));
 		if (!rb)
 		if (!rb)
 		{
 		{
 			LOG(L_ERR, "ERROR: t_forward: out of shmem\n");
 			LOG(L_ERR, "ERROR: t_forward: out of shmem\n");
@@ -328,12 +311,14 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		rb->fr_timer.payload =  rb;
 		rb->fr_timer.payload =  rb;
 		rb->to.sin_family = AF_INET;
 		rb->to.sin_family = AF_INET;
 		rb->my_T =  T;
 		rb->my_T =  T;
+		rb->branch = branch;
 		T->nr_of_outgoings = 1;
 		T->nr_of_outgoings = 1;
 		rb->bufflen = len ;
 		rb->bufflen = len ;
 		memcpy( rb->retr_buffer , buf , len );
 		memcpy( rb->retr_buffer , buf , len );
 		free( buf ) ; buf=NULL;
 		free( buf ) ; buf=NULL;
 
 
-		DBG("DEBUG: t_forward: starting timers (retrans and FR) %d\n",get_ticks() );
+		DBG("DEBUG: t_forward: starting timers (retrans and FR) %d\n",
+			get_ticks() );
 		/*sets and starts the FINAL RESPONSE timer */
 		/*sets and starts the FINAL RESPONSE timer */
 		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
 		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
 
 
@@ -357,13 +342,14 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 	{
 	{
 		DBG("DEBUG: t_forward: forwarding CANCEL \n");
 		DBG("DEBUG: t_forward: forwarding CANCEL \n");
 		/* if no transaction to CANCEL
 		/* if no transaction to CANCEL
-		    or if the canceled transaction has a final status -> drop the CANCEL*/
+		or if the canceled transaction has a final status -> drop the CANCEL*/
 		if ( T->T_canceled!=T_NULL && T->T_canceled->status>=200)
 		if ( T->T_canceled!=T_NULL && T->T_canceled->status>=200)
 		{
 		{
 			reset_timer( hash_table, &(rb->fr_timer ));
 			reset_timer( hash_table, &(rb->fr_timer ));
 			reset_timer( hash_table, &(rb->retr_timer ));
 			reset_timer( hash_table, &(rb->retr_timer ));
 			return 1;
 			return 1;
 		}
 		}
+		T->outgoing_cancel = EXTERNAL_CANCEL;
 	}
 	}
 
 
 	/* send the request */
 	/* send the request */
@@ -412,7 +398,7 @@ int t_forward_uri( struct sip_msg* p_msg  )
 int t_on_request_received( struct sip_msg  *p_msg , 
 int t_on_request_received( struct sip_msg  *p_msg , 
 	unsigned int ip , unsigned int port)
 	unsigned int ip , unsigned int port)
 {
 {
-	if ( t_check( p_msg , 0 ) )
+	if ( t_check( p_msg , 0 , 0 ) )
 	{
 	{
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
 		{
 		{
@@ -495,25 +481,14 @@ int t_on_request_received_uri( struct sip_msg  *p_msg )
 
 
 
 
 /*   returns 1 if everything was OK or -1 for error
 /*   returns 1 if everything was OK or -1 for error
-  */
+*/
 int t_release_transaction( struct sip_msg* p_msg)
 int t_release_transaction( struct sip_msg* p_msg)
 {
 {
-/*
-	if (t_check( p_msg  , 0 )==-1) return 1;
-
-   if ( T && T!=T_UNDEFINED )
-*/
       return t_put_on_wait( T );
       return t_put_on_wait( T );
-
-/*   return 1; */
 }
 }
 
 
 
 
 
 
-
-
-
-
 int t_unref( /* struct sip_msg* p_msg */ )
 int t_unref( /* struct sip_msg* p_msg */ )
 {
 {
 	if (T==T_UNDEFINED || T==T_NULL)
 	if (T==T_UNDEFINED || T==T_NULL)
@@ -527,23 +502,16 @@ int t_unref( /* struct sip_msg* p_msg */ )
 
 
 
 
 
 
-
-
 /* ----------------------------HELPER FUNCTIONS-------------------------------- */
 /* ----------------------------HELPER FUNCTIONS-------------------------------- */
 
 
 
 
-
-
-
-/*
-  */
 int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 {
 {
 	struct cell *Trans = rb->my_T;
 	struct cell *Trans = rb->my_T;
 
 
 	/* make sure that if we send something final upstream, everything else
 	/* make sure that if we send something final upstream, everything else
 	   will be cancelled */
 	   will be cancelled */
-	if (Trans->status>=300 && Trans->inbound_request->REQ_METHOD==METHOD_INVITE )
+	if (Trans->status>=300&&Trans->inbound_request->REQ_METHOD==METHOD_INVITE)
 	{
 	{
 		rb->retr_list = RT_T1_TO_1;
 		rb->retr_list = RT_T1_TO_1;
 		set_timer( hash_table, &(rb->retr_timer), RT_T1_TO_1 );
 		set_timer( hash_table, &(rb->retr_timer), RT_T1_TO_1 );
@@ -568,10 +536,10 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 
 
 /* Checks if the new reply (with new_code status) should be sent or not
 /* Checks if the new reply (with new_code status) should be sent or not
  *  based on the current
  *  based on the current
-  * transactin status.
-  * Returns 	- branch number (0,1,...) which should be relayed
-		- -1 if nothing to be relayed
-  */
+ * transactin status.
+ * Returns 	- branch number (0,1,...) which should be relayed
+ *         -1 if nothing to be relayed
+ */
 int t_should_relay_response( struct cell *Trans , int new_code, 
 int t_should_relay_response( struct cell *Trans , int new_code, 
 	int branch , int *should_store )
 	int branch , int *should_store )
 {
 {
@@ -619,13 +587,12 @@ int t_should_relay_response( struct cell *Trans , int new_code,
 					Trans->inbound_response[b]->REPLY_STATUS<200 )
 					Trans->inbound_response[b]->REPLY_STATUS<200 )
 					return -1;
 					return -1;
 				if ( Trans->inbound_response[b]->REPLY_STATUS<lowest_s )
 				if ( Trans->inbound_response[b]->REPLY_STATUS<lowest_s )
-      				{
-         				lowest_b =b;
-         				lowest_s = T->inbound_response[b]->REPLY_STATUS;
-      				}
+				{
+					lowest_b =b;
+					lowest_s = T->inbound_response[b]->REPLY_STATUS;
+				}
 			}
 			}
 			return lowest_b;
 			return lowest_b;
-
 		/* 1xx except 100 and 2xx will be relayed */
 		/* 1xx except 100 and 2xx will be relayed */
 		} else if (new_code>100) {
 		} else if (new_code>100) {
 			*should_store=1;
 			*should_store=1;
@@ -633,7 +600,7 @@ int t_should_relay_response( struct cell *Trans , int new_code,
 		}
 		}
 		/* 100 won't be relayed */
 		/* 100 won't be relayed */
 		else {
 		else {
-			if (!T->inbound_response[branch]) *should_store=1; 
+			if (!T->inbound_response[branch]) *should_store=1;
 			else *should_store=0;
 			else *should_store=0;
 			return -1;
 			return -1;
 		}
 		}
@@ -860,7 +827,7 @@ error:
 
 
 
 
 /* Builds a CANCEL request based on an INVITE request. CANCEL is send
 /* Builds a CANCEL request based on an INVITE request. CANCEL is send
- * to same address */
+ * to same address as the INVITE */
 int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 {
 {
 	struct sip_msg      *p_msg;
 	struct sip_msg      *p_msg;
@@ -870,6 +837,13 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	int                  n;
 	int                  n;
 	struct retrans_buff *srb;
 	struct retrans_buff *srb;
 
 
+	if (Trans->outbound_cancel[branch]!=NO_CANCEL)
+	{
+		DBG("DEBUG: t_build_and_send_CANCEL: this branch was already canceled"
+			" : dropping local cancel! \n");
+		return 1;
+	}
+	
 	cancel_buf = 0;
 	cancel_buf = 0;
 	via = 0;
 	via = 0;
 	p_msg = Trans->inbound_request;
 	p_msg = Trans->inbound_request;
@@ -956,9 +930,30 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	/* end of message */
 	/* end of message */
 	append_mem_block(p,CRLF,CRLF_LEN);
 	append_mem_block(p,CRLF,CRLF_LEN);
 	*p=0;
 	*p=0;
-	
 
 
-	DBG("LOCAL CANCEL = \n%s\n",cancel_buf);
+	memset( srb, 0, sizeof( struct retrans_buff ) );
+	memcpy( & srb->to, & Trans->outbound_request[branch]->to,
+		sizeof (struct sockaddr_in));
+	srb->tolen = sizeof (struct sockaddr_in);
+	srb->my_T = Trans;
+	srb->branch = branch;
+	srb->status = STATUS_LOCAL_CANCEL;
+	srb->retr_buffer = (char *) srb + sizeof( struct retrans_buff );
+	srb->bufflen = len;
+	if (Trans->outbound_cancel[branch]) {
+		shm_free( srb );	
+		LOG(L_WARN, "send_cancel: Warning: CANCEL already sent out\n");
+		goto error;
+	}
+	Trans->outbound_cancel[branch] = srb;
+	/*sets and starts the FINAL RESPONSE timer */
+	set_timer( hash_table, &(srb->fr_timer), FR_TIMER_LIST );
+
+	/* sets and starts the RETRANS timer */
+	srb->retr_list = RT_T1_TO_1;
+	set_timer( hash_table, &(srb->retr_timer), RT_T1_TO_1 );
+	DBG("DEBUG: T_build_and_send_CANCEL : sending cancel...\n");
+	SEND_BUFFER( srb );
 
 
 	pkg_free(via);
 	pkg_free(via);
 	return 1;
 	return 1;
@@ -1131,13 +1126,8 @@ void retransmission_handler( void *attr)
 
 
 	/* retransmision */
 	/* retransmision */
 	DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
 	DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
-	if (r_buf->reply) {
+	if (r_buf->status!=STATUS_LOCAL_CANCEL && r_buf->status!=STATUS_REQUEST){
 		T=r_buf->my_T;
 		T=r_buf->my_T;
-/*
-		LOCK_REPLIES( r_buf->my_T );
-		SEND_BUFFER( r_buf );
-		UNLOCK_REPLIES( r_buf->my_T );
-*/
 		t_retransmit_reply();
 		t_retransmit_reply();
 	}else{
 	}else{
 		SEND_BUFFER( r_buf );
 		SEND_BUFFER( r_buf );
@@ -1168,13 +1158,20 @@ void final_response_handler( void *attr)
 #endif
 #endif
 
 
 	/* the transaction is already removed from FR_LIST by the timer */
 	/* the transaction is already removed from FR_LIST by the timer */
+	if (r_buf->status==STATUS_LOCAL_CANCEL)
+	{
+		DBG("DEBUG: final_response_handler: stop retransmission for"
+			"Local Cancel\n");
+		reset_timer( hash_table , &(r_buf->retr_timer) );
+		return;
+	}
 	/* send a 408 */
 	/* send a 408 */
 	if ( r_buf->my_T->status<200)
 	if ( r_buf->my_T->status<200)
 	{
 	{
 		DBG("DEBUG: final_response_handler:stop retransmission and"
 		DBG("DEBUG: final_response_handler:stop retransmission and"
 			" send 408 (t=%p)\n", r_buf->my_T);
 			" send 408 (t=%p)\n", r_buf->my_T);
 		reset_timer( hash_table, &(r_buf->retr_timer) );
 		reset_timer( hash_table, &(r_buf->retr_timer) );
-		t_build_and_send_CANCEL( r_buf->my_T ,0);
+		//t_build_and_send_CANCEL( r_buf->my_T ,r_buf->branch);
 		/* dirty hack:t_send_reply would increase ref_count which would indeed
 		/* dirty hack:t_send_reply would increase ref_count which would indeed
 		result in refcount++ which would not -- until timer processe's
 		result in refcount++ which would not -- until timer processe's
 		T changes again; currently only on next call to t_send_reply from
 		T changes again; currently only on next call to t_send_reply from

+ 4 - 3
modules/tm/t_funcs.h

@@ -157,7 +157,7 @@ int  t_add_transaction( struct sip_msg* p_msg  );
  *      -1 - transaction wasn't found
  *      -1 - transaction wasn't found
  *       1 - transaction found
  *       1 - transaction found
  */
  */
-int t_check( struct sip_msg* , int *branch );
+int t_check( struct sip_msg* , int *branch , int* is_cancel);
 
 
 
 
 
 
@@ -167,7 +167,7 @@ int t_check( struct sip_msg* , int *branch );
  *      -1 - error during forward
  *      -1 - error during forward
  */
  */
 int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
 int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
-				unsigned int dst_port);
+										unsigned int dst_port);
 
 
 
 
 
 
@@ -249,7 +249,7 @@ int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 
 
 
 
 struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg );
 struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg );
-int t_reply_matching( struct sip_msg* , unsigned int*  );
+int t_reply_matching( struct sip_msg* , unsigned int* , unsigned int* );
 int t_store_incoming_reply( struct cell* , unsigned int , struct sip_msg* );
 int t_store_incoming_reply( struct cell* , unsigned int , struct sip_msg* );
 int  t_lookup_request( struct sip_msg* p_msg , int leave_new_locked );
 int  t_lookup_request( struct sip_msg* p_msg , int leave_new_locked );
 int t_all_final( struct cell * );
 int t_all_final( struct cell * );
@@ -284,6 +284,7 @@ inline int static send_ack( struct cell *t, int branch,
 	memcpy( & srb->to, & t->ack_to, sizeof (struct sockaddr_in));
 	memcpy( & srb->to, & t->ack_to, sizeof (struct sockaddr_in));
 	srb->tolen = sizeof (struct sockaddr_in);
 	srb->tolen = sizeof (struct sockaddr_in);
 	srb->my_T = t;
 	srb->my_T = t;
+	srb->branch = branch;
 	srb->retr_buffer = (char *) srb + sizeof( struct retrans_buff );
 	srb->retr_buffer = (char *) srb + sizeof( struct retrans_buff );
 	srb->bufflen = len;
 	srb->bufflen = len;
 	LOCK_ACK( t );
 	LOCK_ACK( t );

+ 85 - 75
modules/tm/t_lookup.c

@@ -182,68 +182,70 @@ found:
  *       0 - transaction wasn't found
  *       0 - transaction wasn't found
  *       T - transaction found
  *       T - transaction found
  */
  */
-struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg )
+struct cell* t_lookupOriginalT(  struct s_table* hash_table ,
+													struct sip_msg* p_msg )
 {
 {
-   struct cell         *p_cell;
-   struct cell         *tmp_cell;
-   unsigned int       hash_index=0;
-   struct sip_msg	*t_msg;
+	struct cell     *p_cell;
+	struct cell     *tmp_cell;
+	unsigned int     hash_index=0;
+	struct sip_msg  *t_msg;
 
 
-   /* it's a CANCEL request for sure */
 
 
-   /* start searching into the table */
-   /* hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number  ) ; */
+	/* start searching into the table */
 	hash_index = p_msg->hash_index;
 	hash_index = p_msg->hash_index;
-   DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index );
-
-   /* all the transactions from the entry are compared */
-   p_cell     = hash_table->entrys[hash_index].first_cell;
-   tmp_cell = 0;
-   while( p_cell )
-   {
-     t_msg = p_cell->inbound_request;
-
-      /* is it the wanted transaction ? */
-      /* first only the length are checked */
-      if ( p_cell->inbound_request->REQ_METHOD!=METHOD_CANCEL )
-         if ( /*callid length*/ EQ_LEN(callid)  )
-            if ( get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len )
-               if ( EQ_REQ_URI_LEN )
-                   if ( EQ_VIA_LEN(via1) )
-                      if ( EQ_LEN(from) && EQ_LEN(to) )
-                        //if ( /*tag length*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && p_cell->inbound_request->tag->body.len == p_msg->tag->body.len) )
-                           /* so far the lengths are the same -> let's check the contents */
-                            if ( /*callid*/ EQ_STR(callid) )
-                               if ( /*cseq_nr*/ !memcmp( get_cseq(t_msg)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
-                                  if ( EQ_REQ_URI_STR )
-                                     if ( EQ_VIA_STR(via1) )
-                                        if ( EQ_STR(from) )
-                                            //if ( /*tag*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && memcmp( p_cell->inbound_request->tag->body.s , p_msg->tag->body.s , p_msg->tag->body.len )==0) )
-                                              { /* WE FOUND THE GOLDEN EGG !!!! */
-                                                DBG("DEBUG: t_lookupOriginalT: canceled transaction found (%x)! \n",p_cell );
-                                                return p_cell;
-                                             }
-      /* next transaction */
-      tmp_cell = p_cell;
-      p_cell = p_cell->next_cell;
-   }
-
-   /* no transaction found */
-   DBG("DEBUG: t_lookupOriginalT: no CANCEL maching found! \n" );
-   return 0;
+	DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index );
+
+	/* all the transactions from the entry are compared */
+	p_cell   = hash_table->entrys[hash_index].first_cell;
+	tmp_cell = 0;
+	while( p_cell )
+	{
+		t_msg = p_cell->inbound_request;
+
+		/* is it the wanted transaction ? */
+		/* first only the length are checked */
+		if ( p_cell->inbound_request->REQ_METHOD!=METHOD_CANCEL
+			&& /*callid length*/ EQ_LEN(callid)
+			&& get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
+			&& EQ_REQ_URI_LEN
+			&& EQ_VIA_LEN(via1) 
+			&& EQ_LEN(from)
+			&& EQ_LEN(to) )
+				/* so far the lengths are the same
+				 let's check the contents */
+				if ( /*callid*/ EQ_STR(callid)
+					&& /*cseq_nr*/ !memcmp(get_cseq(t_msg)->number.s,
+						get_cseq(p_msg)->number.s,get_cseq(p_msg)->number.len)
+					&& EQ_REQ_URI_STR
+					&& EQ_VIA_STR(via1)
+					&& EQ_STR(from) )
+					{ /* WE FOUND THE GOLDEN EGG !!!! */
+						DBG("DEBUG: t_lookupOriginalT: canceled transaction"
+							" found (%x)! \n",p_cell );
+						return p_cell;
+					}
+		/* next transaction */
+		tmp_cell = p_cell;
+		p_cell = p_cell->next_cell;
+	}
+
+	/* no transaction found */
+	DBG("DEBUG: t_lookupOriginalT: no CANCEL maching found! \n" );
+	return 0;
 }
 }
 
 
 
 
 
 
 
 
 /* Returns 0 - nothing found
 /* Returns 0 - nothing found
-  *              1  - T found
-  */
-int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
+ *         1  - T found
+ */
+int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch ,
+												unsigned int *local_cancel)
 {
 {
 	struct cell*  p_cell;
 	struct cell*  p_cell;
 	unsigned int loop_code    = 0;
 	unsigned int loop_code    = 0;
-	unsigned int hash_index = 0;
+	unsigned int hash_index   = 0;
 	unsigned int entry_label  = 0;
 	unsigned int entry_label  = 0;
 	unsigned int branch_id    = 0;
 	unsigned int branch_id    = 0;
 	char  *loopi,*hashi, *syni, *branchi, *p, *n;
 	char  *loopi,*hashi, *syni, *branchi, *p, *n;
@@ -251,9 +253,9 @@ int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
 	int scan_space;
 	int scan_space;
 
 
 	/* split the branch into pieces: loop_detection_check(ignored),
 	/* split the branch into pieces: loop_detection_check(ignored),
-	     hash_table_id, synonym_id, branch_id*/
+	 hash_table_id, synonym_id, branch_id */
 
 
-	if (!( p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s) )
+	if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s))
 		goto nomatch2;
 		goto nomatch2;
 
 
 	p=p_msg->via1->branch->value.s;
 	p=p_msg->via1->branch->value.s;
@@ -294,35 +296,40 @@ int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
 	branchi=p;
 	branchi=p;
 
 
 	/* sanity check */
 	/* sanity check */
-	if ( (hash_index=reverse_hex2int(hashi, hashl))<0 || hash_index >=TABLE_ENTRIES
-	  || (branch_id=reverse_hex2int(branchi, branchl))<0 || branch_id>=MAX_FORK
+	if ((hash_index=reverse_hex2int(hashi, hashl))<0||hash_index>=TABLE_ENTRIES
+		|| (branch_id=reverse_hex2int(branchi, branchl))<0||branch_id>=MAX_FORK
 #ifdef USE_SYNONIM
 #ifdef USE_SYNONIM
-	  || (entry_label=reverse_hex2int(syni, synl))<0
+		|| (entry_label=reverse_hex2int(syni, synl))<0
 #else
 #else
-	  || loopl!=32
+		|| loopl!=32
 #endif
 #endif
-	   ) {
-		DBG("DEBUG: t_reply_matching: poor reply lables %d label %d branch %d\n",
-			hash_index, entry_label, branch_id );
+	) {
+		DBG("DEBUG: t_reply_matching: poor reply lables %d label %d "
+			"branch %d\n",hash_index, entry_label, branch_id );
 		goto nomatch2;
 		goto nomatch2;
 	}
 	}
 
 
 
 
 	DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
 	DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
-	   hash_index, entry_label, branch_id );
+		hash_index, entry_label, branch_id );
 
 
 	/* lock the hole entry*/
 	/* lock the hole entry*/
 	lock(&(hash_table->entrys[hash_index].mutex));
 	lock(&(hash_table->entrys[hash_index].mutex));
 
 
-	/*all the cells from the entry are scan to detect an entry_label matching */
-	p_cell     = hash_table->entrys[hash_index].first_cell;
+	/*all the cells from the entry are scan to detect an entry_label matching*/
+	p_cell = hash_table->entrys[hash_index].first_cell;
 	while( p_cell )
 	while( p_cell )
 	{
 	{
 		/* is it the cell with the wanted entry_label? */
 		/* is it the cell with the wanted entry_label? */
 		if ( (get_cseq(p_msg)->method.len ==
 		if ( (get_cseq(p_msg)->method.len ==
-		  get_cseq(p_cell->inbound_request)->method.len)
-		&& (get_cseq(p_msg)->method.s[0] ==
-		  get_cseq(p_cell->inbound_request)->method.s[0])
+		get_cseq(p_cell->inbound_request)->method.len)
+		&& ((get_cseq(p_msg)->method.s[0] ==
+		get_cseq(p_cell->inbound_request)->method.s[0] && (*local_cancel=0)==0)
+		|| (get_cseq(p_cell->inbound_request)->method.s[0]=='I' &&
+		get_cseq(p_msg)->method.s[0]=='C' 
+		&& p_cell->outbound_cancel[branch_id]!=NO_CANCEL
+		&& p_cell->outbound_cancel[branch_id]!=EXTERNAL_CANCEL
+		&& (*local_cancel=1)==1))
 #ifdef USE_SYNONIM
 #ifdef USE_SYNONIM
 		&& (p_cell->label == entry_label )
 		&& (p_cell->label == entry_label )
 #else
 #else
@@ -330,7 +337,7 @@ int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
 		  !memcmp(p_cell->inbound_request->add_to_branch_s,loopi,32))
 		  !memcmp(p_cell->inbound_request->add_to_branch_s,loopi,32))
 #endif
 #endif
 		)
 		)
-			/* has the transaction the wantedbranch? */
+			/* has the transaction the wanted branch? */
 			if ( p_cell->nr_of_outgoings>branch_id &&
 			if ( p_cell->nr_of_outgoings>branch_id &&
 			p_cell->outbound_request[branch_id] )
 			p_cell->outbound_request[branch_id] )
  			{/* WE FOUND THE GOLDEN EGG !!!! */
  			{/* WE FOUND THE GOLDEN EGG !!!! */
@@ -339,7 +346,7 @@ int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
 				T_REF( T );
 				T_REF( T );
 				unlock(&(hash_table->entrys[hash_index].mutex));
 				unlock(&(hash_table->entrys[hash_index].mutex));
 				DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_reply_matching:"
 				DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_reply_matching:"
-				  " reply matched (T=%p,ref=%x)!\n",T,T->ref_bitmap);
+					" reply matched (T=%p,ref=%x)!\n",T,T->ref_bitmap);
 				return 1;
 				return 1;
 			}
 			}
 		/* next cell */
 		/* next cell */
@@ -365,9 +372,10 @@ nomatch2:
   * for current message exists;
   * for current message exists;
   * it returns 1 if found, 0 if not found, -1 on error
   * it returns 1 if found, 0 if not found, -1 on error
   */
   */
-int t_check( struct sip_msg* p_msg , int *param_branch)
+int t_check( struct sip_msg* p_msg , int *param_branch, int *param_cancel)
 {
 {
 	int local_branch;
 	int local_branch;
+	int local_cancel;
 
 
 	/* is T still up-to-date ? */
 	/* is T still up-to-date ? */
 	DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on entrance=%p\n", 
 	DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on entrance=%p\n", 
@@ -378,24 +386,26 @@ int t_check( struct sip_msg* p_msg , int *param_branch)
 		T = T_UNDEFINED;
 		T = T_UNDEFINED;
 		/* transaction lookup */
 		/* transaction lookup */
 		if ( p_msg->first_line.type==SIP_REQUEST ) {
 		if ( p_msg->first_line.type==SIP_REQUEST ) {
-
 			/* force parsing all the needed headers*/
 			/* force parsing all the needed headers*/
 			if (parse_headers(p_msg, HDR_EOH )==-1)
 			if (parse_headers(p_msg, HDR_EOH )==-1)
 				return -1;
 				return -1;
-		t_lookup_request( p_msg , 0 /* unlock before returning */ );
-	 	} else {
-		 	if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO|HDR_CSEQ )==-1 ||
-			!p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
+			t_lookup_request( p_msg , 0 /* unlock before returning */ );
+		} else {
+			if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO|HDR_CSEQ )==-1
+			|| !p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
 				return -1;
 				return -1;
-			t_reply_matching( p_msg , ((param_branch!=0)?(param_branch):(&local_branch)) );
+			t_reply_matching( p_msg ,
+				((param_branch!=0)?(param_branch):(&local_branch)),
+				((param_cancel!=0)?(param_cancel):(&local_cancel)));
+
 		}
 		}
-#		ifdef EXTRA_DEBUG
+#ifdef EXTRA_DEBUG
 		if ( T && T!=T_UNDEFINED && T->damocles) {
 		if ( T && T!=T_UNDEFINED && T->damocles) {
 			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
 			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
 				"and called from t_check\n", T);
 				"and called from t_check\n", T);
 			abort();
 			abort();
 		}
 		}
-#		endif
+#endif
 		DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on finish=%p\n",
 		DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on finish=%p\n",
 			p_msg->id,global_msg_id,T);
 			p_msg->id,global_msg_id,T);
 	} else {
 	} else {

+ 73 - 43
modules/tm/t_reply.c

@@ -21,6 +21,7 @@
 int t_on_reply_received( struct sip_msg  *p_msg )
 int t_on_reply_received( struct sip_msg  *p_msg )
 {
 {
 	unsigned int  branch,len, msg_status, msg_class, save_clone;
 	unsigned int  branch,len, msg_status, msg_class, save_clone;
+	unsigned int local_cancel;
 	struct sip_msg *clone, *backup;
 	struct sip_msg *clone, *backup;
 	int relay;
 	int relay;
 	int start_fr;
 	int start_fr;
@@ -29,11 +30,23 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 
 
 
 
 	/* make sure we know the assosociated tranaction ... */
 	/* make sure we know the assosociated tranaction ... */
-	if (t_check( p_msg  , &branch )==-1) return 1;
+	if (t_check( p_msg  , &branch , &local_cancel)==-1) return 1;
 	/* ... if there is no such, tell the core router to forward statelessly */
 	/* ... if there is no such, tell the core router to forward statelessly */
 	if ( T<=0 ) return 1;
 	if ( T<=0 ) return 1;
 
 
-	DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status);
+	DBG("DEBUG: t_on_reply_received: Original status=%d (%d,%d)\n",
+		T->status,branch,local_cancel);
+
+	/* special cases (local cancel reply and another 100 reply!)*/
+	if (p_msg->REPLY_STATUS==100 && T->status==100)
+		return 0;
+	if (local_cancel==1)
+	{
+		reset_timer( hash_table, &(T_>outbound_cancel[branch]->retr_timer));
+		if ( p_msg->REPLY_STATUS>=200 )
+			reset_timer( hash_table, &(T_>outbound_cancel[branch]->fr_timer));
+		return 0;
+	}
 
 
 	/* it can take quite long -- better do it now than later 
 	/* it can take quite long -- better do it now than later 
 	   inside a reply_lock */
 	   inside a reply_lock */
@@ -86,16 +99,19 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 		if ( T->outbound_ack[branch] )
 		if ( T->outbound_ack[branch] )
 		{   /*retransmit*/
 		{   /*retransmit*/
 			SEND_BUFFER( T->outbound_ack[branch] );
 			SEND_BUFFER( T->outbound_ack[branch] );
-		} else if (msg_class>2 ) {   /*on a non-200 reply to INVITE*/
-           		DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
-           		if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
-           		{
-               		LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
-					/* restart FR */
-					start_fr=1;
-           		}
-       		}
-   	}
+		}else if (msg_class>2 ) {   
+			/*on a non-200 reply to INVITE*/
+			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"
+				" send ACK\n");
+			if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
+			{
+				LOG( L_ERR , "ERROR: t_on_reply_received:"
+					" unable to send ACK\n" );
+				/* restart FR */
+				start_fr=1;
+			}
+		}
+	}
 cleanup:
 cleanup:
 	UNLOCK_REPLIES( T );
 	UNLOCK_REPLIES( T );
 	if (backup) sip_msg_free(backup);
 	if (backup) sip_msg_free(backup);
@@ -119,12 +135,10 @@ error:
 
 
 
 
 /* Retransmits the last sent inbound reply.
 /* Retransmits the last sent inbound reply.
-
-  * input: p_msg==request for which I want to retransmit an associated
-    reply
-  * Returns  -1 -error
-  *                1 - OK
-  */
+ * input: p_msg==request for which I want to retransmit an associated reply
+ * Returns  -1 - error
+ *           1 - OK
+ */
 int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 {
 {
 
 
@@ -152,6 +166,10 @@ int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 	return 1;
 	return 1;
 }
 }
 
 
+
+
+
+
 /* Force a new response into inbound response buffer.
 /* Force a new response into inbound response buffer.
   * returns 1 if everything was OK or -1 for erro
   * returns 1 if everything was OK or -1 for erro
   */
   */
@@ -161,8 +179,6 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
 	char * buf, *shbuf;
 	char * buf, *shbuf;
 	struct retrans_buff *rb;
 	struct retrans_buff *rb;
 
 
-	DBG("DEBUG: t_send_reply: entered\n");
-
 	buf = build_res_buf_from_sip_req(code,text,0,0,T->inbound_request,&len);
 	buf = build_res_buf_from_sip_req(code,text,0,0,T->inbound_request,&len);
 	DBG("DEBUG: t_send_reply: buffer computed\n");
 	DBG("DEBUG: t_send_reply: buffer computed\n");
 	if (!buf)
 	if (!buf)
@@ -191,10 +207,9 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
 		rb->fr_timer.payload = rb;
 		rb->fr_timer.payload = rb;
 		rb->to.sin_family = AF_INET;
 		rb->to.sin_family = AF_INET;
 		rb->my_T = T;
 		rb->my_T = T;
-		rb->reply = code;
+		rb->status = code;
 	}
 	}
 
 
-
 	/* if this is a first reply (?100), longer replies will probably follow;
 	/* if this is a first reply (?100), longer replies will probably follow;
 	   try avoiding shm_resize by higher buffer size */
 	   try avoiding shm_resize by higher buffer size */
 	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
 	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
@@ -272,7 +287,7 @@ static int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch
 		rb->fr_timer.payload =  rb;
 		rb->fr_timer.payload =  rb;
 		rb->to.sin_family = AF_INET;
 		rb->to.sin_family = AF_INET;
 		rb->my_T = trans;
 		rb->my_T = trans;
-		rb->reply = trans->inbound_response[branch]->REPLY_STATUS;
+		rb->status = trans->inbound_response[branch]->REPLY_STATUS;
 
 
 	} else {
 	} else {
 #ifndef SRL
 #ifndef SRL
@@ -360,7 +375,7 @@ static int push_reply( struct cell* trans , unsigned int branch ,
 		rb->fr_timer.payload =  rb;
 		rb->fr_timer.payload =  rb;
 		rb->to.sin_family = AF_INET;
 		rb->to.sin_family = AF_INET;
 		rb->my_T = trans;
 		rb->my_T = trans;
-		rb->reply = trans->inbound_response[branch]->REPLY_STATUS;
+		rb->status = trans->inbound_response[branch]->REPLY_STATUS;
 	};
 	};
 
 
 	/* if this is a first reply (?100), longer replies will probably follow;
 	/* if this is a first reply (?100), longer replies will probably follow;
@@ -401,7 +416,8 @@ error:
   */
   */
 int t_on_reply( struct sip_msg  *p_msg )
 int t_on_reply( struct sip_msg  *p_msg )
 {
 {
-	unsigned int  branch,len, msg_status, msg_class, save_clone;
+	unsigned int branch,len, msg_status, msg_class, save_clone;
+	unsigned int local_cancel;
 	struct sip_msg *clone, *backup;
 	struct sip_msg *clone, *backup;
 	int relay;
 	int relay;
 	int start_fr;
 	int start_fr;
@@ -412,11 +428,23 @@ int t_on_reply( struct sip_msg  *p_msg )
 
 
 
 
 	/* make sure we know the assosociated tranaction ... */
 	/* make sure we know the assosociated tranaction ... */
-	if (t_check( p_msg  , &branch )==-1) return 1;
+	if (t_check( p_msg  , &branch , &local_cancel)==-1) return 1;
 	/* ... if there is no such, tell the core router to forward statelessly */
 	/* ... if there is no such, tell the core router to forward statelessly */
 	if ( T<=0 ) return 1;
 	if ( T<=0 ) return 1;
 
 
-	DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status);
+	DBG("DEBUG: t_on_reply_received: Original status=%d (%d,%d)\n",
+		T->status,branch,local_cancel);
+
+	/* special cases (local cancel reply and another 100 reply!)*/
+	if (p_msg->REPLY_STATUS==100 && T->status==100)
+		return 0;
+	if (local_cancel==1)
+	{
+		reset_timer( hash_table, &(T->outbound_cancel[branch]->retr_timer));
+		if ( p_msg->REPLY_STATUS>=200 )
+			reset_timer( hash_table, &(T->outbound_cancel[branch]->fr_timer));
+		return 0;
+	}
 
 
 	/* it can take quite long -- better do it now than later 
 	/* it can take quite long -- better do it now than later 
 	   inside a reply_lock */
 	   inside a reply_lock */
@@ -427,12 +455,11 @@ int t_on_reply( struct sip_msg  *p_msg )
 	msg_class=REPLY_CLASS(p_msg);
 	msg_class=REPLY_CLASS(p_msg);
 	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;
 	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;
 
 
-    /*  generate the retrans buffer, make a simplified
-	    assumption everything but 100 will be fwd-ed;
-		sometimes it will result in useless CPU cycles
-		but mostly the assumption holds and allows the
-		work to be done out of criticial lock region
-	 */
+	/*  generate the retrans buffer, make a simplified
+	assumption everything but 100 will be fwd-ed;
+	sometimes it will result in useless CPU cycles
+	but mostly the assumption holds and allows the
+	work to be done out of criticial lock region */
 	if (msg_status==100) buf=0;
 	if (msg_status==100) buf=0;
 	else {
 	else {
 		buf = build_res_buf_from_sip_res ( p_msg, &buf_len);
 		buf = build_res_buf_from_sip_res ( p_msg, &buf_len);
@@ -486,16 +513,19 @@ int t_on_reply( struct sip_msg  *p_msg )
 		if ( T->outbound_ack[branch] )
 		if ( T->outbound_ack[branch] )
 		{   /*retransmit*/
 		{   /*retransmit*/
 			SEND_BUFFER( T->outbound_ack[branch] );
 			SEND_BUFFER( T->outbound_ack[branch] );
-		} else if (msg_class>2 ) {   /*on a non-200 reply to INVITE*/
-           		DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
-           		if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
-           		{
-               		LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
-					/* restart FR */
-					start_fr=1;
-           		}
-       		}
-   	}
+		} else if (msg_class>2 ) {   
+			/*on a non-200 reply to INVITE*/
+			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"
+				" send ACK\n");
+			if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
+			{
+				LOG( L_ERR , "ERROR: t_on_reply_received:"
+					" unable to send ACK\n" );
+				/* restart FR */
+				start_fr=1;
+			}
+		}
+	}
 cleanup:
 cleanup:
 	UNLOCK_REPLIES( T );
 	UNLOCK_REPLIES( T );
 	if (backup) sip_msg_free(backup);
 	if (backup) sip_msg_free(backup);

+ 1 - 1
modules/tm/timer.c

@@ -174,7 +174,7 @@ void timer_routine(unsigned int ticks , void * attr)
 			/* reset the timer list linkage */
 			/* reset the timer list linkage */
 			tmp_tl = tl->next_tl;
 			tmp_tl = tl->next_tl;
 			tl->next_tl = tl->prev_tl =0 ; 
 			tl->next_tl = tl->prev_tl =0 ; 
-			DBG("DEBUG: timer routine: timer[%d] , tl=%p next=%p\n",id,tl,tmp_tl);
+			DBG("DEBUG: timer routine:timer[%d],tl=%p next=%p\n",id,tl,tmp_tl);
 			timers[id].timeout_handler( tl->payload );
 			timers[id].timeout_handler( tl->payload );
 			tl = tmp_tl;
 			tl = tmp_tl;
 		}
 		}

+ 11 - 11
modules/tm/tm.c

@@ -267,13 +267,13 @@ static int fixup_t_send_reply(void** param, int param_no)
 
 
 static int w_t_check(struct sip_msg* msg, char* str, char* str2)
 static int w_t_check(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	return t_check( msg , 0 ) ? 1 : -1;
+	return t_check( msg , 0 , 0 ) ? 1 : -1;
 }
 }
 
 
 #ifdef _OBSOLETED_TM
 #ifdef _OBSOLETED_TM
 static int w_t_forward(struct sip_msg* msg, char* str, char* str2)
 static int w_t_forward(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg , 0 )==-1) return -1;
+	if (t_check( msg , 0 , 0 )==-1) return -1;
 	if (!T) {
 	if (!T) {
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		return -1;
 		return -1;
@@ -282,7 +282,7 @@ static int w_t_forward(struct sip_msg* msg, char* str, char* str2)
 }
 }
 static int w_t_forward_def(struct sip_msg* msg, char* str, char* str2)
 static int w_t_forward_def(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg , 0 )==-1) return -1;
+	if (t_check( msg , 0 , 0 )==-1) return -1;
 	if (!T) {
 	if (!T) {
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		return -1;
 		return -1;
@@ -291,7 +291,7 @@ static int w_t_forward_def(struct sip_msg* msg, char* str, char* str2)
 }
 }
 
 
 int w_t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  ) {
 int w_t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  ) {
-	if (t_check( p_msg , 0 )==-1) return -1;
+	if (t_check( p_msg , 0 , 0)==-1) return -1;
 	if (!T) {
 	if (!T) {
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
 		return -1;
 		return -1;
@@ -313,7 +313,7 @@ static int w_t_on_request_received_uri(struct sip_msg* msg, char* str, char* str
 
 
 static int w_t_forward_ack(struct sip_msg* msg, char* str, char* str2)
 static int w_t_forward_ack(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg , 0 )==-1) return -1;
+	if (t_check( msg , 0 , 0 )==-1) return -1;
 	if (!T) {
 	if (!T) {
 		DBG("DEBUG: t_forward_ack: no transaction found for request forwarding\n");
 		DBG("DEBUG: t_forward_ack: no transaction found for request forwarding\n");
 		return -1;
 		return -1;
@@ -322,7 +322,7 @@ static int w_t_forward_ack(struct sip_msg* msg, char* str, char* str2)
 }
 }
 static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* str2)
 static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg , 0 )==-1) return -1;
+	if (t_check( msg , 0 , 0)==-1) return -1;
 	if (!T) {
 	if (!T) {
 		DBG("DEBUG: t_forward_nonack: no transaction found for request forwarding\n");
 		DBG("DEBUG: t_forward_nonack: no transaction found for request forwarding\n");
 		return -1;
 		return -1;
@@ -334,7 +334,7 @@ static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* str2)
 
 
 static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg , 0 )==-1) return -1;
+	if (t_check( msg , 0 , 0)==-1) return -1;
 	if (!T) {
 	if (!T) {
 		LOG(L_ERR, "ERROR: t_send_reply: cannot send a t_reply to a message "
 		LOG(L_ERR, "ERROR: t_send_reply: cannot send a t_reply to a message "
 			"for which no T-state has been established\n");
 			"for which no T-state has been established\n");
@@ -345,7 +345,7 @@ static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 
 
 static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 {
 {
-	if (t_check( msg  , 0 )==-1) return 1;
+	if (t_check( msg  , 0 , 0 )==-1) return 1;
 	if ( T && T!=T_UNDEFINED ) 
 	if ( T && T!=T_UNDEFINED ) 
 		return t_put_on_wait( T );
 		return t_put_on_wait( T );
 	return 1;
 	return 1;
@@ -361,13 +361,13 @@ static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 
 
 static w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
 static w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
 {
 {
-	if (t_check( p_msg  , 0 )==-1) return 1;
-	if (T) return t_retransmit_reply( /* p_msg */ );
+	if (t_check( p_msg  , 0 , 0 )==-1) return 1;
+	if (T) return t_retransmit_reply( p_msg );
 	else return -1;
 	else return -1;
 }
 }
 
 
 static int w_t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar ) {
 static int w_t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar ) {
-	if (t_check( p_msg , 0 )==-1) return -1;
+	if (t_check( p_msg , 0 , 0 )==-1) return -1;
 	if (T) {
 	if (T) {
 		LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
 		LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
 		return -1;
 		return -1;

+ 1 - 1
test/th-uri.cfg

@@ -29,7 +29,7 @@ loadmodule "modules/tm/tm.so"
 #loadmodule "modules/rr/rr.so"
 #loadmodule "modules/rr/rr.so"
 loadmodule "modules/maxfwd/maxfwd.so"
 loadmodule "modules/maxfwd/maxfwd.so"
 loadmodule "modules/sl/sl.so"
 loadmodule "modules/sl/sl.so"
-loadmodule "modules/cpl/cpl.so"
+#loadmodule "modules/cpl/cpl.so"
 
 
 
 
 route{
 route{