when an health-check is performed if it makes sense and if the sample fetch was
adapted to be called in this context.
-check.payload(<offset>,<length>) : binary
- This extracts a binary block of <length> bytes and starting at byte <offset>
- in the check input buffer. As a special case, if the <length> argument is
- zero, then the whole buffer from <offset> to the end is extracted. This can
- be called from a tcp-check expect rule, or eventually from a set-var rule
- after an expect rule and before a send rule (check input buffer is filled on
+check.len : integer
+ Returns an integer value corresponding to the number of bytes present in the
+ check input buffer, containing the data received from the server. This can be
+ called from a tcp-check expect rule, or eventually from a set-var rule after
+ an expect rule and before a send rule (check input buffer is filled on
tcp-check expect rules and reset on tcp-check send rules).
+check.payload(<offset>,<length>) : binary
+ This extracts a binary block of <length> bytes and starting at byte <offset>
+ in the check input buffer, containing data received from the server. As a
+ special case, if the <length> argument is zero, then the whole buffer from
+ <offset> to the end is extracted. This can be called from a tcp-check expect
+ rule, or eventually from a set-var rule after an expect rule and before a
+ send rule (check input buffer is filled on tcp-check expect rules and reset
+ on tcp-check send rules).
+
+check.payload_lv(<offset1>,<length>[,<offset2>]) : binary
+ This extracts a binary block whose size is specified at <offset1> for
+ <length> bytes, and which starts at <offset2> if specified or just after the
+ length in the check input buffer, containing data received from the
+ server. The <offset2> parameter also supports relative offsets if prepended
+ with a '+' or '-' sign. This can be called from a tcp-check expect rule, or
+ eventually from a set-var rule after an expect rule and before a send rule
+ (check input buffer is filled on tcp-check expect rules and reset on
+ tcp-check send rules).
7.3.8. Fetching samples for developers
---------------------------------------
*/
if (rule->expect.status_expr) {
smp = sample_fetch_as_type(check->proxy, check->sess, NULL, SMP_OPT_DIR_RES | SMP_OPT_FINAL,
- rule->expect.status_expr, SMP_T_SINT);
- if (smp)
+ rule->expect.status_expr, SMP_T_STR);
+
+ if (smp && sample_casts[smp->data.type][SMP_T_SINT] &&
+ sample_casts[smp->data.type][SMP_T_SINT](smp))
check->code = smp->data.u.sint;
}
*/
if (rule->expect.status_expr) {
smp = sample_fetch_as_type(check->proxy, check->sess, NULL, SMP_OPT_DIR_RES | SMP_OPT_FINAL,
- rule->expect.status_expr, SMP_T_SINT);
- if (smp)
+ rule->expect.status_expr, SMP_T_STR);
+
+ if (smp && sample_casts[smp->data.type][SMP_T_SINT] &&
+ sample_casts[smp->data.type][SMP_T_SINT](smp))
check->code = smp->data.u.sint;
}
/**************************************************************************/
/************************** Check sample fetches **************************/
/**************************************************************************/
-/* extracts check payload at a fixed position and length */
-static int
-smp_fetch_chk_payload(const struct arg *arg_p, struct sample *smp, const char *kw, void *private)
-{
- unsigned int buf_offset = ((arg_p[0].type == ARGT_SINT) ? arg_p[0].data.sint : 0);
- unsigned int buf_size = ((arg_p[1].type == ARGT_SINT) ? arg_p[1].data.sint : 0);
- struct check *check = (smp->sess ? objt_check(smp->sess->origin) : NULL);
- struct buffer *buf;
-
- if (!check)
- return 0;
-
- buf = &check->bi;
- if (buf_offset > b_data(buf))
- goto no_match;
- if (buf_offset + buf_size > b_data(buf))
- buf_size = 0;
-
- /* init chunk as read only */
- smp->data.type = SMP_T_STR;
- smp->flags = SMP_F_VOLATILE | SMP_F_CONST;
- chunk_initlen(&smp->data.u.str, b_head(buf) + buf_offset, 0, (buf_size ? buf_size : (b_data(buf) - buf_offset)));
-
- return 1;
-
- no_match:
- smp->flags = 0;
- return 0;
-}
static struct sample_fetch_kw_list smp_kws = {ILH, {
- { "check.payload", smp_fetch_chk_payload, ARG2(0,SINT,SINT), NULL, SMP_T_STR, SMP_USE_INTRN },
{ /* END */ },
}};
chk = parse_tcpcheck_expect((char *[]){"tcp-check", "expect", "string", redis_res,
"error-status", "L7STS",
- "on-error", "%[check.payload(),cut_crlf]",
+ "on-error", "%[check.payload(0,0),cut_crlf]",
"on-success", "Redis server is ok",
""},
1, curpx, &rs->rules, TCPCHK_RULES_REDIS_CHK, file, line, &errmsg);
chk = parse_tcpcheck_expect((char *[]){"tcp-check", "expect", "rstring", "^[0-9]{3}[ \r]",
"min-recv", "4",
"error-status", "L7RSP",
- "on-error", "%[check.payload(),cut_crlf]",
+ "on-error", "%[check.payload(0,0),cut_crlf]",
""},
1, curpx, &rs->rules, TCPCHK_RULES_SMTP_CHK, file, line, &errmsg);
if (!chk) {
#include <proto/acl.h>
#include <proto/arg.h>
#include <proto/channel.h>
+#include <proto/connection.h>
#include <proto/pattern.h>
#include <proto/payload.h>
#include <proto/sample.h>
static int
smp_fetch_len(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct channel *chn;
-
- if (!smp->strm)
+ if (smp->strm) {
+ struct channel *chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+ if (IS_HTX_STRM(smp->strm)) {
+ struct htx *htx = htxbuf(&chn->buf);
+ smp->data.u.sint = htx->data - co_data(chn);
+ }
+ else
+ smp->data.u.sint = ci_data(chn);
+ }
+ else if (smp->sess && obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
+ struct check *check = __objt_check(smp->sess->origin);
+ smp->data.u.sint = ((check->cs && IS_HTX_CS(check->cs)) ? (htxbuf(&check->bi))->data: b_data(&check->bi));
+ }
+ else
return 0;
- chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
smp->data.type = SMP_T_SINT;
- if (IS_HTX_STRM(smp->strm)) {
- struct htx *htx = htxbuf(&chn->buf);
- smp->data.u.sint = htx->data - co_data(chn);
- }
- else
- smp->data.u.sint = ci_data(chn);
smp->flags = SMP_F_VOLATILE | SMP_F_MAY_CHANGE;
return 1;
}
unsigned int len_size = arg_p[1].data.sint;
unsigned int buf_offset;
unsigned int buf_size = 0;
- struct channel *chn;
+ struct channel *chn = NULL;
+ char *head = NULL;
+ size_t max, data;
int i;
/* Format is (len offset, len size, buf offset) or (len offset, len size) */
/* by default buf offset == len offset + len size */
/* buf offset could be absolute or relative to len offset + len size if prefixed by + or - */
- if (!smp->strm)
+ if (smp->strm) {
+ chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+ head = ci_head(chn);
+ data = ci_data(chn);
+ max = global.tune.bufsize;
+ }
+ else if (smp->sess && obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
+ struct buffer *buf = &(__objt_check(smp->sess->origin)->bi);
+ head = b_head(buf);
+ data = b_data(buf);
+ max = global.tune.chksize;
+ }
+ if (!head)
return 0;
- chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
- if (len_offset + len_size > ci_data(chn))
+ if (len_offset + len_size > data)
goto too_short;
for (i = 0; i < len_size; i++) {
- buf_size = (buf_size << 8) + ((unsigned char *)ci_head(chn))[i + len_offset];
+ buf_size = (buf_size << 8) + ((unsigned char *)head)[i + len_offset];
}
/* buf offset may be implicit, absolute or relative. If the LSB
buf_offset = arg_p[2].data.sint >> 1;
}
- if (!buf_size || buf_size > global.tune.bufsize || buf_offset + buf_size > global.tune.bufsize) {
+ if (!buf_size || buf_size > max || buf_offset + buf_size > max) {
/* will never match */
smp->flags = 0;
return 0;
}
- if (buf_offset + buf_size > ci_data(chn))
+ if (buf_offset + buf_size > data)
goto too_short;
/* init chunk as read only */
smp->data.type = SMP_T_BIN;
smp->flags = SMP_F_VOLATILE | SMP_F_CONST;
- chunk_initlen(&smp->data.u.str, ci_head(chn) + buf_offset, 0, buf_size);
+ chunk_initlen(&smp->data.u.str, head + buf_offset, 0, buf_size);
return 1;
too_short:
{
unsigned int buf_offset = arg_p[0].data.sint;
unsigned int buf_size = arg_p[1].data.sint;
- struct channel *chn;
-
- if (!smp->strm)
+ struct channel *chn = NULL;
+ char *head = NULL;
+ size_t max, data;
+
+ if (smp->strm) {
+ chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+ head = ci_head(chn);
+ data = ci_data(chn);
+ max = global.tune.bufsize;
+ }
+ else if (smp->sess && obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
+ struct buffer *buf = &(__objt_check(smp->sess->origin)->bi);
+ head = b_head(buf);
+ data = b_data(buf);
+ max = global.tune.chksize;
+ }
+ if (!head)
return 0;
- chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
- if (buf_size > global.tune.bufsize || buf_offset + buf_size > global.tune.bufsize) {
+ if (buf_size > max || buf_offset + buf_size > max) {
/* will never match */
smp->flags = 0;
return 0;
}
-
- if (buf_offset + buf_size > ci_data(chn))
+ if (buf_offset + buf_size > data)
goto too_short;
/* init chunk as read only */
smp->data.type = SMP_T_BIN;
smp->flags = SMP_F_VOLATILE | SMP_F_CONST;
- chunk_initlen(&smp->data.u.str, ci_head(chn) + buf_offset, 0, buf_size ? buf_size : (ci_data(chn) - buf_offset));
- if (!buf_size && channel_may_recv(chn) && !channel_input_closed(chn))
+ chunk_initlen(&smp->data.u.str, head + buf_offset, 0, buf_size ? buf_size : (data - buf_offset));
+
+ if (!buf_size && chn && channel_may_recv(chn) && !channel_input_closed(chn))
smp->flags |= SMP_F_MAY_CHANGE;
return 1;
- too_short:
+ too_short:
smp->flags = SMP_F_MAY_CHANGE | SMP_F_CONST;
return 0;
}
{ "res.payload_lv", smp_fetch_payload_lv, ARG3(2,SINT,SINT,STR), val_payload_lv, SMP_T_BIN, SMP_USE_L6RES },
{ "res.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_SINT, SMP_USE_L6RES },
{ "wait_end", smp_fetch_wait_end, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
+
+ { "check.len", smp_fetch_len, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
+ { "check.payload", smp_fetch_payload, ARG2(2,SINT,SINT), NULL, SMP_T_BIN, SMP_USE_INTRN },
+ { "check.payload_lv", smp_fetch_payload_lv, ARG3(2,SINT,SINT,STR), val_payload_lv, SMP_T_BIN, SMP_USE_INTRN },
{ /* END */ },
}};