struct receiver {
int fd; /* handle we receive from (fd only for now) */
unsigned int flags; /* receiver options (RX_F_*) */
+ struct protocol *proto; /* protocol this receiver belongs to */
+ struct list proto_list; /* list in the protocol header */
/* warning: this struct is huge, keep it at the bottom */
struct sockaddr_storage addr; /* the address the socket is bound to */
};
int luid; /* listener universally unique ID, used for SNMP */
int options; /* socket options : LI_O_* */
struct fe_counters *counters; /* statistics counters */
- struct protocol *proto; /* protocol this listener belongs to */
int nbconn; /* current number of connections on this listener */
int maxconn; /* maximum connections allowed on this listener */
unsigned int backlog; /* if set, listen backlog */
struct list by_fe; /* chaining in frontend's list of listeners */
struct list by_bind; /* chaining in bind_conf's list of listeners */
struct bind_conf *bind_conf; /* "bind" line settings, include SSL settings among other things */
- struct list proto_list; /* list in the protocol header */
struct receiver rx; /* network receiver parts */
struct {
struct eb32_node id; /* place in the tree of used IDs */
if (l->state <= LI_ZOMBIE)
goto end;
- if (l->proto->pause) {
+ if (l->rx.proto->pause) {
/* Returns < 0 in case of failure, 0 if the listener
* was totally stopped, or > 0 if correctly paused.
*/
- int ret = l->proto->pause(l);
+ int ret = l->rx.proto->pause(l);
if (ret < 0) {
ret = 0;
char msg[100];
int err;
- err = l->proto->bind(l, msg, sizeof(msg));
+ err = l->rx.proto->bind(l, msg, sizeof(msg));
if (err & ERR_ALERT)
ha_alert("Resuming listener: %s\n", msg);
else if (err & ERR_WARN)
goto end;
}
- if (l->proto->sock_prot == IPPROTO_TCP &&
+ if (l->rx.proto->sock_prot == IPPROTO_TCP &&
l->state == LI_PAUSED &&
listen(l->rx.fd, listener_backlog(l)) != 0) {
ret = 0;
{
struct listener *listener;
- list_for_each_entry(listener, &proto->listeners, proto_list)
+ list_for_each_entry(listener, &proto->listeners, rx.proto_list)
enable_listener(listener);
return ERR_NONE;
}
{
struct listener *listener;
- list_for_each_entry(listener, &proto->listeners, proto_list)
+ list_for_each_entry(listener, &proto->listeners, rx.proto_list)
disable_listener(listener);
return ERR_NONE;
}
HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock);
if (listener->state == LI_ASSIGNED) {
listener->state = LI_INIT;
- LIST_DEL(&listener->proto_list);
- listener->proto->nb_listeners--;
+ LIST_DEL(&listener->rx.proto_list);
+ listener->rx.proto->nb_listeners--;
_HA_ATOMIC_SUB(&jobs, 1);
_HA_ATOMIC_SUB(&listeners, 1);
}
}
list_for_each_entry(l, &bind_conf->listeners, by_bind) {
/* Currently, only UDP handlers are allowed */
- if (l->proto->sock_domain != AF_CUST_UDP4 && l->proto->sock_domain != AF_CUST_UDP6) {
+ if (l->rx.proto->sock_domain != AF_CUST_UDP4 && l->rx.proto->sock_domain != AF_CUST_UDP6) {
ha_alert("parsing [%s:%d] : '%s %s' : error, listening address must be prefixed using 'udp@', 'udp4@' or 'udp6@' %s.\n",
file, linenum, args[0], args[1], args[2]);
err_code |= ERR_ALERT | ERR_FATAL;
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_sockpair;
- LIST_ADDQ(&proto_sockpair.listeners, &listener->proto_list);
+ listener->rx.proto = &proto_sockpair;
+ LIST_ADDQ(&proto_sockpair.listeners, &listener->rx.proto_list);
proto_sockpair.nb_listeners++;
}
listener->state = LI_LISTEN;
- fd_insert(fd, listener, listener->proto->accept,
+ fd_insert(fd, listener, listener->rx.proto->accept,
thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
return err;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
#endif
- if (!ext && bind(fd, (struct sockaddr *)&listener->rx.addr, listener->proto->sock_addrlen) == -1) {
+ if (!ext && bind(fd, (struct sockaddr *)&listener->rx.addr, listener->rx.proto->sock_addrlen) == -1) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot bind socket";
goto tcp_close_return;
listener->rx.fd = fd;
listener->state = LI_LISTEN;
- fd_insert(fd, listener, listener->proto->accept,
+ fd_insert(fd, listener, listener->rx.proto->accept,
thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
/* for now, all regularly bound TCP listeners are exportable */
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_tcpv4;
+ listener->rx.proto = &proto_tcpv4;
((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
- LIST_ADDQ(&proto_tcpv4.listeners, &listener->proto_list);
+ LIST_ADDQ(&proto_tcpv4.listeners, &listener->rx.proto_list);
proto_tcpv4.nb_listeners++;
}
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_tcpv6;
+ listener->rx.proto = &proto_tcpv6;
((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
- LIST_ADDQ(&proto_tcpv6.listeners, &listener->proto_list);
+ LIST_ADDQ(&proto_tcpv6.listeners, &listener->rx.proto_list);
proto_tcpv6.nb_listeners++;
}
struct sockaddr_storage addr_inet = listener->rx.addr;
/* force to classic sock family */
- addr_inet.ss_family = listener->proto->sock_family;
+ addr_inet.ss_family = listener->rx.proto->sock_family;
/* ensure we never return garbage */
if (errlen)
* IPPROTO (sockaddr is not enough)
*/
- fd = my_socketat(listener->bind_conf->settings.netns, listener->proto->sock_family, listener->proto->sock_type, listener->proto->sock_prot);
+ fd = my_socketat(listener->bind_conf->settings.netns,
+ listener->rx.proto->sock_family,
+ listener->rx.proto->sock_type,
+ listener->rx.proto->sock_prot);
if (fd == -1) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot create listening socket";
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
#endif
- if (bind(fd, (struct sockaddr *)&addr_inet, listener->proto->sock_addrlen) < 0) {
+ if (bind(fd, (struct sockaddr *)&addr_inet, listener->rx.proto->sock_addrlen) < 0) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot bind socket";
goto udp_close_return;
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_udp4;
+ listener->rx.proto = &proto_udp4;
((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
- LIST_ADDQ(&proto_udp4.listeners, &listener->proto_list);
+ LIST_ADDQ(&proto_udp4.listeners, &listener->rx.proto_list);
proto_udp4.nb_listeners++;
}
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_udp6;
+ listener->rx.proto = &proto_udp6;
((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
- LIST_ADDQ(&proto_udp6.listeners, &listener->proto_list);
+ LIST_ADDQ(&proto_udp6.listeners, &listener->rx.proto_list);
proto_udp6.nb_listeners++;
}
listener->rx.fd = fd;
listener->state = LI_LISTEN;
- fd_insert(fd, listener, listener->proto->accept,
+ fd_insert(fd, listener, listener->rx.proto->accept,
thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
/* for now, all regularly bound UNIX listeners are exportable */
if (listener->state != LI_INIT)
return;
listener->state = LI_ASSIGNED;
- listener->proto = &proto_unix;
- LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
+ listener->rx.proto = &proto_unix;
+ LIST_ADDQ(&proto_unix.listeners, &listener->rx.proto_list);
proto_unix.nb_listeners++;
}
err = 0;
HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
list_for_each_entry(proto, &protocols, list) {
- list_for_each_entry(listener, &proto->listeners, proto_list) {
+ list_for_each_entry(listener, &proto->listeners, rx.proto_list) {
lerr = proto->bind(listener, msg, sizeof(msg));
/* errors are reported if <verbose> is set or if they are fatal */
err = 0;
HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
list_for_each_entry(proto, &protocols, list) {
- list_for_each_entry(listener, &proto->listeners, proto_list)
+ list_for_each_entry(listener, &proto->listeners, rx.proto_list)
unbind_listener(listener);
}
HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
cli_conn->flags |= CO_FL_ADDR_FROM_SET;
cli_conn->proxy_netns = l->bind_conf->settings.netns;
- conn_prepare(cli_conn, l->proto, l->bind_conf->xprt);
+ conn_prepare(cli_conn, l->rx.proto, l->bind_conf->xprt);
conn_ctrl_init(cli_conn);
/* wait for a PROXY protocol header */
* - HEALTH mode without HTTP check => just send "OK"
* - TCP mode from monitoring address => just close
*/
- if (l->proto->drain)
- l->proto->drain(cfd);
+ if (l->rx.proto->drain)
+ l->rx.proto->drain(cfd);
if (p->mode == PR_MODE_HTTP ||
(p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK &&
(p->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK))
int ns_namelen = 0;
int ret = -1;
- if (!l->proto->addrcmp)
+ if (!l->rx.proto->addrcmp)
return -1;
/* WT: this is not the right way to do it, it is temporary for the
#ifdef USE_NS
(!ns_namelen || strcmp(l->bind_conf->settings.netns->node.key, xfer_sock->namespace) == 0) &&
#endif
- l->proto->addrcmp(&xfer_sock->addr, &l->rx.addr) == 0)
+ l->rx.proto->addrcmp(&xfer_sock->addr, &l->rx.addr) == 0)
break;
xfer_sock = xfer_sock->next;
}
tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(strm->logs.accept_date.tv_usec),
strm->uniq_id,
- strm_li(strm) ? strm_li(strm)->proto->name : "?");
+ strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
conn = objt_conn(strm_orig(strm));
switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
chunk_appendf(&trash,
"%p: proto=%s",
curr_strm,
- strm_li(curr_strm) ? strm_li(curr_strm)->proto->name : "?");
+ strm_li(curr_strm) ? strm_li(curr_strm)->rx.proto->name : "?");
conn = objt_conn(strm_orig(curr_strm));
switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {