mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-20 04:37:04 +00:00
MAJOR: tcp: remove the specific I/O callbacks for TCP connection probes
Use a single tcp_connect_probe() instead of tcp_connect_write() and tcp_connect_read(). We call this one only when no data layer function have been processed, so this is a fallback to test for completion of a connection attempt. With this done, we don't have the need for any direct I/O callback anymore. The function still relies on ->write() to wake the stream interface up, so it's not finished.
This commit is contained in:
parent
2c6be84b3a
commit
2da156fe5e
@ -31,6 +31,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
|
||||
void tcpv4_add_listener(struct listener *listener);
|
||||
void tcpv6_add_listener(struct listener *listener);
|
||||
int tcp_connect_server(struct stream_interface *si);
|
||||
int tcp_connect_probe(int fd);
|
||||
int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <types/connection.h>
|
||||
|
||||
#include <proto/proto_tcp.h>
|
||||
#include <proto/stream_interface.h>
|
||||
|
||||
/* I/O callback for fd-based connections. It calls the read/write handlers
|
||||
@ -46,6 +47,18 @@ int conn_fd_handler(int fd)
|
||||
if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
|
||||
if (!conn->data->write(fd))
|
||||
ret |= FD_WAIT_WRITE;
|
||||
|
||||
if (conn->flags & CO_FL_ERROR)
|
||||
goto leave;
|
||||
|
||||
if (conn->flags & CO_FL_WAIT_L4_CONN) {
|
||||
/* still waiting for a connection to establish and no data to
|
||||
* send in order to probe it ? Then let's retry the connect().
|
||||
*/
|
||||
if (!tcp_connect_probe(fd))
|
||||
ret |= FD_WAIT_WRITE;
|
||||
}
|
||||
|
||||
leave:
|
||||
/* remove the events before leaving */
|
||||
fdtab[fd].ev &= ~(FD_POLL_IN | FD_POLL_OUT | FD_POLL_HUP | FD_POLL_ERR);
|
||||
|
@ -61,8 +61,6 @@
|
||||
|
||||
static int tcp_bind_listeners(struct protocol *proto, char *errmsg, int errlen);
|
||||
static int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen);
|
||||
static int tcp_connect_write(int fd);
|
||||
static int tcp_connect_read(int fd);
|
||||
|
||||
/* Note: must not be declared <const> as its list will be overwritten */
|
||||
static struct protocol proto_tcpv4 = {
|
||||
@ -480,10 +478,6 @@ int tcp_connect_server(struct stream_interface *si)
|
||||
|
||||
if (si->send_proxy_ofs)
|
||||
si->conn.flags |= CO_FL_SI_SEND_PROXY;
|
||||
else if (si->ob->flags & BF_OUT_EMPTY) {
|
||||
fdtab[fd].cb[DIR_RD].f = tcp_connect_read;
|
||||
fdtab[fd].cb[DIR_WR].f = tcp_connect_write;
|
||||
}
|
||||
|
||||
fdtab[fd].iocb = conn_fd_handler;
|
||||
fd_insert(fd);
|
||||
@ -536,7 +530,7 @@ int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
* once the connection is established. It returns zero if it needs some polling
|
||||
* before being called again.
|
||||
*/
|
||||
static int tcp_connect_write(int fd)
|
||||
int tcp_connect_probe(int fd)
|
||||
{
|
||||
struct connection *conn = fdtab[fd].owner;
|
||||
struct stream_interface *si = container_of(conn, struct stream_interface, conn);
|
||||
@ -549,6 +543,10 @@ static int tcp_connect_write(int fd)
|
||||
if (!(conn->flags & CO_FL_WAIT_L4_CONN))
|
||||
goto out_ignore; /* strange we were called while ready */
|
||||
|
||||
/* stop here if we reached the end of data */
|
||||
if ((fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP)) == FD_POLL_HUP)
|
||||
goto out_error;
|
||||
|
||||
/* we might have been called just after an asynchronous shutw */
|
||||
if (b->flags & BF_SHUTW)
|
||||
goto out_wakeup;
|
||||
@ -609,49 +607,6 @@ static int tcp_connect_write(int fd)
|
||||
}
|
||||
|
||||
|
||||
/* might be used on connect error */
|
||||
static int tcp_connect_read(int fd)
|
||||
{
|
||||
struct connection *conn = fdtab[fd].owner;
|
||||
struct stream_interface *si = container_of(conn, struct stream_interface, conn);
|
||||
int retval;
|
||||
|
||||
retval = 1;
|
||||
|
||||
if (conn->flags & CO_FL_ERROR)
|
||||
goto out_error;
|
||||
|
||||
if (!(conn->flags & CO_FL_WAIT_L4_CONN)) {
|
||||
retval = 0;
|
||||
goto out_ignore; /* strange we were called while ready */
|
||||
}
|
||||
|
||||
/* stop here if we reached the end of data */
|
||||
if ((fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP)) == FD_POLL_HUP)
|
||||
goto out_error;
|
||||
|
||||
out_wakeup:
|
||||
task_wakeup(si->owner, TASK_WOKEN_IO);
|
||||
out_ignore:
|
||||
fdtab[fd].ev &= ~FD_POLL_IN;
|
||||
return retval;
|
||||
|
||||
out_error:
|
||||
/* Read error on the file descriptor. We mark the FD as STERROR so
|
||||
* that we don't use it anymore. The error is reported to the stream
|
||||
* interface which will take proper action. We must not perturbate the
|
||||
* buffer because the stream interface wants to ensure transparent
|
||||
* connection retries.
|
||||
*/
|
||||
|
||||
conn->flags |= CO_FL_ERROR;
|
||||
fdtab[fd].ev &= ~FD_POLL_STICKY;
|
||||
EV_FD_REM(fd);
|
||||
si->flags |= SI_FL_ERR;
|
||||
goto out_wakeup;
|
||||
}
|
||||
|
||||
|
||||
/* This function tries to bind a TCPv4/v6 listener. It may return a warning or
|
||||
* an error message in <err> if the message is at most <errlen> bytes long
|
||||
* (including '\0'). The return value is composed from ERR_ABORT, ERR_WARN,
|
||||
|
Loading…
Reference in New Issue
Block a user