- force_send_socket per message API support
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 9 Nov 2004 15:15:11 +0000 (15:15 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 9 Nov 2004 15:15:11 +0000 (15:15 +0000)
 => changedinterface to get_send_socket; it takes now also the sip msg as param
 (updated the calls to it in all the modules)

17 files changed:
Makefile.defs
action.c
forward.c
forward.h
modules/tm/t_fwd.c
modules/tm/t_lookup.c
modules/tm/t_msgbuilder.c
modules/tm/t_reply.c
modules/tm/uac.c
modules/tm/uac_fifo.c
modules/tm/uac_unixsock.c
modules/tm/ut.h
parser/msg_parser.c
parser/msg_parser.h
socket_info.c
socket_info.h
tcp_main.c

index dab63bc..63b120d 100644 (file)
@@ -50,7 +50,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL =   99
-EXTRAVERSION = -dev12
+EXTRAVERSION = -dev13
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
index ae18c59..723b3c8 100644 (file)
--- a/action.c
+++ b/action.c
@@ -241,7 +241,7 @@ int do_action(struct action* a, struct sip_msg* msg)
                                p->tx_bytes+=msg->len;
                                if (a->type==SEND_T){
                                        /*udp*/
-                                       send_sock=get_send_socket(to, PROTO_UDP);
+                                       send_sock=get_send_socket(msg, to, PROTO_UDP);
                                        if (send_sock!=0){
                                                ret=udp_send(send_sock, msg->buf, msg->len, to);
                                        }else{
index a5bdf20..ddc8cc3 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -45,6 +45,7 @@
  *  2003-10-21  check_self updated to handle proto (andrei)
  *  2003-10-24  converted to the new socket_info lists (andrei)
  *  2004-10-10  modified check_self to use grep_sock_info (andrei)
+ *  2004-11-08  added force_send_socket support in get_send_socket (andrei)
  */
 
 
@@ -79,6 +80,8 @@
 #include <dmalloc.h>
 #endif
 
+
+
 /* return a socket_info_pointer to the sending socket; as opposed to
  * get_send_socket, which returns process's default socket, get_out_socket
  * attempts to determine the outbound interface which will be used;
@@ -153,11 +156,29 @@ found:
 
 
 /* returns a socket_info pointer to the sending socket or 0 on error
- * params: destination socket_union pointer
+ * params: sip msg (can be null), destination socket_union pointer, protocol
+ * if msg!=null and msg->force_send_socket, the force_send_socket will be
+ * used
  */
-struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
+struct socket_info* get_send_socket(struct sip_msg *msg, 
+                                                                               union sockaddr_union* to, int proto)
 {
        struct socket_info* send_sock;
+       
+       /* check if send interface is not forced */
+       if (msg && msg->force_send_socket){
+               if (msg->force_send_socket->proto!=proto){
+                       DBG("get_send_socket: force_send_socket of different proto"
+                                       " (%d)!\n", proto);
+                       msg->force_send_socket=find_si(&(msg->force_send_socket->address),
+                                                                                       msg->force_send_socket->port_no,
+                                                                                       proto);
+               }
+               if (msg->force_send_socket) 
+                       return msg->force_send_socket;
+               else
+                       LOG(L_WARN, "WARNING: get_send_socket: protocol/port mismatch\n");
+       };
 
        if (mhomed && proto==PROTO_UDP) return get_out_socket(to, proto);
 
@@ -278,7 +299,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
        p->tx_bytes+=len;
        
 
-       send_sock=get_send_socket(to, proto);
+       send_sock=get_send_socket(msg, to, proto);
        if (send_sock==0){
                LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
                                "no corresponding listening socket\n", to->s.sa_family, proto);
index a323123..1e0665f 100644 (file)
--- a/forward.h
+++ b/forward.h
@@ -53,7 +53,9 @@
 #endif
 
 
-struct socket_info* get_send_socket(union sockaddr_union* su, int proto);
+
+struct socket_info* get_send_socket(struct sip_msg* msg,
+                                                                       union sockaddr_union* su, int proto);
 struct socket_info* get_out_socket(union sockaddr_union* to, int proto);
 int check_self(str* host, unsigned short port, unsigned short proto);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p, int proto);
@@ -87,7 +89,7 @@ static inline int msg_send(   struct socket_info* send_sock, int proto,
 {
        
        if (proto==PROTO_UDP){
-               if (send_sock==0) send_sock=get_send_socket(to, proto);
+               if (send_sock==0) send_sock=get_send_socket(0, to, proto);
                if (send_sock==0){
                        LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
                        goto error;
index 7f1b87e..e288b07 100644 (file)
@@ -215,7 +215,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
        hostent2su( &to, &proxy->host, proxy->addr_idx, 
                proxy->port ? proxy->port:SIP_PORT);
 
-       send_sock=get_send_socket( &to , proto);
+       send_sock=get_send_socket( request, &to , proto);
        if (send_sock==0) {
                LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d "
                        " (no corresponding listening socket)\n",
index f1f7c37..6a73d80 100644 (file)
@@ -933,7 +933,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
        */
        backup_mhomed=mhomed;
        mhomed=0;
-       send_sock=get_send_socket(&rb->dst.to, proto);
+       send_sock=get_send_socket(msg, &rb->dst.to, proto);
        mhomed=backup_mhomed;
        if (send_sock==0) {
                LOG(L_ERR, "ERROR: init_rb: cannot fwd to af %d, proto %d "
index 9938757..3b96aaf 100644 (file)
@@ -408,7 +408,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
        
        
             /* via */
-       send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
+       send_sock = uri2sock(rpl, next_hop, &to_su, PROTO_NONE);
        if (!send_sock) {
                LOG(L_ERR, "build_dlg_ack: no socket found\n");
                goto error;
index aa6a6ab..d19e6a4 100644 (file)
@@ -309,7 +309,8 @@ static char *build_local_ack(struct sip_msg* rpl, struct cell *trans, int branch
       * The function is used to send a localy generated ACK to INVITE
       * (tm generates the ACK on behalf of application using UAC
       */
-static int send_local_ack(str* next_hop, char* ack, int ack_len)
+static int send_local_ack(struct sip_msg* msg, str* next_hop,
+                                                       char* ack, int ack_len)
 {
        struct socket_info* send_sock;
        union sockaddr_union to_su;
@@ -319,7 +320,7 @@ static int send_local_ack(str* next_hop, char* ack, int ack_len)
                return -1;
        }
        
-       send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
+       send_sock = uri2sock(msg, next_hop, &to_su, PROTO_NONE);
        if (!send_sock) {
                LOG(L_ERR, "send_local_ack: no socket found\n");
                return -1;
@@ -480,6 +481,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
        static struct cell *backup_t;
        static unsigned int backup_msgid;
        static struct usr_avp **backup_list;
+       static struct socket_info* backup_si;
 
        if (msg) {
                /* remember we are back in request processing, but process
@@ -502,6 +504,9 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
                set_t(t);
                /* make available the avp list from transaction */
                backup_list = set_avp_list( &t->user_avps );
+               /* set default send address to the saved value */
+               backup_si=bind_address;
+               bind_address=t->uac[0].request.dst.send_sock;
        } else {
                /* restore original environment */
                set_t(backup_t);
@@ -509,6 +514,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
                rmode=backup_mode;
                /* restore original avp list */
                set_avp_list( backup_list );
+               bind_address=backup_si;
        }
 }
 
@@ -1255,7 +1261,7 @@ int reply_received( struct sip_msg  *p_msg )
                } else if ((t->flags & T_IS_LOCAL_FLAG) && msg_status >= 200) {
                        ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);
                        if (ack) {
-                               if (send_local_ack(&next_hop, ack, ack_len) < 0) {
+                               if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {
                                        LOG(L_ERR, "Error while sending local ACK\n");
                                }
                                shm_free(ack);
index 689637b..4587572 100644 (file)
@@ -185,7 +185,8 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 
        DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
                        dialog->hooks.next_hop->s);
-       send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE);
+       /* it's a new message, so we will take the default socket */
+       send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);
        if (!send_sock) {
                ret=ser_error;
                LOG(L_ERR, "t_uac: no socket found\n");
index a7b6b61..91dd120 100644 (file)
@@ -267,7 +267,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
                                                if (!new) goto error;
                                                /* substitute */
                                                if (!sock_name) {
-                                                       send_sock=uri2sock( uri, &to_su, proto );
+                                                       send_sock=uri2sock(0, uri, &to_su, proto );
                                                        if (!send_sock) {
                                                                LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
                                                                goto error;
index f8c38c1..0c17cce 100644 (file)
@@ -294,7 +294,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
                                        if (!new_str(begin, frag_len, &last, &total_len)) goto error;
                                             /* substitute */
                                        if (!sock_name) {
-                                               send_sock = uri2sock(uri, &to_su, proto);
+                                               send_sock = uri2sock(0, uri, &to_su, proto);
                                                if (!send_sock) {
                                                        LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
                                                        goto error;
index 2970464..5a671fa 100644 (file)
@@ -133,7 +133,8 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
 /*
  * Convert a URI into socket_info
  */
-static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su, int proto)
+static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
+                                                                       union sockaddr_union *to_su, int proto)
 {
        struct proxy_l *proxy;
        struct socket_info* send_sock;
@@ -148,7 +149,7 @@ static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su
        hostent2su(to_su, &proxy->host, proxy->addr_idx, 
                   (proxy->port) ? proxy->port : SIP_PORT);
                        /* we use proxy->proto since uri2proxy just set it correctly*/
-       send_sock = get_send_socket(to_su, proxy->proto);
+       send_sock = get_send_socket(msg, to_su, proxy->proto);
        if (!send_sock) {
                LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
                    to_su->s.sa_family);
index 25a4483..dbd9fdb 100644 (file)
@@ -91,7 +91,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
        }
 
        /* eliminate leading whitespace */
-       tmp=eat_lws_end(tmp, end);
+       /* tmp=eat_lws_end(tmp, end); not allowed anyway --andrei */
        if (tmp>=end) {
                LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n");
                goto error;
index 600e678..d24196f 100644 (file)
@@ -36,6 +36,7 @@
  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
  *  2003-04-12  added msg_flags to sip_msg (andrei)
  *  2003-11-02  added diversion header field to sip_msg (jh)
+ *  2004-11-08  added force_send_socket (andrei)
  */
 
 
@@ -237,6 +238,8 @@ struct sip_msg {
        flag_t flags;   
        str set_global_address;
        str set_global_port;
+       struct socket_info* force_send_socket; /* force sending on this socket,
+                                                                                         if ser */
 };
 
 /* pointer to a fakes message which was never received ;
index 865a4cf..bb19e26 100644 (file)
@@ -33,6 +33,7 @@
  * --------
  *  2003-10-22  created by andrei
  *  2004-10-10  added grep_sock_info (andrei)
+ *  2004-11-08  added find_si (andrei)
  */
 
 
@@ -205,7 +206,6 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
 #ifdef USE_IPV6
        struct ip_addr* ip6;
 #endif
-
        h_len=host->len;
        hname=host->s;
 #ifdef USE_IPV6
@@ -279,6 +279,53 @@ found:
 
 
 
+/* checks if the proto: ip:port is one of the address we listen on
+ * and returns the corresponding socket_info structure.
+ * (same as grep_socket_info, but use ip addr instead)
+ * if port==0, the  port number is ignored
+ * if proto==0 (PROTO_NONE) the protocol is ignored
+ * returns  0 if not found
+ * WARNING: uses str2ip6 so it will overwrite any previous
+ *  unsaved result of this function (static buffer)
+ */
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
+                                                                                               unsigned short proto)
+{
+       struct socket_info* si;
+       struct socket_info** list;
+       unsigned short c_proto;
+       
+       c_proto=proto?proto:PROTO_UDP;
+       do{
+               /* get the proper sock_list */
+               if (c_proto==PROTO_NONE)
+                       list=&udp_listen;
+               else
+                       list=get_sock_info_list(c_proto);
+       
+               if (list==0){
+                       LOG(L_WARN, "WARNING: grep_sock_info: "
+                                               "unknown proto %d\n", c_proto);
+                       goto not_found; /* false */
+               }
+               for (si=*list; si; si=si->next){
+                       if (port) {
+                               if (si->port_no!=port) {
+                                       continue;
+                               }
+                       }
+                       if (ip_addr_cmp(ip, &si->address))
+                               goto found;
+               }
+       }while( (proto==0) && (c_proto=next_proto(c_proto)) );
+not_found:
+       return 0;
+found:
+       return si;
+}
+
+
+
 /* adds a new sock_info structure to the corresponding list
  * return  0 on success, -1 on error */
 int new_sock2list(char* name, unsigned short port, unsigned short proto,
index 347c665..5be326f 100644 (file)
@@ -59,6 +59,8 @@ void print_aliases();
 
 struct socket_info* grep_sock_info(str* host, unsigned short port,
                                                                                unsigned short proto);
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
+                                                                                               unsigned short proto);
 
 /* helper function:
  * returns next protocol, if the last one is reached return 0
index f174aed..8626845 100644 (file)
@@ -51,6 +51,7 @@
  *  2003-11-17  handle_new_connect & tcp_connect will close the 
  *              new socket if tcpconn_new return 0 (e.g. out of mem) (andrei)
  *  2003-11-28  tcp_blocking_write & tcp_blocking_connect added (andrei)
+ *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
  */
 
 
@@ -368,22 +369,6 @@ error:
 
 
 
-
-struct socket_info* find_tcp_si(union sockaddr_union* s)
-{
-       struct ip_addr ip;
-       struct socket_info* si;
-       
-       su2ip_addr(&ip, s);
-       for (si=tcp_listen; si; si=si->next)
-               if (ip_addr_cmp(&ip, &si->address)){
-                       /* found it, we use first match */
-                       return si;
-               }
-       return 0; /* no match */
-}
-
-
 struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
 {
        int s;
@@ -391,6 +376,7 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
        union sockaddr_union my_name;
        socklen_t my_name_len;
        struct tcp_connection* con;
+       struct ip_addr ip;
 
        s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
        if (s==-1){
@@ -412,12 +398,13 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
                                strerror(errno), errno);
                si=0; /* try to go on */
        }
+       su2ip_addr(&ip, &my_name);
 #ifdef USE_TLS
        if (type==PROTO_TLS)
-               si=find_tls_si(&my_name);
+               si=find_si(&ip, 0, PROTO_TLS);
        else
 #endif
-               si=find_tcp_si(&my_name);
+               si=find_si(&ip, 0, PROTO_TCP);
 
        if (si==0){
                LOG(L_ERR, "ERROR: tcp_connect: could not find corresponding"