diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 8a4cf3a2a..909d04096 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 5b20f2ff5..991b46b9f 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 6be0354e8..17f2447db 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: