- more dest_info conversions:
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 18 Apr 2006 19:56:48 +0000 (19:56 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 18 Apr 2006 19:56:48 +0000 (19:56 +0000)
    - forward_request takes now a dest_info parameter
    - various something2dst conversions functions
    - got rid of the temprary mk_proxy when forwarding after the uri
    - updated all the affected modules

WARNING: not tested, use with care

15 files changed:
Makefile.defs
action.c
error.c
error.h
forward.c
forward.h
ip_addr.h
modules/tm/t_funcs.c
modules/tm/t_fwd.c
modules/tm/t_reply.c
modules/tm/uac.c
modules/tm/ut.h
proxy.h
resolve.c
resolve.h

index 473d026..3e45495 100644 (file)
@@ -66,7 +66,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev38
+EXTRAVERSION = -dev39
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
                        $(SUBLEVEL) )
index 5c9b3b9..810c753 100644 (file)
--- a/action.c
+++ b/action.c
@@ -62,6 +62,7 @@
 #include "globals.h"
 #include "dset.h"
 #include "onsend.h"
+#include "resolve.h"
 #ifdef USE_TCP
 #include "tcp_server.h"
 #endif
@@ -97,7 +98,6 @@ int do_action(struct action* a, struct sip_msg* msg)
        int ret;
        int v;
        struct dest_info dst;
-       struct proxy_l* p;
        char* tmp;
        char *new_uri, *end, *crt;
        int len;
@@ -105,7 +105,6 @@ int do_action(struct action* a, struct sip_msg* msg)
        struct sip_uri uri, next_hop;
        struct sip_uri *u;
        unsigned short port;
-       int proto;
        unsigned short flags;
        int_str name, value;
 
@@ -133,15 +132,16 @@ int do_action(struct action* a, struct sip_msg* msg)
                case FORWARD_TLS_T:
 #endif
                case FORWARD_UDP_T:
-
-                       if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
+                       /* init dst */
+                       init_dest_info(&dst);
+                       if (a->type==FORWARD_UDP_T) dst.proto=PROTO_UDP;
 #ifdef USE_TCP
-                       else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
+                       else if (a->type==FORWARD_TCP_T) dst.proto= PROTO_TCP;
 #endif
 #ifdef USE_TLS
-                       else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
+                       else if (a->type==FORWARD_TLS_T) dst.proto= PROTO_TLS;
 #endif
-                       else proto= PROTO_NONE;
+                       else dst.proto= PROTO_NONE;
                        if (a->val[0].type==URIHOST_ST){
                                /*parse uri*/
 
@@ -172,11 +172,11 @@ int do_action(struct action* a, struct sip_msg* msg)
                                                        ret=E_UNSPEC;
                                                        goto error_fwd_uri;
                                }
-                               if (proto == PROTO_NONE){ /* only if proto not set get it
+                               if (dst.proto == PROTO_NONE){ /* only if proto not set get it
                                                                                         from the uri */
                                        switch(u->proto){
                                                case PROTO_NONE:
-                                                       proto=PROTO_UDP;
+                                                       dst.proto=PROTO_UDP;
                                                        break;
                                                case PROTO_UDP:
 #ifdef USE_TCP
@@ -185,7 +185,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 #ifdef USE_TLS
                                                case PROTO_TLS:
 #endif
-                                                       proto=u->proto;
+                                                       dst.proto=u->proto;
                                                        break;
                                                default:
                                                        LOG(L_ERR,"ERROR: do action: forward: bad uri"
@@ -202,29 +202,29 @@ int do_action(struct action* a, struct sip_msg* msg)
                                                        ret=E_BAD_PROTO;
                                                        goto error_fwd_uri;
                                                }
-                                               proto=PROTO_TLS;
+                                               dst.proto=PROTO_TLS;
                                        }
 #endif
                                }
-                               /* create a temporary proxy*/
-                               p=mk_proxy(&u->host, port, proto);
-                               if (p==0){
+                               if (sip_hostport2su(&dst.to, &u->host, port, dst.proto)<0){
                                        LOG(L_ERR, "ERROR:  bad host name in uri,"
                                                        " dropping packet\n");
                                        ret=E_BAD_ADDRESS;
                                        goto error_fwd_uri;
                                }
-                               ret=forward_request(msg, p, proto);
-                               /*free_uri(&uri); -- no longer needed, in sip_msg*/
-                               free_proxy(p); /* frees only p content, not p itself */
-                               pkg_free(p);
+                               ret=forward_request(msg, &dst);
                                if (ret>=0) ret=1;
                        }else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
-                               if (proto==PROTO_NONE)
-                                       proto=msg->rcv.proto;
-                               ret=forward_request(msg, (struct proxy_l*)a->val[0].u.data,
-                                                                               proto);
-                               if (ret>=0) ret=1;
+                               if (dst.proto==PROTO_NONE)
+                                       dst.proto=msg->rcv.proto;
+                               proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
+                               ret=forward_request(msg, &dst);
+                               if (ret>=0){
+                                       ret=1;
+                                       proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
+                               }else if (ser_error!=E_OK){
+                                       proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
+                               }
                        }else{
                                LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
                                                a->val[0].type, a->val[1].type);
@@ -239,16 +239,9 @@ int do_action(struct action* a, struct sip_msg* msg)
                                ret=E_BUG;
                                break;
                        }
-                       p=(struct proxy_l*)a->val[0].u.data;
-                       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;
-                       }
-                       ret=hostent2su(&dst.to, &p->host, p->addr_idx,
-                                               (p->port)?p->port:SIP_PORT );
+                       /* init dst */
+                       init_dest_info(&dst);
+                       ret=proxy2su(&dst.to,  (struct proxy_l*)a->val[0].u.data);
                        if (ret==0){
                                if (p_onsend){
                                        tmp=p_onsend->buf;
@@ -257,8 +250,6 @@ int do_action(struct action* a, struct sip_msg* msg)
                                        tmp=msg->buf;
                                        len=msg->len;
                                }
-                               p->tx++;
-                               p->tx_bytes+=len;
                                if (a->type==SEND_T){
                                        /*udp*/
                                        dst.proto=PROTO_UDP; /* not really needed for udp_send */
@@ -271,17 +262,18 @@ int do_action(struct action* a, struct sip_msg* msg)
                                }
 #ifdef USE_TCP
                                        else{
-                                       /*tcp*/
-                                       dst.proto=PROTO_TCP;
-                                       dst.id=0;
-                                       ret=tcp_send(&dst, tmp, len);
+                                               /*tcp*/
+                                               dst.proto=PROTO_TCP;
+                                               dst.id=0;
+                                               ret=tcp_send(&dst, tmp, len);
                                }
 #endif
+                       }else{
+                               ret=E_BUG;
+                               break;
                        }
-                       if (ret<0){
-                               p->errors++;
-                               p->ok=0;
-                       }else ret=1;
+                       proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
+                       if (ret>=0) ret=1;
 
                        break;
                case LOG_T:
diff --git a/error.c b/error.c
index 5c94db7..b1ff67b 100644 (file)
--- a/error.c
+++ b/error.c
@@ -119,6 +119,10 @@ int err2reason_phrase(
                        *sip_error=500;
                        break;
 #endif
+               case E_OK:
+                       error_txt="No error";
+                       *sip_error=500;
+                       break;
                default:
                        error_txt="I'm terribly sorry, server error occurred";
                        *sip_error=500;
diff --git a/error.h b/error.h
index 9db6c7f..4e7f211 100644 (file)
--- a/error.h
+++ b/error.h
@@ -29,6 +29,7 @@
 #ifndef error_h
 #define error_h
 
+#define E_OK           0
 #define E_UNSPEC      -1
 #define E_OUT_OF_MEM  -2
 #define E_BAD_RE      -3
index 58f704e..9850076 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -261,42 +261,31 @@ found:
 
 
 
-/* parameters:
- *   msg - sip msg
- *   p   - proxy structure to forward to
- *   proto - protocol used
+/* forwards a request to dst
+ * parameters:
+ *   msg       - sip msg
+ *   send_info - filled dest_info structure:
+ *               if the send_socket memeber is null, a send_socket will be 
+ *               choosen automatically
+ * WARNING: don' forget to zero-fill all the  unused members (a non-zero 
+ * random id along with proto==PROTO_TCP can have bad consequences, same for
+ *   a bogus send_socket vaule)
  */
-int forward_request(struct sip_msg* msg, struct proxy_l * p, int proto)
+int forward_request(struct sip_msg* msg, struct dest_info* send_info)
 {
        unsigned int len;
        char* buf;
        char md5[MD5_LEN];
-       struct dest_info send_info;
        
        buf=0;
        
-       /* 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(&send_info.to, &p->host, p->addr_idx, 
-                               (p->port)?p->port:SIP_PORT);
-       p->tx++;
-       p->tx_bytes+=len;
-       
-       
-       send_info.proto=proto;
-       send_info.id=0;
-       send_info.send_sock=get_send_socket(msg, &send_info.to,
-                                                                                       send_info.proto);
-       if (send_info.send_sock==0){
+       if (send_info->send_sock==0)
+               send_info->send_sock=get_send_socket(msg, &send_info->to,
+                                                                                               send_info->proto);
+       if (send_info->send_sock==0){
                LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
                                "no corresponding listening socket\n",
-                               send_info.to.s.sa_family, send_info.proto);
+                               send_info->to.s.sa_family, send_info->proto);
                ser_error=E_NO_SOCKET;
                goto error;
        }
@@ -326,8 +315,8 @@ int forward_request(struct sip_msg* msg, struct proxy_l * p, int proto)
                }
        }
 
-       buf = build_req_buf_from_sip_req(msg, &len, send_info.send_sock,
-                                                                                       send_info.proto);
+       buf = build_req_buf_from_sip_req(msg, &len, send_info->send_sock,
+                                                                                       send_info->proto);
        if (!buf){
                LOG(L_ERR, "ERROR: forward_request: building failed\n");
                goto error;
@@ -335,17 +324,16 @@ int forward_request(struct sip_msg* msg, struct proxy_l * p, int proto)
         /* send it! */
        DBG("Sending:\n%.*s.\n", (int)len, buf);
        DBG("orig. len=%d, new_len=%d, proto=%d\n",
-                       msg->len, len, send_info.proto );
+                       msg->len, len, send_info->proto );
        
-       if (run_onsend(msg, &send_info, buf, len)==0){
+       if (run_onsend(msg, send_info, buf, len)==0){
                LOG(L_INFO, "forward_request: request dropped (onsend_route)\n");
                STATS_TX_DROPS;
+               ser_error=E_OK; /* no error */
                goto error; /* error ? */
        }
-       if (msg_send(&send_info, buf, len)<0){
+       if (msg_send(send_info, buf, len)<0){
                ser_error=E_SEND;
-               p->errors++;
-               p->ok=0;
                STATS_TX_DROPS;
                goto error;
        }
@@ -440,7 +428,7 @@ int forward_reply(struct sip_msg* msg)
        char* s;
        int len;
 #endif
-       memset(&dst, 0, sizeof(struct dest_info));      
+       init_dest_info(&dst);
        new_buf=0;
        /*check if first via host = us */
        if (check_via){
index c605729..2341eea 100644 (file)
--- a/forward.h
+++ b/forward.h
@@ -60,7 +60,7 @@ 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);
+int forward_request( struct sip_msg* msg,  struct dest_info* send_info);
 int update_sock_struct_from_via( union sockaddr_union* to,
                                                                 struct sip_msg* msg,
                                                                 struct via_body* via );
index 279eecf..cae7883 100644 (file)
--- a/ip_addr.h
+++ b/ip_addr.h
@@ -547,4 +547,16 @@ static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)
        he.h_name=hostname;
        return &he;
 }
+
+
+
+/* init a dest_info structure */
+#define init_dest_info(dst) \
+       do{ \
+               (dst)->proto=0; \
+               (dst)->id=0; \
+               (dst)->send_sock=0; \
+               memset(&(dst)->to, 0, sizeof(union sockaddr_union)); \
+       } while(0) 
+
 #endif
index 88e1e1a..6aef325 100644 (file)
@@ -202,6 +202,7 @@ int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
        int reply_ret;
        /* struct hdr_field *hdr; */
        struct cell *t;
+       struct dest_info dst;
 
        ret=0;
 
@@ -229,18 +230,16 @@ int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
                DBG( "SER: forwarding ACK  statelessly \n");
                if (proxy==0) {
                        uri = GET_RURI(p_msg);
-                       proxy=uri2proxy(GET_NEXT_HOP(p_msg), proto);
-                       if (proxy==0) {
-                                       ret=E_BAD_ADDRESS;
-                                       goto done;
+                       if (uri2dst(&dst, GET_NEXT_HOP(p_msg), proto)==0){
+                               ret=E_BAD_ADDRESS;
+                               goto done;
                        }
-                       proto=proxy->proto; /* uri2proxy set it correctly */
-                       ret=forward_request( p_msg , proxy, proto) ;
-                       free_proxy( proxy );    
-                       pkg_free( proxy );
+                       ret=forward_request( p_msg , &dst) ;
                } else {
-                       proto=get_proto(proto, proxy->proto);
-                       ret=forward_request( p_msg , proxy, proto ) ;
+                       init_dest_info(&dst);
+                       dst.proto=get_proto(proto, proxy->proto);
+                       proxy2su(&dst.to, proxy);
+                       ret=forward_request( p_msg , &dst) ;
                }
                goto done;
        }
index 61075a8..d2356db 100644 (file)
@@ -48,6 +48,7 @@
  *  2006-01-27  t_forward_no_ack will return error if a forward on an 
  *              already canceled transaction is attempted (andrei)
  *  2006-02-07  named routes support (andrei)
+ *  2006-04-18  add_uac simplified + switched to struct dest_info (andrei)
  */
 
 #include "defs.h"
@@ -227,10 +228,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
 {
 
        int ret;
-       short temp_proxy;
-       union sockaddr_union to;
        unsigned short branch;
-       struct socket_info* send_sock;
        char *shbuf;
        unsigned int len;
 
@@ -248,52 +246,44 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
                goto error;
        }
 
+       init_dest_info(&t->uac[branch].request.dst);
        /* check DNS resolution */
        if (proxy){
-               temp_proxy=0;
-               proto=get_proto(proto, proxy->proto);
+               /* dst filled from the proxy */
+               t->uac[branch].request.dst.proto=get_proto(proto, proxy->proto);
+               proxy2su(&t->uac[branch].request.dst.to, proxy);
        }else {
-               proxy=uri2proxy( next_hop ? next_hop : uri, proto );
-               if (proxy==0)  {
+               /* dst filled from the uri */
+               if (uri2dst(&t->uac[branch].request.dst,
+                                               next_hop ? next_hop: uri, proto)==0){
                        ret=E_BAD_ADDRESS;
                        goto error;
                }
-               proto=proxy->proto; /* uri2proxy will fix it for us */
-               temp_proxy=1;
        }
 
-       if (proxy->ok==0) {
-               if (proxy->host.h_addr_list[proxy->addr_idx+1])
-                       proxy->addr_idx++;
-               else proxy->addr_idx=0;
-               proxy->ok=1;
-       }
-
-       hostent2su( &to, &proxy->host, proxy->addr_idx, 
-               proxy->port ? proxy->port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT));
-
-       send_sock=get_send_socket( request, &to , proto);
-       if (send_sock==0) {
+       /* fill dst send_sock */
+       t->uac[branch].request.dst.send_sock =
+                       get_send_socket( request, &t->uac[branch].request.dst.to,
+                                                               t->uac[branch].request.dst. proto);
+       if (t->uac[branch].request.dst.send_sock==0) {
                LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d "
                        " (no corresponding listening socket)\n",
-                       to.s.sa_family, proto );
+                       t->uac[branch].request.dst.to.s.sa_family, 
+                       t->uac[branch].request.dst.proto );
                ret=ser_error=E_NO_SOCKET;
                goto error01;
        }
 
        /* now message printing starts ... */
        shbuf=print_uac_request( t, request, branch, uri, 
-               &len, send_sock, proto );
+               &len, t->uac[branch].request.dst.send_sock, 
+                       t->uac[branch].request.dst.proto );
        if (!shbuf) {
                ret=ser_error=E_OUT_OF_MEM;
                goto error01;
        }
 
        /* things went well, move ahead and install new buffer! */
-       t->uac[branch].request.dst.to=to;
-       t->uac[branch].request.dst.send_sock=send_sock;
-       t->uac[branch].request.dst.proto=proto;
-       t->uac[branch].request.dst.id=0;
        t->uac[branch].request.buffer=shbuf;
        t->uac[branch].request.buffer_len=len;
        t->uac[branch].uri.s=t->uac[branch].request.buffer+
@@ -302,17 +292,13 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
        t->nr_of_outgoings++;
 
        /* update stats */
-       proxy->tx++;
-       proxy->tx_bytes+=len;
-
+       if (proxy){
+               proxy_mark(proxy, 1);
+       }
        /* done! */     
        ret=branch;
                
 error01:
-       if (temp_proxy) {
-               free_proxy( proxy );
-               pkg_free( proxy );
-       }
 error:
        return ret;
 }
index f2b9263..4502ce7 100644 (file)
@@ -322,7 +322,7 @@ static int send_local_ack(struct sip_msg* msg, str* next_hop,
                LOG(L_ERR, "send_local_ack: Invalid parameter value\n");
                return -1;
        }
-
+       init_dest_info(&dst);
        dst.send_sock = uri2sock(msg, next_hop, &dst.to, PROTO_NONE);
        if (!dst.send_sock) {
                LOG(L_ERR, "send_local_ack: no socket found\n");
index 00c9a2a..4e44570 100644 (file)
@@ -232,6 +232,8 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
        set_kr(REQ_FWDED);
 
        request = &new_cell->uac[0].request;
+       
+       init_dest_info(&request->dst);
        request->dst.to = to_su;
        request->dst.send_sock = send_sock;
        request->dst.proto = send_sock->proto;
index 5a78589..710edb8 100644 (file)
@@ -35,6 +35,7 @@
  *              specified explicitly (jiri)
  *  2003-07-07  get_proto takes now two protos as arguments (andrei)
  *              tls/sips support for get_proto & uri2proxy (andrei)
+ *  2006-04-13  added uri2dst(), simplified uri2sock() (andrei)
  */
 
 
@@ -52,6 +53,7 @@
 #include "../../forward.h"
 #include "../../mem/mem.h"
 #include "../../parser/msg_parser.h"
+#include "../../resolve.h"
 
 /* a forced_proto takes precedence if != PROTO_NONE */
 inline static enum sip_protos get_proto(enum sip_protos force_proto,
@@ -130,35 +132,71 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
 }
 
 
+
+/*
+ * Convert a URI into a dest_info structure
+ * params: dst - will be filled
+ *         uri - uri in str form
+ *         proto - if != PROTO_NONE, this protocol will be forced over the
+ *                 uri_proto, otherwise the uri proto will be used
+ * returns 0 on error, dst on success
+ */
+inline static struct dest_info *uri2dst(struct dest_info* dst, str *uri, 
+                                                                                       int proto )
+{
+       struct sip_uri parsed_uri;
+       enum sip_protos uri_proto;
+
+       if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
+               LOG(L_ERR, "ERROR: uri2dst: bad_uri: %.*s\n",
+                   uri->len, uri->s );
+               return 0;
+       }
+       
+       if (parsed_uri.type==SIPS_URI_T){
+               if ((parsed_uri.proto!=PROTO_TCP) && (parsed_uri.proto!=PROTO_NONE)){
+                       LOG(L_ERR, "ERROR: uri2dst: bad transport  for sips uri: %d\n",
+                                       parsed_uri.proto);
+                       return 0;
+               }else
+                       uri_proto=PROTO_TLS;
+       }else
+               uri_proto=parsed_uri.proto;
+       
+       init_dest_info(dst);
+       dst->proto= get_proto(proto, uri_proto);
+       sip_hostport2su(&dst->to, &parsed_uri.host, parsed_uri.port_no,
+                                               dst->proto);
+       return dst;
+}
+
+
+
 /*
  * Convert a URI into socket_info
  */
 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;
+       struct dest_info dst;
 
-       proxy = uri2proxy(uri, proto);
-       if (!proxy) {
-               ser_error = E_BAD_ADDRESS;
+       if (uri2dst(&dst, uri, proto)==0){
                LOG(L_ERR, "ERROR: uri2sock: Can't create a dst proxy\n");
+               ser_error=E_BAD_ADDRESS;
                return 0;
        }
+       *to_su=dst.to; /* copy 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(msg, to_su, proxy->proto);
+       /* we use dst->proto since uri2dst just set it correctly*/
+       send_sock = get_send_socket(msg, to_su, dst.proto);
        if (!send_sock) {
                LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
                    to_su->s.sa_family);
                ser_error = E_NO_SOCKET;
        }
-
-       free_proxy(proxy);
-       pkg_free(proxy);
        return send_sock;
 }
 
+
 #endif /* _TM_UT_H */
diff --git a/proxy.h b/proxy.h
index 613de0f..88cf208 100644 (file)
--- a/proxy.h
+++ b/proxy.h
@@ -38,6 +38,7 @@
 #include <netdb.h>
 #include "ip_addr.h"
 #include "str.h"
+#include "config.h"
 
 struct proxy_l{
        struct proxy_l* next;
@@ -66,5 +67,36 @@ struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port,
 void free_proxy(struct proxy_l* p);
 
 
+
+/* returns 0 on success, -1 on error (unknown af/bug) */
+inline static int proxy2su(union sockaddr_union* su, struct proxy_l* p)
+{
+       /* 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;
+       }
+       
+       return hostent2su(su, &p->host, p->addr_idx,
+                               (p->port)?p->port:((p->proto==PROTO_TLS)?SIPS_PORT:SIP_PORT) );
+}
+
+
+
+/* mark as proxy either as ok (err>=0) or as bad (err<0) */
+inline static void proxy_mark(struct proxy_l* p, int err)
+{
+       if (err<0){
+               p->errors++;
+               p->ok=0;
+       }else{
+               p->tx++;
+       }
+}
+
+
+
 #endif
 
index 548f260..1975f38 100644 (file)
--- a/resolve.c
+++ b/resolve.c
@@ -30,6 +30,7 @@
  *  2003-02-13  added proto to sip_resolvehost, for SRV lookups (andrei)
  *  2003-07-03  default port value set according to proto (andrei)
  *  2005-07-11  added resolv_init (timeouts a.s.o) (andrei)
+ *  2006-04-13  added sip_hostport2su()  (andrei)
  */ 
 
 
@@ -43,6 +44,7 @@
 #include "dprint.h"
 #include "mem/mem.h"
 #include "ip_addr.h"
+#include "error.h"
 
 
 
@@ -587,3 +589,31 @@ skip_srv:
        he=resolvehost(tmp);
        return he;
 }
+
+
+
+/* resolve host, port, proto using sip rules (e.g. use SRV if port=0 a.s.o)
+ *  and write the result in the sockaddr_union to
+ *  returns -1 on error (resolve failed), 0 on success */
+int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
+                                               int proto)
+{
+       struct hostent* he;
+       
+       
+       he=sip_resolvehost(name, &port, proto);
+       if (he==0){
+               ser_error=E_BAD_ADDRESS;
+               LOG(L_ERR, "ERROR: sip_hostport2su: could not resolve hostname:"
+                                       " \"%.*s\"\n", name->len, name->s);
+               goto error;
+       }
+       /* port filled by sip_resolvehost if empty*/
+       if (hostent2su(su, he, 0, port)<0){
+               ser_error=E_BAD_ADDRESS;
+               goto error;
+       }
+       return 0;
+error:
+       return -1;
+}
index 71a7ac6..58d3bbb 100644 (file)
--- a/resolve.h
+++ b/resolve.h
@@ -359,4 +359,6 @@ skip_ipv4:
 
 int resolv_init();
 
+int sip_hostport2su(union sockaddr_union* su, str* host, unsigned short port,
+                                               int proto);
 #endif