From: Willy Tarreau Date: Sat, 4 Apr 2015 14:55:53 +0000 (+0200) Subject: MEDIUM: stream: move all the session-specific stuff of stream_accept() earlier X-Git-Tag: v1.6-dev2~248 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5ecb069c58472ff8fc8a6757affb0474eb19e716;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/src/stream.c b/src/stream.c index 47310f5d70..651f0119a6 100644 --- a/src/stream.c +++ b/src/stream.c @@ -98,60 +98,31 @@ 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; - sess->listener = l; - sess->fe = p; - sess->origin = &cli_conn->obj_type; - sess->accept_date = date; /* user-visible date for logging */ - sess->tv_accept = now; /* corrected date for internal use */ - memset(sess->stkctr, 0, sizeof(sess->stkctr)); - - if (unlikely((s = pool_alloc2(pool2_stream)) == NULL)) - goto out_free_sess; - - /* minimum stream initialization required for an embryonic stream is - * fairly low. We need very little to execute L4 ACLs, then we need a - * task to make the client-side connection live on its own. - * - flags - * - stick-entry tracking - */ - s->flags = 0; - s->logs.logwait = p->to_log; - s->logs.level = 0; - - /* Initialise the current rule list pointer to NULL. We are sure that - * any rulelist match the NULL pointer. - */ - s->current_rule_list = NULL; - - memset(s->stkctr, 0, sizeof(s->stkctr)); - - s->sess = sess; - s->si[0].flags = SI_FL_NONE; - s->si[1].flags = SI_FL_ISBACK; - - 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 */ + /* 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); - /* 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 - * "tcp-request connection" ruleset. We also carefully attach the - * connection to the stream interface without initializing the rest, - * so that ACLs can use si[0]->end. - */ - si_attach_conn(&s->si[0], cli_conn); - conn_attach(cli_conn, s, &sess_conn_cb); - conn_ctrl_init(cli_conn); + sess->listener = l; + sess->fe = p; + sess->origin = &cli_conn->obj_type; + sess->accept_date = date; /* user-visible date for logging */ + 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 @@ -161,7 +132,7 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) /* 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; + goto out_free_sess; } /* monitor-net and health mode are processed immediately after TCP @@ -189,14 +160,45 @@ int stream_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) else if (p->mode == PR_MODE_HEALTH) send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE); ret = 0; - goto out_free_strm; + goto out_free_sess; } - /* 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((s = pool_alloc2(pool2_stream)) == NULL)) + goto out_free_sess; + + /* minimum stream initialization required for an embryonic stream is + * fairly low. We need very little to execute L4 ACLs, then we need a + * task to make the client-side connection live on its own. + * - flags + * - stick-entry tracking + */ + s->flags = 0; + s->logs.logwait = p->to_log; + s->logs.level = 0; + + /* Initialise the current rule list pointer to NULL. We are sure that + * any rulelist match the NULL pointer. + */ + s->current_rule_list = NULL; + + memset(s->stkctr, 0, sizeof(s->stkctr)); + + s->sess = sess; + s->si[0].flags = SI_FL_NONE; + s->si[1].flags = SI_FL_ISBACK; + + 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++; + + /* 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 + * "tcp-request connection" ruleset. We also carefully attach the + * connection to the stream interface without initializing the rest, + * so that ACLs can use si[0]->end. + */ + si_attach_conn(&s->si[0], cli_conn); + conn_attach(cli_conn, s, &sess_conn_cb); 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;