ser_error processing, ipv6-ization of TM, new TM callbacks;
authorJiri Kuthan <jiri@iptel.org>
Fri, 31 May 2002 01:59:06 +0000 (01:59 +0000)
committerJiri Kuthan <jiri@iptel.org>
Fri, 31 May 2002 01:59:06 +0000 (01:59 +0000)
not stable yet (serial forking is screwed up)

24 files changed:
action.c
data_lump.c
error.c [new file with mode: 0644]
error.h
forward.c
modules/tm/h_table.c
modules/tm/h_table.h
modules/tm/t_fork.c [new file with mode: 0644]
modules/tm/t_fork.h [new file with mode: 0644]
modules/tm/t_funcs.c
modules/tm/t_funcs.h
modules/tm/t_fwd.c
modules/tm/t_hooks.h
modules/tm/t_lookup.c
modules/tm/t_msgbuilder.c [new file with mode: 0644]
modules/tm/t_reply.c
modules/tm/t_thandlers.c [new file with mode: 0644]
modules/tm/test.c [new file with mode: 0644]
modules/tm/tm.c
modules/tm/ut.h [new file with mode: 0644]
msg_translator.c
parser/msg_parser.c
parser/msg_parser.h
proxy.c

index 7ef9706..b7eb552 100644 (file)
--- a/action.c
+++ b/action.c
@@ -16,6 +16,7 @@
 #include "ut.h"
 #include "sr_module.h"
 #include "mem/mem.h"
+#include "globals.h"
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -48,6 +49,13 @@ int do_action(struct action* a, struct sip_msg* msg)
        struct sip_uri uri;
        unsigned short port;
 
+       /* reset the value of error to E_UNSPEC so avoid unknowledgable
+          functions to return with errror (status<0) and not setting it
+          leaving there previous error; cache the previous value though
+          for functions which want to process it */
+       prev_ser_error=ser_error;
+       ser_error=E_UNSPEC;
+
        ret=E_BUG;
        switch (a->type){
                case DROP_T:
@@ -63,10 +71,10 @@ int do_action(struct action* a, struct sip_msg* msg)
                                                tmp=msg->first_line.u.request.uri.s;
                                                len=msg->first_line.u.request.uri.len;
                                }
-                               if (parse_uri(tmp, len, &uri)<0){
+                               ret=parse_uri(tmp, len, &uri );
+                               if (ret<0) {
                                        LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
                                                                " dropping packet\n",tmp);
-                                       ret=E_UNSPEC;
                                        break;
                                }
                                switch (a->p2_type){
@@ -80,7 +88,7 @@ int do_action(struct action* a, struct sip_msg* msg)
                                                                                        LOG(L_ERR, "ERROR: do_action: "
                                                                                                "forward: bad port in "
                                                                                                "uri: <%s>\n", uri.port.s);
-                                                                                       ret=E_UNSPEC;
+                                                                                       ret=E_BAD_URI;
                                                                                        goto error_fwd_uri;
                                                                                }
                                                                        }else port=SIP_PORT;
index fba7eb2..9462b7b 100644 (file)
@@ -5,6 +5,8 @@
 #include "data_lump.h"
 #include "dprint.h"
 #include "mem/mem.h"
+#include "globals.h"
+#include "error.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -14,7 +16,6 @@
 #endif
 
 
-
 /* adds a header to the end
  * returns  pointer on success, 0 on error */
 struct lump* append_new_lump(struct lump** list, char* new_hdr,
@@ -75,6 +76,7 @@ struct lump* insert_new_lump_after( struct lump* after, char* new_hdr,
 
        tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR, "ERROR: insert_new_lump_after: out of memory\n");
                return 0;
        }
@@ -99,6 +101,7 @@ struct lump* insert_new_lump_before( struct lump* before, char* new_hdr,
 
        tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR,"ERROR: insert_new_lump_before: out of memory\n");
                return 0;
        }
@@ -152,6 +155,7 @@ struct lump* anchor_lump(struct lump** list, int offset, int len, int type)
 
        tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR, "ERROR: insert_new_lump_before: out of memory\n");
                return 0;
        }
diff --git a/error.c b/error.c
new file mode 100644 (file)
index 0000000..fb5b5f1
--- /dev/null
+++ b/error.c
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ */
+
+#include "error.h"
+
+/* current function's error; */
+int ser_error=-1;
+/* previous error */
+int prev_ser_error=-1;
+
+int err2reason_phrase( 
+       int ser_error,  /* current itnernal ser error */
+       int *sip_error,  /* the sip error code to which ser     
+                                           ser error will be turned */
+       char *phrase,    /* resulting error text */
+       int etl,                /* error text buffer length */
+       char *signature ) /* extra text to be appended */
+{
+
+       char *error_txt;
+
+       switch( ser_error ) {
+               case E_OUT_OF_MEM:
+                       error_txt="Excuse me I ran out of memory";
+                       *sip_error=500;
+                       break;
+               case E_SEND:
+                       error_txt="Unfortunately error on sending to next hop occured";
+                       *sip_error=-ser_error;
+                       break;
+               case E_BAD_ADDRESS:
+                       error_txt="Unresolveable destination";
+                       *sip_error=-ser_error;
+                       break;
+               case E_BAD_REQ:
+                       error_txt="Bad Request";
+                       *sip_error=-ser_error;
+                       break;
+               case E_BAD_URI:
+                       error_txt="Regretfuly, we were not able to process the URI";
+                       *sip_error=-ser_error;
+                       break;
+               default:
+                       error_txt="I'm terribly sorry, server error occured";
+                       *sip_error=500;
+                       break;
+       }
+       return snprintf( phrase, etl, "%s (%d/%s)", error_txt, 
+               -ser_error, signature );
+}
diff --git a/error.h b/error.h
index ab395e1..d71fd55 100644 (file)
--- a/error.h
+++ b/error.h
@@ -8,9 +8,27 @@
 #define E_UNSPEC      -1
 #define E_OUT_OF_MEM  -2
 #define E_BAD_RE      -3
-#define E_BAD_ADDRESS -4
+/* #define E_BAD_ADDRESS -4 */
 #define E_BUG         -5
 #define E_CFG         -6
+#define E_NO_SOCKET            -7
+
+#define E_SEND           -477
+/* unresolveable next-hop address */
+#define E_BAD_ADDRESS -478
+/* unparseable URI */
+#define E_BAD_URI        -479
+/* misformated request */
+#define E_BAD_REQ        -400
+
+#define MAX_REASON_LEN 128
+
+/* processing status of the last command */
+extern int ser_error;
+extern int prev_ser_error;
+
+int err2reason_phrase( int ser_error, int *sip_error, 
+                char *phrase, int etl, char *signature );
 
 
 #endif
index 732f5db..4a160ea 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -73,6 +73,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        
        to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
        if (to==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR, "ERROR: forward_request: out of memory\n");
                goto error;
        }
@@ -96,6 +97,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        if (send_sock==0){
                LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
                                "no coresponding listening socket\n", to->s.sa_family);
+               ser_error=E_NO_SOCKET;
                goto error;
        }
        
@@ -110,6 +112,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        
        if (udp_send( send_sock, buf, len,  to, 
                                                        sizeof(union sockaddr_union))==-1){
+                       ser_error=E_SEND;
                        p->errors++;
                        p->ok=0;
                        STATS_TX_DROPS;
index 153447c..373f4a8 100644 (file)
@@ -9,6 +9,8 @@
 #include "../../md5utils.h"
 /* bogdan test */
 #include "../../ut.h"
+#include "../../globals.h"
+#include "../../error.h"
 
 
 
@@ -75,8 +77,10 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 
        /* allocs a new cell */
        new_cell = (struct cell*)sh_malloc( sizeof( struct cell ) );
-       if  ( !new_cell )
+       if  ( !new_cell ) {
+               ser_error=E_OUT_OF_MEM;
                return NULL;
+       }
 
        /* filling with 0 */
        memset( new_cell, 0, sizeof( struct cell ) );
index 28089e3..d92388d 100644 (file)
@@ -54,7 +54,11 @@ typedef struct retr_buf
        char *cancel;
        int   cancel_len;
 
-       struct sockaddr_in to;
+       /* v6 changes; -jiri
+       struct sockaddr_in to; */
+       union sockaddr_union to;
+       struct socket_info* send_sock;
+
        size_t tolen;
 
        /* a message can be linked just to retransmission and FR list */
@@ -144,7 +148,9 @@ typedef struct cell
 
        /* this is where destination is stored for picked branch;
        good if a need to forward ACK later on */
-       struct sockaddr_in ack_to;
+       /* v6 changes; -jiri
+       struct sockaddr_in ack_to; */
+       union sockaddr_union ack_to;
 #ifndef        USE_SYNONIM
        /* MD5checksum */
        char md5[MD5_LEN];
diff --git a/modules/tm/t_fork.c b/modules/tm/t_fork.c
new file mode 100644 (file)
index 0000000..7d1e44d
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * forking requests
+ */
+
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../parser/parser_f.h"
+#include "../../ut.h"
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "t_fork.h"
+
+
+
+unsigned int     nr_forks;
+struct fork      t_forks[ NR_OF_CLIENTS ];
+
+
+int t_add_fork( union sockaddr_union to, char* uri_s,
+                       unsigned int uri_len, enum fork_type type, 
+                       unsigned char free_flag)
+{
+       unsigned int pos=0;
+       char         *foo=0;
+
+       switch (type)
+       {
+               case DEFAULT:
+                       if (nr_forks+1>=MAX_FORK)
+                       {
+                               LOG(L_ERR,"ERROR:t_add_fork: trying to add new fork ->"
+                                       " MAX_FORK exceded\n");
+                               return -1;
+                       }
+                       pos = ++nr_forks;
+                       break;
+               case NO_RESPONSE:
+                       /* v6; -Jiri
+                       if (t_forks[NO_RPL_BRANCH].ip)
+                       */
+                       if (!t_forks[NO_RPL_BRANCH].inactive)
+                               LOG(L_WARN,"WARNING:t_add_fork: trying to add NO_RPL fork ->"
+                                       " it was set before -> overriding\n");
+                       if (uri_s && uri_len)
+                       {
+                               foo = (char*)shm_malloc(uri_len);
+                               if (!foo)
+                               {
+                                       LOG(L_ERR,"ERROR:t_add_fork: cannot get free memory\n");
+                                       return -1;
+                               }
+                               memcpy(foo,uri_s,uri_len);
+                       }
+                       if (free_flag && uri_s)
+                               pkg_free(uri_s);
+                       uri_s = foo;
+                       free_flag = 0;
+                       pos = NO_RPL_BRANCH;
+       }
+       /* -v6
+       t_forks[pos].ip = ip;
+       t_forks[pos].port = port;
+       */
+       t_forks[pos].to=to;
+
+       if (uri_s && uri_len)
+       {
+               t_forks[pos].free_flag = free_flag;
+               t_forks[pos].uri.len = uri_len;
+               t_forks[pos].uri.s = uri_s;
+       }
+
+       return 1;
+}
+
+
+
+
+int t_clear_forks( )
+{
+       int i;
+
+       DBG("DEBUG: t_clear_forks: clearing tabel...\n");
+       for(i=1;i<nr_forks;i++)
+               if (t_forks[i].free_flag && t_forks[i].uri.s)
+                       pkg_free(t_forks[i].uri.s);
+       memset( t_forks, 0, sizeof(t_forks));
+       nr_forks = 0;
+       return 1;
+}
+
+
+
diff --git a/modules/tm/t_fork.h b/modules/tm/t_fork.h
new file mode 100644 (file)
index 0000000..dce7f73
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * $Id$
+ */
+
+#ifndef _T_FORKS_H
+#define _T_FORKS_H
+
+#include "../../ip_addr.h"
+#include "../../str.h"
+
+
+struct fork
+{
+    union sockaddr_union to;
+    char inactive;
+    unsigned char free_flag;
+    str           uri;
+
+};
+
+extern struct fork      t_forks[ NR_OF_CLIENTS ];
+extern unsigned int     nr_forks;
+
+int t_add_fork( union sockaddr_union to, char* uri_s,
+                               unsigned int uri_len, enum fork_type type,
+                               unsigned char free_flag);
+int t_clear_forks();
+
+
+#endif
index 322ac26..b14c65d 100644 (file)
@@ -1,38 +1,21 @@
 /*
  * $Id$
  *
+ * transaction maintenance functions
  */
 
-#include "hash_func.h"
-#include "t_funcs.h"
 #include "../../dprint.h"
 #include "../../config.h"
 #include "../../parser/parser_f.h"
 #include "../../ut.h"
-//#include "../../timer.h"
-
-
-
-#define  append_mem_block(_d,_s,_len) \
-               do{\
-                       memcpy((_d),(_s),(_len));\
-                       (_d) += (_len);\
-               }while(0);
-#define  req_line(_msg) \
-               ((_msg)->first_line.u.request)
-
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "t_fork.h"
 
 
 struct cell      *T;
 unsigned int     global_msg_id;
 struct s_table*  hash_table;
-unsigned int     nr_forks;
-struct fork      t_forks[ NR_OF_CLIENTS ];
-
-
-
-void timer_routine(unsigned int, void*);
-
 
 
 int tm_startup()
@@ -193,85 +176,6 @@ int t_update_timers_after_sending_reply( struct retr_buf *rb )
 
 
 
-/* Checks if the new reply (with new_code status) should be sent or not
- *  based on the current
- * transactin status.
- * Returns     - branch number (0,1,...) which should be relayed
- *         -1 if nothing to be relayed
- */
-int t_should_relay_response( struct cell *Trans , int new_code,
-                                                                       int branch , int *should_store )
-{
-       //int T_code;
-       int b, lowest_b, lowest_s;
-
-       //if (Trans->uas.request->REQ_METHOD==METHOD_INVITE)
-       //      T_code = Trans->uac[branch].status;
-       //else
-       //T_code = Trans->uas.status;
-
-       /* note: this code never lets replies to CANCEL go through;
-          we generate always a local 200 for CANCEL; 200s are
-          not relayed because it's not an INVITE transaction;
-          >= 300 are not relayed because 200 was already sent
-          out
-       */
-       DBG("->>>>>>>>> T_code=%d, new_code=%d\n",Trans->uas.status,new_code);
-       /* if final response sent out, allow only INVITE 2xx  */
-       if ( Trans->uas.status >= 200 ) {
-               if (new_code>=200 && new_code < 300  && 
-                       Trans->uas.request->REQ_METHOD==METHOD_INVITE) {
-                       DBG("DBG: t_should_relay: 200 INV after final sent\n");
-                       *should_store=1;
-                       return branch;
-               } else {
-                       *should_store=0;
-                       return -1;
-               }
-       } else { /* no final response sent yet */
-               /* negative replies subject to fork picking */
-               if (new_code >=300 ) {
-                       *should_store=1;
-                       /* if all_final return lowest */
-                       lowest_b=-1; lowest_s=999;
-                       for ( b=0; b<Trans->nr_of_outgoings ; b++ ) {
-                               /* "fake" for the currently processed branch */
-                               if (b==branch) {
-                                       if (new_code<lowest_s) {
-                                               lowest_b=b;
-                                               lowest_s=new_code;
-                                       }
-                                       continue;
-                               }
-                               /* there is still an unfinished UAC transaction; wait now! */
-                               if ( Trans->uac[b].status<200 )
-                                       return -1;
-                               if ( Trans->uac[b].status<lowest_s )
-                               {
-                                       lowest_b =b;
-                                       lowest_s = T->uac[b].status;
-                               }
-                       }
-                       return lowest_b;
-               /* 1xx except 100 and 2xx will be relayed */
-               } else if (new_code>100) {
-                       *should_store=1;
-                       return branch;
-               }
-               /* 100 won't be relayed */
-               else {
-                       if (!T->uac[branch].rpl_received) *should_store=1;
-                               else *should_store=0;
-                       if (Trans->uas.status==0) return branch;
-                               else return -1;
-               }
-       }
-
-       LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay\n");
-       abort();
-}
-
-
 /*
   */
 int t_put_on_wait(  struct cell  *Trans  )
@@ -325,147 +229,6 @@ int t_put_on_wait(  struct cell  *Trans  )
 
 
 
-/* Builds a CANCEL request based on an INVITE request. CANCEL is send
- * to same address as the INVITE */
-int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
-{
-       struct sip_msg      *p_msg;
-       struct hdr_field    *hdr;
-       char                *cancel_buf, *p, *via;
-       unsigned int         len, via_len;
-
-       if ( !Trans->uac[branch].rpl_received )
-       {
-               DBG("DEBUG: t_build_and_send_CANCEL: no response ever received"
-                       " : dropping local cancel! \n");
-               return 1;
-       }
-
-       if (Trans->uac[branch].request.cancel!=NO_CANCEL)
-       {
-               DBG("DEBUG: t_build_and_send_CANCEL: branch (%d)was already canceled"
-                       " : dropping local cancel! \n",branch);
-               return 1;
-       }
-
-       cancel_buf = 0;
-       via = 0;
-       p_msg = Trans->uas.request;
-
-       len = 0;
-       /*first line's len - CANCEL and INVITE has the same lenght */
-       len += ( req_line(p_msg).version.s+req_line(p_msg).version.len)-
-               req_line(p_msg).method.s+CRLF_LEN;
-       /*check if the REQ URI was override */
-       if (Trans->uac[branch].uri.s)
-               len += Trans->uac[branch].uri.len - req_line(p_msg).uri.len;
-       /*via*/
-       if ( add_branch_label(Trans,p_msg,branch)==-1 )
-               goto error;
-       via = via_builder( p_msg , &via_len );
-       if (!via)
-       {
-               LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: "
-                       "no via header got from builder\n");
-               goto error;
-       }
-       len+= via_len;
-       /*headers*/
-       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-               if (hdr->type==HDR_FROM || hdr->type==HDR_CALLID || 
-                       hdr->type==HDR_CSEQ || hdr->type==HDR_TO )
-                       len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN ;
-       /* User Agent header*/
-       len += USER_AGENT_LEN + CRLF_LEN;
-       /* Content Lenght heder*/
-       len += CONTENT_LEN_LEN + CRLF_LEN;
-       /* end of message */
-       len += CRLF_LEN;
-
-       cancel_buf=sh_malloc( len+1 );
-       if (!cancel_buf)
-       {
-               LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
-               goto error;
-       }
-       p = cancel_buf;
-
-       /* first line -> do we have a new URI? */
-       if (Trans->uac[branch].uri.s)
-       {
-               append_mem_block(p,req_line(p_msg).method.s,
-                       req_line(p_msg).uri.s-req_line(p_msg).method.s);
-               append_mem_block(p,Trans->uac[branch].uri.s,
-                       Trans->uac[branch].uri.len);
-               append_mem_block(p,req_line(p_msg).uri.s+req_line(p_msg).uri.len,
-                       req_line(p_msg).version.s+req_line(p_msg).version.len-
-                       (req_line(p_msg).uri.s+req_line(p_msg).uri.len))
-       }else{
-               append_mem_block(p,req_line(p_msg).method.s,
-                       req_line(p_msg).version.s+req_line(p_msg).version.len-
-                       req_line(p_msg).method.s);
-       }
-       /* changhing method name*/
-       memcpy(cancel_buf, CANCEL , CANCEL_LEN );
-       append_mem_block(p,CRLF,CRLF_LEN);
-       /* insert our via */
-       append_mem_block(p,via,via_len);
-
-       /*other headers*/
-       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-       {
-               if(hdr->type==HDR_FROM||hdr->type==HDR_CALLID||hdr->type==HDR_TO)
-               {
-                       append_mem_block(p,hdr->name.s,
-                               ((hdr->body.s+hdr->body.len)-hdr->name.s) );
-                       append_mem_block(p, CRLF, CRLF_LEN );
-               }else if ( hdr->type==HDR_CSEQ )
-               {
-                       append_mem_block(p,hdr->name.s,
-                               ((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
-                       append_mem_block(p, CANCEL CRLF, CANCEL_LEN +CRLF_LEN );
-               }
-}
-
-       /* User Agent header */
-       append_mem_block(p,USER_AGENT,USER_AGENT_LEN);
-       append_mem_block(p,CRLF,CRLF_LEN);
-       /* Content Lenght header*/
-       append_mem_block(p,CONTENT_LEN,CONTENT_LEN_LEN);
-       append_mem_block(p,CRLF,CRLF_LEN);
-       /* end of message */
-       append_mem_block(p,CRLF,CRLF_LEN);
-       *p=0;
-
-       if (Trans->uac[branch].request.cancel) {
-               shm_free( cancel_buf );
-               LOG(L_WARN, "send_cancel: Warning: CANCEL already sent out\n");
-               goto error;
-       }
-
-       Trans->uac[branch].request.activ_type = TYPE_LOCAL_CANCEL;
-       Trans->uac[branch].request.cancel = cancel_buf;
-       Trans->uac[branch].request.cancel_len = len;
-
-       /*sets and starts the FINAL RESPONSE timer */
-       set_timer(hash_table,&(Trans->uac[branch].request.fr_timer),FR_TIMER_LIST);
-       /* sets and starts the RETRANS timer */
-       Trans->uac[branch].request.retr_list = RT_T1_TO_1;
-       set_timer(hash_table,&(Trans->uac[branch].request.retr_timer),RT_T1_TO_1);
-       DBG("DEBUG: T_build_and_send_CANCEL : sending cancel...\n");
-       SEND_CANCEL_BUFFER( &(Trans->uac[branch].request) );
-
-       pkg_free(via);
-       return 1;
-error:
-       if (via) pkg_free(via);
-       return -1;
-}
-
-
-
-
-
 
 void delete_cell( struct cell *p_cell )
 {
@@ -524,492 +287,3 @@ void delete_cell( struct cell *p_cell )
 }
 
 
-
-
-/* Returns  -1 = error
-                    0 = OK
-*/
-int get_ip_and_port_from_uri( str *uri , unsigned int *param_ip, unsigned int *param_port)
-{
-       struct hostent  *nhost;
-       unsigned int    ip, port;
-       struct sip_uri  parsed_uri;
-       int             err;
-#ifdef DNS_IP_HACK
-       int             len;
-#endif
-
-       /* 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: %.*s\n", uri->len, uri->s );
-               goto error;
-       }
-
-       /* getting the port */
-       if ( parsed_uri.port.s==0 || parsed_uri.port.len==0 )
-               port = SIP_PORT;
-       else{
-               port = str2s( (unsigned char*) 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\turi:%.*s\n",
-                               uri->len, uri->s );
-                       port = SIP_PORT;
-               }
-       }
-       port = htons(port);
-
-       /* getting host address*/
-#ifdef DNS_IP_HACK
-       len=strlen( parsed_uri.host.s );
-       ip=str2ip( (unsigned char*)parsed_uri.host.s, len, &err);
-       if (err==0)
-               goto success;
-#endif
-       /* fail over to normal lookup */
-       nhost = gethostbyname( parsed_uri.host.s );
-       if ( !nhost )
-       {
-               LOG(L_ERR, "ERROR: get_ip_and_port_from_uri: "
-                 "cannot resolve host in uri: %.*s\n", uri->len, uri->s );
-               free_uri(&parsed_uri);
-               goto error;
-       }
-       memcpy(&ip, nhost->h_addr_list[0], sizeof(unsigned int));
-
-
-success:
-       free_uri(&parsed_uri);
-       *param_ip = ip;
-       *param_port = port;
-       return 0;
-
-error:
-       *param_ip = 0;
-       *param_port = 0;
-       return -1;
-}
-
-
-
-
-int t_add_fork( unsigned int ip, unsigned int port, char* uri_s,
-                       unsigned int uri_len, enum fork_type type, unsigned char free_flag)
-{
-       unsigned int pos=0;
-       char         *foo=0;
-
-       switch (type)
-       {
-               case DEFAULT:
-                       if (nr_forks+1>=MAX_FORK)
-                       {
-                               LOG(L_ERR,"ERROR:t_add_fork: trying to add new fork ->"
-                                       " MAX_FORK exceded\n");
-                               return -1;
-                       }
-                       pos = ++nr_forks;
-                       break;
-               case NO_RESPONSE:
-                       if (t_forks[NO_RPL_BRANCH].ip)
-                               LOG(L_WARN,"WARNING:t_add_fork: trying to add NO_RPL fork ->"
-                                       " it was set before -> overriding\n");
-                       if (uri_s && uri_len)
-                       {
-                               foo = (char*)shm_malloc(uri_len);
-                               if (!foo)
-                               {
-                                       LOG(L_ERR,"ERROR:t_add_fork: cannot get free memory\n");
-                                       return -1;
-                               }
-                               memcpy(foo,uri_s,uri_len);
-                       }
-                       if (free_flag && uri_s)
-                               pkg_free(uri_s);
-                       uri_s = foo;
-                       free_flag = 0;
-                       pos = NO_RPL_BRANCH;
-       }
-       t_forks[pos].ip = ip;
-       t_forks[pos].port = port;
-       if (uri_s && uri_len)
-       {
-               t_forks[pos].free_flag = free_flag;
-               t_forks[pos].uri.len = uri_len;
-               t_forks[pos].uri.s = uri_s;
-       }
-
-       return 1;
-}
-
-
-
-
-int t_clear_forks( )
-{
-       int i;
-
-       DBG("DEBUG: t_clear_forks: clearing tabel...\n");
-       for(i=1;i<nr_forks;i++)
-               if (t_forks[i].free_flag && t_forks[i].uri.s)
-                       pkg_free(t_forks[i].uri.s);
-       memset( t_forks, 0, sizeof(t_forks));
-       nr_forks = 0;
-       return 1;
-}
-
-
-
-
-
-/*---------------------------TIMERS FUNCTIONS-------------------------------*/
-
-
-
-
-
-inline void retransmission_handler( void *attr)
-{
-       struct retr_buf* r_buf ;
-       enum lists id;
-
-       r_buf = (struct retr_buf*)attr;
-#ifdef EXTRA_DEBUG
-       if (r_buf->my_T->damocles) {
-               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
-                       " called from RETR timer\n",r_buf->my_T);
-               abort();
-       }       
-#endif
-
-       /*the transaction is already removed from RETRANSMISSION_LIST by timer*/
-       /* retransmision */
-       DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
-       switch ( r_buf->activ_type )
-       {
-               case (TYPE_REQUEST):
-                       SEND_BUFFER( r_buf );
-                       break;
-               case (TYPE_LOCAL_CANCEL):
-                       SEND_CANCEL_BUFFER( r_buf );
-                       break;
-               default:
-                       T=r_buf->my_T;
-                       t_retransmit_reply();
-       }
-
-       id = r_buf->retr_list;
-       r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
-
-       set_timer(hash_table,&(r_buf->retr_timer),id < RT_T2 ? id + 1 : RT_T2 );
-
-       DBG("DEBUG: retransmission_handler : done\n");
-}
-
-
-
-
-inline void final_response_handler( void *attr)
-{
-       struct retr_buf* r_buf = (struct retr_buf*)attr;
-
-#ifdef EXTRA_DEBUG
-       if (r_buf->my_T->damocles) 
-       {
-               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
-                       " called from FR timer\n",r_buf->my_T);
-               abort();
-       }
-#endif
-
-       /* the transaction is already removed from FR_LIST by the timer */
-       if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
-       {
-               DBG("DEBUG: FR_handler: stop retransmission for Local Cancel\n");
-               reset_timer( hash_table , &(r_buf->retr_timer) );
-               return;
-       }
-       /* send a 408 */
-       if ( r_buf->my_T->uac[r_buf->branch].status<200
-#ifdef SILENT_FR
-       && (r_buf->my_T->nr_of_outgoings>1     /*if we have forked*/
-               || r_buf->my_T->uas.request->first_line.u.request.method_value!=
-                       METHOD_INVITE                  /*if is not an INVITE */
-               || r_buf->my_T->uac[r_buf->my_T->nr_of_outgoings].uri.s
-                                                  /*if "no on no response" was set*/
-               || r_buf->my_T->uac[r_buf->branch].rpl_received==0
-                                                                                       /*if no reply was received*/
-       )
-#endif
-       )
-       {
-               DBG("DEBUG: FR_handler:stop retr. and send CANCEL (%p)\n",r_buf->my_T);
-               reset_timer( hash_table, &(r_buf->retr_timer) );
-               t_build_and_send_CANCEL( r_buf->my_T ,r_buf->branch);
-               /* dirty hack:t_send_reply would increase ref_count which would indeed
-               result in refcount++ which would not -- until timer processe's
-               T changes again; currently only on next call to t_send_reply from
-               FR timer; thus I fake the values now to avoid recalculating T
-               and refcount++ JKU */
-               T=r_buf->my_T;
-               global_msg_id=T->uas.request->id;
-               DBG("DEBUG: FR_handler: send 408 (%p)\n", r_buf->my_T);
-               t_send_reply( r_buf->my_T->uas.request, 408, "Request Timeout",
-                       r_buf->branch);
-       }else{
-               /* put it on WT_LIST - transaction is over */
-               DBG("DEBUG: final_response_handler:-> put on wait"
-                       " (t=%p)\n", r_buf->my_T);
-               t_put_on_wait(  r_buf->my_T );
-       }
-       DBG("DEBUG: final_response_handler : done\n");
-}
-
-
-
-
-inline void wait_handler( void *attr)
-{
-       struct cell *p_cell = (struct cell*)attr;
-
-#ifdef EXTRA_DEBUG
-       if (p_cell->damocles) {
-               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
-                       " called from WAIT timer\n",p_cell);
-               abort();
-       }       
-#endif
-
-       /* the transaction is already removed from WT_LIST by the timer */
-       /* the cell is removed from the hash table */
-       DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
-       remove_from_hash_table( hash_table, p_cell );
-       /* jku: no more here -- we do it when we put a transaction on wait */
-       DBG("DEBUG: wait_handler : stopping all timers\n");
-       reset_retr_timers(hash_table,p_cell) ; 
-       /* put it on DEL_LIST - sch for del */
-#ifdef EXTRA_DEBUG
-       p_cell->damocles = 1;
-#endif
-       delete_cell( p_cell );
-       DBG("DEBUG: wait_handler : done\n");
-}
-
-
-
-
-inline void delete_handler( void *attr)
-{
-       struct cell *p_cell = (struct cell*)attr;
-
-       DBG("DEBUG: delete_handler : removing %p \n", p_cell );
-#ifdef EXTRA_DEBUG
-       if (p_cell->damocles==0) {
-               LOG( L_ERR, "ERROR: transaction %p not scheduled for deletion"
-                       " and called from DELETE timer\n",p_cell);
-               abort();
-       }       
-#endif
-       delete_cell( p_cell );
-    DBG("DEBUG: delete_handler : done\n");
-}
-
-
-
-
-#define run_handler_for_each( _tl , _handler ) \
-       while ((_tl))\
-       {\
-               /* reset the timer list linkage */\
-               tmp_tl = (_tl)->next_tl;\
-               (_tl)->next_tl = (_tl)->prev_tl = 0;\
-               DBG("DEBUG: timer routine:%d,tl=%p next=%p\n",\
-                       id,(_tl),tmp_tl);\
-               (_handler)( (_tl)->payload );\
-               (_tl) = tmp_tl;\
-       }
-
-
-
-
-void timer_routine(unsigned int ticks , void * attr)
-{
-       struct s_table    *hash_table = (struct s_table *)attr;
-       struct timer_link *tl, *tmp_tl;
-       int                id;
-
-#ifdef BOGDAN_TRIFLE
-       DBG(" %d \n",ticks);
-#endif
-
-       for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
-       {
-               /* to waste as little time in lock as possible, detach list
-                  with expired items and process them after leaving the lock */
-               tl=check_and_split_time_list( &(hash_table->timers[ id ]), ticks);
-               /* process items now */
-               switch (id)
-               {
-                       case FR_TIMER_LIST:
-                       case FR_INV_TIMER_LIST:
-                               run_handler_for_each(tl,final_response_handler);
-                               break;
-                       case RT_T1_TO_1:
-                       case RT_T1_TO_2:
-                       case RT_T1_TO_3:
-                       case RT_T2:
-                               run_handler_for_each(tl,retransmission_handler);
-                               break;
-                       case WT_TIMER_LIST:
-                               run_handler_for_each(tl,wait_handler);
-                               break;
-                       case DELETE_LIST:
-                               run_handler_for_each(tl,delete_handler);
-                               break;
-               }
-       }
-}
-
-
-
-
-
-
-
-/* Builds an ACK request based on an INVITE request. ACK is send
- * to same address */
-char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,int *ret_len)
-{
-       struct sip_msg      *p_msg , *r_msg;
-       struct hdr_field    *hdr;
-       char                *ack_buf, *p, *via;
-       unsigned int         len, via_len;
-
-       ack_buf = 0;
-       via =0;
-       p_msg = trans->uas.request;
-       r_msg = rpl;
-
-       if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
-       {
-               LOG(L_ERR, "ERROR: t_build_ACK: "
-                       "cannot generate a HBH ACK if key HFs in reply missing\n");
-               goto error;
-       }
-
-       len = 0;
-       /*first line's len */
-       len += 4/*reply code and one space*/+
-               p_msg->first_line.u.request.version.len+CRLF_LEN;
-       /*uri's len*/
-       if (trans->uac[branch].uri.s)
-               len += trans->uac[branch].uri.len +1;
-       else
-               len += p_msg->first_line.u.request.uri.len +1;
-       /*adding branch param*/
-       if ( add_branch_label( trans , trans->uas.request , branch)==-1 )
-               goto error;
-       /*via*/
-       via = via_builder( p_msg , &via_len );
-       if (!via)
-       {
-               LOG(L_ERR, "ERROR: t_build_ACK: "
-                       "no via header got from builder\n");
-               goto error;
-       }
-       len+= via_len;
-       /*headers*/
-       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-               if (hdr->type==HDR_FROM||hdr->type==HDR_CALLID||hdr->type==HDR_CSEQ)
-                       len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN ;
-               else if ( hdr->type==HDR_TO )
-                       len += ((r_msg->to->body.s+r_msg->to->body.len ) -
-                               r_msg->to->name.s ) + CRLF_LEN ;
-       /* CSEQ method : from INVITE-> ACK */
-       len -= 3  ;
-       /* end of message */
-       len += CRLF_LEN; /*new line*/
-
-       ack_buf = sh_malloc(len+1);
-       if (!ack_buf)
-       {
-               LOG(L_ERR, "ERROR: t_build_and_ACK: cannot allocate memory\n");
-               goto error1;
-       }
-       p = ack_buf;
-
-       /* first line */
-       memcpy( p , "ACK " , 4);
-       p += 4;
-       /* uri */
-       if ( trans->uac[branch].uri.s )
-       {
-               memcpy(p,trans->uac[branch].uri.s,trans->uac[branch].uri.len);
-               p +=trans->uac[branch].uri.len;
-       }else{
-               memcpy(p,p_msg->orig+(p_msg->first_line.u.request.uri.s-p_msg->buf),
-                       p_msg->first_line.u.request.uri.len );
-               p += p_msg->first_line.u.request.uri.len;
-       }
-       /* SIP version */
-       *(p++) = ' ';
-       memcpy(p,p_msg->orig+(p_msg->first_line.u.request.version.s-p_msg->buf),
-               p_msg->first_line.u.request.version.len );
-       p += p_msg->first_line.u.request.version.len;
-       memcpy( p, CRLF, CRLF_LEN );
-       p+=CRLF_LEN;
-
-       /* insert our via */
-       memcpy( p , via , via_len );
-       p += via_len;
-
-       /*other headers*/
-       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
-       {
-               if ( hdr->type==HDR_FROM || hdr->type==HDR_CALLID  )
-               {
-                       memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
-                               ((hdr->body.s+hdr->body.len ) - hdr->name.s ) );
-                       p += ((hdr->body.s+hdr->body.len ) - hdr->name.s );
-                       memcpy( p, CRLF, CRLF_LEN );
-                       p+=CRLF_LEN;
-               }
-               else if ( hdr->type==HDR_TO )
-               {
-                       memcpy( p , r_msg->orig+(r_msg->to->name.s-r_msg->buf) ,
-                               ((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s));
-                       p+=((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s);
-                       memcpy( p, CRLF, CRLF_LEN );
-                       p+=CRLF_LEN;
-               }
-               else if ( hdr->type==HDR_CSEQ )
-               {
-                       memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
-                               ((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
-                       p+=((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s);
-                       memcpy( p , "ACK" CRLF, 3+CRLF_LEN );
-                       p += 3+CRLF_LEN;
-               }
-       }
-
-       /* end of message */
-       memcpy( p , CRLF , CRLF_LEN );
-       p += CRLF_LEN;
-
-       pkg_free( via );
-       DBG("DEBUG: t_build_ACK: ACK generated\n");
-
-       *(ret_len) = p-ack_buf;
-       return ack_buf;
-
-error1:
-       pkg_free(via );
-error:
-       return 0;
-}
-
-
-
index 3985b6a..6cdcf81 100644 (file)
 #include "../../timer.h"
 #include "../../forward.h"
 #include "../../mem/mem.h"
-
 #include "../../md5utils.h"
+#include "../../ip_addr.h"
 
 #include "config.h"
 #include "lock.h"
 #include "timer.h"
+#include "sh_malloc.h"
+#include "sip_msg.h"
 
 
 struct s_table;
@@ -30,27 +32,10 @@ struct timer;
 struct entry;
 struct cell;
 
-struct fork
-{
-       unsigned int  ip,port;
-       unsigned char free_flag;
-       str           uri;
-
-};
-
-
 extern struct cell      *T;
 extern unsigned int     global_msg_id;
 extern struct s_table*  hash_table;
-extern struct fork      t_forks[ NR_OF_CLIENTS ];
-extern unsigned int     nr_forks;
-
-
-#include "sh_malloc.h"
 
-#include "timer.h"
-#include "lock.h"
-#include "sip_msg.h"
 
 
 #define LOCK_REPLIES(_t) lock(&(_t)->reply_mutex )
@@ -66,17 +51,35 @@ extern unsigned int     nr_forks;
    for reducing time spend in REPLIES locks
 */
 
-#define SEND_PR_BUFFER(_rb,_bf,_le ) \
-       {\
-               if ((_bf) && (_le) && (_bf) ) {\
-                       udp_send( (_bf), (_le), (struct sockaddr*)&((_rb)->to) , \
-                               sizeof(struct sockaddr_in) ); \
-               }else{ \
-                       LOG(L_CRIT,"ERROR: sending an empty buffer from %s (%d)\n",\
-                               __FUNCTION__, __LINE__ );\
-               }\
+inline static int send_pr_buffer( struct retr_buf *rb,
+       void *buf, int len, char *function, int line )
+{
+       if (buf && len && rb )
+               return udp_send( rb->send_sock, buf, 
+                       len, &rb->to,  sizeof(union sockaddr_union) ) ;
+       else {
+               LOG(L_CRIT, "ERROR: sending an empty buffer from %s (%d)\n",
+                       function, line );
+               return -1;
        }
+}
+
+#define SEND_PR_BUFFER(_rb,_bf,_le ) \
+       send_pr_buffer( (_rb), (_bf), (_le),  __FUNCTION__, __LINE__ )
 
+/*
+#define SEND_PR_BUFFER(_rb,_bf,_le ) \
+       ( ((_bf) && (_le) && (_bf)) ? \
+       udp_send( (_bf), (_le), &((_rb)->to), sizeof(union sockaddr_union) ) : \
+       log_send_error( __FUNCTION__, __LINE__ ) )
+*/
+
+/* just for understanding of authors of the following macros, who did not
+   include 'PR' in macro names though they use 'PR' macro: PR stands for
+   PRIVATE and indicates usage of memory buffers in PRIVATE memory space,
+   where -- as opposed to SHARED memory space -- no concurrent memory
+   access can occur and thus no locking is needed ! -jiri
+*/
 #define SEND_ACK_BUFFER( _rb ) \
        SEND_PR_BUFFER( (_rb) , (_rb)->ack , (_rb)->ack_len )
 
@@ -134,9 +137,10 @@ extern unsigned int     nr_forks;
 
 
 
-
+/*
 enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK,
        AIN_OLDACK, AIN_RTRACK } ;
+*/
 
 
 int   tm_startup();
@@ -165,8 +169,10 @@ int t_check( struct sip_msg* , int *branch , int* is_cancel);
  *       1 - forward successfull
  *      -1 - error during forward
  */
+/* v6; -jiri
 int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
                                                                                unsigned int dst_port);
+*/
 
 
 
@@ -175,7 +181,9 @@ int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
  *       1 - forward successfull
  *      -1 - error during forward
  */
+/* v6; -jiri
 int t_forward_uri( struct sip_msg* p_msg  );
+*/
 
 
 
@@ -239,11 +247,16 @@ int t_unref( /* struct sip_msg* p_msg */ );
 
 
 
-
+/* v6; -jiri
 int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
        unsigned int dest_port_param );
 int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
        unsigned int dest_port_param );
+*/
+int t_forward_nonack( struct sip_msg* p_msg, struct proxy_l * p );
+int t_forward_ack( struct sip_msg* p_msg );
+
+
 int forward_serial_branch(struct cell* Trans,int branch);
 struct cell* t_lookupOriginalT(  struct s_table* hash_table,
        struct sip_msg* p_msg );
@@ -264,10 +277,11 @@ int get_ip_and_port_from_uri( str* uri , unsigned int *param_ip,
 int t_build_and_send_CANCEL(struct cell *Trans, unsigned int branch);
 char *build_ack( struct sip_msg* rpl, struct cell *trans, int branch ,
        int *ret_len);
-enum addifnew_status t_addifnew( struct sip_msg* p_msg );
-int t_add_fork( unsigned int ip , unsigned int port, char* uri_s,
-       unsigned int uri_len, enum fork_type type, unsigned char free_flag);
-int t_clear_forks( );
+
+int t_addifnew( struct sip_msg* p_msg );
+
+void timer_routine(unsigned int, void*);
+
 
 
 
@@ -356,7 +370,9 @@ static inline void reset_retr_timers( struct s_table *h_table,
        DBG("DEBUG:stop_RETR_and_FR_timers : timers stopped\n");
 }
 
+void delete_cell( struct cell *p_cell );
 
+int t_newtran( struct sip_msg* p_msg );
 
 #endif
 
index 53d13a6..1fbca2a 100644 (file)
@@ -3,13 +3,14 @@
  *
  */
 
-#include "hash_func.h"
-#include "t_funcs.h"
 #include "../../dprint.h"
 #include "../../config.h"
 #include "../../parser/parser_f.h"
 #include "../../ut.h"
 #include "../../timer.h"
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "t_fork.h"
 
 #include "t_hooks.h"
 
  *       1 - forward successfull
  *      -1 - error during forward
  */
-int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
+int t_forward_nonack( struct sip_msg* p_msg , 
+                                         struct proxy_l * p )
+/* v6; -jiri                                                                   unsigned int dest_ip_param ,
                                                                                                unsigned int dest_port_param )
+*/
 {
        int          branch;
        unsigned int len;
@@ -38,20 +42,18 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
        struct cell  *T_source = T;
        struct lump  *a,*b,*b1,*c;
        str          backup_uri;
+       int                      ret;
+       struct socket_info* send_sock;
+       union sockaddr_union to;
 
 
+       /* default error value == -1; be more specific if you want to */
+       ret=-1;
        buf    = 0;
        shbuf  = 0;
        backup_uri.s = p_msg->new_uri.s;
        backup_uri.len = p_msg->new_uri.len;
 
-       /* sets as first fork the default outgoing */
-       nr_forks++;
-       t_forks[0].ip = dest_ip_param;
-       t_forks[0].port = dest_port_param;
-       t_forks[0].uri.len = p_msg->new_uri.len;
-       t_forks[0].uri.s =  p_msg->new_uri.s;
-       t_forks[0].free_flag = 0;
 
 
        /* are we forwarding for the first time? */
@@ -61,9 +63,32 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                   somewhere else */
                LOG( L_CRIT, "ERROR: t_forward_nonack: attempt to rewrite"
                        " request structures\n");
+               ser_error=E_BUG;
                return 0;
        }
 
+       /* v6; -jiri ... copynpasted from forward_request */
+       /* if error try next ip address if possible */
+       if (p->ok==0){
+               if (p->host.h_addr_list[p->addr_idx+1])
+                       p->addr_idx++;
+               else p->addr_idx=0;
+               p->ok=1;
+       }
+       hostent2su(&to, &p->host, p->addr_idx,
+       (p->port)?htons(p->port):htons(SIP_PORT));
+
+       /* sets as first fork the default outgoing */
+       nr_forks++;
+       /* v6; -jiri
+       t_forks[0].ip = dest_ip_param;
+       t_forks[0].port = dest_port_param;
+       */
+       t_forks[0].to=to;
+       t_forks[0].uri.len = p_msg->new_uri.len;
+       t_forks[0].uri.s =  p_msg->new_uri.s;
+       t_forks[0].free_flag = 0;
+
        DBG("DEBUG: t_forward_nonack: first time forwarding\n");
        /* special case : CANCEL */
        if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
@@ -83,10 +108,14 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                                {
                                        DBG("DEBUG: t_forward_nonack: branch %d not finalize"
                                                ": sending CANCEL for it\n",nr_forks);
+                                       /* v6; -jiri
                                        t_forks[nr_forks].ip =
-                                         T->T_canceled->uac[nr_forks].request.to.sin_addr.s_addr;
+                                         T->T_canceled->uac[nr_forks].request.to.sin_addr.s_addr; 
                                        t_forks[nr_forks].port =
                                          T->T_canceled->uac[nr_forks].request.to.sin_port;
+                                       */
+                                       t_forks[nr_forks].to = T->T_canceled->uac[nr_forks].request.to;
+
                                        t_forks[nr_forks].uri.len =
                                          T->T_canceled->uac[nr_forks].uri.len;
                                        t_forks[nr_forks].uri.s =
@@ -96,7 +125,10 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                                        /* transaction exists, but nothing to cancel */
                                        DBG("DEBUG: t_forward_nonack: branch %d finalized"
                                                ": no CANCEL sent here\n",nr_forks);
+                                       /* -v6; -jiri
                                        t_forks[nr_forks].ip = 0;
+                                       */
+                                       t_forks[nr_forks].inactive= 1;
                                }
                        }
 #ifdef USE_SYNONIM
@@ -110,14 +142,16 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
        }/* end special case CANCEL*/
 
 #ifndef USE_SYNONIM
-       if ( nr_forks && add_branch_label( T_source, T->uas.request , 0 )==-1)
+       branch=0;
+       if ( nr_forks && add_branch_label( T_source, T->uas.request , branch )==-1)
                goto error;
 #endif
 
        DBG("DEBUG: t_forward_nonack: nr_forks=%d\n",nr_forks);
        for(branch=0;branch<nr_forks;branch++)
        {
-               if (!t_forks[branch].ip)
+               /* -v6; -jiri if (!t_forks[branch].ip) */
+               if (t_forks[branch].inactive)
                        goto end_loop;
                DBG("DEBUG: t_forward_nonack: branch = %d\n",branch);
                /*generates branch param*/
@@ -139,8 +173,24 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                /* updates the new uri*/
                p_msg->new_uri.s = t_forks[branch].uri.s;
                p_msg->new_uri.len = t_forks[branch].uri.len;
-               if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))
+
+               T->uac[branch].request.to = t_forks[branch].to;
+               send_sock=get_send_socket( & T->uac[branch].request.to );
+               if (send_sock==0) {
+                       LOG(L_ERR, "ERROR: t_forward_nonack: can't fwd to af %d "
+                               "no corresponding listening socket\n", 
+                               T->uac[branch].request.to.s.sa_family);
+                       ser_error=E_NO_SOCKET;
                        goto error;
+               }
+               T->uac[branch].request.send_sock=send_sock;
+               
+               callback_event( TMCB_REQUEST_OUT, p_msg );      
+               /* _test_insert_to_reply(p_msg, "Foo: Bar\r\n");*/
+               if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len, send_sock ))) {
+                       ser_error=ret=E_OUT_OF_MEM;
+                       goto error;
+               }
                /* allocates a new retrans_buff for the outbound request */
                DBG("DEBUG: t_forward_nonack: building outbound request"
                        " for branch %d.\n",branch);
@@ -148,6 +198,7 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                if (!shbuf)
                {
                        LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem buffer\n");
+                       ser_error=ret=E_OUT_OF_MEM;
                        goto error;
                }
                T->uac[branch].request.buffer = shbuf;
@@ -159,10 +210,22 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
                T->uac[branch].uri.len=t_forks[branch].uri.s?(t_forks[branch].uri.len)
                        :(p_msg->first_line.u.request.uri.len);
                /* send the request */
+               /* v6; -jiri
                T->uac[branch].request.to.sin_addr.s_addr = t_forks[branch].ip;
                T->uac[branch].request.to.sin_port = t_forks[branch].port;
                T->uac[branch].request.to.sin_family = AF_INET;
-               SEND_BUFFER( &(T->uac[branch].request) );
+               */
+               T->uac[branch].request.to = t_forks[branch].to;
+               p->tx++;
+               p->tx_bytes+=len;
+               if (SEND_BUFFER( &(T->uac[branch].request) )==-1) {
+                       p->errors++;
+                       p->ok=0;
+                       ser_error=ret=E_SEND;
+                       goto error;
+               }
+               /* should have p->errors++; p->ok=0; on error here... */
+
 
                pkg_free( buf ) ;
                buf=NULL;
@@ -185,11 +248,17 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
 
        /* if we have a branch spec. for NO_RESPONSE_RECEIVED, we have to 
        move it immediatly after the last parallel branch */
-       if (t_forks[NO_RPL_BRANCH].ip && T->nr_of_outgoings!=NO_RPL_BRANCH )
+       /* v6; -jiri 
+       if (t_forks[NO_RPL_BRANCH].ip && T->nr_of_outgoings!=NO_RPL_BRANCH ) */
+       if (!t_forks[NO_RPL_BRANCH].inactive && T->nr_of_outgoings!=NO_RPL_BRANCH )
        {
                branch = T->nr_of_outgoings;
+               /* v6; -jiri
                T->uac[branch].request.to.sin_addr.s_addr = t_forks[NO_RPL_BRANCH].ip;
                T->uac[branch].request.to.sin_port = t_forks[NO_RPL_BRANCH].port;
+               */
+               T->uac[branch].request.to = t_forks[NO_RPL_BRANCH].to;
+
                T->uac[branch].uri.s = t_forks[NO_RPL_BRANCH].uri.s;
                T->uac[branch].uri.len = t_forks[NO_RPL_BRANCH].uri.len;
        }
@@ -205,22 +274,17 @@ error:
        p_msg->new_uri.s = backup_uri.s;
        p_msg->new_uri.len = backup_uri.len;
        t_clear_forks();
-       return -1;
+       return ret;
 }
 
 
+#ifdef _YOU_DONT_REALLY_WANT_THIS
 
-
-int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
-                                                                               unsigned int dest_port_param )
+int t_forward_ack( struct sip_msg* p_msg  )
 {
        int branch;
        unsigned int len;
        char *buf, *ack;
-#ifdef _DONT_USE
-       struct sockaddr_in to_sock;
-#endif
-
 
        /* drop local ACKs */
        if (T->uas.status/100!=2 ) {
@@ -272,21 +336,9 @@ int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param ,
        SEND_PR_BUFFER( &(T->uac[branch].request), ack, len );
        callback_event( TMCB_E2EACK, p_msg );
        return attach_ack( T, branch, ack , len );
+}
 
-#ifdef _DON_USE
-fwd_sl: /* some strange conditions occured; try statelessly */
-       LOG(L_ERR, "ERROR: fwd-ing a 2xx ACK with T-state failed; "
-               "trying statelessly\n");
-       memset( &to_sock, sizeof to_sock, 0 );
-       to_sock.sin_family = AF_INET;
-       to_sock.sin_port =  dest_port_param;
-       to_sock.sin_addr.s_addr = dest_ip_param;
-       udp_send( buf, len, (struct sockaddr*)(&to_sock), 
-               sizeof(struct sockaddr_in) );
-       free( buf );
-       return 1;
 #endif
-}
 
 
 
@@ -298,6 +350,8 @@ int forward_serial_branch(struct cell* Trans,int branch)
        unsigned int     len;
        char             *buf=0, *shbuf=0;
        str              backup_uri;
+       union sockaddr_union *to;
+       struct socket_info* send_sock;
 
        backup_uri.s = p_msg->new_uri.s;
        backup_uri.len = p_msg->new_uri.len;
@@ -324,7 +378,16 @@ int forward_serial_branch(struct cell* Trans,int branch)
        /* updates the new uri*/
        p_msg->new_uri.s = Trans->uac[branch].uri.s;
        p_msg->new_uri.len = Trans->uac[branch].uri.len;
-       if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))
+
+       to=&Trans->uac[branch].request.to;
+       send_sock=get_send_socket(to);
+       if (send_sock==0) {
+               LOG(L_ERR, "ERROR: t_forward_nonack: can't fwd to af %d "
+               "no corresponding listening socket\n", to->s.sa_family );
+               ser_error=E_NO_SOCKET;
+               goto error;
+       }
+       if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len, send_sock )))
                goto error;
        shm_free(Trans->uac[branch].uri.s);
 
@@ -345,7 +408,7 @@ int forward_serial_branch(struct cell* Trans,int branch)
                :(p_msg->first_line.u.request.uri.len);
        Trans->nr_of_outgoings++ ;
        /* send the request */
-       Trans->uac[branch].request.to.sin_family = AF_INET;
+       /* -v6; -jiri Trans->uac[branch].request.to.sin_family = AF_INET; */
        SEND_BUFFER( &(T->uac[branch].request) );
 
        pkg_free( buf ) ;
index 4fe6f95..6398b41 100644 (file)
@@ -8,7 +8,7 @@
 #include "h_table.h"
 #include "t_funcs.h"
 
-typedef enum { TMCB_REPLY,  TMCB_E2EACK, TMCB_END } tmcb_type;
+typedef enum { TMCB_REPLY,  TMCB_E2EACK, TMCB_REPLY_IN, TMCB_REQUEST_OUT, TMCB_END } tmcb_type;
 
 typedef void (transaction_cb) ( struct cell* t, struct sip_msg* msg );
 
index 872c2c6..b9efcb4 100644 (file)
@@ -37,6 +37,7 @@
 #include "t_funcs.h"
 #include "config.h"
 #include "sip_msg.h"
+#include "t_hooks.h"
 
 
 #define EQ_LEN(_hf) (t_msg->_hf->body.len==p_msg->_hf->body.len)
        )==0 )
 
 
+/* function returns:
+ *      negative - transaction wasn't found
+ *                     (-2 = possibly e2e ACK matched )
+ *      positive - transaction found
+ */
+
+int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
+{
+       struct cell         *p_cell;
+       unsigned int       isACK;
+       struct sip_msg  *t_msg;
+       int ret;
+
+       /* 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 */
+               return 0;
+       }
+
+       /* start searching into the table */
+       p_msg->hash_index=hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
+       isACK = p_msg->REQ_METHOD==METHOD_ACK;
+       DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
+               p_msg->hash_index,isACK);
+
+       /* asume not found */
+       ret=-1;
+
+       /* lock the hole entry*/
+       lock(&(hash_table->entrys[p_msg->hash_index].mutex));
+
+       /* all the transactions from the entry are compared */
+       for ( p_cell = hash_table->entrys[p_msg->hash_index].first_cell;
+                 p_cell; p_cell = p_cell->next_cell ) 
+       {
+               t_msg = p_cell->uas.request;
+
+               if (!isACK) {   
+                       /* compare lengths first */ 
+                       if (!EQ_LEN(callid)) continue;
+                       if (!EQ_LEN(cseq)) continue;
+                       if (!EQ_LEN(from)) continue;
+                       if (!EQ_LEN(to)) continue;
+                       if (!EQ_REQ_URI_LEN) continue;
+                       if (!EQ_VIA_LEN(via1)) continue;
+
+                       /* length ok -- move on */
+                       if (!EQ_STR(callid)) continue;
+                       if (!EQ_STR(cseq)) continue;
+                       if (!EQ_STR(from)) continue;
+                       if (!EQ_STR(to)) continue;
+                       if (!EQ_REQ_URI_STR) continue;
+                       if (!EQ_VIA_STR(via1)) continue;
+
+                       /* request matched ! */
+                       DBG("DEBUG: non-ACK matched\n");
+                       goto found;
+               } else { /* it's an ACK request*/
+                       /* ACK's relate only to INVITEs */
+                       if (t_msg->REQ_METHOD!=METHOD_INVITE) continue;
+
+                       /* compare lengths now */
+                       if (!EQ_LEN(callid)) continue;
+                       /* CSeq only the number without method ! */
+                       if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
+                               continue;
+                       if (! EQ_LEN(from)) continue;
+                       /* To only the uri and ... */
+                       if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len)
+                               continue;
+                       /* ... its to-tag compared to reply's tag */
+                       if (p_cell->uas.tag->len!=get_to(p_msg)->tag_value.len)
+                               continue;
+
+                       /* we first skip r-uri and Via and proceed with
+                          content of other header-fields */
+
+                       if ( memcmp(t_msg->callid->body.s, p_msg->callid->body.s,
+                               p_msg->callid->body.len)!=0) continue;
+                       if ( memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
+                               get_cseq(p_msg)->number.len)!=0) continue;
+                       if (!EQ_STR(from)) continue;
+                       if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s,
+                               get_to(t_msg)->uri.len)!=0) continue;
+                       if (memcmp(p_cell->uas.tag->s, get_to(p_msg)->tag_value.s,
+                               p_cell->uas.tag->len)!=0) continue;
+       
+                       /* ok, now only r-uri or via can mismatch; they must match
+                          for non-2xx; if it is a 2xx, we don't try to match
+                          (we might have checked that earlier to speed-up, but
+                          we still want to see a diagnosti message telling
+                          "this ACK presumably belongs to this 2xx transaction";
+                          might change in future); the reason is 2xx ACKs are
+                          a separate transaction which may carry different
+                          r-uri/via1 and is thus also impossible to match it
+                          uniquely to a spiraled transaction;
+                       */
+                       if (p_cell->uas.status>=200 && p_cell->uas.status<300) {
+                               DBG("DEBUG: an ACK hit a 2xx transaction (T=%p); "
+                                       "considered mismatch\n", p_cell );
+                               /* perhaps there are some spirals on the synonym list, but
+                                  it makes no sense to iterate the list until bitter end */
+                               ret=-2;
+                               break;
+                       }
+                       /* its for a >= 300 ... everything must match ! */
+                       if (! EQ_REQ_URI_LEN ) continue;
+                       if (! EQ_VIA_LEN(via1)) continue;
+                       if (!EQ_REQ_URI_STR) continue;
+                       if (!EQ_VIA_STR(via1)) continue;
+
+                       /* wow -- we survived all the check! we matched! */
+                       DBG("DEBUG: non-2xx ACK matched\n");
+                       goto found;
+               } /* ACK */
+       } /* synonym loop */
+
+       /* no transaction found */
+       T = 0;
+       if (!leave_new_locked)
+               unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
+       DBG("DEBUG: t_lookup_request: no transaction found\n");
+       return ret;
+
+found:
+       T=p_cell;
+       T_REF( T );
+       DBG("DEBUG: t_lookup_request: transaction found (T=%p , ref=%x)\n",
+               T,T->ref_bitmap);
+       unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
+       return 1;
+}
+
+
+#ifdef __YOU_DONT_WANT_TO_DO_THIS
 
 /* function returns:
  *      -1 - transaction wasn't found
@@ -213,6 +352,7 @@ found:
        return 1;
 }
 
+#endif
 
 
 
@@ -560,7 +700,7 @@ int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
 }
 
 
-
+#ifdef _YOU_DONT_REALLY_WANT_THIS
 
 /* atomic "add_if_new" construct; it returns:
        AIN_ERROR       if a fatal error (e.g, parsing) occured
@@ -635,4 +775,81 @@ enum addifnew_status t_addifnew( struct sip_msg* p_msg )
 }
 
 
+#endif
+
+
+/* atomic "new_tran" construct; it returns:
+
+       -1      if      a request matched a transaction
+               - if that was an ack, the calling function
+                 shall reset timers
+               - otherwise the calling function shall 
+                 attempt to retransmit
+
+       +1      if a request did not match a transaction
+               - it that was an ack, the calling function
+                 shall forward statelessy
+               - otherwise it means, a new transaction was
+                 introduced and the calling function
+                 shall reply/relay/whatever_appropriate
+
+       0 on error
+*/
+int t_newtran( struct sip_msg* p_msg )
+{
+
+       int ret, lret;
+       struct cell *new_cell;
+
+       /* is T still up-to-date ? */
+       DBG("DEBUG: t_addifnew: msg id=%d , global msg id=%d ,"
+               " T on entrance=%p\n",p_msg->id,global_msg_id,T);
+
+       if ( !(p_msg->id != global_msg_id || T==T_UNDEFINED 
+               /* if someone tried to do something previously by mistake with
+                  a transaction which did not exist yet, try to look-up
+                  the transacion too */
+               || T==T_NULL)) 
+       {
+               LOG(L_ERR, "ERROR: t_newtran: alreaddy processing this message"
+                       ", T %s found\n", T ? "" : "not" );
+               return 0;
+       }
+
+       global_msg_id = p_msg->id;
+       T = T_UNDEFINED;
+       /* transaction lookup */
+       /* force parsing all the needed headers*/
+       if (parse_headers(p_msg, HDR_EOH )==-1)
+               return 0;
+       lret = t_lookup_request( p_msg, 1 /* leave locked */ );
+       /* on error, pass the error in the stack ... */
+       if (lret==0) return 0;
+       if (lret<0) {
+               /* transaction not found, it's a new request;
+                  establish a new transaction (unless it is an ACK) */
+               ret=1;
+               if ( p_msg->REQ_METHOD!=METHOD_ACK ) {
+                       /* add new transaction */
+                       new_cell = build_cell( p_msg ) ;
+                       if  ( !new_cell ){
+                               LOG(L_ERR, "ERROR: t_addifnew: out of mem:\n");
+                               ret = 0;
+                       } else {
+                               insert_into_hash_table_unsafe( hash_table , new_cell );
+                               T=new_cell;
+                               T_REF(T);
+                       }
+               }
+               unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
+               /* it that was a presumable e2e ACK, run a callback */
+               if (lret==-2) callback_event( TMCB_E2EACK, p_msg );
+               return ret;
+       } else {
+               /* transaction found, it's a retransmission  or ACK */
+                       return -1;
+       }
+}
+
+
 
diff --git a/modules/tm/t_msgbuilder.c b/modules/tm/t_msgbuilder.c
new file mode 100644 (file)
index 0000000..95c2d22
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * $Id$
+ *
+ * message printing
+ */
+
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../parser/parser_f.h"
+#include "../../ut.h"
+#include "../../parser/msg_parser.h"
+
+
+
+#define  append_mem_block(_d,_s,_len) \
+               do{\
+                       memcpy((_d),(_s),(_len));\
+                       (_d) += (_len);\
+               }while(0);
+
+
+/* Builds a CANCEL request based on an INVITE request. CANCEL is send
+ * to same address as the INVITE */
+int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
+{
+       struct sip_msg      *p_msg;
+       struct hdr_field    *hdr;
+       char                *cancel_buf, *p, *via;
+       unsigned int         len, via_len;
+
+       if ( !Trans->uac[branch].rpl_received )
+       {
+               DBG("DEBUG: t_build_and_send_CANCEL: no response ever received"
+                       " : dropping local cancel! \n");
+               return 1;
+       }
+
+       if (Trans->uac[branch].request.cancel!=NO_CANCEL)
+       {
+               DBG("DEBUG: t_build_and_send_CANCEL: branch (%d)was already canceled"
+                       " : dropping local cancel! \n",branch);
+               return 1;
+       }
+
+       cancel_buf = 0;
+       via = 0;
+       p_msg = Trans->uas.request;
+
+       len = 0;
+       /*first line's len - CANCEL and INVITE has the same lenght */
+       len += ( REQ_LINE(p_msg).version.s+REQ_LINE(p_msg).version.len)-
+               REQ_LINE(p_msg).method.s+CRLF_LEN;
+       /*check if the REQ URI was override */
+       if (Trans->uac[branch].uri.s)
+               len += Trans->uac[branch].uri.len - REQ_LINE(p_msg).uri.len;
+       /*via*/
+       if ( add_branch_label(Trans,p_msg,branch)==-1 )
+               goto error;
+       via = via_builder(p_msg , &via_len, Trans->uac[branch].request.send_sock );
+       if (!via)
+       {
+               LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: "
+                       "no via header got from builder\n");
+               goto error;
+       }
+       len+= via_len;
+       /*headers*/
+       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
+               if (hdr->type==HDR_FROM || hdr->type==HDR_CALLID || 
+                       hdr->type==HDR_CSEQ || hdr->type==HDR_TO )
+                       len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN ;
+       /* User Agent header*/
+       len += USER_AGENT_LEN + CRLF_LEN;
+       /* Content Lenght heder*/
+       len += CONTENT_LEN_LEN + CRLF_LEN;
+       /* end of message */
+       len += CRLF_LEN;
+
+       cancel_buf=sh_malloc( len+1 );
+       if (!cancel_buf)
+       {
+               LOG(L_ERR, "ERROR: t_build_and_send_CANCEL: cannot allocate memory\n");
+               goto error;
+       }
+       p = cancel_buf;
+
+       /* first line -> do we have a new URI? */
+       if (Trans->uac[branch].uri.s)
+       {
+               append_mem_block(p,REQ_LINE(p_msg).method.s,
+                       REQ_LINE(p_msg).uri.s-REQ_LINE(p_msg).method.s);
+               append_mem_block(p,Trans->uac[branch].uri.s,
+                       Trans->uac[branch].uri.len);
+               append_mem_block(p,REQ_LINE(p_msg).uri.s+REQ_LINE(p_msg).uri.len,
+                       REQ_LINE(p_msg).version.s+REQ_LINE(p_msg).version.len-
+                       (REQ_LINE(p_msg).uri.s+REQ_LINE(p_msg).uri.len))
+       }else{
+               append_mem_block(p,REQ_LINE(p_msg).method.s,
+                       REQ_LINE(p_msg).version.s+REQ_LINE(p_msg).version.len-
+                       REQ_LINE(p_msg).method.s);
+       }
+       /* changhing method name*/
+       memcpy(cancel_buf, CANCEL , CANCEL_LEN );
+       append_mem_block(p,CRLF,CRLF_LEN);
+       /* insert our via */
+       append_mem_block(p,via,via_len);
+
+       /*other headers*/
+       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
+       {
+               if(hdr->type==HDR_FROM||hdr->type==HDR_CALLID||hdr->type==HDR_TO)
+               {
+                       append_mem_block(p,hdr->name.s,
+                               ((hdr->body.s+hdr->body.len)-hdr->name.s) );
+                       append_mem_block(p, CRLF, CRLF_LEN );
+               }else if ( hdr->type==HDR_CSEQ )
+               {
+                       append_mem_block(p,hdr->name.s,
+                               ((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
+                       append_mem_block(p, CANCEL CRLF, CANCEL_LEN +CRLF_LEN );
+               }
+}
+
+       /* User Agent header */
+       append_mem_block(p,USER_AGENT,USER_AGENT_LEN);
+       append_mem_block(p,CRLF,CRLF_LEN);
+       /* Content Lenght header*/
+       append_mem_block(p,CONTENT_LEN,CONTENT_LEN_LEN);
+       append_mem_block(p,CRLF,CRLF_LEN);
+       /* end of message */
+       append_mem_block(p,CRLF,CRLF_LEN);
+       *p=0;
+
+       if (Trans->uac[branch].request.cancel) {
+               shm_free( cancel_buf );
+               LOG(L_WARN, "send_cancel: Warning: CANCEL already sent out\n");
+               goto error;
+       }
+
+       Trans->uac[branch].request.activ_type = TYPE_LOCAL_CANCEL;
+       Trans->uac[branch].request.cancel = cancel_buf;
+       Trans->uac[branch].request.cancel_len = len;
+
+       /*sets and starts the FINAL RESPONSE timer */
+       set_timer(hash_table,&(Trans->uac[branch].request.fr_timer),FR_TIMER_LIST);
+       /* sets and starts the RETRANS timer */
+       Trans->uac[branch].request.retr_list = RT_T1_TO_1;
+       set_timer(hash_table,&(Trans->uac[branch].request.retr_timer),RT_T1_TO_1);
+       DBG("DEBUG: T_build_and_send_CANCEL : sending cancel...\n");
+       SEND_CANCEL_BUFFER( &(Trans->uac[branch].request) );
+
+       pkg_free(via);
+       return 1;
+error:
+       if (via) pkg_free(via);
+       return -1;
+}
+
+
+/* Builds an ACK request based on an INVITE request. ACK is send
+ * to same address */
+char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,int *ret_len)
+{
+       struct sip_msg      *p_msg , *r_msg;
+       struct hdr_field    *hdr;
+       char                *ack_buf, *p, *via;
+       unsigned int         len, via_len;
+
+       ack_buf = 0;
+       via =0;
+       p_msg = trans->uas.request;
+       r_msg = rpl;
+
+       if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
+       {
+               LOG(L_ERR, "ERROR: t_build_ACK: "
+                       "cannot generate a HBH ACK if key HFs in reply missing\n");
+               goto error;
+       }
+
+       len = 0;
+       /*first line's len */
+       len += 4/*reply code and one space*/+
+               p_msg->first_line.u.request.version.len+CRLF_LEN;
+       /*uri's len*/
+       if (trans->uac[branch].uri.s)
+               len += trans->uac[branch].uri.len +1;
+       else
+               len += p_msg->first_line.u.request.uri.len +1;
+       /*adding branch param*/
+       if ( add_branch_label( trans , trans->uas.request , branch)==-1 )
+               goto error;
+       /*via*/
+       via = via_builder(p_msg , &via_len, trans->uac[branch].request.send_sock );
+       if (!via)
+       {
+               LOG(L_ERR, "ERROR: t_build_ACK: "
+                       "no via header got from builder\n");
+               goto error;
+       }
+       len+= via_len;
+       /*headers*/
+       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
+               if (hdr->type==HDR_FROM||hdr->type==HDR_CALLID||hdr->type==HDR_CSEQ)
+                       len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN ;
+               else if ( hdr->type==HDR_TO )
+                       len += ((r_msg->to->body.s+r_msg->to->body.len ) -
+                               r_msg->to->name.s ) + CRLF_LEN ;
+       /* CSEQ method : from INVITE-> ACK */
+       len -= 3  ;
+       /* end of message */
+       len += CRLF_LEN; /*new line*/
+
+       ack_buf = sh_malloc(len+1);
+       if (!ack_buf)
+       {
+               LOG(L_ERR, "ERROR: t_build_and_ACK: cannot allocate memory\n");
+               goto error1;
+       }
+       p = ack_buf;
+
+       /* first line */
+       memcpy( p , "ACK " , 4);
+       p += 4;
+       /* uri */
+       if ( trans->uac[branch].uri.s )
+       {
+               memcpy(p,trans->uac[branch].uri.s,trans->uac[branch].uri.len);
+               p +=trans->uac[branch].uri.len;
+       }else{
+               memcpy(p,p_msg->orig+(p_msg->first_line.u.request.uri.s-p_msg->buf),
+                       p_msg->first_line.u.request.uri.len );
+               p += p_msg->first_line.u.request.uri.len;
+       }
+       /* SIP version */
+       *(p++) = ' ';
+       memcpy(p,p_msg->orig+(p_msg->first_line.u.request.version.s-p_msg->buf),
+               p_msg->first_line.u.request.version.len );
+       p += p_msg->first_line.u.request.version.len;
+       memcpy( p, CRLF, CRLF_LEN );
+       p+=CRLF_LEN;
+
+       /* insert our via */
+       memcpy( p , via , via_len );
+       p += via_len;
+
+       /*other headers*/
+       for ( hdr=p_msg->headers ; hdr ; hdr=hdr->next )
+       {
+               if ( hdr->type==HDR_FROM || hdr->type==HDR_CALLID  )
+               {
+                       memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
+                               ((hdr->body.s+hdr->body.len ) - hdr->name.s ) );
+                       p += ((hdr->body.s+hdr->body.len ) - hdr->name.s );
+                       memcpy( p, CRLF, CRLF_LEN );
+                       p+=CRLF_LEN;
+               }
+               else if ( hdr->type==HDR_TO )
+               {
+                       memcpy( p , r_msg->orig+(r_msg->to->name.s-r_msg->buf) ,
+                               ((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s));
+                       p+=((r_msg->to->body.s+r_msg->to->body.len)-r_msg->to->name.s);
+                       memcpy( p, CRLF, CRLF_LEN );
+                       p+=CRLF_LEN;
+               }
+               else if ( hdr->type==HDR_CSEQ )
+               {
+                       memcpy( p , p_msg->orig+(hdr->name.s-p_msg->buf) ,
+                               ((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
+                       p+=((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s);
+                       memcpy( p , "ACK" CRLF, 3+CRLF_LEN );
+                       p += 3+CRLF_LEN;
+               }
+       }
+
+       /* end of message */
+       memcpy( p , CRLF , CRLF_LEN );
+       p += CRLF_LEN;
+
+       pkg_free( via );
+       DBG("DEBUG: t_build_ACK: ACK generated\n");
+
+       *(ret_len) = p-ack_buf;
+       return ack_buf;
+
+error1:
+       pkg_free(via );
+error:
+       return 0;
+}
+
+
+
index fa623e4..c5aa309 100644 (file)
@@ -19,7 +19,7 @@
 
 inline int check_for_no_response( struct cell *Trans ,int code, int relay)
 {
-       if ( code/100>3 && Trans->uac[Trans->nr_of_outgoings].uri.s )
+       if ( code/100>=3 && Trans->uac[Trans->nr_of_outgoings].uri.s )
        {
                forward_serial_branch( Trans , Trans->nr_of_outgoings );
                return -1;
@@ -59,16 +59,17 @@ int t_retransmit_reply( /* struct sip_msg* p_msg    */ )
 /* Force a new response into inbound response buffer.
   * returns 1 if everything was OK or -1 for error
   */
-int t_send_reply( struct sip_msg* p_msg, unsigned int code, char * text,
-                                                                                                               unsigned int branch)
+int t_send_reply( struct sip_msg* p_msg, unsigned int code, 
+       char * text, unsigned int branch)
 {
        unsigned int len, buf_len=0;
        char * buf;
        struct retr_buf *rb;
        int relay, save_clone;
+       struct socket_info* send_sock;
 
-       buf = build_res_buf_from_sip_req(code,text,T->uas.tag->s,T->uas.tag->len,
-               T->uas.request,&len);
+       buf = build_res_buf_from_sip_req(code,text,T->uas.tag->s,
+               T->uas.tag->len, T->uas.request,&len);
        DBG("DEBUG: t_send_reply: buffer computed\n");
        if (!buf)
        {
@@ -96,7 +97,15 @@ int t_send_reply( struct sip_msg* p_msg, unsigned int code, char * text,
                                        p_msg->via1->host.s );
                                goto error2;
                        }
-                       rb->to.sin_family = AF_INET;
+                       send_sock=get_send_socket(&rb->to);
+                       if (send_sock==0) {
+                               LOG(L_ERR, "ERROR: t_send_reply: cannot fwd to af %d "
+                                       "no socket\n", rb->to.s.sa_family);
+                               ser_error=E_NO_SOCKET;
+                               goto error2;
+                       }
+                       rb->send_sock=send_sock;
+                       /* rb->to.sin_family = AF_INET; */
                        rb->activ_type = code;
                        buf_len = len + REPLY_OVERBUFFER_LEN;
                }else{
@@ -195,7 +204,6 @@ error:
 #endif
 
 
-
 /*  This function is called whenever a reply for our module is received; 
   * we need to register  this function on module initialization;
   *  Returns :   0 - core router stops
@@ -216,6 +224,7 @@ int t_on_reply( struct sip_msg  *p_msg )
        /* buffer length (might be somewhat larger than message size */
        unsigned int alloc_len;
        str *str_foo;
+       struct socket_info* send_sock;
 
 
        /* make sure we know the assosociated tranaction ... */
@@ -247,7 +256,8 @@ int t_on_reply( struct sip_msg  *p_msg )
        msg_class=REPLY_CLASS(p_msg);
        is_invite= T->uas.request->REQ_METHOD==METHOD_INVITE;
 
-       /*  generate the retrans buffer, make a simplified
+#ifdef _DONT_DO_IT_MAN
+/*  generate the retrans buffer, make a simplified
        assumption everything but 100 will be fwd-ed;
        sometimes it will result in useless CPU cycles
        but mostly the assumption holds and allows the
@@ -263,6 +273,7 @@ int t_on_reply( struct sip_msg  *p_msg )
                        goto error;
                }
        }
+#endif
 
        /* *** stop timers *** */
        /* stop retransmission */
@@ -317,6 +328,17 @@ int t_on_reply( struct sip_msg  *p_msg )
 
        rb = & T->uas.response;
        if (relay >= 0  && (relay=check_for_no_response(T,msg_status,relay))>=0 ) {
+
+               buf = build_res_buf_from_sip_res ( p_msg, &res_len);
+               if (!buf) {
+                       UNLOCK_REPLIES( T );
+                       start_fr = 1;
+                       LOG(L_ERR, "ERROR: t_on_reply_received: "
+                               "no mem for outbound reply buffer\n");
+                       goto error1;
+               }
+               callback_event( TMCB_REPLY_IN, p_msg );
+
                if (relay!=branch)
                {
                        str_foo = &(T->uac[relay].rpl_buffer);
@@ -342,7 +364,16 @@ int t_on_reply( struct sip_msg  *p_msg )
                                        p_msg->via2->host.s );
                                goto error1;
                        }
-                       rb->to.sin_family = AF_INET;
+                       send_sock=get_send_socket(&rb->to);
+                       if (send_sock==0) {
+                               UNLOCK_REPLIES( T );
+                               LOG(L_ERR, "ERROR: t_on_reply: cannot fwd to af %d "
+                                       "no socket\n", rb->to.s.sa_family);
+                               start_fr=1;
+                               goto error1;
+                       }
+                       /* rb->to.sin_family = AF_INET; */
+                       rb->send_sock=send_sock;
                        rb->activ_type = p_msg->REPLY_STATUS;
                        /* allocate something more for the first message;
                           subsequent messages will be longer and buffer
@@ -419,3 +450,88 @@ error:
        return 0;
 }
 
+
+/* Checks if the new reply (with new_code status) should be sent or not
+ *  based on the current
+ * transactin status.
+ * Returns     - branch number (0,1,...) which should be relayed
+ *         -1 if nothing to be relayed
+ */
+int t_should_relay_response( struct cell *Trans , int new_code,
+                                                                       int branch , int *should_store )
+{
+       //int T_code;
+       int b, lowest_b, lowest_s;
+
+       //if (Trans->uas.request->REQ_METHOD==METHOD_INVITE)
+       //      T_code = Trans->uac[branch].status;
+       //else
+       //T_code = Trans->uas.status;
+
+       /* note: this code never lets replies to CANCEL go through;
+          we generate always a local 200 for CANCEL; 200s are
+          not relayed because it's not an INVITE transaction;
+          >= 300 are not relayed because 200 was already sent
+          out
+       */
+       DBG("->>>>>>>>> T_code=%d, new_code=%d\n",Trans->uas.status,new_code);
+       /* if final response sent out, allow only INVITE 2xx  */
+       if ( Trans->uas.status >= 200 ) {
+               if (new_code>=200 && new_code < 300  && 
+                       Trans->uas.request->REQ_METHOD==METHOD_INVITE) {
+                       DBG("DBG: t_should_relay: 200 INV after final sent\n");
+                       *should_store=1;
+                       return branch;
+               } else {
+                       *should_store=0;
+                       return -1;
+               }
+       } else { /* no final response sent yet */
+               /* negative replies subject to fork picking */
+               if (new_code >=300 ) {
+                       /* dirty hack by Jiri -- subject to clean up as all the
+                          reply_processing crap; if there are no branches at
+                          all, I guess TM wants to reply itself and allow that
+                       */
+                       if (Trans->nr_of_outgoings==0)
+                               return 0;
+                       *should_store=1;
+                       /* if all_final return lowest */
+                       lowest_b=-1; lowest_s=999;
+                       for ( b=0; b<Trans->nr_of_outgoings ; b++ ) {
+                               /* "fake" for the currently processed branch */
+                               if (b==branch) {
+                                       if (new_code<lowest_s) {
+                                               lowest_b=b;
+                                               lowest_s=new_code;
+                                       }
+                                       continue;
+                               }
+                               /* there is still an unfinished UAC transaction; wait now! */
+                               if ( Trans->uac[b].status<200 )
+                                       return -1;
+                               if ( Trans->uac[b].status<lowest_s )
+                               {
+                                       lowest_b =b;
+                                       lowest_s = T->uac[b].status;
+                               }
+                       }
+                       return lowest_b;
+               /* 1xx except 100 and 2xx will be relayed */
+               } else if (new_code>100) {
+                       *should_store=1;
+                       return branch;
+               }
+               /* 100 won't be relayed */
+               else {
+                       if (!T->uac[branch].rpl_received) *should_store=1;
+                               else *should_store=0;
+                       if (Trans->uas.status==0) return branch;
+                               else return -1;
+               }
+       }
+
+       LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay\n");
+       abort();
+}
+
diff --git a/modules/tm/t_thandlers.c b/modules/tm/t_thandlers.c
new file mode 100644 (file)
index 0000000..7e226a1
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * $Id$
+ *
+ * Timer handlers
+ */
+
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../parser/parser_f.h"
+#include "../../ut.h"
+//#include "../../timer.h"
+
+
+
+
+
+inline void retransmission_handler( void *attr)
+{
+       struct retr_buf* r_buf ;
+       enum lists id;
+
+       r_buf = (struct retr_buf*)attr;
+#ifdef EXTRA_DEBUG
+       if (r_buf->my_T->damocles) {
+               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
+                       " called from RETR timer\n",r_buf->my_T);
+               abort();
+       }       
+#endif
+
+       /*the transaction is already removed from RETRANSMISSION_LIST by timer*/
+       /* retransmision */
+       DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
+       switch ( r_buf->activ_type )
+       {
+               case (TYPE_REQUEST):
+                       SEND_BUFFER( r_buf );
+                       break;
+               case (TYPE_LOCAL_CANCEL):
+                       SEND_CANCEL_BUFFER( r_buf );
+                       break;
+               default:
+                       T=r_buf->my_T;
+                       t_retransmit_reply();
+       }
+
+       id = r_buf->retr_list;
+       r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
+
+       set_timer(hash_table,&(r_buf->retr_timer),id < RT_T2 ? id + 1 : RT_T2 );
+
+       DBG("DEBUG: retransmission_handler : done\n");
+}
+
+
+
+
+inline void final_response_handler( void *attr)
+{
+       struct retr_buf* r_buf = (struct retr_buf*)attr;
+
+#ifdef EXTRA_DEBUG
+       if (r_buf->my_T->damocles) 
+       {
+               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
+                       " called from FR timer\n",r_buf->my_T);
+               abort();
+       }
+#endif
+
+       /* the transaction is already removed from FR_LIST by the timer */
+       if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
+       {
+               DBG("DEBUG: FR_handler: stop retransmission for Local Cancel\n");
+               reset_timer( hash_table , &(r_buf->retr_timer) );
+               return;
+       }
+       /* send a 408 */
+       if ( r_buf->my_T->uac[r_buf->branch].status<200
+#ifdef SILENT_FR
+       && (r_buf->my_T->nr_of_outgoings>1     /*if we have forked*/
+               || r_buf->my_T->uas.request->first_line.u.request.method_value!=
+                       METHOD_INVITE                  /*if is not an INVITE */
+               || r_buf->my_T->uac[r_buf->my_T->nr_of_outgoings].uri.s
+                                                  /*if "no on no response" was set*/
+               || r_buf->my_T->uac[r_buf->branch].rpl_received==0
+                                                                                       /*if no reply was received*/
+       )
+#endif
+       )
+       {
+               DBG("DEBUG: FR_handler:stop retr. and send CANCEL (%p)\n",r_buf->my_T);
+               reset_timer( hash_table, &(r_buf->retr_timer) );
+               t_build_and_send_CANCEL( r_buf->my_T ,r_buf->branch);
+               /* dirty hack:t_send_reply would increase ref_count which would indeed
+               result in refcount++ which would not -- until timer processe's
+               T changes again; currently only on next call to t_send_reply from
+               FR timer; thus I fake the values now to avoid recalculating T
+               and refcount++ JKU */
+               T=r_buf->my_T;
+               global_msg_id=T->uas.request->id;
+               DBG("DEBUG: FR_handler: send 408 (%p)\n", r_buf->my_T);
+               t_send_reply( r_buf->my_T->uas.request, 408, "Request Timeout",
+                       r_buf->branch);
+       }else{
+               /* put it on WT_LIST - transaction is over */
+               DBG("DEBUG: final_response_handler:-> put on wait"
+                       " (t=%p)\n", r_buf->my_T);
+               t_put_on_wait(  r_buf->my_T );
+       }
+       DBG("DEBUG: final_response_handler : done\n");
+}
+
+
+
+
+inline void wait_handler( void *attr)
+{
+       struct cell *p_cell = (struct cell*)attr;
+
+#ifdef EXTRA_DEBUG
+       if (p_cell->damocles) {
+               LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
+                       " called from WAIT timer\n",p_cell);
+               abort();
+       }       
+#endif
+
+       /* the transaction is already removed from WT_LIST by the timer */
+       /* the cell is removed from the hash table */
+       DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
+       remove_from_hash_table( hash_table, p_cell );
+       /* jku: no more here -- we do it when we put a transaction on wait */
+       DBG("DEBUG: wait_handler : stopping all timers\n");
+       reset_retr_timers(hash_table,p_cell) ; 
+       /* put it on DEL_LIST - sch for del */
+#ifdef EXTRA_DEBUG
+       p_cell->damocles = 1;
+#endif
+       delete_cell( p_cell );
+       DBG("DEBUG: wait_handler : done\n");
+}
+
+
+
+
+inline void delete_handler( void *attr)
+{
+       struct cell *p_cell = (struct cell*)attr;
+
+       DBG("DEBUG: delete_handler : removing %p \n", p_cell );
+#ifdef EXTRA_DEBUG
+       if (p_cell->damocles==0) {
+               LOG( L_ERR, "ERROR: transaction %p not scheduled for deletion"
+                       " and called from DELETE timer\n",p_cell);
+               abort();
+       }       
+#endif
+       delete_cell( p_cell );
+    DBG("DEBUG: delete_handler : done\n");
+}
+
+
+
+
+#define run_handler_for_each( _tl , _handler ) \
+       while ((_tl))\
+       {\
+               /* reset the timer list linkage */\
+               tmp_tl = (_tl)->next_tl;\
+               (_tl)->next_tl = (_tl)->prev_tl = 0;\
+               DBG("DEBUG: timer routine:%d,tl=%p next=%p\n",\
+                       id,(_tl),tmp_tl);\
+               (_handler)( (_tl)->payload );\
+               (_tl) = tmp_tl;\
+       }
+
+
+
+
+void timer_routine(unsigned int ticks , void * attr)
+{
+       struct s_table    *hash_table = (struct s_table *)attr;
+       struct timer_link *tl, *tmp_tl;
+       int                id;
+
+#ifdef BOGDAN_TRIFLE
+       DBG(" %d \n",ticks);
+#endif
+
+       for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
+       {
+               /* to waste as little time in lock as possible, detach list
+                  with expired items and process them after leaving the lock */
+               tl=check_and_split_time_list( &(hash_table->timers[ id ]), ticks);
+               /* process items now */
+               switch (id)
+               {
+                       case FR_TIMER_LIST:
+                       case FR_INV_TIMER_LIST:
+                               run_handler_for_each(tl,final_response_handler);
+                               break;
+                       case RT_T1_TO_1:
+                       case RT_T1_TO_2:
+                       case RT_T1_TO_3:
+                       case RT_T2:
+                               run_handler_for_each(tl,retransmission_handler);
+                               break;
+                       case WT_TIMER_LIST:
+                               run_handler_for_each(tl,wait_handler);
+                               break;
+                       case DELETE_LIST:
+                               run_handler_for_each(tl,delete_handler);
+                               break;
+               }
+       }
+}
+
diff --git a/modules/tm/test.c b/modules/tm/test.c
new file mode 100644 (file)
index 0000000..9cdf54e
--- /dev/null
@@ -0,0 +1,37 @@
+#include "hash_func.h"
+#include "t_funcs.h"
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../parser/parser_f.h"
+#include "../../ut.h"
+#include "../../timer.h"
+
+#include "t_hooks.h"
+
+int _test_insert_to_reply( struct sip_msg *msg, char *str )
+{
+    struct lump* anchor;
+    char *buf;
+    int len;
+
+    len=strlen( str );
+    buf=pkg_malloc( len );
+    if (!buf) {
+        LOG(L_ERR, "_test_insert_to_reply: no mem\n");
+        return 0;
+    }
+    memcpy( buf, str, len );
+
+    anchor = anchor_lump(&msg->add_rm,
+        msg->headers->name.s - msg->buf, 0 , 0);
+    if (anchor == NULL) {
+        LOG(L_ERR, "_test_insert_to_reply: anchor_lump failed\n");
+        return 0;
+    }
+    if (insert_new_lump_before(anchor,buf, len, 0)==0) {
+        LOG(L_ERR, "_test_insert_to_reply: inser_new_lump failed\n");
+        return 0;
+    }
+    return 1;
+}
+
index 489be9e..be96788 100644 (file)
 #include "t_funcs.h"
 #include "t_hooks.h"
 #include "tm_load.h"
+#include "t_fork.h"
+#include "ut.h"
 
 
 
-static int w_t_check(struct sip_msg* msg, char* str, char* str2);
-static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2);
-static int w_t_release(struct sip_msg* msg, char* str, char* str2);
-static int fixup_t_forward(void** param, int param_no);
-static int fixup_t_send_reply(void** param, int param_no);
-static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar );
-static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
-static int w_t_add_transaction(struct sip_msg* p_msg, char* foo, char* bar );
-static int t_relay_to( struct sip_msg *p_msg, char *str_ip, char *str_port);
-static int t_relay( struct sip_msg  *p_msg ,  char* foo, char* bar  );
-static int w_t_forward_ack(struct sip_msg* msg, char* str, char* str2);
-static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* str2);
-static int w_t_add_fork_ip(struct sip_msg* msg, char* str, char* str2);
-static int w_t_add_fork_uri(struct sip_msg* msg, char* str, char* str2);
-static int fixup_t_add_fork_uri(void** param, int param_no);
-static int w_t_add_fork_on_no_rpl(struct sip_msg* msg,char* str,char* str2);
-static int w_t_clear_forks(struct sip_msg* msg, char* str, char* str2);
-static void w_onbreak(struct sip_msg* msg) { t_unref(); }
+inline static int w_t_check(struct sip_msg* msg, char* str, char* str2);
+inline static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2);
+inline static int w_t_release(struct sip_msg* msg, char* str, char* str2);
+inline static int fixup_t_send_reply(void** param, int param_no);
+inline static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar );
+inline static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
+/*
+inline static int w_t_add_transaction(struct sip_msg* p_msg, char* foo, char* bar );
+*/
+
+inline static int w_t_newtran(struct sip_msg* p_msg, char* foo, char* bar );
+
+inline static int t_relay( struct sip_msg  *p_msg ,  char* , char* );
+inline static int w_t_relay_to( struct sip_msg  *p_msg , char *proxy, char *);
+static int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy );
+/*
+inline static int w_t_forward_ack(struct sip_msg* msg, char* proxy, char* );
+*/
+inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
+inline static int fixup_hostport2proxy(void** param, int param_no);
+
+inline static int w_t_add_fork_ip(struct sip_msg* msg, char* proxy, char* );
+inline static int w_t_add_fork_uri(struct sip_msg* msg, char* str, char* );
+inline static int w_t_add_fork_on_no_rpl(struct sip_msg* msg,char* str,char* );
+inline static int w_t_clear_forks(struct sip_msg* msg, char* , char* );
+
+inline static int fixup_uri2fork(void** param, int param_no);
+
+inline static void w_onbreak(struct sip_msg* msg) { t_unref(); }
 
 static int mod_init(void);
 
@@ -51,7 +64,10 @@ struct module_exports exports= {
        "tm",
        /* -------- exported functions ----------- */
        (char*[]){                      
+/*             - obsoleted by atomic t_newtran 
                                "t_add_transaction",
+*/
+                               "t_newtran",
                                "t_lookup_request",
                                "t_send_reply",
                                "t_retransmit_reply",
@@ -60,7 +76,9 @@ struct module_exports exports= {
                                "t_relay_to",
                                "t_relay",
                                "t_forward_nonack",
+/*
                                "t_forward_ack",
+*/
                                "t_fork_to_ip",
                                "t_fork_to_uri",
                                "t_clear_forks",
@@ -69,16 +87,20 @@ struct module_exports exports= {
                                "load_tm"
                        },
        (cmd_function[]){
+/*
                                        w_t_add_transaction,
+*/                                     w_t_newtran,
                                        w_t_check,
                                        w_t_send_reply,
                                        w_t_retransmit_reply,
                                        w_t_release,
                                        w_t_unref,
-                                       t_relay_to,
+                                       w_t_relay_to,
                                        t_relay,
                                        w_t_forward_nonack,
+/*
                                        w_t_forward_ack,
+*/
                                        w_t_add_fork_ip,
                                        w_t_add_fork_uri,
                                        w_t_clear_forks,
@@ -87,7 +109,7 @@ struct module_exports exports= {
                                        (cmd_function) load_tm
                                        },
        (int[]){
-                               0, /* t_add_transaction */
+                               0, /* t_newtran */
                                0, /* t_lookup_request */
                                2, /* t_send_reply */
                                0, /* t_retransmit_reply */
@@ -96,7 +118,8 @@ struct module_exports exports= {
                                2, /* t_relay_to */
                                0, /* t_relay */
                                2, /* t_forward_nonack */
-                               2, /* t_forward_ack */
+/*                             2,*/ /* t_forward_ack */
+
                                2, /* t_fork_to_ip */
                                1, /* t_fork_to_uri */
                                0, /* t_clear_forks */
@@ -105,25 +128,25 @@ struct module_exports exports= {
                                1 /* load_tm */
                        },
        (fixup_function[]){
-                               0,                                              /* t_add_transaction */
+                               0,                                              /* t_newtran */
                                0,                                              /* t_lookup_request */
                                fixup_t_send_reply,             /* t_send_reply */
                                0,                                              /* t_retransmit_reply */
                                0,                                              /* t_release */
                                0,                                              /* t_unref */
-                               fixup_t_forward,                /* t_relay_to */
+                               fixup_hostport2proxy,   /* t_relay_to */
                                0,                                              /* t_relay */
-                               fixup_t_forward,                /* t_forward_nonack */
-                               fixup_t_forward,                /* t_forward_ack */
-                               fixup_t_forward,                /* t_fork_to_ip */
-                               fixup_t_add_fork_uri,   /* t_fork_to_uri */
+                               fixup_hostport2proxy,   /* t_forward_nonack */
+                               /* fixup_hostport2proxy,        */ /* t_forward_ack */
+                               fixup_hostport2proxy,   /* t_fork_to_ip */
+                               fixup_uri2fork,                 /* t_fork_to_uri */
                                0,                                              /* t_clear_forks */
-                               fixup_t_add_fork_uri,   /* t_add_fork_on_no_response */
+                               fixup_uri2fork,         /* t_add_fork_on_no_response */
                                0,                                              /* register_tmcb */
                                0                                               /* load_tm */
        
                },
-       16,
+       15,
 
        /* ------------ exported variables ---------- */
        (char *[]) { /* Module parameter names */
@@ -176,60 +199,49 @@ static int mod_init(void)
 }
 
 
+/* (char *hostname, char *port_nr) ==> (struct proxy_l *, -)  */
 
-
-static int fixup_t_forward(void** param, int param_no)
+inline static int fixup_hostport2proxy(void** param, int param_no)
 {
-       char* name;
-       struct hostent* he;
        unsigned int port;
+       char *host;
        int err;
-#ifdef DNS_IP_HACK
-       unsigned int ip;
-       int len;
-#endif
-
+       struct proxy_l *proxy;
+       
        DBG("TM module: fixup_t_forward(%s, %d)\n", (char*)*param, param_no);
        if (param_no==1){
-               name=*param;
-#ifdef DNS_IP_HACK
-               len=strlen(name);
-               ip=str2ip((unsigned char*)name, len, &err);
-               if (err==0){
-                       goto copy;
+               DBG("TM module: fixup_t_forward: param 1.. do nothing, wait for #2\n");
+               return 0;
+       } else if (param_no==2) {
+
+               host=(char *) (*(param-1)); 
+               port=str2s(*param, strlen(*param), &err);
+               if (err!=0) {
+                       LOG(L_ERR, "TM module:fixup_t_forward: bad port number <%s>\n",
+                               (char*)(*param));
+                        return E_UNSPEC;
                }
-#endif
-               /* fail over to normal lookup */
-               he=gethostbyname(name);
-               if (he==0){
-                       LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
-                                               " \"%s\"\n", name);
+               proxy=mk_proxy(host, port);
+               if (proxy==0) {
+                       LOG(L_ERR, "ERROR: fixup_t_forwardv6: bad host name in URI <%s>\n",
+                               host );
                        return E_BAD_ADDRESS;
                }
-               memcpy(&ip, he->h_addr_list[0], sizeof(unsigned int));
-       copy:
-               free(*param);
-               *param=(void*)ip;
+               /* success -- fix the first parameter to proxy now ! */
+               free( *(param-1));
+               *(param-1)=proxy;
                return 0;
-       }else if (param_no==2){
-               port=htons(str2s(*param, strlen(*param), &err));
-               if (err==0){
-                       free(*param);
-                       *param=(void*)port;
-                       return 0;
-               }else{
-                       LOG(L_ERR, "TM module:fixup_t_forward: bad port number <%s>\n",
-                                       (char*)(*param));
-                       return E_UNSPEC;
-               }
+       } else {
+               LOG(L_ERR, "ERROR: fixup_t_forwardv6 called with parameter #<>{1,2}\n");
+               return E_BUG;
        }
-       return 0;
 }
 
 
+/* (char *code, char *reason_phrase)==>(int code, r_p as is) */
 
 
-static int fixup_t_send_reply(void** param, int param_no)
+inline static int fixup_t_send_reply(void** param, int param_no)
 {
        unsigned int code;
        int err;
@@ -253,40 +265,40 @@ static int fixup_t_send_reply(void** param, int param_no)
 
 
 
-static int w_t_check(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_check(struct sip_msg* msg, char* str, char* str2)
 {
        return t_check( msg , 0 , 0 ) ? 1 : -1;
 }
 
 
 
-
-static int w_t_forward_ack(struct sip_msg* msg, char* str, char* str2)
+#ifdef _TOO_OLD
+inline static int w_t_forward_ack(struct sip_msg* msg, char* proxy, char* _foo)
 {
        if (t_check( msg , 0 , 0 )==-1) return -1;
        if (!T) {
                DBG("DEBUG: t_forward_ack: no transaction found \n");
                return -1;
        }
-       return t_forward_ack(msg, (unsigned int) str, (unsigned int) str2);
+       return t_forward_ack(msg /*, ( struct proxy_l *) proxy */ );
 }
 
+#endif
 
 
-
-static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_forward_nonack(struct sip_msg* msg, char* proxy, char* _foo)
 {
        if (t_check( msg , 0 , 0)==-1) return -1;
        if (!T) {
                DBG("DEBUG: t_forward_nonack: no transaction found\n");
                return -1;
        }
-       return t_forward_nonack(msg, (unsigned int) str, (unsigned int) str2);
+       return t_forward_nonack(msg, ( struct proxy_l *) proxy );
 }
 
 
 
-static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 {
        if (t_check( msg , 0 , 0)==-1) return -1;
        if (!T) {
@@ -300,7 +312,7 @@ static int w_t_send_reply(struct sip_msg* msg, char* str, char* str2)
 
 
 
-static int w_t_release(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 {
        if (t_check( msg  , 0 , 0 )==-1) return 1;
        if ( T && T!=T_UNDEFINED ) 
@@ -311,7 +323,7 @@ static int w_t_release(struct sip_msg* msg, char* str, char* str2)
 
 
 
-static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
+inline static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 {
        if (T==T_UNDEFINED || T==T_NULL)
                return -1;
@@ -321,7 +333,7 @@ static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar )
 
 
 
-static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
+inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
 {
        if (t_check( p_msg  , 0 , 0 )==-1) 
                return 1;
@@ -335,30 +347,38 @@ static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
 
 
 
-static int w_t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar ) {
+/* inline static int w_t_add_transaction( struct sip_msg* p_msg, 
+       char* foo, char* bar ) {
+*/
+inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) {
        if (t_check( p_msg , 0 , 0 )==-1) return -1;
        if (T) {
                LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
                return -1;
        }
-       return t_add_transaction( p_msg );
+       return t_newtran( p_msg );
 }
 
 
 
 
-static int w_t_add_fork_ip(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_add_fork_ip(struct sip_msg* msg, char* proxy, char* _foo )
 {
-       return t_add_fork((unsigned int)str, (unsigned int)str2, 0,0,DEFAULT,0);
+       struct proxy_l *p;
+       union sockaddr_union to;
+
+       p=(struct proxy_l *) proxy;
+       hostent2su(&to, &p->host, p->addr_idx, (p->port)?htons(p->port):htons(SIP_PORT));
+       return t_add_fork( to, 0,0,DEFAULT,0);
 }
 
 
 
 
-static int fixup_t_add_fork_uri(void** param, int param_no)
+inline static int fixup_uri2fork (void** param, int param_no)
 {
-       unsigned int ip, port;
        struct fork* fork_pack;
+       struct proxy_l *p;
 
        if (param_no==1)
        {
@@ -371,79 +391,128 @@ static int fixup_t_add_fork_uri(void** param, int param_no)
                }
                fork_pack->uri.len = strlen(*param);
                fork_pack->uri.s = *param;
-               if ( get_ip_and_port_from_uri(&(fork_pack->uri), &ip, &port)==0 )
-               {
-                       fork_pack->ip = ip;
-                       fork_pack->port = port;
-                       *param=(void*)fork_pack;
-                       return 0;
-               }else{
-                       LOG(L_ERR, "TM module:fixup_t_add_fork_uri: bad uri <%s>\n",
-                       (char*)(*param));
-                       return E_UNSPEC;
+
+               p=uri2proxy( & fork_pack->uri );
+               if (p==0) {
+                       pkg_free( fork_pack );
+                       return E_CFG;
                }
+               hostent2su(&fork_pack->to, &p->host, p->addr_idx,
+               (p->port)?htons(p->port):htons(SIP_PORT));
+
+               free_proxy(p); free(p);
+               *param=(void*)fork_pack;
+               return 0;
+       } else {
+               LOG(L_ERR, "Error: URI should not be followed by another parameter\n");
+               /* second param => no conversion*/
+               return E_BUG;
        }
-       /* second param => no conversion*/
-       return 0;
 }
 
 
 
 
-static int w_t_add_fork_uri(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_add_fork_uri(struct sip_msg* msg, char* str, char* _foo)
 {
-       return t_add_fork( ((struct fork*)str)->ip, ((struct fork*)str)->port,
-               ((struct fork*)str)->uri.s, ((struct fork*)str)->uri.len, DEFAULT,0);
+       struct fork *fp;
+       fp=(struct fork *) str;
+       return t_add_fork( fp->to, fp->uri.s, fp->uri.len, DEFAULT, 0);
 }
 
+inline static int w_t_add_fork_on_no_rpl(struct sip_msg* msg, char* str, char* _foo )
+{
+       struct fork *fp;
+       fp=(struct fork *) str;
+       return t_add_fork(  fp->to, fp->uri.s, fp->uri.len, NO_RESPONSE, 0);
+}
 
-
-
-static int w_t_clear_forks(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_clear_forks(struct sip_msg* msg, char* _foo, char* _bar )
 {
        return t_clear_forks();
 }
 
 
-
-
-static int w_t_add_fork_on_no_rpl(struct sip_msg* msg, char* str, char* str2)
+inline static int w_t_relay_to( struct sip_msg  *p_msg , 
+                                                char *proxy, /* struct proxy_l *proxy expected */
+                                                char *_foo       /* nothing expected */ )
 {
-       return t_add_fork( ((struct fork*)str)->ip, ((struct fork*)str)->port,
-               ((struct fork*)str)->uri.s,((struct fork*)str)->uri.len,NO_RESPONSE,0);
+       return t_relay_to( p_msg, ( struct proxy_l *) proxy );
 }
 
-
-
-
-static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
+static int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy )
 {
-       struct proxy_l *proxy;
-       enum addifnew_status status;
-       int ret=0;
-
-       status = t_addifnew( p_msg );
+       int ret;
+       int new_tran;
+       char err_buffer[128];
+       int sip_err;
+       int reply_ret;
+
+       ret=0;
+
+       new_tran = t_newtran( p_msg );
+
+       /* parsing error, memory alloc, whatever ... return -1;
+          note -- this is a difference to writing a real script --
+          we translate t_newtran 0 error to a negative value allowign
+          some error handling; a script breaks on 0
+    */
+       if (new_tran==0) {
+               ret=E_UNSPEC;
+               goto done;
+       }
 
-       switch( status ) {
-               case AIN_ERROR:         /*  fatal error (e.g, parsing) occured */
-                       ret = 0;
-                       break;
-               case AIN_RETR:          /* it's a retransmission */
+       /* nothing new -- it is an existing transaction */
+       if (new_tran==-1) {
+               if ( p_msg->REQ_METHOD==METHOD_ACK) {
+                       DBG( "SER: ACK received -> t_release\n");
+                       if ( !t_release_transaction( p_msg ) )
+                       {
+                               DBG( "SER: WARNING: bad t_release\n");
+                       }
+                       /* ack fwd-ing not needed -- only hbh ACK
+                          match (new_tran==1) and do not need to
+                          be fwd-ed */
+                       ret = 1;
+               } else { /* non-ACK -- retransmit */
                        ret=t_retransmit_reply( p_msg );
                        /* look at ret for better debugging output ... */
                        if (ret>0) DBG("DEBUG: reply retransmitted (status %d)\n", ret);
                        else if (ret==-1) DBG("DEBUG: no reply to retransmit; "
                                "probably a non-INVITE transaction which was not replied\n");
                        else LOG(L_ERR, "ERROR: reply retranmission failed\n");
-                       /* eventually, do not worry and proceed whatever happened to you...*/
+                       /* do not worry and proceed whatever happened to you...*/
                        ret = 1;
-                       break;
-               case AIN_NEW:           /* it's a new request */
-                       if (!t_forward_nonack(p_msg,(unsigned int)str_ip,
-                       (unsigned int) str_port ))
+               }
+       } else { /* it is a new transaction */
+               if ( p_msg->REQ_METHOD==METHOD_ACK) {
+                       /* ACKs does not establish a transaction and is
+                          fwd-ed statelessly */
+                       DBG( "SER: forwarding ACK  statelessly \n");
+                       ret=forward_request( p_msg , proxy ) ;
+               } else {
+                       ret=t_forward_nonack(p_msg, proxy);
+                       if (ret<=0)
                        {
                                DBG( "SER:ERROR: t_forward \n");
-                               ret = 0;
+                               /* we reply statefuly and enter WAIT state since error might 
+                                  have occured in middle of forking and we do not 
+                                  want to put the forking burden on upstream client;
+                                  howver, it may fail too due to lack of memory */
+                               err2reason_phrase( ser_error, &sip_err,
+                                       err_buffer, sizeof(err_buffer), "TM" );
+                               reply_ret=t_send_reply( p_msg , sip_err, err_buffer,0);
+                               t_release_transaction( p_msg );
+                               if (reply_ret>0) {
+                                       /* we have taken care of all -- do nothing in
+                                       script */
+                                       DBG("ERROR: generation of a stateful reply "
+                                               "on error succeeded\n");
+                                       ret=0;
+                               }  else {
+                                       DBG("ERROR: generation of a stateful reply "
+                                               "on error failed\n");
+                               };
                        } else { /* let upstream know, I forwarded downstream */
                                if ( p_msg->REQ_METHOD==METHOD_CANCEL)
                                {
@@ -459,39 +528,12 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
                                } else {
                                        DBG( "SER: new transaction\n");
                                }
-                               ret = 1;
-                       }
-                       break;
-               case AIN_NEWACK:        /* it's an ACK for which no transaction exists */
-                       DBG( "SER: forwarding ACK  statelessly \n");
-                       proxy = mk_proxy_from_ip( (unsigned int)str_ip,
-                               ntohs((unsigned int)str_port) );
-                       forward_request( p_msg , proxy ) ;
-                       free_proxy(proxy);
-                       free(proxy);
-                       ret=1;
-                       break;
-               case AIN_OLDACK:        /* it's an ACK for an existing transaction */
-                       DBG( "SER: ACK received -> t_release\n");
-                       if ( !t_release_transaction( p_msg ) )
-                       {
-                               DBG( "SER: WARNING: bad t_release\n");
-                       }
-                       /* t_forward decides whether to forward (2xx) 
-                          or not (anything else) */
-                       if ( !t_forward_ack( p_msg , (unsigned int) str_ip ,
-                       (unsigned int) str_port ) )
-                               DBG( "SER: WARNING: bad ACK forward\n");
-                       ret = 1;
-                       break;
-               case AIN_RTRACK:        /* ACK retransmission */
-                       DBG( "SER: ACK retransmission\n");
-                       ret = 1;
-                       break;
-               default:
-                       LOG(L_CRIT, "ERROR: unexpected addifnew return value: %d\n", ret);
-                       abort();
-       };
+                       } /* forward_nonack succeeded */
+               } /* a new non-ACK trancation */
+       } /* a new transaction */
+
+
+done:
        if (T!=T_UNDEFINED && T!=T_NULL) {
                T_UNREF( T );
        }
@@ -499,27 +541,25 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 }
 
 
-
-
-static int t_relay( struct sip_msg  *p_msg , char* foo, char* bar)
+static int t_relay( struct sip_msg  *p_msg , char* _foo , char* _bar )
 {
-       unsigned int  ip, port;
        str           *uri;
+       struct proxy_l *p;
+       int ret;
 
        /* 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);
-       /* extracts ip and port from uri */             
-       if ( get_ip_and_port_from_uri( uri , &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_relay_to( p_msg , ( char *) ip , (char *) port );
-}
 
+       p=uri2proxy( uri );
+       if (p==0) return E_BAD_ADDRESS;
 
+       /* relay now */
+       ret=t_relay_to( p_msg, p );
+       free_proxy( p );
+       free( p );
+       return ret;
+}
 
diff --git a/modules/tm/ut.h b/modules/tm/ut.h
new file mode 100644 (file)
index 0000000..c769cad
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ * utilities
+ *
+ */
+
+#ifndef _TM_UT_H
+#define _TM_UT_H
+
+#include "../../dprint.h"
+#include "../../error.h"
+#include "../../ut.h"
+#include "../../str.h"
+#include "../../parser/msg_parser.h"
+
+inline static struct proxy_l *uri2proxy( str *uri )
+{
+       struct sip_uri  parsed_uri;
+       unsigned int  port; 
+       struct proxy_l *p;
+       int err;
+
+       if (parse_uri(uri->s, uri->len, &parsed_uri)<0) {
+               LOG(L_ERR, "ERROR: t_relay: bad_uri: %.*s\n",
+                       uri->len, uri->s );
+               return 0;
+       }
+       if (parsed_uri.port.s){ 
+               port=str2s((unsigned char*)parsed_uri.port.s, parsed_uri.port.len, &err);
+               if (err){
+                       LOG(L_ERR, "ERROR: t_relay: bad port in uri: <%.*s>\n",
+                               parsed_uri.port.len, parsed_uri.port.s);
+                       goto error;
+               }
+       } else port=SIP_PORT;
+       p=mk_proxy(parsed_uri.host.s, port);
+       if (p==0) {
+               LOG(L_ERR, "ERROR: t_relay: bad host name in URI <%.*s>\n",
+                       uri->len, uri->s);
+               goto error;
+       }
+       free_uri( &parsed_uri );
+       return p;
+
+error:
+       free_uri( &parsed_uri );
+       return 0;
+       
+}
+
+#endif
index be31b3d..d205afe 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "msg_translator.h"
 #include "globals.h"
+#include "error.h"
 #include "mem/mem.h"
 #include "dprint.h"
 #include "config.h"
@@ -84,12 +85,6 @@ int check_address(struct ip_addr* ip, char *name, int resolver)
 }
 
 
-
-
-
-
-
-
 char* via_builder( struct sip_msg *msg , unsigned int *len, 
                                        struct socket_info* send_sock )
 {
@@ -101,6 +96,7 @@ char* via_builder( struct sip_msg *msg , unsigned int *len,
 
        line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE);
        if (line_buf==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR, "ERROR: via_builder: out of memory\n");
                goto error;
        }
@@ -162,6 +158,7 @@ char* via_builder( struct sip_msg *msg , unsigned int *len,
        }else{
                LOG(L_ERR, " ERROR: via_builder: via too long (%d)\n",
                                via_len);
+               ser_error=E_BUG;
                goto error;
        }
 
@@ -278,6 +275,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
        if (check_address(source_ip, msg->via1->host.s, received_dns)!=0){
                received_buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
                if (received_buf==0){
+                       ser_error=E_OUT_OF_MEM;
                        LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
                        goto error1;
                }
@@ -390,6 +388,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
        }
        new_buf=(char*)local_malloc(new_len+1);
        if (new_buf==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
                goto error;
        }
index 09bbef9..5053331 100644 (file)
@@ -15,6 +15,8 @@
 #include "../dprint.h"
 #include "../data_lump_rpl.h"
 #include "../mem/mem.h"
+#include "../error.h"
+#include "../globals.h"
 
 #ifdef DEBUG_DMALLOC
 #include <mem/dmalloc.h>
@@ -422,13 +424,13 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
        next=q_memchr(buf, ':',  len);
        if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){
                LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n");
-               ret=E_UNSPEC;
+               ser_error=ret=E_BAD_URI;
                goto error;
        }
        buf=next+1; /* next char after ':' */
        if (buf>end){
                LOG(L_DBG, "ERROR: parse_uri: uri too short\n");
-               ret=E_UNSPEC;
+               ser_error=ret=E_BAD_URI;
                goto error;
        }
        /*look for '@' */
@@ -449,7 +451,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        uri->user.s=(char*)pkg_malloc(next-user+1);
                        if (uri->user.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
-                               ret=E_OUT_OF_MEM;
+                               ser_error=ret=E_OUT_OF_MEM;
                                goto error;
                        }
                        memcpy(uri->user.s, user, next-user);
@@ -460,7 +462,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        uri->user.s=(char*)pkg_malloc(passwd-user+1);
                        if (uri->user.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
-                               ret=E_OUT_OF_MEM;
+                               ser_error=ret=E_OUT_OF_MEM;
                                goto error;
                        }
                        memcpy(uri->user.s, user, passwd-user);
@@ -470,7 +472,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        uri->passwd.s=(char*)pkg_malloc(next-passwd+1);
                        if (uri->passwd.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
-                               ret=E_OUT_OF_MEM;
+                               ser_error=ret=E_OUT_OF_MEM;
                                goto error;
                        }
                        memcpy(uri->passwd.s, passwd, next-passwd);
@@ -482,7 +484,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
        /* try to find the rest */
        if(host>=end){
                LOG(L_DBG, "ERROR: parse_uri: missing hostport\n");
-               ret=E_UNSPEC;
+               ser_error=ret=E_UNSPEC;
                goto error;
        }
        next=host;
@@ -529,14 +531,14 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){
                        /* error -> invalid uri we found ';' or '?' before ':' */
                        LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
-                       ret=E_UNSPEC;
+                       ser_error=ret=E_BAD_URI;
                        goto error;
                }
                port_len=(params)?params-port:(headers)?headers-port:end-port;
                uri->port.s=pkg_malloc(port_len+1);
                if (uri->port.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
-                       ret=E_OUT_OF_MEM;
+                       ser_error=ret=E_OUT_OF_MEM;
                        goto error;
                }
                memcpy(uri->port.s, port, port_len);
@@ -549,14 +551,14 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                if ((headers) && (headers<params)){
                        /* error -> invalid uri we found '?' or '?' before ';' */
                        LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
-                       ret=E_UNSPEC;
+                       ser_error=ret=E_BAD_URI;
                        goto error;
                }
                params_len=(headers)?headers-params:end-params;
                uri->params.s=pkg_malloc(params_len+1);
                if (uri->params.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
-                       ret=E_OUT_OF_MEM;
+                       ser_error=ret=E_OUT_OF_MEM;
                        goto error;
                }
                memcpy(uri->params.s, params, params_len);
@@ -570,7 +572,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                uri->headers.s=pkg_malloc(headers_len+1);
                if(uri->headers.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
-                       ret=E_OUT_OF_MEM;
+                       ser_error=ret=E_OUT_OF_MEM;
                        goto error;
                }
                memcpy(uri->headers.s, headers, headers_len);
@@ -611,6 +613,7 @@ int parse_headers(struct sip_msg* msg, int flags)
        while( tmp<end && (flags & msg->parsed_flag) != flags){
                hf=pkg_malloc(sizeof(struct hdr_field));
                if (hf==0){
+                       ser_error=E_OUT_OF_MEM;
                        LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
                        goto error;
                }
@@ -710,6 +713,7 @@ skip:
        return 0;
 
 error:
+       ser_error=E_BAD_REQ;
        if (hf) pkg_free(hf);
        return -1;
 }
index e90f5bd..2f17749 100644 (file)
@@ -75,6 +75,7 @@ enum{
 #define INVITE "INVITE"
 
 /* convenience short-cut macros */
+#define REQ_LINE(_msg) ((_msg)->first_line.u.request)
 #define REQ_METHOD first_line.u.request.method_value
 #define REPLY_STATUS first_line.u.reply.statuscode
 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
diff --git a/proxy.c b/proxy.c
index b31cf1e..c1275a1 100644 (file)
--- a/proxy.c
+++ b/proxy.c
@@ -20,6 +20,7 @@
 
 #include "resolve.h"
 #include "ip_addr.h"
+#include "globals.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -54,7 +55,7 @@ static int hostent_cpy(struct hostent *dst, struct hostent* src)
        dst->h_name=(char*)malloc(sizeof(char) * len);
        if (dst->h_name) strncpy(dst->h_name,src->h_name, len);
        else{
-               ret=E_OUT_OF_MEM;
+               ser_error=ret=E_OUT_OF_MEM;
                goto error;
        }
 
@@ -62,7 +63,7 @@ static int hostent_cpy(struct hostent *dst, struct hostent* src)
        for (len=0;src->h_aliases[len];len++);
        dst->h_aliases=(char**)malloc(sizeof(char*)*(len+1));
        if (dst->h_aliases==0){
-               ret=E_OUT_OF_MEM;
+               ser_error=ret=E_OUT_OF_MEM;
                free(dst->h_name);
                goto error;
        }
@@ -71,7 +72,7 @@ static int hostent_cpy(struct hostent *dst, struct hostent* src)
                len2=strlen(src->h_aliases[i])+1;
                dst->h_aliases[i]=(char*)malloc(sizeof(char)*len2);
                if (dst->h_aliases==0){
-                       ret=E_OUT_OF_MEM;
+                       ser_error=ret=E_OUT_OF_MEM;
                        free(dst->h_name);
                        for(r=0; r<i; r++)      free(dst->h_aliases[r]);
                        free(dst->h_aliases);
@@ -83,7 +84,7 @@ static int hostent_cpy(struct hostent *dst, struct hostent* src)
        for (len=0;src->h_addr_list[len];len++);
        dst->h_addr_list=(char**)malloc(sizeof(char*)*(len+1));
        if (dst->h_addr_list==0){
-               ret=E_OUT_OF_MEM;
+               ser_error=ret=E_OUT_OF_MEM;
                free(dst->h_name);
                for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
                free(dst->h_aliases[r]);
@@ -94,7 +95,7 @@ static int hostent_cpy(struct hostent *dst, struct hostent* src)
        for (i=0;i<len;i++){
                dst->h_addr_list[i]=(char*)malloc(sizeof(char)*src->h_length);
                if (dst->h_addr_list[i]==0){
-                       ret=E_OUT_OF_MEM;
+                       ser_error=ret=E_OUT_OF_MEM;
                        free(dst->h_name);
                        for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
                        free(dst->h_aliases[r]);
@@ -170,6 +171,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
 
        p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
        if (p==0){
+               ser_error=E_OUT_OF_MEM;
                LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
                goto error;
        }
@@ -186,6 +188,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
                memcpy(p->host.h_name, name, len);
                p->host.h_aliases=malloc(sizeof(char*));
                if (p->host.h_aliases==0) {
+                       ser_error=E_OUT_OF_MEM;
                        free(p->host.h_name);
                        goto error;
                }
@@ -194,6 +197,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
                p->host.h_length=4;
                p->host.h_addr_list=malloc(2*sizeof(char*));
                if (p->host.h_addr_list==0){
+                       ser_error=E_OUT_OF_MEM;
                        free(p->host.h_name);
                        free(p->host.h_aliases);
                        goto error;
@@ -201,6 +205,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
                p->host.h_addr_list[1]=0;
                p->host.h_addr_list[0]=malloc(5);
                if (p->host.h_addr_list[0]==0){
+                       ser_error=E_OUT_OF_MEM;
                        free(p->host.h_name);
                        free(p->host.h_aliases);
                        free(p->host.h_addr_list);
@@ -216,6 +221,7 @@ struct proxy_l* mk_proxy(char* name, unsigned short port)
 
        he=resolvehost(name);
        if (he==0){
+               ser_error=E_BAD_ADDRESS;
                LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
                                        " \"%s\"\n", name);
                free(p);