diff --git a/include/types/connection.h b/include/types/connection.h index 578c5b5a6..beaf6bb55 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -35,11 +35,17 @@ struct protocol; 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 35db516bb..63f143e5b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -27,31 +27,48 @@ int conn_fd_handler(int fd) 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 @@ int conn_fd_handler(int fd) 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 8415abbb5..cf26b51ab 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -502,7 +502,7 @@ void stream_sock_update_conn(struct connection *conn) 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; }