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);
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:
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