REORG/MEDIUM: replace stream interface protocol functions by a proto pointer
The stream interface now makes use of the socket protocol pointer instead
of the direct functions.
diff --git a/src/backend.c b/src/backend.c
index f125931..4652fba 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -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 @@
* 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 @@
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;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 8bfa4b2..e4ee9a0 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1266,6 +1266,15 @@
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 @@
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;
diff --git a/src/peers.c b/src/peers.c
index 31fb8d9..ba57e18 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1154,9 +1154,8 @@
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 @@
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 @@
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);
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index f709e73..478bff5 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -70,6 +70,7 @@
.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 @@
.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,
diff --git a/src/protocols.c b/src/protocols.c
index 5b3e081..155636f 100644
--- a/src/protocols.c
+++ b/src/protocols.c
@@ -319,6 +319,18 @@
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. */
/************************************************************************/
diff --git a/src/session.c b/src/session.c
index 5cddabd..af3a464 100644
--- a/src/session.c
+++ b/src/session.c
@@ -169,10 +169,8 @@
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 @@
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 @@
/*
* 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 @@
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 @@
*/
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;
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 35ebc30..543cfee 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -331,7 +331,7 @@
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 @@
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;