[MEDIUM] http: don't switch to tunnel mode upon close

The close mode of a transaction would be switched to tunnel mode
at the end of the processing, letting a lot of pending data pass
in the other direction if any. Let's fix that by checking for the
close mode during state resync too.
This commit is contained in:
Willy Tarreau 2010-01-16 23:19:39 +01:00
parent d3c343f8aa
commit cce7fa4c81

View File

@ -3542,25 +3542,36 @@ int http_sync_req_state(struct session *s)
* direction, and sometimes for a close to be effective. * direction, and sometimes for a close to be effective.
*/ */
if (!(buf->flags & (BF_SHUTW|BF_SHUTW_NOW))) {
if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) { if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) {
/* Server-close mode : queue a connection close to the server */ /* Server-close mode : queue a connection close to the server */
if (!(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)))
buffer_shutw_now(buf); buffer_shutw_now(buf);
buf->cons->flags |= SI_FL_NOLINGER;
} }
else if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_CLO) { else if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_CLO) {
/* Option forceclose is set, let's enforce it now /* Option forceclose is set, or either side wants to close,
* that we're not expecting any new data to come. * let's enforce it now that we're not expecting any new
* data to come. The caller knows the session is complete
* once both states are CLOSED.
*/ */
if (!(buf->flags & (BF_SHUTW|BF_SHUTW_NOW))) {
buffer_shutr_now(buf); buffer_shutr_now(buf);
buffer_shutw_now(buf); buffer_shutw_now(buf);
buf->cons->flags |= SI_FL_NOLINGER;
} }
/* other modes include httpclose (no action) and keepalive (not implemented) */ }
else {
/* The last possible modes are keep-alive and tunnel. Since tunnel
* mode does not set the body analyser, we can't reach this place
* in tunnel mode, so we're left with keep-alive only.
* This mode is currently not implemented, we switch to tunnel mode.
*/
buffer_auto_read(buf);
txn->req.msg_state = HTTP_MSG_TUNNEL;
} }
if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) { if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {
/* if we've just closed an output, let's switch */ /* if we've just closed an output, let's switch */
buf->cons->flags |= SI_FL_NOLINGER; /* we want to close ASAP */
if (!(buf->flags & BF_OUT_EMPTY)) { if (!(buf->flags & BF_OUT_EMPTY)) {
txn->req.msg_state = HTTP_MSG_CLOSING; txn->req.msg_state = HTTP_MSG_CLOSING;
goto http_msg_closing; goto http_msg_closing;
@ -3570,13 +3581,8 @@ int http_sync_req_state(struct session *s)
goto http_msg_closed; goto http_msg_closed;
} }
} }
else {
/* other modes are used as a tunnel right now */
buffer_auto_read(buf);
txn->req.msg_state = HTTP_MSG_TUNNEL;
goto wait_other_side; goto wait_other_side;
} }
}
if (txn->req.msg_state == HTTP_MSG_CLOSING) { if (txn->req.msg_state == HTTP_MSG_CLOSING) {
http_msg_closing: http_msg_closing:
@ -3663,26 +3669,26 @@ int http_sync_res_state(struct session *s)
*/ */
if (!(buf->flags & (BF_SHUTR|BF_SHUTR_NOW))) if (!(buf->flags & (BF_SHUTR|BF_SHUTR_NOW)))
buffer_shutr_now(buf); buffer_shutr_now(buf);
goto wait_other_side;
} }
else if (!(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) && else if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_CLO) {
((s->fe->options | s->be->options) & PR_O_FORCE_CLO)) { /* Option forceclose is set, or either side wants to close,
/* Option forceclose is set, let's enforce it now * let's enforce it now that we're not expecting any new
* that we're not expecting any new data to come. * data to come. The caller knows the session is complete
* The caller knows the session is complete once * once both states are CLOSED.
* both states are CLOSED.
*/ */
if (!(buf->flags & (BF_SHUTW|BF_SHUTW_NOW))) {
buffer_shutr_now(buf); buffer_shutr_now(buf);
buffer_shutw_now(buf); buffer_shutw_now(buf);
} }
}
else { else {
/* other modes include httpclose (no action) and keepalive /* The last possible modes are keep-alive and tunnel. Since tunnel
* (not implemented). These modes are used as a tunnel right * mode does not set the body analyser, we can't reach this place
* now. * in tunnel mode, so we're left with keep-alive only.
* This mode is currently not implemented, we switch to tunnel mode.
*/ */
buffer_auto_read(buf); buffer_auto_read(buf);
txn->rsp.msg_state = HTTP_MSG_TUNNEL; txn->rsp.msg_state = HTTP_MSG_TUNNEL;
goto wait_other_side;
} }
if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) { if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {