Browse Source

haproxy: Update all patches for HAProxy v1.8.8

- Add new patches (see https://www.haproxy.org/bugs/bugs-1.8.8.html)
- Raise patch-level to 02

Signed-off-by: Christian Lachner <gladiac@gmail.com>
lilik-openwrt-22.03
Christian Lachner 7 years ago
parent
commit
c866db0911
8 changed files with 559 additions and 1 deletions
  1. +1
    -1
      net/haproxy/Makefile
  2. +26
    -0
      net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch
  3. +87
    -0
      net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch
  4. +50
    -0
      net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch
  5. +48
    -0
      net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch
  6. +147
    -0
      net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch
  7. +164
    -0
      net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch
  8. +36
    -0
      net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch

+ 1
- 1
net/haproxy/Makefile View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=haproxy
PKG_VERSION:=1.8.8
PKG_RELEASE:=01
PKG_RELEASE:=02
PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/


+ 26
- 0
net/haproxy/patches/0000-BUG-MINOR-pattern-Add-a-missing-HA_SPIN_INIT-in-pat_ref_newid.patch View File

@ -0,0 +1,26 @@
commit 6c9efc8219e35f4eb17e94b364f4c371cfb56cca
Author: Aurélien Nephtali <aurelien.nephtali@corp.ovh.com>
Date: Thu Apr 19 16:56:07 2018 +0200
BUG/MINOR: pattern: Add a missing HA_SPIN_INIT() in pat_ref_newid()
pat_ref_newid() is lacking a spinlock init. It was probably forgotten
in b5997f740b ("MAJOR: threads/map: Make acls/maps thread safe").
Signed-off-by: Aurélien Nephtali <aurelien.nephtali@corp.ovh.com>
(cherry picked from commit 564d15a71ecb3ae3372767866335cfbc068c4b48)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/pattern.c b/src/pattern.c
index fe672f12..2eb82650 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -1906,7 +1906,7 @@ struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int f
ref->unique_id = unique_id;
LIST_INIT(&ref->head);
LIST_INIT(&ref->pat);
-
+ HA_SPIN_INIT(&ref->lock);
LIST_ADDQ(&pattern_reference, &ref->list);
return ref;

+ 87
- 0
net/haproxy/patches/0001-BUG-MAJOR-channel-Fix-crash-when-trying-to-read-from-a-closed-socket.patch View File

@ -0,0 +1,87 @@
commit e0f6d4a4e8696140d1fcff812fb287d534d702e9
Author: Tim Duesterhus <tim@bastelstu.be>
Date: Tue Apr 24 19:20:43 2018 +0200
BUG/MAJOR: channel: Fix crash when trying to read from a closed socket
When haproxy is compiled using GCC <= 3.x or >= 5.x the `unlikely`
macro performs a comparison with zero: `(x) != 0`, thus returning
either 0 or 1.
In `int co_getline_nc()` this macro was accidentally applied to
the variable `retcode` itself, instead of the result of the
comparison `retcode <= 0`. As a result any negative `retcode`
is converted to `1` for purposes of the comparison.
Thus never taking the branch (and exiting the function) for
negative values.
This in turn leads to reads of uninitialized memory in the for-loop
below:
==12141== Conditional jump or move depends on uninitialised value(s)
==12141== at 0x4EB6B4: co_getline_nc (channel.c:346)
==12141== by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
==12141== by 0x421F6F: hlua_socket_receive (hlua.c:1896)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141==
==12141== Use of uninitialised value of size 8
==12141== at 0x4EB6B9: co_getline_nc (channel.c:346)
==12141== by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
==12141== by 0x421F6F: hlua_socket_receive (hlua.c:1896)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141==
==12141== Invalid read of size 1
==12141== at 0x4EB6B9: co_getline_nc (channel.c:346)
==12141== by 0x421CA4: hlua_socket_receive_yield (hlua.c:1713)
==12141== by 0x421F6F: hlua_socket_receive (hlua.c:1896)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B497: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529711A: lua_pcallk (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52ABDF0: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B08F: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x52A7EFC: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529A9F1: ??? (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== by 0x529B523: lua_resume (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==12141== Address 0x8637171e928bb500 is not stack'd, malloc'd or (recently) free'd
Fix this bug by correctly applying the `unlikely` macro to the result of the comparison.
This bug exists as of commit ca16b038132444dea06e6d83953034128a812bce
which is the first commit adding this function.
v1.6-dev1 is the first tag containing this commit, the fix should
be backported to haproxy 1.6 and newer.
(cherry picked from commit 45be38c9c7ba2b20806f2b887876db4fb5b9457c)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/channel.c b/src/channel.c
index bd5c4de0..3770502c 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -340,7 +340,7 @@ int co_getline_nc(const struct channel *chn,
int l;
retcode = co_getblk_nc(chn, blk1, len1, blk2, len2);
- if (unlikely(retcode) <= 0)
+ if (unlikely(retcode <= 0))
return retcode;
for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);

+ 50
- 0
net/haproxy/patches/0002-BUG-MINOR-log-t_idle-Ti-is-not-set-for-some-requests.patch View File

@ -0,0 +1,50 @@
commit 0e645ba57ddff9163a3d9b5626f189e974e671bd
Author: Rian McGuire <rian.mcguire@stileeducation.com>
Date: Tue Apr 24 11:19:21 2018 -0300
BUG/MINOR: log: t_idle (%Ti) is not set for some requests
If TCP content inspection is used, msg_state can be >= HTTP_MSG_ERROR
the first time http_wait_for_request is called. t_idle was being left
unset in that case.
In the example below :
stick-table type string len 64 size 100k expire 60s
tcp-request inspect-delay 1s
tcp-request content track-sc1 hdr(X-Session)
%Ti will always be -1, because the msg_state is already at HTTP_MSG_BODY
when http_wait_for_request is called for the first time.
This patch should backported to 1.8 and 1.7.
(cherry picked from commit 89fcb7d929283e904cabad58de495d62fc753da2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/proto_http.c b/src/proto_http.c
index b38dd84f..4c18a27c 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1618,18 +1618,16 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
/* we're speaking HTTP here, so let's speak HTTP to the client */
s->srv_error = http_return_srv_error;
+ /* If there is data available for analysis, log the end of the idle time. */
+ if (buffer_not_empty(req->buf) && s->logs.t_idle == -1)
+ s->logs.t_idle = tv_ms_elapsed(&s->logs.tv_accept, &now) - s->logs.t_handshake;
+
/* There's a protected area at the end of the buffer for rewriting
* purposes. We don't want to start to parse the request if the
* protected area is affected, because we may have to move processed
* data later, which is much more complicated.
*/
if (buffer_not_empty(req->buf) && msg->msg_state < HTTP_MSG_ERROR) {
-
- /* This point is executed when some data is avalaible for analysis,
- * so we log the end of the idle time. */
- if (s->logs.t_idle == -1)
- s->logs.t_idle = tv_ms_elapsed(&s->logs.tv_accept, &now) - s->logs.t_handshake;
-
if (txn->flags & TX_NOT_FIRST) {
if (unlikely(!channel_is_rewritable(req))) {
if (req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT))

+ 48
- 0
net/haproxy/patches/0003-BUG-MEDIUM-lua-Fix-segmentation-fault-if-a-Lua-task-exits.patch View File

@ -0,0 +1,48 @@
commit 17f3e16826e5b1a3f79b7421d69bb85be09a4ad9
Author: Tim Duesterhus <tim@bastelstu.be>
Date: Tue Apr 24 13:56:01 2018 +0200
BUG/MEDIUM: lua: Fix segmentation fault if a Lua task exits
PiBa-NL reported that haproxy crashes with a segmentation fault
if a function registered using `core.register_task` returns.
An example Lua script that reproduces the bug is:
mytask = function()
core.Info("Stopping task")
end
core.register_task(mytask)
The Valgrind output is as follows:
==6759== Process terminating with default action of signal 11 (SIGSEGV)
==6759== Access not within mapped region at address 0x20
==6759== at 0x5B60AA9: lua_sethook (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
==6759== by 0x430264: hlua_ctx_resume (hlua.c:1009)
==6759== by 0x43BB68: hlua_process_task (hlua.c:5525)
==6759== by 0x4FED0A: process_runnable_tasks (task.c:231)
==6759== by 0x4B2256: run_poll_loop (haproxy.c:2397)
==6759== by 0x4B2256: run_thread_poll_loop (haproxy.c:2459)
==6759== by 0x41A7E4: main (haproxy.c:3049)
Add the missing `task = NULL` for the `HLUA_E_OK` case. The error cases
have been fixed as of 253e53e661c49fb9723535319cf511152bf09bc7 which
first was included in haproxy v1.8-dev3. This bugfix should be backported
to haproxy 1.8.
(cherry picked from commit cd235c60425dbe66c9015a357369afacc4880211)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/hlua.c b/src/hlua.c
index 4e759c7c..d4b7ce91 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -5528,6 +5528,7 @@ static struct task *hlua_process_task(struct task *task)
hlua_ctx_destroy(hlua);
task_delete(task);
task_free(task);
+ task = NULL;
break;
case HLUA_E_AGAIN: /* co process or timeout wake me later. */

+ 147
- 0
net/haproxy/patches/0004-MINOR-h2-detect-presence-of-CONNECT-and-or-content-length.patch View File

@ -0,0 +1,147 @@
commit a8bcc7dd3fe5aa615f21e795375ff9225f004498
Author: Willy Tarreau <w@1wt.eu>
Date: Wed Apr 25 18:13:58 2018 +0200
MINOR: h2: detect presence of CONNECT and/or content-length
We'll need this in order to support uploading chunks. The h2 to h1
converter checks for the presence of the content-length header field
as well as the CONNECT method and returns these information to the
caller. The caller indicates whether or not a body is detected for
the message (presence of END_STREAM or not). No transfer-encoding
header is emitted yet.
(cherry picked from commit 174b06a572ef141f15d8b7ea64eb6b34ec4c9af1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/common/h2.h b/include/common/h2.h
index 65c5ab1c..576ed105 100644
--- a/include/common/h2.h
+++ b/include/common/h2.h
@@ -145,9 +145,15 @@ enum h2_err {
"\x0d\x0a\x53\x4d\x0d\x0a\x0d\x0a"
+/* some flags related to protocol parsing */
+#define H2_MSGF_BODY 0x0001 // a body is present
+#define H2_MSGF_BODY_CL 0x0002 // content-length is present
+#define H2_MSGF_BODY_TUNNEL 0x0004 // a tunnel is in use (CONNECT)
+
+
/* various protocol processing functions */
-int h2_make_h1_request(struct http_hdr *list, char *out, int osize);
+int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf);
/*
* Some helpful debugging functions.
diff --git a/src/h2.c b/src/h2.c
index 43ed7f3c..7d9ddd50 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -36,9 +36,10 @@
* stored in <phdr[]>. <fields> indicates what was found so far. This should be
* called once at the detection of the first general header field or at the end
* of the request if no general header field was found yet. Returns 0 on success
- * or a negative error code on failure.
+ * or a negative error code on failure. Upon success, <msgf> is updated with a
+ * few H2_MSGF_* flags indicating what was found while parsing.
*/
-static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr, char *end)
+static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr, char *end, unsigned int *msgf)
{
char *out = *ptr;
int uri_idx = H2_PHDR_IDX_PATH;
@@ -62,6 +63,7 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
}
// otherwise OK ; let's use the authority instead of the URI
uri_idx = H2_PHDR_IDX_AUTH;
+ *msgf |= H2_MSGF_BODY_TUNNEL;
}
else if ((fields & (H2_PHDR_FND_METH|H2_PHDR_FND_SCHM|H2_PHDR_FND_PATH)) !=
(H2_PHDR_FND_METH|H2_PHDR_FND_SCHM|H2_PHDR_FND_PATH)) {
@@ -113,6 +115,10 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
* for a max of <osize> bytes, and the amount of bytes emitted is returned. In
* case of error, a negative error code is returned.
*
+ * Upon success, <msgf> is filled with a few H2_MSGF_* flags indicating what
+ * was found while parsing. The caller must set it to zero in or H2_MSGF_BODY
+ * if a body is detected (!ES).
+ *
* The headers list <list> must be composed of :
* - n.name != NULL, n.len > 0 : literal header name
* - n.name == NULL, n.len > 0 : indexed pseudo header name number <n.len>
@@ -124,7 +130,7 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
* The Cookie header will be reassembled at the end, and for this, the <list>
* will be used to create a linked list, so its contents may be destroyed.
*/
-int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
+int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf)
{
struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
char *out_end = out + osize;
@@ -176,7 +182,7 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
/* regular header field in (name,value) */
if (!(fields & H2_PHDR_FND_NONE)) {
/* no more pseudo-headers, time to build the request line */
- ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end);
+ ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end, msgf);
if (ret != 0)
goto leave;
fields |= H2_PHDR_FND_NONE;
@@ -185,6 +191,10 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
if (isteq(list[idx].n, ist("host")))
fields |= H2_PHDR_FND_HOST;
+ if ((*msgf & (H2_MSGF_BODY|H2_MSGF_BODY_TUNNEL|H2_MSGF_BODY_CL)) == H2_MSGF_BODY &&
+ isteq(list[idx].n, ist("content-length")))
+ *msgf |= H2_MSGF_BODY_CL;
+
/* these ones are forbidden in requests (RFC7540#8.1.2.2) */
if (isteq(list[idx].n, ist("connection")) ||
isteq(list[idx].n, ist("proxy-connection")) ||
@@ -232,7 +242,7 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize)
/* Let's dump the request now if not yet emitted. */
if (!(fields & H2_PHDR_FND_NONE)) {
- ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end);
+ ret = h2_prepare_h1_reqline(fields, phdr_val, &out, out_end, msgf);
if (ret != 0)
goto leave;
}
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 4fde7fcc..82dd414a 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -2626,6 +2626,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
struct chunk *tmp = get_trash_chunk();
struct http_hdr list[MAX_HTTP_HDR * 2];
struct chunk *copy = NULL;
+ unsigned int msgf;
int flen = h2c->dfl;
int outlen = 0;
int wrap;
@@ -2727,13 +2728,22 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
}
/* OK now we have our header list in <list> */
- outlen = h2_make_h1_request(list, bi_end(buf), try);
+ msgf = (h2c->dff & H2_F_DATA_END_STREAM) ? 0 : H2_MSGF_BODY;
+ outlen = h2_make_h1_request(list, bi_end(buf), try, &msgf);
if (outlen < 0) {
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
goto fail;
}
+ if (msgf & H2_MSGF_BODY) {
+ /* a payload is present */
+ if (msgf & H2_MSGF_BODY_CL)
+ h2s->flags |= H2_SF_DATA_CLEN;
+ else if (!(msgf & H2_MSGF_BODY_TUNNEL))
+ h2s->flags |= H2_SF_DATA_CHNK;
+ }
+
/* now consume the input data */
bi_del(h2c->dbuf, h2c->dfl);
h2c->st0 = H2_CS_FRAME_H;

+ 164
- 0
net/haproxy/patches/0005-BUG-MEDIUM-h2-implement-missing-support-for-chunked-encoded-uploads.patch View File

@ -0,0 +1,164 @@
commit 05657bd24ebaf20e5c508a435be9a0830591f033
Author: Willy Tarreau <w@1wt.eu>
Date: Wed Apr 25 20:44:22 2018 +0200
BUG/MEDIUM: h2: implement missing support for chunked encoded uploads
Upload requests not carrying a content-length nor tunnelling data must
be sent chunked-encoded over HTTP/1. The code was planned but for some
reason forgotten during the implementation, leading to such payloads to
be sent as tunnelled data.
Browsers always emit a content length in uploads so this problem doesn't
happen for most sites. However some applications may send data frames
after a request without indicating it earlier.
The only way to detect that a client will need to send data is that the
HEADERS frame doesn't hold the ES bit. In this case it's wise to look
for the content-length header. If it's not there, either we're in tunnel
(CONNECT method) or chunked-encoding (other methods).
This patch implements this.
The following request is sent using content-length :
curl --http2 -sk https://127.0.0.1:4443/s2 -XPOST -T /large/file
and these ones using chunked-encoding :
curl --http2 -sk https://127.0.0.1:4443/s2 -XPUT -T /large/file
curl --http2 -sk https://127.0.0.1:4443/s2 -XPUT -T - < /dev/urandom
Thanks to Robert Samuel Newson for raising this issue with details.
This fix must be backported to 1.8.
(cherry picked from commit eba10f24b7da27cde60d2db24aeb1147e1657579)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/h2.c b/src/h2.c
index 7d9ddd50..5c83d6b6 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -262,6 +262,14 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int
*(out++) = '\n';
}
+ if ((*msgf & (H2_MSGF_BODY|H2_MSGF_BODY_TUNNEL|H2_MSGF_BODY_CL)) == H2_MSGF_BODY) {
+ /* add chunked encoding */
+ if (out + 28 > out_end)
+ goto fail;
+ memcpy(out, "transfer-encoding: chunked\r\n", 28);
+ out += 28;
+ }
+
/* now we may have to build a cookie list. We'll dump the values of all
* visited headers.
*/
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 82dd414a..5f1da0df 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -2785,6 +2785,7 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
struct h2c *h2c = h2s->h2c;
int block1, block2;
unsigned int flen = h2c->dfl;
+ unsigned int chklen = 0;
h2s->cs->flags &= ~CS_FL_RCV_MORE;
h2c->flags &= ~H2_CF_DEM_SFULL;
@@ -2820,14 +2821,35 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
return 0;
}
+ /* chunked-encoding requires more room */
+ if (h2s->flags & H2_SF_DATA_CHNK) {
+ chklen = MIN(flen, count);
+ chklen = (chklen < 16) ? 1 : (chklen < 256) ? 2 :
+ (chklen < 4096) ? 3 : (chklen < 65536) ? 4 :
+ (chklen < 1048576) ? 4 : 8;
+ chklen += 4; // CRLF, CRLF
+ }
+
/* does it fit in output buffer or should we wait ? */
- if (flen > count) {
- flen = count;
- if (!flen) {
- h2c->flags |= H2_CF_DEM_SFULL;
- h2s->cs->flags |= CS_FL_RCV_MORE;
- return 0;
- }
+ if (flen + chklen > count) {
+ if (chklen >= count)
+ goto full;
+ flen = count - chklen;
+ }
+
+ if (h2s->flags & H2_SF_DATA_CHNK) {
+ /* emit the chunk size */
+ unsigned int chksz = flen;
+ char str[10];
+ char *beg;
+
+ beg = str + sizeof(str);
+ *--beg = '\n';
+ *--beg = '\r';
+ do {
+ *--beg = hextab[chksz & 0xF];
+ } while (chksz >>= 4);
+ bi_putblk(buf, beg, str + sizeof(str) - beg);
}
/* Block1 is the length of the first block before the buffer wraps,
@@ -2844,6 +2866,11 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
if (block2)
bi_putblk(buf, b_ptr(h2c->dbuf, block1), block2);
+ if (h2s->flags & H2_SF_DATA_CHNK) {
+ /* emit the CRLF */
+ bi_putblk(buf, "\r\n", 2);
+ }
+
/* now mark the input data as consumed (will be deleted from the buffer
* by the caller when seeing FRAME_A after sending the window update).
*/
@@ -2854,15 +2881,22 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
if (h2c->dfl > h2c->dpl) {
/* more data available, transfer stalled on stream full */
- h2c->flags |= H2_CF_DEM_SFULL;
- h2s->cs->flags |= CS_FL_RCV_MORE;
- return flen;
+ goto more;
}
end_transfer:
/* here we're done with the frame, all the payload (except padding) was
* transferred.
*/
+
+ if (h2c->dff & H2_F_DATA_END_STREAM && h2s->flags & H2_SF_DATA_CHNK) {
+ /* emit the trailing 0 CRLF CRLF */
+ if (count < 5)
+ goto more;
+ chklen += 5;
+ bi_putblk(buf, "0\r\n\r\n", 5);
+ }
+
h2c->rcvd_c += h2c->dpl;
h2c->rcvd_s += h2c->dpl;
h2c->dpl = 0;
@@ -2877,7 +2911,13 @@ static int h2_frt_transfer_data(struct h2s *h2s, struct buffer *buf, int count)
h2s->flags |= H2_SF_ES_RCVD;
}
- return flen;
+ return flen + chklen;
+ full:
+ flen = chklen = 0;
+ more:
+ h2c->flags |= H2_CF_DEM_SFULL;
+ h2s->cs->flags |= CS_FL_RCV_MORE;
+ return flen + chklen;
}
/*

+ 36
- 0
net/haproxy/patches/0006-BUG-MINOR-lua-threads-Make-luas-tasks-sticky-to-the-current-thread.patch View File

@ -0,0 +1,36 @@
commit 8b8d55be7e94ee3d758d41a21fa86a036e91a264
Author: Christopher Faulet <cfaulet@haproxy.com>
Date: Wed Apr 25 10:34:45 2018 +0200
BUG/MINOR: lua/threads: Make lua's tasks sticky to the current thread
PiBa-NL reported a bug with tasks registered in lua when HAProxy is started with
serveral threads. These tasks have not specific affinity with threads so they
can be woken up on any threads. So, it is impossbile for these tasks to handled
cosockets or applets, because cosockets and applets are sticky on the thread
which created them. It is forbbiden to manipulate a cosocket from another
thread.
So to fix the bug, tasks registered in lua are now sticky to the current
thread. Because these tasks can be registered before threads creation, the
affinity is set the first time a lua's task is processed.
This patch must be backported in HAProxy 1.8.
(cherry picked from commit 5bc9972ed836517924eea91954d255d317a53418)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/hlua.c b/src/hlua.c
index d4b7ce91..bd0b87e3 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -5513,6 +5513,9 @@ static struct task *hlua_process_task(struct task *task)
struct hlua *hlua = task->context;
enum hlua_exec status;
+ if (task->thread_mask == MAX_THREADS_MASK)
+ task_set_affinity(task, tid_bit);
+
/* If it is the first call to the task, we must initialize the
* execution timeouts.
*/

Loading…
Cancel
Save