int timeout; /* idle timeout duration in ticks */
int shut_timeout; /* idle timeout duration in ticks after GOAWAY was sent */
+ unsigned int nb_streams; /* number of streams in the tree */
+ /* 32 bit hole here */
struct task *task; /* timeout management task */
struct eb_root streams_by_id; /* all active streams by their ID */
struct list send_list; /* list of blocked streams requesting to send */
h2c->flags = H2_CF_NONE;
h2c->rcvd_c = 0;
h2c->rcvd_s = 0;
+ h2c->nb_streams = 0;
h2c->dbuf = &buf_empty;
h2c->dsi = -1;
LIST_INIT(&h2s->list);
eb32_insert(&h2c->streams_by_id, &h2s->by_id);
+ h2c->nb_streams++;
+ if (h2c->nb_streams > h2_settings_max_concurrent_streams)
+ goto out_close;
cs = cs_new(h2c->conn);
if (!cs)
out_free_cs:
cs_free(cs);
out_close:
+ h2c->nb_streams--;
eb32_delete(&h2s->by_id);
pool_free(pool_head_h2s, h2s);
h2s = NULL;
if (!h2s->cs) {
/* this stream was already orphaned */
+ h2c->nb_streams--;
eb32_delete(&h2s->by_id);
pool_free(pool_head_h2s, h2s);
continue;
h2s->cs->flags &= ~CS_FL_DATA_WR_ENA;
else {
/* just sent the last frame for this orphaned stream */
+ h2c->nb_streams--;
eb32_delete(&h2s->by_id);
pool_free(pool_head_h2s, h2s);
}
h2s->cs->flags &= ~CS_FL_DATA_WR_ENA;
else {
/* just sent the last frame for this orphaned stream */
+ h2c->nb_streams--;
eb32_delete(&h2s->by_id);
pool_free(pool_head_h2s, h2s);
}
if (h2s->by_id.node.leaf_p) {
/* h2s still attached to the h2c */
+ h2c->nb_streams--;
eb32_delete(&h2s->by_id);
/* We don't want to close right now unless we're removing the