goto out_close;
}
+ s->flags = 0;
+ s->analysis = 0;
+
/* if this session comes from a known monitoring system, we want to ignore
* it as soon as possible, which means closing it immediately for TCP.
*/
- s->flags = 0;
if (addr.ss_family == AF_INET &&
p->mon_mask.s_addr &&
(((struct sockaddr_in *)&addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr) {
* TCP mode there will be no header processing so any default
* backend must be assigned if set.
*/
- if (p->mode == PR_MODE_HTTP) {
- if (s->fe->tcp_req.inspect_delay)
- s->cli_state = CL_STINSPECT;
- else
- s->cli_state = CL_STHEADERS;
- } else {
- /* We must assign any default backend now since
- * there will be no header processing.
- */
- if (p->mode == PR_MODE_TCP) {
- if (p->defbe.be)
- s->be = p->defbe.be;
- s->flags |= SN_BE_ASSIGNED;
- }
- if (s->fe->tcp_req.inspect_delay)
- s->cli_state = CL_STINSPECT;
- else
- s->cli_state = CL_STDATA; /* no HTTP headers for non-HTTP proxies */
+ if (p->mode == PR_MODE_TCP) {
+ if (p->defbe.be)
+ s->be = p->defbe.be;
+ s->flags |= SN_BE_ASSIGNED;
}
+ if (p->mode == PR_MODE_HTTP)
+ s->analysis |= AN_REQ_HTTP_HDR;
+
+ if (s->fe->tcp_req.inspect_delay)
+ s->analysis |= AN_REQ_INSPECT;
+
+ s->cli_state = CL_STDATA;
s->srv_state = SV_STIDLE;
s->req = s->rep = NULL; /* will be allocated later */
if (p->mode == PR_MODE_HTTP) /* reserve some space for header rewriting */
s->req->rlim -= MAXREWRITE;
- if (s->cli_state == CL_STDATA)
+ if (!(s->analysis & AN_REQ_ANY))
s->req->flags |= BF_MAY_CONNECT; /* don't wait to establish connection */
s->req->rto = s->fe->timeout.client;
}
}
- if (s->cli_state == CL_STHEADERS && s->fe->timeout.httpreq) {
- s->txn.exp = tick_add(now_ms, s->fe->timeout.httpreq);
- t->expire = tick_first(t->expire, s->txn.exp);
- }
- else if (s->cli_state == CL_STINSPECT && s->fe->tcp_req.inspect_delay) {
- s->inspect_exp = tick_add(now_ms, s->fe->tcp_req.inspect_delay);
- t->expire = tick_first(t->expire, s->inspect_exp);
+ if (s->analysis & AN_REQ_ANY) {
+ if (s->analysis & AN_REQ_INSPECT) {
+ s->inspect_exp = tick_add_ifset(now_ms, s->fe->tcp_req.inspect_delay);
+ t->expire = tick_first(t->expire, s->inspect_exp);
+ }
+ else if (s->analysis & AN_REQ_HTTP_HDR) {
+ s->txn.exp = tick_add_ifset(now_ms, s->fe->timeout.httpreq);
+ t->expire = tick_first(t->expire, s->txn.exp);
+ }
}
if (p->mode != PR_MODE_HEALTH)
#ifdef DEBUG_FULL
-static char *cli_stnames[6] = {"INS", "HDR", "DAT", "SHR", "SHW", "CLS" };
-static char *srv_stnames[8] = {"IDL", "ANA", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
+static char *cli_stnames[4] = { "DAT", "SHR", "SHW", "CLS" };
+static char *srv_stnames[8] = { "IDL", "ANA", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
#endif
static void http_sess_log(struct session *s);
t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
tick_first(s->rep->rex, s->rep->wex));
t->expire = tick_first(t->expire, s->req->cex);
- if (s->cli_state == CL_STHEADERS)
- t->expire = tick_first(t->expire, s->txn.exp);
- else if (s->cli_state == CL_STINSPECT)
- t->expire = tick_first(t->expire, s->inspect_exp);
+ if (s->analysis & AN_REQ_ANY) {
+ if (s->analysis & AN_REQ_INSPECT)
+ t->expire = tick_first(t->expire, s->inspect_exp);
+ else if (s->analysis & AN_REQ_HTTP_HDR)
+ t->expire = tick_first(t->expire, s->txn.exp);
+ }
/* restore t to its place in the task list */
task_queue(t);
EV_FD_ISSET(t->cli_fd, DIR_RD), EV_FD_ISSET(t->cli_fd, DIR_WR),
req->rex, rep->wex);
- if (c == CL_STINSPECT) {
+ if (t->analysis & AN_REQ_INSPECT) {
struct tcp_rule *rule;
int partial;
buffer_shutw_done(rep);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
+ t->analysis &= ~AN_REQ_ANY;
t->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLICL;
buffer_shutw_done(rep);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
+ t->analysis &= ~AN_REQ_ANY;
t->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLITO;
buffer_shutw_done(rep);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
+ t->analysis &= ~AN_REQ_ANY;
t->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_PRXCOND;
}
}
- /* if we get there, it means we have no rule which matches, so
- * we apply the default accept.
+ /* if we get there, it means we have no rule which matches, or
+ * we have an explicit accept, so we apply the default accept.
*/
req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
- if (t->fe->mode == PR_MODE_HTTP) {
- t->cli_state = CL_STHEADERS;
+ t->analysis &= ~AN_REQ_INSPECT;
+ if (t->analysis & AN_REQ_HTTP_HDR)
t->txn.exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq);
- } else {
- t->cli_state = CL_STDATA;
+ else
req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
- }
+
t->inspect_exp = TICK_ETERNITY;
return 1;
}
- else if (c == CL_STHEADERS) {
+
+ if (t->analysis & AN_REQ_HTTP_HDR) {
/*
* Now parse the partial (or complete) lines.
* We will check the request syntax, and also join multi-line
buffer_shutw_done(rep);
fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE;
+ t->analysis &= ~AN_REQ_ANY;
t->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLICL;
/* read timeout : give up with an error message. */
txn->status = 408;
client_retnclose(t, error_message(t, HTTP_ERR_408));
+ t->analysis &= ~AN_REQ_ANY;
t->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLITO;
*/
req->rex = tick_add_ifset(now_ms, t->fe->timeout.client);
}
- return t->cli_state != CL_STHEADERS;
+ /* we don't need to resync if the state has not changed */
+ return !(t->analysis & AN_REQ_HTTP_HDR);
}
* of each header's length, so we can parse them quickly. *
****************************************************************/
+ t->analysis &= ~AN_REQ_HTTP_HDR;
+
/* ensure we keep this pointer to the beginning of the message */
msg->sol = req->data + msg->som;
http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx);
if (unlikely(ctx.idx && strncasecmp(ctx.line+ctx.val,"chunked",7)==0)) {
t->srv_state = SV_STANALYZE;
+ t->analysis |= AN_REQ_HTTP_BODY;
} else {
ctx.idx = 0;
http_find_header2("Content-Length", 14, msg->sol, &txn->hdr_idx, &ctx);
if ( t->be->url_param_post_limit < hint )
hint = t->be->url_param_post_limit;
/* now do we really need to buffer more data? */
- if ( len < hint )
+ if ( len < hint ) {
t->srv_state = SV_STANALYZE;
+ t->analysis |= AN_REQ_HTTP_BODY;
+ }
/* else... There are no body bytes to wait for */
}
}
* could. Let's switch to the DATA state. *
************************************************************/
- t->cli_state = CL_STDATA;
req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
-
req->rlim = req->data + BUFSIZE; /* no more rewrite needed */
t->logs.tv_request = now;
if (!(t->flags & SN_FINST_MASK))
t->flags |= SN_FINST_R;
return 1;
-
}
- else if (c == CL_STDATA) {
+
+ if (c == CL_STDATA) {
process_data:
/* FIXME: this error handling is partly buggy because we always report
* a 'DATA' phase while we don't know if the server was in IDLE, CONN
msg.len = sprintf(trash, HTTP_401_fmt, uri_auth->auth_realm);
txn->status = 401;
client_retnclose(t, &msg);
+ t->analysis &= ~AN_REQ_ANY;
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_PRXCOND;
if (!(t->flags & SN_FINST_MASK))