From: Willy Tarreau Date: Mon, 6 Aug 2012 15:00:18 +0000 (+0200) Subject: MEDIUM: sock_raw: introduce a read0 callback that is different from shutr X-Git-Tag: v1.5-dev12~98 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d8903fae0fcd52357af312fa6b06848616693f0;p=thirdparty%2Fhaproxy.git MEDIUM: sock_raw: introduce a read0 callback that is different from shutr 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. --- diff --git a/src/sock_raw.c b/src/sock_raw.c index 39a962e01e..08e0b3198b 100644 --- a/src/sock_raw.c +++ b/src/sock_raw.c @@ -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