MEDIUM: connection: use a generic data-layer init() callback
The generic data-layer init callback is now used after the transport
layer is complete and before calling the data layer recv/send callbacks.
This allows the session to switch from the embryonic session data layer
to the complete stream interface data layer, by making conn_session_complete()
the data layer's init callback.
It sill looks awkwards that the init() callback must be used opon error,
but except by adding yet another one, it does not seem to be mergeable
into another function (eg: it should probably not be merged with ->wake
to avoid unneeded calls during the handshake, though semantically that
would make sense).
diff --git a/include/proto/session.h b/include/proto/session.h
index b9eb447..049fc93 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -47,7 +47,6 @@
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 ddc610e..60caa4d 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -86,7 +86,7 @@
/* 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 007d3b1..d1813f9 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -67,12 +67,12 @@
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 @@
}
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 6209921..a32ec6b 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 @@
.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 @@
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 @@
/* 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;
}