diff --git a/include/proto/session.h b/include/proto/session.h index b9eb44771..049fc931c 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -47,7 +47,6 @@ int parse_track_counters(char **args, int *arg, int section_type, struct proxy *curpx, struct track_ctr_prm *prm, struct proxy *defpx, char **err); -int conn_session_complete(struct connection *conn, int flag); /* Remove the refcount from the session to the tracked counters, and clear the * pointer to ensure this is only performed once. The caller is responsible for diff --git a/include/types/connection.h b/include/types/connection.h index ddc610e2b..60caa4dc8 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -86,7 +86,7 @@ enum { /* below we have all handshake flags grouped into one */ CO_FL_HANDSHAKE = CO_FL_SI_SEND_PROXY | CO_FL_SSL_WAIT_HS | CO_FL_ACCEPT_PROXY, - CO_FL_INIT_SESS = 0x00000800, /* initialize a session before using data */ + CO_FL_INIT_DATA = 0x00000800, /* initialize the data layer before using it */ /* when any of these flags is set, polling is defined by socket-layer * operations, as opposed to data-layer. Transport is explicitly not diff --git a/src/connection.c b/src/connection.c index 007d3b1be..d1813f967 100644 --- a/src/connection.c +++ b/src/connection.c @@ -67,12 +67,12 @@ int conn_fd_handler(int fd) if (!(conn->flags & CO_FL_POLL_SOCK)) __conn_sock_stop_both(conn); - /* Maybe we need to finish initializing an incoming session. The - * function may fail and cause the connection to be destroyed, thus + /* The data layer might not be ready yet (eg: when using embryonic + * sessions). If we're about to move data, we must initialize it first. + * The function may fail and cause the connection to be destroyed, thus * we must not use it anymore and should immediately leave instead. */ - if ((conn->flags & CO_FL_INIT_SESS) && - conn_session_complete(conn, CO_FL_INIT_SESS) < 0) + if ((conn->flags & CO_FL_INIT_DATA) && conn->data->init(conn) < 0) return 0; /* The data transfer starts here and stops on error and handshakes */ @@ -103,10 +103,12 @@ int conn_fd_handler(int fd) } leave: - /* we may need to release the connection which is an embryonic session */ - if ((conn->flags & (CO_FL_ERROR|CO_FL_INIT_SESS)) == (CO_FL_ERROR|CO_FL_INIT_SESS)) { - conn->flags |= CO_FL_ERROR; - conn_session_complete(conn, CO_FL_INIT_SESS); + /* we may need to release the connection which is an embryonic session + * in case of failure. For this we use the init callback which will + * detect the error and clean everything up. + */ + if ((conn->flags & (CO_FL_ERROR|CO_FL_INIT_DATA)) == (CO_FL_ERROR|CO_FL_INIT_DATA)) { + conn->data->init(conn); return 0; } diff --git a/src/session.c b/src/session.c index 62099213d..a32ec6b09 100644 --- a/src/session.c +++ b/src/session.c @@ -50,6 +50,7 @@ struct pool_head *pool2_session; struct list sessions; +static int conn_session_complete(struct connection *conn); static struct task *expire_mini_session(struct task *t); int session_complete(struct session *s); @@ -58,7 +59,7 @@ struct data_cb sess_conn_cb = { .recv = NULL, .send = NULL, .wake = NULL, - .init = NULL, + .init = conn_session_complete, }; /* This function is called from the protocol layer accept() in order to @@ -193,7 +194,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) t->process = expire_mini_session; t->expire = tick_add_ifset(now_ms, p->timeout.client); task_queue(t); - s->si[0].conn.flags |= CO_FL_INIT_SESS; + s->si[0].conn.flags |= CO_FL_INIT_DATA; return 1; } @@ -266,12 +267,12 @@ static void kill_mini_session(struct session *s) /* Finish initializing a session from a connection, or kills it if the * connection shows and error. Returns <0 if the connection was killed. */ -int conn_session_complete(struct connection *conn, int flag) +static int conn_session_complete(struct connection *conn) { struct session *s = conn->owner; if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) { - conn->flags &= ~flag; + conn->flags &= ~CO_FL_INIT_DATA; return 0; }