From 9bf9c14c12ea3f5f0cfd407d043d248d01167dd0 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 20 Aug 2012 15:38:41 +0200 Subject: [PATCH] MEDIUM: stream-interface: provide a generic stream_sock_read0() function This function is used by the data layer when a zero has been read over a connection. At the moment it only handles sockets and nothing else. Once the complete split is done between buffers and stream interfaces, it should become possible to work regardless on the connection type. --- include/proto/stream_interface.h | 1 + src/sock_raw.c | 52 +------------------------------- src/stream_interface.c | 49 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 8a4cf3a2ae..909d040961 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -42,6 +42,7 @@ 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); void si_conn_send_cb(struct connection *conn); +void stream_sock_read0(struct stream_interface *si); extern struct sock_ops stream_int_embedded; extern struct sock_ops stream_int_task; diff --git a/src/sock_raw.c b/src/sock_raw.c index 5b20f2ff59..991b46b9f3 100644 --- a/src/sock_raw.c +++ b/src/sock_raw.c @@ -44,7 +44,6 @@ /* main event functions used to move data between sockets and buffers */ static void sock_raw_read(struct connection *conn); -static void sock_raw_read0(struct stream_interface *si); #if defined(CONFIG_HAP_LINUX_SPLICE) @@ -436,7 +435,7 @@ static void sock_raw_read(struct connection *conn) b->flags |= BF_READ_NULL; if (b->flags & BF_AUTO_CLOSE) buffer_shutw_now(b); - sock_raw_read0(si); + stream_sock_read0(si); return; out_error: @@ -591,55 +590,6 @@ static int sock_raw_write_loop(struct connection *conn) } -/* - * 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 */ - conn_data_stop_recv(&si->conn); - 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; -} - /* stream sock operations */ struct sock_ops sock_raw = { .update = stream_int_update_conn, diff --git a/src/stream_interface.c b/src/stream_interface.c index 6be0354e8d..17f2447db1 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -898,6 +898,55 @@ void si_conn_send_cb(struct connection *conn) conn_data_stop_both(conn); } +/* + * This function propagates a null read received on a socket-based connection. + * It updates the stream interface. If the stream interface has SI_FL_NOHALF, + * the close is also forwarded to the write side as an abort. This function is + * still socket-specific as it handles a setsockopt() call to set the SO_LINGER + * state on the socket. + */ +void stream_sock_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 want to immediately forward this close to the write side */ + 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)); + } + /* force flag on ssl to keep session in cache */ + if (si->conn.data->shutw) + si->conn.data->shutw(&si->conn, 0); + goto do_close; + } + + /* otherwise that's just a normal read shutdown */ + conn_data_stop_recv(&si->conn); + 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; +} + /* * Local variables: -- 2.39.5