T-management hugely refurbished, fat bugs fixed; alas, the timer routing
authorJiri Kuthan <jiri@iptel.org>
Mon, 3 Dec 2001 13:07:13 +0000 (13:07 +0000)
committerJiri Kuthan <jiri@iptel.org>
Mon, 3 Dec 2001 13:07:13 +0000 (13:07 +0000)
in T-mgmt core dumps now

16 files changed:
Makefile
debug.gdb
forward.c
forward.h
modules/tm/h_table.c
modules/tm/h_table.h
modules/tm/sip_msg.c
modules/tm/t_funcs.c
modules/tm/t_funcs.h
msg_parser.h
msg_translator.c
msg_translator.h
receive.c
t_debug.cfg
test/repl1.sip
udp_server.c

index 381afb3..504adfa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -33,14 +33,14 @@ NAME=ser
 # PKG_MALLOC uses a faster malloc (exclusive w/ USE_SHM_MEM)
 # USE_SHM_MEM all pkg_malloc => sh_malloc (most mallocs use a common sh. mem.
 #           segment); don't define PKG_MALLOC!
-DEFS=-DNOCR -DMACROEATER -DDNS_IP_HACK  -DSHM_MEM -DUSE_SHM_MEM #-DNO_DEBUG 
+DEFS=-DTHREAD -DNOCR -DMACROEATER -DDNS_IP_HACK  -DSHM_MEM -DUSE_SHM_MEM #-DNO_DEBUG 
 #-DPKG_MALLOC
 #-DNO_DEBUG#-DSTATS -DNO_DEBUG 
 #-DNO_LOG
 
 PROFILE=  # -pg #set this if you want profiling
-#mode = debug
-mode = release
+mode = debug
+#mode = release
 
 # platform dependent settings
 
index 62e1bd6..5c230d9 100644 (file)
--- a/debug.gdb
+++ b/debug.gdb
@@ -1,6 +1,7 @@
 file ./ser
-set args -f debug.cfg 
+set args -f t_debug.cfg
 break main
 #break dump_all_statistic
 #break lock_initialize
+break udp_send
 run
index 945a784..3af4410 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -41,8 +41,8 @@
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
 {
        unsigned int len;
-       char* buf;
-       struct sockaddr_in* to;
+       char* buf=NULL;
+       struct sockaddr_in* to=NULL;
 
 
        buf = build_req_buf_from_sip_req( msg, &len);
@@ -53,12 +53,12 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 
        to=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
        if (to==0){
-               LOG(L_ERR, "ERROR: forward_reply: out of memory\n");
+               LOG(L_ERR, "ERROR: forward_request: out of memory\n");
                goto error;
        }
 
         /* send it! */
-       DBG("Sending:\n%s.\n", buf);
+       DBG("Sending:", buf);
        DBG("orig. len=%d, new_len=%d\n", msg->len, len );
 
        to->sin_family = AF_INET;
@@ -99,14 +99,39 @@ error:
 }
 
 
+int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via )
+{
+       int err;
+
+       to->sin_family = AF_INET;
+       to->sin_port = (via->port)?htons(via->port): htons(SIP_PORT);
+
+#ifdef DNS_IP_HACK
+       to->sin_addr.s_addr=str2ip(via->host.s, via->host.len, &err);
+       if (err)
+#endif
+       {
+               struct hostent* he;
+               /* fork? gethostbyname will probably block... */
+               he=gethostbyname(via->host.s);
+               if (he==0){
+                       LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
+                                       via->host.s);
+                       return -1;
+               }
+               to->sin_addr.s_addr=*((long*)he->h_addr_list[0]);
+       }
+       return 1;
+}
+
 
 /* removes first via & sends msg to the second */
 int forward_reply(struct sip_msg* msg)
 {
        int  r;
-       char* new_buf;
-       struct hostent* he;
-       struct sockaddr_in* to;
+       char* new_buf=NULL;
+       struct hostent* he=NULL;
+       struct sockaddr_in* to=NULL;
        unsigned int new_len;
        struct sr_module *mod;
 #ifdef DNS_IP_HACK
@@ -151,34 +176,16 @@ int forward_reply(struct sip_msg* msg)
        }
 
         /* send it! */
+       /* moved to udp_send; -jiri
+
        DBG("Sending: to %s:%d, \n%s.\n",
                        msg->via2->host.s,
                        (unsigned short)msg->via2->port,
                        new_buf);
+       */
 
-#ifdef DNS_IP_HACK
-       to->sin_addr.s_addr=str2ip(msg->via2->host.s, msg->via2->host.len, &err);
-       if (err==0){
-               to->sin_family = AF_INET;
-               to->sin_port = (msg->via2->port)?htons(msg->via2->port):
-                                               htons(SIP_PORT);
-       }else{
-#endif
-               /* fork? gethostbyname will probably block... */
-               he=gethostbyname(msg->via2->host.s);
-               if (he==0){
-                       LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
-                                       msg->via2->host.s);
-                       goto error;
-               }
-               to->sin_family = AF_INET;
-               to->sin_port = (msg->via2->port)?htons(msg->via2->port):
-                                               htons(SIP_PORT);
-               to->sin_addr.s_addr=*((long*)he->h_addr_list[0]);
+       if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
 
-#ifdef DNS_IP_HACK
-       }
-#endif
        if (udp_send(new_buf,new_len, (struct sockaddr*) to,
                                        sizeof(struct sockaddr_in))==-1)
        {
index 1884d6d..f64b059 100644 (file)
--- a/forward.h
+++ b/forward.h
@@ -12,7 +12,7 @@
 
 
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
-
+int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via );
 int forward_reply( struct sip_msg* msg);
 
 #endif
index 6e4b1c4..dd21d76 100644 (file)
@@ -8,27 +8,27 @@ void free_cell( struct cell* dead_cell )
 {
    int i;
 
-   /* inbound_request */
+   /* UA Server */ 
    if ( dead_cell->inbound_request )
       sip_msg_free( dead_cell->inbound_request );
-   /* inbound_response */
-   if ( dead_cell->inbound_response )
+   if ( dead_cell->outbound_response )
    {
-      sh_free( dead_cell->inbound_response->buffer );
-      sh_free( dead_cell->inbound_response );
+      sh_free( dead_cell->outbound_response->retr_buffer );
+      sh_free( dead_cell->outbound_response );
    }
 
+  /* UA Clients */
    for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
    {
       /* outbound requests*/
       if ( dead_cell->outbound_request[i] )
       {
-         sh_free( dead_cell->outbound_request[i]->buffer );
+         sh_free( dead_cell->outbound_request[i]->retr_buffer );
          sh_free( dead_cell->outbound_request[i] );
       }
       /* outbound requests*/
-      if ( dead_cell -> outbound_response[i] )
-         sip_msg_free( dead_cell->outbound_response[i] );
+      if ( dead_cell -> inbound_response[i] )
+         sip_msg_free( dead_cell->inbound_response[i] );
    }
    /* mutex */
    release_cell_lock( dead_cell );
@@ -105,10 +105,10 @@ struct s_table* init_hash_table()
    for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
       init_timerlist_lock( hash_table, i );
 
-//#ifdef THREAD
+#ifdef THREAD
    /* starts the timer thread/ process */
    pthread_create( thread, NULL, timer_routine, hash_table );
-//#endif
+#endif
 
    return  hash_table;
 
index ad8de92..816628a 100644 (file)
@@ -45,10 +45,12 @@ typedef struct  timer
 
 typedef struct retrans_buff
 {
-   char               *buffer;
+   char               *retr_buffer;
    int                  bufflen;
+/*
    unsigned int dest_ip;
    unsigned int dest_port;
+*/
 
    struct sockaddr_in to;
    /* changed in favour of Solaris to size_t
@@ -88,15 +90,16 @@ typedef struct cell
    struct timer_link dele_tl;
 
    /* usefull data */
-   /* incoming request and its response*/
+   /* UA Server */
    struct sip_msg         *inbound_request;
-   struct retrans_buff   *inbound_response;
+   struct retrans_buff   *outbound_response;
    unsigned int             status;
    str*                             tag;
    /* array of outgoing requests and its responses */
    int                               nr_of_outgoings;
+   /* UA Clients */
    struct retrans_buff   *outbound_request[ MAX_FORK ];
-   struct sip_msg          *outbound_response[ MAX_FORK ];
+   struct sip_msg          *inbound_response[ MAX_FORK ];
 }cell_type;
 
 
index 8aba71b..696e973 100644 (file)
@@ -6,7 +6,7 @@
 
 struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
 {
-    struct sip_msg   *new_msg;
+    struct sip_msg   *new_msg=NULL;
     struct hdr_field  *header, *last_hdr, *new_hdr;
 
     /* clones the sip_msg structure */
@@ -127,6 +127,13 @@ struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg )
     /* repl_add_rm ( struct lump* ) -> have to be changed!!!!!!!  */
     new_msg->repl_add_rm  = 0;
 
+    return new_msg;
+
+error:
+       sip_msg_free( new_msg );
+       sh_free( new_msg );
+       return NULL;
+
 }
 
 
@@ -310,12 +317,14 @@ void free_hdr_field_lst(struct hdr_field* hf)
 /*only the content*/
 void sip_msg_free(struct sip_msg* msg)
 {
+   if (!msg) return;
+
    if (msg->new_uri.s)
    {
       sh_free(msg->new_uri.s);
       msg->new_uri.len=0;
    }
-   DBG("DEBUG: sip_msg_free : headers\n");
+   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");
@@ -323,11 +332,7 @@ void sip_msg_free(struct sip_msg* msg)
       free_lump_list(msg->add_rm);
    if (msg->repl_add_rm)
       free_lump_list(msg->repl_add_rm);
-   sh_free( msg->orig );
-   sh_free( msg->buf );
+   if (msg->orig) sh_free( msg->orig );
+   if (msg->buf) sh_free( msg->buf );
+   
 }
-
-
-
-
-
index a70bb62..97462ac 100644 (file)
@@ -23,7 +23,7 @@ int tm_startup()
 
    /*first msg id*/
    global_msg_id = 0;
-   T = (struct cell*)-1;
+   T = T_UNDEFINED;
 
    return 0;
 }
@@ -54,12 +54,12 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
    /* it's about the same transaction or not?*/
    if ( global_msg_id != p_msg->id )
    {
-      T = (struct cell*)-1;
+      T = T_UNDEFINED;
       global_msg_id = p_msg->id;
    }
 
     /* if the transaction is not found yet we are tring to look for it*/
-   if ( (int)T==-1 )
+   if ( T==T_UNDEFINED )
       /* if the lookup's result is not 0 means that it's a retransmission */
       if ( t_lookup_request( p_msg, foo, bar ) )
       {
@@ -95,12 +95,12 @@ int t_lookup_request( struct sip_msg* p_msg, char* foo, char* bar  )
    /* it's about the same transaction or not?*/
    if ( global_msg_id != p_msg->id )
    {
-      T = (struct cell*)-1;
+      T = T_UNDEFINED;
       global_msg_id = p_msg->id;
    }
 
     /* if  T is previous found -> return found */
-   if ( (int)T !=-1 && T )     {
+   if ( T!=T_UNDEFINED && T )  {
       DBG("DEBUG: t_lookup_request: T already exists\n");
       return 1;
    }
@@ -115,7 +115,7 @@ int t_lookup_request( struct sip_msg* p_msg, char* foo, char* bar  )
    /* parse all*/
    if (check_transaction_quadruple(p_msg)==0) {
           LOG(L_ERR, "ERROR: TM module: t_lookup_request: too few headers\n");
-          T=0;
+          T=T_NULL;
           return -1;
    }
    /* start searching into the table */
@@ -205,13 +205,13 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
    /* it's about the same transaction or not? */
    if ( global_msg_id != p_msg->id )
    {
-      T = (struct cell*)-1;
+      T = T_UNDEFINED;
       global_msg_id = p_msg->id;
    }
 
    DBG("t_forward: 1. T=%x\n", T);
    /* if  T hasn't been previous searched -> search for it */
-   if ( (int)T ==-1 )
+   if ( T == T_UNDEFINED )
       t_lookup_request( p_msg, 0 , 0 );
 
    DBG("t_forward: 2. T=%x\n", T);
@@ -246,8 +246,8 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
             if ( (T2->status/100)==1 )
             {
                DBG("DEBUG: t_forward: it's CANCEL and I will send to the same place where INVITE went\n");
-               dest_ip    = T2->outbound_request[branch]->dest_ip;
-               dest_port = T2->outbound_request[branch]->dest_port;
+               dest_ip    = T2->outbound_request[branch]->to.sin_addr.s_addr;
+               dest_port = T2->outbound_request[branch]->to.sin_port;
             }
             else
             {
@@ -261,6 +261,10 @@ 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");
       T->outbound_request[branch] = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
+      if (!T->outbound_request[branch]) {
+        LOG(L_ERR, "ERROR: t_forward: out of shmem\n");
+        return -1;
+      }
       memset( T->outbound_request[branch] , 0 , sizeof (struct retrans_buff) );
       T->outbound_request[branch]->tl[RETRASMISSIONS_LIST].payload =  T->outbound_request[branch];
       T->outbound_request[branch]->tl[FR_TIMER_LIST].payload =  T->outbound_request[branch];
@@ -269,17 +273,16 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
       T->nr_of_outgoings = 1;
 
       if (add_branch_label( T, p_msg , branch )==-1) return -1;
-      DBG("DEBUG: XXX: branch_size after call to add_branch_label: %d\n", p_msg->add_to_branch_len );
       buf = build_req_buf_from_sip_req  ( p_msg, &len);
       if (!buf)
          return -1;
       T->outbound_request[branch]->bufflen = len ;
-      if ( !(T->outbound_request[branch]->buffer   = (char*)sh_malloc( len ))) {
+      if ( !(T->outbound_request[branch]->retr_buffer   = (char*)sh_malloc( len ))) {
        LOG(L_ERR, "ERROR: t_forward: shmem allocation failed\n");
        free( buf );
        return -1;
       }
-      memcpy( T->outbound_request[branch]->buffer , buf , len );
+      memcpy( T->outbound_request[branch]->retr_buffer , buf , len );
       free( buf ) ;
 
       DBG("DEBUG: t_forward: starting timers (retrans and FR)\n");
@@ -292,15 +295,13 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
       insert_into_timer_list( hash_table , &(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST]), RETRASMISSIONS_LIST , RETR_T1 );
    }/* end for the first time */
 
-   DBG("DEBUG: t_forward: sending outbund request from buffer (%d bytes):\n%*s\n",
-       T->outbound_request[branch]->bufflen, T->outbound_request[branch]->bufflen,
-        T->outbound_request[branch]->buffer);
    /* send the request */
-   T->outbound_request[branch]->dest_ip         = dest_ip;
-   T->outbound_request[branch]->dest_port      = dest_port;
+   /* known to be in network order */
    T->outbound_request[branch]->to.sin_port     =  dest_port;
    T->outbound_request[branch]->to.sin_addr.s_addr =  dest_ip;
-   udp_send( T->outbound_request[branch]->buffer , T->outbound_request[branch]->bufflen ,
+   T->outbound_request[branch]->to.sin_family = AF_INET;
+
+   udp_send( T->outbound_request[branch]->retr_buffer , T->outbound_request[branch]->bufflen ,
                     (struct sockaddr*)&(T->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
    return 1;
 }
@@ -323,13 +324,13 @@ int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
    /* it's about the same transaction or not? */
    if ( global_msg_id != p_msg->id )
    {
-      T = (struct cell*)-1;
+      T = T_UNDEFINED;
       global_msg_id = p_msg->id;
    }
 
    DBG("DEBUG: t_forward_uri: 1. T=%x\n", T);
    /* if  T hasn't been previous searched -> search for it */
-   if ( (int)T ==-1 )
+   if ( T==T_UNDEFINED )
       t_lookup_request( p_msg, 0 , 0 );
 
    DBG("DEBUG: t_forward_uri: 2. T=%x\n", T);
@@ -379,7 +380,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
    t_reply_matching( hash_table , p_msg , &T , &branch  );
 
    /* if no T found ->tell the core router to forward statelessly */
-   if ( !T )
+   if ( T<=0 )
       return 1;
 
    /* stop retransmission */
@@ -462,7 +463,7 @@ int t_put_on_wait(  struct sip_msg  *p_msg  )
 
    t_check( hash_table , p_msg );
    /* do we have something to release? */
-   if (T==0)
+   if (T==T_NULL)
       return -1;
 
   if ( is_in_timer_list( (&(T->wait_tl)) , WT_TIMER_LIST) )
@@ -474,16 +475,16 @@ int t_put_on_wait(  struct sip_msg  *p_msg  )
 
   /**/
   for( i=0 ; i<T->nr_of_outgoings ; i++ )
-      if ( T->outbound_response[i] && T->outbound_response[i]->first_line.u.reply.statusclass==1)
+      if ( T->inbound_response[i] && T->inbound_response[i]->first_line.u.reply.statusclass==1)
           t_cancel_branch(i);
 
    /* make double-sure we have finished everything */
    /* remove from  retranssmision  and  final response   list */
    DBG("DEBUG: t_put_on_wait: remove inboud stuff from lists\n");
-   if ( T->inbound_response )
+   if ( T->outbound_response )
    {
-      remove_from_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
-      remove_from_timer_list( hash_table , &(T->inbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
+      remove_from_timer_list( hash_table , &(T->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+      remove_from_timer_list( hash_table , &(T->outbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
    }
    for( i=0 ; i<T->nr_of_outgoings ; i++ )
    {
@@ -500,6 +501,9 @@ int t_put_on_wait(  struct sip_msg  *p_msg  )
 
 
 /* Retransmits the last sent inbound reply.
+
+  * input: p_msg==request for which I want to retransmit an associated
+    reply
   * Returns  -1 -error
   *                1 - OK
   */
@@ -508,12 +512,14 @@ int t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
    t_check( hash_table, p_msg );
 
    /* if no transaction exists or no reply to be resend -> out */
-   if ( T  && T->inbound_response )
+   if ( T  && T->outbound_response )
    {
-      udp_send( T->inbound_response->buffer , T->inbound_response->bufflen , (struct sockaddr*)&(T->inbound_response->to) , sizeof(struct sockaddr_in) );
+      udp_send( T->outbound_response->retr_buffer , T->outbound_response->bufflen , 
+       (struct sockaddr*)&(T->outbound_response->to) , sizeof(struct sockaddr_in) );
       return 1;
    }
 
+  /* no transaction found */
    return -1;
 }
 
@@ -525,85 +531,88 @@ int t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
   */
 int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
 {
-   t_check( hash_table, p_msg );
+       unsigned int len;
+       char * buf = NULL;
+        struct hostent  *nhost;
+        unsigned int      ip, port;
+        char foo;
+       int err;
+        struct retrans_buff* rb = NULL;
+
+       DBG("DEBUG: t_send_reply: entered\n");
+       t_check( hash_table, p_msg );
+
+       if (!T) {
+               LOG(L_ERR, "ERROR: cannot send a t_reply to a message for which no T-state has been established\n");
+               return -1;
+       } ;
 
-   if (T)
-   {
-      unsigned int len;
-      char * buf;
+       buf = build_res_buf_from_sip_req( code , text , T->inbound_request , &len );
+        DBG("DEBUG: t_send_reply: after build\n");
+       if (!buf)
+       {
+               DBG("DEBUG: t_send_reply: response building failed\n");
+               goto error;
+       }
+
+       if ( T->outbound_response) {
+               if (  T->outbound_response->retr_buffer )
+               {
+                       sh_free( T->outbound_response->retr_buffer );
+                       T->outbound_response->retr_buffer = NULL;
+               }
+       } else {
+               rb = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
+               if (!rb) {
+                       LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem\n");
+                       goto error;
+               } 
+               T->outbound_response = rb;
+               memset( T->outbound_response , 0 , sizeof (struct retrans_buff) );
+       }
 
-      buf = build_res_buf_from_sip_req( code , text , T->inbound_request , &len );
-         DBG("DEBUG: t_send_reply: after build\n");
-      if (!buf)
-      {
-         DBG("DEBUG: t_send_reply: response building failed\n");
-         return -1;
-      }
 
-     if ( T->inbound_response )
-      {
-         sh_free( T->inbound_response->buffer );
-      }
-      else
-      {
-         struct hostent  *nhost;
-         unsigned int      ip, port;
-         char foo;
-
-          /*some dirty trick to get the port from via */
-          foo = *((p_msg->via1->host.s)+(p_msg->via1->host.len));
-          *((p_msg->via1->host.s)+(p_msg->via1->host.len)) = 0;
-          nhost = gethostbyname( p_msg->via1->host.s );
-          *((p_msg->via1->host.s)+(p_msg->via1->host.len)) = foo;
-          if ( !nhost )
-          {
-             DBG("ERROR: t_send_reply: resolving host failed\n");
-             free(buf);
-             return -1;
-          }
-          memcpy( &ip , nhost->h_addr_list[0] , sizeof(unsigned int) );
-          /* port */
-          if ( !(port = p_msg->via1->port) )
-             port = SIP_PORT;
-
-          /* build a retrans_buff and fill it */
-          T->inbound_response = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
-          memset( T->inbound_response , 0 , sizeof (struct retrans_buff) );
-          T->inbound_response->tl[RETRASMISSIONS_LIST].payload = T->inbound_response;
-          T->inbound_response->tl[FR_TIMER_LIST].payload = T->inbound_response;
-          T->inbound_response->to.sin_family = AF_INET;
-          T->inbound_response->my_T = T;
-          T->inbound_response->to.sin_addr.s_addr = ip;
-          T->inbound_response->to.sin_port =  htons(port);
-          T->inbound_response->dest_ip       = ip;
-          T->inbound_response->dest_port    = htons(port);
-      }
-      T->status = code;
-      T->inbound_response->bufflen = len ;
-      T->inbound_response->buffer   = (char*)sh_malloc( len );
-      memcpy( T->inbound_response->buffer , buf , len );
-      free( buf ) ;
+       /* initialize retransmission structure */
+       if (update_sock_struct_from_via(  &(T->outbound_response->to),  p_msg->via1 )==-1) {
+               LOG(L_ERR, "ERROR: t_send_reply: cannot lookup reply dst: %s\n",
+                p_msg->via1->host.s );
+               goto error;
+         }
+
+       T->outbound_response->tl[RETRASMISSIONS_LIST].payload = T->outbound_response;
+       T->outbound_response->tl[FR_TIMER_LIST].payload = T->outbound_response;
+       T->outbound_response->my_T = T;
+       T->status = code;
+       T->outbound_response->bufflen = len ;
+       T->outbound_response->retr_buffer   = (char*)sh_malloc( len );
+       if (!T->outbound_response->retr_buffer) {
+               T->outbound_response->retr_buffer = NULL;
+               LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n");
+               goto error;
+       }
+       memcpy( T->outbound_response->retr_buffer , buf , len );
+       free( buf ) ;
 
       /* make sure that if we send something final upstream, everything else will be cancelled */
-      if ( code>=200 )
-         if ( p_msg->first_line.u.request.method_value==METHOD_INVITE )
-         {
-            T->inbound_response->timeout_ceiling  = RETR_T2;
-            T->inbound_response->timeout_value    = RETR_T1;
-            remove_from_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
-            insert_into_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , RETR_T1 );
-            remove_from_timer_list( hash_table , &(T->inbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
-            insert_into_timer_list( hash_table , &(T->inbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST , FR_TIME_OUT );
-         }
-         else
+      if ( code>=300 &&  p_msg->first_line.u.request.method_value==METHOD_INVITE )
          {
-            t_put_on_wait( p_msg );
+            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 (code>=200) t_put_on_wait( p_msg );
 
-      udp_send( T->inbound_response->buffer , T->inbound_response->bufflen , (struct sockaddr*)&(T->inbound_response->to) , sizeof(struct sockaddr_in) );
-   }
+      t_retransmit_reply( p_msg, 0 , 0);
 
-   return 1;
+      return 1;
+
+error:
+       if (rb) { sh_free(rb); T->outbound_response = rb = NULL;}
+       if ( buf ) free ( buf );
+       return -1;
 }
 
 
@@ -712,6 +721,9 @@ 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;
 
@@ -803,11 +815,11 @@ nomatch:
 int t_store_incoming_reply( struct cell* Trans, unsigned int branch, struct sip_msg* p_msg )
 {
    /* if there is a previous reply, replace it */
-   if ( Trans->outbound_response[branch] )
-      free_sip_msg( Trans->outbound_response[branch] ) ;
+   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 );
-   Trans->outbound_response[branch] = sip_msg_cloner( p_msg );
+   Trans->inbound_response[branch] = sip_msg_cloner( p_msg );
 }
 
 
@@ -819,7 +831,7 @@ int t_store_incoming_reply( struct cell* Trans, unsigned int branch, struct sip_
 int t_relay_reply( struct cell* Trans, unsigned int branch, struct sip_msg* p_msg )
 {
    t_store_incoming_reply( Trans , branch, p_msg );
-   push_reply_from_uac_to_uas( p_msg , branch );
+   push_reply_from_uac_to_uas( Trans , branch );
 }
 
 
@@ -834,7 +846,7 @@ int t_check( struct s_table *hash_table , struct sip_msg* p_msg )
    unsigned int branch;
 
    /* is T still up-to-date ? */
-   if ( p_msg->id != global_msg_id || (int)T==-1 )
+   if ( p_msg->id != global_msg_id || T==T_UNDEFINED )
    {
       global_msg_id = p_msg->id;
       /* transaction lookup */
@@ -861,7 +873,7 @@ int t_all_final( struct cell *Trans )
    unsigned int i;
 
    for( i=0 ; i<Trans->nr_of_outgoings ; i++  )
-      if (  !Trans->outbound_response[i] || (Trans->outbound_response[i]) && Trans->outbound_response[i]->first_line.u.reply.statuscode<200 )
+      if (  !Trans->inbound_response[i] || (Trans->inbound_response[i]) && Trans->inbound_response[i]->first_line.u.reply.statuscode<200 )
          return 0;
 
    return 1;
@@ -880,14 +892,16 @@ int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg )
    int                 lowest_v = 999;
 
    for(  ; i<T->nr_of_outgoings ; i++ )
-      if ( T->outbound_response[i] && T->outbound_response[i]->first_line.u.reply.statuscode>=200 && T->outbound_response[i]->first_line.u.reply.statuscode<lowest_v )
+      if ( T->inbound_response[i] && 
+          T->inbound_response[i]->first_line.u.reply.statuscode>=200 && 
+          T->inbound_response[i]->first_line.u.reply.statuscode<lowest_v )
       {
          lowest_i =i;
-         lowest_v = T->outbound_response[i]->first_line.u.reply.statuscode;
+         lowest_v = T->inbound_response[i]->first_line.u.reply.statuscode;
       }
 
    if ( lowest_i != -1 )
-      push_reply_from_uac_to_uas( p_msg ,lowest_i );
+      push_reply_from_uac_to_uas( T ,lowest_i );
 
    return lowest_i;
 }
@@ -898,62 +912,65 @@ int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg )
 /* Push a previously stored reply from UA Client to UA Server
   * and send it out
   */
-int push_reply_from_uac_to_uas( struct sip_msg *p_msg , unsigned int branch )
+int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
 {
    char *buf;
    unsigned int len;
 
    /* if there is a reply, release the buffer (everything else stays same) */
-   if ( T->inbound_response )
+   if ( trans->outbound_response )
    {
-      sh_free( T->inbound_response->buffer );
-      remove_from_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+      sh_free( trans->outbound_response->retr_buffer );
+      remove_from_timer_list( hash_table , &(trans->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
    }
    else
    {
       struct hostent  *nhost;
      char foo;
 
-      T->inbound_response = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
-      memset( T->inbound_response , 0 , sizeof (struct retrans_buff) );
-      T->inbound_response->tl[RETRASMISSIONS_LIST].payload = &(T->inbound_response);
-      /*some dirty trick to get the port and ip of destination */
-      foo = *((p_msg->via2->host.s)+(p_msg->via2->host.len));
-      *((p_msg->via2->host.s)+(p_msg->via2->host.len)) = 0;
-      nhost = gethostbyname( p_msg->via2->host.s );
-      *((p_msg->via2->host.s)+(p_msg->via2->host.len)) = foo;
-      if ( !nhost )
-         return -1;
-      memcpy( &(T->inbound_response->to.sin_addr) , &(nhost->h_addr) , nhost->h_length );
-      T->inbound_response->dest_ip         = htonl(T->inbound_response->to.sin_addr.s_addr);
-      T->inbound_response->dest_port      = ntohl(T->inbound_response->to.sin_port);
-      T->inbound_response->to.sin_family = AF_INET;
+      trans->outbound_response = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
+      if (!trans->outbound_response) {
+       LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: no more shmem\n");
+       trans->outbound_response = NULL;
+       return -1;
+      }
+      memset( trans->outbound_response , 0 , sizeof (struct retrans_buff) );
+      trans->outbound_response->tl[RETRASMISSIONS_LIST].payload = trans->outbound_response;
+      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 );
+       sh_free(  T->outbound_response );
+       T->outbound_response = NULL;
+       return -1;
+      }
    }
 
    /*  */
-   buf = build_res_buf_from_sip_res ( p_msg, &len);
-   if (!buf)
+   buf = build_res_buf_from_sip_res ( trans->inbound_response[branch], &len);
+   if (!buf) {
+       LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: no shmem for outbound reply buffer\n");
         return -1;
-   T->inbound_response->bufflen = len ;
-   T->inbound_response->buffer   = (char*)sh_malloc( len );
-   memcpy( T->inbound_response->buffer , buf , len );
+   }
+   trans->outbound_response->bufflen = len ;
+   trans->outbound_response->retr_buffer   = (char*)sh_malloc( len );
+   memcpy( trans->outbound_response->retr_buffer , buf , len );
    free( buf ) ;
 
    /* make sure that if we send something final upstream, everything else will be cancelled */
-   if (T->outbound_response[branch]->first_line.u.reply.statusclass>=2 )
-      t_put_on_wait( p_msg );
+   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 ( T->inbound_request->first_line.u.request.method_value==METHOD_INVITE &&
-         T->outbound_response[branch]->first_line.u.reply.statusclass>=300)
+   if ( trans->inbound_request->first_line.u.request.method_value==METHOD_INVITE &&
+         trans->inbound_response[branch]->first_line.u.reply.statusclass>=300)
          {
-            remove_from_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
-            remove_from_timer_list( hash_table , &(T->inbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
-            insert_into_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , RETR_T1 );
-            insert_into_timer_list( hash_table , &(T->inbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST , FR_TIME_OUT );
+            remove_from_timer_list( hash_table , &(trans->outbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
+            remove_from_timer_list( hash_table , &(trans->outbound_response->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
+            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( p_msg, 0 , 0 );
+   t_retransmit_reply( trans->inbound_request, 0 , 0 );
 }
 
 
@@ -1109,7 +1126,7 @@ void retransmission_handler( void *attr)
 
    /* retransmision */
    DBG("DEBUG: retransmission_handler : resending\n");
-   udp_send( r_buf->buffer, r_buf->bufflen, (struct sockaddr*)&(r_buf->to) , sizeof(struct sockaddr_in) );
+   udp_send( r_buf->retr_buffer, r_buf->bufflen, (struct sockaddr*)&(r_buf->to) , sizeof(struct sockaddr_in) );
 
    /* re-insert into RETRASMISSIONS_LIST */
    insert_into_timer_list( hash_table , &(r_buf->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , r_buf->timeout_value );
index b23f98e..670dedf 100644 (file)
@@ -19,6 +19,9 @@ struct cell;
 #include "lock.h"
 #include "sip_msg.h"
 
+#define T_UNDEFINED    ( (struct cell*) -1 )
+#define T_NULL         ( (struct cell*) 0 )
+
 #define sh_malloc( size )     malloc(size)
 #define sh_free( ptr )           free(ptr)
 /* already defined in msg_parser.h
@@ -113,7 +116,7 @@ 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 relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
-int push_reply_from_uac_to_uas( struct sip_msg * , unsigned int );
+int push_reply_from_uac_to_uas( struct cell* Trans , unsigned int );
 int t_cancel_branch(unsigned int branch); //TO DO
 int add_branch_label( struct cell *Trans, struct sip_msg *p_msg , int branch );
 
index 2dd3e99..e5fd679 100644 (file)
@@ -240,8 +240,7 @@ void free_sip_msg(struct sip_msg* msg);
    ( ((msg)->from || (parse_headers( (msg), HDR_FROM)!=-1 && (msg)->from)) &&  \
    ((msg)->to|| (parse_headers( (msg), HDR_TO)!=-1 && (msg)->to)) &&           \
    ((msg)->callid|| (parse_headers( (msg), HDR_CALLID)!=-1 && (msg)->callid)) &&\
-   ((msg)->cseq|| (parse_headers( (msg), HDR_CSEQ)!=-1 && (msg)->cseq)) ) 
-
-
+   ((msg)->cseq|| (parse_headers( (msg), HDR_CSEQ)!=-1 && (msg)->cseq)) && \
+   ((msg)->via1|| (parse_headers( (msg), HDR_VIA)!=-1 && (msg)->via1)) ) 
 
 #endif
index c9f378c..32d54db 100644 (file)
@@ -515,27 +515,41 @@ error:
 
 
 char * build_res_buf_from_sip_req(     unsigned int code ,
-                                                                       char *text ,
-                                                                       struct sip_msg* msg,
-                                                                       unsigned int *returned_len)
+       char *text , struct sip_msg* msg, unsigned int *returned_len)
 {
        char                    *buf=0, *p;
        unsigned int       len,foo;
        struct hdr_field  *hdr;
-       int                       i;
+       int first_via;
+       int str_len_text;
+       int i;
+
+       str_len_text=strlen(text);
 
        /*computes the lenght of the new response buffer*/
        len = 0;
        /* first line */
-       len += 3/*code*/ + 1/*space*/ + strlen(text) + 1/*new line*/;
-       /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
-       for ( hdr=msg->headers ; hdr ; hdr=hdr->next )
-               if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM ||
-                               hdr->type==HDR_CALLID || hdr->type==HDR_TO ||
-                               hdr->type==HDR_CSEQ )
-                       len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) ;
+       len += 3/*code*/ + 1/*space*/ + str_len_text + CRLF_LEN/*new line*/;
+
+       /* force parsing all headers -- we want to return all
+           Via's in the reply and they may be scattered down to the
+          end of header (non-block Vias are a really poor property
+          of SIP :( )
+        */
+       parse_headers( msg, HDR_EOH );
+       /* check if I have those HFs identifying a transaction here */
+       if (!check_transaction_quadruple( msg ))
+               goto error;
+
+       first_via = 1;
+       for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) 
+               if (  hdr->type==HDR_FROM || 
+                       (hdr->type==HDR_VIA ?  (first_via ? first_via=0, 0: 1 ) : 0) ||
+                       hdr->type==HDR_CALLID || hdr->type==HDR_TO ||
+                       hdr->type==HDR_CSEQ )
+                       len += hdr->body.len  + hdr->name.len  + MY_HF_SEP_LEN + CRLF_LEN;
        /* end of message */
-       len += 1; /*new line*/
+       len += CRLF_LEN; /*new line*/
 
        /*allocating mem*/
        buf = (char*) malloc( len+1 );
@@ -545,30 +559,51 @@ char * build_res_buf_from_sip_req(        unsigned int code ,
                LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: out of memory\n");
                goto error;
        }
+       p=buf;
 
        /* filling the buffer*/
        /* first line */
        for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
-               *(p+i) = '0' + foo - ( foo/10 )*10;
+               *(p+i) = '0' + foo 10;
        p += 3;
        *(p++) = ' ' ;
-       memcpy( p , text , strlen(text) );
-       p += strlen(text);
-       *(p++) = '\n';
+       memcpy( p , text , str_len_text );
+       p += str_len_text;
+       memcpy( p, CRLF, CRLF_LEN );
+       p+=CRLF_LEN;
+       
        /* headers*/
+       first_via=1;
        for ( hdr=msg->headers ; hdr ; hdr=hdr->next )
-               if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM ||
-               hdr->type==HDR_CALLID || hdr->type==HDR_TO || hdr->type==HDR_CSEQ )
+               if ( hdr->type==HDR_FROM ||
+                               hdr->type==HDR_CALLID || hdr->type==HDR_TO ||
+                       (hdr->type==HDR_VIA ?  (first_via ? first_via=0, 0: 1 ) : 0) ||
+                               hdr->type==HDR_CSEQ )
                {
-                       memcpy( p , msg->orig+(hdr->name.s-msg->buf) ,
-                                       ((hdr->body.s+hdr->body.len ) -
-                                       hdr->name.s ) );
-                       p += ((hdr->body.s+hdr->body.len ) - hdr->name.s );
+                       char *end; int plen;
+
+                       end = hdr->name.s+hdr->name.len-1;
+                       plen= (*end==0) ? hdr->name.len - 1 : hdr->name.len;
+                       memcpy( p, hdr->name.s, plen );
+                       p+=plen;
+
+                       memcpy( p, MY_HF_SEP, MY_HF_SEP_LEN );
+                       p+=MY_HF_SEP_LEN;
+
+                       end = hdr->body.s+hdr->body.len-1;
+                       plen= (*end==0) ? hdr->body.len - 1 : hdr->body.len;
+                       memcpy( p, hdr->body.s, plen );
+                       p+=plen;
+                       memcpy( p, CRLF, CRLF_LEN );
+                       p+=CRLF_LEN;
                }
-
-       *(p++) = '\n';
+       memcpy( p, CRLF, CRLF_LEN );
+        p+=CRLF_LEN;
        *(p++) = 0;
-       *returned_len=len;
+       
+
+       /* *returned_len=len; */
+       *returned_len=p-buf;
        return buf;
 error:
        if (buf) free(buf);
index ddf8d43..cb81c0d 100644 (file)
@@ -5,6 +5,9 @@
 #ifndef  _MSG_TRANSLATOR_H
 #define _MSG_TRANSLATOR_H
 
+#define MY_HF_SEP ": "
+#define MY_HF_SEP_LEN 2
+
 #include "msg_parser.h"
 
 char * build_req_buf_from_sip_req (    struct sip_msg* msg, 
index b4561f4..cac7c54 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -111,8 +111,10 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 #ifdef STATS
        skipped = 0;
 #endif
+/* jku: skip no more used
 skip:
        DBG("skip:...\n");
+*/
        free_sip_msg(msg);
        pkg_free(msg);
 #ifdef STATS
index 3fdcbef..9989a09 100644 (file)
@@ -5,7 +5,7 @@ rev_dns=yes      # (cmd. line: -R)
 fork=no          # (cmd. line: -D)
 log_stderror=yes # (cmd line: -E)
 port=5080
-listen=127.0.0.1
+listen=192.168.99.100
 loop_checks=1
 # for more info: sip_router -h
 
@@ -21,21 +21,21 @@ route{
        if ( t_lookup_request()) {
                if ( method=="ACK" )    {
                        # XXX ... t_release not implemented yet
-                       log("t_release");
+                       log("SER: t_release\n");
                        #t_release();
                } else {
                        t_retransmit_reply();
-                       log("yet another annoying retranmission");
+                       log("SER: yet another annoying retranmission\n");
                };
        } else {
                t_add_transaction();
                if (method=="CANCEL") {
-                       log("new CANCEL");
+                       log("SER: new CANCEL\n");
                        # XXX ... it wants me to put status code in ""
                        t_send_reply( "200", "glad to cancel");
                } else {
-                       log("new transaction");
-                       #t_send_reply("100", "trying -- your call is important to us");
+                       log("SER: new transaction\n");
+                       t_send_reply("100", "trying -- your call is important to us");
                };
                #rewritehost("xy.com");
                # XXX ... it wants me to put port nr in ""
index ae46117..106b15c 100644 (file)
@@ -1,6 +1,6 @@
 SIP/2.0 200 Ok
 Via: SIP/2.0/UDP 127.0.0.1
-Via: SIP/2.0/UDP 127.0.0.1:5061
+Via: SIP/2.0/UDP 193.175.133.195:5060
 From: <sip:x@foo.bar>
 To: <sip:y@bar.foo>
 Call-ID:9437892232b@foo.bar
index d92b8b3..739cb8e 100644 (file)
@@ -8,6 +8,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <errno.h>
+#include <arpa/inet.h>
 
 
 #include "udp_server.h"
@@ -200,11 +201,50 @@ int udp_send(char *buf, unsigned len, struct sockaddr*  to, unsigned tolen)
 {
 
        int n;
+
+/*     struct sockaddr_in a2;*/
+
+#ifndef NO_DEBUG
+#define MAX_IP_LENGTH 18
+       char ip_txt[MAX_IP_LENGTH];
+       char *c;
+       struct sockaddr_in* a;
+       unsigned short p;
+
+       a=(struct sockaddr_in*) to;
+       memset(ip_txt, 0, MAX_IP_LENGTH);
+       c=inet_ntoa(a->sin_addr);
+       strncpy( ip_txt, c, MAX_IP_LENGTH - 1 );
+       p=ntohs(a->sin_port);
+       DBG("DEBUG: udp_send: ");
+
+       if (tolen < sizeof(struct sockaddr_in)) 
+               DBG("DEBUG: tolen small\n");
+       if (a->sin_family && a->sin_family != AF_INET) 
+               DBG("DEBUG: to not INET\n");
+       if (a->sin_port == 0) 
+               DBG("DEBUG: no port\n");
+
+       DBG(" destination: IP=%s, port=%u; packet:\n", ip_txt, p);
+       DBG(" destination (hex): IP=%x, port=%x;\n", a->sin_addr.s_addr, a->sin_port );
+       DBG("%*s\n", len, buf );
+#endif
+/*
+       memset(&a2, 0, sizeof(struct sockaddr_in));
+       a2.sin_family = a->sin_family;
+       a2.sin_port = a->sin_port;
+       a2.sin_addr.s_addr = a->sin_addr.s_addr;
+*/
+
 again:
        n=sendto(udp_sock, buf, len, 0, to, tolen);
+/*     n=sendto(udp_sock, buf, len, 0, &a2, sizeof(struct sockaddr_in) );*/
        if (n==-1){
                LOG(L_ERR, "ERROR: udp_send: sendto: %s\n", strerror(errno));
                if (errno==EINTR) goto again;
+               if (errno==EINVAL) LOG(L_CRIT,"CRITICAL: invalid sendtoparameters\n"
+                       "one possible reason is the server is bound to localhost and\n"
+                       "attempts to send to the net\n");
        }
        return n;
 }