]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG/MEDIUM: replace stream interface protocol functions by a proto pointer
authorWilly Tarreau <w@1wt.eu>
Mon, 7 May 2012 16:12:14 +0000 (18:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 19:28:15 +0000 (21:28 +0200)
The stream interface now makes use of the socket protocol pointer instead
of the direct functions.

13 files changed:
include/proto/protocols.h
include/proto/stream_sock.h
include/types/peers.h
include/types/protocols.h
include/types/server.h
include/types/stream_interface.h
src/backend.c
src/cfgparse.c
src/peers.c
src/proto_tcp.c
src/protocols.c
src/session.c
src/stream_interface.c

index 05567ea689fec777d23b0b020d6dceb9cd4ad7fc..cebe56091395b65b5e2fd4a6beea1cd1f01faa63 100644 (file)
@@ -125,6 +125,8 @@ int protocol_unbind_all(void);
  */
 int protocol_enable_all(void);
 
+/* returns the protocol associated to family <family> or NULL if not found */
+struct protocol *protocol_by_family(int family);
 
 #endif /* _PROTO_PROTOCOLS_H */
 
index f66d32192a7b63a7c9d6b6655c8cc6dc1c162013..577dad8540e3e42147b8a32c121880987673479b 100644 (file)
@@ -78,8 +78,8 @@ static inline void stream_sock_get_to_addr(struct stream_interface *si)
                return;
        }
 #endif
-       if (si->get_dst &&
-           si->get_dst(si->fd, (struct sockaddr *)&si->addr.to, &namelen) != -1)
+       if (si->proto->get_dst &&
+           si->proto->get_dst(si->fd, (struct sockaddr *)&si->addr.to, &namelen) != -1)
                si->flags |= SI_FL_TO_SET;
        return;
 }
@@ -95,8 +95,8 @@ static inline void stream_sock_get_from_addr(struct stream_interface *si)
                return;
 
        namelen = sizeof(si->addr.to);
-       if (si->get_src &&
-           si->get_src(si->fd, (struct sockaddr *)&si->addr.from, &namelen) != -1)
+       if (si->proto->get_src &&
+           si->proto->get_src(si->fd, (struct sockaddr *)&si->addr.from, &namelen) != -1)
                si->flags |= SI_FL_FROM_SET;
        return;
 }
index 24ab804b19822e17a2864a3ee254a1bfb108ae18..50e4ea384056f51c9994552f3d1e423a96072b25 100644 (file)
@@ -73,6 +73,7 @@ struct peer {
        } conf;                   /* config information */
        time_t last_change;
        struct sockaddr_storage addr;  /* peer address */
+       struct protocol *proto;        /* peer address protocol */
        struct peer *next;        /* next peer in the list */
 };
 
index 104cee56ff8ddc5282d6198bef6fa71ec900b676..4112b08c88de31443fdfd9075312de8b23ca339c 100644 (file)
@@ -134,6 +134,8 @@ struct listener {
        } conf;                         /* config information */
 };
 
+struct stream_interface;
+
 /* This structure contains all information needed to easily handle a protocol.
  * Its primary goal is to ease listeners maintenance. Specifically, the
  * bind_all() primitive must be used before any fork(), and the enable_all()
@@ -154,6 +156,10 @@ struct protocol {
        int (*unbind_all)(struct protocol *proto);      /* unbind all bound listeners */
        int (*enable_all)(struct protocol *proto);      /* enable all bound listeners */
        int (*disable_all)(struct protocol *proto);     /* disable all bound listeners */
+       int (*connect)(struct stream_interface *);      /* connect function if any */
+       int (*get_src)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve src addr */
+       int (*get_dst)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve dst addr */
+
        struct list listeners;                          /* list of listeners using this protocol */
        int nb_listeners;                               /* number of listeners */
        struct list list;                               /* list of registered protocols */
index c0729fc5443fcbec169879e6a7414c810ac3d48f..31f036d83607f35fea55d877313be3e7b6060560 100644 (file)
@@ -148,6 +148,7 @@ struct server {
        int bind_hdr_len;                       /* length of the name of the header above */
        int bind_hdr_occ;                       /* occurrence number of header above: >0 = from first, <0 = from end, 0=disabled */
 #endif
+       struct protocol *proto;                 /* server address protocol */
        unsigned down_time;                     /* total time the server was down */
        time_t last_change;                     /* last time, when the state was changed */
        struct timeval check_start;             /* last health check start time */
index 1dc5052caab59ec5f6b1bdf917ae1a44979b6db9..fb2b258e5856dadfedd0d73d7f7b50528d07a5e1 100644 (file)
@@ -137,10 +137,7 @@ struct stream_interface {
        void *err_loc;          /* commonly the server, NULL when SI_ET_NONE */
 
        struct sock_ops sock;   /* socket level operations */
-
-       int  (*connect)(struct stream_interface *); /* connect function if any */
-       int (*get_src)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve src addr */
-       int (*get_dst)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve dst addr */
+       struct protocol *proto; /* socket protocol */
 
        void (*release)(struct stream_interface *); /* handler to call after the last close() */
 
index f125931818b678f1d9da6e99057d02cdb64a2af9..4652fba047018eccbcb93350062c7b623b75e63b 100644 (file)
@@ -36,6 +36,7 @@
 #include <proto/lb_fwlc.h>
 #include <proto/lb_fwrr.h>
 #include <proto/lb_map.h>
+#include <proto/protocols.h>
 #include <proto/proto_http.h>
 #include <proto/proto_tcp.h>
 #include <proto/queue.h>
@@ -974,9 +975,7 @@ int connect_server(struct session *s)
         * session's freshly assigned target with the stream interface's.
         */
        stream_interface_prepare(s->req->cons, &stream_sock);
-       s->req->cons->connect = tcp_connect_server;
-       s->req->cons->get_src = getsockname;
-       s->req->cons->get_dst = getpeername;
+
        /* the target was only on the session, assign it to the SI now */
        copy_target(&s->req->cons->target, &s->target);
 
@@ -987,13 +986,22 @@ int connect_server(struct session *s)
                stream_sock_get_to_addr(s->req->prod);
        }
 
+       /* set the correct protocol on the output stream interface */
+       if (s->target.type == TARG_TYPE_SERVER)
+               s->req->cons->proto = target_srv(&s->target)->proto;
+       else if (s->target.type == TARG_TYPE_PROXY) {
+               s->req->cons->proto = protocol_by_family(s->req->cons->addr.to.ss_family);
+               if (!s->req->cons->proto)
+                       return SN_ERR_INTERNAL;
+       }
+
        assign_tproxy_address(s);
 
        /* flag for logging source ip/port */
        if (s->fe->options2 & PR_O2_SRC_ADDR)
                s->req->cons->flags |= SI_FL_SRC_ADDR;
 
-       err = s->req->cons->connect(s->req->cons);
+       err = s->req->cons->proto->connect(s->req->cons);
 
        if (err != SN_ERR_NONE)
                return err;
index 8bfa4b2c9798169032980646b300fed491a3660e..e4ee9a052250f5f4d3a284f902b0672916b3de84 100644 (file)
@@ -1266,6 +1266,15 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
                        goto out;
                }
                newpeer->addr = *sk;
+               newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
+
+               if (!sk) {
+                       Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
+                             file, linenum, newpeer->addr.ss_family, args[2]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+
                set_host_port(&newpeer->addr, realport);
 
                if (strcmp(newpeer->id, localpeer) == 0) {
@@ -4080,6 +4089,14 @@ stats_error_parsing:
                                goto out;
                        }
                        newsrv->addr = *sk;
+                       newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
+
+                       if (!sk) {
+                               Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
+                                     file, linenum, newsrv->addr.ss_family, args[2]);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+                       }
                        set_host_port(&newsrv->addr, realport);
 
                        newsrv->check_port      = curproxy->defsrv.check_port;
index 31fb8d95376ea2f329b596d60573b610d2aeb1f4..ba57e1868fc706fcfad55dcdd38758d75d9c1641 100644 (file)
@@ -1154,9 +1154,8 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
        s->si[0].state = s->si[0].prev_state = SI_ST_EST;
        s->si[0].err_type = SI_ET_NONE;
        s->si[0].err_loc = NULL;
-       s->si[0].connect   = NULL;
-       s->si[0].get_src   = NULL;
-       s->si[0].get_dst   = NULL;
+       s->si[0].proto   = NULL;
+       s->si[0].release = NULL;
        clear_target(&s->si[0].target);
        s->si[0].exp = TICK_ETERNITY;
        s->si[0].flags = SI_FL_NONE;
@@ -1173,9 +1172,8 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
        s->si[1].conn_retries = p->conn_retries;
        s->si[1].err_type = SI_ET_NONE;
        s->si[1].err_loc = NULL;
-       s->si[1].connect = tcp_connect_server;
-       s->si[1].get_src = getsockname;
-       s->si[1].get_dst = getpeername;
+       s->si[1].proto = peer->proto;
+       s->si[1].release = NULL;
        set_target_proxy(&s->si[1].target, s->be);
        s->si[1].exp = TICK_ETERNITY;
        s->si[1].flags = SI_FL_NONE;
@@ -1183,7 +1181,6 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
                s->si[1].flags |= SI_FL_INDEP_STR;
 
        stream_interface_prepare(&s->si[1], &stream_sock);
-       s->si[1].release = NULL;
 
        session_init_srv_conn(s);
        set_target_proxy(&s->target, s->be);
index f709e736557eb9d0d650611e7c5db15b9dbbf66c..478bff572978b7f0740150e89639c8ee095d5eea 100644 (file)
@@ -70,6 +70,7 @@ static struct protocol proto_tcpv4 = {
        .sock_addrlen = sizeof(struct sockaddr_in),
        .l3_addrlen = 32/8,
        .accept = &stream_sock_accept,
+       .connect = tcp_connect_server,
        .bind = tcp_bind_listener,
        .bind_all = tcp_bind_listeners,
        .unbind_all = unbind_all_listeners,
@@ -88,6 +89,7 @@ static struct protocol proto_tcpv6 = {
        .sock_addrlen = sizeof(struct sockaddr_in6),
        .l3_addrlen = 128/8,
        .accept = &stream_sock_accept,
+       .connect = tcp_connect_server,
        .bind = tcp_bind_listener,
        .bind_all = tcp_bind_listeners,
        .unbind_all = unbind_all_listeners,
index 5b3e081cfabee334214a77feb5c5cfc2de185be7..155636f4fd81c78beb49c9d40104643a17ceda09 100644 (file)
@@ -319,6 +319,18 @@ int protocol_disable_all(void)
        return err;
 }
 
+/* Returns the protocol handler for socket family <family> or NULL if not found */
+struct protocol *protocol_by_family(int family)
+{
+       struct protocol *proto;
+
+       list_for_each_entry(proto, &protocols, list) {
+               if (proto->sock_domain == family)
+                       return proto;
+       }
+       return NULL;
+}
+
 /************************************************************************/
 /*           All supported ACL keywords must be declared here.          */
 /************************************************************************/
index 5cddabdf85374aa2f2002b323e026f641892a4b2..af3a4644208cf0b4ca8274ec238f722629aa5ca8 100644 (file)
@@ -169,10 +169,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
        s->si[0].state     = s->si[0].prev_state = SI_ST_EST;
        s->si[0].err_type  = SI_ET_NONE;
        s->si[0].err_loc   = NULL;
-       s->si[0].connect   = NULL;
+       s->si[0].proto     = l->proto;
        s->si[0].release   = NULL;
-       s->si[0].get_src   = getpeername;
-       s->si[0].get_dst   = getsockname;
        clear_target(&s->si[0].target);
        s->si[0].exp       = TICK_ETERNITY;
        s->si[0].flags     = SI_FL_NONE;
@@ -195,10 +193,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
        s->si[1].err_type  = SI_ET_NONE;
        s->si[1].conn_retries = 0;  /* used for logging too */
        s->si[1].err_loc   = NULL;
-       s->si[1].connect   = NULL;
+       s->si[1].proto     = NULL;
        s->si[1].release   = NULL;
-       s->si[1].get_src   = NULL;
-       s->si[1].get_dst   = NULL;
        clear_target(&s->si[1].target);
        s->si[1].sock.shutr= stream_int_shutr;
        s->si[1].sock.shutw= stream_int_shutw;
@@ -685,7 +681,7 @@ static int sess_update_st_cer(struct session *s, struct stream_interface *si)
 /*
  * This function handles the transition between the SI_ST_CON state and the
  * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
- * SI_ST_INI) to SI_ST_EST, but only when a ->connect function is defined.
+ * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
  */
 static void sess_establish(struct session *s, struct stream_interface *si)
 {
@@ -713,7 +709,7 @@ static void sess_establish(struct session *s, struct stream_interface *si)
 
        rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
        rep->flags |= BF_READ_ATTACHED; /* producer is now attached */
-       if (si->connect) {
+       if (si->proto) {
                /* real connections have timeouts */
                req->wto = s->be->timeout.server;
                rep->rto = s->be->timeout.server;
@@ -1920,7 +1916,8 @@ struct task *process_session(struct task *t)
                                 */
                                s->req->cons->state = SI_ST_REQ; /* new connection requested */
                                s->req->cons->conn_retries = s->be->conn_retries;
-                               if (unlikely(s->req->cons->target.type == TARG_TYPE_APPLET && !s->req->cons->connect)) {
+                               if (unlikely(s->req->cons->target.type == TARG_TYPE_APPLET &&
+                                            !(s->req->cons->proto && s->req->cons->proto->connect))) {
                                        s->req->cons->state = SI_ST_EST; /* connection established */
                                        s->rep->flags |= BF_READ_ATTACHED; /* producer is now attached */
                                        s->req->wex = TICK_ETERNITY;
index 35ebc30596fefb4bbe0c9f1580dccdd34eed3d34..543cfeea605a17bac04efb7cdc049cd37d8f5415 100644 (file)
@@ -331,7 +331,7 @@ struct task *stream_int_register_handler(struct stream_interface *si, struct si_
        DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", app, si, si->owner);
 
        stream_interface_prepare(si, &stream_int_embedded);
-       si->connect = NULL;
+       si->proto = NULL;
        set_target_applet(&si->target, app);
        si->applet.state = 0;
        si->release   = app->release;
@@ -354,7 +354,7 @@ struct task *stream_int_register_handler_task(struct stream_interface *si,
        DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", fct, si, si->owner);
 
        stream_interface_prepare(si, &stream_int_task);
-       si->connect = NULL;
+       si->proto = NULL;
        clear_target(&si->target);
        si->release   = NULL;
        si->flags |= SI_FL_WAIT_DATA;