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)
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);
+ }
}
}
}
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);
+ }
}
}
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