]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stream_interface: offer a generic function for connection updates
authorWilly Tarreau <wtarreau@exceliance.fr>
Mon, 20 Aug 2012 10:06:26 +0000 (12:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 2 Sep 2012 19:54:18 +0000 (21:54 +0200)
We need to have a generic function to be called by upper layers when buffer
flags have been updated (the si->update function). At the moment, both sock_raw
and sock_ssl had their own which basically was a copy-paste. Since these
functions are only used to update stream interface flags, it is logical to
have them handled by the stream interface code.

This allowed us to remove the stream_interface-specific update function from
sock_raw and sock_ssl which now use the generic code.

The stream_sock_update_conn callback has also been more appropriately renamed
conn_notify_si() since it's meant to be called by lower layers to notify the
SI and possibly upper layers about incoming changes.

include/proto/stream_interface.h
src/connection.c
src/sock_raw.c
src/stream_interface.c

index 224ce8499b9a93c89f63f475cc3f4624ac8aa9a4..5e2d74f6b8a19fb11603421fc9eb913befbc7276 100644 (file)
@@ -35,7 +35,8 @@ int stream_int_check_timeouts(struct stream_interface *si);
 void stream_int_report_error(struct stream_interface *si);
 void stream_int_retnclose(struct stream_interface *si, const struct chunk *msg);
 int conn_si_send_proxy(struct connection *conn, unsigned int flag);
-void stream_sock_update_conn(struct connection *conn);
+void conn_notify_si(struct connection *conn);
+void stream_int_update_conn(struct stream_interface *si);
 int stream_int_shutr(struct stream_interface *si);
 int stream_int_shutw(struct stream_interface *si);
 
index 1f0d8a98c4654770019cd0c977513a76235fa426..1eada2d67044fe474f696f47cf0b0f80e15cee71 100644 (file)
@@ -82,7 +82,7 @@ int conn_fd_handler(int fd)
 
  leave:
        if (conn->flags & CO_FL_NOTIFY_SI)
-               stream_sock_update_conn(conn);
+               conn_notify_si(conn);
 
        /* Last check, verify if the connection just established */
        if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
index 6ce4c91181e1c105c7aef7614b1b634eec469496..6a3a2565cfa3de10a20358e559a2fede07f71231 100644 (file)
@@ -45,7 +45,6 @@
 /* main event functions used to move data between sockets and buffers */
 static void sock_raw_read(struct connection *conn);
 static void sock_raw_write(struct connection *conn);
-static void sock_raw_data_finish(struct stream_interface *si);
 static void sock_raw_read0(struct stream_interface *si);
 static void sock_raw_chk_rcv(struct stream_interface *si);
 static void sock_raw_chk_snd(struct stream_interface *si);
@@ -674,86 +673,6 @@ static void sock_raw_read0(struct stream_interface *si)
        return;
 }
 
-/*
- * Updates a connected sock_raw file descriptor status and timeouts
- * according to the buffers' flags. It should only be called once after the
- * buffer flags have settled down, and before they are cleared. It doesn't
- * harm to call it as often as desired (it just slightly hurts performance).
- */
-static void sock_raw_data_finish(struct stream_interface *si)
-{
-       struct buffer *ib = si->ib;
-       struct buffer *ob = si->ob;
-
-       DPRINTF(stderr,"[%u] %s: fd=%d owner=%p ib=%p, ob=%p, exp(r,w)=%u,%u ibf=%08x obf=%08x ibh=%d ibt=%d obh=%d obd=%d si=%d\n",
-               now_ms, __FUNCTION__,
-               si_fd(si), fdtab[si_fd(fd)].owner,
-               ib, ob,
-               ib->rex, ob->wex,
-               ib->flags, ob->flags,
-               ib->i, ib->o, ob->i, ob->o, si->state);
-
-       /* Check if we need to close the read side */
-       if (!(ib->flags & BF_SHUTR)) {
-               /* Read not closed, update FD status and timeout for reads */
-               if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
-                       /* stop reading */
-                       if (!(si->flags & SI_FL_WAIT_ROOM)) {
-                               if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
-                                       si->flags |= SI_FL_WAIT_ROOM;
-                               conn_data_stop_recv(&si->conn);
-                               ib->rex = TICK_ETERNITY;
-                       }
-               }
-               else {
-                       /* (re)start reading and update timeout. Note: we don't recompute the timeout
-                        * everytime we get here, otherwise it would risk never to expire. We only
-                        * update it if is was not yet set. The stream socket handler will already
-                        * have updated it if there has been a completed I/O.
-                        */
-                       si->flags &= ~SI_FL_WAIT_ROOM;
-                       conn_data_want_recv(&si->conn);
-                       if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
-                               ib->rex = tick_add_ifset(now_ms, ib->rto);
-               }
-       }
-
-       /* Check if we need to close the write side */
-       if (!(ob->flags & BF_SHUTW)) {
-               /* Write not closed, update FD status and timeout for writes */
-               if (ob->flags & BF_OUT_EMPTY) {
-                       /* stop writing */
-                       if (!(si->flags & SI_FL_WAIT_DATA)) {
-                               if ((ob->flags & (BF_FULL|BF_HIJACK|BF_SHUTW_NOW)) == 0)
-                                       si->flags |= SI_FL_WAIT_DATA;
-                               conn_data_stop_send(&si->conn);
-                               ob->wex = TICK_ETERNITY;
-                       }
-               }
-               else {
-                       /* (re)start writing and update timeout. Note: we don't recompute the timeout
-                        * everytime we get here, otherwise it would risk never to expire. We only
-                        * update it if is was not yet set. The stream socket handler will already
-                        * have updated it if there has been a completed I/O.
-                        */
-                       si->flags &= ~SI_FL_WAIT_DATA;
-                       conn_data_want_send(&si->conn);
-                       if (!tick_isset(ob->wex)) {
-                               ob->wex = tick_add_ifset(now_ms, ob->wto);
-                               if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
-                                       /* Note: depending on the protocol, we don't know if we're waiting
-                                        * for incoming data or not. So in order to prevent the socket from
-                                        * expiring read timeouts during writes, we refresh the read timeout,
-                                        * except if it was already infinite or if we have explicitly setup
-                                        * independent streams.
-                                        */
-                                       ib->rex = tick_add_ifset(now_ms, ib->rto);
-                               }
-                       }
-               }
-       }
-}
-
 /* This function is used for inter-stream-interface calls. It is called by the
  * consumer to inform the producer side that it may be interested in checking
  * for free space in the buffer. Note that it intentionally does not update
@@ -889,7 +808,7 @@ static void sock_raw_chk_snd(struct stream_interface *si)
 
 /* stream sock operations */
 struct sock_ops sock_raw = {
-       .update  = sock_raw_data_finish,
+       .update  = stream_int_update_conn,
        .shutr   = NULL,
        .shutw   = NULL,
        .chk_rcv = sock_raw_chk_rcv,
index 5f32933f8caecdc7994a27b239c00e06a6cc93f7..e3816e414f1ed6e6681e62838386eb0c5cecb1c1 100644 (file)
@@ -552,8 +552,12 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag)
        return 0;
 }
 
-/* function to be called on stream sockets after all I/O handlers */
-void stream_sock_update_conn(struct connection *conn)
+/* Callback to be used by connection I/O handlers upon completion. It differs from
+ * the function below in that it is designed to be called by lower layers after I/O
+ * events have been completed. It will also try to wake the associated task up if
+ * an important event requires special handling.
+ */
+void conn_notify_si(struct connection *conn)
 {
        int fd = conn->t.sock.fd;
        struct stream_interface *si = container_of(conn, struct stream_interface, conn);
@@ -651,6 +655,85 @@ void stream_sock_update_conn(struct connection *conn)
                si->ib->flags &= ~BF_READ_DONTWAIT;
 }
 
+/* Updates the timers and flags of a stream interface attached to a connection,
+ * depending on the buffers' flags. It should only be called once after the
+ * buffer flags have settled down, and before they are cleared. It doesn't
+ * harm to call it as often as desired (it just slightly hurts performance).
+ * It is only meant to be called by upper layers after buffer flags have been
+ * manipulated by analysers.
+ */
+void stream_int_update_conn(struct stream_interface *si)
+{
+       struct buffer *ib = si->ib;
+       struct buffer *ob = si->ob;
+
+       if (si->conn.flags & CO_FL_HANDSHAKE) {
+               /* a handshake is in progress */
+               si->flags &= ~SI_FL_WAIT_DATA;
+               return;
+       }
+
+       /* Check if we need to close the read side */
+       if (!(ib->flags & BF_SHUTR)) {
+               /* Read not closed, update FD status and timeout for reads */
+               if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
+                       /* stop reading */
+                       if (!(si->flags & SI_FL_WAIT_ROOM)) {
+                               if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
+                                       si->flags |= SI_FL_WAIT_ROOM;
+                               conn_data_stop_recv(&si->conn);
+                               ib->rex = TICK_ETERNITY;
+                       }
+               }
+               else {
+                       /* (re)start reading and update timeout. Note: we don't recompute the timeout
+                        * everytime we get here, otherwise it would risk never to expire. We only
+                        * update it if is was not yet set. The stream socket handler will already
+                        * have updated it if there has been a completed I/O.
+                        */
+                       si->flags &= ~SI_FL_WAIT_ROOM;
+                       conn_data_want_recv(&si->conn);
+                       if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
+                               ib->rex = tick_add_ifset(now_ms, ib->rto);
+               }
+       }
+
+       /* Check if we need to close the write side */
+       if (!(ob->flags & BF_SHUTW)) {
+               /* Write not closed, update FD status and timeout for writes */
+               if (ob->flags & BF_OUT_EMPTY) {
+                       /* stop writing */
+                       if (!(si->flags & SI_FL_WAIT_DATA)) {
+                               if ((ob->flags & (BF_FULL|BF_HIJACK|BF_SHUTW_NOW)) == 0)
+                                       si->flags |= SI_FL_WAIT_DATA;
+                               conn_data_stop_send(&si->conn);
+                               ob->wex = TICK_ETERNITY;
+                       }
+               }
+               else {
+                       /* (re)start writing and update timeout. Note: we don't recompute the timeout
+                        * everytime we get here, otherwise it would risk never to expire. We only
+                        * update it if is was not yet set. The stream socket handler will already
+                        * have updated it if there has been a completed I/O.
+                        */
+                       si->flags &= ~SI_FL_WAIT_DATA;
+                       conn_data_want_send(&si->conn);
+                       if (!tick_isset(ob->wex)) {
+                               ob->wex = tick_add_ifset(now_ms, ob->wto);
+                               if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
+                                       /* Note: depending on the protocol, we don't know if we're waiting
+                                        * for incoming data or not. So in order to prevent the socket from
+                                        * expiring read timeouts during writes, we refresh the read timeout,
+                                        * except if it was already infinite or if we have explicitly setup
+                                        * independent streams.
+                                        */
+                                       ib->rex = tick_add_ifset(now_ms, ib->rto);
+                               }
+                       }
+               }
+       }
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8