Jelajahi Sumber

script hardwired and ACK maching fixed

Bogdan-Andrei Iancu 24 tahun lalu
induk
melakukan
baa4fa73e4
7 mengubah file dengan 359 tambahan dan 142 penghapusan
  1. 188 91
      modules/tm/t_funcs.c
  2. 22 0
      modules/tm/t_funcs.h
  3. 71 33
      modules/tm/t_lookup.c
  4. 24 4
      modules/tm/tm.c
  5. 42 3
      proxy.c
  6. 1 0
      proxy.h
  7. 11 11
      test/tx.cfg

+ 188 - 91
modules/tm/t_funcs.c

@@ -18,8 +18,9 @@ struct s_table*  hash_table;
 
 
 
+
 /* determine timer length and put on a correct timer list */
-static inline void set_timer( struct s_table *hash_table, 
+static inline void set_timer( struct s_table *hash_table,
 	struct timer_link *new_tl, enum lists list_id )
 {
 	unsigned int timeout;
@@ -35,7 +36,7 @@ static inline void set_timer( struct s_table *hash_table,
 		return;
 	}
 	timeout = to_table[ list_id ];
-	add_to_tail_of_timer_list( &(hash_table->timers[ list_id ]), 
+	add_to_tail_of_timer_list( &(hash_table->timers[ list_id ]),
 		new_tl,get_ticks()+timeout);
 }
 
@@ -209,14 +210,14 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		return -1;
 	}
 
-	/*if it's an ACK and the status is not final or is final, but error the 
-     ACK is not forwarded*/
+	/*if it's an ACK and the status is not final or is final, but error the
+	ACK is not forwarded*/
 	if ( p_msg->REQ_METHOD==METHOD_ACK  && (T->status/100)!=2 ) {
 		DBG("DEBUG: t_forward: local ACK; don't forward\n");
 		return 1;
 	}
 
-	/* if it's forwarded for the first time ; else the request is retransmited 
+	/* if it's forwarded for the first time ; else the request is retransmited
 	 * from the transaction buffer
 	 * when forwarding an ACK, this condition will br all the time false because
 	 * the forwarded INVITE is in the retransmission buffer */
@@ -227,7 +228,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
 		{
 			DBG("DEBUG: t_forward: it's CANCEL\n");
-			/* find original cancelled transaction; if found, use its 
+			/* 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 );
@@ -267,7 +268,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		/* allocates a new retrans_buff for the outbound request */
 		DBG("DEBUG: t_forward: building outbound request\n");
 		shm_lock();
-		T->outbound_request[branch] = rb = 
+		T->outbound_request[branch] = rb =
 			(struct retrans_buff*)shm_malloc_unsafe( sizeof(struct retrans_buff)  );
 		if (!rb)
 		{
@@ -277,7 +278,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 		}
 		shbuf = (char *) shm_malloc_unsafe( len );
 		if (!shbuf)
-		{ 
+		{
 			LOG(L_ERR, "ERROR: t_forward: out of shmem buffer\n");
 			shm_unlock();
 			goto error;
@@ -305,11 +306,11 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
 
 	/* if we are forwarding an ACK*/
 	if (  p_msg->REQ_METHOD==METHOD_ACK &&
-		T->relaied_reply_branch>=0 && 
+		T->relaied_reply_branch>=0 &&
 		T->relaied_reply_branch<=T->nr_of_outgoings)
 	{
 		DBG("DEBUG: t_forward: forwarding ACK [%d]\n",T->relaied_reply_branch);
-		t_build_and_send_ACK( T, branch , 
+		t_build_and_send_ACK( T, branch ,
 			T->inbound_response[T->relaied_reply_branch] );
 		T->inbound_request_isACKed = 1;
 		return 1;
@@ -356,60 +357,13 @@ error:
  */
 int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
 {
-   struct hostent  *nhost;
    unsigned int     ip, port;
-   struct sip_uri    parsed_uri;
-   str                      uri;
-   int                      err;
-
-   /* it's about the same transaction or not? */
-	if (t_check( p_msg  , 0 )==-1) return -1;
-
-   /*if T hasn't been found after all -> return not found (error) */
-   if ( !T )
-   {
-      DBG("DEBUG: t_forward_uri: no transaction found in order  to forward the request\n");
-      return -1;
-   }
-
-   /* the original uri has been changed? */
-   if (p_msg->new_uri.s==0 || p_msg->new_uri.len==0)
-     uri = p_msg->first_line.u.request.uri;
-   else
-     uri = p_msg->new_uri;
-
-   /* parsing the request uri in order to get host and port */
-   if (parse_uri( uri.s , uri.len , &parsed_uri )<0)
-   {
-        LOG(L_ERR, "ERROR: t_forward_uri: unable to parse destination uri\n");
-        return  -1;
-   }
-
-   /* getting host address*/
-   nhost = gethostbyname( parsed_uri.host.s ); 
 
-   if ( !nhost )
+   if ( get_ip_and_port_from_uri( p_msg , &ip, &port)<0 )
    {
-      LOG(L_ERR, "ERROR: t_forward_uri: cannot resolve host\n");
+      LOG( L_ERR , "ERROR: t_forward_uri: unable to extarct ip and port from uri!\n" );
       return -1;
    }
-   memcpy(&ip, nhost->h_addr_list[0], sizeof(unsigned int));
-
-   /* getting the port */
-   if ( parsed_uri.port.s==0 || parsed_uri.port.len==0 )
-      port = SIP_PORT;
-   else
-   {
-       port = str2s( parsed_uri.port.s , parsed_uri.port.len , &err );
-       if ( err<0 )
-       {
-           LOG(L_ERR, "ERROR: t_forward_uri: converting port from str to int failed; using default SIP port\n");
-           port = SIP_PORT;
-       }
-   }
-   port = htons( port );
-
-   free_uri( &parsed_uri );
 
    return t_forward( p_msg , ip , port );
 }
@@ -445,7 +399,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 
 	/* we were not able to process the response due to memory
 	   shortage; simply drop it; hopefuly, we will have more
-           memory on the next try 
+           memory on the next try
 	*/
 	msg_status=p_msg->REPLY_STATUS;
 	msg_class=REPLY_CLASS(p_msg);
@@ -464,7 +418,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 	/* stop final response timer only if I got a final response */
 	if ( msg_class>1 )
 		reset_timer( hash_table, &(rb->fr_timer));
-   	/* 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 */
 	if (!T->inbound_response[branch] && msg_class==1
 	 && T->inbound_request->REQ_METHOD==METHOD_INVITE )
@@ -500,7 +454,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 		return 0;
 	}
 
-   	/* restart retransmission if provisional response came for a non_INVITE -> 
+   	/* restart retransmission if provisional response came for a non_INVITE ->
 		retrasmit at RT_T2*/
 	if ( msg_class==1 && T->inbound_request->REQ_METHOD!=METHOD_INVITE )
 	{
@@ -520,7 +474,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
 		if ( t_all_final(T) && relay_lowest_reply_upstream( T , p_msg )==-1 && clone )
 			goto error;
 	} else {
-		if (push_reply_from_uac_to_uas( T , branch )==-1 && clone ) 
+		if (push_reply_from_uac_to_uas( T , branch )==-1 && clone )
 			goto error;
    	}
 
@@ -539,6 +493,87 @@ error:
 }
 
 
+int t_on_request_received( struct sip_msg  *p_msg , unsigned int ip , unsigned int port)
+{
+	if ( t_check( p_msg , 0 ) )
+	{
+		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
+		{
+			LOG( L_INFO , "SER: ACK received -> t_release\n");
+			if ( !t_forward( p_msg , ip , port ) )
+			{
+				LOG( L_WARN, "SER: WARNING: bad forward\n");
+			}
+			if ( !t_release_transaction( p_msg ) )
+			{
+				LOG( L_WARN ,"SER: WARNING: bad t_release\n");
+			}
+		}
+		else
+		{
+			if ( !t_retransmit_reply( p_msg , 0, 0) )
+			{
+				LOG( L_WARN, "SER: WARNING: bad t_retransmit_reply\n");
+			}
+			LOG( L_INFO, "SER: yet another annoying retranmission\n");
+		}
+		t_unref( p_msg,0,0 );
+	} else {
+		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
+		{
+			LOG( L_INFO , "SER: forwarding ACK  statelessly\n");
+			/* no established transaction ... forward ACK just statelessly*/
+			forward_request( p_msg , mk_proxy_from_ip(ip,port) );
+		}
+		else
+		{
+			/* establish transaction*/
+			if ( !t_add_transaction(p_msg,0,0) )
+			{
+				LOG( L_ERR , "ERROR in ser: t_add_transaction\n");
+			}
+			/* reply */
+			if ( p_msg->first_line.u.request.method_value==METHOD_CANCEL)
+			{
+				LOG( L_INFO, "SER: new CANCEL\n");
+				if ( !t_send_reply( p_msg , 200, "glad to cancel") )
+				{
+					LOG( L_ERR ,"SER:ERROR: t_send_reply\n");
+				}
+			} else {
+				LOG( L_INFO, "SER: new transaction\n");
+				if ( !t_send_reply( p_msg , 100 , "trying -- your call is important to us") )
+				{
+					LOG( L_ERR, "SER: ERROR: t_send_reply (100)\n");
+				}
+			}
+			if ( !t_forward( p_msg, ip, port ) )
+			{
+				LOG( L_ERR , "SER:ERROR: t_forward \n");
+			}
+			t_unref( p_msg , 0 , 0);
+		}
+	}
+
+}
+
+
+
+
+int t_on_request_received_uri( struct sip_msg  *p_msg )
+{
+   unsigned int     ip, port;
+
+   if ( get_ip_and_port_from_uri( p_msg , &ip, &port)<0 )
+   {
+      LOG( L_ERR , "ERROR: t_on_request_received_uri: unable to extract ip and port from uri!\n" );
+      return -1;
+   }
+
+   return t_on_request_received( p_msg , ip , port );
+}
+
+
 
 
 /*   returns 1 if everything was OK or -1 for error
@@ -578,6 +613,9 @@ int t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
    return -1;
 }
 
+
+
+
 int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 {
 	if (T==T_UNDEFINED || T==T_NULL)
@@ -688,7 +726,7 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
 	if ( ! rb->retr_buffer ) {
 		/*init retrans buffer*/
 		memset( rb , 0 , sizeof (struct retrans_buff) );
-		if (update_sock_struct_from_via(  &(rb->to),  
+		if (update_sock_struct_from_via(  &(rb->to),
 			trans->inbound_response[branch]->via2 )==-1) {
 				LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: "
 					"cannot lookup reply dst: %s\n",
@@ -714,8 +752,7 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
 	}
 
 	/* if this is a first reply (?100), longer replies will probably follow;
-       try avoiding shm_resize by higher buffer size
-    */
+	try avoiding shm_resize by higher buffer size */
 	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
 	if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len )))
 	{
@@ -723,22 +760,22 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
 		goto error1;
 	}
 	rb->bufflen = len ;
-   	memcpy( rb->retr_buffer , buf , len );
-   	free( buf ) ;
+	memcpy( rb->retr_buffer , buf , len );
+	free( buf ) ;
 
-   	/* update the status*/
-   	trans->status = trans->inbound_response[branch]->REPLY_STATUS;
-   	if ( trans->inbound_response[branch]->REPLY_STATUS>=200 &&
-         trans->relaied_reply_branch==-1 )
-       		trans->relaied_reply_branch = branch;
+	/* update the status*/
+	trans->status = trans->inbound_response[branch]->REPLY_STATUS;
+	if ( trans->inbound_response[branch]->REPLY_STATUS>=200 &&
+	trans->relaied_reply_branch==-1 )
+		trans->relaied_reply_branch = branch;
 
 	/* start/stops the proper timers*/
 	t_update_timers_after_sending_reply( rb );
 
-   	/*send the reply*/
-   	/* t_retransmit_reply( trans->inbound_response[branch], 0 , 0 ); */
+	/*send the reply*/
+	/* t_retransmit_reply( trans->inbound_response[branch], 0 , 0 ); */
 	SEND_BUFFER( rb );
-   	return 1;
+	return 1;
 
 error1:
 	free( buf );
@@ -763,13 +800,13 @@ int t_all_final( struct cell *Trans )
 {
    unsigned int i;
 
-   for( i=0 ; i<Trans->nr_of_outgoings ; i++  )
-      if (  !Trans->inbound_response[i] ||  
-			Trans->inbound_response[i]->REPLY_STATUS<=200 )
-         return 0;
+	for( i=0 ; i<Trans->nr_of_outgoings ; i++  )
+		if (  !Trans->inbound_response[i] ||
+		Trans->inbound_response[i]->REPLY_STATUS<=200 )
+			return 0;
 
-  DBG("DEBUG: t_all_final: final state!!!!:)) \n");
-  return 1;
+	DBG("DEBUG: t_all_final: final state!!!!:)) \n");
+	return 1;
 }
 
 
@@ -810,7 +847,7 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 {
 	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 */
 	if (Trans->status>=300 && Trans->inbound_request->REQ_METHOD==METHOD_INVITE )
 	{
@@ -819,13 +856,13 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 		set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST );
    	} else if ( Trans->inbound_request->REQ_METHOD==METHOD_CANCEL ) {
 		if ( Trans->T_canceled==T_UNDEFINED )
-			Trans->T_canceled = t_lookupOriginalT( hash_table , 
+			Trans->T_canceled = t_lookupOriginalT( hash_table ,
 				Trans->inbound_request );
       		if ( Trans->T_canceled==T_NULL )
             		return 1;
       		Trans->T_canceled->T_canceler = Trans;
      		/* 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)
             		t_put_on_wait( Trans );
@@ -837,9 +874,9 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
 
 
 
-/* Checks if the new reply (with new_code status) should be sent or not 
+/* Checks if the new reply (with new_code status) should be sent or not
  *  based on the current
-  * transactin status. 
+  * transactin status.
   * Returns 1 - the response can be sent
   *         0 - is not indicated to sent
   */
@@ -859,21 +896,21 @@ int t_should_relay_response( struct cell *Trans , int new_code )
 		if (new_code!=100) { /* all but "100 trying" */
 			DBG("DBG: t_should_relay: !=100 -> relay\n");
 			return 1;
-		} 
+		}
 	}
 	DBG("DBG: t_should_relay: not to be relayed\n");
 	return 0;
 
 
 /*
-   // have we already sent something? 
+   // have we already sent something?
    if ( !Trans->outbound_response.retr_buffer )
    {
       DBG("DEBUG: t_should_relay_response: %d response relayed (no previous response sent)\n",new_code);
       return 1;
    }
 
-   // have we sent a final response? 
+   // have we sent a final response?
    if ( (T_code/100)>1 )
    {  //final response was sent
       if ( new_code==200 && Trans->inbound_request->REQ_METHOD==METHOD_INVITE )
@@ -883,7 +920,7 @@ int t_should_relay_response( struct cell *Trans , int new_code )
       }
    }
    else
-   { // provisional response was sent 
+   { // provisional response was sent
       if ( new_code>T_code )
       {
          DBG("DEBUG: t_should_relay_response: %d response relayed (higher provisional response)\n",new_code);
@@ -1115,6 +1152,66 @@ void delete_cell( struct cell *p_cell )
 }
 
 
+/* Returns  -1 = error
+                    0 = OK
+*/
+int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip, unsigned int *param_port)
+{
+   struct hostent  *nhost;
+   unsigned int     ip, port;
+   struct sip_uri    parsed_uri;
+   str                      uri;
+   int                      err;
+
+   /* the original uri has been changed? */
+   if (p_msg->new_uri.s==0 || p_msg->new_uri.len==0)
+     uri = p_msg->first_line.u.request.uri;
+   else
+     uri = p_msg->new_uri;
+
+   /* parsing the request uri in order to get host and port */
+   if (parse_uri( uri.s , uri.len , &parsed_uri )<0)
+   {
+        LOG(L_ERR, "ERROR: get_ip_and_port_from_uri: unable to parse destination uri\n");
+        return  -1;
+   }
+
+   /* getting host address*/
+   nhost = gethostbyname( parsed_uri.host.s );
+
+   if ( !nhost )
+   {
+      LOG(L_ERR, "ERROR: get_ip_and_port_from_uri: cannot resolve host\n");
+      return -1;
+   }
+   memcpy(&ip, nhost->h_addr_list[0], sizeof(unsigned int));
+
+   /* getting the port */
+   if ( parsed_uri.port.s==0 || parsed_uri.port.len==0 )
+      port = SIP_PORT;
+   else
+   {
+       port = str2s( parsed_uri.port.s , parsed_uri.port.len , &err );
+       if ( err<0 )
+       {
+           LOG(L_ERR, "ERROR: get_ip_and_port_from_uri: converting port from str to int failed; using default SIP port\n");
+           port = SIP_PORT;
+       }
+   }
+   port = htons( port );
+
+   free_uri( &parsed_uri );
+
+   *param_ip = ip;
+   *param_port = port;
+   return 0;
+}
+
+
+
+
+
+
 /*---------------------TIMEOUT HANDLERS--------------------------*/
 
 

+ 22 - 0
modules/tm/t_funcs.h

@@ -13,6 +13,7 @@
 #include "../../globals.h"
 #include "../../udp_server.h"
 #include "../../msg_translator.h"
+#include "../../forward.h"
 #include "../../mem/mem.h"
 
 struct s_table;
@@ -162,6 +163,26 @@ int t_on_reply_received( struct sip_msg  *p_msg ) ;
 
 
 
+/*  This function is called whenever a request for our module is received; we need to register
+  *  this function on module initialization;
+  *  Returns :   0 - core router stops
+  *                    1 - core router relay statelessly
+  */
+int t_on_request_received( struct sip_msg  *p_msg , unsigned int ip, unsigned int port) ;
+
+
+
+
+/*  This function is called whenever a request for our module is received; we need to register
+  *  this function on module initialization;
+  *  Returns :   0 - core router stops
+  *                    1 - core router relay statelessly
+  */
+int t_on_request_received_uri( struct sip_msg  *p_msg ) ;
+
+
+
+
 /* returns 1 if everything was OK or -1 for error
 */
 int t_release_transaction( struct sip_msg* );
@@ -202,6 +223,7 @@ int t_put_on_wait(  struct cell  *Trans  );
 int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
 int push_reply_from_uac_to_uas( struct cell* Trans , unsigned int );
 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, unsigned int *param_port);
 
 void retransmission_handler( void *);
 void final_response_handler( void *);

+ 71 - 33
modules/tm/t_lookup.c

@@ -12,6 +12,13 @@
 #include "t_funcs.h"
 #include "config.h"
 
+
+#define EQ_LEN(_hf) (t_msg->_hf->body.len==p_msg->_hf->body.len)
+#define EQ_STR(_hf) (memcmp(t_msg->_hf->body.s, p_msg->_hf->body.s, \
+		p_msg->_hf->body.len)==0)
+
+
+
 static int reverse_hex2int( char *c, int len )
 {
 	char *pc;
@@ -63,21 +70,19 @@ int t_lookup_request( struct sip_msg* p_msg )
    unsigned int  isACK;
    struct sip_msg	*t_msg;
 
-   DBG("t_lookup_request: start searching\n");
-
    /* parse all*/
    if (check_transaction_quadruple(p_msg)==0)
    {
       LOG(L_ERR, "ERROR: TM module: t_lookup_request: too few headers\n");
       T=0;
-	  /* stop processing */
+      /* stop processing */
       return 0;
    }
 
    /* start searching into the table */
    hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
    isACK = p_msg->REQ_METHOD==METHOD_ACK;
-   DBG("t_lookup_request: continue searching;  hash=%d, isACK=%d\n",hash_index,isACK);
+   DBG("t_lookup_request: start searching:  hash=%d, isACK=%d\n",hash_index,isACK);
 
    /* lock the hole entry*/
    lock( hash_table->entrys[hash_index].mutex );
@@ -87,37 +92,73 @@ int t_lookup_request( struct sip_msg* p_msg )
    tmp_cell = 0;
    while( p_cell )
    {
+/*
 		int abba;
 
 		t_msg = p_cell->inbound_request;
 
-#define EQ_LEN(_hf) (t_msg->_hf->body.len==p_msg->_hf->body.len)
-#define EQ_STR(_hf) (memcmp(t_msg->_hf->body.s, p_msg->_hf->body.s, \
-		p_msg->_hf->body.len)==0)
 
 
 		if ( EQ_LEN(from) && EQ_LEN(callid) &&
 		  EQ_STR(callid) && EQ_STR(callid) &&
 		  /* we compare only numerical parts of CSEQ ...
-		     the method name should be the same as in first line */
-		  memcmp( get_cseq(t_msg)->number.s , get_cseq(p_msg)->number.s , 
+		     the method name should be the same as in first line
+		  memcmp( get_cseq(t_msg)->number.s , get_cseq(p_msg)->number.s ,
 				get_cseq(p_msg)->number.len ) ==0 )
 		{
 			if (!isACK) {
 				if (t_msg->REQ_METHOD == p_msg->REQ_METHOD &&
 					EQ_LEN(to) && EQ_STR(to))
 					goto found;
-			} else { /* ACK */
+			} else { /* ACK
 				if (t_msg->REQ_METHOD == METHOD_INVITE  &&
 					//p_cell->tag &&  p_cell->tag->len==p_msg->tag->body.len &&
-            		//if ( /*tag*/ memcmp( p_cell->tag->s , p_msg->tag->body.s , 
+            		//if ( /*tag memcmp( p_cell->tag->s , p_msg->tag->body.s ,
 					// p_msg->tag->body.len ) ==0 )
 					EQ_STR( to ) ) {
 					goto found;
 				}
-			} /* ACK */
-		} /* common HFs equal */
+			} /* ACK
+		} /* common HFs equal
+*/
+     t_msg = p_cell->inbound_request;
 
+      /* is it the wanted transaction ? */
+      if ( !isACK )
+      { /* is not an ACK request */
+         /* first only the length are checked */
+         if ( /*from length*/ EQ_LEN(from) )
+            if ( /*to length*/ EQ_LEN(to) )
+               if ( /*callid length*/ EQ_LEN(callid) )
+                  if ( /*cseq length*/ EQ_LEN(cseq) )
+                     /* so far the lengths are the same -> let's check the contents */
+                        if ( /*from*/ EQ_STR(from) )
+                           if ( /*to*/ EQ_STR(to) )
+                               if ( /*callid*/ EQ_STR(callid) )
+                                  if ( /*cseq*/ EQ_STR(cseq) )
+                                     { /* WE FOUND THE GOLDEN EGG !!!! */
+                                        goto found;
+                                     }
+      }
+      else
+      { /* it's a ACK request*/
+         /* first only the length are checked */
+         if ( /*from length*/ EQ_LEN(from) )
+            //if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
+               if ( /*callid length*/ EQ_LEN(callid) )
+                  if ( /*cseq_nr length*/ get_cseq(t_msg)->number.len == get_cseq(p_msg)->number.len )
+                      if ( /*cseq_method type*/ t_msg->first_line.u.request.method_value == METHOD_INVITE  )
+                         //if ( /*tag length*/ p_cell->tag &&  p_cell->tag->len==p_msg->tag->body.len )
+                            /* so far the lengths are the same -> let's check the contents */
+                            if ( /*from*/ EQ_STR(from) )
+                               //if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
+                                  //if ( /*tag*/ !memcmp( p_cell->tag->s , p_msg->tag->body.s , p_msg->tag->body.len ) )
+                                     if ( /*callid*/ !memcmp( t_msg->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
+                                        if ( /*cseq_nr*/ !memcmp( get_cseq(t_msg)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
+                                           { /* WE FOUND THE GOLDEN EGG !!!! */
+                                              goto found;
+                                           }
+      }
       /* next transaction */
       tmp_cell = p_cell;
       p_cell = p_cell->next_cell;
@@ -130,13 +171,12 @@ int t_lookup_request( struct sip_msg* p_msg )
    return -1;
 
 found:
-	T=p_cell;
-	/* ref_T( T ); */
-	T_REF( T );
-	DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_lookup_request: "
-			"transaction found ( T=%p , ref=%x)\n",T,T->ref_bitmap);
-	unlock( hash_table->entrys[hash_index].mutex );
-	return 1;
+   T=p_cell;
+   T_REF( T );
+   DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_lookup_request: "
+                   "transaction found ( T=%p , ref=%x)\n",T,T->ref_bitmap);
+   unlock( hash_table->entrys[hash_index].mutex );
+   return 1;
 }
 
 
@@ -328,21 +368,20 @@ int t_check( struct sip_msg* p_msg , int *param_branch)
 	if ( p_msg->id != global_msg_id || T==T_UNDEFINED )
 	{
 		global_msg_id = p_msg->id;
-		/* if ( T && T!=T_UNDEFINED ) unref_T(T); */
-      		T = T_UNDEFINED;
+		T = T_UNDEFINED;
 		/* transaction lookup */
 		if ( p_msg->first_line.type==SIP_REQUEST ) {
 
-   			/* force parsing all the needed headers*/
-   			if (parse_headers(p_msg, HDR_EOH )==-1)
-    				return -1;
-         		t_lookup_request( p_msg );
+			/* force parsing all the needed headers*/
+			if (parse_headers(p_msg, HDR_EOH )==-1)
+				return -1;
+		t_lookup_request( p_msg );
 	 	} else {
 		 	if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO|HDR_CSEQ )==-1 ||
-        			!p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
-    			return -1;
-         		t_reply_matching( p_msg , ((param_branch!=0)?(param_branch):(&local_branch)) );
-	 	}
+			!p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
+			return -1;
+		t_reply_matching( p_msg , ((param_branch!=0)?(param_branch):(&local_branch)) );
+		}
 #		ifdef EXTRA_DEBUG
 		if ( T && T!=T_UNDEFINED && T->damocles) {
 			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
@@ -350,10 +389,9 @@ int t_check( struct sip_msg* p_msg , int *param_branch)
 			abort();
 		}
 #		endif
-   		DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on finish=%p\n", 
+		DBG("DEBUG: t_check : msg id=%d , global msg id=%d , T on finish=%p\n",
 			p_msg->id,global_msg_id,T);
-
-   	} else {
+	} else {
 		if (T)
 			DBG("DEBUG: t_check: T alredy found!\n");
 		else

+ 24 - 4
modules/tm/tm.c

@@ -26,9 +26,12 @@ static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2);
 static int w_t_forward(struct sip_msg* msg, char* str, char* str2);
 static int w_t_forward_def(struct sip_msg* msg, char* str, char* str2);
 static int w_t_release(struct sip_msg* msg, char* str, char* str2);
+static int w_t_on_request_received(struct sip_msg* msg, char* str, char* str2);
+static int w_t_on_request_received_uri(struct sip_msg* msg, char* str, char* str2);
 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_on_request_received(void** param, int param_no);
 
 static void w_onbreak(struct sip_msg* msg) { t_unref(msg, NULL, NULL); }
 
@@ -42,7 +45,9 @@ static struct module_exports nm_exports= {
 				"t_send_reply",
 				"t_retransmit_reply",
 				"t_release",
-				"t_unref"
+				"t_unref",
+				"t_on_request_receive_uri",
+				"t_on_request_receive_to"
 			},
 	(cmd_function[]){
 					t_add_transaction,
@@ -53,7 +58,9 @@ static struct module_exports nm_exports= {
 					w_t_send_reply,
 					t_retransmit_reply,
 					w_t_release,
-					t_unref
+					t_unref,
+					w_t_on_request_received_uri,
+					w_t_on_request_received
 					},
 	(int[]){
 				0,
@@ -64,7 +71,9 @@ static struct module_exports nm_exports= {
 				2,
 				0,
 				0,
-				0
+				0,
+				0,
+				2
 			},
 	(fixup_function[]){
 				0,
@@ -76,8 +85,10 @@ static struct module_exports nm_exports= {
 				0,
 				0,
 				0,
+				0,
+				fixup_t_forward
 		},
-	9,
+	11,
 	(response_function) t_on_reply_received,
 	(destroy_function) tm_shutdown,
 	w_onbreak
@@ -237,3 +248,12 @@ static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 	return t_release_transaction(msg);
 }
 
+static int w_t_on_request_received(struct sip_msg* msg, char* str, char* str2)
+{
+	return t_on_request_received(msg, (unsigned int) str, (unsigned int) str2);
+}
+
+static int w_t_on_request_received_uri(struct sip_msg* msg, char* str, char* str2)
+{
+	return t_on_request_received_uri(msg);
+}

+ 42 - 3
proxy.c

@@ -154,6 +154,7 @@ error:
 
 
 
+
 /* same as add_proxy, but it doesn't add the proxy to the list*/
 struct proxy_l* mk_proxy(char* name, unsigned short port)
 {
@@ -164,7 +165,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
 	unsigned int ip;
 	int len;
 #endif
-	
+
 	p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
 	if (p==0){
 		LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
@@ -204,12 +205,12 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
 		}
 		memcpy(p->host.h_addr_list[0], (char*)&ip, 4);
 		p->host.h_addr_list[0][4]=0;
-		
+
 		return p;
 	}
 #endif
 	/* fail over to normal lookup */
-	
+
 	he=gethostbyname(name);
 	if (he==0){
 		LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
@@ -229,6 +230,44 @@ error:
 
 
 
+/* same as mk_proxy, but get the host as an ip*/
+struct proxy_l* mk_proxy_from_ip(unsigned int ip, unsigned short port)
+{
+	struct proxy_l* p;
+	struct hostent* he;
+	int err;
+
+	p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
+	if (p==0){
+		LOG(L_CRIT, "ERROR: mk_proxy_from_ip: memory allocation failure\n");
+		goto error;
+	}
+	memset(p,0,sizeof(struct proxy_l));
+
+	p->port=port;
+	p->host.h_addrtype=AF_INET;
+	p->host.h_length=4;
+	p->host.h_addr_list=malloc(2*sizeof(char*));
+	if (p->host.h_addr_list==0) goto error;
+	p->host.h_addr_list[1]=0;
+	p->host.h_addr_list[0]=malloc(5);
+	if (p->host.h_addr_list[0]==0){
+		free(p->host.h_addr_list);
+		goto error;
+	}
+
+	memcpy(p->host.h_addr_list[0], (char*)&ip, 4);
+	p->host.h_addr_list[0][4]=0;
+
+	return p;
+
+error:
+	return 0;
+}
+
+
+
+
 void free_proxy(struct proxy_l* p)
 {
 	if (p) free_hostent(&p->host);

+ 1 - 0
proxy.h

@@ -29,6 +29,7 @@ extern struct proxy_l* proxies;
 
 struct proxy_l* add_proxy(char* name, unsigned short port);
 struct proxy_l* mk_proxy(char* name, unsigned short port);
+struct proxy_l* mk_proxy_from_ip(unsigned int ip, unsigned short port);
 void free_proxy(struct proxy_l* p);
 
 

+ 11 - 11
test/tx.cfg

@@ -4,25 +4,25 @@
 # $ID: $
 #
 
-debug=1          # debug level (cmd line: -dddddddddd)
-fork=yes          # (cmd. line: -D)
-#fork=no
+debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=no
 #log_stderror=yes # (cmd line: -E)
-log_stderror=no	# (cmd line: -E)
+log_stderror=yes	# (cmd line: -E)
 
 
-children=8
-check_via=yes     # (cmd. line: -v)
-dns=on           # (cmd. line: -r)
-rev_dns=yes      # (cmd. line: -R)
-port=5080
+#children=8
+check_via=no     # (cmd. line: -v)
+#dns=on           # (cmd. line: -r)
+#rev_dns=yes      # (cmd. line: -R)
+#port=5080
 #listen=127.0.0.1
-listen=195.37.77.101
+#listen=195.37.77.101
 loop_checks=0
 # for more info: sip_router -h
 
 #modules
-loadmodule "modules/print/print.so"
+#loadmodule "modules/print/print.so"
 #loadmodule "modules/tm/tm.so"
 
 #route[0]{