]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: connection: use a generic data-layer init() callback
authorWilly Tarreau <w@1wt.eu>
Tue, 2 Oct 2012 23:39:48 +0000 (01:39 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 4 Oct 2012 20:26:10 +0000 (22:26 +0200)
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).

include/proto/session.h
include/types/connection.h
src/connection.c
src/session.c

index b9eb4477173c7c53efd93e552c9fa36229a14d25..049fc931c61822b24f9002decaf01e7c139873e0 100644 (file)
@@ -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
index ddc610e2b2be781ddeeaa6e17d7c875e6b6f9f10..60caa4dc8cc4a03f50a6b8af6c78ae904edcc378 100644 (file)
@@ -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
index 007d3b1bed754e2b31e356b6671c2eec689a9a32..d1813f96758e13bbf711f176d4d5a5963595ca62 100644 (file)
@@ -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;
        }
 
index 62099213dfa6a8a4534603161b04e3414b62c5c1..a32ec6b09d738307a6383be020addd9a37877ccb 100644 (file)
@@ -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;
        }