]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: htx: make htx_add_data() return the transmitted byte count
authorWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 08:30:11 +0000 (10:30 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 12:48:59 +0000 (14:48 +0200)
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.

include/common/htx.h
src/cache.c
src/hlua.c
src/http_htx.c
src/htx.c
src/mux_h1.c
src/mux_h2.c
src/proto_htx.c
src/stats.c

index 463f7299bf511951591252a470563af8222277b8..fd0871c5296e616b8ebc259bec14cd23b3e153e7 100644 (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);
 
index 83aacd136d1eb79599f7e7b8027270282c9c1c9c..e390b2168200336d3a0bf9b93a9258c12b8694c9 100644 (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;
        }
index 3c9c70a78eabc91562cf850351e993a9e415eccf..a3fd57b9157fb7b5d499b9f7f1fc6f49c4cf5317 100644 (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. */
index b9501bed73f8e452dfa0cefb9fad79b109a6693c..9892fd32ac05aaa356be5402e6c50234cd59c6c2 100644 (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;
index 2aeb077f2f5ee1fa9130fa534d7fa5866044ae86..32e23d115ff7d9a68c9f1ee6150d299477a4ad79 100644 (file)
--- a/src/htx.c
+++ b/src/htx.c
@@ -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
index d1e7c1d76bf0788b24ec4418c61ce2da5942df71..ef622bd2b6fdcd9e9f1b1360077ba2d63c2bd91b 100644 (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;
                }
        }
 
index 6bec578b6224180f502d433d71f364816d7557c4..7d29a7d1f66e2e8f75ef05267186b4179050ba57 100644 (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) &&
index 0bb1eb2fd3f98509c2a5e6c447324f40d937cdd4..27150a8ed5cd1e7d7634365505b903b3dbe2cd2f 100644 (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);
index 9c3bf7c14f1ae2ff8d4b47b352464091200d5da8..4b994b72c330e9aa0657128df6f4a58d31fba375 100644 (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;