소스 검색

lot and hard debugging

Bogdan-Andrei Iancu 24 년 전
부모
커밋
f27f89057c
6개의 변경된 파일228개의 추가작업 그리고 71개의 파일을 삭제
  1. 1 1
      modules/tm/h_table.c
  2. 76 23
      modules/tm/sip_msg.c
  3. 139 41
      modules/tm/t_funcs.c
  4. 1 1
      modules/tm/t_funcs.h
  5. 6 1
      modules/tm/tm.c
  6. 5 4
      msg_parser.c

+ 1 - 1
modules/tm/h_table.c

@@ -148,7 +148,7 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 
    /* inbound request */
    /* force parsing all the needed headers*/
-   parse_headers(p_msg, HDR_VIA|HDR_TO|HDR_FROM|HDR_CALLID|HDR_CSEQ );
+   parse_headers(p_msg, HDR_EOH );
    new_cell->inbound_request =  sip_msg_cloner(p_msg) ;
    /* inbound response is NULL*/
    /* status is 0 */

+ 76 - 23
modules/tm/sip_msg.c

@@ -51,11 +51,16 @@ struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
 
     /* via1 (via_body* type) */
     if (org_msg->via1)
-	 new_msg->via1 = via_body_cloner( new_msg->buf , org_msg->buf , org_msg->via1 );
+         new_msg->via1 = via_body_cloner( new_msg->buf , org_msg->buf , org_msg->via1 );
 
     /* via2 (via_body* type) */
     if (org_msg->via2)
-	new_msg->via2 = via_body_cloner( new_msg->buf , org_msg->buf , org_msg->via2 );
+    {
+        if (org_msg->via1 && org_msg->via1->next )
+            new_msg->via2 = new_msg->via1->next;
+        else
+            new_msg->via2 = via_body_cloner( new_msg->buf , org_msg->buf , org_msg->via2 );
+    }
 
     /* all the headers */
     new_msg->h_via1=0;
@@ -91,6 +96,7 @@ struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
 		  new_hdr->parsed = (void*)sh_malloc( sizeof(struct cseq_body) );
 		  memcpy( new_hdr->parsed , header->parsed , sizeof(struct cseq_body) );
 		  ((struct cseq_body*)new_hdr->parsed)->number.s = translate_pointer( new_msg->buf , org_msg->buf , ((struct cseq_body*)header->parsed)->number.s );
+		  ((struct cseq_body*)new_hdr->parsed)->method.s = translate_pointer( new_msg->buf , org_msg->buf , ((struct cseq_body*)header->parsed)->method.s );
 		}
 		new_msg->cseq = new_hdr;
 		break;
@@ -188,7 +194,9 @@ struct via_body* via_body_cloner( char* new_buf , char *org_buf , struct via_bod
     }
 
     if ( new_via->next )
-	new_via->next = via_body_cloner( new_buf , org_buf , org_via->next );
+        new_via->next = via_body_cloner( new_buf , org_buf , org_via->next );
+
+   return new_via;
 }
 
 
@@ -224,7 +232,52 @@ char*   translate_pointer( char* new_buf , char *org_buf , char* p)
 
 /* Frees the memory occupied by a SIP message
   */
-void free_uri(struct sip_uri* u)
+void sh_free_lump(struct lump* lmp)
+{
+	if (lmp && (lmp->op==LUMP_ADD)){
+		if (lmp->u.value) sh_free(lmp->u.value);
+		lmp->u.value=0;
+		lmp->len=0;
+	}
+}
+
+
+
+void sh_free_lump_list(struct lump* l)
+{
+	struct lump* t, *r, *foo,*crt;
+	t=l;
+	while(t){
+		crt=t;
+		t=t->next;
+	/*
+		 dangerous recursive clean
+		if (crt->before) free_lump_list(crt->before);
+		if (crt->after)  free_lump_list(crt->after);
+	*/
+		/* no more recursion, clean after and before and that's it */
+		r=crt->before;
+		while(r){
+			foo=r; r=r->before;
+			sh_free_lump(foo);
+			sh_free(foo);
+		}
+		r=crt->after;
+		while(r){
+			foo=r; r=r->after;
+			sh_free_lump(foo);
+			sh_free(foo);
+		}
+
+		/*clean current elem*/
+		sh_free_lump(crt);
+		sh_free(crt);
+	}
+}
+
+
+
+void sh_free_uri(struct sip_uri* u)
 {
    if (u)
    {
@@ -245,7 +298,7 @@ void free_uri(struct sip_uri* u)
 
 
 
-void free_via_param_list(struct via_param* vp)
+void sh_free_via_param_list(struct via_param* vp)
 {
    struct via_param* foo;
    while(vp)
@@ -258,7 +311,7 @@ void free_via_param_list(struct via_param* vp)
 
 
 
-void free_via_list(struct via_body* vb)
+void sh_free_via_list(struct via_body* vb)
 {
    struct via_body* foo;
    while(vb)
@@ -266,7 +319,7 @@ void free_via_list(struct via_body* vb)
       foo=vb;
       vb=vb->next;
      if (foo->param_lst)
-        free_via_param_list(foo->param_lst);
+        sh_free_via_param_list(foo->param_lst);
       sh_free(foo);
     }
 }
@@ -274,21 +327,22 @@ void free_via_list(struct via_body* vb)
 
 /* frees a hdr_field structure,
  * WARNING: it frees only parsed (and not name.s, body.s)*/
-void clean_hdr_field(struct hdr_field* hf)
+void sh_clean_hdr_field(struct hdr_field* hf)
 {
    if (hf->parsed)
    {
       switch(hf->type)
       {
          case HDR_VIA:
-   DBG("DEBUG: sip_msg_free : via headers\n");
-               free_via_list(hf->parsed);
+   DBG("DEBUG: sh_clean_hdr_field : via headers\n");
+               sh_free_via_list(hf->parsed);
              break;
          case HDR_CSEQ:
-   DBG("DEBUG: sip_msg_free : cseq headers\n");
+   DBG("DEBUG: sh_clean_hdr_field : cseq headers\n");
                 sh_free(hf->parsed);
              break;
          default:
+   DBG("DEBUG: sh_clean_hdr_field : unknown headers\n");
       }
    }
 }
@@ -297,18 +351,17 @@ void clean_hdr_field(struct hdr_field* hf)
 
 /* frees a hdr_field list,
  * WARNING: frees only ->parsed and ->next*/
-void free_hdr_field_lst(struct hdr_field* hf)
+void sh_free_hdr_field_lst(struct hdr_field* hf)
 {
    struct hdr_field* foo;
-  DBG("DEBUG: free_hdr_field_lst : \n");
 
    while(hf)
     {
-      DBG("DEBUG: free_hdr_field_lst : \n");
+      DBG("DEBUG: free_hdr_field_lst : %s [%d]\n",hf->name.s, hf->type);
        foo=hf;
        hf=hf->next;
-       clean_hdr_field(foo);
-       pkg_free(foo);
+       sh_clean_hdr_field(foo);
+       sh_free(foo);
     }
 }
 
@@ -319,20 +372,20 @@ void sip_msg_free(struct sip_msg* msg)
 {
    if (!msg) return;
 
+   DBG("DEBUG: sip_msg_free : start\n");
+
    if (msg->new_uri.s)
    {
       sh_free(msg->new_uri.s);
       msg->new_uri.len=0;
    }
-   LOG(L_ERR, "ERROR: sip_msg_free : headers and via1/via2 freeing still missing\n");
-   //if (msg->headers)
-    //  free_hdr_field_lst(msg->headers);
-   DBG("DEBUG: sip_msg_free : lump\n");
+   if (msg->headers)
+      sh_free_hdr_field_lst(msg->headers);
    if (msg->add_rm)
-      free_lump_list(msg->add_rm);
+      sh_free_lump_list(msg->add_rm);
    if (msg->repl_add_rm)
-      free_lump_list(msg->repl_add_rm);
+      sh_free_lump_list(msg->repl_add_rm);
    if (msg->orig) sh_free( msg->orig );
    if (msg->buf) sh_free( msg->buf );
-   
+
 }

+ 139 - 41
modules/tm/t_funcs.c

@@ -172,14 +172,14 @@ int t_lookup_request( struct sip_msg* p_msg, char* foo, char* bar  )
       { /* it's a ACK request*/
          /* first only the length are checked */
          if ( /*from length*/ p_cell->inbound_request->from->body.len == p_msg->from->body.len )
-            if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
+            //if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
                if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
                   if ( /*cseq_nr length*/ get_cseq(p_cell->inbound_request)->number.len == get_cseq(p_msg)->number.len )
                       if ( /*cseq_method type*/ p_cell->inbound_request->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*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
-                               if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
+                               //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( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
                                         if ( /*cseq_nr*/ !memcmp( get_cseq(p_cell->inbound_request)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
@@ -393,7 +393,7 @@ int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
   */
 int t_on_reply_received( struct sip_msg  *p_msg )
 {
-   unsigned int  branch;
+   unsigned int  branch,len;
 
    global_msg_id = p_msg->id;
 
@@ -403,16 +403,18 @@ int t_on_reply_received( struct sip_msg  *p_msg )
    /* if no T found ->tell the core router to forward statelessly */
    if ( T<=0 )
       return 1;
+   DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status);
 
    /* stop retransmission */
    remove_from_timer_list( hash_table , &(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+   // ??? what about FR_TIMER ????
 
    /* on a non-200 reply to INVITE, generate local ACK */
    if ( T->inbound_request->first_line.u.request.method_value==METHOD_INVITE && p_msg->first_line.u.reply.statusclass>2 )
    {
       DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
-      t_build_and_send_ACK( T , branch );
-      t_store_incoming_reply( T , branch , p_msg );
+      //t_store_incoming_reply( T , branch , p_msg );
+      t_build_and_send_ACK( T , branch , p_msg );
    }
 
    #ifdef FORKING
@@ -420,7 +422,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
    #endif
 
    /*let's check the current inbound response status (is final or not) */
-   if ( T->inbound_response && (T->status/100)>1 )
+   if ( T->inbound_response[branch] && (T->status/100)>1 )
    {  /*a final reply was already sent upstream */
       /* alway relay 2xx immediately ; drop anything else */
       DBG("DEBUG: t_on_reply_received: something final had been relayed\n");
@@ -444,7 +446,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
       /* relay ringing and OK immediately */
       if ( p_msg->first_line.u.reply.statusclass ==1 || p_msg->first_line.u.reply.statusclass ==2  )
       {
-	   DBG("DEBUG: t_on_reply_received:  relay ringing and OK immediately \n");
+           DBG("DEBUG: t_on_reply_received:  relay ringing and OK immediately \n");
            if ( p_msg->first_line.u.reply.statuscode > T->status )
               t_relay_reply( T , branch , p_msg );
          return 0;
@@ -453,7 +455,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
       /* error final responses are only stored */
       if ( p_msg->first_line.u.reply.statusclass>=3 && p_msg->first_line.u.reply.statusclass<=5 )
       {
-	   DBG("DEBUG: t_on_reply_received:  error final responses are only stored  \n");
+         DBG("DEBUG: t_on_reply_received:  error final responses are only stored  \n");
          t_store_incoming_reply( T , branch , p_msg );
          if ( t_all_final(T) )
               relay_lowest_reply_upstream( T , p_msg );
@@ -588,6 +590,7 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
 
       T->outbound_response->tl[RETRASMISSIONS_LIST].payload = T->outbound_response;
       T->outbound_response->tl[FR_TIMER_LIST].payload = T->outbound_response;
+      T->outbound_response->to.sin_family = AF_INET;
       T->outbound_response->my_T = T;
    }
 
@@ -741,20 +744,21 @@ int t_reply_matching( struct s_table *hash_table , struct sip_msg *p_msg , struc
    /* split the branch into pieces: loop_detection_check(ignored),
       hash_table_id, synonym_id, branch_id
    */
+
    if (! ( p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s) )
 	goto nomatch;
 
    p=p_msg->via1->branch->value.s;
    scan_space=p_msg->via1->branch->value.len;
 
-   /* loop detection ... ignore */ 
+   /* loop detection ... ignore */
    n=eat_token2_end( p, p+scan_space, '.');
    scan_space-=n-p;
    if (n==p || scan_space<2 || *n!='.') goto nomatch;
    p=n+1; scan_space--;
 
    /* hash_id */
-   n=eat_token2_end( p, p+scan_space, '.'); 
+   n=eat_token2_end( p, p+scan_space, '.');
    hashl=n-p;
    scan_space-=hashl;
    if (!hashl || scan_space<2 || *n!='.') goto nomatch;
@@ -773,7 +777,7 @@ int t_reply_matching( struct s_table *hash_table , struct sip_msg *p_msg , struc
    /* branch id */  /*  should exceed the scan_space */
    n=eat_token_end( p, p+scan_space );
    branchl=n-p;
-   if (!branchl ) goto nomatch; 
+   if (!branchl ) goto nomatch;
    branchi=p;
 
 
@@ -781,7 +785,7 @@ int t_reply_matching( struct s_table *hash_table , struct sip_msg *p_msg , struc
    entry_label=str_unsigned_hex_2_int(syni, synl);
    branch_id=str_unsigned_hex_2_int(branchi, branchl);
 
-   DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n", 
+   DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
 	hash_index, entry_label, branch_id );
 
    /* sanity check */
@@ -799,13 +803,14 @@ int t_reply_matching( struct s_table *hash_table , struct sip_msg *p_msg , struc
       /* the transaction is referenceted for reading */
       ref_cell( p_cell );
       /* is it the cell with the wanted entry_label? */
-      if ( p_cell->label = entry_label )
+      if ( p_cell->label == entry_label )
       /* 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 !!!! */
 		*p_Trans = p_cell;
 		*p_branch = branch_id;
 		unref_cell( p_cell );
+                              DBG("DEBUG: t_reply_matching: reply matched!\n");
 		return 1;
 	}
       /* next cell */
@@ -838,8 +843,16 @@ int t_store_incoming_reply( struct cell* Trans, unsigned int branch, struct sip_
    if ( Trans->inbound_response[branch] )
       free_sip_msg( Trans->inbound_response[branch] ) ;
    /* force parsing all the needed headers*/
-   parse_headers(p_msg, HDR_VIA|HDR_TO|HDR_FROM|HDR_CALLID|HDR_CSEQ );
+   if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO )==-1 ||
+        !p_msg->via1 || !p_msg->via2 || !p_msg->to )
+   {
+      LOG( L_ERR , "ERROR: t_store_incoming_reply: unable to parse headers !\n"  );
+      return -1;
+   }
    Trans->inbound_response[branch] = sip_msg_cloner( p_msg );
+   Trans->status = p_msg->first_line.u.reply.statuscode;
+   DBG("DEBUG: t_store_incoming_reply: reply stored\n");
+   return 1;
 }
 
 
@@ -895,10 +908,11 @@ 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]) && Trans->inbound_response[i]->first_line.u.reply.statuscode<200 )
+      if (  !Trans->inbound_response[i] ||  Trans->inbound_response[i]->first_line.u.reply.statuscode<=200 )
          return 0;
 
-   return 1;
+  DBG("DEBUG: t_all_final: final state!!!!:)) \n");
+  return 1;
 }
 
 
@@ -922,6 +936,8 @@ int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg )
          lowest_v = T->inbound_response[i]->first_line.u.reply.statuscode;
       }
 
+   DBG("DEBUG: relay_lowest_reply_upstream: lowest reply [%d]=%d\n",lowest_i,lowest_v);
+
    if ( lowest_i != -1 )
       push_reply_from_uac_to_uas( T ,lowest_i );
 
@@ -944,6 +960,7 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
    {
       sh_free( trans->outbound_response->retr_buffer );
       remove_from_timer_list( hash_table , &(trans->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+      // final response ????
    }
    else
    {
@@ -956,8 +973,13 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
 	trans->outbound_response = NULL;
 	return -1;
       }
+      /*init retrans buffer*/
       memset( trans->outbound_response , 0 , sizeof (struct retrans_buff) );
       trans->outbound_response->tl[RETRASMISSIONS_LIST].payload = trans->outbound_response;
+      trans->outbound_response->tl[FR_TIMER_LIST].payload = trans->outbound_response;
+      trans->outbound_response->to.sin_family = AF_INET;
+      trans->outbound_response->my_T = trans;
+
       if (update_sock_struct_from_via(  &(trans->outbound_response->to),  trans->inbound_response[branch]->via2 )==-1) {
 	LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: cannot lookup reply dst: %s\n",
 		trans->inbound_response[branch]->via2->host.s );
@@ -968,7 +990,9 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
    }
 
    /*  */
+   DBG("DEBUG: push_reply_from_uac_to_uas: building buf from response\n");
    buf = build_res_buf_from_sip_res ( trans->inbound_response[branch], &len);
+   DBG("DEBUG: push_reply_from_uac_to_uas: after building\n");
    if (!buf) {
 	LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: no shmem for outbound reply buffer\n");
         return -1;
@@ -979,10 +1003,24 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
    free( buf ) ;
 
    /* make sure that if we send something final upstream, everything else will be cancelled */
+   if ( trans->status>=300 &&  trans->inbound_request->first_line.u.request.method_value==METHOD_INVITE )
+   {
+            T->outbound_response->timeout_ceiling  = RETR_T2;
+            T->outbound_response->timeout_value    = RETR_T1;
+            remove_from_timer_list( hash_table , &(T->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+            insert_into_timer_list( hash_table , &(T->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , RETR_T1 );
+            remove_from_timer_list( hash_table , &(T->outbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
+            insert_into_timer_list( hash_table , &(T->outbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST , FR_TIME_OUT );
+   }
+   else if (trans->status>=200)
+            t_put_on_wait( trans->inbound_request );
+
+    /*
+   // make sure that if we send something final upstream, everything else will be cancelled
    if (trans->inbound_response[branch]->first_line.u.reply.statusclass>=2 )
       t_put_on_wait( trans->inbound_request );
 
-   /* if the code is 3,4,5,6 class for an INVITE-> starts retrans timer*/
+   // if the code is 3,4,5,6 class for an INVITE-> starts retrans timer
    if ( trans->inbound_request->first_line.u.request.method_value==METHOD_INVITE &&
          trans->inbound_response[branch]->first_line.u.reply.statusclass>=300)
          {
@@ -991,7 +1029,7 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
             insert_into_timer_list( hash_table , &(trans->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , RETR_T1 );
             insert_into_timer_list( hash_table , &(trans->outbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST , FR_TIME_OUT );
          }
-
+    */
    t_retransmit_reply( trans->inbound_request, 0 , 0 );
 }
 
@@ -1016,48 +1054,83 @@ int copy_hf( char **dst, struct hdr_field* hf, char *bumper )
    *dst+= hf->name.len ;
    **dst = ':'; (*dst)++;
    **dst = ' '; (*dst)++;
-   memcpy(*dst, hf->body.s, hf->body.len);
+   memcpy(*dst, hf->body.s, hf->body.len-1);
    *dst+= hf->body.len;
    memcpy( *dst, CRLF, CRLF_LEN );
    *dst+=CRLF_LEN;
    return 0;
 }
-  
+
 
 
 
 /* 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)
+int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_msg* rpl)
 {
-    struct sip_msg* p_msg = T->inbound_request;
+   struct sip_msg* p_msg , *r_msg;
     struct via_body *via;
     struct hdr_field *hdr;
-    char *ack_buf=NULL, *p;
+    char *ack_buf, *p;
     unsigned int len;
     int n;
 
-   /* enough place for first line and Via ? */
+
+   p_msg = T->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 INVITE missing\n");
+	goto error;
+   }
+
+    len = 0;
+    /*first line's len */
+    len += 4+p_msg->first_line.u.request.uri.len+1+p_msg->first_line.u.request.version.len+CRLF_LEN;
+    /*via*/
+    len+= MY_VIA_LEN + names_len[0] + 1+ port_no_str_len + MY_BRANCH_LEN + 3*sizeof(unsigned int) /*branch*/ + CRLF_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 ) ;
+      else if ( hdr->type==HDR_TO )
+                 len += ((r_msg->to->body.s+r_msg->to->body.len ) - r_msg->to->name.s ) ;
+
+   /* CSEQ method : from INVITE-> ACK*/
+   len -= 3;
+   /* end of message */
+   len += CRLF_LEN; /*new line*/
+
+   /*
+   // enough place for first line and Via ?
    if ( 4 + p_msg->first_line.u.request.uri.len + 1 + p_msg->first_line.u.request.version.len +
-	CRLF_LEN + MY_VIA_LEN + names_len[0] + 1 + port_no_str_len + MY_BRANCH_LEN  < MAX_ACK_LEN ) {
+	CRLF_LEN + MY_VIA_LEN + names_len[0] + 1 + port_no_str_len + MY_BRANCH_LEN  > MAX_ACK_LEN ) {
 		LOG( L_ERR, "ERROR: t_build_and_send_ACK: no place for FL/Via\n");
 		goto error;
    }
+   */
+   ack_buf = (char *)malloc( len +1);
+   if (!ack_buf)
+   {
+       LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
+       goto error;
+   }
 
-   ack_buf = (char *)malloc( MAX_ACK_LEN );
    p = ack_buf;
+   DBG("DEBUG: t_build_and_send_ACK: len = %d \n",len);
 
    /* first line */
    memcpy( p , "ACK " , 4);
    p += 4;
 
-   memcpy( p , p_msg->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.len );
+   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;
 
    *(p++) = ' ';
 
-   memcpy( p , p_msg->first_line.u.request.version.s , p_msg->first_line.u.request.version.len );
+   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 );
@@ -1070,7 +1143,7 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch)
    memcpy( p , names[0] , names_len[0] );
    p += names_len[0];
 
-   *(p++) = ':';
+  // *(p++) = ':';
 
    memcpy( p , port_no_str , port_no_str_len );
    p += port_no_str_len;
@@ -1078,37 +1151,59 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch)
    memcpy( p, MY_BRANCH, MY_BRANCH_LEN );
    p+=MY_BRANCH_LEN;
 
-   n=snprintf( p, ack_buf + MAX_ACK_LEN - p,
-                 ".%x.%x.%x%s",
+   n=sprintf( p /*, ack_buf + MAX_ACK_LEN - p*/, ".%x.%x.%x%s",
                  Trans->hash_index, Trans->label, branch, CRLF );
 
    if (n==-1) {
-	LOG(L_ERR, "ERROR: t_build_and_send_ACK: not enough memory for branch\n");
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: unable to generate branch\n");
 	goto error;
    }
    p+=n;
 
-   if (!check_transaction_quadruple( p_msg )) {
-	LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot generate a HBH ACK if key HFs in INVITE missing\n");
-	goto error;
-   }
 
-   /* To */
+
+   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 );
+	}
+      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 );
+	}
+       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;
+	}
+    }
+
+
+/*
+   // To
    if (copy_hf( &p, p_msg->to , ack_buf + MAX_ACK_LEN )==-1) {
 	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for To\n");
 	goto error;
    }
-   /* From */
+   // From
    if (copy_hf( &p, p_msg->from, ack_buf + MAX_ACK_LEN )==-1) {
 	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for From\n");
 	goto error;
    }
-   /* CallId */
+   // CallId
    if (copy_hf( &p, p_msg->callid, ack_buf + MAX_ACK_LEN )==-1) {
 	LOG(L_ERR, "ERROR: t_build_and_send_ACK: no place for callid\n");
 	goto error;
    }
-   /* CSeq, EoH */
+   // CSeq, EoH
    n=snprintf( p, ack_buf + MAX_ACK_LEN - p,
                  "Cseq: %*s ACK%s%s", get_cseq(p_msg)->number.len,
 		get_cseq(p_msg)->number.s, CRLF, CRLF );
@@ -1117,10 +1212,13 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch)
 	goto error;
    }
    p+=n;
-
+*/
+    memcpy( p , CRLF , CRLF_LEN );
+    p += CRLF_LEN;
 
    /* sends the ACK message to the same destination as the INVITE */
    udp_send( ack_buf, p-ack_buf, (struct sockaddr*)&(T->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
+   DBG("DEBUG: t_build_and_send_ACK: ACK sent\n",);
 
    /* free mem*/
    if (ack_buf) free( ack_buf );

+ 1 - 1
modules/tm/t_funcs.h

@@ -114,7 +114,7 @@ int t_store_incoming_reply( struct cell* , unsigned int , struct sip_msg* );
 int t_relay_reply( struct cell* , unsigned int , struct sip_msg* );
 int t_check( struct s_table* , struct sip_msg*  );
 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);
 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 t_cancel_branch(unsigned int branch); //TO DO

+ 6 - 1
modules/tm/tm.c

@@ -24,6 +24,7 @@
 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_put_on_wait(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);
@@ -47,7 +48,7 @@ static struct module_exports nm_exports= {
 					t_forward_uri,
 					w_t_send_reply,
 					t_retransmit_reply,
-					t_put_on_wait
+					w_t_put_on_wait
 					},
 	(int[]){
 				0,
@@ -213,6 +214,10 @@ static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 	return t_send_reply(msg, (unsigned int) str, str2);
 }
 
+static int w_t_put_on_wait(struct sip_msg* msg, char* str, char* str2)
+{
+	return t_put_on_wait(msg);
+}
 
 
 

+ 5 - 4
msg_parser.c

@@ -677,7 +677,7 @@ error:
    time; if you call it twice and the HF is found on second time too,
    it's not replaced in the well-known HF pointer but just added to
    header list; if you want to use a dumbie convenience function which will
-   give you the first occurance of a header you are interested in, 
+   give you the first occurance of a header you are interested in,
    look at check_transaction_quadruple
 */
 int parse_headers(struct sip_msg* msg, int flags)
@@ -686,10 +686,10 @@ int parse_headers(struct sip_msg* msg, int flags)
 	char* tmp;
 	char* rest;
 	char* end;
-	
+
 	end=msg->buf+msg->len;
 	tmp=msg->unparsed;
-	
+
 	DBG("parse_headers: flags=%d\n", flags);
 	while( tmp<end && (flags & msg->parsed_flag) != flags){
 		hf=pkg_malloc(sizeof(struct hdr_field));
@@ -707,6 +707,7 @@ int parse_headers(struct sip_msg* msg, int flags)
 			case HDR_EOH:
 				msg->eoh=tmp; /* or rest?*/
 				msg->parsed_flag|=HDR_EOH;
+				pkg_free(hf);
 				goto skip;
 			case HDR_OTHER: /*do nothing*/
 				break;
@@ -769,7 +770,7 @@ int parse_headers(struct sip_msg* msg, int flags)
 skip:
 	msg->unparsed=tmp;
 	return 0;
-	
+
 error:
 	if (hf) pkg_free(hf);
 	return -1;