]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stream-interface: provide a generic stream_int_chk_snd_conn() function
authorWilly Tarreau <wtarreau@exceliance.fr>
Mon, 20 Aug 2012 13:01:10 +0000 (15:01 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 2 Sep 2012 19:54:55 +0000 (21:54 +0200)
This one can be used by both sock_raw and sock_ssl instead of each having their own.

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

index 24072a61207526baf306271c09c3a116df7d18f4..844d9258a8d78130780f7af1b78f52270eec1166 100644 (file)
@@ -40,6 +40,7 @@ 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);
 void stream_int_chk_rcv_conn(struct stream_interface *si);
+void stream_int_chk_snd_conn(struct stream_interface *si);
 
 extern struct sock_ops stream_int_embedded;
 extern struct sock_ops stream_int_task;
index f5aadcd18bed089e51716df469b0b74aec1b0067..e21177cd17b412e648cccef6eca46b48377a99a6 100644 (file)
@@ -46,7 +46,6 @@
 static void sock_raw_read(struct connection *conn);
 static void sock_raw_write(struct connection *conn);
 static void sock_raw_read0(struct stream_interface *si);
-static void sock_raw_chk_snd(struct stream_interface *si);
 
 
 #if defined(CONFIG_HAP_LINUX_SPLICE)
@@ -674,112 +673,13 @@ static void sock_raw_read0(struct stream_interface *si)
        return;
 }
 
-/* This function is used for inter-stream-interface calls. It is called by the
- * producer to inform the consumer side that it may be interested in checking
- * for data in the buffer. Note that it intentionally does not update timeouts,
- * so that we can still check them later at wake-up.
- */
-static void sock_raw_chk_snd(struct stream_interface *si)
-{
-       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(si)].owner,
-               si->ib, ob,
-               si->ib->rex, ob->wex,
-               si->ib->flags, ob->flags,
-               si->ib->i, si->ib->o, ob->i, ob->o, si->state);
-
-       if (unlikely(si->state != SI_ST_EST || (ob->flags & BF_SHUTW)))
-               return;
-
-       if (unlikely(ob->flags & BF_OUT_EMPTY))  /* called with nothing to send ! */
-               return;
-
-       if (!ob->pipe &&                          /* spliced data wants to be forwarded ASAP */
-           (!(si->flags & SI_FL_WAIT_DATA) ||    /* not waiting for data */
-            (fdtab[si_fd(si)].ev & FD_POLL_OUT)))   /* we'll be called anyway */
-               return;
-
-       if (conn_data_snd_buf(&si->conn) < 0) {
-               /* Write error on the file descriptor. We mark the FD as STERROR so
-                * that we don't use it anymore and we notify the task.
-                */
-               si->conn.flags |= CO_FL_ERROR;
-               fdtab[si_fd(si)].ev &= ~FD_POLL_STICKY;
-               conn_data_stop_both(&si->conn);
-               si->flags |= SI_FL_ERR;
-               goto out_wakeup;
-       }
-
-       /* OK, so now we know that some data might have been sent, and that we may
-        * have to poll first. We have to do that too if the buffer is not empty.
-        */
-       if (ob->flags & BF_OUT_EMPTY) {
-               /* the connection is established but we can't write. Either the
-                * buffer is empty, or we just refrain from sending because the
-                * ->o limit was reached. Maybe we just wrote the last
-                * chunk and need to close.
-                */
-               if (((ob->flags & (BF_SHUTW|BF_HIJACK|BF_AUTO_CLOSE|BF_SHUTW_NOW)) ==
-                    (BF_AUTO_CLOSE|BF_SHUTW_NOW)) &&
-                   (si->state == SI_ST_EST)) {
-                       si_shutw(si);
-                       goto out_wakeup;
-               }
-
-               if ((ob->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_FULL|BF_HIJACK)) == 0)
-                       si->flags |= SI_FL_WAIT_DATA;
-               ob->wex = TICK_ETERNITY;
-       }
-       else {
-               /* Otherwise there are remaining data to be sent in the buffer,
-                * which means we have to poll before doing so.
-                */
-               conn_data_want_send(&si->conn);
-               si->flags &= ~SI_FL_WAIT_DATA;
-               if (!tick_isset(ob->wex))
-                       ob->wex = tick_add_ifset(now_ms, ob->wto);
-       }
-
-       if (likely(ob->flags & BF_WRITE_ACTIVITY)) {
-               /* update timeout if we have written something */
-               if ((ob->flags & (BF_OUT_EMPTY|BF_SHUTW|BF_WRITE_PARTIAL)) == BF_WRITE_PARTIAL)
-                       ob->wex = tick_add_ifset(now_ms, ob->wto);
-
-               if (tick_isset(si->ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
-                       /* Note: to prevent the client from expiring read timeouts
-                        * during writes, we refresh it. We only do this if the
-                        * interface is not configured for "independent streams",
-                        * because for some applications it's better not to do this,
-                        * for instance when continuously exchanging small amounts
-                        * of data which can full the socket buffers long before a
-                        * write timeout is detected.
-                        */
-                       si->ib->rex = tick_add_ifset(now_ms, si->ib->rto);
-               }
-       }
-
-       /* in case of special condition (error, shutdown, end of write...), we
-        * have to notify the task.
-        */
-       if (likely((ob->flags & (BF_WRITE_NULL|BF_WRITE_ERROR|BF_SHUTW)) ||
-                  ((ob->flags & BF_OUT_EMPTY) && !ob->to_forward) ||
-                  si->state != SI_ST_EST)) {
-       out_wakeup:
-               if (!(si->flags & SI_FL_DONT_WAKE) && si->owner)
-                       task_wakeup(si->owner, TASK_WOKEN_IO);
-       }
-}
-
 /* stream sock operations */
 struct sock_ops sock_raw = {
        .update  = stream_int_update_conn,
        .shutr   = NULL,
        .shutw   = NULL,
        .chk_rcv = stream_int_chk_rcv_conn,
-       .chk_snd = sock_raw_chk_snd,
+       .chk_snd = stream_int_chk_snd_conn,
        .read    = sock_raw_read,
        .write   = sock_raw_write,
        .snd_buf = sock_raw_write_loop,
index 6a46df40a46ea7891292cc861f07005e70269591..06a5d4e682b065ace8efcb1f490687d826360718 100644 (file)
@@ -766,6 +766,105 @@ void stream_int_chk_rcv_conn(struct stream_interface *si)
 }
 
 
+/* This function is used for inter-stream-interface calls. It is called by the
+ * producer to inform the consumer side that it may be interested in checking
+ * for data in the buffer. Note that it intentionally does not update timeouts,
+ * so that we can still check them later at wake-up.
+ */
+void stream_int_chk_snd_conn(struct stream_interface *si)
+{
+       struct buffer *ob = si->ob;
+
+       if (unlikely(si->state != SI_ST_EST || (ob->flags & BF_SHUTW)))
+               return;
+
+       /* handshake running on producer */
+       if (si->conn.flags & CO_FL_HANDSHAKE) {
+               /* a handshake is in progress */
+               si->flags &= ~SI_FL_WAIT_DATA;
+               return;
+       }
+
+       if (unlikely((ob->flags & BF_OUT_EMPTY)))  /* called with nothing to send ! */
+               return;
+
+       if (!ob->pipe &&                          /* spliced data wants to be forwarded ASAP */
+           (!(si->flags & SI_FL_WAIT_DATA) ||    /* not waiting for data */
+            (fdtab[si_fd(si)].ev & FD_POLL_OUT)))   /* we'll be called anyway */
+               return;
+
+       if (conn_data_snd_buf(&si->conn) < 0) {
+               /* Write error on the file descriptor. We mark the FD as STERROR so
+                * that we don't use it anymore and we notify the task.
+                */
+               fdtab[si_fd(si)].ev &= ~FD_POLL_STICKY;
+               conn_data_stop_both(&si->conn);
+               si->flags |= SI_FL_ERR;
+               si->conn.flags |= CO_FL_ERROR;
+               goto out_wakeup;
+       }
+
+       /* OK, so now we know that some data might have been sent, and that we may
+        * have to poll first. We have to do that too if the buffer is not empty.
+        */
+       if (ob->flags & BF_OUT_EMPTY) {
+               /* the connection is established but we can't write. Either the
+                * buffer is empty, or we just refrain from sending because the
+                * ->o limit was reached. Maybe we just wrote the last
+                * chunk and need to close.
+                */
+               if (((ob->flags & (BF_SHUTW|BF_HIJACK|BF_AUTO_CLOSE|BF_SHUTW_NOW)) ==
+                    (BF_AUTO_CLOSE|BF_SHUTW_NOW)) &&
+                   (si->state == SI_ST_EST)) {
+                       si_shutw(si);
+                       goto out_wakeup;
+               }
+
+               if ((ob->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_FULL|BF_HIJACK)) == 0)
+                       si->flags |= SI_FL_WAIT_DATA;
+               ob->wex = TICK_ETERNITY;
+       }
+       else {
+               /* Otherwise there are remaining data to be sent in the buffer,
+                * which means we have to poll before doing so.
+                */
+               conn_data_want_send(&si->conn);
+               si->flags &= ~SI_FL_WAIT_DATA;
+               if (!tick_isset(ob->wex))
+                       ob->wex = tick_add_ifset(now_ms, ob->wto);
+       }
+
+       if (likely(ob->flags & BF_WRITE_ACTIVITY)) {
+               /* update timeout if we have written something */
+               if ((ob->flags & (BF_OUT_EMPTY|BF_SHUTW|BF_WRITE_PARTIAL)) == BF_WRITE_PARTIAL)
+                       ob->wex = tick_add_ifset(now_ms, ob->wto);
+
+               if (tick_isset(si->ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
+                       /* Note: to prevent the client from expiring read timeouts
+                        * during writes, we refresh it. We only do this if the
+                        * interface is not configured for "independent streams",
+                        * because for some applications it's better not to do this,
+                        * for instance when continuously exchanging small amounts
+                        * of data which can full the socket buffers long before a
+                        * write timeout is detected.
+                        */
+                       si->ib->rex = tick_add_ifset(now_ms, si->ib->rto);
+               }
+       }
+
+       /* in case of special condition (error, shutdown, end of write...), we
+        * have to notify the task.
+        */
+       if (likely((ob->flags & (BF_WRITE_NULL|BF_WRITE_ERROR|BF_SHUTW)) ||
+                  ((ob->flags & BF_OUT_EMPTY) && !ob->to_forward) ||
+                  si->state != SI_ST_EST)) {
+       out_wakeup:
+               if (!(si->flags & SI_FL_DONT_WAKE) && si->owner)
+                       task_wakeup(si->owner, TASK_WOKEN_IO);
+       }
+}
+
+
 /*
  * Local variables:
  *  c-indent-level: 8