BUG/MEDIUM: h2: support orphaned streams

When a stream_interface performs a shutw() then a shutr(), the stream
is marked closed. Then cs_destroy() calls h2_detach() and it cannot
fail since we're on the leaving path of the caller. The problem is that
in order to close streams we usually have to send either an emty DATA
frame with the ES flag set or an RST_STREAM frame, and the mux buffer
might already be full, forcing the stream to be queued. The forced
removal of this stream causes this last message to silently disappear,
and the client to wait forever for a response.

This commit ensures we can detach the conn_stream from the h2 stream
if the stream is blocked, effectively making the h2 stream an orphan,
ensures that the mux can deal with orphaned streams after processing
them, and that the demux can kill them upon receipt of GOAWAY.
diff --git a/src/mux_h2.c b/src/mux_h2.c
index a5cd89b..d06a234 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -984,14 +984,21 @@
 		if (h2s->id <= last)
 			break;
 		node = eb32_next(node);
-		if (h2s->cs) {
-			h2s->cs->flags |= flags;
-			/* recv is used to force to detect CS_FL_EOS that wake()
-			 * doesn't handle in the stream int code.
-			 */
-			h2s->cs->data_cb->recv(h2s->cs);
-			h2s->cs->data_cb->wake(h2s->cs);
+
+		if (!h2s->cs) {
+			/* this stream was already orphaned */
+			eb32_delete(&h2s->by_id);
+			pool_free2(pool2_h2s, h2s);
+			continue;
 		}
+
+		h2s->cs->flags |= flags;
+		/* recv is used to force to detect CS_FL_EOS that wake()
+		 * doesn't handle in the stream int code.
+		 */
+		h2s->cs->data_cb->recv(h2s->cs);
+		h2s->cs->data_cb->wake(h2s->cs);
+
 		if (flags & CS_FL_ERROR && h2s->st < H2_SS_ERROR)
 			h2s->st = H2_SS_ERROR;
 		else if (flags & CS_FL_EOS && h2s->st == H2_SS_OPEN)
@@ -1884,6 +1891,11 @@
 				LIST_INIT(&h2s->list);
 				if (h2s->cs)
 					h2s->cs->flags &= ~CS_FL_DATA_WR_ENA;
+				else {
+					/* just sent the last frame for this orphaned stream */
+					eb32_delete(&h2s->by_id);
+					pool_free2(pool2_h2s, h2s);
+				}
 			}
 		}
 	}
@@ -1921,6 +1933,11 @@
 			LIST_INIT(&h2s->list);
 			if (h2s->cs)
 				h2s->cs->flags &= ~CS_FL_DATA_WR_ENA;
+			else {
+				/* just sent the last frame for this orphaned stream */
+				eb32_delete(&h2s->by_id);
+				pool_free2(pool2_h2s, h2s);
+			}
 		}
 	}
 
@@ -2237,6 +2254,12 @@
 	h2c = h2s->h2c;
 	h2s->cs = NULL;
 
+	/* this stream may be blocked waiting for some data to leave (possibly
+	 * an ES or RST frame), so orphan it in this case.
+	 */
+	if (h2s->flags & (H2_SF_BLK_MBUSY | H2_SF_BLK_MROOM | H2_SF_BLK_MFCTL))
+		return;
+
 	if ((h2c->flags & H2_CF_DEM_BLOCK_ANY && h2s->id == h2c->dsi) ||
 	    (h2c->flags & H2_CF_MUX_BLOCK_ANY && h2s->id == h2c->msi)) {
 		/* unblock the connection if it was blocked on this