MEDIUM: stream/trace: Register a new trace source with its events
Runtime traces are now supported for the streams, only if compiled with
debug. process_stream() is covered as well as TCP/HTTP analyzers and filters.
In traces, the first argument is always a stream. So it is easy to get the info
about the channels and the stream-interfaces. The second argument, when defined,
is always a HTTP transaction. And the third one is an HTTP message. The trace
message is adapted to report HTTP info when possible.
diff --git a/src/backend.c b/src/backend.c
index 049a1ae..ebc5050 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -60,6 +60,8 @@
#include <proto/ssl_sock.h>
#include <proto/task.h>
+#define TRACE_SOURCE &trace_strm
+
int be_lastsession(const struct proxy *be)
{
if (be->be_counters.last_sess)
@@ -1707,14 +1709,7 @@
uint32_t addr;
char *p;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
if (s->flags & SF_ASSIGNED)
goto no_cookie;
@@ -1757,6 +1752,7 @@
no_cookie:
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 1;
}
diff --git a/src/filters.c b/src/filters.c
index f02f45b..23af163 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -33,6 +33,8 @@
#include <proto/stream.h>
#include <proto/stream_interface.h>
+#define TRACE_SOURCE &trace_strm
+
/* Pool used to allocate filters */
DECLARE_STATIC_POOL(pool_head_filter, "filter", sizeof(struct filter));
@@ -542,14 +544,17 @@
{
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
RESUME_FILTER_LOOP(s, msg->chn) {
if (FLT_OPS(filter)->http_end) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->http_end(s, filter, msg);
if (ret <= 0)
BREAK_EXECUTION(s, msg->chn, end);
}
} RESUME_FILTER_END;
end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
return ret;
}
@@ -562,10 +567,14 @@
{
struct filter *filter;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
list_for_each_entry(filter, &strm_flt(s)->filters, list) {
- if (FLT_OPS(filter)->http_reset)
+ if (FLT_OPS(filter)->http_reset) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
FLT_OPS(filter)->http_reset(s, filter, msg);
+ }
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
}
/*
@@ -577,10 +586,14 @@
{
struct filter *filter;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
list_for_each_entry(filter, &strm_flt(s)->filters, list) {
- if (FLT_OPS(filter)->http_reply)
+ if (FLT_OPS(filter)->http_reply) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
FLT_OPS(filter)->http_reply(s, filter, status, msg);
+ }
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
}
/*
@@ -600,6 +613,7 @@
unsigned int out = co_data(msg->chn);
int ret = len - out;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
list_for_each_entry(filter, &strm_flt(s)->filters, list) {
/* Call "data" filters only */
if (!IS_DATA_FILTER(filter, msg->chn))
@@ -608,6 +622,7 @@
unsigned long long *flt_off = &FLT_OFF(filter, msg->chn);
unsigned int offset = *flt_off - *strm_off;
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->http_payload(s, filter, msg, out + offset, ret - offset);
if (ret < 0)
goto end;
@@ -617,6 +632,7 @@
}
*strm_off += ret;
end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
return ret;
}
@@ -634,6 +650,8 @@
{
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+
/* If this function is called, this means there is at least one filter,
* so we do not need to check the filter list's emptiness. */
@@ -656,6 +674,7 @@
FLT_FWD(filter, chn) = 0;
if (FLT_OPS(filter)->channel_start_analyze) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->channel_start_analyze(s, filter, chn);
if (ret <= 0)
BREAK_EXECUTION(s, chn, end);
@@ -663,7 +682,9 @@
} RESUME_FILTER_END;
end:
- return handle_analyzer_result(s, chn, an_bit, ret);
+ ret = handle_analyzer_result(s, chn, an_bit, ret);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+ return ret;
}
/*
@@ -681,8 +702,11 @@
{
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+
RESUME_FILTER_LOOP(s, chn) {
if (FLT_OPS(filter)->channel_pre_analyze && (filter->pre_analyzers & an_bit)) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->channel_pre_analyze(s, filter, chn, an_bit);
if (ret <= 0)
BREAK_EXECUTION(s, chn, check_result);
@@ -690,7 +714,9 @@
} RESUME_FILTER_END;
check_result:
- return handle_analyzer_result(s, chn, 0, ret);
+ ret = handle_analyzer_result(s, chn, 0, ret);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+ return ret;
}
/*
@@ -708,14 +734,19 @@
struct filter *filter;
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+
list_for_each_entry(filter, &strm_flt(s)->filters, list) {
if (FLT_OPS(filter)->channel_post_analyze && (filter->post_analyzers & an_bit)) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->channel_post_analyze(s, filter, chn, an_bit);
if (ret < 0)
break;
}
}
- return handle_analyzer_result(s, chn, 0, ret);
+ ret = handle_analyzer_result(s, chn, 0, ret);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+ return ret;
}
/*
@@ -730,8 +761,11 @@
int ret = 1;
msg = ((chn->flags & CF_ISRESP) ? &s->txn->rsp : &s->txn->req);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
+
RESUME_FILTER_LOOP(s, chn) {
if (FLT_OPS(filter)->http_headers) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->http_headers(s, filter, msg);
if (ret <= 0)
BREAK_EXECUTION(s, chn, check_result);
@@ -740,7 +774,9 @@
channel_htx_fwd_headers(chn, htxbuf(&chn->buf));
check_result:
- return handle_analyzer_result(s, chn, an_bit, ret);
+ ret = handle_analyzer_result(s, chn, an_bit, ret);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
+ return ret;
}
/*
@@ -755,6 +791,8 @@
{
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+
/* Check if all filters attached on the stream have finished their
* processing on this channel. */
if (!(chn->flags & CF_FLT_ANALYZE))
@@ -766,6 +804,7 @@
unregister_data_filter(s, chn, filter);
if (FLT_OPS(filter)->channel_end_analyze) {
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->channel_end_analyze(s, filter, chn);
if (ret <= 0)
BREAK_EXECUTION(s, chn, end);
@@ -801,8 +840,11 @@
/* Remove backend filters from the list */
flt_stream_release(s, 1);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
}
-
+ else {
+ DBG_TRACE_DEVEL("waiting for sync", STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
+ }
return ret;
}
@@ -836,6 +878,7 @@
if (FLT_OPS(filter)->tcp_data) {
unsigned int i = ci_data(chn);
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->tcp_data(s, filter, chn);
if (ret < 0)
break;
@@ -891,6 +934,7 @@
if (FLT_OPS(filter)->tcp_forward_data) {
/* Remove bytes that the current filter considered as
* forwarded */
+ DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s);
ret = FLT_OPS(filter)->tcp_forward_data(s, filter, chn, ret - *fwd);
if (ret < 0)
goto end;
@@ -934,6 +978,8 @@
{
int ret = 1;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s);
+
/* If there is no "data" filters, we do nothing */
if (!HAS_DATA_FILTERS(s, chn))
goto end;
@@ -966,11 +1012,14 @@
}
/* Wait for data */
+ DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s);
return 0;
end:
/* Terminate the data filtering. If <ret> is negative, an error was
* encountered during the filtering. */
- return handle_analyzer_result(s, chn, an_bit, ret);
+ ret = handle_analyzer_result(s, chn, an_bit, ret);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s);
+ return ret;
}
/*
@@ -1028,11 +1077,13 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= finst;
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_FLT_ANA|STRM_EV_FLT_ERR, s);
return 0;
wait:
if (!(chn->flags & CF_ISRESP))
channel_dont_connect(chn);
+ DBG_TRACE_DEVEL("wairing for more data", STRM_EV_FLT_ANA, s);
return 0;
}
diff --git a/src/http_ana.c b/src/http_ana.c
index 715dcc7..cb9308b 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -35,6 +35,8 @@
#include <proto/stats.h>
#include <proto/vars.h>
+#define TRACE_SOURCE &trace_strm
+
extern const char *stat_status_codes[];
struct pool_head *pool_head_requri = NULL;
@@ -86,14 +88,7 @@
struct htx *htx;
struct htx_sl *sl;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&req->buf);
@@ -250,6 +245,8 @@
}
/* we're not ready yet */
+ DBG_TRACE_DEVEL("waiting for the request",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
failed_keep_alive:
@@ -265,6 +262,8 @@
s->logs.level = 0;
s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
http_reply_and_close(s, txn->status, NULL);
+ DBG_TRACE_DEVEL("leaving by closing K/A connection",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -424,6 +423,7 @@
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
return_int_err:
@@ -452,6 +452,8 @@
req->analysers &= AN_REQ_FLT_END;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -479,14 +481,7 @@
goto return_prx_yield;
}
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&req->buf);
@@ -619,6 +614,7 @@
req->analyse_exp = TICK_ETERNITY;
done_without_exp: /* done with this analyser, but dont reset the analyse_exp. */
req->analysers &= ~an_bit;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
tarpit:
@@ -689,10 +685,14 @@
req->analysers &= AN_REQ_FLT_END;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
return_prx_yield:
channel_dont_connect(req);
+ DBG_TRACE_DEVEL("waiting for more data",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -715,14 +715,7 @@
return 0;
}
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
/*
* Right now, we know that we have processed the entire headers
@@ -750,6 +743,8 @@
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_R;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
sl = http_get_stline(htx);
@@ -927,6 +922,7 @@
s->logs.tv_request = now;
/* OK let's go on with the BODY now */
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
return_bad_req: /* let's centralize all bad requests */
@@ -942,6 +938,8 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_R;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -953,6 +951,7 @@
{
struct http_txn *txn = s->txn;
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, &txn->req);
/* This connection is being tarpitted. The CLIENT side has
* already set the connect expiration date to the right
* timeout. We just have to check that the client is still
@@ -960,8 +959,12 @@
*/
channel_dont_connect(req);
if ((req->flags & (CF_SHUTR|CF_READ_ERROR)) == 0 &&
- !tick_is_expired(req->analyse_exp, now_ms))
+ !tick_is_expired(req->analyse_exp, now_ms)) {
+ DBG_TRACE_DEVEL("waiting for tarpit timeout expiry",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
+ }
+
/* We will set the queue timer to the time spent, just for
* logging purposes. We fake a 500 server error, so that the
@@ -981,6 +984,8 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_T;
+
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -1000,15 +1005,7 @@
struct http_msg *msg = &s->txn->req;
struct htx *htx;
-
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&req->buf);
@@ -1062,6 +1059,8 @@
channel_dont_connect(req);
if (!tick_isset(req->analyse_exp))
req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.httpreq);
+ DBG_TRACE_DEVEL("waiting for more data",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -1070,6 +1069,7 @@
s->logs.tv_request = now; /* update the request timer to reflect full request */
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
return_int_err:
@@ -1097,6 +1097,8 @@
_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
if (sess->listener->counters)
_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1119,14 +1121,7 @@
short status = 0;
int ret;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&req->buf);
@@ -1145,11 +1140,16 @@
* was a write error, we may recover.
*/
if (!(req->flags & (CF_READ_ERROR | CF_READ_TIMEOUT)) &&
- (s->si[1].flags & SI_FL_L7_RETRY))
+ (s->si[1].flags & SI_FL_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;
+ }
msg->msg_state = HTTP_MSG_ERROR;
http_end_request(s);
http_end_response(s);
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 1;
}
@@ -1242,6 +1242,7 @@
}
goto return_bad_req;
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
}
@@ -1262,6 +1263,8 @@
* on some systems (eg: Linux). */
channel_auto_read(req);
}
+ DBG_TRACE_DEVEL("waiting for the end of the HTTP txn",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
missing_data_or_waiting:
@@ -1296,6 +1299,8 @@
if (msg->flags & HTTP_MSGF_TE_CHNK)
req->flags |= CF_EXPECT_MORE;
+ DBG_TRACE_DEVEL("waiting for more data to forward",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
return_cli_abort:
@@ -1344,6 +1349,8 @@
s->res.analysers &= AN_RES_FLT_END; /* we're in data phase, we want to abort both directions */
if (!(s->flags & SF_FINST_MASK))
s->flags |= ((txn->rsp.msg_state < HTTP_MSG_ERROR) ? SF_FINST_H : SF_FINST_D);
+ DBG_TRACE_DEVEL("leaving on error ",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1415,14 +1422,7 @@
struct htx_sl *sl;
int n;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- rep,
- rep->rex, rep->wex,
- rep->flags,
- ci_data(rep),
- rep->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&rep->buf);
@@ -1483,8 +1483,11 @@
if (conn->err_code == CO_ER_SSL_EARLY_FAILED) {
if ((s->be->retry_type & PR_RE_EARLY_ERROR) &&
(si_b->flags & SI_FL_L7_RETRY) &&
- do_l7_retry(s, si_b) == 0)
+ do_l7_retry(s, si_b) == 0) {
+ DBG_TRACE_DEVEL("leaving on L7 retry",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
+ }
txn->status = 425;
}
@@ -1495,6 +1498,8 @@
s->flags |= SF_ERR_SRVCL;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_H;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1502,8 +1507,11 @@
else if (rep->flags & CF_READ_TIMEOUT) {
if ((si_b->flags & SI_FL_L7_RETRY) &&
(s->be->retry_type & PR_RE_TIMEOUT)) {
- if (co_data(rep) || do_l7_retry(s, si_b) == 0)
+ if (co_data(rep) || do_l7_retry(s, si_b) == 0) {
+ DBG_TRACE_DEVEL("leaving on L7 retry",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
+ }
}
_HA_ATOMIC_ADD(&s->be->be_counters.failed_resp, 1);
if (objt_server(s->target)) {
@@ -1520,6 +1528,8 @@
s->flags |= SF_ERR_SRVTO;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_H;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1540,6 +1550,8 @@
s->flags |= SF_FINST_H;
/* process_stream() will take care of the error */
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1547,8 +1559,11 @@
else if (rep->flags & CF_SHUTR) {
if ((si_b->flags & SI_FL_L7_RETRY) &&
(s->be->retry_type & PR_RE_DISCONNECTED)) {
- if (co_data(rep) || do_l7_retry(s, si_b) == 0)
+ if (co_data(rep) || do_l7_retry(s, si_b) == 0) {
+ DBG_TRACE_DEVEL("leaving on L7 retry",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
+ }
}
if (txn->flags & TX_NOT_FIRST)
@@ -1569,6 +1584,8 @@
s->flags |= SF_ERR_SRVCL;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_H;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -1586,11 +1603,15 @@
s->flags |= SF_FINST_H;
/* process_stream() will take care of the error */
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
channel_dont_close(rep);
rep->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
+ DBG_TRACE_DEVEL("waiting for more data",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -1766,6 +1787,7 @@
rep->analysers &= ~an_bit;
rep->analyse_exp = TICK_ETERNITY;
channel_auto_close(rep);
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
return_int_err:
@@ -1783,8 +1805,11 @@
}
if ((s->be->retry_type & PR_RE_JUNK_REQUEST) &&
(si_b->flags & SI_FL_L7_RETRY) &&
- do_l7_retry(s, si_b) == 0)
+ do_l7_retry(s, si_b) == 0) {
+ DBG_TRACE_DEVEL("leaving on L7 retry",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
+ }
txn->status = 502;
/* fall through */
@@ -1799,6 +1824,8 @@
s->si[1].flags |= SI_FL_NOLINGER;
rep->analysers &= AN_RES_FLT_END;
rep->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
abort_keep_alive:
@@ -1813,6 +1840,8 @@
s->logs.level = 0;
s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
http_reply_and_close(s, txn->status, NULL);
+ DBG_TRACE_DEVEL("leaving by closing K/A connection",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -1833,14 +1862,7 @@
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) /* we need more data */
return 0;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- rep,
- rep->rex, rep->wex,
- rep->flags,
- ci_data(rep),
- rep->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&rep->buf);
@@ -1893,6 +1915,8 @@
/* we need to be called again. */
if (ret == HTTP_RULE_RES_YIELD) {
channel_dont_close(rep);
+ DBG_TRACE_DEVEL("waiting for more data",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
@@ -2063,6 +2087,7 @@
s->do_log(s);
s->logs.bytes_out = 0;
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
return_bad_resp:
@@ -2082,6 +2107,8 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_H;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -2122,14 +2149,7 @@
struct htx *htx;
int ret;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- res,
- res->rex, res->wex,
- res->flags,
- ci_data(res),
- res->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
htx = htxbuf(&res->buf);
@@ -2146,6 +2166,8 @@
msg->msg_state = HTTP_MSG_ERROR;
http_end_response(s);
http_end_request(s);
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 1;
}
@@ -2232,8 +2254,11 @@
}
goto return_bad_res;
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
}
+ DBG_TRACE_DEVEL("waiting for the end of the HTTP txn",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
missing_data_or_waiting:
@@ -2274,6 +2299,8 @@
res->flags |= CF_EXPECT_MORE;
/* the stream handler will take care of timeouts and errors */
+ DBG_TRACE_DEVEL("waiting for more data to forward",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
return_srv_abort:
@@ -2316,6 +2343,8 @@
s->req.analysers &= AN_REQ_FLT_END; /* we're in data phase, we want to abort both directions */
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_D;
+ DBG_TRACE_DEVEL("leaving on error",
+ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
}
@@ -4630,10 +4659,7 @@
struct channel *chn = &s->req;
struct http_txn *txn = s->txn;
- DPRINTF(stderr,"[%u] %s: stream=%p states=%s,%s req->analysers=0x%08x res->analysers=0x%08x\n",
- now_ms, __FUNCTION__, s,
- h1_msg_state_str(txn->req.msg_state), h1_msg_state_str(txn->rsp.msg_state),
- s->req.analysers, s->res.analysers);
+ DBG_TRACE_ENTER(STRM_EV_HTTP_ANA, s, txn);
if (unlikely(txn->req.msg_state == HTTP_MSG_ERROR ||
txn->rsp.msg_state == HTTP_MSG_ERROR)) {
@@ -4642,8 +4668,10 @@
goto end;
}
- if (unlikely(txn->req.msg_state < HTTP_MSG_DONE))
+ if (unlikely(txn->req.msg_state < HTTP_MSG_DONE)) {
+ DBG_TRACE_DEVEL("waiting end of the request", STRM_EV_HTTP_ANA, s, txn);
return;
+ }
if (txn->req.msg_state == HTTP_MSG_DONE) {
/* No need to read anymore, the request was completely parsed.
@@ -4673,6 +4701,7 @@
/* The server has not finished to respond, so we
* don't want to move in order not to upset it.
*/
+ DBG_TRACE_DEVEL("waiting end of the response", STRM_EV_HTTP_ANA, s, txn);
return;
}
@@ -4686,8 +4715,10 @@
* poll for reads.
*/
channel_auto_read(chn);
- if (b_data(&chn->buf))
+ if (b_data(&chn->buf)) {
+ DBG_TRACE_DEVEL("waiting to flush the request", STRM_EV_HTTP_ANA, s, txn);
return;
+ }
txn->req.msg_state = HTTP_MSG_TUNNEL;
}
else {
@@ -4724,6 +4755,7 @@
txn->req.msg_state = HTTP_MSG_ERROR;
goto end;
}
+ DBG_TRACE_LEAVE(STRM_EV_HTTP_ANA, s, txn);
return;
}
@@ -4752,6 +4784,7 @@
chn->analysers |= AN_REQ_FLT_XFER_DATA;
channel_auto_close(chn);
channel_auto_read(chn);
+ DBG_TRACE_LEAVE(STRM_EV_HTTP_ANA, s, txn);
}
@@ -4763,10 +4796,7 @@
struct channel *chn = &s->res;
struct http_txn *txn = s->txn;
- DPRINTF(stderr,"[%u] %s: stream=%p states=%s,%s req->analysers=0x%08x res->analysers=0x%08x\n",
- now_ms, __FUNCTION__, s,
- h1_msg_state_str(txn->req.msg_state), h1_msg_state_str(txn->rsp.msg_state),
- s->req.analysers, s->res.analysers);
+ DBG_TRACE_ENTER(STRM_EV_HTTP_ANA, s, txn);
if (unlikely(txn->req.msg_state == HTTP_MSG_ERROR ||
txn->rsp.msg_state == HTTP_MSG_ERROR)) {
@@ -4775,8 +4805,10 @@
goto end;
}
- if (unlikely(txn->rsp.msg_state < HTTP_MSG_DONE))
+ if (unlikely(txn->rsp.msg_state < HTTP_MSG_DONE)) {
+ DBG_TRACE_DEVEL("waiting end of the response", STRM_EV_HTTP_ANA, s, txn);
return;
+ }
if (txn->rsp.msg_state == HTTP_MSG_DONE) {
/* In theory, we don't need to read anymore, but we must
@@ -4792,6 +4824,7 @@
* We have the choice of either breaking the connection
* or letting it pass through. Let's do the later.
*/
+ DBG_TRACE_DEVEL("waiting end of the request", STRM_EV_HTTP_ANA, s, txn);
return;
}
@@ -4803,8 +4836,10 @@
if (txn->flags & TX_CON_WANT_TUN) {
channel_auto_read(chn);
chn->flags |= CF_NEVER_WAIT;
- if (b_data(&chn->buf))
+ if (b_data(&chn->buf)) {
+ DBG_TRACE_DEVEL("waiting to flush the respone", STRM_EV_HTTP_ANA, s, txn);
return;
+ }
txn->rsp.msg_state = HTTP_MSG_TUNNEL;
}
else {
@@ -4835,6 +4870,7 @@
_HA_ATOMIC_ADD(&objt_server(s->target)->counters.cli_aborts, 1);
goto end;
}
+ DBG_TRACE_LEAVE(STRM_EV_HTTP_ANA, s, txn);
return;
}
@@ -4860,6 +4896,7 @@
chn->analysers |= AN_RES_FLT_XFER_DATA;
channel_auto_close(chn);
channel_auto_read(chn);
+ DBG_TRACE_LEAVE(STRM_EV_HTTP_ANA, s, txn);
}
void http_server_error(struct stream *s, struct stream_interface *si, int err,
diff --git a/src/stream.c b/src/stream.c
index 10d8004..8646ce8 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -74,6 +74,199 @@
static struct list service_keywords = LIST_HEAD_INIT(service_keywords);
+/* trace source and events */
+static void strm_trace(enum trace_level level, uint64_t mask,
+ const struct trace_source *src,
+ const struct ist where, const struct ist func,
+ const void *a1, const void *a2, const void *a3, const void *a4);
+
+/* The event representation is split like this :
+ * strm - stream
+ * si - stream interface
+ * http - http analyzis
+ * tcp - tcp analyzis
+ *
+ * STRM_EV_* macros are defined in <proto/stream.h>
+ */
+static const struct trace_event strm_trace_events[] = {
+ { .mask = STRM_EV_STRM_NEW, .name = "strm_new", .desc = "new stream" },
+ { .mask = STRM_EV_STRM_FREE, .name = "strm_free", .desc = "release stream" },
+ { .mask = STRM_EV_STRM_ERR, .name = "strm_err", .desc = "error during stream processing" },
+ { .mask = STRM_EV_STRM_ANA, .name = "strm_ana", .desc = "stream analyzers" },
+ { .mask = STRM_EV_STRM_PROC, .name = "strm_proc", .desc = "stream processing" },
+
+ { .mask = STRM_EV_SI_ST, .name = "si_state", .desc = "processing stream-interface states" },
+
+ { .mask = STRM_EV_HTTP_ANA, .name = "http_ana", .desc = "HTTP analyzers" },
+ { .mask = STRM_EV_HTTP_ERR, .name = "http_err", .desc = "error during HTTP analyzis" },
+
+ { .mask = STRM_EV_TCP_ANA, .name = "tcp_ana", .desc = "TCP analyzers" },
+ { .mask = STRM_EV_TCP_ERR, .name = "tcp_err", .desc = "error during TCP analyzis" },
+ {}
+};
+
+static const struct name_desc strm_trace_lockon_args[4] = {
+ /* arg1 */ { /* already used by the stream */ },
+ /* arg2 */ { },
+ /* arg3 */ { },
+ /* arg4 */ { }
+};
+
+static const struct name_desc strm_trace_decoding[] = {
+#define STRM_VERB_CLEAN 1
+ { .name="clean", .desc="only user-friendly stuff, generally suitable for level \"user\"" },
+#define STRM_VERB_MINIMAL 2
+ { .name="minimal", .desc="report info on stream and stream-interfaces" },
+#define STRM_VERB_SIMPLE 3
+ { .name="simple", .desc="add info on request and response channels" },
+#define STRM_VERB_ADVANCED 4
+ { .name="advanced", .desc="add info on channel's buffer for data and developer levels only" },
+#define STRM_VERB_COMPLETE 5
+ { .name="complete", .desc="add info on channel's buffer" },
+ { /* end */ }
+};
+
+struct trace_source trace_strm = {
+ .name = IST("stream"),
+ .desc = "Applicative stream",
+ .arg_def = TRC_ARG1_STRM, // TRACE()'s first argument is always a stream
+ .default_cb = strm_trace,
+ .known_events = strm_trace_events,
+ .lockon_args = strm_trace_lockon_args,
+ .decoding = strm_trace_decoding,
+ .report_events = ~0, // report everything by default
+};
+
+#define TRACE_SOURCE &trace_strm
+INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
+
+/* the stream traces always expect that arg1, if non-null, is of a stream (from
+ * which we can derive everything), that arg2, if non-null, is an http
+ * transaction, that arg3, if non-null, is an http message.
+ */
+static void strm_trace(enum trace_level level, uint64_t mask, const struct trace_source *src,
+ const struct ist where, const struct ist func,
+ const void *a1, const void *a2, const void *a3, const void *a4)
+{
+ const struct stream *s = a1;
+ const struct http_txn *txn = a2;
+ const struct http_msg *msg = a3;
+ struct task *task;
+ const struct stream_interface *si_f, *si_b;
+ const struct channel *req, *res;
+ struct htx *htx;
+
+ if (!s || src->verbosity < STRM_VERB_CLEAN)
+ return;
+
+ task = s->task;
+ si_f = &s->si[0];
+ si_b = &s->si[1];
+ req = &s->req;
+ res = &s->res;
+ htx = (msg ? htxbuf(&msg->chn->buf) : NULL);
+
+ /* General info about the stream (htx/tcp, id...) */
+ chunk_appendf(&trace_buf, " : [%u,%s]",
+ s->uniq_id, ((s->flags & SF_HTX) ? "HTX" : "TCP"));
+ if (s->unique_id)
+ chunk_appendf(&trace_buf, " id=%s", s->unique_id);
+
+ /* Front and back stream-int state */
+ chunk_appendf(&trace_buf, " SI=(%s,%s)",
+ si_state_str(si_f->state), si_state_str(si_b->state));
+
+ /* If txn is defined, HTTP req/rep states */
+ if (txn)
+ chunk_appendf(&trace_buf, " HTTP=(%s,%s)",
+ h1_msg_state_str(txn->req.msg_state), h1_msg_state_str(txn->rsp.msg_state));
+ if (msg)
+ chunk_appendf(&trace_buf, " %s", ((msg->chn->flags & CF_ISRESP) ? "RESPONSE" : "REQUEST"));
+
+ if (src->verbosity == STRM_VERB_CLEAN)
+ return;
+
+ /* If msg defined, display status-line if possible (verbosity > MINIMAL) */
+ if (src->verbosity > STRM_VERB_MINIMAL && htx && htx_nbblks(htx)) {
+ const struct htx_blk *blk = htx_get_head_blk(htx);
+ const struct htx_sl *sl = htx_get_blk_ptr(htx, blk);
+ enum htx_blk_type type = htx_get_blk_type(blk);
+
+ if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL)
+ chunk_appendf(&trace_buf, " - \"%.*s %.*s %.*s\"",
+ HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl),
+ HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl),
+ HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
+ }
+
+
+ /* If txn defined info about HTTP msgs, otherwise info about SI. */
+ if (txn) {
+ chunk_appendf(&trace_buf, " - t=%p s=(%p,0x%08x) txn.flags=0x%08x, http.flags=(0x%08x,0x%08x) status=%d",
+ task, s, s->flags, txn->flags, txn->req.flags, txn->rsp.flags, txn->status);
+ }
+ else {
+ chunk_appendf(&trace_buf, " - t=%p s=(%p,0x%08x) si_f=(%p,0x%08x,0x%x) si_b=(%p,0x%08x,0x%x) retries=%d",
+ task, s, s->flags, si_f, si_f->flags, si_f->err_type,
+ si_b, si_b->flags, si_b->err_type, si_b->conn_retries);
+ }
+
+ if (src->verbosity == STRM_VERB_MINIMAL)
+ return;
+
+
+ /* If txn defined, don't display all channel info */
+ if (src->verbosity == STRM_VERB_SIMPLE || txn) {
+ chunk_appendf(&trace_buf, " req=(%p .fl=0x%08x .exp(r,w,a)=(%u,%u,%u))",
+ req, req->flags, req->rex, req->wex, req->analyse_exp);
+ chunk_appendf(&trace_buf, " res=(%p .fl=0x%08x .exp(r,w,a)=(%u,%u,%u))",
+ res, res->flags, res->rex, res->wex, res->analyse_exp);
+ }
+ else {
+ chunk_appendf(&trace_buf, " req=(%p .fl=0x%08x .ana=0x%08x .exp(r,w,a)=(%u,%u,%u) .o=%lu .tot=%llu .to_fwd=%u)",
+ req, req->flags, req->analysers, req->rex, req->wex, req->analyse_exp,
+ req->output, req->total, req->to_forward);
+ chunk_appendf(&trace_buf, " res=(%p .fl=0x%08x .ana=0x%08x .exp(r,w,a)=(%u,%u,%u) .o=%lu .tot=%llu .to_fwd=%u)",
+ res, res->flags, res->analysers, res->rex, res->wex, res->analyse_exp,
+ res->output, res->total, res->to_forward);
+ }
+
+ if (src->verbosity == STRM_VERB_SIMPLE ||
+ (src->verbosity == STRM_VERB_ADVANCED && src->level < TRACE_LEVEL_DATA))
+ return;
+
+ /* channels' buffer info */
+ if (s->flags & SF_HTX) {
+ struct htx *rqhtx = htxbuf(&req->buf);
+ struct htx *rphtx = htxbuf(&res->buf);
+
+ chunk_appendf(&trace_buf, " htx=(%u/%u#%u, %u/%u#%u)",
+ rqhtx->data, rqhtx->size, htx_nbblks(rqhtx),
+ rphtx->data, rphtx->size, htx_nbblks(rphtx));
+ }
+ else {
+ chunk_appendf(&trace_buf, " buf=(%u@%p+%u/%u, %u@%p+%u/%u)",
+ (unsigned int)b_data(&req->buf), b_orig(&req->buf),
+ (unsigned int)b_head_ofs(&req->buf), (unsigned int)b_size(&req->buf),
+ (unsigned int)b_data(&req->buf), b_orig(&req->buf),
+ (unsigned int)b_head_ofs(&req->buf), (unsigned int)b_size(&req->buf));
+ }
+
+ /* If msg defined, display htx info if defined (level > USER) */
+ if (src->level > TRACE_LEVEL_USER && htx && htx_nbblks(htx)) {
+ int full = 0;
+
+ /* Full htx info (level > STATE && verbosity > SIMPLE) */
+ if (src->level > TRACE_LEVEL_STATE) {
+ if (src->verbosity == STRM_VERB_COMPLETE)
+ full = 1;
+ }
+
+ chunk_memcat(&trace_buf, "\n\t", 2);
+ htx_dump(&trace_buf, htx, full);
+ }
+}
+
/* Create a new stream for connection <conn>. Return < 0 on error. This is only
* valid right after the handshake, before the connection's data layer is
* initialized, because it relies on the session to be in conn->owner.
@@ -132,6 +325,7 @@
struct appctx *appctx = objt_appctx(origin);
const struct cs_info *csinfo;
+ DBG_TRACE_ENTER(STRM_EV_STRM_NEW);
if (unlikely((s = pool_alloc(pool_head_stream)) == NULL))
goto out_fail_alloc;
@@ -338,6 +532,7 @@
* stream is fully initialized before calling task_wakeup. So
* the caller must handle the task_wakeup
*/
+ DBG_TRACE_LEAVE(STRM_EV_STRM_NEW, s);
return s;
/* Error unrolling */
@@ -350,6 +545,7 @@
tasklet_free(s->si[0].wait_event.tasklet);
out_fail_alloc:
pool_free(pool_head_stream, s);
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_NEW|STRM_EV_STRM_ERR);
return NULL;
}
@@ -365,6 +561,8 @@
int must_free_sess;
int i;
+ DBG_TRACE_POINT(STRM_EV_STRM_FREE, s);
+
/* detach the stream from its own task before even releasing it so
* that walking over a task list never exhibits a dying stream.
*/
@@ -663,6 +861,8 @@
struct conn_stream *srv_cs = objt_cs(si->end);
struct connection *conn = srv_cs ? srv_cs->conn : objt_conn(si->end);
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+
/* the client might want to abort */
if ((rep->flags & CF_SHUTW) ||
((req->flags & CF_SHUTW_NOW) &&
@@ -673,11 +873,11 @@
if (s->srv_error)
s->srv_error(s, si);
/* Note: state = SI_ST_DIS now */
- return;
+ DBG_TRACE_STATE("client abort during connection attempt", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
}
/* retryable error ? */
- if (si->flags & (SI_FL_EXP|SI_FL_ERR)) {
+ else if (si->flags & (SI_FL_EXP|SI_FL_ERR)) {
if (!(s->flags & SF_SRV_REUSED) && conn) {
conn_stop_tracking(conn);
conn_full_close(conn);
@@ -691,8 +891,10 @@
}
si->state = SI_ST_CER;
- return;
+ DBG_TRACE_STATE("connection failed, retry", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
}
+
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
/* This function is called with (si->state == SI_ST_CER) meaning that a
@@ -710,6 +912,8 @@
struct conn_stream *cs = objt_cs(si->end);
struct connection *conn = cs_conn(cs);
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+
si->exp = TICK_ETERNITY;
si->flags &= ~SI_FL_EXP;
@@ -741,6 +945,7 @@
* client provoke retries.
*/
si->conn_retries = 0;
+ DBG_TRACE_DEVEL("Bad SSL cert, disable connection retries", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
}
}
@@ -766,7 +971,9 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
- return;
+
+ DBG_TRACE_STATE("connection failed", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
stream_choose_redispatch(s);
@@ -796,7 +1003,11 @@
si->exp = tick_add(now_ms, MS_TO_TICKS(delay));
}
si->flags &= ~SI_FL_ERR;
+ DBG_TRACE_STATE("retry a new connection", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
+
+ end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
/* This function is called with (si->state == SI_ST_RDY) meaning that a
@@ -814,6 +1025,7 @@
struct conn_stream *srv_cs = objt_cs(si->end);
struct connection *conn = srv_cs ? srv_cs->conn : objt_conn(si->end);
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
/* We know the connection at least succeeded, though it could have
* since met an error for any other reason. At least it didn't time out
* eventhough the timeout might have been reported right after success.
@@ -843,7 +1055,8 @@
si->err_type |= SI_ET_CONN_ABRT;
if (s->srv_error)
s->srv_error(s, si);
- return;
+ DBG_TRACE_STATE("client abort during connection attempt", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
/* retryable error ? */
@@ -856,15 +1069,20 @@
if (!si->err_type)
si->err_type = SI_ET_CONN_ERR;
si->state = SI_ST_CER;
- return;
+ DBG_TRACE_STATE("connection failed, retry", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
}
/* data were sent and/or we had no error, sess_establish() will
* now take over.
*/
+ DBG_TRACE_STATE("connection established", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
si->err_type = SI_ET_NONE;
si->state = SI_ST_EST;
+
+ end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
/*
@@ -887,6 +1105,7 @@
struct channel *req = &s->req;
struct channel *rep = &s->res;
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
/* First, centralize the timers information, and clear any irrelevant
* timeout.
*/
@@ -905,6 +1124,7 @@
req->flags |= CF_WRITE_ERROR;
rep->flags |= CF_READ_ERROR;
si->err_type = SI_ET_DATA_ERR;
+ DBG_TRACE_STATE("read/write error", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
}
if (objt_server(s->target))
@@ -946,8 +1166,12 @@
req->wex = TICK_ETERNITY;
/* If we managed to get the whole response, and we don't have anything
* left to send, or can't, switch to SI_ST_DIS now. */
- if (rep->flags & (CF_SHUTR | CF_SHUTW))
+ if (rep->flags & (CF_SHUTR | CF_SHUTW)) {
si->state = SI_ST_DIS;
+ DBG_TRACE_STATE("response channel shutdwn for read/write", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ }
+
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
/* Check if the connection request is in such a state that it can be aborted. */
@@ -970,13 +1194,7 @@
struct stream_interface *si = &s->si[1];
struct channel *req = &s->req;
- DPRINTF(stderr,"[%u] %s: sess=%p rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%lu rqt=%lu rph=%lu rpt=%lu cs=%d ss=%d\n",
- now_ms, __FUNCTION__,
- s,
- req, &s->res,
- req->rex, s->res.wex,
- req->flags, s->res.flags,
- ci_data(req), co_data(req), ci_data(&s->res), co_data(&s->res), s->si[0].state, s->si[1].state);
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
if (si->state == SI_ST_ASS) {
/* Server assigned to connection request, we have to try to connect now */
@@ -987,6 +1205,7 @@
*/
if (check_req_may_abort(req, s)) {
si->err_type |= SI_ET_CONN_ABRT;
+ DBG_TRACE_STATE("connection aborted", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
goto abort_connection;
}
@@ -999,7 +1218,8 @@
srv_inc_sess_ctr(srv);
if (srv)
srv_set_sess_last(srv);
- return;
+ DBG_TRACE_STATE("connection attempt", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+ goto end;
}
/* We have received a synchronous error. We might have to
@@ -1037,7 +1257,8 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
- return;
+ DBG_TRACE_STATE("internal error during connection", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
/* We are facing a retryable error, but we don't want to run a
@@ -1047,8 +1268,9 @@
si->state = SI_ST_CER;
si->flags &= ~SI_FL_ERR;
sess_update_st_cer(s);
+
+ DBG_TRACE_STATE("connection error, retry", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
/* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
- return;
}
else if (si->state == SI_ST_QUE) {
/* connection request was queued, check for any update */
@@ -1065,7 +1287,8 @@
s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
si->state = SI_ST_ASS;
}
- return;
+ DBG_TRACE_STATE("dequeue connection request", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+ goto end;
}
/* Connection request still in queue... */
@@ -1089,7 +1312,8 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
- return;
+ DBG_TRACE_STATE("connection request still queued", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+ goto end;
}
/* Connection remains in queue, check if we have to abort it */
@@ -1100,16 +1324,17 @@
pendconn_cond_unlink(s->pend_pos);
si->err_type |= SI_ET_QUEUE_ABRT;
+ DBG_TRACE_STATE("abort queued connection request", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
goto abort_connection;
}
/* Nothing changed */
- return;
}
else if (si->state == SI_ST_TAR) {
/* Connection request might be aborted */
if (check_req_may_abort(req, s)) {
si->err_type |= SI_ET_CONN_ABRT;
+ DBG_TRACE_STATE("connection aborted", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
goto abort_connection;
}
@@ -1127,8 +1352,12 @@
si->state = SI_ST_ASS;
else
si->state = SI_ST_REQ;
- return;
+
+ DBG_TRACE_STATE("retry connection now", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
+
+ end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
return;
abort_connection:
@@ -1140,6 +1369,7 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
return;
}
@@ -1179,17 +1409,11 @@
{
struct stream_interface *si = &s->si[1];
- DPRINTF(stderr,"[%u] %s: sess=%p rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%lu rqt=%lu rph=%lu rpt=%lu cs=%d ss=%d\n",
- now_ms, __FUNCTION__,
- s,
- &s->req, &s->res,
- s->req.rex, s->res.wex,
- s->req.flags, s->res.flags,
- ci_data(&s->req), co_data(&s->req), ci_data(&s->res), co_data(&s->res), s->si[0].state, s->si[1].state);
-
if (si->state != SI_ST_REQ)
return;
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+
if (unlikely(obj_type(s->target) == OBJ_TYPE_APPLET)) {
/* the applet directly goes to the EST state */
struct appctx *appctx = objt_appctx(si->end);
@@ -1211,7 +1435,8 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
- return;
+ DBG_TRACE_STATE("failed to register applet", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
if (tv_iszero(&s->logs.tv_request))
@@ -1220,8 +1445,10 @@
si->state = SI_ST_EST;
si->err_type = SI_ET_NONE;
be_set_sess_last(s->be);
+
+ DBG_TRACE_STATE("applet registered", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
/* let sess_establish() finish the job */
- return;
+ goto end;
}
/* Try to assign a server */
@@ -1229,8 +1456,10 @@
/* We did not get a server. Either we queued the
* connection request, or we encountered an error.
*/
- if (si->state == SI_ST_QUE)
- return;
+ if (si->state == SI_ST_QUE) {
+ DBG_TRACE_STATE("connection request queued", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+ goto end;
+ }
/* we did not get any server, let's check the cause */
si_shutr(si);
@@ -1241,13 +1470,18 @@
si->state = SI_ST_CLO;
if (s->srv_error)
s->srv_error(s, si);
- return;
+ DBG_TRACE_STATE("connection request failed", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
}
/* The server is assigned */
s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
si->state = SI_ST_ASS;
be_set_sess_last(s->be);
+ DBG_TRACE_STATE("connection request assigned to a server", STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
+
+ end:
+ DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}
/* This function parses the use-service action ruleset. It executes
@@ -1320,14 +1554,7 @@
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
/* now check whether we have some switching rules for this request */
if (!(s->flags & SF_BE_ASSIGNED)) {
@@ -1416,6 +1643,7 @@
}
}
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
return 1;
sw_failed:
@@ -1432,6 +1660,7 @@
s->txn->status = 500;
s->req.analysers &= AN_REQ_FLT_END;
s->req.analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_ANA|STRM_EV_STRM_ERR, s);
return 0;
}
@@ -1445,14 +1674,7 @@
struct session *sess = s->sess;
struct server_rule *rule;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- c_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
if (!(s->flags & SF_ASSIGNED)) {
list_for_each_entry(rule, &px->server_rules, list) {
@@ -1482,6 +1704,7 @@
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
return 1;
}
@@ -1538,14 +1761,7 @@
struct session *sess = s->sess;
struct sticking_rule *rule;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
list_for_each_entry(rule, &px->sticking_rules, list) {
int ret = 1 ;
@@ -1605,6 +1821,7 @@
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
return 1;
}
@@ -1620,14 +1837,7 @@
int i;
int nbreq = s->store_count;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- rep,
- rep->rex, rep->wex,
- rep->flags,
- ci_data(rep),
- rep->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
list_for_each_entry(rule, &px->storersp_rules, list) {
int ret = 1 ;
@@ -1717,6 +1927,8 @@
rep->analysers &= ~an_bit;
rep->analyse_exp = TICK_ETERNITY;
+
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
return 1;
}
@@ -1788,6 +2000,8 @@
struct stream_interface *si_f, *si_b;
unsigned int rate;
+ DBG_TRACE_ENTER(STRM_EV_STRM_PROC, s);
+
activity[tid].stream++;
req = &s->req;
@@ -1805,9 +2019,6 @@
stream_dump_and_crash(&s->obj_type, read_freq_ctr(&s->call_rate));
}
- //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
- // si_f->state, si_b->state, si_b->err_type, req->flags, res->flags);
-
/* this data may be no longer valid, clear it */
if (s->txn)
memset(&s->txn->auth, 0, sizeof(s->txn->auth));
@@ -1972,18 +2183,7 @@
rp_prod_last = si_b->state;
/* Check for connection closure */
-
- DPRINTF(stderr,
- "[%u] %s:%d: task=%p s=%p, sfl=0x%08x, rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%lu rqt=%lu rph=%lu rpt=%lu cs=%d ss=%d, cet=0x%x set=0x%x retr=%d\n",
- now_ms, __FUNCTION__, __LINE__,
- t,
- s, s->flags,
- req, res,
- req->rex, res->wex,
- req->flags, res->flags,
- ci_data(req), co_data(req), ci_data(res), co_data(res), si_f->state, si_b->state,
- si_f->err_type, si_b->err_type,
- si_b->conn_retries);
+ DBG_TRACE_POINT(STRM_EV_STRM_PROC, s);
/* nothing special to be done on client side */
if (unlikely(si_f->state == SI_ST_DIS))
@@ -2650,17 +2850,15 @@
if (si_b->exp)
t->expire = tick_first(t->expire, si_b->exp);
- DPRINTF(stderr,
- "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
- " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
- now_ms, t->expire, req->rex, req->wex, req->analyse_exp,
- res->rex, res->wex, si_f->exp, si_b->exp, si_f->state, si_b->state);
-
s->pending_events &= ~(TASK_WOKEN_TIMER | TASK_WOKEN_RES);
stream_release_buffers(s);
+
+ DBG_TRACE_DEVEL("queuing", STRM_EV_STRM_PROC, s);
return t; /* nothing more to do */
}
+ DBG_TRACE_DEVEL("releasing", STRM_EV_STRM_PROC, s);
+
if (s->flags & SF_BE_ASSIGNED)
_HA_ATOMIC_SUB(&s->be->beconn, 1);
diff --git a/src/tcp_rules.c b/src/tcp_rules.c
index 99af7c7..86b4df5 100644
--- a/src/tcp_rules.c
+++ b/src/tcp_rules.c
@@ -36,6 +36,8 @@
#include <proto/stream_interface.h>
#include <proto/tcp_rules.h>
+#define TRACE_SOURCE &trace_strm
+
/* List head of all known action keywords for "tcp-request connection" */
struct list tcp_req_conn_keywords = LIST_HEAD_INIT(tcp_req_conn_keywords);
struct list tcp_req_sess_keywords = LIST_HEAD_INIT(tcp_req_sess_keywords);
@@ -104,14 +106,7 @@
int partial;
int act_flags = 0;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- req,
- req->rex, req->wex,
- req->flags,
- ci_data(req),
- req->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
/* We don't know whether we have enough data, so must proceed
* this way :
@@ -177,6 +172,7 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_R;
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_TCP_ERR, s);
return 0;
}
else if (rule->action >= ACT_ACTION_TRK_SC0 && rule->action <= ACT_ACTION_TRK_SCMAX) {
@@ -258,6 +254,7 @@
*/
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 1;
missing_data:
@@ -265,6 +262,7 @@
/* just set the request timeout once at the beginning of the request */
if (!tick_isset(req->analyse_exp) && s->be->tcp_req.inspect_delay)
req->analyse_exp = tick_add(now_ms, s->be->tcp_req.inspect_delay);
+ DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 0;
}
@@ -282,14 +280,7 @@
int partial;
int act_flags = 0;
- DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
- now_ms, __FUNCTION__,
- s,
- rep,
- rep->rex, rep->wex,
- rep->flags,
- ci_data(rep),
- rep->analysers);
+ DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
/* We don't know whether we have enough data, so must proceed
* this way :
@@ -328,6 +319,7 @@
/* just set the analyser timeout once at the beginning of the response */
if (!tick_isset(rep->analyse_exp) && s->be->tcp_rep.inspect_delay)
rep->analyse_exp = tick_add(now_ms, s->be->tcp_rep.inspect_delay);
+ DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 0;
}
@@ -358,6 +350,7 @@
s->flags |= SF_ERR_PRXCOND;
if (!(s->flags & SF_FINST_MASK))
s->flags |= SF_FINST_D;
+ DBG_TRACE_DEVEL("leaving on error", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA|STRM_EV_TCP_ERR, s);
return 0;
}
else if (rule->action == ACT_TCP_CLOSE) {
@@ -385,6 +378,7 @@
case ACT_RET_YIELD:
channel_dont_close(rep);
s->current_rule = rule;
+ DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 0;
}
break; /* ACT_RET_STOP/DONE */
@@ -397,6 +391,7 @@
*/
rep->analysers &= ~an_bit;
rep->analyse_exp = TICK_ETERNITY;
+ DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s);
return 1;
}