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.
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index 8a4cf3a..909d040 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.h
@@ -42,6 +42,7 @@
 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 5b20f2f..991b46b 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 @@
 	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 @@
 }
 
 
-/*
- * 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 6be0354..17f2447 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -898,6 +898,55 @@
 	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: