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.

153 lines
5.1 KiB

  1. From 1430a0c0f62fcff4303706f5baf2b544e00fcda3 Mon Sep 17 00:00:00 2001
  2. From: Christopher Faulet <cfaulet@haproxy.com>
  3. Date: Tue, 18 Jul 2017 10:48:24 +0200
  4. Subject: [PATCH 13/18] MINOR: http: Switch requests/responses in TUNNEL mode
  5. only by checking txn flags
  6. Today, the only way to have a request or a response in HTTP_MSG_TUNNEL state is
  7. to have the flag TX_CON_WANT_TUN set on the transaction. So this is a symmetric
  8. state. Both the request and the response are switch in same time in this
  9. state. This can be done only by checking transaction flags instead of relying on
  10. the other side state. This is the purpose of this patch.
  11. This way, if for any reason we need to switch only one side in TUNNEL mode, it
  12. will be possible. And to prepare asymmetric cases, we check channel flags in
  13. DONE _AND_ TUNNEL states.
  14. WARNING: This patch will be used to fix a bug. The fix will be commited in a
  15. very next commit. So if the fix is backported, this one must be backported too.
  16. (cherry picked from commit 4be9803914ae7156109c915659aad216e4a3c6c1)
  17. Signed-off-by: William Lallemand <wlallemand@haproxy.org>
  18. ---
  19. src/proto_http.c | 65 +++++++++++++++++++-------------------------------------
  20. 1 file changed, 22 insertions(+), 43 deletions(-)
  21. diff --git a/src/proto_http.c b/src/proto_http.c
  22. index aaf9f648..00a92cdb 100644
  23. --- a/src/proto_http.c
  24. +++ b/src/proto_http.c
  25. @@ -5294,7 +5294,7 @@ int http_sync_req_state(struct stream *s)
  26. unsigned int old_flags = chn->flags;
  27. unsigned int old_state = txn->req.msg_state;
  28. - if (unlikely(txn->req.msg_state < HTTP_MSG_BODY))
  29. + if (unlikely(txn->req.msg_state < HTTP_MSG_DONE))
  30. return 0;
  31. if (txn->req.msg_state == HTTP_MSG_DONE) {
  32. @@ -5338,13 +5338,6 @@ int http_sync_req_state(struct stream *s)
  33. goto wait_other_side;
  34. }
  35. - if (txn->rsp.msg_state == HTTP_MSG_TUNNEL) {
  36. - /* if any side switches to tunnel mode, the other one does too */
  37. - channel_auto_read(chn);
  38. - txn->req.msg_state = HTTP_MSG_TUNNEL;
  39. - goto wait_other_side;
  40. - }
  41. -
  42. /* When we get here, it means that both the request and the
  43. * response have finished receiving. Depending on the connection
  44. * mode, we'll have to wait for the last bytes to leave in either
  45. @@ -5377,20 +5370,7 @@ int http_sync_req_state(struct stream *s)
  46. }
  47. }
  48. - if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) {
  49. - /* if we've just closed an output, let's switch */
  50. - s->si[1].flags |= SI_FL_NOLINGER; /* we want to close ASAP */
  51. -
  52. - if (!channel_is_empty(chn)) {
  53. - txn->req.msg_state = HTTP_MSG_CLOSING;
  54. - goto http_msg_closing;
  55. - }
  56. - else {
  57. - txn->req.msg_state = HTTP_MSG_CLOSED;
  58. - goto http_msg_closed;
  59. - }
  60. - }
  61. - goto wait_other_side;
  62. + goto check_channel_flags;
  63. }
  64. if (txn->req.msg_state == HTTP_MSG_CLOSING) {
  65. @@ -5419,6 +5399,16 @@ int http_sync_req_state(struct stream *s)
  66. goto wait_other_side;
  67. }
  68. + check_channel_flags:
  69. + /* Here, we are in HTTP_MSG_DONE or HTTP_MSG_TUNNEL */
  70. + if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) {
  71. + /* if we've just closed an output, let's switch */
  72. + s->si[1].flags |= SI_FL_NOLINGER; /* we want to close ASAP */
  73. + txn->req.msg_state = HTTP_MSG_CLOSING;
  74. + goto http_msg_closing;
  75. + }
  76. +
  77. +
  78. wait_other_side:
  79. return txn->req.msg_state != old_state || chn->flags != old_flags;
  80. }
  81. @@ -5438,7 +5428,7 @@ int http_sync_res_state(struct stream *s)
  82. unsigned int old_flags = chn->flags;
  83. unsigned int old_state = txn->rsp.msg_state;
  84. - if (unlikely(txn->rsp.msg_state < HTTP_MSG_BODY))
  85. + if (unlikely(txn->rsp.msg_state < HTTP_MSG_DONE))
  86. return 0;
  87. if (txn->rsp.msg_state == HTTP_MSG_DONE) {
  88. @@ -5461,14 +5451,6 @@ int http_sync_res_state(struct stream *s)
  89. goto wait_other_side;
  90. }
  91. - if (txn->req.msg_state == HTTP_MSG_TUNNEL) {
  92. - /* if any side switches to tunnel mode, the other one does too */
  93. - channel_auto_read(chn);
  94. - txn->rsp.msg_state = HTTP_MSG_TUNNEL;
  95. - chn->flags |= CF_NEVER_WAIT;
  96. - goto wait_other_side;
  97. - }
  98. -
  99. /* When we get here, it means that both the request and the
  100. * response have finished receiving. Depending on the connection
  101. * mode, we'll have to wait for the last bytes to leave in either
  102. @@ -5506,18 +5488,7 @@ int http_sync_res_state(struct stream *s)
  103. txn->rsp.msg_state = HTTP_MSG_TUNNEL;
  104. }
  105. - if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) {
  106. - /* if we've just closed an output, let's switch */
  107. - if (!channel_is_empty(chn)) {
  108. - txn->rsp.msg_state = HTTP_MSG_CLOSING;
  109. - goto http_msg_closing;
  110. - }
  111. - else {
  112. - txn->rsp.msg_state = HTTP_MSG_CLOSED;
  113. - goto http_msg_closed;
  114. - }
  115. - }
  116. - goto wait_other_side;
  117. + goto check_channel_flags;
  118. }
  119. if (txn->rsp.msg_state == HTTP_MSG_CLOSING) {
  120. @@ -5548,6 +5519,14 @@ int http_sync_res_state(struct stream *s)
  121. goto wait_other_side;
  122. }
  123. + check_channel_flags:
  124. + /* Here, we are in HTTP_MSG_DONE or HTTP_MSG_TUNNEL */
  125. + if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) {
  126. + /* if we've just closed an output, let's switch */
  127. + txn->rsp.msg_state = HTTP_MSG_CLOSING;
  128. + goto http_msg_closing;
  129. + }
  130. +
  131. wait_other_side:
  132. /* We force the response to leave immediately if we're waiting for the
  133. * other side, since there is no pending shutdown to push it out.
  134. --
  135. 2.13.0