You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
3.4 KiB

  1. commit 620381599324e15403002270637a3b677c3fe7e5
  2. Author: Willy Tarreau <w@1wt.eu>
  3. Date: Fri Aug 23 09:29:29 2019 +0200
  4. BUG/MEDIUM: mux-h1: do not report errors on transfers ending on buffer full
  5. If a receipt ends with the HTX buffer full and everything is completed except
  6. appending the HTX EOM block, we end up detecting an error because the H1
  7. parser did not switch to H1_MSG_DONE yet while all conditions for an end of
  8. stream and end of buffer are met. This can be detected by retrieving 31532
  9. or 31533 chunk-encoded bytes over H1 and seeing haproxy log "SD--" at the
  10. end of a successful transfer.
  11. Ideally the EOM part should be totally independent on the H1 message state
  12. since the block was really parsed and finished. So we should switch to a
  13. last state requiring to send only EOM. However this needs a few risky
  14. changes. This patch aims for simplicity and backport safety, thus it only
  15. adds a flag to the H1 stream indicating that an EOM is still needed, and
  16. excludes this condition from the ones used to detect end of processing. A
  17. cleaner approach needs to be studied, either by adding a state before DONE
  18. or by setting DONE once the various blocks are parsed and before trying to
  19. send EOM.
  20. This fix must be backported to 2.0. The issue does not seem to affect 1.9
  21. though it is not yet known why, probably that it is related to the different
  22. encoding of trailers which always leaves a bit of room to let EOM be stored.
  23. (cherry picked from commit 0bb5a5c4b5ad375b1254c2e8bec2dd5ea85d6ebb)
  24. Signed-off-by: Willy Tarreau <w@1wt.eu>
  25. diff --git a/src/mux_h1.c b/src/mux_h1.c
  26. index 01f225a2..b9a37ce5 100644
  27. --- a/src/mux_h1.c
  28. +++ b/src/mux_h1.c
  29. @@ -67,7 +67,8 @@
  30. #define H1S_F_BUF_FLUSH 0x00000100 /* Flush input buffer and don't read more data */
  31. #define H1S_F_SPLICED_DATA 0x00000200 /* Set when the kernel splicing is in used */
  32. #define H1S_F_HAVE_I_TLR 0x00000800 /* Set during input process to know the trailers were processed */
  33. -/* 0x00001000 .. 0x00002000 unused */
  34. +#define H1S_F_APPEND_EOM 0x00001000 /* Send EOM to the HTX buffer */
  35. +/* 0x00002000 .. 0x00002000 unused */
  36. #define H1S_F_HAVE_O_CONN 0x00004000 /* Set during output process to know connection mode was processed */
  37. /* H1 connection descriptor */
  38. @@ -954,9 +955,12 @@ static size_t h1_eval_htx_res_size(struct h1m *h1m, union h1_sl *h1sl, struct ht
  39. */
  40. static size_t h1_process_eom(struct h1s *h1s, struct h1m *h1m, struct htx *htx, size_t max)
  41. {
  42. - if (max < sizeof(struct htx_blk) + 1 || !htx_add_endof(htx, HTX_BLK_EOM))
  43. + if (max < sizeof(struct htx_blk) + 1 || !htx_add_endof(htx, HTX_BLK_EOM)) {
  44. + h1s->flags |= H1S_F_APPEND_EOM;
  45. return 0;
  46. + }
  47. + h1s->flags &= ~H1S_F_APPEND_EOM;
  48. h1m->state = H1_MSG_DONE;
  49. h1s->cs->flags |= CS_FL_EOI;
  50. return (sizeof(struct htx_blk) + 1);
  51. @@ -1472,7 +1476,8 @@ static size_t h1_process_input(struct h1c *h1c, struct buffer *buf, size_t count
  52. else if (h1s_data_pending(h1s) && !htx_is_empty(htx))
  53. h1s->cs->flags |= CS_FL_RCV_MORE | CS_FL_WANT_ROOM;
  54. - if ((h1s->flags & H1S_F_REOS) && (!h1s_data_pending(h1s) || htx_is_empty(htx))) {
  55. + if (((h1s->flags & (H1S_F_REOS|H1S_F_APPEND_EOM)) == H1S_F_REOS) &&
  56. + (!h1s_data_pending(h1s) || htx_is_empty(htx))) {
  57. h1s->cs->flags |= CS_FL_EOS;
  58. if (h1m->state > H1_MSG_LAST_LF && h1m->state < H1_MSG_DONE)
  59. h1s->cs->flags |= CS_FL_ERROR;