bignag change -- lot of things primarily added in relationship with
[sip-router] / forward.c
index 6197599..53588bd 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -13,6 +13,7 @@
 #include <arpa/inet.h>
 
 #include "forward.h"
+#include "hash_func.h"
 #include "config.h"
 #include "parser/msg_parser.h"
 #include "route.h"
@@ -67,6 +68,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        char* buf;
        union sockaddr_union* to;
        struct socket_info* send_sock;
+       char md5[MD5_LEN];
        
        to=0;
        buf=0;
@@ -98,13 +100,39 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
                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;
+               goto error1;
        }
-       
+
+       /* calculate branch for outbound request;  if syn_branch is turned off,
+          calculate is from transaction key, i.e., as an md5 of From/To/CallID/
+          CSeq exactly the same way as TM does; good for reboot -- than messages
+          belonging to transaction lost due to reboot will still be forwarded
+          with the same branch parameter and will be match-able downstream
+
+       if it is turned on, we don't care about reboot; we simply put a simple
+          value in there; better for performance
+       */
+
+       if (syn_branch ) {
+               *msg->add_to_branch_s='0';
+               msg->add_to_branch_len=1;
+       } else {
+               if (!char_msg_val( msg, md5 ))  { /* parses transaction key */
+                       LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
+                       goto error1;
+               }
+               msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
+               if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
+                                       msg->add_to_branch_s, &msg->add_to_branch_len )) {
+                       LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
+                       goto error1;
+               }
+       }
+
        buf = build_req_buf_from_sip_req( msg, &len, send_sock);
        if (!buf){
-               LOG(L_ERR, "ERROR: forward_reply: building failed\n");
-               goto error;
+               LOG(L_ERR, "ERROR: forward_request: building failed\n");
+               goto error1;
        }
         /* send it! */
        DBG("Sending:\n%s.\n", buf);
@@ -116,7 +144,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
                        p->errors++;
                        p->ok=0;
                        STATS_TX_DROPS;
-                       goto error;
+                       goto error1;
        }
        /* sent requests stats */
        else STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
@@ -124,13 +152,26 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        free(to);
        /* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/
        return 0;
+
+error1:
+       free(to);
 error:
        if (buf) pkg_free(buf);
-       if (to) free(to);
        return -1;
 }
 
 
+int update_sock_struct_from_ip( union sockaddr_union* to,
+       struct sip_msg *msg )
+{
+       to->sin.sin_port=(msg->via1->port)
+               ?htons(msg->via1->port): htons(SIP_PORT);
+       to->sin.sin_family=msg->src_ip.af;
+       memcpy(&to->sin.sin_addr, &msg->src_ip.u, msg->src_ip.len);
+
+       return 1;
+}
+
 int update_sock_struct_from_via( union sockaddr_union* to,
                                                                 struct via_body* via )
 {
@@ -252,9 +293,10 @@ int forward_reply(struct sip_msg* msg)
                        if (mod->exports->response_f(msg)==0) goto skip;
                }
        }
-       
+
        /* we have to forward the reply stateless, so we need second via -bogdan*/
-       if ((msg->via2==0) || (msg->via2->error!=PARSE_OK))
+       if (parse_headers( msg, HDR_VIA2, 0 )==-1 
+               || (msg->via2==0) || (msg->via2->error!=PARSE_OK))
        {
                /* no second via => error */
                LOG(L_ERR, "ERROR: forward_msg: no 2nd via found in reply\n");