mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 23:56:57 +02:00
[MAJOR] make the client side use stream_sock_process_data()
The client side now relies on stream_sock_process_data(). One part has not yet been re-implemented, it concerns the calls to produce_content(). process_session() has been adjusted to correctly check for changing bits in order not to call useless functions too many times. It already appears that stream_sock_process_data() should be split so that the timeout computations are only performed at the exit of process_session().
This commit is contained in:
parent
2d2127989c
commit
f9839bdffe
@ -66,6 +66,12 @@
|
|||||||
#define BF_SHUTW_NOW 262144 /* the consumer must shut down for writes ASAP */
|
#define BF_SHUTW_NOW 262144 /* the consumer must shut down for writes ASAP */
|
||||||
#define BF_HIJACK 524288 /* the producer is temporarily replaced */
|
#define BF_HIJACK 524288 /* the producer is temporarily replaced */
|
||||||
|
|
||||||
|
/* masks which define input bits for stream interfaces and stream analysers */
|
||||||
|
#define BF_MASK_INTERFACE_I (BF_FULL|BF_HIJACK|BF_READ_NULL|BF_SHUTR|BF_SHUTR_NOW|BF_SHUTW)
|
||||||
|
#define BF_MASK_INTERFACE_O (BF_EMPTY|BF_HIJACK|BF_MAY_FORWARD|BF_SHUTR|BF_SHUTW|BF_SHUTW_NOW)
|
||||||
|
#define BF_MASK_INTERFACE (BF_MASK_INTF_I | BF_MASK_INTF_O)
|
||||||
|
|
||||||
|
#define BF_MASK_ANALYSER (BF_FULL|BF_READ_ERROR|BF_READ_TIMEOUT|BF_WRITE_ERROR|BF_SHUTW|BF_SHUTR|BF_READ_NULL)
|
||||||
|
|
||||||
/* Analysers (buffer->analysers).
|
/* Analysers (buffer->analysers).
|
||||||
* Those bits indicate that there are some processing to do on the buffer
|
* Those bits indicate that there are some processing to do on the buffer
|
||||||
|
626
src/proto_http.c
626
src/proto_http.c
@ -650,98 +650,45 @@ http_get_path(struct http_txn *txn)
|
|||||||
* to be woken up, or TICK_ETERNITY. In order not to call all functions for
|
* to be woken up, or TICK_ETERNITY. In order not to call all functions for
|
||||||
* nothing too many times, the request and response buffers flags are monitored
|
* nothing too many times, the request and response buffers flags are monitored
|
||||||
* and each function is called only if at least another function has changed at
|
* and each function is called only if at least another function has changed at
|
||||||
* least one flag. If one of the functions called returns non-zero, then it
|
* least one flag it is interested in.
|
||||||
* will be called once again after all other functions. This permits explicit
|
|
||||||
* external loops which may be useful for complex state machines.
|
|
||||||
*/
|
*/
|
||||||
#define PROCESS_CLI 0x1
|
|
||||||
#define PROCESS_SRV 0x2
|
|
||||||
#define PROCESS_REQ 0x4
|
|
||||||
#define PROCESS_RTR 0x8
|
|
||||||
#define PROCESS_ALL (PROCESS_CLI|PROCESS_SRV|PROCESS_REQ|PROCESS_RTR)
|
|
||||||
|
|
||||||
void process_session(struct task *t, int *next)
|
void process_session(struct task *t, int *next)
|
||||||
{
|
{
|
||||||
struct session *s = t->context;
|
struct session *s = t->context;
|
||||||
unsigned resync = PROCESS_ALL;
|
int resync;
|
||||||
unsigned int rqf;
|
unsigned int rqf_cli, rpf_cli;
|
||||||
unsigned int rpf;
|
unsigned int rqf_srv, rpf_srv;
|
||||||
|
unsigned int rqf_req, rpf_rep;
|
||||||
|
|
||||||
/* check timeout expiration only once and adjust buffer flags
|
/* force one first pass everywhere */
|
||||||
* accordingly.
|
rqf_cli = rqf_srv = rqf_req = ~s->req->flags;
|
||||||
*/
|
rpf_cli = rpf_srv = rpf_rep = ~s->rep->flags;
|
||||||
if (unlikely(tick_is_expired(t->expire, now_ms))) {
|
|
||||||
if (tick_is_expired(s->req->rex, now_ms))
|
|
||||||
s->req->flags |= BF_READ_TIMEOUT;
|
|
||||||
|
|
||||||
//if (tick_is_expired(s->req->wex, now_ms))
|
|
||||||
// s->req->flags |= BF_WRITE_TIMEOUT;
|
|
||||||
//
|
|
||||||
//if (tick_is_expired(s->rep->rex, now_ms))
|
|
||||||
// s->rep->flags |= BF_READ_TIMEOUT;
|
|
||||||
|
|
||||||
if (tick_is_expired(s->rep->wex, now_ms))
|
|
||||||
s->rep->flags |= BF_WRITE_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (fdtab[s->cli_fd].state == FD_STERROR) {
|
|
||||||
// fprintf(stderr, "s=%p fd=%d req=%p rep=%p cs=%d ss=%d, term=%08x\n",
|
|
||||||
// s, s->cli_fd, s->req, s->rep, s->cli_state,
|
|
||||||
// s->si[1].state, s->term_trace);
|
|
||||||
// sleep(1);
|
|
||||||
//}
|
|
||||||
do {
|
do {
|
||||||
if (resync & PROCESS_REQ) {
|
resync = 0;
|
||||||
resync &= ~PROCESS_REQ;
|
|
||||||
rqf = s->req->flags;
|
|
||||||
rpf = s->rep->flags;
|
|
||||||
|
|
||||||
/* the analysers must block it themselves */
|
if (((rqf_cli ^ s->req->flags) & BF_MASK_INTERFACE_I) ||
|
||||||
s->req->flags |= BF_MAY_FORWARD;
|
((rpf_cli ^ s->rep->flags) & BF_MASK_INTERFACE_O)) {
|
||||||
|
resync = 1;
|
||||||
if (s->req->analysers) {
|
if (s->rep->cons->state != SI_ST_CLO) {
|
||||||
if (process_request(s))
|
stream_sock_process_data(s->rep->cons->fd);
|
||||||
resync |= PROCESS_REQ;
|
if (unlikely((s->rep->cons->state == SI_ST_CLO) &&
|
||||||
|
(global.mode & MODE_DEBUG) &&
|
||||||
if (rqf != s->req->flags || rpf != s->rep->flags)
|
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
|
||||||
resync |= PROCESS_ALL & ~PROCESS_REQ;
|
int len;
|
||||||
|
len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
|
||||||
|
s->uniq_id, s->be->id, (unsigned short)s->rep->cons->fd, (unsigned short)s->req->cons->fd);
|
||||||
|
write(1, trash, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rqf_cli = s->req->flags;
|
||||||
if (resync & PROCESS_RTR) {
|
rpf_cli = s->rep->flags;
|
||||||
resync &= ~PROCESS_RTR;
|
|
||||||
rqf = s->req->flags;
|
|
||||||
rpf = s->rep->flags;
|
|
||||||
|
|
||||||
/* the analysers must block it themselves */
|
|
||||||
s->rep->flags |= BF_MAY_FORWARD;
|
|
||||||
|
|
||||||
if (s->rep->analysers) {
|
|
||||||
if (process_response(s))
|
|
||||||
resync |= PROCESS_RTR;
|
|
||||||
|
|
||||||
if (rqf != s->req->flags || rpf != s->rep->flags)
|
|
||||||
resync |= PROCESS_ALL & ~PROCESS_RTR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resync & PROCESS_CLI) {
|
|
||||||
rqf = s->req->flags;
|
|
||||||
rpf = s->rep->flags;
|
|
||||||
|
|
||||||
resync &= ~PROCESS_CLI;
|
if (((rpf_srv ^ s->rep->flags) & BF_MASK_INTERFACE_I) ||
|
||||||
if (process_cli(s))
|
((rqf_srv ^ s->req->flags) & BF_MASK_INTERFACE_O)) {
|
||||||
resync |= PROCESS_CLI;
|
resync = 1;
|
||||||
|
|
||||||
if (rqf != s->req->flags || rpf != s->rep->flags)
|
|
||||||
resync |= PROCESS_ALL & ~PROCESS_CLI;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resync & PROCESS_SRV) {
|
|
||||||
rqf = s->req->flags;
|
|
||||||
rpf = s->rep->flags;
|
|
||||||
|
|
||||||
resync &= ~PROCESS_SRV;
|
|
||||||
if (s->req->cons->state != SI_ST_CLO) {
|
if (s->req->cons->state != SI_ST_CLO) {
|
||||||
if (s->req->cons->state < SI_ST_EST && s->req->flags & BF_MAY_FORWARD)
|
if (s->req->cons->state < SI_ST_EST && s->req->flags & BF_MAY_FORWARD)
|
||||||
process_srv_conn(s);
|
process_srv_conn(s);
|
||||||
@ -757,8 +704,7 @@ void process_session(struct task *t, int *next)
|
|||||||
buffer_shutw_now(s->req);
|
buffer_shutw_now(s->req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream_sock_process_data(s->req->cons->fd))
|
stream_sock_process_data(s->req->cons->fd);
|
||||||
resync |= PROCESS_SRV;
|
|
||||||
|
|
||||||
/* Count server-side errors (but not timeouts). */
|
/* Count server-side errors (but not timeouts). */
|
||||||
if (s->req->flags & BF_WRITE_ERROR) {
|
if (s->req->flags & BF_WRITE_ERROR) {
|
||||||
@ -789,12 +735,34 @@ void process_session(struct task *t, int *next)
|
|||||||
write(1, trash, len);
|
write(1, trash, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rqf != s->req->flags || rpf != s->rep->flags)
|
rqf_srv = s->req->flags;
|
||||||
resync |= PROCESS_ALL & ~PROCESS_SRV;
|
rpf_srv = s->rep->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((rqf_req ^ s->req->flags) & BF_MASK_ANALYSER) {
|
||||||
|
resync = 1;
|
||||||
|
/* the analysers must block it themselves */
|
||||||
|
s->req->flags |= BF_MAY_FORWARD;
|
||||||
|
if (s->req->analysers) {
|
||||||
|
process_request(s);
|
||||||
|
}
|
||||||
|
rqf_req = s->req->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rpf_rep ^ s->rep->flags) & BF_MASK_ANALYSER) {
|
||||||
|
resync = 1;
|
||||||
|
/* the analysers must block it themselves */
|
||||||
|
s->rep->flags |= BF_MAY_FORWARD;
|
||||||
|
|
||||||
|
if (s->rep->analysers) {
|
||||||
|
process_response(s);
|
||||||
|
}
|
||||||
|
rpf_rep = s->rep->flags;
|
||||||
|
}
|
||||||
|
|
||||||
} while (resync);
|
} while (resync);
|
||||||
|
|
||||||
if (likely(s->cli_state != CL_STCLOSE ||
|
if (likely((s->rep->cons->state != SI_ST_CLO) ||
|
||||||
(s->req->cons->state != SI_ST_CLO && s->req->cons->state != SI_ST_INI))) {
|
(s->req->cons->state != SI_ST_CLO && s->req->cons->state != SI_ST_INI))) {
|
||||||
|
|
||||||
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
|
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
|
||||||
@ -1724,7 +1692,7 @@ int process_request(struct session *t)
|
|||||||
*/
|
*/
|
||||||
if (req->flags & BF_READ_ERROR) {
|
if (req->flags & BF_READ_ERROR) {
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
t->fe->failed_req++;
|
//t->fe->failed_req++;
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
t->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(t->flags & SN_FINST_MASK))
|
||||||
@ -1879,14 +1847,12 @@ int process_request(struct session *t)
|
|||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2: have we encountered a close ? */
|
/* 2: have we encountered a read error ? */
|
||||||
else if (req->flags & (BF_READ_NULL | BF_SHUTR)) {
|
else if (req->flags & BF_READ_ERROR) {
|
||||||
txn->status = 400;
|
/* we cannot return any message on error */
|
||||||
client_retnclose(t, error_message(t, HTTP_ERR_400));
|
|
||||||
msg->msg_state = HTTP_MSG_ERROR;
|
msg->msg_state = HTTP_MSG_ERROR;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
t->fe->failed_req++;
|
//t->fe->failed_req++;
|
||||||
|
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
t->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(t->flags & SN_FINST_MASK))
|
||||||
@ -1909,12 +1875,14 @@ int process_request(struct session *t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4: have we encountered a read error ? */
|
/* 4: have we encountered a close ? */
|
||||||
else if (req->flags & BF_READ_ERROR) {
|
else if (req->flags & (BF_READ_NULL | BF_SHUTR)) {
|
||||||
/* we cannot return any message on error */
|
txn->status = 400;
|
||||||
|
client_retnclose(t, error_message(t, HTTP_ERR_400));
|
||||||
msg->msg_state = HTTP_MSG_ERROR;
|
msg->msg_state = HTTP_MSG_ERROR;
|
||||||
req->analysers = 0;
|
req->analysers = 0;
|
||||||
t->fe->failed_req++;
|
t->fe->failed_req++;
|
||||||
|
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
t->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
if (!(t->flags & SN_FINST_MASK))
|
||||||
@ -2816,18 +2784,22 @@ int process_response(struct session *t)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* write error to client, read error or close from server */
|
/* too large response does not fit in buffer. */
|
||||||
if (rep->flags & (BF_WRITE_ERROR|BF_SHUTW|BF_READ_ERROR|BF_SHUTR|BF_READ_NULL)) {
|
else if (rep->flags & BF_FULL) {
|
||||||
|
goto hdr_response_bad;
|
||||||
|
}
|
||||||
|
/* read error */
|
||||||
|
else if (rep->flags & BF_READ_ERROR) {
|
||||||
buffer_shutr_now(rep);
|
buffer_shutr_now(rep);
|
||||||
buffer_shutw_now(req);
|
buffer_shutw_now(req);
|
||||||
//fd_delete(req->cons->fd);
|
//fd_delete(req->cons->fd);
|
||||||
//req->cons->state = SI_ST_CLO;
|
//req->cons->state = SI_ST_CLO;
|
||||||
if (t->srv) {
|
//if (t->srv) {
|
||||||
//t->srv->cur_sess--;
|
//t->srv->cur_sess--;
|
||||||
t->srv->failed_resp++;
|
//t->srv->failed_resp++;
|
||||||
//sess_change_server(t, NULL);
|
//sess_change_server(t, NULL);
|
||||||
}
|
//}
|
||||||
t->be->failed_resp++;
|
//t->be->failed_resp++;
|
||||||
rep->analysers = 0;
|
rep->analysers = 0;
|
||||||
txn->status = 502;
|
txn->status = 502;
|
||||||
client_return(t, error_message(t, HTTP_ERR_502));
|
client_return(t, error_message(t, HTTP_ERR_502));
|
||||||
@ -2841,10 +2813,6 @@ int process_response(struct session *t)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* too large response does not fit in buffer. */
|
|
||||||
else if (rep->flags & BF_FULL) {
|
|
||||||
goto hdr_response_bad;
|
|
||||||
}
|
|
||||||
/* read timeout : return a 504 to the client. */
|
/* read timeout : return a 504 to the client. */
|
||||||
else if (rep->flags & BF_READ_TIMEOUT) {
|
else if (rep->flags & BF_READ_TIMEOUT) {
|
||||||
buffer_shutr_now(rep);
|
buffer_shutr_now(rep);
|
||||||
@ -2869,7 +2837,31 @@ int process_response(struct session *t)
|
|||||||
// process_srv_queue(t->srv);
|
// process_srv_queue(t->srv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* write error to client, or close from server */
|
||||||
|
else if (rep->flags & (BF_WRITE_ERROR|BF_SHUTW|BF_SHUTR|BF_READ_NULL)) {
|
||||||
|
buffer_shutr_now(rep);
|
||||||
|
buffer_shutw_now(req);
|
||||||
|
//fd_delete(req->cons->fd);
|
||||||
|
//req->cons->state = SI_ST_CLO;
|
||||||
|
if (t->srv) {
|
||||||
|
//t->srv->cur_sess--;
|
||||||
|
t->srv->failed_resp++;
|
||||||
|
//sess_change_server(t, NULL);
|
||||||
|
}
|
||||||
|
t->be->failed_resp++;
|
||||||
|
rep->analysers = 0;
|
||||||
|
txn->status = 502;
|
||||||
|
client_return(t, error_message(t, HTTP_ERR_502));
|
||||||
|
if (!(t->flags & SN_ERR_MASK))
|
||||||
|
t->flags |= SN_ERR_SRVCL;
|
||||||
|
if (!(t->flags & SN_FINST_MASK))
|
||||||
|
t->flags |= SN_FINST_H;
|
||||||
|
|
||||||
|
//if (t->srv && may_dequeue_tasks(t->srv, t->be))
|
||||||
|
// process_srv_queue(t->srv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
rep->flags &= ~BF_MAY_FORWARD;
|
rep->flags &= ~BF_MAY_FORWARD;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3192,219 +3184,219 @@ int process_response(struct session *t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
///*
|
||||||
* Manages the client FSM and its socket. It normally returns zero, but may
|
// * Manages the client FSM and its socket. It normally returns zero, but may
|
||||||
* return 1 if it absolutely wants to be called again.
|
// * return 1 if it absolutely wants to be called again.
|
||||||
*
|
// *
|
||||||
* Note: process_cli is the ONLY function allowed to set cli_state to anything
|
// * Note: process_cli is the ONLY function allowed to set cli_state to anything
|
||||||
* but CL_STCLOSE.
|
// * but CL_STCLOSE.
|
||||||
*/
|
// */
|
||||||
int process_cli(struct session *t)
|
//int process_cli(struct session *t)
|
||||||
{
|
//{
|
||||||
struct buffer *req = t->req;
|
// struct buffer *req = t->req;
|
||||||
struct buffer *rep = t->rep;
|
// struct buffer *rep = t->rep;
|
||||||
|
//
|
||||||
DPRINTF(stderr,"[%u] %s: fd=%d[%d] c=%s set(r,w)=%d,%d exp(r,w)=%u,%u req=%08x rep=%08x rql=%d rpl=%d\n",
|
// DPRINTF(stderr,"[%u] %s: fd=%d[%d] c=%s set(r,w)=%d,%d exp(r,w)=%u,%u req=%08x rep=%08x rql=%d rpl=%d\n",
|
||||||
now_ms, __FUNCTION__,
|
// now_ms, __FUNCTION__,
|
||||||
t->cli_fd, t->cli_fd >= 0 ? fdtab[t->cli_fd].state : 0, /* fd,state*/
|
// t->cli_fd, t->cli_fd >= 0 ? fdtab[t->cli_fd].state : 0, /* fd,state*/
|
||||||
cli_stnames[t->cli_state],
|
// cli_stnames[t->cli_state],
|
||||||
t->cli_fd >= 0 && fdtab[t->cli_fd].state != FD_STCLOSE ? EV_FD_ISSET(t->cli_fd, DIR_RD) : 0,
|
// t->cli_fd >= 0 && fdtab[t->cli_fd].state != FD_STCLOSE ? EV_FD_ISSET(t->cli_fd, DIR_RD) : 0,
|
||||||
t->cli_fd >= 0 && fdtab[t->cli_fd].state != FD_STCLOSE ? EV_FD_ISSET(t->cli_fd, DIR_WR) : 0,
|
// t->cli_fd >= 0 && fdtab[t->cli_fd].state != FD_STCLOSE ? EV_FD_ISSET(t->cli_fd, DIR_WR) : 0,
|
||||||
req->rex, rep->wex,
|
// req->rex, rep->wex,
|
||||||
req->flags, rep->flags,
|
// req->flags, rep->flags,
|
||||||
req->l, rep->l);
|
// req->l, rep->l);
|
||||||
|
//
|
||||||
update_state:
|
// update_state:
|
||||||
/* FIXME: we still have to check for CL_STSHUTR because client_retnclose
|
// /* FIXME: we still have to check for CL_STSHUTR because client_retnclose
|
||||||
* still set this state (and will do until unix sockets are converted).
|
// * still set this state (and will do until unix sockets are converted).
|
||||||
*/
|
// */
|
||||||
if (t->cli_state == CL_STDATA || t->cli_state == CL_STSHUTR) {
|
// if (t->cli_state == CL_STDATA || t->cli_state == CL_STSHUTR) {
|
||||||
/* we can skip most of the tests at once if some conditions are not met */
|
// /* we can skip most of the tests at once if some conditions are not met */
|
||||||
if (!((fdtab[t->cli_fd].state == FD_STERROR) ||
|
// if (!((fdtab[t->cli_fd].state == FD_STERROR) ||
|
||||||
(req->flags & (BF_READ_TIMEOUT|BF_READ_ERROR|BF_SHUTR_NOW)) ||
|
// (req->flags & (BF_READ_TIMEOUT|BF_READ_ERROR|BF_SHUTR_NOW)) ||
|
||||||
(rep->flags & (BF_WRITE_TIMEOUT|BF_WRITE_ERROR|BF_SHUTW_NOW)) ||
|
// (rep->flags & (BF_WRITE_TIMEOUT|BF_WRITE_ERROR|BF_SHUTW_NOW)) ||
|
||||||
(!(req->flags & BF_SHUTR) && req->flags & (BF_READ_NULL|BF_SHUTW)) ||
|
// (!(req->flags & BF_SHUTR) && req->flags & (BF_READ_NULL|BF_SHUTW)) ||
|
||||||
(!(rep->flags & BF_SHUTW) &&
|
// (!(rep->flags & BF_SHUTW) &&
|
||||||
(rep->flags & (BF_EMPTY|BF_MAY_FORWARD|BF_SHUTR)) == (BF_EMPTY|BF_MAY_FORWARD|BF_SHUTR))))
|
// (rep->flags & (BF_EMPTY|BF_MAY_FORWARD|BF_SHUTR)) == (BF_EMPTY|BF_MAY_FORWARD|BF_SHUTR))))
|
||||||
goto update_timeouts;
|
// goto update_timeouts;
|
||||||
|
//
|
||||||
/* read or write error */
|
// /* read or write error */
|
||||||
if (fdtab[t->cli_fd].state == FD_STERROR) {
|
// if (fdtab[t->cli_fd].state == FD_STERROR) {
|
||||||
buffer_shutr(req);
|
// buffer_shutr(req);
|
||||||
req->flags |= BF_READ_ERROR;
|
// req->flags |= BF_READ_ERROR;
|
||||||
buffer_shutw(rep);
|
// buffer_shutw(rep);
|
||||||
rep->flags |= BF_WRITE_ERROR;
|
// rep->flags |= BF_WRITE_ERROR;
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_1);
|
// trace_term(t, TT_HTTP_CLI_1);
|
||||||
if (!req->analysers) {
|
// if (!req->analysers) {
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
// if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLICL;
|
// t->flags |= SN_ERR_CLICL;
|
||||||
if (!(t->flags & SN_FINST_MASK)) {
|
// if (!(t->flags & SN_FINST_MASK)) {
|
||||||
if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
// if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
||||||
t->flags |= SN_FINST_Q;
|
// t->flags |= SN_FINST_Q;
|
||||||
else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
// else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
||||||
t->flags |= SN_FINST_C;
|
// t->flags |= SN_FINST_C;
|
||||||
else
|
// else
|
||||||
t->flags |= SN_FINST_D;
|
// t->flags |= SN_FINST_D;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
/* last read, or end of server write */
|
// /* last read, or end of server write */
|
||||||
else if (!(req->flags & BF_SHUTR) && /* not already done */
|
// else if (!(req->flags & BF_SHUTR) && /* not already done */
|
||||||
req->flags & (BF_READ_NULL|BF_SHUTR_NOW|BF_SHUTW)) {
|
// req->flags & (BF_READ_NULL|BF_SHUTR_NOW|BF_SHUTW)) {
|
||||||
buffer_shutr(req);
|
// buffer_shutr(req);
|
||||||
if (!(rep->flags & BF_SHUTW)) {
|
// if (!(rep->flags & BF_SHUTW)) {
|
||||||
EV_FD_CLR(t->cli_fd, DIR_RD);
|
// EV_FD_CLR(t->cli_fd, DIR_RD);
|
||||||
trace_term(t, TT_HTTP_CLI_2);
|
// trace_term(t, TT_HTTP_CLI_2);
|
||||||
} else {
|
// } else {
|
||||||
/* output was already closed */
|
// /* output was already closed */
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_3);
|
// trace_term(t, TT_HTTP_CLI_3);
|
||||||
}
|
// }
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
/* last server read and buffer empty : we only check them when we're
|
// /* last server read and buffer empty : we only check them when we're
|
||||||
* allowed to forward the data.
|
// * allowed to forward the data.
|
||||||
*/
|
// */
|
||||||
else if (!(rep->flags & BF_SHUTW) && /* not already done */
|
// else if (!(rep->flags & BF_SHUTW) && /* not already done */
|
||||||
((rep->flags & BF_SHUTW_NOW) ||
|
// ((rep->flags & BF_SHUTW_NOW) ||
|
||||||
(rep->flags & BF_EMPTY && rep->flags & BF_MAY_FORWARD &&
|
// (rep->flags & BF_EMPTY && rep->flags & BF_MAY_FORWARD &&
|
||||||
rep->flags & BF_SHUTR && !(t->flags & SN_SELF_GEN)))) {
|
// rep->flags & BF_SHUTR && !(t->flags & SN_SELF_GEN)))) {
|
||||||
buffer_shutw(rep);
|
// buffer_shutw(rep);
|
||||||
if (!(req->flags & BF_SHUTR)) {
|
// if (!(req->flags & BF_SHUTR)) {
|
||||||
EV_FD_CLR(t->cli_fd, DIR_WR);
|
// EV_FD_CLR(t->cli_fd, DIR_WR);
|
||||||
shutdown(t->cli_fd, SHUT_WR);
|
// shutdown(t->cli_fd, SHUT_WR);
|
||||||
trace_term(t, TT_HTTP_CLI_4);
|
// trace_term(t, TT_HTTP_CLI_4);
|
||||||
} else {
|
// } else {
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_5);
|
// trace_term(t, TT_HTTP_CLI_5);
|
||||||
}
|
// }
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
/* read timeout */
|
// /* read timeout */
|
||||||
else if ((req->flags & (BF_SHUTR|BF_READ_TIMEOUT)) == BF_READ_TIMEOUT) {
|
// else if ((req->flags & (BF_SHUTR|BF_READ_TIMEOUT)) == BF_READ_TIMEOUT) {
|
||||||
buffer_shutr(req);
|
// buffer_shutr(req);
|
||||||
if (!(rep->flags & BF_SHUTW)) {
|
// if (!(rep->flags & BF_SHUTW)) {
|
||||||
EV_FD_CLR(t->cli_fd, DIR_RD);
|
// EV_FD_CLR(t->cli_fd, DIR_RD);
|
||||||
trace_term(t, TT_HTTP_CLI_6);
|
// trace_term(t, TT_HTTP_CLI_6);
|
||||||
} else {
|
// } else {
|
||||||
/* output was already closed */
|
// /* output was already closed */
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_7);
|
// trace_term(t, TT_HTTP_CLI_7);
|
||||||
}
|
// }
|
||||||
if (!req->analysers) {
|
// if (!req->analysers) {
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
// if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLITO;
|
// t->flags |= SN_ERR_CLITO;
|
||||||
if (!(t->flags & SN_FINST_MASK)) {
|
// if (!(t->flags & SN_FINST_MASK)) {
|
||||||
if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
// if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
||||||
t->flags |= SN_FINST_Q;
|
// t->flags |= SN_FINST_Q;
|
||||||
else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
// else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
||||||
t->flags |= SN_FINST_C;
|
// t->flags |= SN_FINST_C;
|
||||||
else
|
// else
|
||||||
t->flags |= SN_FINST_D;
|
// t->flags |= SN_FINST_D;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
/* write timeout */
|
// /* write timeout */
|
||||||
else if ((rep->flags & (BF_SHUTW|BF_WRITE_TIMEOUT)) == BF_WRITE_TIMEOUT) {
|
// else if ((rep->flags & (BF_SHUTW|BF_WRITE_TIMEOUT)) == BF_WRITE_TIMEOUT) {
|
||||||
buffer_shutw(rep);
|
// buffer_shutw(rep);
|
||||||
if (!(req->flags & BF_SHUTR)) {
|
// if (!(req->flags & BF_SHUTR)) {
|
||||||
EV_FD_CLR(t->cli_fd, DIR_WR);
|
// EV_FD_CLR(t->cli_fd, DIR_WR);
|
||||||
shutdown(t->cli_fd, SHUT_WR);
|
// shutdown(t->cli_fd, SHUT_WR);
|
||||||
trace_term(t, TT_HTTP_CLI_8);
|
// trace_term(t, TT_HTTP_CLI_8);
|
||||||
} else {
|
// } else {
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_9);
|
// trace_term(t, TT_HTTP_CLI_9);
|
||||||
}
|
// }
|
||||||
if (!req->analysers) {
|
// if (!req->analysers) {
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
// if (!(t->flags & SN_ERR_MASK))
|
||||||
t->flags |= SN_ERR_CLITO;
|
// t->flags |= SN_ERR_CLITO;
|
||||||
if (!(t->flags & SN_FINST_MASK)) {
|
// if (!(t->flags & SN_FINST_MASK)) {
|
||||||
if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
// if (req->cons->err_type <= SI_ET_QUEUE_ABRT)
|
||||||
t->flags |= SN_FINST_Q;
|
// t->flags |= SN_FINST_Q;
|
||||||
else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
// else if (req->cons->err_type <= SI_ET_CONN_OTHER)
|
||||||
t->flags |= SN_FINST_C;
|
// t->flags |= SN_FINST_C;
|
||||||
else
|
// else
|
||||||
t->flags |= SN_FINST_D;
|
// t->flags |= SN_FINST_D;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
update_timeouts:
|
// update_timeouts:
|
||||||
/* manage read timeout */
|
// /* manage read timeout */
|
||||||
if (!(req->flags & BF_SHUTR)) {
|
// if (!(req->flags & BF_SHUTR)) {
|
||||||
if (req->flags & BF_FULL) {
|
// if (req->flags & BF_FULL) {
|
||||||
/* no room to read more data */
|
// /* no room to read more data */
|
||||||
if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
|
// if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
|
||||||
/* stop reading until we get some space */
|
// /* stop reading until we get some space */
|
||||||
req->rex = TICK_ETERNITY;
|
// req->rex = TICK_ETERNITY;
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
EV_FD_COND_S(t->cli_fd, DIR_RD);
|
// EV_FD_COND_S(t->cli_fd, DIR_RD);
|
||||||
req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
|
// req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* manage write timeout */
|
// /* manage write timeout */
|
||||||
if (!(rep->flags & BF_SHUTW)) {
|
// if (!(rep->flags & BF_SHUTW)) {
|
||||||
/* first, we may have to produce data (eg: stats).
|
// /* first, we may have to produce data (eg: stats).
|
||||||
* right now, this is limited to the SHUTR state.
|
// * right now, this is limited to the SHUTR state.
|
||||||
*/
|
// */
|
||||||
if (req->flags & BF_SHUTR && t->flags & SN_SELF_GEN) {
|
// if (req->flags & BF_SHUTR && t->flags & SN_SELF_GEN) {
|
||||||
produce_content(t);
|
// produce_content(t);
|
||||||
if (rep->flags & BF_EMPTY) {
|
// if (rep->flags & BF_EMPTY) {
|
||||||
buffer_shutw(rep);
|
// buffer_shutw(rep);
|
||||||
fd_delete(t->cli_fd);
|
// fd_delete(t->cli_fd);
|
||||||
t->cli_state = CL_STCLOSE;
|
// t->cli_state = CL_STCLOSE;
|
||||||
trace_term(t, TT_HTTP_CLI_10);
|
// trace_term(t, TT_HTTP_CLI_10);
|
||||||
goto update_state;
|
// goto update_state;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* we don't enable client write if the buffer is empty, nor if the server has to analyze it */
|
// /* we don't enable client write if the buffer is empty, nor if the server has to analyze it */
|
||||||
if ((rep->flags & (BF_EMPTY|BF_MAY_FORWARD)) != BF_MAY_FORWARD) {
|
// if ((rep->flags & (BF_EMPTY|BF_MAY_FORWARD)) != BF_MAY_FORWARD) {
|
||||||
if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
|
// if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
|
||||||
/* stop writing */
|
// /* stop writing */
|
||||||
rep->wex = TICK_ETERNITY;
|
// rep->wex = TICK_ETERNITY;
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
/* buffer not empty */
|
// /* buffer not empty */
|
||||||
EV_FD_COND_S(t->cli_fd, DIR_WR);
|
// EV_FD_COND_S(t->cli_fd, DIR_WR);
|
||||||
if (!tick_isset(rep->wex)) {
|
// if (!tick_isset(rep->wex)) {
|
||||||
/* restart writing */
|
// /* restart writing */
|
||||||
rep->wex = tick_add_ifset(now_ms, t->fe->timeout.client);
|
// rep->wex = tick_add_ifset(now_ms, t->fe->timeout.client);
|
||||||
if (!(req->flags & BF_SHUTR) && tick_isset(rep->wex) && tick_isset(req->rex)) {
|
// if (!(req->flags & BF_SHUTR) && tick_isset(rep->wex) && tick_isset(req->rex)) {
|
||||||
/* FIXME: to prevent the client from expiring read timeouts during writes,
|
// /* FIXME: to prevent the client from expiring read timeouts during writes,
|
||||||
* we refresh it, except if it was already infinite. */
|
// * we refresh it, except if it was already infinite. */
|
||||||
req->rex = rep->wex;
|
// req->rex = rep->wex;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return 0; /* other cases change nothing */
|
// return 0; /* other cases change nothing */
|
||||||
}
|
// }
|
||||||
else if (t->cli_state == CL_STCLOSE) { /* CL_STCLOSE: nothing to do */
|
// else if (t->cli_state == CL_STCLOSE) { /* CL_STCLOSE: nothing to do */
|
||||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
// if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||||
int len;
|
// int len;
|
||||||
len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)req->cons->fd);
|
// len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)req->cons->fd);
|
||||||
write(1, trash, len);
|
// write(1, trash, len);
|
||||||
}
|
// }
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
#ifdef DEBUG_DEV
|
//#ifdef DEBUG_DEV
|
||||||
fprintf(stderr, "FIXME !!!! impossible state at %s:%d = %d\n", __FILE__, __LINE__, t->cli_state);
|
// fprintf(stderr, "FIXME !!!! impossible state at %s:%d = %d\n", __FILE__, __LINE__, t->cli_state);
|
||||||
ABORT_NOW();
|
// ABORT_NOW();
|
||||||
#endif
|
//#endif
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
/* Return 1 if the pending connection has failed and should be retried,
|
/* Return 1 if the pending connection has failed and should be retried,
|
||||||
|
Loading…
Reference in New Issue
Block a user