]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: sock_raw: introduce a read0 callback that is different from shutr
authorWilly Tarreau <wtarreau@exceliance.fr>
Mon, 6 Aug 2012 15:00:18 +0000 (17:00 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 2 Sep 2012 19:53:10 +0000 (21:53 +0200)
This one is supposed to be called by the lower layer upon receiving a shutr
notification, which is different from the call performed by the upper layer.
Specifically, this function will ultimately not call EV_FD_* but will just
manipulate event flags instead. The function also does not call shutw anymore
and instead performs the necessary work.

Splitting it into si-specific part and data-specific parts will not be easy.

src/sock_raw.c

index 39a962e01ec21c3bf1d7571c1fb2f2077c58637d..08e0b3198b399f2adf978491e3ff3c545ac3cce0 100644 (file)
@@ -48,6 +48,7 @@ static int sock_raw_write(struct connection *conn);
 static void sock_raw_data_finish(struct stream_interface *si);
 static void sock_raw_shutr(struct stream_interface *si);
 static void sock_raw_shutw(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);
 
@@ -456,7 +457,7 @@ static int sock_raw_read(struct connection *conn)
        b->flags |= BF_READ_NULL;
        if (b->flags & BF_AUTO_CLOSE)
                buffer_shutw_now(b);
-       sock_raw_shutr(si);
+       sock_raw_read0(si);
        goto out_wakeup;
 
  out_error:
@@ -766,6 +767,55 @@ static void sock_raw_shutr(struct stream_interface *si)
        return;
 }
 
+/*
+ * This function propagates a null read received on a connection. It updates
+ * the stream interface. If the stream interface has SI_FL_NOHALF, we also
+ * forward the close to the write side.
+ */
+static void sock_raw_read0(struct stream_interface *si)
+{
+       si->ib->flags &= ~BF_SHUTR_NOW;
+       if (si->ib->flags & BF_SHUTR)
+               return;
+       si->ib->flags |= BF_SHUTR;
+       si->ib->rex = TICK_ETERNITY;
+       si->flags &= ~SI_FL_WAIT_ROOM;
+
+       if (si->state != SI_ST_EST && si->state != SI_ST_CON)
+               return;
+
+       if (si->ob->flags & BF_SHUTW)
+               goto do_close;
+
+       if (si->flags & SI_FL_NOHALF) {
+               /* we have to shut before closing, otherwise some short messages
+                * may never leave the system, especially when there are remaining
+                * unread data in the socket input buffer, or when nolinger is set.
+                * However, if SI_FL_NOLINGER is explicitly set, we know there is
+                * no risk so we close both sides immediately.
+                */
+               if (si->flags & SI_FL_NOLINGER) {
+                       si->flags &= ~SI_FL_NOLINGER;
+                       setsockopt(si_fd(si), SOL_SOCKET, SO_LINGER,
+                                  (struct linger *) &nolinger, sizeof(struct linger));
+               }
+               goto do_close;
+       }
+
+       /* otherwise that's just a normal read shutdown */
+       EV_FD_CLR(si_fd(si), DIR_RD);
+       return;
+
+ do_close:
+       conn_data_close(&si->conn);
+       fd_delete(si_fd(si));
+       si->state = SI_ST_DIS;
+       si->exp = TICK_ETERNITY;
+       if (si->release)
+               si->release(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