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.
This commit is contained in:
Willy Tarreau 2012-05-07 18:12:14 +02:00
parent 5c979a9c71
commit 26d8c59f0b
13 changed files with 70 additions and 30 deletions

View 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 */

View 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;
}

View 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 */
};

View 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 */

View 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 */

View 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() */

View 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;

View 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;

View 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);

View 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,

View 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. */
/************************************************************************/

View 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;

View 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;