MAJOR: connection: call data layer handshakes from the handler
Handshakes is not called anymore from the data handlers, they're only
called from the connection handler when their flag is set.
Also, this move has uncovered an issue with the stream interface notifier :
it doesn't consider the FD_WAIT_* flags possibly set by the handshake
handlers. This will result in a stuck handshake when no data is in the
output buffer. In order to cover this, for now we'll perform the EV_FD_SET
in the SSL handshake function, but this needs to be addressed separately
from the stream interface operations.
diff --git a/include/types/connection.h b/include/types/connection.h
index 578c5b5..beaf6bb 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -35,11 +35,17 @@
enum {
CO_FL_NONE = 0x00000000,
CO_FL_ERROR = 0x00000001, /* a fatal error was reported */
- CO_FL_WAIT_L4_CONN = 0x00000002, /* waiting for L4 to be connected */
+ CO_FL_CONNECTED = 0x00000002, /* the connection is now established */
+ CO_FL_WAIT_L4_CONN = 0x00000004, /* waiting for L4 to be connected */
+ CO_FL_WAIT_L6_CONN = 0x00000008, /* waiting for L6 to be connected (eg: SSL) */
+
+ CO_FL_NOTIFY_SI = 0x00000010, /* notify stream interface about changes */
+
/* flags below are used for connection handshakes */
- CO_FL_SI_SEND_PROXY = 0x00000004, /* send a valid PROXY protocol header */
- CO_FL_NOTIFY_SI = 0x00000008, /* notify stream interface about changes */
- CO_FL_CONNECTED = 0x00000010, /* the connection is now established */
+ CO_FL_SI_SEND_PROXY = 0x00000020, /* send a valid PROXY protocol header */
+
+ /* below we have all handshake flags grouped into one */
+ CO_FL_HANDSHAKE = CO_FL_SI_SEND_PROXY,
};
/* This structure describes a connection with its methods and data.
diff --git a/src/connection.c b/src/connection.c
index 35db516..63f143e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -27,31 +27,48 @@
struct connection *conn = fdtab[fd].owner;
int ret = 0;
- if (!conn)
+ if (unlikely(!conn))
goto leave;
- if (conn->flags & CO_FL_ERROR)
- goto leave;
-
- if (conn->flags & CO_FL_SI_SEND_PROXY)
- if ((ret = conn_si_send_proxy(conn, CO_FL_SI_SEND_PROXY)))
+ process_handshake:
+ while (unlikely(conn->flags & CO_FL_HANDSHAKE)) {
+ if (unlikely(conn->flags & CO_FL_ERROR))
goto leave;
+ if (conn->flags & CO_FL_SI_SEND_PROXY)
+ if ((ret = conn_si_send_proxy(conn, CO_FL_SI_SEND_PROXY)))
+ goto leave;
+ }
+
+ /* OK now we're in the data phase now */
+
if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR))
if (!conn->data->read(conn))
ret |= FD_WAIT_READ;
- if (conn->flags & CO_FL_ERROR)
+ if (unlikely(conn->flags & CO_FL_ERROR))
goto leave;
+ /* It may happen during the data phase that a handshake is
+ * enabled again (eg: SSL)
+ */
+ if (unlikely(conn->flags & CO_FL_HANDSHAKE))
+ goto process_handshake;
+
if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
if (!conn->data->write(conn))
ret |= FD_WAIT_WRITE;
- if (conn->flags & CO_FL_ERROR)
+ if (unlikely(conn->flags & CO_FL_ERROR))
goto leave;
- if (conn->flags & CO_FL_WAIT_L4_CONN) {
+ /* It may happen during the data phase that a handshake is
+ * enabled again (eg: SSL)
+ */
+ if (unlikely(conn->flags & CO_FL_HANDSHAKE))
+ goto process_handshake;
+
+ if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN)) {
/* still waiting for a connection to establish and no data to
* send in order to probe it ? Then let's retry the connect().
*/
@@ -64,7 +81,7 @@
stream_sock_update_conn(conn);
/* Last check, verify if the connection just established */
- if (!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED)))
+ if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
conn->flags |= CO_FL_CONNECTED;
/* remove the events before leaving */
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 8415abb..cf26b51 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -502,7 +502,7 @@
si->flags |= SI_FL_ERR;
/* check for recent connection establishment */
- if (!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED))) {
+ if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED)))) {
si->exp = TICK_ETERNITY;
si->ob->flags |= BF_WRITE_NULL;
}