void conn_fd_handler(int fd);
/* conn_stream functions */
-size_t __cs_recv(struct conn_stream *cs, struct buffer *buf, size_t count, int flags);
size_t __cs_send(struct conn_stream *cs, struct buffer *buf, size_t count, int flags);
/* receive a PROXY protocol header over a connection */
LIST_INIT(&cs->wait_list.list);
LIST_INIT(&cs->send_wait_list);
cs->conn = conn;
- cs->rxbuf = BUF_NULL;
cs->txbuf = BUF_NULL;
}
return conn;
}
-/* Releases the conn_stream's rx buf if it exists. The buffer is automatically
- * replaced with a pointer to the empty buffer.
- */
-static inline void cs_drop_rxbuf(struct conn_stream *cs)
-{
- if (b_size(&cs->rxbuf)) {
- b_free(&cs->rxbuf);
- offer_buffers(NULL, tasks_run_queue);
- }
-}
-
/* Releases the conn_stream's tx buf if it exists. The buffer is automatically
* replaced with a pointer to the empty buffer.
*/
if (cs->wait_list.task)
tasklet_free(cs->wait_list.task);
- cs_drop_rxbuf(cs);
cs_drop_txbuf(cs);
pool_free(pool_head_connstream, cs);
}
int mws; /* mux window size for this stream */
enum h2_err errcode; /* H2 err code (H2_ERR_*) */
enum h2_ss st;
+ struct buffer rxbuf; /* receive buffer, always valid (buf_empty or real buffer) */
};
/* descriptor for an h2 frame header */
if ((h2c->flags & H2_CF_DEM_SALLOC) &&
(h2s = h2c_st_by_id(h2c, h2c->dsi)) && h2s->cs &&
- b_alloc_margin(&h2s->cs->rxbuf, 0)) {
+ b_alloc_margin(&h2s->rxbuf, 0)) {
h2c->flags &= ~H2_CF_DEM_SALLOC;
if (h2_recv_allowed(h2c))
conn_xprt_want_recv(h2c->conn);
LIST_DEL(&h2s->list);
LIST_INIT(&h2s->list);
eb32_delete(&h2s->by_id);
+ if (b_size(&h2s->rxbuf)) {
+ b_free(&h2s->rxbuf);
+ offer_buffers(NULL, tasks_run_queue);
+ }
pool_free(pool_head_h2s, h2s);
}
h2s->flags = H2_SF_NONE;
h2s->errcode = H2_ERR_NO_ERROR;
h2s->st = H2_SS_IDLE;
+ h2s->rxbuf = BUF_NULL;
h1m_init(&h2s->req);
h1m_init(&h2s->res);
h2s->by_id.key = h2s->id = id;
/* Only H2_CS_FRAME_P and H2_CS_FRAME_A here */
tmp_h2s = h2c_st_by_id(h2c, h2c->dsi);
- if (tmp_h2s != h2s && h2s && h2s->cs && b_data(&h2s->cs->rxbuf)) {
+ if (tmp_h2s != h2s && h2s && h2s->cs && b_data(&h2s->rxbuf)) {
/* we may have to signal the upper layers */
h2s->cs->flags |= CS_FL_RCV_MORE;
if (h2s->cs->data_cb->wake(h2s->cs) < 0) {
fail:
/* we can go here on missing data, blocked response or error */
- if (h2s && h2s->cs && b_data(&h2s->cs->rxbuf)) {
+ if (h2s && h2s->cs && b_data(&h2s->rxbuf)) {
/* we may have to signal the upper layers */
h2s->cs->flags |= CS_FL_RCV_MORE;
if (h2s->cs->data_cb->wake(h2s->cs) < 0) {
goto fail;
}
- csbuf = h2_get_buf(h2c, &h2s->cs->rxbuf);
+ csbuf = h2_get_buf(h2c, &h2s->rxbuf);
if (!csbuf) {
h2c->flags |= H2_CF_DEM_SALLOC;
goto fail;
h2c->dff &= ~H2_F_DATA_PADDED;
}
- csbuf = h2_get_buf(h2c, &h2s->cs->rxbuf);
+ csbuf = h2_get_buf(h2c, &h2s->rxbuf);
if (!csbuf) {
h2c->flags |= H2_CF_DEM_SALLOC;
goto fail;
/* Called from the upper layer, to receive data */
static size_t h2_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int flags)
{
+ struct h2s *h2s = cs->ctx;
size_t ret = 0;
/* transfer possibly pending data to the upper layer */
- ret = b_xfer(buf, &cs->rxbuf, count);
+ ret = b_xfer(buf, &h2s->rxbuf, count);
- if (b_data(&cs->rxbuf))
+ if (b_data(&h2s->rxbuf))
cs->flags |= CS_FL_RCV_MORE;
else {
cs->flags &= ~CS_FL_RCV_MORE;
if (cs->flags & CS_FL_REOS)
cs->flags |= CS_FL_EOS;
- cs_drop_rxbuf(cs);
+ if (b_size(&h2s->rxbuf)) {
+ b_free(&h2s->rxbuf);
+ offer_buffers(NULL, tasks_run_queue);
+ }
}
return ret;