mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-26 21:31:01 +01:00
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:
parent
5c979a9c71
commit
26d8c59f0b
@ -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 */
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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() */
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
11
src/peers.c
11
src/peers.c
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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. */
|
||||
/************************************************************************/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user