return 1;
full:
- sc_need_room(sc);
+ sc_need_room(sc, channel_htx_recv_max(sc_ic(appctx_sc(appctx)), htx) + 1);
return 0;
error:
/* unrecoverable error */
return 1;
full:
htx_reset(htx);
- sc_need_room(sc);
+ sc_need_room(sc, 0);
return 0;
}
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
*/
if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
- sc_need_room(sc);
+ sc_need_room(sc, sizeof(struct htx_blk) + 1);
goto out;
}
channel_add_input(res, 1);
ret = ci_putchk(sc_ic(se->sc), chunk);
if (ret == -1)
- sc_need_room(se->sc);
+ sc_need_room(se->sc, chunk->data);
return ret;
}
ret = ci_putblk(sc_ic(se->sc), blk, len);
if (ret == -1)
- sc_need_room(se->sc);
+ sc_need_room(se->sc, len);
return ret;
}
ret = ci_putstr(sc_ic(se->sc), str);
if (ret == -1)
- sc_need_room(se->sc);
+ sc_need_room(se->sc, strlen(str));
return ret;
}
ret = ci_putchr(sc_ic(se->sc), chr);
if (ret == -1)
- sc_need_room(se->sc);
+ sc_need_room(se->sc, 1);
return ret;
}
{
if (sc->flags & SC_FL_NEED_ROOM) {
sc->flags &= ~SC_FL_NEED_ROOM;
+ sc->room_needed = 0;
sc_ep_report_read_activity(sc);
}
}
* by lack of room. Since it indicates a willingness to deliver data to the
* buffer that will have to be retried. Usually the caller will also clear
* SE_FL_HAVE_NO_DATA to be called again as soon as SC_FL_NEED_ROOM is cleared.
+ *
+ * The caller is responsible to specified the amount of free space required to
+ * progress.
*/
-static inline void sc_need_room(struct stconn *sc)
+static inline void sc_need_room(struct stconn *sc, ssize_t room_needed)
{
sc->flags |= SC_FL_NEED_ROOM;
+ sc->room_needed = room_needed;
}
/* The stream endpoint indicates that it's ready to consume data from the
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
if (len) {
ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_UNUSED);
if (ret < len) {
- sc_need_room(sc);
+ sc_need_room(sc, len - ret);
goto out;
}
}
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
* would want to return some info right after parsing.
*/
if (buffer_almost_full(sc_ib(sc))) {
- sc_need_room(sc);
+ sc_need_room(sc, b_size(&res->buf) / 2);
break;
}
/* check if there is enough room to put message len and query id */
if (available_room < sizeof(slen) + sizeof(new_qid)) {
- sc_need_room(sc);
+ sc_need_room(sc, sizeof(slen) + sizeof(new_qid));
ret = 0;
break;
}
/* check if it remains available room on output chan */
if (unlikely(!available_room)) {
- sc_need_room(sc);
+ sc_need_room(sc, 1);
ret = 0;
break;
}
if (ds->tx_msg_offset) {
/* msg was not fully processed, we must be awake to drain pending data */
-
- sc_need_room(sc);
+ sc_need_room(sc, 0);
ret = 0;
break;
}
memcpy(buf, (char *)&netint, 4);
ret = applet_putblk(appctx, buf, framesz+4);
if (ret <= 0) {
- if ((ret == -3 && b_is_null(&sc_ic(sc)->buf)) || ret == -1) {
+ if (ret == -3 && b_is_null(&sc_ic(sc)->buf)) {
/* WT: is this still needed for the case ret==-3 ? */
- sc_need_room(sc);
+ sc_need_room(sc, 0);
return 1; /* retry */
}
SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_IO;
* applet, and returns a yield.
*/
if (l < len) {
- sc_need_room(sc);
+ sc_need_room(sc, channel_recv_max(chn) + 1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
}
if (l < len) {
snd_yield:
htx_to_buf(htx, &res->buf);
- sc_need_room(sc);
+ sc_need_room(sc, channel_recv_max(res) + 1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
}
struct channel *res = sc_ic(sc);
if (co_data(res)) {
- sc_need_room(sc);
+ sc_need_room(sc, -1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
}
return MAY_LJMP(hlua_applet_http_send_response(L));
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
*/
if (htx_is_empty(res_htx) && (strm->txn->rsp.flags & (HTTP_MSGF_XFER_LEN|HTTP_MSGF_CNT_LEN)) == HTTP_MSGF_XFER_LEN) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
- sc_need_room(sc);
+ sc_need_room(sc, sizeof(struct htx_blk)+1);
goto out;
}
channel_add_input(res, 1);
case HLUA_E_AGAIN:
/* We want write. */
if (HLUA_IS_WAKERESWR(hlua))
- sc_need_room(sc);
+ sc_need_room(sc, -1);
/* Set the timeout. */
if (hlua->wake_time != TICK_ETERNITY)
task_schedule(hlua->task, hlua->wake_time);
* it's the first call, we can freely copy the
* request from the httpclient buffer */
ret = b_xfer(&req->buf, &hc->req.buf, b_data(&hc->req.buf));
- if (!ret)
- goto full;
+ if (!ret) {
+ sc_need_room(sc, 0);
+ goto out;
+ }
if (!b_data(&hc->req.buf))
b_free(&hc->req.buf);
htx = htx_from_buf(&req->buf);
- if (!htx)
- goto full;
+ if (!htx) {
+ sc_need_room(sc, 0);
+ goto out;
+ }
channel_add_input(req, htx->data);
sc_will_read(sc);
goto out;
-full:
- /* There was not enough room in the response channel */
- sc_need_room(sc);
- goto out;
-
error:
se_fl_set(appctx->sedesc, SE_FL_ERROR);
goto out;
/* pretend we're full so that we get back ASAP */
struct stconn *sc = appctx_sc(appctx);
- sc_need_room(sc);
+ sc_need_room(sc, 0);
ret = -1;
break;
}
/* pretend we're full so that we get back ASAP */
struct stconn *sc = appctx_sc(appctx);
- sc_need_room(sc);
+ sc_need_room(sc, 0);
return -1;
}
}
/* Check if the input buffer is available. */
if (sc_ib(sc)->size == 0) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
newline = ctx->bol;
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, ctx->ptr);
- if (newptr == ctx->ptr)
+ if (newptr == ctx->ptr) {
+ sc_need_room(sc, 0);
goto cant_send_unlock;
+ }
if (applet_putchk(appctx, &trash) == -1)
goto cant_send_unlock;
cant_send_unlock:
HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &ctx->px->lock);
cant_send:
- sc_need_room(sc);
return 0;
}
list_for_each_entry_from(ns, &resolver->nameservers, list) {
ctx->obj2 = ns;
- if (buffer_almost_full(&rep->buf))
+ if (buffer_almost_full(&rep->buf)) {
+ sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
+ }
if (!stats_dump_resolv_to_buffer(sc, ns,
stats, stats_count,
/* dump proxies */
while (ctx->obj1) {
if (htx) {
- if (htx_almost_full(htx))
+ if (htx_almost_full(htx)) {
+ sc_need_room(sc, htx->size / 2);
goto full;
+ }
}
else {
- if (buffer_almost_full(&rep->buf))
+ if (buffer_almost_full(&rep->buf)) {
+ sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
+ }
}
px = ctx->obj1;
return 1;
full:
- sc_need_room(sc);
return 0;
}
full:
htx_reset(htx);
- sc_need_room(sc);
+ sc_need_room(sc, 0);
return 0;
}
full:
htx_reset(htx);
- sc_need_room(sc);
+ sc_need_room(sc, 0);
return 0;
}
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto out;
}
*/
if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
- sc_need_room(sc);
+ sc_need_room(sc, sizeof(struct htx_blk) + 1);
goto out;
}
channel_add_input(res, 1);
if (ic->pipe) {
/* stop reading */
- sc_need_room(sc);
+ sc_need_room(sc, -1);
}
else {
/* (re)start reading */
/* the pipe is full or we have read enough data that it
* could soon be full. Let's stop before needing to poll.
*/
- sc_need_room(sc);
+ sc_need_room(sc, 0);
goto done_recv;
}
*/
BUG_ON(c_empty(ic));
- sc_need_room(sc);
+ sc_need_room(sc, channel_recv_max(ic) + 1);
/* Add READ_PARTIAL because some data are pending but
* cannot be xferred to the channel
*/
* here to proceed.
*/
if (flags & CO_RFL_BUF_FLUSH)
- sc_need_room(sc);
+ sc_need_room(sc, -1);
break;
}