Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Varnisncsa: Change matching rules to reflect reality #4213

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 85 additions & 25 deletions bin/varnishncsa/varnishncsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,48 @@ static struct ctx {
const char *handling;
const char *side;
int64_t vxid;
int recv_compl;
} CTX;

enum format_policy {
FMTPOL_INTERNAL,
FMTPOL_REQ,
FMTPOL_RESP,
};

static void parse_format(const char *format);

static unsigned
frag_needed(const struct fragment *frag, enum format_policy fp)
{
unsigned is_first, want_first, want_frag;

is_first = CTX.gen != frag->gen;

switch (fp) {
case FMTPOL_INTERNAL:
want_first = 1;
want_frag = 1;
break;
case FMTPOL_REQ:
want_first = *CTX.side == 'c';
want_frag = !CTX.recv_compl;
break;
case FMTPOL_RESP:
want_first = *CTX.side == 'b';
want_frag = (*CTX.side == 'c') || !CTX.recv_compl;
break;
default:
WRONG("Invalid format policy");
}

if (!want_frag)
return (0);
if (want_first && !is_first)
return (0);
return (1);
}

static void
openout(int append)
{
Expand Down Expand Up @@ -850,7 +888,7 @@ isprefix(const char *prefix, size_t len, const char *b,
}

static void
frag_fields(int force, const char *b, const char *e, ...)
frag_fields(enum format_policy fp, const char *b, const char *e, ...)
{
va_list ap;
const char *p, *q;
Expand Down Expand Up @@ -882,7 +920,7 @@ frag_fields(int force, const char *b, const char *e, ...)
assert(p != NULL && q != NULL);
if (p >= e || q <= p)
continue;
if (frag->gen != CTX.gen || force) {
if (frag_needed(frag, fp)) {
/* We only grab the same matching field once */
frag->gen = CTX.gen;
frag->b = p;
Expand All @@ -893,13 +931,17 @@ frag_fields(int force, const char *b, const char *e, ...)
}

static void
frag_line(int force, const char *b, const char *e, struct fragment *f)
frag_line(enum format_policy fp, const char *b, const char *e,
struct fragment *f)
{

if (f->gen == CTX.gen && !force)
if (!frag_needed(f, fp))
/* We only grab the same matching record once */
return;

if (e == NULL)
e = b + strlen(b);

/* Skip leading space */
while (b < e && isspace(*b))
++b;
Expand All @@ -914,7 +956,8 @@ frag_line(int force, const char *b, const char *e, struct fragment *f)
}

static void
process_hdr(const struct watch_head *head, const char *b, const char *e)
process_hdr(enum format_policy fp, const struct watch_head *head, const char *b,
const char *e, int unset)
{
struct watch *w;
const char *p;
Expand All @@ -923,7 +966,12 @@ process_hdr(const struct watch_head *head, const char *b, const char *e)
CHECK_OBJ_NOTNULL(w, WATCH_MAGIC);
if (!isprefix(w->key, w->keylen, b, e, &p))
continue;
frag_line(1, p, e, &w->frag);
if (unset) {
frag_line(fp, CTX.missing_string,
NULL,
&w->frag);
} else
frag_line(fp, p, e, &w->frag);
}
}

Expand All @@ -942,9 +990,9 @@ process_vsl(const struct vsl_watch_head *head, enum VSL_tag_e tag,
!isprefix(w->prefix, w->prefixlen, b, e, &p))
continue;
if (w->idx == 0)
frag_line(0, p, e, &w->frag);
frag_line(FMTPOL_INTERNAL, p, e, &w->frag);
else
frag_fields(0, p, e, w->idx, &w->frag, 0, NULL);
frag_fields(FMTPOL_INTERNAL, p, e, w->idx, &w->frag, 0, NULL);
}
}

Expand All @@ -971,6 +1019,7 @@ dispatch_f(struct VSL_data *vsl, struct VSL_transaction * const pt[],
} else
continue;

CTX.recv_compl = 0;
CTX.hitmiss = "-";
CTX.handling = "-";
CTX.vxid = t->vxid;
Expand All @@ -993,44 +1042,44 @@ dispatch_f(struct VSL_data *vsl, struct VSL_transaction * const pt[],
skip = 1;
break;
case SLT_PipeAcct:
frag_fields(0, b, e,
frag_fields(FMTPOL_INTERNAL, b, e,
3, &CTX.frag[F_I],
4, &CTX.frag[F_O],
0, NULL);
break;
case SLT_BackendOpen:
frag_fields(1, b, e,
frag_fields(FMTPOL_INTERNAL, b, e,
3, &CTX.frag[F_h],
0, NULL);
break;
case SLT_ReqStart:
frag_fields(0, b, e,
frag_fields(FMTPOL_INTERNAL, b, e,
1, &CTX.frag[F_h],
0, NULL);
break;
case SLT_BereqMethod:
case SLT_ReqMethod:
frag_line(0, b, e, &CTX.frag[F_m]);
frag_line(FMTPOL_REQ, b, e, &CTX.frag[F_m]);
break;
case SLT_BereqURL:
case SLT_ReqURL:
p = memchr(b, '?', e - b);
if (p == NULL)
p = e;
frag_line(0, b, p, &CTX.frag[F_U]);
frag_line(0, p, e, &CTX.frag[F_q]);
frag_line(FMTPOL_REQ, b, p, &CTX.frag[F_U]);
frag_line(FMTPOL_REQ, p, e, &CTX.frag[F_q]);
break;
case SLT_BereqProtocol:
case SLT_ReqProtocol:
frag_line(0, b, e, &CTX.frag[F_H]);
frag_line(FMTPOL_REQ, b, e, &CTX.frag[F_H]);
break;
case SLT_BerespStatus:
case SLT_RespStatus:
frag_line(1, b, e, &CTX.frag[F_s]);
frag_line(FMTPOL_RESP, b, e, &CTX.frag[F_s]);
break;
case SLT_BereqAcct:
case SLT_ReqAcct:
frag_fields(0, b, e,
frag_fields(FMTPOL_INTERNAL, b, e,
3, &CTX.frag[F_I],
5, &CTX.frag[F_b],
6, &CTX.frag[F_O],
Expand All @@ -1039,40 +1088,49 @@ dispatch_f(struct VSL_data *vsl, struct VSL_transaction * const pt[],
case SLT_Timestamp:
#define ISPREFIX(a, b, c, d) isprefix(a, strlen(a), b, c, d)
if (ISPREFIX("Start:", b, e, &p)) {
frag_fields(0, p, e, 1,
frag_fields(FMTPOL_INTERNAL, p, e, 1,
&CTX.frag[F_tstart], 0, NULL);

} else if (ISPREFIX("Resp:", b, e, &p) ||
ISPREFIX("PipeSess:", b, e, &p) ||
ISPREFIX("BerespBody:", b, e, &p)) {
frag_fields(0, p, e, 1,
frag_fields(FMTPOL_INTERNAL, p, e, 1,
&CTX.frag[F_tend], 0, NULL);

} else if (ISPREFIX("Process:", b, e, &p) ||
ISPREFIX("Pipe:", b, e, &p) ||
ISPREFIX("Beresp:", b, e, &p)) {
frag_fields(0, p, e, 2,
frag_fields(FMTPOL_INTERNAL, p, e, 2,
&CTX.frag[F_ttfb], 0, NULL);
}
break;
case SLT_BereqHeader:
case SLT_ReqHeader:
process_hdr(&CTX.watch_reqhdr, b, e);
process_hdr(FMTPOL_REQ, &CTX.watch_reqhdr, b, e, 0);
if (ISPREFIX("Authorization:", b, e, &p) &&
ISPREFIX("basic ", p, e, &p))
frag_line(0, p, e,
frag_line(FMTPOL_REQ, p, e,
&CTX.frag[F_auth]);
else if (ISPREFIX("Host:", b, e, &p))
frag_line(0, p, e,
frag_line(FMTPOL_REQ, p, e,
&CTX.frag[F_host]);
#undef ISPREFIX
break;
case SLT_BerespHeader:
case SLT_RespHeader:
process_hdr(&CTX.watch_resphdr, b, e);
process_hdr(FMTPOL_RESP, &CTX.watch_resphdr, b, e, 0);
break;
case SLT_BereqUnset:
case SLT_ReqUnset:
process_hdr(FMTPOL_REQ, &CTX.watch_reqhdr, b, e, 1);
break;
case SLT_BerespUnset:
case SLT_RespUnset:
process_hdr(FMTPOL_RESP, &CTX.watch_resphdr, b, e, 1);
break;
case SLT_VCL_call:
if (!strcasecmp(b, "recv")) {
CTX.recv_compl = 1;
CTX.hitmiss = "-";
CTX.handling = "-";
} else if (!strcasecmp(b, "hit")) {
Expand All @@ -1090,6 +1148,8 @@ dispatch_f(struct VSL_data *vsl, struct VSL_transaction * const pt[],
wrong */
CTX.hitmiss = "miss";
CTX.handling = "synth";
} else if (!strcasecmp(b, "backend_response")) {
CTX.recv_compl = 1;
}
break;
case SLT_VCL_return:
Expand All @@ -1106,7 +1166,7 @@ dispatch_f(struct VSL_data *vsl, struct VSL_transaction * const pt[],
strncmp(b, w->key, w->keylen))
continue;
p = b + w->keylen;
frag_line(0, p, e, &w->frag);
frag_line(FMTPOL_INTERNAL, p, e, &w->frag);
}
break;
default:
Expand Down
Loading