Pārlūkot izejas kodu

new structures + forking

Bogdan-Andrei Iancu 23 gadi atpakaļ
vecāks
revīzija
46931a4dfc
13 mainītis faili ar 726 papildinājumiem un 863 dzēšanām
  1. 3 2
      Makefile.defs
  2. 1 1
      modules/tm/config.h
  3. 147 134
      modules/tm/h_table.c
  4. 69 41
      modules/tm/h_table.h
  5. 115 239
      modules/tm/t_funcs.c
  6. 38 64
      modules/tm/t_funcs.h
  7. 114 128
      modules/tm/t_fwd.c
  8. 23 22
      modules/tm/t_lookup.c
  9. 112 134
      modules/tm/t_reply.c
  10. 0 1
      modules/tm/timer.c
  11. 63 56
      modules/tm/tm.c
  12. 1 6
      msg_translator.c
  13. 40 35
      test/th-uri.cfg

+ 3 - 2
Makefile.defs

@@ -84,11 +84,12 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
 	 -DF_MALLOC  -DUSE_SYNONIM\
 	 -DF_MALLOC  -DUSE_SYNONIM\
 	 -DSHM_MEM  -DSHM_MMAP \
 	 -DSHM_MEM  -DSHM_MMAP \
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
+	 -DWAIT -DNEW_HNAME -DBOGDAN_TRIFLE \
 	 -DWAIT -DNEW_HNAME \
 	 -DWAIT -DNEW_HNAME \
 	 -DSILENT_FR \
 	 -DSILENT_FR \
-	 -DNO_DEBUG \
-	 #-DVERY_NOISY_REPLIES\
+	 #-DNO_DEBUG \
 	 #-DNOISY_REPLIES \
 	 #-DNOISY_REPLIES \
+	 #-DBOGDAN_TRIFLE \
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
 	 #-DNOSMP \
 	 #-DNOSMP \
 	 #-DEXTRA_DEBUG 
 	 #-DEXTRA_DEBUG 

+ 1 - 1
modules/tm/config.h

@@ -11,7 +11,7 @@
 #define TABLE_ENTRIES  		(1 << (T_TABLE_POWER))
 #define TABLE_ENTRIES  		(1 << (T_TABLE_POWER))
 
 
 /* maximum number of forks per transaction */
 /* maximum number of forks per transaction */
-#define MAX_FORK		2
+#define MAX_FORK		4
 
 
 /* maximumum length of localy generated acknowledgement */
 /* maximumum length of localy generated acknowledgement */
 #define MAX_ACK_LEN 		1024
 #define MAX_ACK_LEN 		1024

+ 147 - 134
modules/tm/h_table.c

@@ -8,127 +8,57 @@
 #include "sh_malloc.h"
 #include "sh_malloc.h"
 #include "../../md5utils.h"
 #include "../../md5utils.h"
 
 
-/* containes of a cell and the cell's body itself */
+
+
+
 void free_cell( struct cell* dead_cell )
 void free_cell( struct cell* dead_cell )
 {
 {
-	int i;
-	struct retrans_buff* rb;
 	char *b;
 	char *b;
+	int i;
 
 
-	/* UA Server */
 	release_cell_lock( dead_cell );
 	release_cell_lock( dead_cell );
 	shm_lock();
 	shm_lock();
-	if ( dead_cell->inbound_request )
-		sip_msg_free_unsafe( dead_cell->inbound_request );
-	if ((b=dead_cell->outbound_response.retr_buffer))
-		shm_free_unsafe( b );
+
+	/* UA Server */
+	if ( dead_cell->uas.request )
+		sip_msg_free_unsafe( dead_cell->uas.request );
+	if ( dead_cell->uas.response.buffer )
+		shm_free_unsafe( dead_cell->uas.response.buffer );
 
 
 	/* UA Clients */
 	/* UA Clients */
 	for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
 	for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
 	{
 	{
-		/* outbound requests*/
-		if ( (rb=dead_cell->outbound_request[i]) )
+		/* retransmission buffer */
+		if ( (b=dead_cell->uac[i].request.buffer) )
+		{
+			shm_free_unsafe( b );
+			b = 0;
+		}
+		if ( (b=dead_cell->uac[i].request.ack) )
+		{
+			shm_free_unsafe( b );
+			b = 0;
+		}
+		if ( (b=dead_cell->uac[i].request.cancel) )
 		{
 		{
-			if (rb->retr_buffer) shm_free_unsafe( rb->retr_buffer );
-			dead_cell->outbound_request[i] = NULL;
-			shm_free_unsafe( rb );
+			shm_free_unsafe( b );
+			b = 0;
 		}
 		}
-		/* outbound ACKs, if any */
-		if ( (rb=dead_cell->outbound_ack[i]) )
-			shm_free_unsafe( rb );
-		/* local cancel , if any */
-		if ( (rb=dead_cell->outbound_cancel[i]) )
-			shm_free_unsafe( rb );
-		/* inbound response */
-		if ( dead_cell -> inbound_response[i] )
-			sip_msg_free_unsafe( dead_cell->inbound_response[i] );
 	}
 	}
-	/* mutex */
-	/* 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();
-}
-
-
-
 
 
-/* Release all the data contained by the hash table. All the aux. structures
-  *  as sems, lists, etc, are also released
-  */
-void free_hash_table( struct s_table *hash_table )
-{
-   struct cell* p_cell;
-   struct cell* tmp_cell;
-   int   i;
-
-   if (hash_table)
-   {
-      /* remove the data contained by each entry */
-      for( i = 0 ; i<TABLE_ENTRIES; i++)
-      {
-         release_entry_lock( (hash_table->entrys)+i );
-         /* delete all synonyms at hash-collision-slot i */
-         for( p_cell = hash_table->entrys[i].first_cell; p_cell; p_cell = tmp_cell )
-         {
-            tmp_cell = p_cell->next_cell;
-            free_cell( p_cell );
-         }
-      }
-
-      /* the mutexs for sync the lists are released*/
-      for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
-         release_timerlist_lock( &(hash_table->timers[i]) );
-
-      sh_free( hash_table );
-   }
+	shm_unlock();
 }
 }
 
 
 
 
 
 
 
 
-/*
-  */
-struct s_table* init_hash_table()
-{
-   struct s_table*  hash_table;
-   int       i;
-
-   /*allocs the table*/
-   hash_table = (struct s_table*)sh_malloc( sizeof( struct s_table ) );
-   if ( !hash_table )
-      goto error;
-
-   memset( hash_table, 0, sizeof (struct s_table ) );
-
-   /* try first allocating all the structures needed for syncing */
-   if (lock_initialize()==-1)
-     goto error;
-
-   /* inits the entrys */
-   for(  i=0 ; i<TABLE_ENTRIES; i++ )
-   {
-      init_entry_lock( hash_table , (hash_table->entrys)+i );
-      hash_table->entrys[i].next_label = rand();
-   }
-
-   /* inits the timers*/
-   for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
-      init_timer_list( hash_table, i );
-
-   return  hash_table;
-
-error:
-   free_hash_table( hash_table );
-   lock_cleanup();
-   return 0;
-}
-
-
-
 struct cell*  build_cell( struct sip_msg* p_msg )
 struct cell*  build_cell( struct sip_msg* p_msg )
 {
 {
 	struct cell* new_cell;
 	struct cell* new_cell;
+	unsigned int i;
 #ifndef USE_SYNONIM
 #ifndef USE_SYNONIM
 	str          src[5];
 	str          src[5];
 #endif
 #endif
@@ -145,25 +75,37 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 	/* filling with 0 */
 	/* filling with 0 */
 	memset( new_cell, 0, sizeof( struct cell ) );
 	memset( new_cell, 0, sizeof( struct cell ) );
 
 
-	new_cell->outbound_response.retr_timer.tg=TG_RT;
-	new_cell->outbound_response.fr_timer.tg=TG_FR;
-	new_cell->wait_tl.tg=TG_WT;
-	new_cell->dele_tl.tg=TG_DEL;
+	/* UAS */
+	new_cell->uas.response.retr_timer.tg=TG_RT;
+	new_cell->uas.response.fr_timer.tg=TG_FR;
+	new_cell->uas.response.fr_timer.payload =
+		new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response);
+	new_cell->uas.request = sip_msg_cloner(p_msg);
+	if (!new_cell->uas.request)
+		goto error;
+	new_cell->uas.tag = &( get_to(new_cell->uas.request)->tag_value );
+	new_cell->uas.response.my_T = new_cell;
 
 
-	/* hash index of the entry */
+	/* UAC */
+	for(i=0;i<MAX_FORK;i++)
+	{
+		new_cell->uac[i].request.my_T = new_cell;
+		new_cell->uac[i].request.branch = i;
+		new_cell->uac[i].request.fr_timer.tg = TG_FR;
+		new_cell->uac[i].request.retr_timer.tg = TG_RT;
+		new_cell->uac[i].request.retr_timer.payload = 
+			new_cell->uac[i].request.fr_timer.payload =
+			&(new_cell->uac[i].request);
+	}
+
+	/* global data for transaction */
 	new_cell->hash_index = p_msg->hash_index;
 	new_cell->hash_index = p_msg->hash_index;
-	/* mutex */
-	/* ref counter is 0 */
-	/* all pointers from timers list tl are NULL */
 	new_cell->wait_tl.payload = new_cell;
 	new_cell->wait_tl.payload = new_cell;
 	new_cell->dele_tl.payload = new_cell;
 	new_cell->dele_tl.payload = new_cell;
-
-	new_cell->inbound_request =  sip_msg_cloner(p_msg) ;
-	if (!new_cell->inbound_request)
-		goto error;
 	new_cell->relaied_reply_branch   = -1;
 	new_cell->relaied_reply_branch   = -1;
 	new_cell->T_canceled = T_UNDEFINED;
 	new_cell->T_canceled = T_UNDEFINED;
-	new_cell->tag=&(get_to(new_cell->inbound_request)->tag_value);
+	new_cell->wait_tl.tg=TG_WT;
+	new_cell->dele_tl.tg=TG_DEL;
 #ifndef USE_SYNONIM
 #ifndef USE_SYNONIM
 	src[0]= p_msg->from->body;
 	src[0]= p_msg->from->body;
 	src[1]= p_msg->to->body;
 	src[1]= p_msg->to->body;
@@ -174,7 +116,6 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 #endif
 #endif
 
 
 	init_cell_lock(  new_cell );
 	init_cell_lock(  new_cell );
-
 	return new_cell;
 	return new_cell;
 
 
 error:
 error:
@@ -185,10 +126,84 @@ error:
 
 
 
 
 
 
+/* Release all the data contained by the hash table. All the aux. structures
+ *  as sems, lists, etc, are also released */
+void free_hash_table( struct s_table *hash_table )
+{
+	struct cell* p_cell;
+	struct cell* tmp_cell;
+	int    i;
+
+	if (hash_table)
+	{
+		/* remove the data contained by each entry */
+		for( i = 0 ; i<TABLE_ENTRIES; i++)
+		{
+			release_entry_lock( (hash_table->entrys)+i );
+			/* delete all synonyms at hash-collision-slot i */
+			p_cell=hash_table->entrys[i].first_cell;
+			for( ; p_cell; p_cell = tmp_cell )
+			{
+				tmp_cell = p_cell->next_cell;
+				free_cell( p_cell );
+			}
+		}
+
+		/* the mutexs for sync the lists are released*/
+		for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
+			release_timerlist_lock( &(hash_table->timers[i]) );
+
+		sh_free( hash_table );
+	}
+}
+
+
+
+
+/*
+ */
+struct s_table* init_hash_table()
+{
+	struct s_table*  hash_table;
+	int              i;
+
+	/*allocs the table*/
+	hash_table = (struct s_table*)sh_malloc( sizeof( struct s_table ) );
+	if ( !hash_table )
+		goto error;
+
+	memset( hash_table, 0, sizeof (struct s_table ) );
+
+	/* try first allocating all the structures needed for syncing */
+	if (lock_initialize()==-1)
+		goto error;
+
+	/* inits the entrys */
+	for(  i=0 ; i<TABLE_ENTRIES; i++ )
+	{
+		init_entry_lock( hash_table , (hash_table->entrys)+i );
+		hash_table->entrys[i].next_label = rand();
+	}
+
+	/* inits the timers*/
+	for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
+		init_timer_list( hash_table, i );
+
+	return  hash_table;
+
+error:
+	free_hash_table( hash_table );
+	lock_cleanup();
+	return 0;
+}
+
+
+
+
 /*  Takes an already created cell and links it into hash table on the
 /*  Takes an already created cell and links it into hash table on the
-  *  appropiate entry.
-  */
-void    insert_into_hash_table_unsafe( struct s_table *hash_table,  struct cell * p_cell )
+ *  appropiate entry. */
+void insert_into_hash_table_unsafe( struct s_table *hash_table,
+											struct cell * p_cell )
 {
 {
 	struct entry* p_entry;
 	struct entry* p_entry;
 
 
@@ -205,7 +220,10 @@ void    insert_into_hash_table_unsafe( struct s_table *hash_table,  struct cell
 	p_entry->last_cell = p_cell;
 	p_entry->last_cell = p_cell;
 }
 }
 
 
-void insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
+
+
+
+void insert_into_hash_table(struct s_table *hash_table,  struct cell * p_cell)
 {
 {
 	lock( &(hash_table->entrys[ p_cell->hash_index ].mutex) );
 	lock( &(hash_table->entrys[ p_cell->hash_index ].mutex) );
 	insert_into_hash_table_unsafe( hash_table,  p_cell );
 	insert_into_hash_table_unsafe( hash_table,  p_cell );
@@ -215,30 +233,25 @@ void insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
 
 
 
 
 
 
-/*  Un-link a  cell from hash_table, but the cell itself is not released
-  */
-void remove_from_hash_table( struct s_table *hash_table,  struct cell * p_cell )
+/*  Un-link a  cell from hash_table, but the cell itself is not released */
+void remove_from_hash_table(struct s_table *hash_table,  struct cell * p_cell)
 {
 {
-   struct entry*  p_entry  = &(hash_table->entrys[p_cell->hash_index]);
+	struct entry*  p_entry  = &(hash_table->entrys[p_cell->hash_index]);
 
 
-   /* unlink the cell from entry list */
-   lock( &(p_entry->mutex) );
+	/* unlink the cell from entry list */
+	lock( &(p_entry->mutex) );
 
 
-   if ( p_cell->prev_cell )
-      p_cell->prev_cell->next_cell = p_cell->next_cell;
-   else
-      p_entry->first_cell = p_cell->next_cell;
+	if ( p_cell->prev_cell )
+		p_cell->prev_cell->next_cell = p_cell->next_cell;
+	else
+		p_entry->first_cell = p_cell->next_cell;
 
 
-   if ( p_cell->next_cell )
-      p_cell->next_cell->prev_cell = p_cell->prev_cell;
-   else
-      p_entry->last_cell = p_cell->prev_cell;
+	if ( p_cell->next_cell )
+		p_cell->next_cell->prev_cell = p_cell->prev_cell;
+	else
+		p_entry->last_cell = p_cell->prev_cell;
 
 
-   unlock( &(p_entry->mutex) );
+	unlock( &(p_entry->mutex) );
 }
 }
 
 
 
 
-
-
-
-

+ 69 - 41
modules/tm/h_table.h

@@ -31,17 +31,26 @@ struct timer;
 #define T_NULL       ( (struct cell*) 0 )
 #define T_NULL       ( (struct cell*) 0 )
 
 
 
 
-#define NO_CANCEL       ( (struct retrans_buff*) 0 )
-#define EXTERNAL_CANCEL ( (struct retrans_buff*) -1)
+#define NO_CANCEL       ( (char*) 0 )
+#define EXTERNAL_CANCEL ( (char*) -1)
 
 
-#define STATUS_LOCAL_CANCEL -1
-#define STATUS_REQUEST       0
+#define TYPE_LOCAL_CANCEL -1
+#define TYPE_REQUEST       0
 
 
 
 
-typedef struct retrans_buff
+
+typedef struct retr_buf
 {
 {
-	char *retr_buffer;
-	int   bufflen;
+	int activ_type;
+	/* set to status code if the buffer is a reply,
+	0 if request or -1 if local CANCEL */
+
+	char *buffer;
+	int   buffer_len;
+	char *ack;
+	int   ack_len;
+	char *cancel;
+	int   cancel_len;
 
 
 	struct sockaddr_in to;
 	struct sockaddr_in to;
 	size_t tolen;
 	size_t tolen;
@@ -49,18 +58,39 @@ typedef struct retrans_buff
 	/* a message can be linked just to retransmission and FR list */
 	/* a message can be linked just to retransmission and FR list */
 	struct timer_link retr_timer;
 	struct timer_link retr_timer;
 	struct timer_link fr_timer;
 	struct timer_link fr_timer;
+	enum lists retr_list;
 
 
 	/*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;
 	unsigned int branch;
 
 
-	enum lists retr_list;
+}retr_buf_type;
+
+
+
+/* User Agent Server content */
+
+typedef struct ua_server
+{
+	struct sip_msg   *request;
+	struct retr_buf  response;
+	unsigned int     status;
+	str              *tag;
+	unsigned int     isACKed;
+}ua_server_type;
 
 
-	/* set to status code if the buffer is a reply, 
-	0 if request or -1 if local CANCEL */
-	int status;
 
 
-}retrans_buff_type;
+
+/* User Agent Client content */
+
+typedef struct ua_client
+{
+	struct retr_buf  request;
+	unsigned int     status;
+	str              tag;
+	unsigned int     rpl_received;
+}ua_client_type;
+
 
 
 
 
 /* transaction context */
 /* transaction context */
@@ -82,23 +112,17 @@ typedef struct cell
 	struct timer_link wait_tl;
 	struct timer_link wait_tl;
 	struct timer_link dele_tl;
 	struct timer_link dele_tl;
 
 
-	/*the transaction that is canceled (usefull only for CANCEL req)*/
-	struct cell *T_canceled;
-
 	/* useful data */
 	/* useful data */
+	/* number of forks */
+	int nr_of_outgoings;
+	/* nr of replied branch */
+	int relaied_reply_branch;
+	/* transaction that is canceled (usefull only for CANCEL req) */
+	struct cell *T_canceled;
 	/* UA Server */
 	/* UA Server */
-	struct sip_msg       *inbound_request;
-	struct retrans_buff   outbound_response;
-	unsigned int          status;
-	str                  *tag;
-	unsigned int          inbound_request_isACKed;
-	int                   relaied_reply_branch;
-	int                   nr_of_outgoings;
+	struct ua_server  uas;
 	/* UA Clients */
 	/* UA Clients */
-	struct retrans_buff   *outbound_request[ MAX_FORK ];
-	struct sip_msg        *inbound_response[ MAX_FORK ];
-	struct retrans_buff   *outbound_ack[ MAX_FORK ];
-	struct retrans_buff   *outbound_cancel[ MAX_FORK ];
+	struct ua_client  uac[ MAX_FORK ];
 
 
 	/* protection against concurrent reply processing */
 	/* protection against concurrent reply processing */
 	ser_lock_t   reply_mutex;
 	ser_lock_t   reply_mutex;
@@ -131,12 +155,12 @@ typedef struct cell
 /* double-linked list of cells with hash synonyms */
 /* double-linked list of cells with hash synonyms */
 typedef struct entry
 typedef struct entry
 {
 {
-   struct cell*       first_cell;
-   struct cell*       last_cell;
-   /* currently highest sequence number in a synonym list */
-   unsigned int    next_label;
-   /* sync mutex */
-   ser_lock_t                 mutex;
+	struct cell*    first_cell;
+	struct cell*    last_cell;
+	/* currently highest sequence number in a synonym list */
+	unsigned int    next_label;
+	/* sync mutex */
+	ser_lock_t      mutex;
 }entry_type;
 }entry_type;
 
 
 
 
@@ -144,19 +168,23 @@ typedef struct entry
 /* transaction table */
 /* transaction table */
 struct s_table
 struct s_table
 {
 {
-   /* table of hash entries; each of them is a list of synonyms  */
-   struct entry   entrys[ TABLE_ENTRIES ];
-   /* table of timer lists */
-   struct timer   timers[ NR_OF_TIMER_LISTS ];
+	/* table of hash entries; each of them is a list of synonyms  */
+	struct entry   entrys[ TABLE_ENTRIES ];
+	/* table of timer lists */
+	struct timer   timers[ NR_OF_TIMER_LISTS ];
 };
 };
 
 
 
 
+
 struct s_table* init_hash_table();
 struct s_table* init_hash_table();
-void free_hash_table( struct s_table* hash_table );
-void free_cell( struct cell* dead_cell );
+void   free_hash_table( struct s_table* hash_table );
+void   free_cell( struct cell* dead_cell );
 struct cell*  build_cell( struct sip_msg* p_msg );
 struct cell*  build_cell( struct sip_msg* p_msg );
-void remove_from_hash_table( struct s_table *hash_table, struct cell * p_cell );
-void insert_into_hash_table( struct s_table *hash_table, struct cell * p_cell );
-void insert_into_hash_table_unsafe( struct s_table *hash_table, struct cell * p_cell );
+void   remove_from_hash_table(struct s_table *hash_table,struct cell * p_cell);
+void   insert_into_hash_table(struct s_table *hash_table,struct cell * p_cell);
+void   insert_into_hash_table_unsafe( struct s_table *hash_table,
+		struct cell * p_cell );
 
 
 #endif
 #endif
+
+

+ 115 - 239
modules/tm/t_funcs.c

@@ -23,9 +23,12 @@
 
 
 
 
 
 
-struct cell         *T;
+struct cell      *T;
 unsigned int     global_msg_id;
 unsigned int     global_msg_id;
 struct s_table*  hash_table;
 struct s_table*  hash_table;
+unsigned int     nr_forks;
+unsigned int     t_forks[MAX_FORK+1][2];
+
 
 
 void timer_routine(unsigned int, void*);
 void timer_routine(unsigned int, void*);
 
 
@@ -51,6 +54,9 @@ int tm_startup()
 	/* register the timer function */
 	/* register the timer function */
 	register_timer( timer_routine , hash_table , 1 );
 	register_timer( timer_routine , hash_table , 1 );
 
 
+	/* fork table */
+	nr_forks = 0;
+
 	/*first msg id*/
 	/*first msg id*/
 	global_msg_id = 0;
 	global_msg_id = 0;
 	T = T_UNDEFINED;
 	T = T_UNDEFINED;
@@ -157,28 +163,28 @@ 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 retr_buf *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->uas.status>=300&&Trans->uas.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 );
 		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
 		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
-	} else if ( Trans->inbound_request->REQ_METHOD==METHOD_CANCEL ) {
+	} else if ( Trans->uas.request->REQ_METHOD==METHOD_CANCEL ) {
 		if ( Trans->T_canceled==T_UNDEFINED )
 		if ( Trans->T_canceled==T_UNDEFINED )
 			Trans->T_canceled = t_lookupOriginalT( hash_table ,
 			Trans->T_canceled = t_lookupOriginalT( hash_table ,
-				Trans->inbound_request );
+				Trans->uas.request );
 		if ( Trans->T_canceled==T_NULL )
 		if ( Trans->T_canceled==T_NULL )
 			return 1;
 			return 1;
 		/* put CANCEL transaction on wait only if canceled transaction already
 		/* put CANCEL transaction on wait only if canceled transaction already
 		    is in final status and there is nothing to cancel; */
 		    is in final status and there is nothing to cancel; */
-		if ( Trans->T_canceled->status>=200)
+		if ( Trans->T_canceled->uas.status>=200)
 			t_put_on_wait( Trans );
 			t_put_on_wait( Trans );
-	} else if (Trans->status>=200)
+	} else if (Trans->uas.status>=200)
 		t_put_on_wait( Trans );
 		t_put_on_wait( Trans );
    return 1;
    return 1;
 }
 }
@@ -192,13 +198,13 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
  * Returns 	- branch number (0,1,...) which should be relayed
  * Returns 	- branch number (0,1,...) which should be relayed
  *         -1 if nothing to be relayed
  *         -1 if nothing to be relayed
  */
  */
-int t_should_relay_response( struct cell *Trans , int new_code, 
-	int branch , int *should_store )
+int t_should_relay_response( struct cell *Trans , int new_code,
+									int branch , int *should_store )
 {
 {
 	int T_code;
 	int T_code;
 	int b, lowest_b, lowest_s;
 	int b, lowest_b, lowest_s;
 
 
-	T_code = Trans->status;
+	T_code = Trans->uac[branch].status;
 
 
 	/* note: this code never lets replies to CANCEL go through;
 	/* note: this code never lets replies to CANCEL go through;
 	   we generate always a local 200 for CANCEL; 200s are
 	   we generate always a local 200 for CANCEL; 200s are
@@ -208,9 +214,9 @@ int t_should_relay_response( struct cell *Trans , int new_code,
 	*/
 	*/
 
 
 	/* if final response sent out, allow only INVITE 2xx  */
 	/* if final response sent out, allow only INVITE 2xx  */
-	if ( T_code >= 200 ) { 
+	if ( T_code >= 200 ) {
 		if (new_code>=200 && new_code < 300  && 
 		if (new_code>=200 && new_code < 300  && 
-			Trans->inbound_request->REQ_METHOD==METHOD_INVITE) {
+			Trans->uas.request->REQ_METHOD==METHOD_INVITE) {
 			DBG("DBG: t_should_relay: 200 INV after final sent\n");
 			DBG("DBG: t_should_relay: 200 INV after final sent\n");
 			*should_store=1;
 			*should_store=1;
 			return branch;
 			return branch;
@@ -234,13 +240,12 @@ int t_should_relay_response( struct cell *Trans , int new_code,
 					continue;
 					continue;
 				}
 				}
 				/* there is still an unfinished UAC transaction; wait now! */
 				/* there is still an unfinished UAC transaction; wait now! */
-				if ( !Trans->inbound_response[b] ||
-					Trans->inbound_response[b]->REPLY_STATUS<200 )
+				if ( Trans->uac[b].status<200 )
 					return -1;
 					return -1;
-				if ( Trans->inbound_response[b]->REPLY_STATUS<lowest_s )
+				if ( Trans->uac[b].status<lowest_s )
 				{
 				{
 					lowest_b =b;
 					lowest_b =b;
-					lowest_s = T->inbound_response[b]->REPLY_STATUS;
+					lowest_s = T->uac[b].status;
 				}
 				}
 			}
 			}
 			return lowest_b;
 			return lowest_b;
@@ -251,9 +256,10 @@ 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->uac[branch].rpl_received) *should_store=1;
 			else *should_store=0;
 			else *should_store=0;
-			return -1;
+			if (T_code==0) return branch;
+				else return -1;
 		}
 		}
 	}
 	}
 
 
@@ -299,9 +305,8 @@ int t_put_on_wait(  struct cell  *Trans  )
 
 
 	/* cancel pending client transactions, if any */
 	/* cancel pending client transactions, if any */
 	for( i=0 ; i<Trans->nr_of_outgoings ; i++ )
 	for( i=0 ; i<Trans->nr_of_outgoings ; i++ )
-		if ( Trans->inbound_response[i] && 
-		REPLY_CLASS(Trans->inbound_response[i])==1)
-			t_cancel_branch(i);
+		if ( Trans->uac[i].rpl_received && Trans->uac[i].status<200 )
+			t_build_and_send_CANCEL(Trans , i);
 
 
 
 
 	/* we don't need outbound requests anymore -- let's save
 	/* we don't need outbound requests anymore -- let's save
@@ -329,155 +334,6 @@ int t_put_on_wait(  struct cell  *Trans  )
 
 
 
 
 
 
-/*
-  */
-int t_cancel_branch(unsigned int branch)
-{
-	LOG(L_ERR, "ERROR: t_cancel_branch: NOT IMPLEMENTED YET\n");
-	return 1;
-}
-
-
-
-#ifdef _REALLY_TOO_OLD
-/* Builds an ACK request based on an INVITE request. ACK is send
-  * to same address */
-int t_build_and_send_ACK(struct cell *Trans,unsigned int branch,
-														struct sip_msg* rpl)
-{
-	struct sip_msg      *p_msg , *r_msg;
-	struct hdr_field    *hdr;
-	char                *ack_buf, *p, *via;
-	unsigned int         len, via_len;
-	int                  n;
-	struct retrans_buff *srb;
-
-	ack_buf = 0;
-	via =0;
-	p_msg = Trans->inbound_request;
-	r_msg = rpl;
-
-	if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
-	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
-			"cannot generate a HBH ACK if key HFs in reply missing\n");
-		goto error;
-	}
-
-	len = 0;
-	/*first line's len */
-	len += 4/*reply code and one space*/+
-		p_msg->first_line.u.request.version.len+CRLF_LEN;
-	/*uri's len*/
-	if (p_msg->new_uri.s)
-		len += p_msg->new_uri.len +1;
-	else
-		len += p_msg->first_line.u.request.uri.len +1;
-	/*via*/
-	via = via_builder( p_msg , &via_len );
-	if (!via)
-	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
-			"no via header got from builder\n");
-		goto error;
-	}
-	len+= via_len;
-	/*headers*/
-	for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-		if (hdr->type==HDR_FROM||hdr->type==HDR_CALLID||hdr->type==HDR_CSEQ)
-			len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN ;
-		else if ( hdr->type==HDR_TO )
-			len += ((r_msg->to->body.s+r_msg->to->body.len ) -
-				r_msg->to->name.s ) + CRLF_LEN ;
-	/* CSEQ method : from INVITE-> ACK */
-	len -= 3  ;
-	/* end of message */
-	len += CRLF_LEN; /*new line*/
-
-	srb=(struct retrans_buff*)sh_malloc(sizeof(struct retrans_buff)+len+1);
-	if (!srb)
-	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
-		goto error1;
-	}
-	ack_buf = (char *) srb + sizeof(struct retrans_buff);
-	p = ack_buf;
-
-	/* first line */
-	memcpy( p , "ACK " , 4);
-	p += 4;
-	/* uri */
-	if ( p_msg->new_uri.s )
-	{
-		memcpy(p,p_msg->orig+(p_msg->new_uri.s-p_msg->buf),p_msg->new_uri.len);
-		p +=p_msg->new_uri.len;
-	}else{
-		memcpy(p,p_msg->orig+(p_msg->first_line.u.request.uri.s-p_msg->buf),
-			p_msg->first_line.u.request.uri.len );
-		p += p_msg->first_line.u.request.uri.len;
-	}
-	/* SIP version */
-	*(p++) = ' ';
-	memcpy(p,p_msg->orig+(p_msg->first_line.u.request.version.s-p_msg->buf),
-		p_msg->first_line.u.request.version.len );
-	p += p_msg->first_line.u.request.version.len;
-	memcpy( p, CRLF, CRLF_LEN );
-	p+=CRLF_LEN;
-
-	/* insert our via */
-	memcpy( p , via , via_len );
-	p += via_len;
-
-	/*other headers*/
-	for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-	{
-		if ( hdr->type==HDR_FROM || hdr->type==HDR_CALLID  )
-		{
-			memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
-				((hdr->body.s+hdr->body.len ) - hdr->name.s ) );
-			p += ((hdr->body.s+hdr->body.len ) - hdr->name.s );
-			memcpy( p, CRLF, CRLF_LEN );
-			p+=CRLF_LEN;
-		}
-		else if ( hdr->type==HDR_TO )
-		{
-			memcpy( p , r_msg->orig+(r_msg->to->name.s-r_msg->buf) ,
-				((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s));
-			p+=((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s);
-			memcpy( p, CRLF, CRLF_LEN );
-			p+=CRLF_LEN;
-		}
-		else if ( hdr->type==HDR_CSEQ )
-		{
-			memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
-				((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
-			p+=((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s);
-			memcpy( p , "ACK" CRLF, 3+CRLF_LEN );
-			p += 3+CRLF_LEN;
-		}
-	}
-
-	/* end of message */
-	memcpy( p , CRLF , CRLF_LEN );
-	p += CRLF_LEN;
-
-	send_ack( T, branch, srb, p-ack_buf );
-	pkg_free( via );
-	DBG("DEBUG: t_build_and_send_ACK: ACK sent\n");
-	return 0;
-
-error1:
-	pkg_free(via );
-error:
-	return -1;
-}
-
-#endif /* _REALLY_TOO_OLD */
-
-
-
-
-
 /* 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 as the INVITE */
  * 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)
@@ -486,26 +342,24 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	struct hdr_field    *hdr;
 	struct hdr_field    *hdr;
 	char                *cancel_buf, *p, *via;
 	char                *cancel_buf, *p, *via;
 	unsigned int         len, via_len;
 	unsigned int         len, via_len;
-	struct retrans_buff *srb;
-
 
 
-	if ( !Trans->inbound_response[branch] )
+	if ( !Trans->uac[branch].rpl_received )
 	{
 	{
 		DBG("DEBUG: t_build_and_send_CANCEL: no response ever received"
 		DBG("DEBUG: t_build_and_send_CANCEL: no response ever received"
 			" : dropping local cancel! \n");
 			" : dropping local cancel! \n");
 		return 1;
 		return 1;
 	}
 	}
 
 
-	if (Trans->outbound_cancel[branch]!=NO_CANCEL)
+	if (Trans->uac[branch].request.cancel!=NO_CANCEL)
 	{
 	{
-		DBG("DEBUG: t_build_and_send_CANCEL: this branch was already canceled"
-			" : dropping local cancel! \n");
+		DBG("DEBUG: t_build_and_send_CANCEL: branch (%d)was already canceled"
+			" : dropping local cancel! \n",branch);
 		return 1;
 		return 1;
 	}
 	}
 
 
 	cancel_buf = 0;
 	cancel_buf = 0;
 	via = 0;
 	via = 0;
-	p_msg = Trans->inbound_request;
+	p_msg = Trans->uas.request;
 
 
 	len = 0;
 	len = 0;
 	/*first line's len - CANCEL and INVITE has the same lenght */
 	/*first line's len - CANCEL and INVITE has the same lenght */
@@ -515,6 +369,8 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	if (p_msg->new_uri.s)
 	if (p_msg->new_uri.s)
 		len += p_msg->new_uri.len - req_line(p_msg).uri.len;
 		len += p_msg->new_uri.len - req_line(p_msg).uri.len;
 	/*via*/
 	/*via*/
+	if ( add_branch_label(Trans,p_msg,branch)==-1 )
+		goto error;
 	via = via_builder( p_msg , &via_len );
 	via = via_builder( p_msg , &via_len );
 	if (!via)
 	if (!via)
 	{
 	{
@@ -535,13 +391,12 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	/* end of message */
 	/* end of message */
 	len += CRLF_LEN;
 	len += CRLF_LEN;
 
 
-	srb=(struct retrans_buff*)sh_malloc(sizeof(struct retrans_buff)+len+1);
-	if (!srb)
+	cancel_buf=sh_malloc( len+1 );
+	if (!cancel_buf)
 	{
 	{
 		LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
 		LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
 		goto error;
 		goto error;
 	}
 	}
-	cancel_buf = (char*) srb + sizeof(struct retrans_buff);
 	p = cancel_buf;
 	p = cancel_buf;
 
 
 	/* first line -> do we have a new URI? */
 	/* first line -> do we have a new URI? */
@@ -590,30 +445,23 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 	append_mem_block(p,CRLF,CRLF_LEN);
 	append_mem_block(p,CRLF,CRLF_LEN);
 	*p=0;
 	*p=0;
 
 
-	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->fr_timer.payload = srb->retr_timer.payload = srb;
-	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 );	
+	if (Trans->uac[branch].request.cancel) {
+		shm_free( cancel_buf );
 		LOG(L_WARN, "send_cancel: Warning: CANCEL already sent out\n");
 		LOG(L_WARN, "send_cancel: Warning: CANCEL already sent out\n");
 		goto error;
 		goto error;
 	}
 	}
-	Trans->outbound_cancel[branch] = srb;
-	/*sets and starts the FINAL RESPONSE timer */
-	set_timer( hash_table, &(srb->fr_timer), FR_TIMER_LIST );
 
 
+	Trans->uac[branch].request.activ_type = TYPE_LOCAL_CANCEL;
+	Trans->uac[branch].request.cancel = cancel_buf;
+	Trans->uac[branch].request.cancel_len = len;
+
+	/*sets and starts the FINAL RESPONSE timer */
+	set_timer(hash_table,&(Trans->uac[branch].request.fr_timer),FR_TIMER_LIST);
 	/* sets and starts the RETRANS timer */
 	/* sets and starts the RETRANS timer */
-	srb->retr_list = RT_T1_TO_1;
-	set_timer( hash_table, &(srb->retr_timer), RT_T1_TO_1 );
+	Trans->uac[branch].request.retr_list = RT_T1_TO_1;
+	set_timer(hash_table,&(Trans->uac[branch].request.retr_timer),RT_T1_TO_1);
 	DBG("DEBUG: T_build_and_send_CANCEL : sending cancel...\n");
 	DBG("DEBUG: T_build_and_send_CANCEL : sending cancel...\n");
-	SEND_BUFFER( srb );
+	SEND_CANCEL_BUFFER( &(Trans->uac[branch].request) );
 
 
 	pkg_free(via);
 	pkg_free(via);
 	return 1;
 	return 1;
@@ -692,12 +540,12 @@ void delete_cell( struct cell *p_cell )
 int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip, unsigned int *param_port)
 int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip, unsigned int *param_port)
 {
 {
 	struct hostent  *nhost;
 	struct hostent  *nhost;
-	unsigned int      ip, port;
-	struct sip_uri    parsed_uri;
-	str                      uri;
-	int                      err;
+	unsigned int    ip, port;
+	struct sip_uri  parsed_uri;
+	str             uri;
+	int             err;
 #ifdef DNS_IP_HACK
 #ifdef DNS_IP_HACK
-	int                      len;
+	int             len;
 #endif
 #endif
 
 
 	/* the original uri has been changed? */
 	/* the original uri has been changed? */
@@ -763,6 +611,34 @@ error:
 
 
 
 
 
 
+int t_add_fork( unsigned int ip , unsigned int port)
+{
+	if (nr_forks+1>=MAX_FORK)
+	{
+		LOG(L_ERR,"ERROR:t_add_fork: trying to add new fork ->"
+			" MAX_FORK exceded\n");
+		return -1;
+	}
+
+	nr_forks++;
+	t_forks[nr_forks][0] = ip;
+	t_forks[nr_forks][1] = port;
+
+	return 1;
+}
+
+
+
+
+int t_clear_forks( )
+{
+	nr_forks = 0;
+	return 1;
+}
+
+
+
+
 
 
 
 
 /*---------------------------TIMERS FUNCTIONS-------------------------------*/
 /*---------------------------TIMERS FUNCTIONS-------------------------------*/
@@ -773,10 +649,10 @@ error:
 
 
 inline void retransmission_handler( void *attr)
 inline void retransmission_handler( void *attr)
 {
 {
-	struct retrans_buff* r_buf ;
+	struct retr_buf* r_buf ;
 	enum lists id;
 	enum lists id;
-	DBG("DEBUG: entering retransmisson with attr = %p\n",attr);
-	r_buf = (struct retrans_buff*)attr;
+
+	r_buf = (struct retr_buf*)attr;
 #ifdef EXTRA_DEBUG
 #ifdef EXTRA_DEBUG
 	if (r_buf->my_T->damocles) {
 	if (r_buf->my_T->damocles) {
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
@@ -788,11 +664,17 @@ inline void retransmission_handler( void *attr)
 	/*the transaction is already removed from RETRANSMISSION_LIST by timer*/
 	/*the transaction is already removed from RETRANSMISSION_LIST by timer*/
 	/* 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->status!=STATUS_LOCAL_CANCEL && r_buf->status!=STATUS_REQUEST){
-		T=r_buf->my_T;
-		t_retransmit_reply();
-	}else{
-		SEND_BUFFER( r_buf );
+	switch ( r_buf->activ_type )
+	{
+		case (TYPE_REQUEST):
+			SEND_BUFFER( r_buf );
+			break;
+		case (TYPE_LOCAL_CANCEL):
+			SEND_CANCEL_BUFFER( r_buf );
+			break;
+		default:
+			T=r_buf->my_T;
+			t_retransmit_reply();
 	}
 	}
 
 
 	id = r_buf->retr_list;
 	id = r_buf->retr_list;
@@ -808,7 +690,7 @@ inline void retransmission_handler( void *attr)
 
 
 inline void final_response_handler( void *attr)
 inline void final_response_handler( void *attr)
 {
 {
-	struct retrans_buff* r_buf = (struct retrans_buff*)attr;
+	struct retr_buf* r_buf = (struct retr_buf*)attr;
 
 
 #ifdef EXTRA_DEBUG
 #ifdef EXTRA_DEBUG
 	if (r_buf->my_T->damocles) 
 	if (r_buf->my_T->damocles) 
@@ -820,16 +702,16 @@ inline 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)
+	if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
 	{
 	{
 		DBG("DEBUG: FR_handler: stop retransmission for Local Cancel\n");
 		DBG("DEBUG: FR_handler: stop retransmission for Local Cancel\n");
 		reset_timer( hash_table , &(r_buf->retr_timer) );
 		reset_timer( hash_table , &(r_buf->retr_timer) );
 		return;
 		return;
 	}
 	}
 	/* send a 408 */
 	/* send a 408 */
-	if ( r_buf->my_T->status<200
+	if ( r_buf->my_T->uac[r_buf->branch].status<200
 #ifdef SILENT_FR
 #ifdef SILENT_FR
-	&& (0)
+	&& (r_buf->my_T->nr_of_outgoings>1)
 	/*should be fork==yes, but we don't have forking yet - bogdan */
 	/*should be fork==yes, but we don't have forking yet - bogdan */
 #endif
 #endif
 	)
 	)
@@ -843,9 +725,10 @@ inline void final_response_handler( void *attr)
 		FR timer; thus I fake the values now to avoid recalculating T
 		FR timer; thus I fake the values now to avoid recalculating T
 		and refcount++ JKU */
 		and refcount++ JKU */
 		T=r_buf->my_T;
 		T=r_buf->my_T;
-		global_msg_id=T->inbound_request->id;
+		global_msg_id=T->uas.request->id;
 		DBG("DEBUG: FR_handler: send 408 (%p)\n", r_buf->my_T);
 		DBG("DEBUG: FR_handler: send 408 (%p)\n", r_buf->my_T);
-		t_send_reply( r_buf->my_T->inbound_request,408,"Request Timeout" );
+		t_send_reply( r_buf->my_T->uas.request, 408, "Request Timeout",
+			r_buf->branch);
 	}else{
 	}else{
 		/* put it on WT_LIST - transaction is over */
 		/* put it on WT_LIST - transaction is over */
 		DBG("DEBUG: final_response_handler:-> put on wait"
 		DBG("DEBUG: final_response_handler:-> put on wait"
@@ -966,26 +849,23 @@ void timer_routine(unsigned int ticks , void * attr)
 
 
 
 
 
 
-#ifndef _REALLY_TOO_OLD
-
 /* Builds an ACK request based on an INVITE request. ACK is send
 /* Builds an ACK request based on an INVITE request. ACK is send
-  * to same address */
-struct retrans_buff *build_ack( struct sip_msg* rpl, struct cell *trans, int branch )
+ * to same address */
+char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,int *ret_len)
 {
 {
 	struct sip_msg      *p_msg , *r_msg;
 	struct sip_msg      *p_msg , *r_msg;
 	struct hdr_field    *hdr;
 	struct hdr_field    *hdr;
 	char                *ack_buf, *p, *via;
 	char                *ack_buf, *p, *via;
 	unsigned int         len, via_len;
 	unsigned int         len, via_len;
-	struct retrans_buff *srb;
 
 
 	ack_buf = 0;
 	ack_buf = 0;
 	via =0;
 	via =0;
-	p_msg = trans->inbound_request;
+	p_msg = trans->uas.request;
 	r_msg = rpl;
 	r_msg = rpl;
 
 
 	if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
 	if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
 	{
 	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
+		LOG(L_ERR, "ERROR: t_build_ACK: "
 			"cannot generate a HBH ACK if key HFs in reply missing\n");
 			"cannot generate a HBH ACK if key HFs in reply missing\n");
 		goto error;
 		goto error;
 	}
 	}
@@ -999,11 +879,14 @@ struct retrans_buff *build_ack( struct sip_msg* rpl, struct cell *trans, int bra
 		len += p_msg->new_uri.len +1;
 		len += p_msg->new_uri.len +1;
 	else
 	else
 		len += p_msg->first_line.u.request.uri.len +1;
 		len += p_msg->first_line.u.request.uri.len +1;
+	/*adding branch param*/
+	if ( add_branch_label( trans , trans->uas.request , branch)==-1 )
+		goto error;
 	/*via*/
 	/*via*/
 	via = via_builder( p_msg , &via_len );
 	via = via_builder( p_msg , &via_len );
 	if (!via)
 	if (!via)
 	{
 	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
+		LOG(L_ERR, "ERROR: t_build_ACK: "
 			"no via header got from builder\n");
 			"no via header got from builder\n");
 		goto error;
 		goto error;
 	}
 	}
@@ -1020,13 +903,12 @@ struct retrans_buff *build_ack( struct sip_msg* rpl, struct cell *trans, int bra
 	/* end of message */
 	/* end of message */
 	len += CRLF_LEN; /*new line*/
 	len += CRLF_LEN; /*new line*/
 
 
-	srb=(struct retrans_buff*)sh_malloc(sizeof(struct retrans_buff)+len+1);
-	if (!srb)
+	ack_buf = sh_malloc(len+1);
+	if (!ack_buf)
 	{
 	{
-		LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
+		LOG(L_ERR, "ERROR: t_build_and_ACK: cannot allocate memory\n");
 		goto error1;
 		goto error1;
 	}
 	}
-	ack_buf = (char *) srb + sizeof(struct retrans_buff);
 	p = ack_buf;
 	p = ack_buf;
 
 
 	/* first line */
 	/* first line */
@@ -1087,16 +969,11 @@ struct retrans_buff *build_ack( struct sip_msg* rpl, struct cell *trans, int bra
 	memcpy( p , CRLF , CRLF_LEN );
 	memcpy( p , CRLF , CRLF_LEN );
 	p += CRLF_LEN;
 	p += CRLF_LEN;
 
 
-	/* fill in the structure */
-	srb->bufflen = p-ack_buf;
-	srb->tolen = sizeof( struct sockaddr_in );
-	srb->my_T = trans;
-	srb->retr_buffer = (char *) srb + sizeof( struct retrans_buff );
-	memcpy( &srb->to, & trans->outbound_request[ branch ]->to, sizeof (struct sockaddr_in));
-
 	pkg_free( via );
 	pkg_free( via );
-	DBG("DEBUG: t_build_and_send_ACK: ACK sent\n");
-	return srb;
+	DBG("DEBUG: t_build_ACK: ACK generated\n");
+
+	*(ret_len) = p-ack_buf;
+	return ack_buf;
 
 
 error1:
 error1:
 	pkg_free(via );
 	pkg_free(via );
@@ -1104,6 +981,5 @@ error:
 	return 0;
 	return 0;
 }
 }
 
 
-#endif
 
 
 
 

+ 38 - 64
modules/tm/t_funcs.h

@@ -22,10 +22,11 @@ struct timer;
 struct entry;
 struct entry;
 struct cell;
 struct cell;
 
 
-extern struct cell         *T;
+extern struct cell      *T;
 extern unsigned int     global_msg_id;
 extern unsigned int     global_msg_id;
 extern struct s_table*  hash_table;
 extern struct s_table*  hash_table;
-
+extern unsigned int     t_forks[MAX_FORK+1][2];
+extern unsigned int     nr_forks;
 
 
 #include "sh_malloc.h"
 #include "sh_malloc.h"
 
 
@@ -54,31 +55,26 @@ extern struct s_table*  hash_table;
 
 
 #define SEND_PR_BUFFER(_rb,_bf,_le ) \
 #define SEND_PR_BUFFER(_rb,_bf,_le ) \
 	{\
 	{\
-		if ((_rb) && (_bf) && (_le) ) \
-		{\
+		if ((_bf) && (_le) && (_bf) ) {\
 			udp_send( (_bf), (_le), (struct sockaddr*)&((_rb)->to) , \
 			udp_send( (_bf), (_le), (struct sockaddr*)&((_rb)->to) , \
 				sizeof(struct sockaddr_in) ); \
 				sizeof(struct sockaddr_in) ); \
-		} else { \
-			LOG(L_CRIT,"ERROR:attempt to send an empty buffer from %s (%d)"\
-				"(%p,%p,%d)\n",__FUNCTION__, __LINE__,(_rb),(_bf),(_le));\
+		}else{ \
+			LOG(L_CRIT,"ERROR: sending an empty buffer from %s (%d)\n",\
+				__FUNCTION__, __LINE__ );\
 		}\
 		}\
-	}\
+	}
 
 
-#define SEND_BUFFER( _rb ) SEND_PR_BUFFER( \
-	_rb,(_rb)->retr_buffer, (_rb)->bufflen )
+#define SEND_ACK_BUFFER( _rb ) \
+	SEND_PR_BUFFER( (_rb) , (_rb)->ack , (_rb)->ack_len )
 
 
-/*
-#define SEND_BUFFER( _rb ) ({ if ((_rb)->retr_buffer) \
-	{ udp_send( (_rb)->retr_buffer, \
-	  (_rb)->bufflen, (struct sockaddr*)&((_rb)->to) , \
-	  sizeof(struct sockaddr_in) ); \
-	} else \
-	DBG("ERROR: attempt to send an empty buffer from %s (%d)", \
-	__FUNCTION__, __LINE__ ); })
-*/
+#define SEND_CANCEL_BUFFER( _rb ) \
+	SEND_PR_BUFFER( (_rb) , (_rb)->cancel , (_rb)->cancel_len )
+
+#define SEND_BUFFER( _rb ) \
+	SEND_PR_BUFFER( (_rb) , (_rb)->buffer , (_rb)->buffer_len )
 
 
 
 
-/* 
+/*
   macros for reference bitmap (lock-less process non-exclusive ownership) 
   macros for reference bitmap (lock-less process non-exclusive ownership) 
 */
 */
 #define T_IS_REFED(_T_cell) ((_T_cell)->ref_bitmap)
 #define T_IS_REFED(_T_cell) ((_T_cell)->ref_bitmap)
@@ -124,24 +120,7 @@ extern struct s_table*  hash_table;
 #endif
 #endif
 
 
 
 
-	
-
-#ifdef _OLD_XX
-#define unref_T(_T_cell) \
-	( {\
-		lock( &(hash_table->entrys[(_T_cell)->hash_index].mutex) );\
-		(_T_cell)->ref_counter--;\
-		DBG_REF("unref", (_T_cell)); \
-		unlock( &(hash_table->entrys[(_T_cell)->hash_index].mutex) );\
-	} );
 
 
-/* we assume that ref_T is only called from places where
-   the associated locks are set up and we don't need to
-   lock/unlock
-*/
-#define ref_T(_T_cell) ({ ((_T_cell)->ref_counter++); \
-		DBG_REF("ref", (_T_cell));	})
-#endif
 
 
 enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK,
 enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK,
 	AIN_OLDACK, AIN_RTRACK } ;
 	AIN_OLDACK, AIN_RTRACK } ;
@@ -187,12 +166,12 @@ int t_forward_uri( struct sip_msg* p_msg  );
 
 
 
 
 
 
+
 /* This function is called whenever a reply for our module is received;
 /* This function is called whenever a reply for our module is received;
  * we need to register this function on module initialization;
  * we need to register this function on module initialization;
  * Returns :   0 - core router stops
  * Returns :   0 - core router stops
  *             1 - core router relay statelessly
  *             1 - core router relay statelessly
  */
  */
-
 int t_on_reply( struct sip_msg  *p_msg ) ;
 int t_on_reply( struct sip_msg  *p_msg ) ;
 
 
 
 
@@ -219,7 +198,7 @@ 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* );
 int t_release_transaction( struct sip_msg* );
 
 
 
 
@@ -237,7 +216,7 @@ int t_retransmit_reply( /* struct sip_msg * */  );
 /* 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
  */
  */
-int t_send_reply( struct sip_msg * , unsigned int , char *  );
+int t_send_reply( struct sip_msg * , unsigned int , char *  , unsigned int);
 
 
 
 
 
 
@@ -260,42 +239,44 @@ 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 * );
 int t_build_and_send_ACK( struct cell *Trans , unsigned int brach ,
 int t_build_and_send_ACK( struct cell *Trans , unsigned int brach ,
 	struct sip_msg* rpl);
 	struct sip_msg* rpl);
-int t_cancel_branch(unsigned int branch); //TO DO
 int t_should_relay_response( struct cell *Trans, int new_code, int branch,
 int t_should_relay_response( struct cell *Trans, int new_code, int branch,
 	int *should_store );
 	int *should_store );
-int t_update_timers_after_sending_reply( struct retrans_buff *rb );
+int t_update_timers_after_sending_reply( struct retr_buf *rb );
 int t_put_on_wait(  struct cell  *Trans  );
 int t_put_on_wait(  struct cell  *Trans  );
 int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
 int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
 int add_branch_label( struct cell *Trans, struct sip_msg *p_msg , int branch );
 int add_branch_label( struct cell *Trans, struct sip_msg *p_msg , int branch );
 int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip,
 int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip,
 	unsigned int *param_port);
 	unsigned int *param_port);
-struct retrans_buff *build_ack( struct sip_msg* rpl, struct cell *trans,
-	int branch );
+int t_build_and_send_CANCEL(struct cell *Trans, unsigned int branch);
+char *build_ack( struct sip_msg* rpl, struct cell *trans, int branch ,
+	int *ret_len);
 enum addifnew_status t_addifnew( struct sip_msg* p_msg );
 enum addifnew_status t_addifnew( struct sip_msg* p_msg );
-
+int t_add_fork( unsigned int ip , unsigned int port);
+int t_clear_forks( );
 
 
 
 
 
 
 inline int static attach_ack(  struct cell *t, int branch,
 inline int static attach_ack(  struct cell *t, int branch,
-    struct retrans_buff *srb )
+									char *ack, int ack_len )
 {
 {
 	LOCK_ACK( t );
 	LOCK_ACK( t );
-	if (t->outbound_ack[branch]) {
+	if (t->uac[branch].request.ack) {
 		UNLOCK_ACK(t);
 		UNLOCK_ACK(t);
-		shm_free( srb );
+		shm_free( ack );
 		LOG(L_WARN, "attach_ack: Warning: ACK already sent out\n");
 		LOG(L_WARN, "attach_ack: Warning: ACK already sent out\n");
 		return 0;
 		return 0;
 	}
 	}
-	t->outbound_ack[branch] = srb;
+	t->uac[branch].request.ack = ack;
+	t->uac[branch].request.ack_len = ack_len;
 	UNLOCK_ACK( t );
 	UNLOCK_ACK( t );
 	return 1;
 	return 1;
 }
 }
 
 
 
 
 
 
-
-inline int static relay_ack( struct cell *t, int branch, 
-	struct retrans_buff *srb, int len )
+/*
+inline int static relay_ack( struct cell *t, int branch,
+						struct retrans_buff *srb, int len )
 {
 {
 	memset( srb, 0, sizeof( struct retrans_buff ) );
 	memset( srb, 0, sizeof( struct retrans_buff ) );
 	memcpy( & srb->to, & t->ack_to, sizeof (struct sockaddr_in));
 	memcpy( & srb->to, & t->ack_to, sizeof (struct sockaddr_in));
@@ -306,7 +287,7 @@ inline int static relay_ack( struct cell *t, int branch,
 	srb->bufflen = len;
 	srb->bufflen = len;
 	SEND_BUFFER( srb );
 	SEND_BUFFER( srb );
 	return attach_ack( t, branch, srb );
 	return attach_ack( t, branch, srb );
-}
+}*/
 
 
 
 
 
 
@@ -360,27 +341,20 @@ static inline void reset_retr_timers( struct s_table *h_table,
 													struct cell *p_cell )
 													struct cell *p_cell )
 {
 {
 	int ijk;
 	int ijk;
-	struct retrans_buff *rb;
 
 
 	/* lock the first timer list of the FR group -- all other
 	/* lock the first timer list of the FR group -- all other
 	   lists share the same lock*/
 	   lists share the same lock*/
 	lock(hash_table->timers[RT_T1_TO_1].mutex);
 	lock(hash_table->timers[RT_T1_TO_1].mutex);
-	remove_timer_unsafe( & p_cell->outbound_response.retr_timer );
+	remove_timer_unsafe( & p_cell->uas.response.retr_timer );
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
-		if ( (rb = p_cell->outbound_request[ijk]) )
-			remove_timer_unsafe( & rb->retr_timer );
-		if ( (rb = p_cell->outbound_cancel[ijk]) )
-			remove_timer_unsafe( & rb->retr_timer );
+		remove_timer_unsafe( & p_cell->uac[ijk].request.retr_timer );
 	}
 	}
 	unlock(hash_table->timers[RT_T1_TO_1].mutex);
 	unlock(hash_table->timers[RT_T1_TO_1].mutex);
 
 
 	lock(hash_table->timers[FR_TIMER_LIST].mutex);
 	lock(hash_table->timers[FR_TIMER_LIST].mutex);
-	remove_timer_unsafe( & p_cell->outbound_response.fr_timer );
+	remove_timer_unsafe( & p_cell->uas.response.fr_timer );
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  {
-		if ( (rb = p_cell->outbound_request[ijk]) )
-			remove_timer_unsafe( & rb->fr_timer );
-		if ( (rb = p_cell->outbound_cancel[ijk]) )
-			remove_timer_unsafe( & rb->fr_timer );
+		remove_timer_unsafe( & p_cell->uac[ijk].request.fr_timer );
 	}
 	}
 	unlock(hash_table->timers[FR_TIMER_LIST].mutex);
 	unlock(hash_table->timers[FR_TIMER_LIST].mutex);
 	DBG("DEBUG:stop_RETR_and_FR_timers : timers stopped\n");
 	DBG("DEBUG:stop_RETR_and_FR_timers : timers stopped\n");

+ 114 - 128
modules/tm/t_fwd.c

@@ -16,170 +16,161 @@
  *      -1 - error during forward
  *      -1 - error during forward
  */
  */
 int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
-	unsigned int dest_port_param )
+											unsigned int dest_port_param )
 {
 {
-	unsigned int        dest_ip = dest_ip_param;
-	unsigned int        dest_port = dest_port_param;
-	int                  branch;
-	unsigned int         len;
-	char                *buf, *shbuf;
-	struct retrans_buff *rb = 0;
-	struct cell         *T_source = T;
-
-
-	buf=NULL;
-	shbuf = NULL;
-	branch = 0;	/* we don't do any forking right now */
+	int          branch,i;
+	unsigned int len;
+	char         *buf, *shbuf;
+	struct cell  *T_source = T;
+	struct lump  *a,*b,*b1,*c;
+
+
+	buf    = 0;
+	shbuf  = 0;
+	t_forks[0][0] = dest_ip_param;
+	t_forks[0][1] = dest_port_param;
+
+	/* are we forwarding for the first time? */
+	if ( T->uac[0].request.buffer )
+	{	/* rewriting a request should really not happen -- retransmission
+		   does not rewrite, whereas a new request should be written
+		   somewhere else */
+		LOG( L_CRIT, "ERROR: t_forward_nonack: attempt to rewrite"
+			" request structures\n");
+		return 0;
+	}
 
 
-	if ( T->outbound_request[branch]==NULL )
+	DBG("DEBUG: t_forward_nonack: first time forwarding\n");
+	/* special case : CANCEL */
+	if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
 	{
 	{
-		DBG("DEBUG: t_forward_nonack: first time forwarding\n");
-		/* special case : CANCEL */
-		if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
+		DBG("DEBUG: t_forward_nonack: it's CANCEL\n");
+		/* find original cancelled transaction; if found, use its
+		   next-hops; otherwise use those passed by script */
+		if ( T->T_canceled==T_UNDEFINED )
+			T->T_canceled = t_lookupOriginalT( hash_table , p_msg );
+		/* if found */
+		if ( T->T_canceled!=T_NULL )
 		{
 		{
-			DBG("DEBUG: t_forward_nonack: it's CANCEL\n");
-			/* find original cancelled transaction; if found, use its
-			   next-hops; otherwise use those passed by script */
-			if ( T->T_canceled==T_UNDEFINED )
-				T->T_canceled = t_lookupOriginalT( hash_table , p_msg );
-			/* if found */
-			if ( T->T_canceled!=T_NULL )
+			/* if in 1xx status, send to the same destination */
+			if ( (T->T_canceled->uas.status/100)==1 )
 			{
 			{
-				/* if in 1xx status, send to the same destination */
-				if ( (T->T_canceled->status/100)==1 )
+				DBG("DEBUG: t_forward_nonack: it's CANCEL and I will send "
+					"to the same place where INVITE went\n");
+				nr_forks = T->T_canceled->nr_of_outgoings-1;
+				for(i=0;i<T->T_canceled->nr_of_outgoings;i++)
 				{
 				{
-					DBG("DEBUG: t_forward_nonack: it's CANCEL and I will send "
-						"to the same place where INVITE went\n");
-					dest_ip=T->T_canceled->outbound_request[branch]->
-						to.sin_addr.s_addr;
-					dest_port = T->T_canceled->outbound_request[branch]->
-						to.sin_port;
+					t_forks[i][0] =
+						T->T_canceled->uac[i].request.to.sin_addr.s_addr;
+					t_forks[i][1] =
+						T->T_canceled->uac[i].request.to.sin_port;
+				}
 #ifdef USE_SYNONIM
 #ifdef USE_SYNONIM
-					T_source = T->T_canceled;
-					T->label  = T->T_canceled->label;
+				T_source = T->T_canceled;
+				T->label  = T->T_canceled->label;
 #endif
 #endif
-				} else { /* transaction exists, but nothing to cancel */
-					DBG("DEBUG: t_forward_nonack: it's CANCEL but "
-						"I have nothing to cancel here\n");
-					/* forward CANCEL as a stand-alone transaction */
-				}
-			} else { /* transaction doesnot exists  */
-				DBG("DEBUG: t_forward_nonack: canceled request not found! "
-				"nothing to CANCEL\n");
+			} else { /* transaction exists, but nothing to cancel */
+				DBG("DEBUG: t_forward_nonack: it's CANCEL but "
+					"I have nothing to cancel here\n");
+				/* forward CANCEL as a stand-alone transaction */
 			}
 			}
-		}/* end special case CANCEL*/
+		} else { /* transaction doesnot exists  */
+			DBG("DEBUG: t_forward_nonack: canceled request not found! "
+			"nothing to CANCEL\n");
+		}
+	}/* end special case CANCEL*/
 
 
-		if ( add_branch_label( T_source, T->inbound_request , branch )==-1)
-			goto error;
+	DBG("DEBUG: t_forward_nonack: nr_forks=%d\n",nr_forks);
+	for(branch=0;branch<nr_forks+1;branch++)
+	{
+		DBG("DEBUG: t_forward_nonack: branch = %d\n",branch);
+		/*generates branch param*/
+		//if ( add_branch_label( T_source, T->uas.request , branch )==-1)
+		//	goto error;
 		if ( add_branch_label( T_source, p_msg , branch )==-1)
 		if ( add_branch_label( T_source, p_msg , branch )==-1)
 			goto error;
 			goto error;
+		/* remove all the HDR_VIA type lumps */
+		if (branch)
+			for(b=p_msg->add_rm,b1=0;b;b1=b,b=b->next)
+				if (b->type==HDR_VIA)
+				{
+					for(a=b->before;a;)
+						{c=a->before;free_lump(a);a=c;}
+					for(a=b->after;a;)
+						{c=a->after;free_lump(a);a=c;}
+					if (b1) b1->next = b->next;
+						else p_msg->add_rm = b->next;
+					free_lump(b);
+				}
 		if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))
 		if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))
 			goto error;
 			goto error;
-
 		/* allocates a new retrans_buff for the outbound request */
 		/* allocates a new retrans_buff for the outbound request */
-		DBG("DEBUG: t_forward_nonack: building outbound request\n");
-		shm_lock();
-		rb = (struct retrans_buff*) shm_malloc_unsafe( sizeof(struct retrans_buff)  );
-		if (!rb)
-		{
-			LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem\n");
-			shm_unlock();
-			goto error;
-		}
-		shbuf = (char *) shm_malloc_unsafe( len );
+		DBG("DEBUG: t_forward_nonack: building outbound request"
+			" for branch %d.\n",branch);
+		shbuf = (char *) shm_malloc( len );
 		if (!shbuf)
 		if (!shbuf)
 		{
 		{
 			LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem buffer\n");
 			LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem buffer\n");
-			shm_unlock();
 			goto error;
 			goto error;
 		}
 		}
-		shm_unlock();
-		memset( rb , 0 , sizeof (struct retrans_buff) );
-		rb->retr_timer.tg=TG_RT;
-		rb->fr_timer.tg=TG_FR;
-		rb->retr_buffer = shbuf;
-		rb->retr_timer.payload =  rb;
-		rb->fr_timer.payload =  rb;
-		rb->my_T =  T;
-		T->nr_of_outgoings = 1;
-		rb->bufflen = len ;
-		memcpy( rb->retr_buffer , buf , len );
+		T->uac[branch].request.buffer = shbuf;
+		T->uac[branch].request.buffer_len = len ;
+		memcpy( T->uac[branch].request.buffer , buf , len );
+		T->nr_of_outgoings++ ;
 		/* send the request */
 		/* send the request */
-		/* known to be in network order */
-		rb->to.sin_port     =  dest_port;
-		rb->to.sin_addr.s_addr =  dest_ip;
-		rb->to.sin_family = AF_INET;
-		T->outbound_request[branch] = rb;
-		SEND_BUFFER( rb );
-		/* link the retransmission buffer to our structures when the job is done */
-		pkg_free( buf ) ; buf=NULL;
-
-		DBG("DEBUG: t_forward_nonack: starting timers (retrans and FR) %d\n",get_ticks() );
-		/*sets and starts the FINAL RESPONSE timer */
-		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
+		T->uac[branch].request.to.sin_addr.s_addr = t_forks[branch][0];
+		T->uac[branch].request.to.sin_port = t_forks[branch][1];
+		T->uac[branch].request.to.sin_family = AF_INET;
+		SEND_BUFFER( &(T->uac[branch].request) );
 
 
+		pkg_free( buf ) ;
+		buf=NULL;
+
+		DBG("DEBUG: t_forward_nonack: starting timers (retrans and FR) %d\n",
+			get_ticks() );
+		/*sets and starts the FINAL RESPONSE timer */
+		set_timer( hash_table, &(T->uac[branch].request.fr_timer),
+			FR_TIMER_LIST );
 		/* sets and starts the RETRANS timer */
 		/* sets and starts the RETRANS timer */
-		rb->retr_list = RT_T1_TO_1;
-		set_timer( hash_table, &(rb->retr_timer), RT_T1_TO_1 );
-	}/* end for the first time */ else {
-		/* rewriting a request should really not happen -- retransmission
-	       does not rewrite, whereas a new request should be written
-		   somewhere else
-		*/
-		LOG( L_CRIT, "ERROR: t_forward_nonack: attempt to rewrite request structures\n");
-		return 0;
+		T->uac[branch].request.retr_list = RT_T1_TO_1;
+		set_timer( hash_table, &(T->uac[branch].request.retr_timer),
+			RT_T1_TO_1 );
 	}
 	}
 
 
-	if (  p_msg->REQ_METHOD==METHOD_CANCEL )
-	{
-		DBG("DEBUG: t_forward_nonack: forwarding CANCEL\n");
-		/* if no transaction to CANCEL */
-		/* or if the canceled transaction has a final status -> drop the CANCEL*/
-		if ( T->T_canceled!=T_NULL && T->T_canceled->status>=200)
-		{
-			reset_timer( hash_table, &(rb->fr_timer ));
-			reset_timer( hash_table, &(rb->retr_timer ));
-			return 1;
-		}
-	}
 	return 1;
 	return 1;
 
 
 error:
 error:
 	if (shbuf) shm_free(shbuf);
 	if (shbuf) shm_free(shbuf);
-	if (rb) {
-		shm_free(rb);
-		T->outbound_request[branch]=NULL;
-	}
+	T->uac[branch].request.buffer=NULL;
 	if (buf) pkg_free( buf );
 	if (buf) pkg_free( buf );
-
 	return -1;
 	return -1;
-
 }
 }
 
 
+
+
+
 int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 										unsigned int dest_port_param )
 										unsigned int dest_port_param )
 {
 {
 	int branch;
 	int branch;
 	unsigned int len;
 	unsigned int len;
-	char *buf;
-	struct retrans_buff *srb;
+	char *buf, *ack;
 #ifdef _DONT_USE
 #ifdef _DONT_USE
 	struct sockaddr_in to_sock;
 	struct sockaddr_in to_sock;
 #endif
 #endif
 
 
 
 
-
 	/* drop local ACKs */
 	/* drop local ACKs */
-	if (T->status/100!=2 ) {
-		DBG("DEBUG: local ACK dropped\n");
+	if (T->uas.status/100!=2 ) {
+		DBG("DEBUG: t_forward_ACK:  local ACK dropped\n");
 		return 1;
 		return 1;
 	}
 	}
 
 
 	branch=T->relaied_reply_branch;
 	branch=T->relaied_reply_branch;
 	/* double-check for odd relaying */
 	/* double-check for odd relaying */
 	if ( branch <0 || branch>=T->nr_of_outgoings ) {
 	if ( branch <0 || branch>=T->nr_of_outgoings ) {
-		DBG("DEBUG: t_forward_ack: strange relaied_reply_branch: %d out of %d\n",
-			branch, T->nr_of_outgoings );
+		DBG("DEBUG: t_forward_ack: strange relaied_reply_branch:"
+			" %d out of %d\n",branch, T->nr_of_outgoings );
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -191,7 +182,7 @@ int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 	}
 	}
 	/* not able to build outbound request -- then better give up */
 	/* not able to build outbound request -- then better give up */
 	if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))  {
 	if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))  {
-		LOG( L_ERR, "ERROR: t_forward_ack failed to generate outbound message\n" );
+		LOG(L_ERR,"ERROR: t_forward_ack failed to generate outbound ACK\n");
 		return 0;
 		return 0;
 	};
 	};
 
 
@@ -203,26 +194,21 @@ int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 	}
 	}
 #endif
 #endif
 
 
-	shm_lock();
 	/* check for bizzar race condition if two processes receive
 	/* check for bizzar race condition if two processes receive
 	   two ACKs concurrently; use shmem semaphore for protection
 	   two ACKs concurrently; use shmem semaphore for protection
 	   -- we have to enter it here anyway (the trick with inACKed
 	   -- we have to enter it here anyway (the trick with inACKed
-	   inside the protection region)
-    */
-	if  (T->inbound_request_isACKed ) {
-		shm_unlock();
-		LOG(L_WARN, "Warning: ACK received when there's one; check upstream\n");
+	   inside the protection region) */
+	if  (T->uas.isACKed ) {
+		LOG(L_WARN,"Warning: ACK received when there's one; check upstream\n");
 		return 1;
 		return 1;
 	}
 	}
-	srb = (struct retrans_buff *) shm_malloc_unsafe( sizeof( struct retrans_buff ) + len );
-	T->inbound_request_isACKed = 1;
-	shm_unlock();
-
-	memcpy( (char *) srb + sizeof ( struct retrans_buff ), buf, len );
+	ack = shm_malloc( len );
+	memcpy(ack , buf , len);
 	pkg_free( buf );
 	pkg_free( buf );
 
 
-	relay_ack( T, branch, srb, len );
-	return 1;
+	T->uas.isACKed = 1;
+	SEND_PR_BUFFER( &(T->uac[branch].request), ack, len );
+	return attach_ack( T, branch, ack , len );
 
 
 #ifdef _DON_USE
 #ifdef _DON_USE
 fwd_sl: /* some strange conditions occured; try statelessly */
 fwd_sl: /* some strange conditions occured; try statelessly */

+ 23 - 22
modules/tm/t_lookup.c

@@ -22,7 +22,7 @@
 	(p_msg->first_line.u.request.uri.len==t_msg->first_line.u.request.uri.len)
 	(p_msg->first_line.u.request.uri.len==t_msg->first_line.u.request.uri.len)
 #define EQ_REQ_URI_STR\
 #define EQ_REQ_URI_STR\
 	( memcmp( t_msg->first_line.u.request.uri.s,\
 	( memcmp( t_msg->first_line.u.request.uri.s,\
-	translate_pointer(p_msg->orig,p_msg->buf, p_msg->first_line.u.request.uri.s),\
+	translate_pointer(p_msg->orig,p_msg->buf,p_msg->first_line.u.request.uri.s),\
 	p_msg->first_line.u.request.uri.len)==0)
 	p_msg->first_line.u.request.uri.len)==0)
 #define EQ_VIA_LEN(_via)\
 #define EQ_VIA_LEN(_via)\
 	( (p_msg->via1->bsize-(p_msg->_via->name.s-(p_msg->_via->hdr.s+p_msg->_via->hdr.len)))==\
 	( (p_msg->via1->bsize-(p_msg->_via->name.s-(p_msg->_via->hdr.s+p_msg->_via->hdr.len)))==\
@@ -108,7 +108,8 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
 	tmp_cell = 0;
 	tmp_cell = 0;
 	while( p_cell )
 	while( p_cell )
 	{
 	{
-		t_msg = p_cell->inbound_request;
+		t_msg = p_cell->uas.request;
+
 		/* is it the wanted transaction ? */
 		/* is it the wanted transaction ? */
 		if ( !isACK )
 		if ( !isACK )
 		{ /* is not an ACK request */
 		{ /* is not an ACK request */
@@ -133,9 +134,9 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
 			&& get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
 			&& get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
 			&& /*from length*/ EQ_LEN(from)
 			&& /*from length*/ EQ_LEN(from)
 			&& /*to uri*/get_to(t_msg)->uri.len==get_to(p_msg)->uri.len
 			&& /*to uri*/get_to(t_msg)->uri.len==get_to(p_msg)->uri.len
-			&& /*to tag*/p_cell->tag->len==get_to(p_msg)->tag_value.len
-			&& /*req URI*/(p_cell->status==200 || EQ_REQ_URI_LEN )
-			&& /*VIA*/(p_cell->status==200 || EQ_VIA_LEN(via1)) )
+			&& /*to tag*/p_cell->uas.tag->len==get_to(p_msg)->tag_value.len
+			&& /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_LEN )
+			&& /*VIA*/(p_cell->uas.status==200 || EQ_VIA_LEN(via1)) )
 				/* so far the lengths are the same
 				/* so far the lengths are the same
 				-> let's check the contents */
 				-> let's check the contents */
 				if (/*callid*/!memcmp( t_msg->callid->body.s,
 				if (/*callid*/!memcmp( t_msg->callid->body.s,
@@ -145,10 +146,10 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
 				&& /*from*/EQ_STR(from)
 				&& /*from*/EQ_STR(from)
 				&& /*to uri*/!memcmp(get_to(t_msg)->uri.s,
 				&& /*to uri*/!memcmp(get_to(t_msg)->uri.s,
 					get_to(p_msg)->uri.s,get_to(t_msg)->uri.len)
 					get_to(p_msg)->uri.s,get_to(t_msg)->uri.len)
-				&& /*to tag*/!memcmp(p_cell->tag->s,
-					get_to(p_msg)->tag_value.s,p_cell->tag->len)
-				&& /*req URI*/(p_cell->status==200 || EQ_REQ_URI_STR)
-				&& /*VAI*/(p_cell->status==200 ||EQ_VIA_STR(via1)) )
+				&& /*to tag*/!memcmp(p_cell->uas.tag->s,
+					get_to(p_msg)->tag_value.s,p_cell->uas.tag->len)
+				&& /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_STR)
+				&& /*VAI*/(p_cell->uas.status==200 ||EQ_VIA_STR(via1)) )
 					{ /* WE FOUND THE GOLDEN EGG !!!! */
 					{ /* WE FOUND THE GOLDEN EGG !!!! */
 						goto found;
 						goto found;
 					}
 					}
@@ -187,7 +188,7 @@ struct cell* t_lookupOriginalT(  struct s_table* hash_table ,
 	struct cell     *p_cell;
 	struct cell     *p_cell;
 	struct cell     *tmp_cell;
 	struct cell     *tmp_cell;
 	unsigned int     hash_index=0;
 	unsigned int     hash_index=0;
-	struct sip_msg  *t_msg;
+	struct sip_msg  *t_msg=0;
 
 
 
 
 	/* start searching into the table */
 	/* start searching into the table */
@@ -199,11 +200,11 @@ struct cell* t_lookupOriginalT(  struct s_table* hash_table ,
 	tmp_cell = 0;
 	tmp_cell = 0;
 	while( p_cell )
 	while( p_cell )
 	{
 	{
-		t_msg = p_cell->inbound_request;
+		t_msg = p_cell->uas.request;
 
 
 		/* is it the wanted transaction ? */
 		/* is it the wanted transaction ? */
 		/* first only the length are checked */
 		/* first only the length are checked */
-		if ( p_cell->inbound_request->REQ_METHOD!=METHOD_CANCEL
+		if ( p_cell->uas.request->REQ_METHOD!=METHOD_CANCEL
 			&& /*callid length*/ EQ_LEN(callid)
 			&& /*callid length*/ EQ_LEN(callid)
 			&& get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
 			&& get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
 			&& EQ_REQ_URI_LEN
 			&& EQ_REQ_URI_LEN
@@ -324,13 +325,13 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ,
 	{
 	{
 		/* 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_cell->uas.request)->method.len)
 		&& ((get_cseq(p_msg)->method.s[0] ==
 		&& ((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_cell->uas.request)->method.s[0] && (*local_cancel=0)==0)
+		|| (get_cseq(p_cell->uas.request)->method.s[0]=='I' &&
 		get_cseq(p_msg)->method.s[0]=='C'
 		get_cseq(p_msg)->method.s[0]=='C'
-		&& p_cell->outbound_cancel[branch_id]!=NO_CANCEL
-		&& p_cell->outbound_cancel[branch_id]!=EXTERNAL_CANCEL
+		&& p_cell->uac[branch_id].request.cancel!=NO_CANCEL
+		&& p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL
 		&& (*local_cancel=1)==1))
 		&& (*local_cancel=1)==1))
 #ifdef USE_SYNONIM
 #ifdef USE_SYNONIM
 		&& (p_cell->label == entry_label )
 		&& (p_cell->label == entry_label )
@@ -340,9 +341,8 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ,
 #endif
 #endif
 		)
 		)
 			/* has the transaction the wanted branch? */
 			/* has the transaction the wanted branch? */
-			if ( p_cell->nr_of_outgoings>branch_id &&
-			p_cell->outbound_request[branch_id] )
- 			{/* WE FOUND THE GOLDEN EGG !!!! */
+			if ( p_cell->nr_of_outgoings>branch_id )
+			{/* WE FOUND THE GOLDEN EGG !!!! */
 				T = p_cell;
 				T = p_cell;
 				*p_branch = branch_id;
 				*p_branch = branch_id;
 				T_REF( T );
 				T_REF( T );
@@ -429,6 +429,7 @@ int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
 	char *begin;
 	char *begin;
 	int size, orig_size;
 	int size, orig_size;
 
 
+	p_msg->add_to_branch_len = 0; /*bogdan*/
 	begin=p_msg->add_to_branch_s+p_msg->add_to_branch_len;
 	begin=p_msg->add_to_branch_s+p_msg->add_to_branch_len;
 	orig_size = size=MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len;
 	orig_size = size=MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len;
 
 
@@ -479,7 +480,7 @@ enum addifnew_status t_addifnew( struct sip_msg* p_msg )
 		if (parse_headers(p_msg, HDR_EOH )==-1)
 		if (parse_headers(p_msg, HDR_EOH )==-1)
 			return AIN_ERROR;
 			return AIN_ERROR;
 		lret = t_lookup_request( p_msg, 1 /* leave locked */ );
 		lret = t_lookup_request( p_msg, 1 /* leave locked */ );
-		if (lret==0) return AIN_ERROR;	
+		if (lret==0) return AIN_ERROR;
 		if (lret==-1) {
 		if (lret==-1) {
 			/* transaction not found, it's a new request */
 			/* transaction not found, it's a new request */
 			if ( p_msg->REQ_METHOD==METHOD_ACK ) {
 			if ( p_msg->REQ_METHOD==METHOD_ACK ) {
@@ -504,7 +505,7 @@ enum addifnew_status t_addifnew( struct sip_msg* p_msg )
 			if (p_msg->REQ_METHOD!=METHOD_ACK)
 			if (p_msg->REQ_METHOD!=METHOD_ACK)
 				return AIN_RETR;
 				return AIN_RETR;
 			else {
 			else {
-				if (T->inbound_request_isACKed)
+				if (T->uas.isACKed)
 					return AIN_RTRACK;
 					return AIN_RTRACK;
 				else
 				else
 					return AIN_OLDACK;
 					return AIN_OLDACK;

+ 112 - 134
modules/tm/t_reply.c

@@ -25,17 +25,16 @@ int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 	static char b[BUF_SIZE];
 	static char b[BUF_SIZE];
 	int len;
 	int len;
 
 
-	if (!T->outbound_response.bufflen)
+	if (!T->uas.response.buffer)
 		return 0;
 		return 0;
 
 
-	LOCK_REPLIES( T );
-	if ( (len=T->outbound_response.bufflen)==0 || len>BUF_SIZE ) {
+	if ( (len=T->uas.response.buffer_len)==0 || len>BUF_SIZE ) {
 		UNLOCK_REPLIES( T );
 		UNLOCK_REPLIES( T );
 		return -1;
 		return -1;
 	}
 	}
-	memcpy( b, T->outbound_response.retr_buffer, len );
+	memcpy( b, T->uas.response.buffer, len );
 	UNLOCK_REPLIES( T );
 	UNLOCK_REPLIES( T );
-	SEND_PR_BUFFER( & T->outbound_response, b, len );
+	SEND_PR_BUFFER( & T->uas.response, b, len );
 	return 1;
 	return 1;
 }
 }
 
 
@@ -46,14 +45,16 @@ int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 /* 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 error
   * returns 1 if everything was OK or -1 for error
   */
   */
-int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
+int t_send_reply( struct sip_msg* p_msg, unsigned int code, char * text,
+														unsigned int branch)
 {
 {
-	unsigned int len, buf_len;
+	unsigned int len, buf_len=0;
 	char * buf;
 	char * buf;
-	struct retrans_buff *rb;
+	struct retr_buf *rb;
+	int relay, save_clone;
 
 
-	buf = build_res_buf_from_sip_req(code,text,T->tag->s,T->tag->len,
-		T->inbound_request,&len);
+	buf = build_res_buf_from_sip_req(code,text,T->uas.tag->s,T->uas.tag->len,
+		T->uas.request,&len);
 	DBG("DEBUG: t_send_reply: buffer computed\n");
 	DBG("DEBUG: t_send_reply: buffer computed\n");
 	if (!buf)
 	if (!buf)
 	{
 	{
@@ -63,52 +64,51 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
 
 
 	LOCK_REPLIES( T );
 	LOCK_REPLIES( T );
 
 
-	rb = & T->outbound_response;
-	if (!rb->retr_buffer) {
-		/* initialize retransmission structure */
-		memset( rb , 0 , sizeof (struct retrans_buff) );
-		if (update_sock_struct_from_via(  &(rb->to),  p_msg->via1 )==-1)
+	relay = t_should_relay_response(T, (int)(code/100), branch, &save_clone);
+
+	if (save_clone)
+	{
+		T->uac[branch].status = code;
+	}
+
+	rb = & T->uas.response;
+	if (relay >=0 )
+	{
+		if (!rb->buffer) {
+			/* initialize retransmission structure */
+			if (update_sock_struct_from_via(  &(rb->to),  p_msg->via1 )==-1)
+			{
+				UNLOCK_REPLIES( T );
+				LOG(L_ERR,"ERROR: t_send_reply: cannot lookup reply dst: %s\n",
+					p_msg->via1->host.s );
+				goto error2;
+			}
+			rb->to.sin_family = AF_INET;
+			rb->activ_type = code;
+			buf_len = len + REPLY_OVERBUFFER_LEN;
+		}else{
+			buf_len = len;
+		}
+		/* puts the reply's buffer to uas.response */
+		if (! (rb->buffer = (char*)shm_resize( rb->buffer, buf_len )))
 		{
 		{
 			UNLOCK_REPLIES( T );
 			UNLOCK_REPLIES( T );
-			LOG(L_ERR, "ERROR: t_send_reply: cannot lookup reply dst: %s\n",
-				p_msg->via1->host.s );
+			LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n");
 			goto error2;
 			goto error2;
 		}
 		}
+		rb->buffer_len = len ;
+		memcpy( rb->buffer , buf , len );
+		T->uas.status = code;
+		/* needs to be protected too because what timers are set depends
+		   on current transactions status */
+		t_update_timers_after_sending_reply( rb );
+	} /* if realy */
 
 
-		rb->retr_timer.tg=TG_RT;
-		rb->fr_timer.tg=TG_FR;
-		rb->retr_timer.payload = rb;
-		rb->fr_timer.payload = rb;
-		rb->to.sin_family = AF_INET;
-		rb->my_T = T;
-		rb->status = code;
-	}
-
-	/* if this is a first reply (?100), longer replies will probably follow;
-	   try avoiding shm_resize by higher buffer size */
-	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
-
-	if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len )))
-	{
-		UNLOCK_REPLIES( T );
-		LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n");
-		goto error2;
-	}
-	rb->bufflen = len ;
-	memcpy( rb->retr_buffer , buf , len );
-	T->status = code;
-	/* needs to be protected too because what timers are set depends
-	   on current transactions status */
-	t_update_timers_after_sending_reply( rb );
 	UNLOCK_REPLIES( T );
 	UNLOCK_REPLIES( T );
 
 
-	SEND_PR_BUFFER( rb, buf, len );
-
+	if (relay>=0) SEND_PR_BUFFER( rb, buf, len );
 	pkg_free( buf ) ;
 	pkg_free( buf ) ;
-	/* start/stops the proper timers*/
-
 	DBG("DEBUG: t_send_reply: finished\n");
 	DBG("DEBUG: t_send_reply: finished\n");
-
 	return 1;
 	return 1;
 
 
 error2:
 error2:
@@ -192,15 +192,14 @@ int t_on_reply( struct sip_msg  *p_msg )
 {
 {
 	int branch, msg_status, msg_class, save_clone;
 	int branch, msg_status, msg_class, save_clone;
 	int local_cancel;
 	int local_cancel;
-	struct sip_msg *clone=0, *backup=0;
 	int relay;
 	int relay;
 	int start_fr = 0;
 	int start_fr = 0;
 	int is_invite;
 	int is_invite;
 	/* retransmission structure of outbound reply and request */
 	/* retransmission structure of outbound reply and request */
-	struct retrans_buff *orq_rb=0, *orp_rb=0, *ack_rb=0;
-	char *buf=0;
+	struct retr_buf *rb=0;
+	char *buf=0, *ack=0;
 	/* length of outbound reply */
 	/* length of outbound reply */
-	unsigned int orp_len;
+	unsigned int res_len, ack_len;
 	/* buffer length (might be somewhat larger than message size */
 	/* buffer length (might be somewhat larger than message size */
 	unsigned int alloc_len;
 	unsigned int alloc_len;
 
 
@@ -211,20 +210,15 @@ int t_on_reply( struct sip_msg  *p_msg )
 	/* ... 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;
 
 
-	/* by default, don't store incoming replies */
-	save_clone = 0;
+	DBG("DEBUG: t_on_reply: org. status uas=%d, uac[%d]=%d loca_cancel=%d)\n",
+		T->uas.status, branch, T->uac[branch].status, local_cancel);
 
 
-	backup = 0;
-
-	DBG("DEBUG: t_on_reply: Original status=%d (%d,%d)\n",
-		T->status,branch,local_cancel);
-
-	/* special cases (local cancel reply)*/
+	/* special cases (local cancel reply) -bogdan */
 	if (local_cancel==1)
 	if (local_cancel==1)
 	{
 	{
-		reset_timer( hash_table, &(T->outbound_cancel[branch]->retr_timer));
+		reset_timer( hash_table, &(T->uac[branch].request.retr_timer));
 		if ( p_msg->REPLY_STATUS>=200 )
 		if ( p_msg->REPLY_STATUS>=200 )
-			reset_timer( hash_table, &(T->outbound_cancel[branch]->fr_timer));
+			reset_timer(hash_table,&(T->uac[branch].request.fr_timer));
 		goto error;
 		goto error;
 	}
 	}
 
 
@@ -232,18 +226,12 @@ int t_on_reply( struct sip_msg  *p_msg )
 	if ((p_msg->via2==0) || (p_msg->via2->error!=VIA_PARSE_OK)){
 	if ((p_msg->via2==0) || (p_msg->via2->error!=VIA_PARSE_OK)){
 		/* no second via => error */
 		/* no second via => error */
 		LOG(L_ERR, "ERROR: t_on_reply: no 2nd via found in reply\n");
 		LOG(L_ERR, "ERROR: t_on_reply: no 2nd via found in reply\n");
-		goto error2;
-	}
-
-	/* it can take quite long - better do it now than later
-	inside a reply_lock */
-	/* CLONE alloc'ed */
-	if (!(clone=sip_msg_cloner( p_msg ))) {
 		goto error;
 		goto error;
 	}
 	}
+
 	msg_status=p_msg->REPLY_STATUS;
 	msg_status=p_msg->REPLY_STATUS;
 	msg_class=REPLY_CLASS(p_msg);
 	msg_class=REPLY_CLASS(p_msg);
-	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;
+	is_invite= T->uas.request->REQ_METHOD==METHOD_INVITE;
 
 
 	/*  generate the retrans buffer, make a simplified
 	/*  generate the retrans buffer, make a simplified
 	assumption everything but 100 will be fwd-ed;
 	assumption everything but 100 will be fwd-ed;
@@ -254,111 +242,104 @@ int t_on_reply( struct sip_msg  *p_msg )
 		buf=0;
 		buf=0;
 	else {
 	else {
 		/* buf maybe allo'ed*/
 		/* buf maybe allo'ed*/
-		buf = build_res_buf_from_sip_res ( p_msg, &orp_len);
+		buf = build_res_buf_from_sip_res ( p_msg, &res_len);
 		if (!buf) {
 		if (!buf) {
 			LOG(L_ERR, "ERROR: t_on_reply_received: "
 			LOG(L_ERR, "ERROR: t_on_reply_received: "
 			"no mem for outbound reply buffer\n");
 			"no mem for outbound reply buffer\n");
-			goto error1;
+			goto error;
 		}
 		}
 	}
 	}
 
 
 	/* *** stop timers *** */
 	/* *** stop timers *** */
-	orq_rb=T->outbound_request[branch];
 	/* stop retransmission */
 	/* stop retransmission */
-	reset_timer( hash_table, &(orq_rb->retr_timer));
+	reset_timer( hash_table, &(T->uac[branch].request.retr_timer));
 	/* stop final response timer only if I got a final response */
 	/* stop final response timer only if I got a final response */
 	if ( msg_class>1 )
 	if ( msg_class>1 )
-		reset_timer( hash_table, &(orq_rb->fr_timer));
+		reset_timer( hash_table, &(T->uac[branch].request.fr_timer));
 
 
 	LOCK_REPLIES( T );
 	LOCK_REPLIES( T );
 	/* if a got the first prov. response for an INVITE ->
 	/* if a got the first prov. response for an INVITE ->
 	   change FR_TIME_OUT to INV_FR_TIME_UT */
 	   change FR_TIME_OUT to INV_FR_TIME_UT */
-	start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite;
+	start_fr = !T->uac[branch].rpl_received && msg_class==1 && is_invite;
 
 
 	/* *** store and relay message as needed *** */
 	/* *** store and relay message as needed *** */
 	relay = t_should_relay_response( T , msg_status, branch, &save_clone );
 	relay = t_should_relay_response( T , msg_status, branch, &save_clone );
+
+	if (save_clone)
+	{
+		T->uac[branch].tag.s = shm_malloc( get_to(p_msg)->tag_value.len );
+		if (!T->uac[branch].tag.s)
+		{
+			LOG( L_ERR , "ERROR: t_on_reply: connot alocate memory!\n");
+			goto error1;
+		}
+		T->uac[branch].tag.len = get_to(p_msg)->tag_value.len;
+		memcpy( T->uac[branch].tag.s, get_to(p_msg)->tag_value.s,
+			T->uac[branch].tag.len );
+		T->uac[branch].rpl_received = 1;
+		T->uac[branch].status = msg_status;
+	}
+
+	rb = & T->uas.response;
 	if (relay >= 0 ) {
 	if (relay >= 0 ) {
-		orp_rb= & T->outbound_response;
 		/* if there is no reply yet, initialize the structure */
 		/* if there is no reply yet, initialize the structure */
-		if ( ! orp_rb->retr_buffer ) {
+		if ( ! rb->buffer ) {
 			/*init retrans buffer*/
 			/*init retrans buffer*/
-			memset( orp_rb , 0 , sizeof (struct retrans_buff) );
-			if (update_sock_struct_from_via( &(orp_rb->to),p_msg->via2 )==-1) {
+			if (update_sock_struct_from_via( &(rb->to),p_msg->via2 )==-1) {
 				UNLOCK_REPLIES( T );
 				UNLOCK_REPLIES( T );
 				start_fr = 1;
 				start_fr = 1;
-				LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: "
-					"cannot lookup reply dst: %s\n",
-				p_msg->via2->host.s );
-				save_clone = 0;
-				goto error2;
+				LOG(L_ERR, "ERROR: t_on_reply: cannot lookup reply dst: %s\n",
+					p_msg->via2->host.s );
+				goto error1;
 			}
 			}
-			orp_rb->retr_timer.tg=TG_RT;
-			orp_rb->fr_timer.tg=TG_FR;
-			orp_rb->retr_timer.payload = orp_rb;
-			orp_rb->fr_timer.payload =  orp_rb;
-			orp_rb->to.sin_family = AF_INET;
-			orp_rb->my_T = T;
-			orp_rb->status = p_msg->REPLY_STATUS;
+			rb->to.sin_family = AF_INET;
+			rb->activ_type = p_msg->REPLY_STATUS;
 			/* allocate something more for the first message;
 			/* allocate something more for the first message;
 			   subsequent messages will be longer and buffer
 			   subsequent messages will be longer and buffer
 			   reusing will save us a malloc lock */
 			   reusing will save us a malloc lock */
-			alloc_len = orp_len + REPLY_OVERBUFFER_LEN ;
+			alloc_len = res_len + REPLY_OVERBUFFER_LEN ;
 		} else {
 		} else {
-			alloc_len = orp_len;
+			alloc_len = res_len;
 		}
 		}
-
-		if (! (orp_rb->retr_buffer = (char *)
-		shm_resize( orp_rb->retr_buffer, alloc_len ))) {
+		/* puts the reply's buffer to uas.response */
+		if (! (rb->buffer = (char *)shm_resize( rb->buffer, alloc_len ))) {
 			UNLOCK_REPLIES( T );
 			UNLOCK_REPLIES( T );
 			start_fr = 1;
 			start_fr = 1;
-			save_clone = 0;
 			LOG(L_ERR, "ERROR: t_on_reply: cannot alloc shmem\n");
 			LOG(L_ERR, "ERROR: t_on_reply: cannot alloc shmem\n");
-			goto error2;
+			goto error1;
 		};
 		};
-
-		orp_rb->bufflen=orp_len;
-		memcpy( orp_rb->retr_buffer, buf, orp_len );
-
+		rb->buffer_len = res_len;
+		memcpy( rb->buffer, buf, res_len );
 		/* update the status ... */
 		/* update the status ... */
-		if ((T->status = p_msg->REPLY_STATUS) >=200 &&
-		/* ... and dst for a possible ACK if we are sending final downstream */
-			T->relaied_reply_branch==-1 ) {
-				memcpy( & T->ack_to, & T->outbound_request[ branch ]->to,
-				sizeof( struct sockaddr_in ) );
-   				T->relaied_reply_branch = branch;
-		}
-
-
+		T->uas.status = p_msg->REPLY_STATUS;
+		T->uas.tag=&(T->uac[branch].tag);
+		if (T->uas.status >=200 && T->relaied_reply_branch==-1 )
+				T->relaied_reply_branch = branch;
 	}; /* if relay ... */
 	}; /* if relay ... */
 
 
-	if (save_clone) {
-		backup = T->inbound_response[branch];
-		T->inbound_response[branch]=clone;
-		T->tag=&(get_to(clone)->tag_value);
-	}
-
 	UNLOCK_REPLIES( T );
 	UNLOCK_REPLIES( T );
+
 	if (relay >= 0) {
 	if (relay >= 0) {
-		SEND_PR_BUFFER( orp_rb, buf, orp_len );
-		t_update_timers_after_sending_reply( orp_rb );
+		SEND_PR_BUFFER( rb, buf, res_len );
+		t_update_timers_after_sending_reply( rb );
 	}
 	}
 
 
 	/* *** ACK handling *** */
 	/* *** ACK handling *** */
 	if ( is_invite ) {
 	if ( is_invite ) {
-		if ( T->outbound_ack[branch] )
+		if ( T->uac[branch].request.ack_len )
 		{   /*retransmit*/
 		{   /*retransmit*/
 			/* I don't need any additional syncing here -- after ack
 			/* I don't need any additional syncing here -- after ack
 			   is introduced it's never changed */
 			   is introduced it's never changed */
-			SEND_BUFFER( T->outbound_ack[branch] );
+			SEND_ACK_BUFFER( &(T->uac[branch].request) );
 		} else if (msg_class>2 ) {
 		} else if (msg_class>2 ) {
 			/*on a non-200 reply to INVITE*/
 			/*on a non-200 reply to INVITE*/
 			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"
 			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"
 				"send ACK\n");
 				"send ACK\n");
-			ack_rb = build_ack( p_msg, T, branch );
-			if (ack_rb) {
-				SEND_BUFFER( ack_rb );
+			ack = build_ack( p_msg, T, branch , &ack_len);
+			if (ack) {
+				SEND_PR_BUFFER( &(T->uac[branch].request), ack, ack_len );
 				/* append to transaction structure */
 				/* append to transaction structure */
-				attach_ack( T, branch, ack_rb );
+				attach_ack( T, branch, ack , ack_len );
 			} else {
 			} else {
 				/* restart FR */
 				/* restart FR */
 				start_fr=1;
 				start_fr=1;
@@ -367,20 +348,17 @@ int t_on_reply( struct sip_msg  *p_msg )
 		}
 		}
 	} /* is_invite */
 	} /* is_invite */
 
 
-	/* restart retransmission if a provisional response came for 
+	/* restart retransmission if a provisional response came for
 	   a non_INVITE -> retrasmit at RT_T2*/
 	   a non_INVITE -> retrasmit at RT_T2*/
 	if ( msg_class==1 && !is_invite )
 	if ( msg_class==1 && !is_invite )
 	{
 	{
-		orq_rb->retr_list = RT_T2;
-		set_timer( hash_table, &(orq_rb->retr_timer), RT_T2 );
+		rb->retr_list = RT_T2;
+		set_timer( hash_table, &(rb->retr_timer), RT_T2 );
 	}
 	}
-	if (backup) sip_msg_free( backup );
-error2:
-	if (start_fr) 
-		set_timer( hash_table, &(orq_rb->fr_timer), FR_INV_TIMER_LIST );
-	if (buf) pkg_free( buf );
 error1:
 error1:
-	if (!save_clone) sip_msg_free( clone );
+	if (start_fr)
+		set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST );
+	if (buf) pkg_free( buf );
 error:
 error:
 	T_UNREF( T );
 	T_UNREF( T );
 	/* don't try to relay statelessly on error; on troubles, simply do nothing;
 	/* don't try to relay statelessly on error; on troubles, simply do nothing;

+ 0 - 1
modules/tm/timer.c

@@ -70,7 +70,6 @@ void remove_timer_unsafe(  struct timer_link* tl )
 		abort();
 		abort();
 	};
 	};
 #endif
 #endif
-
 	if (is_in_timer_list2( tl )) {
 	if (is_in_timer_list2( tl )) {
 		tl->prev_tl->next_tl = tl->next_tl;
 		tl->prev_tl->next_tl = tl->next_tl;
 		tl->next_tl->prev_tl = tl->prev_tl;
 		tl->next_tl->prev_tl = tl->prev_tl;

+ 63 - 56
modules/tm/tm.c

@@ -20,23 +20,23 @@
 
 
 
 
 
 
-/*static int test_f(struct sip_msg*, char*,char*);*/
 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);
 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);
 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);
 static int fixup_t_forward(void** param, int param_no);
 static int fixup_t_forward(void** param, int param_no);
-//static int fixup_t_forward_def(void** param, int param_no);
 static int fixup_t_send_reply(void** param, int param_no);
 static int fixup_t_send_reply(void** param, int param_no);
 static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar );
 static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar );
 static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
 static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
-static int w_t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar );
-
-static int t_relay_to( struct sip_msg  *p_msg ,  char *str_ip , char *str_port  );
+static int w_t_add_transaction(struct sip_msg* p_msg, char* foo, char* bar );
+static int t_relay_to( struct sip_msg *p_msg, char *str_ip, char *str_port);
 static int t_relay( struct sip_msg  *p_msg ,  char* foo, char* bar  );
 static int t_relay( struct sip_msg  *p_msg ,  char* foo, char* bar  );
 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);
 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);
+static int w_t_add_fork(struct sip_msg* msg, char* str, char* str2);
+static int w_t_clear_forks(struct sip_msg* msg, char* str, char* str2);
 static void w_onbreak(struct sip_msg* msg) { t_unref(); }
 static void w_onbreak(struct sip_msg* msg) { t_unref(); }
 
 
+
 static struct module_exports nm_exports= {
 static struct module_exports nm_exports= {
 	"tm_module",
 	"tm_module",
 	(char*[]){			
 	(char*[]){			
@@ -49,7 +49,9 @@ static struct module_exports nm_exports= {
 				"t_relay_to",
 				"t_relay_to",
 				"t_relay",
 				"t_relay",
 				"t_forward_nonack",
 				"t_forward_nonack",
-				"t_forward_ack"
+				"t_forward_ack",
+				"t_fork_to",
+				"t_clear_forks"
 			},
 			},
 	(cmd_function[]){
 	(cmd_function[]){
 					w_t_add_transaction,
 					w_t_add_transaction,
@@ -61,7 +63,9 @@ static struct module_exports nm_exports= {
 					t_relay_to,
 					t_relay_to,
 					t_relay,
 					t_relay,
 					w_t_forward_nonack,
 					w_t_forward_nonack,
-					w_t_forward_ack
+					w_t_forward_ack,
+					w_t_add_fork,
+					w_t_clear_forks
 					},
 					},
 	(int[]){
 	(int[]){
 				0, /* t_add_transaction */
 				0, /* t_add_transaction */
@@ -73,7 +77,9 @@ static struct module_exports nm_exports= {
 				2, /* t_relay_to */
 				2, /* t_relay_to */
 				0, /* t_relay */
 				0, /* t_relay */
 				2, /* t_forward_nonack */
 				2, /* t_forward_nonack */
-				2  /* t_forward_ack */
+				2, /* t_forward_ack */
+				2, /* t_fork_to */
+				0  /* t_clear_forks */
 			},
 			},
 	(fixup_function[]){
 	(fixup_function[]){
 				0,						/* t_add_transaction */
 				0,						/* t_add_transaction */
@@ -84,10 +90,12 @@ static struct module_exports nm_exports= {
 				0,						/* t_unref */
 				0,						/* t_unref */
 				fixup_t_forward,		/* t_relay_to */
 				fixup_t_forward,		/* t_relay_to */
 				0,						/* t_relay */
 				0,						/* t_relay */
-				fixup_t_forward, 		/* t_forward_nonack */
-				fixup_t_forward 		/* t_forward_ack */
+				fixup_t_forward,		/* t_forward_nonack */
+				fixup_t_forward,		/* t_forward_ack */
+				fixup_t_forward,		/* t_fork_to */
+				0						/* t_clear_forks */
 		},
 		},
-	10,
+	12,
 	(response_function) t_on_reply,
 	(response_function) t_on_reply,
 	(destroy_function) tm_shutdown,
 	(destroy_function) tm_shutdown,
 	w_onbreak,
 	w_onbreak,
@@ -110,6 +118,7 @@ struct module_exports* mod_register()
 
 
 
 
 
 
+
 static int fixup_t_forward(void** param, int param_no)
 static int fixup_t_forward(void** param, int param_no)
 {
 {
 	char* name;
 	char* name;
@@ -159,43 +168,6 @@ static int fixup_t_forward(void** param, int param_no)
 }
 }
 
 
 
 
-/*
-static int fixup_t_forward_def(void** param, int param_no)
-{
-	char* name;
-	struct hostent* he;
-	int err;
-#ifdef DNS_IP_HACK
-	unsigned int ip;
-	int len;
-#endif
-
-	DBG("TM module: fixup_t_forward_def(%s, %d)\n", (char*)*param, param_no);
-	if (param_no==1){
-		name=*param;
-#ifdef DNS_IP_HACK
-		len=strlen(name);
-		ip=str2ip(name, len, &err);
-		if (err==0){
-			goto copy;
-		}
-#endif
-		/ fail over to normal lookup /
-		he=gethostbyname(name);
-		if (he==0){
-			LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
-						" \"%s\"\n", name);
-			return E_BAD_ADDRESS;
-		}
-		memcpy(&ip, he->h_addr_list[0], sizeof(unsigned int));
-	copy:
-		free(*param);
-		*param=(void*)ip;
-		return 0;
-	}
-	return 0;
-}
-*/
 
 
 
 
 static int fixup_t_send_reply(void** param, int param_no)
 static int fixup_t_send_reply(void** param, int param_no)
@@ -221,25 +193,33 @@ 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 , 0 ) ? 1 : -1;
 	return t_check( msg , 0 , 0 ) ? 1 : -1;
 }
 }
 
 
+
+
+
 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 , 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 \n");
 		return -1;
 		return -1;
 	}
 	}
 	return t_forward_ack(msg, (unsigned int) str, (unsigned int) str2);
 	return t_forward_ack(msg, (unsigned int) str, (unsigned int) 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 , 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\n");
 		return -1;
 		return -1;
 	}
 	}
 	return t_forward_nonack(msg, (unsigned int) str, (unsigned int) str2);
 	return t_forward_nonack(msg, (unsigned int) str, (unsigned int) str2);
@@ -255,9 +235,12 @@ static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 			"for which no T-state has been established\n");
 			"for which no T-state has been established\n");
 		return -1;
 		return -1;
 	}
 	}
-	return t_send_reply(msg, (unsigned int) str, str2);
+	return t_send_reply(msg, (unsigned int) str, str2, 0);
 }
 }
 
 
+
+
+
 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 , 0 )==-1) return 1;
 	if (t_check( msg  , 0 , 0 )==-1) return 1;
@@ -267,6 +250,8 @@ static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 }
 }
 
 
 
 
+
+
 static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 {
 {
 	if (T==T_UNDEFINED || T==T_NULL)
 	if (T==T_UNDEFINED || T==T_NULL)
@@ -274,6 +259,9 @@ static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
     return t_unref( /* p_msg */ );
     return t_unref( /* p_msg */ );
 }
 }
 
 
+
+
+
 static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
 static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
 {
 {
 	if (t_check( p_msg  , 0 , 0 )==-1) 
 	if (t_check( p_msg  , 0 , 0 )==-1) 
@@ -285,6 +273,9 @@ static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
 	return 1;
 	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 , 0 )==-1) return -1;
 	if (t_check( p_msg , 0 , 0 )==-1) return -1;
 	if (T) {
 	if (T) {
@@ -296,6 +287,23 @@ static int w_t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar ) {
 
 
 
 
 
 
+
+static int w_t_add_fork(struct sip_msg* msg, char* str, char* str2)
+{
+	return t_add_fork((unsigned int)str, (unsigned int)str2);
+}
+
+
+
+
+static int w_t_clear_forks(struct sip_msg* msg, char* str, char* str2)
+{
+	return t_clear_forks();
+}
+
+
+
+
 static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 {
 {
 	struct proxy_l *proxy;
 	struct proxy_l *proxy;
@@ -323,14 +331,14 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 				if ( p_msg->REQ_METHOD==METHOD_CANCEL)
 				if ( p_msg->REQ_METHOD==METHOD_CANCEL)
 				{
 				{
 					DBG( "SER: new CANCEL\n");
 					DBG( "SER: new CANCEL\n");
-					if ( !t_send_reply( p_msg , 200, "glad to cancel") )
+					if ( !t_send_reply( p_msg , 200, "glad to cancel", 0) )
 						DBG( "SER:ERROR: t_send_reply\n");
 						DBG( "SER:ERROR: t_send_reply\n");
 				} else if (p_msg->REQ_METHOD==METHOD_INVITE)
 				} else if (p_msg->REQ_METHOD==METHOD_INVITE)
 				{
 				{
 					DBG( "SER: new INVITE\n");
 					DBG( "SER: new INVITE\n");
 					if (!t_send_reply( p_msg , 100 ,
 					if (!t_send_reply( p_msg , 100 ,
-					"trying -- your call is important to us"))
-						LOG( L_CRIT,"SER: ERROR: t_send_reply (100)\n");
+					"trying -- your call is important to us",0))
+						DBG("SER: ERROR: t_send_reply (100)\n");
 				} else {
 				} else {
 					DBG( "SER: new transaction\n");
 					DBG( "SER: new transaction\n");
 				}
 				}
@@ -359,8 +367,7 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 				DBG( "SER: WARNING: bad ACK forward\n");
 				DBG( "SER: WARNING: bad ACK forward\n");
 			ret = 1;
 			ret = 1;
 			break;
 			break;
-		case AIN_RTRACK:
-			DBG("SER: ACK retransmission detected: drop ACK!\n");
+		case AIN_RTRACK:	/* ACK retransmission */
 			ret = 1;
 			ret = 1;
 			break;
 			break;
 		default:
 		default:

+ 1 - 6
msg_translator.c

@@ -170,11 +170,9 @@ char* via_builder( struct sip_msg *msg , unsigned int *len )
 		via_len+=MY_BRANCH_LEN;
 		via_len+=MY_BRANCH_LEN;
 		/* loop checks ?
 		/* loop checks ?
 		if (loop_checks) {
 		if (loop_checks) {
-
 			if (check_transaction_quadruple( msg )) {
 			if (check_transaction_quadruple( msg )) {
 				str src[5];
 				str src[5];
 				int r;
 				int r;
-
 				src[0]= msg->from->body;
 				src[0]= msg->from->body;
 				src[1]= msg->to->body;
 				src[1]= msg->to->body;
 				src[2]= msg->callid->body;
 				src[2]= msg->callid->body;
@@ -182,11 +180,9 @@ char* via_builder( struct sip_msg *msg , unsigned int *len )
 				src[4]= get_cseq( msg )->number;
 				src[4]= get_cseq( msg )->number;
 				MDStringArray ( line_buf+via_len-1, src, 5 );
 				MDStringArray ( line_buf+via_len-1, src, 5 );
 				via_len+=MD5_LEN - 1;
 				via_len+=MD5_LEN - 1;
-
 			} else DBG("DEBUG: via_builder: required HFs for "
 			} else DBG("DEBUG: via_builder: required HFs for "
 					"loop checking missing\n");
 					"loop checking missing\n");
 		}  */
 		}  */
-		//DBG("DEBUG: XXX will add branch now: %s (%d)\n", msg->add_to_branch_s, msg->add_to_branch_len );
 		/* someone wants me to add something to branch here ? */
 		/* someone wants me to add something to branch here ? */
 		if ( msg->add_to_branch_len ){
 		if ( msg->add_to_branch_len ){
 			memcpy(line_buf+via_len-1, msg->add_to_branch_s,
 			memcpy(line_buf+via_len-1, msg->add_to_branch_s,
@@ -329,7 +325,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 
 
 	/* add via header to the list */
 	/* add via header to the list */
 	/* try to add it before msg. 1st via */
 	/* try to add it before msg. 1st via */
-	/*add first via, as an anchor for second via*/
+	/* add first via, as an anchor for second via*/
 	anchor=anchor_lump(&(msg->add_rm), msg->via1->hdr.s-buf, 0, HDR_VIA);
 	anchor=anchor_lump(&(msg->add_rm), msg->via1->hdr.s-buf, 0, HDR_VIA);
 	if (anchor==0) goto error;
 	if (anchor==0) goto error;
 	if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0)
 	if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0)
@@ -450,7 +446,6 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 							/* only ADD allowed for before/after */
 							/* only ADD allowed for before/after */
 							LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
 							LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
 									"invalid op for data lump (%x)\n", r->op);
 									"invalid op for data lump (%x)\n", r->op);
-
 					}
 					}
 				}
 				}
 				/* copy "main" part */
 				/* copy "main" part */

+ 40 - 35
test/th-uri.cfg

@@ -5,17 +5,17 @@
 #
 #
 
 
 
 
-debug=3          # debug level (cmd line: -dddddddddd)
+debug=9          # debug level (cmd line: -dddddddddd)
 #fork=yes          # (cmd. line: -D)
 #fork=yes          # (cmd. line: -D)
 fork=no
 fork=no
-log_stderror=yes # (cmd line: -E)
-#log_stderror=no	# (cmd line: -E)
+log_stderror=yes  # (cmd line: -E)
+#log_stderror=no   # (cmd line: -E)
 
 
 
 
-children=8
-check_via=no     # (cmd. line: -v)
+children=4
+check_via=no      # (cmd. line: -v)
 dns=off           # (cmd. line: -r)
 dns=off           # (cmd. line: -r)
-rev_dns=off      # (cmd. line: -R)
+rev_dns=off       # (cmd. line: -R)
 #port=5070
 #port=5070
 #listen=10.0.0.179
 #listen=10.0.0.179
 #listen=192.168.57.33
 #listen=192.168.57.33
@@ -33,35 +33,40 @@ loadmodule "modules/sl/sl.so"
 
 
 
 
 route{
 route{
-             sl_filter_ACK();
+	sl_filter_ACK();
 
 
-             if ( !mf_process_maxfwd_header("10") )
-             {
-                     sl_send_reply("483","To Many Hops");
-                     drop();
-             };
+	if ( !mf_process_maxfwd_header("10") )
+	{
+		sl_send_reply("483","To Many Hops");
+		drop();
+	};
 
 
-             /*
-             if (method=="INVITE")
-             {
-                log("SER : runing CPL!! :)\n");
-                if ( !cpl_run_script() )
-                {
-                   log("SER : Error during running CPL script!\n");
-                }else{
-                   if ( cpl_is_response_reject() )
-                   {
-                       sl_send_reply("603","I am not available!");
-                       drop();
-                   }else if ( cpl_is_response_redirect() ) {
-                       log("SER : redirect\n");
-                       cpl_update_contact();
-                       sl_send_reply("302","Moved temporarily");
-                       drop();
-                   };
-                };
-             }; */
-
-
-             t_relay();
+/*
+	if (method=="INVITE")
+	{
+		log("SER : runing CPL!! :)\n");
+		if ( !cpl_run_script() )
+		{
+			log("SER : Error during running CPL script!\n");
+		}else{
+			if ( cpl_is_response_reject() ) {
+				sl_send_reply("603","I am not available!");
+				drop();
+			}else if ( cpl_is_response_redirect() ) {
+				log("SER : redirect\n");
+				cpl_update_contact();
+				sl_send_reply("302","Moved temporarily");
+				drop();
+			};
+		};
+	};
+*/
+	t_clear_forks();
+	if (method=="INVITE")
+	{
+		#t_fork_to("195.37.78.143","5060");
+		t_fork_to("195.37.78.246","5060");
+	};
+	
+	t_relay();
 }
 }