int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote);
int tcp_pause_listener(struct listener *l);
-int tcp_connect_server(struct connection *conn, int data, int delack);
+int tcp_connect_server(struct connection *conn, int flags);
int tcp_connect_probe(struct connection *conn);
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);
return SF_ERR_INTERNAL;
if (!conn_ctrl_ready(conn) || !conn_xprt_ready(conn)) {
- ret = conn->ctrl->connect(conn, !channel_is_empty(si_oc(si)), 0);
+ ret = conn->ctrl->connect(conn, channel_is_empty(si_oc(si)) ?
+ CONNECT_HAS_DATA : 0);
if (ret != SF_ERR_NONE)
return ret;
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 connection *, int data, int delack); /* connect function if any */
+ int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */
int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */
int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */
int (*drain)(int fd); /* indicates whether we can safely close the fd */
struct list list; /* list of registered protocols */
};
+#define CONNECT_HAS_DATA 0x00000001 /* There's data available to be sent */
+#define CONNECT_DELACK_SMART_CONNECT 0x00000002 /* Use a delayed ACK if the backend has tcp-smart-connect */
+#define CONNECT_DELACK_ALWAYS 0x00000004 /* Use a delayed ACK */
#endif /* _TYPES_PROTOCOL_H */
/*
struct protocol *proto;
struct tcpcheck_rule *tcp_rule = NULL;
int ret;
- int quickack;
+ int connflags = 0;
/* we cannot have a connection here */
if (conn)
cs_attach(cs, check, &check_conn_cb);
/* only plain tcp-check supports quick ACK */
- quickack = check->type == 0 || check->type == PR_O2_TCPCHK_CHK;
-
- if (tcp_rule && tcp_rule->action == TCPCHK_ACT_EXPECT)
- quickack = 0;
+ if (check->type != 0)
+ connflags |= CONNECT_HAS_DATA;
+ if ((check->type == 0 || check->type == PR_O2_TCPCHK_CHK) &&
+ (!tcp_rule || tcp_rule->action != TCPCHK_ACT_EXPECT))
+ connflags |= CONNECT_DELACK_ALWAYS;
ret = SF_ERR_INTERNAL;
if (proto && proto->connect)
- ret = proto->connect(conn, check->type, quickack ? 2 : 0);
+ ret = proto->connect(conn, connflags);
#ifdef USE_OPENSSL
ret = SF_ERR_INTERNAL;
if (proto && proto->connect)
ret = proto->connect(conn,
- 1 /* I/O polling is always needed */,
- (next && next->action == TCPCHK_ACT_EXPECT) ? 0 : 2);
+ CONNECT_HAS_DATA /* I/O polling is always needed */ | (next && next->action == TCPCHK_ACT_EXPECT) ? 0 : CONNECT_DELACK_ALWAYS);
if (check->current_step->conn_opts & TCPCHK_OPT_SEND_PROXY) {
conn->send_proxy_ofs = 1;
conn->flags |= CO_FL_SEND_PROXY;
static void sockpair_add_listener(struct listener *listener, int port);
static int sockpair_bind_listener(struct listener *listener, char *errmsg, int errlen);
static int sockpair_bind_listeners(struct protocol *proto, char *errmsg, int errlen);
-static int sockpair_connect_server(struct connection *conn, int data, int delack);
+static int sockpair_connect_server(struct connection *conn, int flags);
/* Note: must not be declared <const> as its list will be overwritten */
static struct protocol proto_sockpair = {
* The connection's fd is inserted only when SF_ERR_NONE is returned, otherwise
* it's invalid and the caller has nothing to do.
*/
-static int sockpair_connect_server(struct connection *conn, int data, int delack)
+static int sockpair_connect_server(struct connection *conn, int flags)
{
int sv[2], fd, dst_fd = -1;
}
/* if a send_proxy is there, there are data */
- data |= conn->send_proxy_ofs;
+ if (conn->send_proxy_ofs)
+ flags |= CONNECT_HAS_DATA;
if (global.tune.server_sndbuf)
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf));
* layer when the connection is already OK otherwise we'll have
* no other opportunity to do it later (eg: health checks).
*/
- data = 1;
+ flags |= CONNECT_HAS_DATA;
}
- if (data)
+ if (flags & CONNECT_HAS_DATA)
conn_xprt_want_send(conn); /* prepare to send data if any */
return SF_ERR_NONE; /* connection is OK */
* depending on conn->target. Only OBJ_TYPE_PROXY and OBJ_TYPE_SERVER are
* supported. The <data> parameter is a boolean indicating whether there are data
* waiting for being sent or not, in order to adjust data write polling and on
- * some platforms, the ability to avoid an empty initial ACK. The <delack> argument
- * allows the caller to force using a delayed ACK when establishing the connection :
+ * some platforms, the ability to avoid an empty initial ACK. The <flags> argument
+ * allows the caller to force using a delayed ACK when establishing the connection
* - 0 = no delayed ACK unless data are advertised and backend has tcp-smart-connect
- * - 1 = delayed ACK if backend has tcp-smart-connect, regardless of data
- * - 2 = delayed ACK regardless of backend options
+ * - CONNECT_DELACK_SMART_CONNECT = delayed ACK if backend has tcp-smart-connect, regardless of data
+ * - CONNECT_DELACK_ALWAYS = delayed ACK regardless of backend options
*
* Note that a pending send_proxy message accounts for data.
*
* it's invalid and the caller has nothing to do.
*/
-int tcp_connect_server(struct connection *conn, int data, int delack)
+int tcp_connect_server(struct connection *conn, int flags)
{
int fd;
struct server *srv;
* machine with the first ACK. We only do this if there are pending
* data in the buffer.
*/
- if (delack == 2 || ((delack || data || conn->send_proxy_ofs) && (be->options2 & PR_O2_SMARTCON)))
+ if (flags & (CONNECT_DELACK_ALWAYS) ||
+ ((flags & CONNECT_DELACK_SMART_CONNECT ||
+ (flags & CONNECT_HAS_DATA) || conn->send_proxy_ofs) &&
+ (be->options2 & PR_O2_SMARTCON)))
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &zero, sizeof(zero));
#endif
* layer when the connection is already OK otherwise we'll have
* no other opportunity to do it later (eg: health checks).
*/
- data = 1;
+ flags |= CONNECT_HAS_DATA;
}
- if (data)
+ if (flags & CONNECT_HAS_DATA)
conn_xprt_want_send(conn); /* prepare to send data if any */
return SF_ERR_NONE; /* connection is OK */
static int uxst_bind_listener(struct listener *listener, char *errmsg, int errlen);
static int uxst_bind_listeners(struct protocol *proto, char *errmsg, int errlen);
static int uxst_unbind_listeners(struct protocol *proto);
-static int uxst_connect_server(struct connection *conn, int data, int delack);
+static int uxst_connect_server(struct connection *conn, int flags);
static void uxst_add_listener(struct listener *listener, int port);
static int uxst_pause_listener(struct listener *l);
static int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
* The connection's fd is inserted only when SF_ERR_NONE is returned, otherwise
* it's invalid and the caller has nothing to do.
*/
-static int uxst_connect_server(struct connection *conn, int data, int delack)
+static int uxst_connect_server(struct connection *conn, int flags)
{
int fd;
struct server *srv;
}
/* if a send_proxy is there, there are data */
- data |= conn->send_proxy_ofs;
+ if (conn->send_proxy_ofs)
+ flags |= CONNECT_HAS_DATA;
if (global.tune.server_sndbuf)
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf));
* layer when the connection is already OK otherwise we'll have
* no other opportunity to do it later (eg: health checks).
*/
- data = 1;
+ flags |= CONNECT_HAS_DATA;
}
- if (data)
+ if (flags & CONNECT_HAS_DATA)
conn_xprt_want_send(conn); /* prepare to send data if any */
return SF_ERR_NONE; /* connection is OK */