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);
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))
offset += sz;
len -= sz;
total += sz;
- if (!len)
+ if (!len || sz < data.len)
break;
offset = 0;
}
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. */
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;
/* 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
* => 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;
* 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) {
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;
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;
}
}
}
if (htx) {
+ unsigned int sent;
+
block1 = htx_free_data_space(htx);
if (!block1) {
h2c->flags |= H2_CF_DEM_SFULL;
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;
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) &&
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);
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;