SHOW_FLAG(f, SI_FL_RXBLK_SHUT);
SHOW_FLAG(f, SI_FL_RXBLK_CONN);
SHOW_FLAG(f, SI_FL_RX_WAIT_EP);
- SHOW_FLAG(f, SI_FL_L7_RETRY);
- SHOW_FLAG(f, SI_FL_D_L7_RETRY);
SHOW_FLAG(f, SI_FL_ADDR_FROM_SET);
SHOW_FLAG(f, SI_FL_ADDR_TO_SET);
return;
}
+ SHOW_FLAG(f, TX_L7_RETRY);
+ SHOW_FLAG(f, TX_D_L7_RETRY);
SHOW_FLAG(f, TX_NOT_FIRST);
SHOW_FLAG(f, TX_USE_PX_CONN);
SHOW_FLAG(f, TX_CACHE_HAS_SEC_KEY);
/* used only for keep-alive purposes, to indicate we're on a second transaction */
#define TX_NOT_FIRST 0x00040000 /* the transaction is not the first one */
+#define TX_L7_RETRY 0x000800000 /* The transaction may attempt L7 retries */
+#define TX_D_L7_RETRY 0x001000000 /* Disable L7 retries on this transaction, even if configured to do it */
/*
* HTTP message status flags (msg->flags)
*/
/* 1 unused byte here */
short status; /* HTTP status from the server, negative if from proxy */
struct http_reply *http_reply; /* The HTTP reply to use as reply */
-
+ struct buffer l7_buffer; /* To store the data, in case we have to retry */
char cache_hash[20]; /* Store the cache hash */
char cache_secondary_hash[HTTP_CACHE_SEC_KEY_LEN]; /* Optional cache secondary key. */
char *uri; /* first line if log needed, NULL otherwise */
SI_FL_RXBLK_CONN = 0x00100000, /* other side is not connected */
SI_FL_RXBLK_ANY = 0x001F0000, /* any of the RXBLK flags above */
SI_FL_RX_WAIT_EP = 0x00200000, /* stream-int waits for more data from the end point */
- SI_FL_L7_RETRY = 0x01000000, /* The stream interface may attempt L7 retries */
- SI_FL_D_L7_RETRY = 0x02000000, /* Disable L7 retries on this stream interface, even if configured to do it */
+ /* unused: 0x01000000, 0x02000000 */
SI_FL_ADDR_FROM_SET = 0x04000000, /* source address is set */
SI_FL_ADDR_TO_SET = 0x08000000 /* destination address is set */
unsigned int hcto; /* half-closed timeout (0 = unset) */
struct wait_event wait_event; /* We're in a wait list */
- struct buffer l7_buffer; /* To store the data, in case we have to retry */
};
/* operations available on a stream-interface */
si->cs = NULL;
si->state = si->prev_state = SI_ST_INI;
si->ops = &si_embedded_ops;
- si->l7_buffer = BUF_NULL;
si->wait_event.tasklet = tasklet_new();
if (!si->wait_event.tasklet)
return -1;
/* This function executes the "disable-l7-retry" HTTP action.
* It disables L7 retries (all retry except for a connection failure). This
* can be useful for example to avoid retrying on POST requests.
- * It just removes the L7 retry flag on the stream_interface, and always
+ * It just removes the L7 retry flag on the HTTP transaction, and always
* return ACT_RET_CONT;
*/
static enum act_return http_req_disable_l7_retry(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{
- struct stream_interface *si = cs_si(s->csb);
-
- /* In theory, the SI_FL_L7_RETRY flags isn't set at this point, but
+ /* In theory, the TX_L7_RETRY flags isn't set at this point, but
* let's be future-proof and remove it anyway.
*/
- si->flags &= ~SI_FL_L7_RETRY;
- si->flags |= SI_FL_D_L7_RETRY;
+ s->txn->flags &= ~TX_L7_RETRY;
+ s->txn->flags |= TX_D_L7_RETRY;
return ACT_RET_CONT;
}
* was a write error, we may recover.
*/
if (!(req->flags & (CF_READ_ERROR | CF_READ_TIMEOUT)) &&
- (cs_si(s->csb)->flags & SI_FL_L7_RETRY)) {
+ (txn->flags & TX_L7_RETRY)) {
DBG_TRACE_DEVEL("leaving on L7 retry",
STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
b_free(&req->buf);
/* Swap the L7 buffer with the channel buffer */
/* We know we stored the co_data as b_data, so get it there */
- co_data = b_data(&si->l7_buffer);
- b_set_data(&si->l7_buffer, b_size(&si->l7_buffer));
- b_xfer(&req->buf, &si->l7_buffer, b_data(&si->l7_buffer));
+ co_data = b_data(&s->txn->l7_buffer);
+ b_set_data(&s->txn->l7_buffer, b_size(&s->txn->l7_buffer));
+ b_xfer(&req->buf, &s->txn->l7_buffer, b_data(&s->txn->l7_buffer));
co_set_data(req, co_data);
DBG_TRACE_DEVEL("perform a L7 retry", STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, s->txn);
struct connection *conn = cs_conn(s->csb);
/* Perform a L7 retry because server refuses the early data. */
- if ((si_b->flags & SI_FL_L7_RETRY) &&
+ if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_EARLY_ERROR) &&
conn && conn->err_code == CO_ER_SSL_EARLY_FAILED &&
do_l7_retry(s, si_b) == 0) {
/* 2: read timeout : return a 504 to the client. */
else if (rep->flags & CF_READ_TIMEOUT) {
- if ((si_b->flags & SI_FL_L7_RETRY) &&
+ if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_TIMEOUT)) {
if (co_data(rep) || do_l7_retry(s, si_b) == 0) {
DBG_TRACE_DEVEL("leaving on L7 retry",
/* 4: close from server, capture the response if the server has started to respond */
else if (rep->flags & CF_SHUTR) {
- if ((si_b->flags & SI_FL_L7_RETRY) &&
+ if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_DISCONNECTED)) {
if (co_data(rep) || do_l7_retry(s, si_b) == 0) {
DBG_TRACE_DEVEL("leaving on L7 retry",
sl = http_get_stline(htx);
/* Perform a L7 retry because of the status code */
- if ((si_b->flags & SI_FL_L7_RETRY) &&
+ if ((txn->flags & TX_L7_RETRY) &&
l7_status_match(s->be, sl->info.res.status) &&
do_l7_retry(s, si_b) == 0) {
DBG_TRACE_DEVEL("leaving on L7 retry", STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
}
/* Now, L7 buffer is useless, it can be released */
- b_free(&(cs_si(s->csb)->l7_buffer));
+ b_free(&txn->l7_buffer);
msg->msg_state = HTTP_MSG_BODY;
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
}
if ((s->be->retry_type & PR_RE_JUNK_REQUEST) &&
- (si_b->flags & SI_FL_L7_RETRY) &&
+ (txn->flags & TX_L7_RETRY) &&
do_l7_retry(s, si_b) == 0) {
DBG_TRACE_DEVEL("leaving on L7 retry",
STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
txn->flags = ((cs && cs->endp->flags & CS_EP_NOT_FIRST) ? TX_NOT_FIRST : 0);
txn->status = -1;
txn->http_reply = NULL;
+ txn->l7_buffer = BUF_NULL;
write_u32(txn->cache_hash, 0);
txn->cookie_first_date = 0;
if (!LIST_ISEMPTY(&s->vars_reqres.head))
vars_prune(&s->vars_reqres, s->sess, s);
+ b_free(&txn->l7_buffer);
+
pool_free(pool_head_http_txn, txn);
s->txn = NULL;
}
si_b->conn_retries = s->be->conn_retries;
if ((s->be->retry_type &~ PR_RE_CONN_FAILED) &&
(s->be->mode == PR_MODE_HTTP) &&
- !(si_b->flags & SI_FL_D_L7_RETRY))
- si_b->flags |= SI_FL_L7_RETRY;
+ !(s->txn->flags & TX_D_L7_RETRY))
+ s->txn->flags |= TX_L7_RETRY;
}
}
else {
if (!si)
return;
- b_free(&si->l7_buffer);
tasklet_free(si->wait_event.tasklet);
sockaddr_free(&si->src);
sockaddr_free(&si->dst);
{
struct connection *conn = __cs_conn(cs);
struct stream_interface *si = cs_si(cs);
+ struct stream *s = si_strm(si);
struct channel *oc = si_oc(si);
int ret;
int did_send = 0;
if (oc->flags & CF_STREAMER)
send_flag |= CO_SFL_STREAMER;
- if ((si->flags & SI_FL_L7_RETRY) && !b_data(&si->l7_buffer)) {
- struct stream *s = si_strm(si);
+ if (s->txn && s->txn->flags & TX_L7_RETRY && !b_data(&s->txn->l7_buffer)) {
/* If we want to be able to do L7 retries, copy
* the data we're about to send, so that we are able
* to resend them if needed
* disable the l7 retries by setting
* l7_conn_retries to 0.
*/
- if (!s->txn || (s->txn->req.msg_state != HTTP_MSG_DONE))
- si->flags &= ~SI_FL_L7_RETRY;
+ if (s->txn->req.msg_state != HTTP_MSG_DONE)
+ s->txn->flags &= ~TX_L7_RETRY;
else {
- if (b_alloc(&si->l7_buffer) == NULL)
- si->flags &= ~SI_FL_L7_RETRY;
+ if (b_alloc(&s->txn->l7_buffer) == NULL)
+ s->txn->flags &= ~TX_L7_RETRY;
else {
- memcpy(b_orig(&si->l7_buffer),
+ memcpy(b_orig(&s->txn->l7_buffer),
b_orig(&oc->buf),
b_size(&oc->buf));
- si->l7_buffer.head = co_data(oc);
- b_add(&si->l7_buffer, co_data(oc));
+ s->txn->l7_buffer.head = co_data(oc);
+ b_add(&s->txn->l7_buffer, co_data(oc));
}
}