mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-25 07:41:36 +02:00
MEDIUM: stream: move all the session-specific stuff of stream_accept() earlier
Since the tcp-request connection rules don't need the stream anymore, we can safely move the session-specific stuff earlier and prepare for a split of session and stream initialization. Some work remains to be done.
This commit is contained in:
parent
1df0cc6466
commit
5ecb069c58
108
src/stream.c
108
src/stream.c
@ -98,10 +98,25 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
cli_conn->target = &l->obj_type;
|
||||
cli_conn->proxy_netns = l->netns;
|
||||
|
||||
conn_ctrl_init(cli_conn);
|
||||
|
||||
/* wait for a PROXY protocol header */
|
||||
if (l->options & LI_O_ACC_PROXY) {
|
||||
cli_conn->flags |= CO_FL_ACCEPT_PROXY;
|
||||
conn_sock_want_recv(cli_conn);
|
||||
}
|
||||
|
||||
sess = pool_alloc2(pool2_session);
|
||||
if (!sess)
|
||||
goto out_free_conn;
|
||||
|
||||
p->feconn++;
|
||||
/* This session was accepted, count it now */
|
||||
if (p->feconn > p->fe_counters.conn_max)
|
||||
p->fe_counters.conn_max = p->feconn;
|
||||
|
||||
proxy_inc_fe_conn_ctr(l, p);
|
||||
|
||||
sess->listener = l;
|
||||
sess->fe = p;
|
||||
sess->origin = &cli_conn->obj_type;
|
||||
@ -109,6 +124,45 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
sess->tv_accept = now; /* corrected date for internal use */
|
||||
memset(sess->stkctr, 0, sizeof(sess->stkctr));
|
||||
|
||||
/* now evaluate the tcp-request layer4 rules. Since we expect to be able
|
||||
* to abort right here as soon as possible, we check the rules before
|
||||
* even initializing the stream interfaces.
|
||||
*/
|
||||
if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(sess)) {
|
||||
/* let's do a no-linger now to close with a single RST. */
|
||||
setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
|
||||
ret = 0; /* successful termination */
|
||||
goto out_free_sess;
|
||||
}
|
||||
|
||||
/* monitor-net and health mode are processed immediately after TCP
|
||||
* connection rules. This way it's possible to block them, but they
|
||||
* never use the lower data layers, they send directly over the socket,
|
||||
* as they were designed for. We first flush the socket receive buffer
|
||||
* in order to avoid emission of an RST by the system. We ignore any
|
||||
* error.
|
||||
*/
|
||||
if (unlikely((p->mode == PR_MODE_HEALTH) ||
|
||||
((l->options & LI_O_CHK_MONNET) &&
|
||||
addr->ss_family == AF_INET &&
|
||||
(((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
|
||||
/* we have 4 possibilities here :
|
||||
* - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
|
||||
* - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
|
||||
* - HEALTH mode without HTTP check => just send "OK"
|
||||
* - TCP mode from monitoring address => just close
|
||||
*/
|
||||
if (l->proto->drain)
|
||||
l->proto->drain(cfd);
|
||||
if (p->mode == PR_MODE_HTTP ||
|
||||
(p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
|
||||
send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
|
||||
else if (p->mode == PR_MODE_HEALTH)
|
||||
send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
|
||||
ret = 0;
|
||||
goto out_free_sess;
|
||||
}
|
||||
|
||||
if (unlikely((s = pool_alloc2(pool2_stream)) == NULL))
|
||||
goto out_free_sess;
|
||||
|
||||
@ -136,12 +190,6 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
s->logs.accept_date = sess->accept_date; /* user-visible date for logging */
|
||||
s->logs.tv_accept = sess->tv_accept; /* corrected date for internal use */
|
||||
s->uniq_id = global.req_count++;
|
||||
p->feconn++;
|
||||
/* This stream was accepted, count it now */
|
||||
if (p->feconn > p->fe_counters.conn_max)
|
||||
p->fe_counters.conn_max = p->feconn;
|
||||
|
||||
proxy_inc_fe_conn_ctr(l, p);
|
||||
|
||||
/* Add the minimum callbacks to prepare the connection's control layer.
|
||||
* We need this so that we can safely execute the ACLs used by the
|
||||
@ -151,52 +199,6 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
*/
|
||||
si_attach_conn(&s->si[0], cli_conn);
|
||||
conn_attach(cli_conn, s, &sess_conn_cb);
|
||||
conn_ctrl_init(cli_conn);
|
||||
|
||||
/* now evaluate the tcp-request layer4 rules. Since we expect to be able
|
||||
* to abort right here as soon as possible, we check the rules before
|
||||
* even initializing the stream interfaces.
|
||||
*/
|
||||
if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(sess)) {
|
||||
/* let's do a no-linger now to close with a single RST. */
|
||||
setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
|
||||
ret = 0; /* successful termination */
|
||||
goto out_free_strm;
|
||||
}
|
||||
|
||||
/* monitor-net and health mode are processed immediately after TCP
|
||||
* connection rules. This way it's possible to block them, but they
|
||||
* never use the lower data layers, they send directly over the socket,
|
||||
* as they were designed for. We first flush the socket receive buffer
|
||||
* in order to avoid emission of an RST by the system. We ignore any
|
||||
* error.
|
||||
*/
|
||||
if (unlikely((p->mode == PR_MODE_HEALTH) ||
|
||||
((l->options & LI_O_CHK_MONNET) &&
|
||||
addr->ss_family == AF_INET &&
|
||||
(((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
|
||||
/* we have 4 possibilities here :
|
||||
* - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
|
||||
* - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
|
||||
* - HEALTH mode without HTTP check => just send "OK"
|
||||
* - TCP mode from monitoring address => just close
|
||||
*/
|
||||
if (l->proto->drain)
|
||||
l->proto->drain(cfd);
|
||||
if (p->mode == PR_MODE_HTTP ||
|
||||
(p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
|
||||
send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
|
||||
else if (p->mode == PR_MODE_HEALTH)
|
||||
send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
|
||||
ret = 0;
|
||||
goto out_free_strm;
|
||||
}
|
||||
|
||||
/* wait for a PROXY protocol header */
|
||||
if (l->options & LI_O_ACC_PROXY) {
|
||||
cli_conn->flags |= CO_FL_ACCEPT_PROXY;
|
||||
conn_sock_want_recv(cli_conn);
|
||||
}
|
||||
|
||||
if (unlikely((t = task_new()) == NULL))
|
||||
goto out_free_strm;
|
||||
@ -237,9 +239,9 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
out_free_task:
|
||||
task_free(t);
|
||||
out_free_strm:
|
||||
p->feconn--;
|
||||
pool_free2(pool2_stream, s);
|
||||
out_free_sess:
|
||||
p->feconn--;
|
||||
session_free(sess);
|
||||
out_free_conn:
|
||||
cli_conn->flags &= ~CO_FL_XPRT_TRACKED;
|
||||
|
Loading…
x
Reference in New Issue
Block a user