MINOR: htx: make htx_add_data() return the transmitted byte count

In order to later allow htx_add_data() to transmit partial blocks and
avoid defragmenting the buffer, we'll need to return the number of bytes
consumed. This first modification makes the function do this and its
callers take this into account. At the moment the function still works
atomically so it returns either the block size or zero. However all
call places have been adapted to consider any value between zero and
the block size.
This commit is contained in:
Willy Tarreau 2019-05-28 10:30:11 +02:00
parent d4908fa465
commit 0a7ef02074
9 changed files with 57 additions and 23 deletions

View File

@ -186,7 +186,7 @@ struct htx_blk *htx_add_blk_type_size(struct htx *htx, enum htx_blk_type type, u
struct htx_blk *htx_add_all_headers(struct htx *htx, const struct http_hdr *hdrs);
struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type);
struct htx_blk *htx_add_data_atonce(struct htx *htx, const struct ist data);
struct htx_blk *htx_add_data(struct htx *htx, const struct ist data);
size_t htx_add_data(struct htx *htx, const struct ist data);
struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist tlr);
struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, const struct ist data);

View File

@ -957,8 +957,7 @@ static size_t htx_cache_dump_data(struct appctx *appctx, struct htx *htx,
sz = MIN(len, shctx->block_size - offset);
data = ist2((const char *)shblk->data + offset, sz);
if (type == HTX_BLK_DATA) {
if (!htx_add_data(htx, data))
break;
sz = htx_add_data(htx, data);
}
else { /* HTX_BLK_TLR */
if (!htx_add_trailer(htx, data))
@ -968,7 +967,7 @@ static size_t htx_cache_dump_data(struct appctx *appctx, struct htx *htx,
offset += sz;
len -= sz;
total += sz;
if (!len)
if (!len || sz < data.len)
break;
offset = 0;
}

View File

@ -4568,8 +4568,7 @@ __LJMP static int hlua_applet_htx_send_yield(lua_State *L, int status, lua_KCont
max = len - l;
/* Copy data. */
if (!htx_add_data(htx, ist2(data + l, max)))
goto snd_yield;
max = htx_add_data(htx, ist2(data + l, max));
channel_add_input(res, max);
/* update counters. */

View File

@ -657,9 +657,11 @@ static struct htx *http_str_to_htx(struct buffer *buf, struct ist raw)
goto error;
sl->info.res.status = h1sl.st.status;
if (raw.len > ret) {
if (!htx_add_data(htx, ist2(raw.ptr + ret, raw.len - ret)))
while (raw.len > ret) {
int sent = htx_add_data(htx, ist2(raw.ptr + ret, raw.len - ret));
if (!sent)
goto error;
ret += sent;
}
if (!htx_add_endof(htx, HTX_BLK_EOM))
goto error;

View File

@ -758,11 +758,18 @@ struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type)
/* Adds an HTX block of type DATA in <htx>. It first tries to append data if
* possible. It returns the new block on success. Otherwise, it returns NULL.
* possible. It returns the number of bytes consumed from <data>, which may be
* zero if nothing could be copied.
*/
struct htx_blk *htx_add_data(struct htx *htx, const struct ist data)
size_t htx_add_data(struct htx *htx, const struct ist data)
{
return htx_add_data_atonce(htx, data);
struct htx_blk *blk;
blk = htx_add_data_atonce(htx, data);
if (blk)
return data.len;
else
return 0;
}
/* Adds an HTX block of type TLR in <htx>. It returns the new block on

View File

@ -1143,6 +1143,8 @@ static size_t h1_process_data(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
* => we can swap the buffers and place an htx header into
* the target buffer instead
*/
int32_t try = ret;
if (unlikely(htx_is_empty(htx) && ret == b_data(buf) &&
!*ofs && b_head_ofs(buf) == sizeof(struct htx))) {
void *raw_area = buf->area;
@ -1162,12 +1164,15 @@ static size_t h1_process_data(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
* empty pre-initialized HTX header
*/
}
else if (!htx_add_data(htx, ist2(b_peek(buf, *ofs), ret)))
goto end;
else {
ret = htx_add_data(htx, ist2(b_peek(buf, *ofs), try));
}
h1m->curr_len -= ret;
max -= sizeof(struct htx_blk) + ret;
*ofs += ret;
total += ret;
if (ret < try)
goto end;
}
if (!h1m->curr_len) {
@ -1220,12 +1225,15 @@ static size_t h1_process_data(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
ret = b_contig_data(buf, *ofs);
if (ret) {
if (!htx_add_data(htx, ist2(b_peek(buf, *ofs), ret)))
goto end;
int32_t try = ret;
ret = htx_add_data(htx, ist2(b_peek(buf, *ofs), try));
h1m->curr_len -= ret;
max -= sizeof(struct htx_blk) + ret;
*ofs += ret;
total += ret;
if (ret < try)
goto end;
}
if (!h1m->curr_len) {
h1m->state = H1_MSG_CHUNK_CRLF;
@ -1291,11 +1299,14 @@ static size_t h1_process_data(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
ret = b_contig_data(buf, *ofs);
if (ret) {
if (!htx_add_data(htx, ist2(b_peek(buf, *ofs), ret)))
goto end;
int32_t try = ret;
ret = htx_add_data(htx, ist2(b_peek(buf, *ofs), try));
*ofs += ret;
total = ret;
if (ret < try)
goto end;
}
}

View File

@ -3802,6 +3802,8 @@ try_again:
}
if (htx) {
unsigned int sent;
block1 = htx_free_data_space(htx);
if (!block1) {
h2c->flags |= H2_CF_DEM_SFULL;
@ -3815,10 +3817,7 @@ try_again:
if (flen > block1)
flen = block1;
if (!htx_add_data(htx, ist2(b_head(&h2c->dbuf), flen))) {
h2c->flags |= H2_CF_DEM_SFULL;
goto fail;
}
sent = htx_add_data(htx, ist2(b_head(&h2c->dbuf), flen));
b_del(&h2c->dbuf, flen);
h2c->dfl -= flen;
@ -3829,6 +3828,12 @@ try_again:
h2s->body_len -= flen;
htx->extra = h2s->body_len;
}
if (sent < flen) {
h2c->flags |= H2_CF_DEM_SFULL;
goto fail;
}
goto try_again;
}
else if (unlikely(b_space_wraps(csbuf) &&

View File

@ -5502,7 +5502,18 @@ static int htx_reply_40x_unauthorized(struct stream *s, const char *auth_realm)
goto fail;
if (status == 407 && !htx_add_header(htx, ist("Proxy-Authenticate"), ist2(trash.area, trash.data)))
goto fail;
if (!htx_add_endof(htx, HTX_BLK_EOH) || !htx_add_data(htx, body) || !htx_add_endof(htx, HTX_BLK_EOM))
if (!htx_add_endof(htx, HTX_BLK_EOH))
goto fail;
while (body.len) {
size_t sent = htx_add_data(htx, body);
if (!sent)
goto fail;
body.ptr += sent;
body.len -= sent;
}
if (!htx_add_endof(htx, HTX_BLK_EOM))
goto fail;
data = htx->data - co_data(res);

View File

@ -258,7 +258,7 @@ static int stats_putchk(struct channel *chn, struct htx *htx, struct buffer *chk
if (htx) {
if (chk->data >= channel_htx_recv_max(chn, htx))
return 0;
if (!htx_add_data(htx, ist2(chk->area, chk->data)))
if (!htx_add_data_atonce(htx, ist2(chk->area, chk->data)))
return 0;
channel_add_input(chn, chk->data);
chk->data = 0;